diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8cc26d2995e73..a0d9eb8c45292 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: - name: mingw-check-tidy os: ubuntu-20.04-4core-16gb env: {} - - name: x86_64-gnu-llvm-15 + - name: x86_64-gnu-llvm-16 env: ENABLE_GCC_CODEGEN: "1" os: ubuntu-20.04-16core-64gb @@ -106,6 +106,9 @@ jobs: - name: install clang run: src/ci/scripts/install-clang.sh if: success() && !env.SKIP_JOB + - name: install tidy + run: src/ci/scripts/install-tidy.sh + if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB @@ -299,10 +302,6 @@ jobs: env: RUST_BACKTRACE: 1 os: ubuntu-20.04-8core-32gb - - name: x86_64-gnu-llvm-15 - env: - RUST_BACKTRACE: 1 - os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-nopt os: ubuntu-20.04-4core-16gb env: {} @@ -370,6 +369,19 @@ jobs: NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 os: macos-13-xlarge + - name: aarch64-apple + env: + SCRIPT: "./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin" + RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_13.4.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + os: macos-13-xlarge - name: x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" @@ -483,6 +495,9 @@ jobs: - name: install clang run: src/ci/scripts/install-clang.sh if: success() && !env.SKIP_JOB + - name: install tidy + run: src/ci/scripts/install-tidy.sh + if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB @@ -607,6 +622,9 @@ jobs: - name: install clang run: src/ci/scripts/install-clang.sh if: success() && !env.SKIP_JOB + - name: install tidy + run: src/ci/scripts/install-tidy.sh + if: success() && !env.SKIP_JOB - name: install WIX run: src/ci/scripts/install-wix.sh if: success() && !env.SKIP_JOB diff --git a/.mailmap b/.mailmap index b6f4112392db7..d70a9f2aed684 100644 --- a/.mailmap +++ b/.mailmap @@ -575,7 +575,8 @@ Val Markovic Valerii Lashmanov Vitali Haravy Vitali Haravy Vitaly Shukela -Waffle Maybe +Waffle Lapkin +Waffle Lapkin Wesley Wiser whitequark William Ting diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dfaa70bb9db00..eeff563d8ecdf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,7 +15,7 @@ standard library in the [Standard library developers Guide][std-dev-guide], comm ## About the [rustc-dev-guide] The [rustc-dev-guide] is meant to help document how rustc –the Rust compiler– works, -as well as to help new contributors get involved in rustc development. It is recommend +as well as to help new contributors get involved in rustc development. It is recommended to read and understand the [rustc-dev-guide] before making a contribution. This guide talks about the different bots in the Rust ecosystem, the Rust development tools, bootstrapping, the compiler architecture, source code representation, and more. diff --git a/Cargo.lock b/Cargo.lock index d56d7e3f2b03c..1d7f93c789afe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,13 +37,14 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -193,12 +194,6 @@ dependencies = [ "object", ] -[[package]] -name = "array_tool" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" - [[package]] name = "arrayvec" version = "0.7.4" @@ -228,7 +223,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -237,17 +232,6 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -356,7 +340,7 @@ version = "0.1.0" dependencies = [ "anyhow", "curl", - "indexmap 2.0.0", + "indexmap", "serde", "serde_json", "toml 0.5.11", @@ -526,9 +510,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.3.1" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6b5c519bab3ea61843a7923d074b04245624bb84a64a8c150f5deb014e388b" +checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" dependencies = [ "clap", ] @@ -542,7 +526,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -553,7 +537,7 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "clippy" -version = "0.1.75" +version = "0.1.76" dependencies = [ "anstream", "clippy_config", @@ -569,7 +553,7 @@ dependencies = [ "regex", "rustc_tools_util", "serde", - "syn 2.0.29", + "syn 2.0.32", "tempfile", "termize", "tester", @@ -581,7 +565,7 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.75" +version = "0.1.76" dependencies = [ "rustc-semver", "serde", @@ -597,21 +581,20 @@ dependencies = [ "clap", "indoc", "itertools", - "opener", + "opener 0.5.2", "shell-escape", "walkdir", ] [[package]] name = "clippy_lints" -version = "0.1.75" +version = "0.1.76" dependencies = [ "arrayvec", "cargo_metadata 0.15.4", "clippy_config", "clippy_utils", "declare_clippy_lint", - "if_chain", "itertools", "quine-mc_cluskey", "regex", @@ -630,11 +613,10 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.75" +version = "0.1.76" dependencies = [ "arrayvec", "clippy_config", - "if_chain", "itertools", "rustc-semver", ] @@ -722,9 +704,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "compiler_builtins" -version = "0.1.101" +version = "0.1.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a6d58e9c3408138099a396a98fd0d0e6cfb25d723594d2ae48b5004513fd5b" +checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242" dependencies = [ "cc", "rustc-std-workspace-core", @@ -741,7 +723,7 @@ dependencies = [ "getopts", "glob", "home", - "indexmap 2.0.0", + "indexmap", "lazycell", "libc", "miow", @@ -813,10 +795,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "coverage_test_macros" -version = "0.0.0" - [[package]] name = "cpufeatures" version = "0.2.8" @@ -983,7 +961,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -1005,7 +983,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -1016,11 +994,11 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.75" +version = "0.1.76" dependencies = [ "itertools", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -1087,7 +1065,7 @@ dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -1176,7 +1154,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -1247,26 +1225,13 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime 1.3.0", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ - "humantime 2.1.0", + "humantime", "is-terminal", "log", "regex", @@ -1281,25 +1246,14 @@ checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "error_index_generator" version = "0.0.0" @@ -1391,7 +1345,7 @@ dependencies = [ "intl-memoizer", "intl_pluralrules", "rustc-hash", - "self_cell", + "self_cell 0.10.3", "smallvec", "unic-langid", ] @@ -1532,7 +1486,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -1621,7 +1575,7 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" dependencies = [ "compiler_builtins", "fallible-iterator", - "indexmap 2.0.0", + "indexmap", "rustc-std-workspace-alloc", "rustc-std-workspace-core", "stable_deref_trait", @@ -1657,9 +1611,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1667,7 +1621,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap", "slab", "tokio", "tokio-util", @@ -1690,15 +1644,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", @@ -1713,15 +1661,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.2" @@ -1813,15 +1752,6 @@ dependencies = [ "libm", ] -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] - [[package]] name = "humantime" version = "2.1.0" @@ -1890,21 +1820,29 @@ dependencies = [ [[package]] name = "icu_list" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7ba7442d9235b689d4fdce17c452ea229934980fd81ba50cc28275752c9f90" +checksum = "dc1a44bbed77a7e7b555f9d7dd4b43f75ec1402b438a901d20451943d50cbd90" dependencies = [ "displaydoc", + "icu_list_data", + "icu_locid_transform", "icu_provider", "regex-automata 0.2.0", "writeable", ] +[[package]] +name = "icu_list_data" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3237583f0cb7feafabb567c4492fe9ef1d2d4113f6a8798a923273ea5de996d" + [[package]] name = "icu_locid" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3003f85dccfc0e238ff567693248c59153a46f4e6125ba4020b973cef4d1d335" +checksum = "f284eb342dc49d3e9d9f3b188489d76b5d22dfb1d1a5e0d1941811253bac625c" dependencies = [ "displaydoc", "litemap", @@ -1913,16 +1851,37 @@ dependencies = [ "zerovec", ] +[[package]] +name = "icu_locid_transform" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6551daf80882d8e68eee186cc19e132d8bde1b1f059a79b93384a5ca0e8fc5e7" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a741eba5431f75eb2f1f9022d3cffabcadda6771e54fb4e77c8ba8653e4da44" + [[package]] name = "icu_provider" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc312a7b6148f7dfe098047ae2494d12d4034f48ade58d4f353000db376e305" +checksum = "68acdef80034b5e35d8524e9817479d389a4f9774f3f0cbe1bf3884d80fd5934" dependencies = [ "displaydoc", "icu_locid", "icu_provider_macros", "stable_deref_trait", + "tinystr", "writeable", "yoke", "zerofrom", @@ -1931,26 +1890,26 @@ dependencies = [ [[package]] name = "icu_provider_adapters" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ae1e2bd0c41728b77e7c46e9afdec5e2127d1eedacc684724667d50c126bd3" +checksum = "36b380ef2d3d93b015cd0563d7e0d005cc07f82a5503716dbc191798d0079e1d" dependencies = [ "icu_locid", + "icu_locid_transform", "icu_provider", "tinystr", - "yoke", "zerovec", ] [[package]] name = "icu_provider_macros" -version = "1.2.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10" +checksum = "2060258edfcfe32ca7058849bf0f146cb5c59aadbedf480333c0d0002f97bc99" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.32", ] [[package]] @@ -1998,16 +1957,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.0.0" @@ -2015,7 +1964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown", "rustc-rayon", "serde", ] @@ -2055,7 +2004,6 @@ dependencies = [ "anyhow", "clap", "flate2", - "num_cpus", "rayon", "tar", "walkdir", @@ -2102,16 +2050,16 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "rustix", "windows-sys 0.48.0", ] [[package]] name = "itertools" -version = "0.10.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] @@ -2134,9 +2082,9 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] @@ -2178,12 +2126,10 @@ dependencies = [ [[package]] name = "jsonpath_lib" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61352ec23883402b7d30b3313c16cbabefb8907361c4eb669d990cbb87ceee5a" +checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" dependencies = [ - "array_tool", - "env_logger 0.7.1", "log", "serde", "serde_json", @@ -2215,9 +2161,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" dependencies = [ "rustc-std-workspace-core", ] @@ -2310,9 +2256,9 @@ checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "litemap" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a04a5b2b6f54acba899926491d0a6c59d98012938ca2ab5befb281c034e8f94" +checksum = "77a1a2647d5b7134127971a6de0d533c49de2159167e7f259c427195f87168a1" [[package]] name = "lld-wrapper" @@ -2391,9 +2337,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.31" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b67ee4a744f36e6280792016c17e69921b51df357181d1eb17d620fcc3609f3" +checksum = "80992cb0e05f22cc052c99f8e883f1593b891014b96a8b4637fd274d7030c85e" dependencies = [ "ammonia", "anyhow", @@ -2401,12 +2347,13 @@ dependencies = [ "clap", "clap_complete", "elasticlunr-rs", - "env_logger 0.10.0", + "env_logger", "handlebars", "log", "memchr", "once_cell", - "opener", + "opener 0.6.1", + "pathdiff", "pulldown-cmark", "regex", "serde", @@ -2526,7 +2473,7 @@ dependencies = [ "aes", "colored", "ctrlc", - "env_logger 0.10.0", + "env_logger", "getrandom", "lazy_static", "libc", @@ -2595,6 +2542,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "normpath" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "ntapi" version = "0.4.1" @@ -2630,7 +2586,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "libc", ] @@ -2642,15 +2598,15 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "compiler_builtins", "crc32fast", "flate2", - "hashbrown 0.14.2", - "indexmap 2.0.0", + "hashbrown", + "indexmap", "memchr", "rustc-std-workspace-alloc", "rustc-std-workspace-core", @@ -2682,6 +2638,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "opener" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788" +dependencies = [ + "bstr", + "normpath", + "winapi", +] + [[package]] name = "openssl" version = "0.10.55" @@ -2705,7 +2672,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -2735,11 +2702,11 @@ dependencies = [ "camino", "clap", "derive_builder", - "env_logger 0.10.0", + "env_logger", "fs_extra", "glob", "humansize", - "humantime 2.1.0", + "humantime", "log", "reqwest", "serde", @@ -2922,7 +2889,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -3005,9 +2972,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.4.2" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" +checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" [[package]] name = "ppv-lite86" @@ -3089,12 +3056,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe" -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quine-mc_cluskey" version = "0.2.4" @@ -3181,9 +3142,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -3191,14 +3152,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -3344,7 +3303,7 @@ name = "rustbook" version = "0.1.0" dependencies = [ "clap", - "env_logger 0.10.0", + "env_logger", "mdbook", ] @@ -3530,6 +3489,7 @@ dependencies = [ name = "rustc_ast_pretty" version = "0.0.0" dependencies = [ + "itertools", "rustc_ast", "rustc_span", "thin-vec", @@ -3558,6 +3518,7 @@ version = "0.0.0" dependencies = [ "icu_list", "icu_locid", + "icu_locid_transform", "icu_provider", "icu_provider_adapters", "zerovec", @@ -3581,7 +3542,6 @@ dependencies = [ "rustc_macros", "rustc_middle", "rustc_mir_dataflow", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", @@ -3727,13 +3687,14 @@ dependencies = [ "bitflags 1.3.2", "elsa", "ena", - "indexmap 2.0.0", + "indexmap", "itertools", "jobserver", "libc", "measureme", "memmap2", "parking_lot 0.12.1", + "portable-atomic", "rustc-hash", "rustc-rayon", "rustc-rayon-core", @@ -3773,7 +3734,6 @@ dependencies = [ "rustc_const_eval", "rustc_data_structures", "rustc_error_codes", - "rustc_error_messages", "rustc_errors", "rustc_expand", "rustc_feature", @@ -3800,6 +3760,7 @@ dependencies = [ "rustc_query_system", "rustc_resolve", "rustc_session", + "rustc_smir", "rustc_span", "rustc_symbol_mangling", "rustc_target", @@ -3827,7 +3788,6 @@ dependencies = [ "intl-memoizer", "rustc_baked_icu_data", "rustc_data_structures", - "rustc_fluent_macro", "rustc_macros", "rustc_serialize", "rustc_span", @@ -3905,7 +3865,7 @@ dependencies = [ "fluent-syntax", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", "unic-langid", ] @@ -3925,7 +3885,6 @@ dependencies = [ "rustc_arena", "rustc_ast", "rustc_data_structures", - "rustc_error_messages", "rustc_index", "rustc_macros", "rustc_serialize", @@ -3990,7 +3949,6 @@ dependencies = [ "rustc_lint", "rustc_macros", "rustc_middle", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", @@ -4026,11 +3984,22 @@ name = "rustc_index" version = "0.0.0" dependencies = [ "arrayvec", + "rustc_index_macros", "rustc_macros", "rustc_serialize", "smallvec", ] +[[package]] +name = "rustc_index_macros" +version = "0.0.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", + "synstructure", +] + [[package]] name = "rustc_infer" version = "0.0.0" @@ -4042,7 +4011,6 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_middle", - "rustc_serialize", "rustc_span", "rustc_target", "smallvec", @@ -4088,6 +4056,7 @@ dependencies = [ "rustc_query_impl", "rustc_query_system", "rustc_resolve", + "rustc_serialize", "rustc_session", "rustc_span", "rustc_symbol_mangling", @@ -4173,8 +4142,8 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", - "synstructure 0.13.0", + "syn 2.0.32", + "synstructure", ] [[package]] @@ -4260,7 +4229,6 @@ dependencies = [ "rustc_infer", "rustc_macros", "rustc_middle", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", @@ -4284,7 +4252,6 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_middle", - "rustc_serialize", "rustc_span", "rustc_target", "smallvec", @@ -4295,7 +4262,6 @@ dependencies = [ name = "rustc_mir_transform" version = "0.0.0" dependencies = [ - "coverage_test_macros", "either", "itertools", "rustc_arena", @@ -4311,7 +4277,6 @@ dependencies = [ "rustc_middle", "rustc_mir_build", "rustc_mir_dataflow", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", @@ -4385,7 +4350,6 @@ dependencies = [ "rustc_lexer", "rustc_macros", "rustc_middle", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", @@ -4487,7 +4451,7 @@ dependencies = [ name = "rustc_serialize" version = "0.0.0" dependencies = [ - "indexmap 2.0.0", + "indexmap", "rustc_macros", "smallvec", "tempfile", @@ -4537,7 +4501,7 @@ dependencies = [ name = "rustc_span" version = "0.0.0" dependencies = [ - "indexmap 2.0.0", + "indexmap", "md-5", "rustc_arena", "rustc_data_structures", @@ -4609,7 +4573,6 @@ dependencies = [ "rustc_middle", "rustc_parse_format", "rustc_query_system", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_target", @@ -4696,7 +4659,7 @@ dependencies = [ "arrayvec", "askama", "expect-test", - "indexmap 2.0.0", + "indexmap", "itertools", "minifier", "once_cell", @@ -4762,7 +4725,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -4886,9 +4849,18 @@ dependencies = [ [[package]] name = "self_cell" -version = "0.10.2" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.0.2", +] + +[[package]] +name = "self_cell" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" +checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" [[package]] name = "semver" @@ -4916,7 +4888,7 @@ checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -4925,7 +4897,7 @@ version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ - "indexmap 2.0.0", + "indexmap", "itoa", "ryu", "serde", @@ -5105,8 +5077,8 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.14.2", - "hermit-abi 0.3.2", + "hashbrown", + "hermit-abi", "libc", "miniz_oxide", "object", @@ -5207,27 +5179,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - [[package]] name = "synstructure" version = "0.13.0" @@ -5236,7 +5196,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", "unicode-xid", ] @@ -5415,7 +5375,7 @@ checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -5425,7 +5385,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b" dependencies = [ "gimli", - "hashbrown 0.14.2", + "hashbrown", "object", "tracing", ] @@ -5497,9 +5457,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef" +checksum = "d5d0e245e80bdc9b4e5356fc45a72184abbc3861992603f515270e9340f5a219" dependencies = [ "displaydoc", "zerovec", @@ -5597,7 +5557,7 @@ version = "0.19.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" dependencies = [ - "indexmap 2.0.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -5636,7 +5596,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", ] [[package]] @@ -5822,9 +5782,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -5923,11 +5883,22 @@ dependencies = [ name = "unwind" version = "0.0.0" dependencies = [ - "cc", "cfg-if", "compiler_builtins", "core", "libc", + "unwinding", +] + +[[package]] +name = "unwinding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b" +dependencies = [ + "compiler_builtins", + "gimli", + "rustc-std-workspace-core", ] [[package]] @@ -6031,7 +6002,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", "wasm-bindgen-shared", ] @@ -6065,7 +6036,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.32", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6128,21 +6099,21 @@ dependencies = [ [[package]] name = "windows-bindgen" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc1f16b778125675feee0d15d6dd9f6af0e3ac52b3233d63a10aa39230c1cd75" +checksum = "970efb0b6849eb8a87a898f586af7cc167567b070014c7434514c0bde0ca341c" dependencies = [ "proc-macro2", "rayon", - "syn 2.0.29", + "syn 2.0.32", "windows-metadata", ] [[package]] name = "windows-metadata" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "753135d996f9da437c0b31dbde3032489a61708361929bcc07d4fba0b161000e" +checksum = "218fd59201e26acdbb894fa2b302d1de84bf3eec7d0eb894ac8e9c5a854ee4ef" [[package]] name = "windows-sys" @@ -6296,9 +6267,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e49e42bdb1d5dc76f4cd78102f8f0714d32edfa3efb82286eb0f0b1fc0da0f" +checksum = "c0af0c3d13faebf8dda0b5256fa7096a2d5ccb662f7b9f54a40fe201077ab1c2" [[package]] name = "xattr" @@ -6358,9 +6329,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1848075a23a28f9773498ee9a0f2cf58fcbad4f8c0ccf84a210ab33c6ae495de" +checksum = "61e38c508604d6bbbd292dadb3c02559aa7fff6b654a078a36217cad871636e4" dependencies = [ "serde", "stable_deref_trait", @@ -6370,42 +6341,62 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af46c169923ed7516eef0aa32b56d2651b229f57458ebe46b49ddd6efef5b7a2" +checksum = "d5e19fb6ed40002bab5403ffa37e53e0e56f914a4450c8765f533018db1db35f" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "synstructure 0.12.6", + "syn 2.0.32", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", ] [[package]] name = "zerofrom" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d76c3251de27615dfcce21e636c172dafb2549cd7fd93e21c66f6ca6bea2" +checksum = "655b0814c5c0b19ade497851070c640773304939a6c0fd5f5fb43da0696d05b7" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eae7c1f7d4b8eafce526bc0771449ddc2f250881ae31c50d22c032b5a1c499" +checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "synstructure 0.12.6", + "syn 2.0.32", + "synstructure", ] [[package]] name = "zerovec" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198f54134cd865f437820aa3b43d0ad518af4e68ee161b444cdd15d8e567c8ea" +checksum = "1194130c5b155bf8ae50ab16c86ab758cd695cf9ad176d2f870b744cbdbb572e" dependencies = [ "yoke", "zerofrom", @@ -6414,14 +6405,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486558732d5dde10d0f8cb2936507c1bb21bc539d924c949baf5f36a58e51bac" +checksum = "acabf549809064225ff8878baedc4ce3732ac3b07e7c7ce6e5c2ccdbc485c324" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "synstructure 0.12.6", + "syn 2.0.32", ] [[package]] diff --git a/README.md b/README.md index a88ee4b8bf061..5d5beaf1b7a20 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ If you wish to _contribute_ to the compiler, you should read [CONTRIBUTING.md](CONTRIBUTING.md) instead.
-Table of content +Table of Contents - [Quick Start](#quick-start) - [Installing from Source](#installing-from-source) diff --git a/RELEASES.md b/RELEASES.md index 1cc110e6607f9..9eb8755dad99a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,119 @@ +Version 1.74.0 (2023-11-16) +========================== + + + +Language +-------- + +- [Codify that `std::mem::Discriminant` does not depend on any lifetimes in T](https://github.com/rust-lang/rust/pull/104299/) +- [Replace `private_in_public` lint with `private_interfaces` and `private_bounds` per RFC 2145.](https://github.com/rust-lang/rust/pull/113126/) + Read more in [RFC 2145](https://rust-lang.github.io/rfcs/2145-type-privacy.html). +- [Allow explicit `#[repr(Rust)]`](https://github.com/rust-lang/rust/pull/114201/) +- [closure field capturing: don't depend on alignment of packed fields](https://github.com/rust-lang/rust/pull/115315/) +- [Enable MIR-based drop-tracking for `async` blocks](https://github.com/rust-lang/rust/pull/107421/) +- [Stabilize `impl_trait_projections`](https://github.com/rust-lang/rust/pull/115659) + + + +Compiler +-------- + +- [stabilize combining +bundle and +whole-archive link modifiers](https://github.com/rust-lang/rust/pull/113301/) +- [Stabilize `PATH` option for `--print KIND=PATH`](https://github.com/rust-lang/rust/pull/114183/) +- [Enable ASAN/LSAN/TSAN for `*-apple-ios-macabi`](https://github.com/rust-lang/rust/pull/115644/) +- [Promote loongarch64-unknown-none* to Tier 2](https://github.com/rust-lang/rust/pull/115368/) +- [Add `i686-pc-windows-gnullvm` as a tier 3 target](https://github.com/rust-lang/rust/pull/115687/) + + + +Libraries +--------- + +- [Implement `From` for ChildStdin/out/err](https://github.com/rust-lang/rust/pull/98704/) +- [Implement `From<{&,&mut} [T; N]>` for `Vec` where `T: Clone`](https://github.com/rust-lang/rust/pull/111278/) +- [impl Step for IP addresses](https://github.com/rust-lang/rust/pull/113748/) +- [Implement `From<[T; N]>` for `Rc<[T]>` and `Arc<[T]>`](https://github.com/rust-lang/rust/pull/114041/) +- [`impl TryFrom for u16`](https://github.com/rust-lang/rust/pull/114065/) +- [Stabilize `io_error_other` feature](https://github.com/rust-lang/rust/pull/115453/) +- [Stabilize the `Saturating` type](https://github.com/rust-lang/rust/pull/115477/) +- [Stabilize const_transmute_copy](https://github.com/rust-lang/rust/pull/115520/) + + + +Stabilized APIs +--------------- + +- [`core::num::Saturating`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html) +- [`impl From for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStdout%3E-for-Stdio) +- [`impl From for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.ChildStderr.html#impl-From%3COwnedHandle%3E-for-ChildStderr) +- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.ChildStderr.html#impl-From%3COwnedFd%3E-for-ChildStderr) +- [`std::ffi::OsString::from_encoded_bytes_unchecked`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.from_encoded_bytes_unchecked) +- [`std::ffi::OsString::into_encoded_bytes`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.into_encoded_bytes) +- [`std::ffi::OsStr::from_encoded_bytes_unchecked`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.from_encoded_bytes_unchecked) +- [`std::ffi::OsStr::as_encoded_bytes`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.as_encoded_bytes) +- [`std::io::Error::other`](https://doc.rust-lang.org/stable/std/io/struct.Error.html#method.other) +- [`impl TryFrom for u16`](https://doc.rust-lang.org/stable/std/primitive.u16.html#impl-TryFrom%3Cchar%3E-for-u16) +- [`impl From<&[T; N]> for Vec`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#impl-From%3C%26%5BT;+N%5D%3E-for-Vec%3CT,+Global%3E) +- [`impl From<&mut [T; N]> for Vec`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#impl-From%3C%26mut+%5BT;+N%5D%3E-for-Vec%3CT,+Global%3E) +- [`impl From<[T; N]> for Arc<[T]>`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#impl-From%3C%5BT;+N%5D%3E-for-Arc%3C%5BT%5D,+Global%3E) +- [`impl From<[T; N]> for Rc<[T]>`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#impl-From%3C%5BT;+N%5D%3E-for-Rc%3C%5BT%5D,+Global%3E) + +These APIs are now stable in const contexts: + +- [`core::mem::transmute_copy`](https://doc.rust-lang.org/beta/std/mem/fn.transmute_copy.html) +- [`str::is_ascii`](https://doc.rust-lang.org/beta/std/primitive.str.html#method.is_ascii) +- [`[u8]::is_ascii`](https://doc.rust-lang.org/beta/std/primitive.slice.html#method.is_ascii) + + + +Cargo +----- + +- [In `Cargo.toml`, stabilize `[lints]`](https://github.com/rust-lang/cargo/pull/12648/) +- [Stabilize credential-process and registry-auth](https://github.com/rust-lang/cargo/pull/12649/) +- [Stabilize `--keep-going` build flag](https://github.com/rust-lang/cargo/pull/12568/) +- [Add styling to `--help` output](https://github.com/rust-lang/cargo/pull/12578/) +- [For `cargo clean`, add `--dry-run` flag and summary line at the end](https://github.com/rust-lang/cargo/pull/12638) +- [For `cargo update`, make `--package` more convenient by being positional](https://github.com/rust-lang/cargo/pull/12545/) +- [For `cargo update`, clarify meaning of --aggressive as --recursive](https://github.com/rust-lang/cargo/pull/12544/) +- [Add '-n' as an alias for `--dry-run`](https://github.com/rust-lang/cargo/pull/12660/) +- [Allow version-prefixes in pkgid's (e.g. `--package` flags) to resolve ambiguities](https://github.com/rust-lang/cargo/pull/12614/) +- [In `.cargo/config.toml`, merge lists in precedence order](https://github.com/rust-lang/cargo/pull/12515/) +- [Add support for `target.'cfg(..)'.linker`](https://github.com/rust-lang/cargo/pull/12535/) + + + +Rustdoc +------- + +- [Add warning block support in rustdoc](https://github.com/rust-lang/rust/pull/106561/) +- [rustdoc-search: add support for type parameters](https://github.com/rust-lang/rust/pull/112725/) +- [rustdoc: show inner enum and struct in type definition for concrete type](https://github.com/rust-lang/rust/pull/114855/) + + + +Compatibility Notes +------------------- + +- [Raise minimum supported Apple OS versions](https://github.com/rust-lang/rust/pull/104385/) +- [make Cell::swap panic if the Cells partially overlap](https://github.com/rust-lang/rust/pull/114795/) +- [Reject invalid crate names in `--extern`](https://github.com/rust-lang/rust/pull/116001/) +- [Don't resolve generic impls that may be shadowed by dyn built-in impls](https://github.com/rust-lang/rust/pull/114941/) +- [The new `impl From<{&,&mut} [T; N]> for Vec` is known to cause some inference failures with overly-generic code.](https://github.com/rust-lang/rust/issues/117054) In those examples using the `tui` crate, the combination of `AsRef<_>` and `Into` leaves the middle type ambiguous, and the new `impl` adds another possibility, so it now requires an explicit type annotation. + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +None this cycle. + Version 1.73.0 (2023-10-05) ========================== @@ -83,7 +199,6 @@ These APIs are now stable in const contexts: Cargo ----- -- [Encode URL params correctly for `SourceId` in `Cargo.lock`.](https://github.com/rust-lang/cargo/pull/12280/) - [Bail out an error when using `cargo::` in custom build script.](https://github.com/rust-lang/cargo/pull/12332/) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 9127e1d06e88f..050366b081f0b 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -14,7 +14,7 @@ use crate::{ pub trait LayoutCalculator { type TargetDataLayoutRef: Borrow; - fn delay_bug(&self, txt: String); + fn delayed_bug(&self, txt: String); fn current_data_layout(&self) -> Self::TargetDataLayoutRef; fn scalar_pair( @@ -111,8 +111,8 @@ pub trait LayoutCalculator { alt_tail_space, layout.fields.count(), prefer_alt_layout, - format_field_niches(&layout, &fields, &dl), - format_field_niches(&alt_layout, &fields, &dl), + format_field_niches(layout, fields, dl), + format_field_niches(&alt_layout, fields, dl), ); if prefer_alt_layout { @@ -792,7 +792,7 @@ pub trait LayoutCalculator { let only_variant = &variants[VariantIdx::new(0)]; for field in only_variant { if field.is_unsized() { - self.delay_bug("unsized field in union".to_string()); + self.delayed_bug("unsized field in union".to_string()); } align = align.max(field.align); @@ -906,9 +906,8 @@ fn univariant< use rand::{seq::SliceRandom, SeedableRng}; // `ReprOptions.layout_seed` is a deterministic seed we can use to randomize field // ordering. - let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64( - repr.field_shuffle_seed.as_u64(), - ); + let mut rng = + rand_xoshiro::Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); // Shuffle the ordering of the fields. optimizing.shuffle(&mut rng); @@ -1026,7 +1025,7 @@ fn univariant< // At the bottom of this function, we invert `inverse_memory_index` to // produce `memory_index` (see `invert_mapping`). let mut sized = true; - let mut offsets = IndexVec::from_elem(Size::ZERO, &fields); + let mut offsets = IndexVec::from_elem(Size::ZERO, fields); let mut offset = Size::ZERO; let mut largest_niche = None; let mut largest_niche_available = 0; @@ -1039,7 +1038,7 @@ fn univariant< for &i in &inverse_memory_index { let field = &fields[i]; if !sized { - this.delay_bug(format!( + this.delayed_bug(format!( "univariant: field #{} comes after unsized field", offsets.len(), )); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 8e7aa59ee341e..eb42803f93e4e 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "nightly", feature(step_trait))] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(all(not(bootstrap), feature = "nightly"), doc(rust_logo))] -#![cfg_attr(all(not(bootstrap), feature = "nightly"), feature(rustdoc_internals))] +#![cfg_attr(feature = "nightly", doc(rust_logo))] +#![cfg_attr(feature = "nightly", feature(rustdoc_internals))] use std::fmt; use std::num::{NonZeroUsize, ParseIntError}; @@ -76,15 +76,14 @@ pub struct ReprOptions { pub align: Option, pub pack: Option, pub flags: ReprFlags, - #[cfg(feature = "randomize")] /// The seed to be used for randomizing a type's layout /// - /// Note: This could technically be a `Hash128` which would + /// Note: This could technically be a `u128` which would /// be the "most accurate" hash as it'd encompass the item and crate /// hash without loss, but it does pay the price of being larger. /// Everything's a tradeoff, a 64-bit seed should be sufficient for our /// purposes (primarily `-Z randomize-layout`) - pub field_shuffle_seed: rustc_data_structures::stable_hasher::Hash64, + pub field_shuffle_seed: u64, } impl ReprOptions { diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index a53fd4ae95a5d..621516af9c053 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -11,8 +11,8 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(no_crate_inject, attr(deny(warnings))) )] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(new_uninit)] @@ -197,23 +197,24 @@ impl TypedArena { start_ptr } + /// Allocates the elements of this iterator into a contiguous slice in the `TypedArena`. + /// + /// Note: for reasons of reentrancy and panic safety we collect into a `SmallVec<[_; 8]>` before + /// storing the elements in the arena. #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { - // This implementation is entirely separate to - // `DroplessIterator::alloc_from_iter`, even though conceptually they - // are the same. + // Despite the similarlty with `DroplessArena`, we cannot reuse their fast case. The reason + // is subtle: these arenas are reentrant. In other words, `iter` may very well be holding a + // reference to `self` and adding elements to the arena during iteration. // - // `DroplessIterator` (in the fast case) writes elements from the - // iterator one at a time into the allocated memory. That's easy - // because the elements don't implement `Drop`. But for `TypedArena` - // they do implement `Drop`, which means that if the iterator panics we - // could end up with some allocated-but-uninitialized elements, which - // will then cause UB in `TypedArena::drop`. + // For this reason, if we pre-allocated any space for the elements of this iterator, we'd + // have to track that some uninitialized elements are followed by some initialized elements, + // else we might accidentally drop uninitialized memory if something panics or if the + // iterator doesn't fill all the length we expected. // - // Instead we use an approach where any iterator panic will occur - // before the memory is allocated. This function is much less hot than - // `DroplessArena::alloc_from_iter`, so it doesn't need to be - // hyper-optimized. + // So we collect all the elements beforehand, which takes care of reentrancy and panic + // safety. This function is much less hot than `DroplessArena::alloc_from_iter`, so it + // doesn't need to be hyper-optimized. assert!(mem::size_of::() != 0); let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); @@ -483,10 +484,25 @@ impl DroplessArena { } } + /// Allocates a string slice that is copied into the `DroplessArena`, returning a + /// reference to it. Will panic if passed an empty string. + /// + /// Panics: + /// + /// - Zero-length string + #[inline] + pub fn alloc_str(&self, string: &str) -> &str { + let slice = self.alloc_slice(string.as_bytes()); + + // SAFETY: the result has a copy of the same valid UTF-8 bytes. + unsafe { std::str::from_utf8_unchecked(slice) } + } + /// # Safety /// - /// The caller must ensure that `mem` is valid for writes up to - /// `size_of::() * len`. + /// The caller must ensure that `mem` is valid for writes up to `size_of::() * len`, and that + /// that memory stays allocated and not shared for the lifetime of `self`. This must hold even + /// if `iter.next()` allocates onto `self`. #[inline] unsafe fn write_from_iter>( &self, @@ -516,6 +532,8 @@ impl DroplessArena { #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { + // Warning: this function is reentrant: `iter` could hold a reference to `&self` and + // allocate additional elements while we're iterating. let iter = iter.into_iter(); assert!(mem::size_of::() != 0); assert!(!mem::needs_drop::()); @@ -524,7 +542,7 @@ impl DroplessArena { match size_hint { (min, Some(max)) if min == max => { - // We know the exact number of elements the iterator will produce here + // We know the exact number of elements the iterator expects to produce here. let len = min; if len == 0 { @@ -532,10 +550,15 @@ impl DroplessArena { } let mem = self.alloc_raw(Layout::array::(len).unwrap()) as *mut T; + // SAFETY: `write_from_iter` doesn't touch `self`. It only touches the slice we just + // reserved. If the iterator panics or doesn't output `len` elements, this will + // leave some unallocated slots in the arena, which is fine because we do not call + // `drop`. unsafe { self.write_from_iter(iter, len, mem) } } (_, _) => { outline(move || -> &mut [T] { + // Takes care of reentrancy. let mut vec: SmallVec<[_; 8]> = iter.collect(); if vec.is_empty() { return &mut []; @@ -646,6 +669,14 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) { self.dropless.alloc_slice(value) } + #[inline] + pub fn alloc_str(&self, string: &str) -> &str { + if string.is_empty() { + return ""; + } + self.dropless.alloc_str(string) + } + #[allow(clippy::mut_from_ref)] pub fn alloc_from_iter, C>( &self, diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 146a4db200caa..d0acf0b560c74 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -301,7 +301,7 @@ pub enum TraitBoundModifier { Maybe, /// `~const Trait` - MaybeConst, + MaybeConst(Span), /// `~const !Trait` // @@ -317,8 +317,7 @@ pub enum TraitBoundModifier { impl TraitBoundModifier { pub fn to_constness(self) -> Const { match self { - // FIXME(effects) span - Self::MaybeConst => Const::Yes(DUMMY_SP), + Self::MaybeConst(span) => Const::Yes(span), _ => Const::No, } } @@ -646,6 +645,7 @@ impl Pat { // These patterns do not contain subpatterns, skip. PatKind::Wild | PatKind::Rest + | PatKind::Never | PatKind::Lit(_) | PatKind::Range(..) | PatKind::Ident(..) @@ -658,6 +658,24 @@ impl Pat { pub fn is_rest(&self) -> bool { matches!(self.kind, PatKind::Rest) } + + /// Whether this could be a never pattern, taking into account that a macro invocation can + /// return a never pattern. Used to inform errors during parsing. + pub fn could_be_never_pattern(&self) -> bool { + let mut could_be_never_pattern = false; + self.walk(&mut |pat| match &pat.kind { + PatKind::Never | PatKind::MacCall(_) => { + could_be_never_pattern = true; + false + } + PatKind::Or(s) => { + could_be_never_pattern = s.iter().all(|p| p.could_be_never_pattern()); + false + } + _ => true, + }); + could_be_never_pattern + } } /// A single field in a struct pattern. @@ -796,6 +814,9 @@ pub enum PatKind { /// only one rest pattern may occur in the pattern sequences. Rest, + // A never pattern `!` + Never, + /// Parentheses in patterns used for grouping (i.e., `(PAT)`). Paren(P), @@ -818,7 +839,7 @@ pub enum BorrowKind { Raw, } -#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)] +#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] pub enum BinOpKind { /// The `+` operator (addition) Add, @@ -859,9 +880,9 @@ pub enum BinOpKind { } impl BinOpKind { - pub fn to_string(&self) -> &'static str { + pub fn as_str(&self) -> &'static str { use BinOpKind::*; - match *self { + match self { Add => "+", Sub => "-", Mul => "*", @@ -882,19 +903,25 @@ impl BinOpKind { Gt => ">", } } - pub fn lazy(&self) -> bool { + + pub fn is_lazy(&self) -> bool { matches!(self, BinOpKind::And | BinOpKind::Or) } pub fn is_comparison(&self) -> bool { use BinOpKind::*; - // Note for developers: please keep this as is; + // Note for developers: please keep this match exhaustive; // we want compilation to fail if another variant is added. match *self { Eq | Lt | Le | Ne | Gt | Ge => true, And | Or | Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr => false, } } + + /// Returns `true` if the binary operator takes its arguments by value. + pub fn is_by_value(self) -> bool { + !self.is_comparison() + } } pub type BinOp = Spanned; @@ -902,7 +929,7 @@ pub type BinOp = Spanned; /// Unary operator. /// /// Note that `&data` is not an operator, it's an `AddrOf` expression. -#[derive(Clone, Encodable, Decodable, Debug, Copy)] +#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] pub enum UnOp { /// The `*` operator for dereferencing Deref, @@ -913,13 +940,18 @@ pub enum UnOp { } impl UnOp { - pub fn to_string(op: UnOp) -> &'static str { - match op { + pub fn as_str(&self) -> &'static str { + match self { UnOp::Deref => "*", UnOp::Not => "!", UnOp::Neg => "-", } } + + /// Returns `true` if the unary operator takes its argument by value. + pub fn is_by_value(self) -> bool { + matches!(self, Self::Neg | Self::Not) + } } /// A statement @@ -1066,8 +1098,8 @@ pub struct Arm { pub pat: P, /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }` pub guard: Option>, - /// Match arm body. - pub body: P, + /// Match arm body. Omitted if the pattern is a never pattern. + pub body: Option>, pub span: Span, pub id: NodeId, pub is_placeholder: bool, @@ -1297,7 +1329,7 @@ pub struct Closure { pub binder: ClosureBinder, pub capture_clause: CaptureBy, pub constness: Const, - pub asyncness: Async, + pub coro_kind: Option, pub movability: Movability, pub fn_decl: P, pub body: P, @@ -1548,7 +1580,10 @@ pub struct QSelf { #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum CaptureBy { /// `move |x| y + x`. - Value, + Value { + /// The span of the `move` keyword. + move_kw: Span, + }, /// `move` keyword was not specified. Ref, } @@ -2234,6 +2269,18 @@ pub enum InlineAsmOperand { }, } +impl InlineAsmOperand { + pub fn reg(&self) -> Option<&InlineAsmRegOrRegClass> { + match self { + Self::In { reg, .. } + | Self::Out { reg, .. } + | Self::InOut { reg, .. } + | Self::SplitInOut { reg, .. } => Some(reg), + Self::Const { .. } | Self::Sym { .. } => None, + } + } +} + /// Inline assembly. /// /// E.g., `asm!("NOP");`. @@ -2377,28 +2424,34 @@ pub enum Unsafe { No, } +/// Describes what kind of coroutine markers, if any, a function has. +/// +/// Coroutine markers are things that cause the function to generate a coroutine, such as `async`, +/// which makes the function return `impl Future`, or `gen`, which makes the function return `impl +/// Iterator`. #[derive(Copy, Clone, Encodable, Decodable, Debug)] -pub enum Async { - Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId }, - No, -} - -#[derive(Copy, Clone, Encodable, Decodable, Debug)] -pub enum Gen { - Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId }, - No, +pub enum CoroutineKind { + /// `async`, which evaluates to `impl Future` + Async { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId }, + /// `gen`, which evaluates to `impl Iterator` + Gen { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId }, } -impl Async { +impl CoroutineKind { pub fn is_async(self) -> bool { - matches!(self, Async::Yes { .. }) + matches!(self, CoroutineKind::Async { .. }) + } + + pub fn is_gen(self) -> bool { + matches!(self, CoroutineKind::Gen { .. }) } - /// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item. - pub fn opt_return_id(self) -> Option<(NodeId, Span)> { + /// In this case this is an `async` or `gen` return, the `NodeId` for the generated `impl Trait` + /// item. + pub fn return_id(self) -> (NodeId, Span) { match self { - Async::Yes { return_impl_trait_id, span, .. } => Some((return_impl_trait_id, span)), - Async::No => None, + CoroutineKind::Async { return_impl_trait_id, span, .. } + | CoroutineKind::Gen { return_impl_trait_id, span, .. } => (return_impl_trait_id, span), } } } @@ -2571,7 +2624,7 @@ pub enum AttrStyle { } rustc_index::newtype_index! { - #[custom_encodable] + #[orderable] #[debug_format = "AttrId({})"] pub struct AttrId {} } @@ -2802,8 +2855,8 @@ impl Extern { pub struct FnHeader { /// The `unsafe` keyword, if any pub unsafety: Unsafe, - /// The `async` keyword, if any - pub asyncness: Async, + /// Whether this is `async`, `gen`, or nothing. + pub coro_kind: Option, /// The `const` keyword, if any pub constness: Const, /// The `extern` keyword and corresponding ABI string, if any @@ -2813,9 +2866,9 @@ pub struct FnHeader { impl FnHeader { /// Does this function header have any qualifiers or is it empty? pub fn has_qualifiers(&self) -> bool { - let Self { unsafety, asyncness, constness, ext } = self; + let Self { unsafety, coro_kind, constness, ext } = self; matches!(unsafety, Unsafe::Yes(_)) - || asyncness.is_async() + || coro_kind.is_some() || matches!(constness, Const::Yes(_)) || !matches!(ext, Extern::None) } @@ -2823,12 +2876,7 @@ impl FnHeader { impl Default for FnHeader { fn default() -> FnHeader { - FnHeader { - unsafety: Unsafe::No, - asyncness: Async::No, - constness: Const::No, - ext: Extern::None, - } + FnHeader { unsafety: Unsafe::No, coro_kind: None, constness: Const::No, ext: Extern::None } } } @@ -3148,11 +3196,11 @@ mod size_asserts { static_assert_size!(Block, 32); static_assert_size!(Expr, 72); static_assert_size!(ExprKind, 40); - static_assert_size!(Fn, 152); + static_assert_size!(Fn, 160); static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericArg, 24); - static_assert_size!(GenericBound, 56); + static_assert_size!(GenericBound, 64); static_assert_size!(Generics, 40); static_assert_size!(Impl, 136); static_assert_size!(Item, 136); diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index be7d1b207bcf4..851ab46345fd1 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -342,7 +342,7 @@ impl MetaItem { let span = span.with_hi(segments.last().unwrap().ident.span.hi()); Path { span, segments, tokens: None } } - Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt { + Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &nt.0 { token::Nonterminal::NtMeta(item) => return item.meta(item.path.span), token::Nonterminal::NtPath(path) => (**path).clone(), _ => return None, @@ -391,7 +391,7 @@ impl MetaItemKind { MetaItemKind::name_value_from_tokens(&mut inner_tokens.trees()) } Some(TokenTree::Token(token, _)) => { - MetaItemLit::from_token(&token).map(MetaItemKind::NameValue) + MetaItemLit::from_token(token).map(MetaItemKind::NameValue) } _ => None, } diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index c1f6ad6a27db0..7e713a49a8cfa 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -8,9 +8,9 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(deny(warnings))) )] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![allow(internal_features)] +#![feature(rustdoc_internals)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(const_trait_impl)] @@ -59,9 +59,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: - rustc_type_ir::HashStableContext + rustc_span::HashStableContext -{ +pub trait HashStableContext: rustc_span::HashStableContext { fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher); } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 0634ee970ec5e..342f5530b40fa 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -121,8 +121,8 @@ pub trait MutVisitor: Sized { noop_visit_fn_decl(d, self); } - fn visit_asyncness(&mut self, a: &mut Async) { - noop_visit_asyncness(a, self); + fn visit_coro_kind(&mut self, a: &mut CoroutineKind) { + noop_visit_coro_kind(a, self); } fn visit_closure_binder(&mut self, b: &mut ClosureBinder) { @@ -302,6 +302,10 @@ pub trait MutVisitor: Sized { fn visit_format_args(&mut self, fmt: &mut FormatArgs) { noop_visit_format_args(fmt, self) } + + fn visit_capture_by(&mut self, capture_by: &mut CaptureBy) { + noop_visit_capture_by(capture_by, self) + } } /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful @@ -449,7 +453,7 @@ pub fn noop_flat_map_arm(mut arm: Arm, vis: &mut T) -> SmallVec<[ vis.visit_id(id); vis.visit_pat(pat); visit_opt(guard, |guard| vis.visit_expr(guard)); - vis.visit_expr(body); + visit_opt(body, |body| vis.visit_expr(body)); vis.visit_span(span); smallvec![arm] } @@ -760,7 +764,10 @@ pub fn visit_token(t: &mut Token, vis: &mut T) { return; // Avoid visiting the span for the second time. } token::Interpolated(nt) => { - visit_nonterminal(Lrc::make_mut(nt), vis); + let nt = Lrc::make_mut(nt); + let (nt, sp) = (&mut nt.0, &mut nt.1); + vis.visit_span(sp); + visit_nonterminal(nt, vis); } _ => {} } @@ -864,13 +871,14 @@ pub fn noop_visit_closure_binder(binder: &mut ClosureBinder, vis: } } -pub fn noop_visit_asyncness(asyncness: &mut Async, vis: &mut T) { - match asyncness { - Async::Yes { span: _, closure_id, return_impl_trait_id } => { +pub fn noop_visit_coro_kind(coro_kind: &mut CoroutineKind, vis: &mut T) { + match coro_kind { + CoroutineKind::Async { span, closure_id, return_impl_trait_id } + | CoroutineKind::Gen { span, closure_id, return_impl_trait_id } => { + vis.visit_span(span); vis.visit_id(closure_id); vis.visit_id(return_impl_trait_id); } - Async::No => {} } } @@ -1163,9 +1171,9 @@ fn visit_const_item( } pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { - let FnHeader { unsafety, asyncness, constness, ext: _ } = header; + let FnHeader { unsafety, coro_kind, constness, ext: _ } = header; visit_constness(constness, vis); - vis.visit_asyncness(asyncness); + coro_kind.as_mut().map(|coro_kind| vis.visit_coro_kind(coro_kind)); visit_unsafety(unsafety, vis); } @@ -1242,7 +1250,7 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { let Pat { id, kind, span, tokens } = pat.deref_mut(); vis.visit_id(id); match kind { - PatKind::Wild | PatKind::Rest => {} + PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Ident(_binding_mode, ident, sub) => { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); @@ -1397,9 +1405,9 @@ pub fn noop_visit_expr( } ExprKind::Closure(box Closure { binder, - capture_clause: _, + capture_clause, constness, - asyncness, + coro_kind, movability: _, fn_decl, body, @@ -1408,7 +1416,8 @@ pub fn noop_visit_expr( }) => { vis.visit_closure_binder(binder); visit_constness(constness, vis); - vis.visit_asyncness(asyncness); + coro_kind.as_mut().map(|coro_kind| vis.visit_coro_kind(coro_kind)); + vis.visit_capture_by(capture_clause); vis.visit_fn_decl(fn_decl); vis.visit_expr(body); vis.visit_span(fn_decl_span); @@ -1562,6 +1571,15 @@ pub fn noop_visit_vis(visibility: &mut Visibility, vis: &mut T) { vis.visit_span(&mut visibility.span); } +pub fn noop_visit_capture_by(capture_by: &mut CaptureBy, vis: &mut T) { + match capture_by { + CaptureBy::Ref => {} + CaptureBy::Value { move_kw } => { + vis.visit_span(move_kw); + } + } +} + /// Some value for the AST node that is valid but possibly meaningless. pub trait DummyAstNode { fn dummy() -> Self; diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs index d16741757d1f1..1cd2449530901 100644 --- a/compiler/rustc_ast/src/node_id.rs +++ b/compiler/rustc_ast/src/node_id.rs @@ -8,6 +8,8 @@ rustc_index::newtype_index! { /// This is later turned into [`DefId`] and `HirId` for the HIR. /// /// [`DefId`]: rustc_span::def_id::DefId + #[encodable] + #[orderable] #[debug_format = "NodeId({})"] pub struct NodeId { /// The [`NodeId`] used to represent the root of the crate. diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 914c97a14ac0d..a7c6f8c5d8c26 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -110,7 +110,7 @@ impl Lit { Ident(name, false) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)), Literal(token_lit) => Some(token_lit), Interpolated(ref nt) - if let NtExpr(expr) | NtLiteral(expr) = &**nt + if let NtExpr(expr) | NtLiteral(expr) = &nt.0 && let ast::ExprKind::Lit(token_lit) = expr.kind => { Some(token_lit) @@ -238,9 +238,9 @@ pub enum TokenKind { EqEq, /// `!=` Ne, - /// `>` - Ge, /// `>=` + Ge, + /// `>` Gt, /// `&&` AndAnd, @@ -314,7 +314,7 @@ pub enum TokenKind { /// - It prevents `Token` from implementing `Copy`. /// It adds complexity and likely slows things down. Please don't add new /// occurrences of this token kind! - Interpolated(Lrc), + Interpolated(Lrc<(Nonterminal, Span)>), /// A doc comment token. /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc) @@ -388,7 +388,8 @@ impl TokenKind { match *self { Comma => Some(vec![Dot, Lt, Semi]), Semi => Some(vec![Colon, Comma]), - FatArrow => Some(vec![Eq, RArrow]), + Colon => Some(vec![Semi]), + FatArrow => Some(vec![Eq, RArrow, Ge, Gt]), _ => None, } } @@ -421,7 +422,7 @@ impl Token { /// if they keep spans or perform edition checks. pub fn uninterpolated_span(&self) -> Span { match &self.kind { - Interpolated(nt) => nt.span(), + Interpolated(nt) => nt.0.use_span(), _ => self.span, } } @@ -464,7 +465,7 @@ impl Token { ModSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt) => matches!(**nt, NtLiteral(..) | + Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) | NtExpr(..) | NtBlock(..) | NtPath(..)), @@ -488,7 +489,7 @@ impl Token { | DotDot | DotDotDot | DotDotEq // ranges | Lt | BinOp(Shl) // associated path | ModSep => true, // global path - Interpolated(ref nt) => matches!(**nt, NtLiteral(..) | + Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) | NtPat(..) | NtBlock(..) | NtPath(..)), @@ -511,7 +512,7 @@ impl Token { Lifetime(..) | // lifetime bound in trait object Lt | BinOp(Shl) | // associated path ModSep => true, // global path - Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)), + Interpolated(ref nt) => matches!(&nt.0, NtTy(..) | NtPath(..)), // For anonymous structs or unions, which only appear in specific positions // (type of struct fields or union fields), we don't consider them as regular types _ => false, @@ -522,7 +523,7 @@ impl Token { pub fn can_begin_const_arg(&self) -> bool { match self.kind { OpenDelim(Delimiter::Brace) => true, - Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), + Interpolated(ref nt) => matches!(&nt.0, NtExpr(..) | NtBlock(..) | NtLiteral(..)), _ => self.can_begin_literal_maybe_minus(), } } @@ -576,7 +577,7 @@ impl Token { match self.uninterpolate().kind { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, - Interpolated(ref nt) => match &**nt { + Interpolated(ref nt) => match &nt.0 { NtLiteral(_) => true, NtExpr(e) => match &e.kind { ast::ExprKind::Lit(_) => true, @@ -597,9 +598,9 @@ impl Token { /// otherwise returns the original token. pub fn uninterpolate(&self) -> Cow<'_, Token> { match &self.kind { - Interpolated(nt) => match **nt { + Interpolated(nt) => match &nt.0 { NtIdent(ident, is_raw) => { - Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)) + Cow::Owned(Token::new(Ident(ident.name, *is_raw), ident.span)) } NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)), _ => Cow::Borrowed(self), @@ -614,8 +615,8 @@ impl Token { // We avoid using `Token::uninterpolate` here because it's slow. match &self.kind { &Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)), - Interpolated(nt) => match **nt { - NtIdent(ident, is_raw) => Some((ident, is_raw)), + Interpolated(nt) => match &nt.0 { + NtIdent(ident, is_raw) => Some((*ident, *is_raw)), _ => None, }, _ => None, @@ -628,8 +629,8 @@ impl Token { // We avoid using `Token::uninterpolate` here because it's slow. match &self.kind { &Lifetime(name) => Some(Ident::new(name, self.span)), - Interpolated(nt) => match **nt { - NtLifetime(ident) => Some(ident), + Interpolated(nt) => match &nt.0 { + NtLifetime(ident) => Some(*ident), _ => None, }, _ => None, @@ -655,7 +656,7 @@ impl Token { /// Returns `true` if the token is an interpolated path. fn is_path(&self) -> bool { if let Interpolated(nt) = &self.kind - && let NtPath(..) = **nt + && let NtPath(..) = &nt.0 { return true; } @@ -668,7 +669,7 @@ impl Token { /// (which happens while parsing the result of macro expansion)? pub fn is_whole_expr(&self) -> bool { if let Interpolated(nt) = &self.kind - && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = **nt + && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = &nt.0 { return true; } @@ -679,7 +680,7 @@ impl Token { /// Is the token an interpolated block (`$b:block`)? pub fn is_whole_block(&self) -> bool { if let Interpolated(nt) = &self.kind - && let NtBlock(..) = **nt + && let NtBlock(..) = &nt.0 { return true; } @@ -755,6 +756,11 @@ impl Token { ) } + /// Returns `true` if the token is the integer literal. + pub fn is_integer_lit(&self) -> bool { + matches!(self.kind, Literal(Lit { kind: LitKind::Integer, .. })) + } + /// Returns `true` if the token is a non-raw identifier for which `pred` holds. pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool { match self.ident() { @@ -927,7 +933,7 @@ impl fmt::Display for NonterminalKind { } impl Nonterminal { - pub fn span(&self) -> Span { + pub fn use_span(&self) -> Span { match self { NtItem(item) => item.span, NtBlock(block) => block.span, @@ -941,6 +947,23 @@ impl Nonterminal { NtVis(vis) => vis.span, } } + + pub fn descr(&self) -> &'static str { + match self { + NtItem(..) => "item", + NtBlock(..) => "block", + NtStmt(..) => "statement", + NtPat(..) => "pattern", + NtExpr(..) => "expression", + NtLiteral(..) => "literal", + NtTy(..) => "type", + NtIdent(..) => "identifier", + NtLifetime(..) => "lifetime", + NtMeta(..) => "attribute", + NtPath(..) => "path", + NtVis(..) => "visibility", + } + } } impl PartialEq for Nonterminal { diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 23b8f9c12d8f6..48854bbae24cd 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -477,13 +477,13 @@ impl TokenStream { fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree { match &token.kind { - token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = **nt => { + token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = nt.0 => { TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing) } token::Interpolated(nt) => TokenTree::Delimited( DelimSpan::from_single(token.span), Delimiter::Invisible, - TokenStream::from_nonterminal_ast(nt).flattened(), + TokenStream::from_nonterminal_ast(&nt.0).flattened(), ), _ => TokenTree::Token(token.clone(), spacing), } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e091961a14438..6b290fdfcc91e 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -251,6 +251,9 @@ pub trait Visitor<'ast>: Sized { fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) { walk_inline_asm_sym(self, sym) } + fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) { + // Nothing to do + } } #[macro_export] @@ -556,7 +559,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, upper_bound); } - PatKind::Wild | PatKind::Rest => {} + PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); } @@ -857,8 +860,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { } ExprKind::Closure(box Closure { binder, - capture_clause: _, - asyncness: _, + capture_clause, + coro_kind: _, constness: _, movability: _, fn_decl, @@ -866,6 +869,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { fn_decl_span: _, fn_arg_span: _, }) => { + visitor.visit_capture_by(capture_clause); visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id) } ExprKind::Block(block, opt_label) => { @@ -947,7 +951,7 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) { pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) { visitor.visit_pat(&arm.pat); walk_list!(visitor, visit_expr, &arm.guard); - visitor.visit_expr(&arm.body); + walk_list!(visitor, visit_expr, &arm.body); walk_list!(visitor, visit_attribute, &arm.attrs); } diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 91591a71611b4..6bde4f2d8fa5a 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -91,6 +91,10 @@ ast_lowering_invalid_register = ast_lowering_invalid_register_class = invalid register class `{$reg_class}`: {$error} +ast_lowering_match_arm_with_no_body = + `match` arm with no body + .suggestion = add a body after the pattern + ast_lowering_misplaced_assoc_ty_binding = associated type bounds are only allowed in where clauses and function signatures, not in {$position} @@ -104,6 +108,15 @@ ast_lowering_misplaced_impl_trait = ast_lowering_misplaced_relax_trait_bound = `?Trait` bounds are only permitted at the point where a type parameter is declared +ast_lowering_never_pattern_with_body = + a never pattern is always unreachable + .label = this will never be executed + .suggestion = remove this expression + +ast_lowering_never_pattern_with_guard = + a guard on a never pattern will never be run + .suggestion = remove this guard + ast_lowering_not_supported_for_lifetime_binder_async_closure = `for<...>` binders on `async` closures are not currently supported diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index a1e626996800f..7111daa2ea9ab 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -14,8 +14,8 @@ use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::definitions::DefPathData; use rustc_session::parse::feature_err; +use rustc_span::symbol::kw; use rustc_span::{sym, Span}; use rustc_target::asm; use std::collections::hash_map::Entry; @@ -227,7 +227,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.create_def( parent_def_id.def_id, node_id, - DefPathData::AnonConst, + kw::Empty, + DefKind::AnonConst, *op_sp, ); let anon_const = AnonConst { id: node_id, value: P(expr) }; @@ -341,61 +342,75 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Flag to output the error only once per operand let mut skip = false; - reg.overlapping_regs(|r| { - let mut check = |used_regs: &mut FxHashMap, - input| { - match used_regs.entry(r) { - Entry::Occupied(o) => { - if skip { - return; - } - skip = true; - let idx2 = *o.get(); - let (ref op2, op_sp2) = operands[idx2]; - let Some(asm::InlineAsmRegOrRegClass::Reg(reg2)) = op2.reg() - else { - unreachable!(); - }; + let mut check = |used_regs: &mut FxHashMap, + input, + r: asm::InlineAsmReg| { + match used_regs.entry(r) { + Entry::Occupied(o) => { + if skip { + return; + } + skip = true; - let in_out = match (op, op2) { - ( - hir::InlineAsmOperand::In { .. }, - hir::InlineAsmOperand::Out { late, .. }, - ) - | ( - hir::InlineAsmOperand::Out { late, .. }, - hir::InlineAsmOperand::In { .. }, - ) => { - assert!(!*late); - let out_op_sp = if input { op_sp2 } else { op_sp }; - Some(out_op_sp) - } - _ => None, - }; + let idx2 = *o.get(); + let (ref op2, op_sp2) = operands[idx2]; - sess.emit_err(RegisterConflict { - op_span1: op_sp, - op_span2: op_sp2, - reg1_name: reg.name(), - reg2_name: reg2.name(), - in_out, - }); - } - Entry::Vacant(v) => { - if r == reg { - v.insert(idx); + let in_out = match (op, op2) { + ( + hir::InlineAsmOperand::In { .. }, + hir::InlineAsmOperand::Out { late, .. }, + ) + | ( + hir::InlineAsmOperand::Out { late, .. }, + hir::InlineAsmOperand::In { .. }, + ) => { + assert!(!*late); + let out_op_sp = if input { op_sp2 } else { op_sp }; + Some(out_op_sp) + } + _ => None, + }; + let reg_str = |idx| -> &str { + // HIR asm doesn't preserve the original alias string of the explicit register, + // so we have to retrieve it from AST + let (op, _): &(InlineAsmOperand, Span) = &asm.operands[idx]; + if let Some(ast::InlineAsmRegOrRegClass::Reg(reg_sym)) = + op.reg() + { + reg_sym.as_str() + } else { + unreachable!(); } + }; + + sess.emit_err(RegisterConflict { + op_span1: op_sp, + op_span2: op_sp2, + reg1_name: reg_str(idx), + reg2_name: reg_str(idx2), + in_out, + }); + } + Entry::Vacant(v) => { + if r == reg { + v.insert(idx); } } - }; + } + }; + let mut overlapping_with = vec![]; + reg.overlapping_regs(|r| { + overlapping_with.push(r); + }); + for r in overlapping_with { if input { - check(&mut used_input_regs, true); + check(&mut used_input_regs, true, r); } if output { - check(&mut used_output_regs, false); + check(&mut used_output_regs, false, r); } - }); + } } } } @@ -410,12 +425,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { continue; } - let mut output_used = false; + let mut overlapping_with = vec![]; clobber.overlapping_regs(|reg| { - if used_output_regs.contains_key(®) { - output_used = true; - } + overlapping_with.push(reg); }); + let output_used = + overlapping_with.iter().any(|reg| used_output_regs.contains_key(®)); if !output_used { operands.push(( diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 6e1a9eff5008d..11bb559719b9f 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -340,6 +340,32 @@ pub struct NotSupportedForLifetimeBinderAsyncClosure { pub span: Span, } +#[derive(Diagnostic)] +#[diag(ast_lowering_match_arm_with_no_body)] +pub struct MatchArmWithNoBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] + pub suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_lowering_never_pattern_with_body)] +pub struct NeverPatternWithBody { + #[primary_span] + #[label] + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_lowering_never_pattern_with_guard)] +pub struct NeverPatternWithGuard { + #[primary_span] + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub span: Span, +} + #[derive(Diagnostic, Clone, Copy)] #[diag(ast_lowering_arbitrary_expression_in_pattern)] pub struct ArbitraryExpressionInPattern { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0fff9a6be926d..835ff36acbc05 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,8 +1,9 @@ use super::errors::{ AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters, - FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, - NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign, + FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody, + NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, + UnderscoreExprLhsAssign, }; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; @@ -12,11 +13,10 @@ use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; -use rustc_hir::def::Res; -use rustc_hir::definitions::DefPathData; +use rustc_hir::def::{DefKind, Res}; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{respan, Spanned}; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::DUMMY_SP; use rustc_span::{DesugaringKind, Span}; use thin_vec::{thin_vec, ThinVec}; @@ -42,8 +42,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } // Merge attributes into the inner expression. if !e.attrs.is_empty() { - let old_attrs = - self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]); + let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]); self.attrs.insert( ex.hir_id.local_id, &*self.arena.alloc_from_iter( @@ -73,7 +72,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), ExprKind::ConstBlock(c) => { - let c = self.with_new_scopes(|this| hir::ConstBlock { + let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), @@ -190,46 +189,46 @@ impl<'hir> LoweringContext<'_, 'hir> { None, e.span, hir::CoroutineSource::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), ), ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), ExprKind::Closure(box Closure { binder, capture_clause, constness, - asyncness, + coro_kind, movability, fn_decl, body, fn_decl_span, fn_arg_span, - }) => { - if let Async::Yes { closure_id, .. } = asyncness { - self.lower_expr_async_closure( - binder, - *capture_clause, - e.id, - hir_id, - *closure_id, - fn_decl, - body, - *fn_decl_span, - *fn_arg_span, - ) - } else { - self.lower_expr_closure( - binder, - *capture_clause, - e.id, - *constness, - *movability, - fn_decl, - body, - *fn_decl_span, - *fn_arg_span, - ) - } - } + }) => match coro_kind { + Some( + CoroutineKind::Async { closure_id, .. } + | CoroutineKind::Gen { closure_id, .. }, + ) => self.lower_expr_async_closure( + binder, + *capture_clause, + e.id, + hir_id, + *closure_id, + fn_decl, + body, + *fn_decl_span, + *fn_arg_span, + ), + None => self.lower_expr_closure( + binder, + *capture_clause, + e.id, + *constness, + *movability, + fn_decl, + body, + *fn_decl_span, + *fn_arg_span, + ), + }, ExprKind::Block(blk, opt_label) => { let opt_label = self.lower_label(*opt_label); hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label) @@ -324,11 +323,11 @@ impl<'hir> LoweringContext<'_, 'hir> { None, e.span, hir::CoroutineSource::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), ), ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err => hir::ExprKind::Err( - self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"), + self.tcx.sess.span_delayed_bug(e.span, "lowered ExprKind::Err"), ), ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr), @@ -351,30 +350,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_binop(&mut self, b: BinOp) -> hir::BinOp { - Spanned { - node: match b.node { - BinOpKind::Add => hir::BinOpKind::Add, - BinOpKind::Sub => hir::BinOpKind::Sub, - BinOpKind::Mul => hir::BinOpKind::Mul, - BinOpKind::Div => hir::BinOpKind::Div, - BinOpKind::Rem => hir::BinOpKind::Rem, - BinOpKind::And => hir::BinOpKind::And, - BinOpKind::Or => hir::BinOpKind::Or, - BinOpKind::BitXor => hir::BinOpKind::BitXor, - BinOpKind::BitAnd => hir::BinOpKind::BitAnd, - BinOpKind::BitOr => hir::BinOpKind::BitOr, - BinOpKind::Shl => hir::BinOpKind::Shl, - BinOpKind::Shr => hir::BinOpKind::Shr, - BinOpKind::Eq => hir::BinOpKind::Eq, - BinOpKind::Lt => hir::BinOpKind::Lt, - BinOpKind::Le => hir::BinOpKind::Le, - BinOpKind::Ne => hir::BinOpKind::Ne, - BinOpKind::Ge => hir::BinOpKind::Ge, - BinOpKind::Gt => hir::BinOpKind::Gt, - }, - span: self.lower_span(b.span), - } + fn lower_binop(&mut self, b: BinOp) -> BinOp { + Spanned { node: b.node, span: self.lower_span(b.span) } } fn lower_legacy_const_generics( @@ -396,7 +373,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst, f.span); + self.create_def( + parent_def_id.def_id, + node_id, + kw::Empty, + DefKind::AnonConst, + f.span, + ); let anon_const = AnonConst { id: node_id, value: arg }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); @@ -525,7 +508,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.mark_span_with_reason( DesugaringKind::TryBlock, expr.span, - this.allow_try_trait.clone(), + Some(this.allow_try_trait.clone()), ), expr, ) @@ -533,7 +516,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let try_span = this.mark_span_with_reason( DesugaringKind::TryBlock, this.tcx.sess.source_map().end_point(body.span), - this.allow_try_trait.clone(), + Some(this.allow_try_trait.clone()), ); (try_span, this.expr_unit(try_span)) @@ -561,13 +544,13 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &'hir hir::Expr<'hir>, overall_span: Span, ) -> &'hir hir::Expr<'hir> { - let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None)); + let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item)); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> { let pat = self.lower_pat(&arm.pat); - let guard = arm.guard.as_ref().map(|cond| { + let mut guard = arm.guard.as_ref().map(|cond| { if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind { hir::Guard::IfLet(self.arena.alloc(hir::Let { hir_id: self.next_id(), @@ -582,14 +565,43 @@ impl<'hir> LoweringContext<'_, 'hir> { } }); let hir_id = self.next_id(); + let span = self.lower_span(arm.span); self.lower_attrs(hir_id, &arm.attrs); - hir::Arm { - hir_id, - pat, - guard, - body: self.lower_expr(&arm.body), - span: self.lower_span(arm.span), - } + let is_never_pattern = pat.is_never_pattern(); + let body = if let Some(body) = &arm.body + && !is_never_pattern + { + self.lower_expr(body) + } else { + // Either `body.is_none()` or `is_never_pattern` here. + if !is_never_pattern { + let suggestion = span.shrink_to_hi(); + self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion }); + } else if let Some(body) = &arm.body { + self.tcx.sess.emit_err(NeverPatternWithBody { span: body.span }); + guard = None; + } else if let Some(g) = &arm.guard { + self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span }); + guard = None; + } + + // We add a fake `loop {}` arm body so that it typecks to `!`. + // FIXME(never_patterns): Desugar into a call to `unreachable_unchecked`. + let block = self.arena.alloc(hir::Block { + stmts: &[], + expr: None, + hir_id: self.next_id(), + rules: hir::BlockCheckMode::DefaultBlock, + span, + targeted_by_break: false, + }); + self.arena.alloc(hir::Expr { + hir_id: self.next_id(), + kind: hir::ExprKind::Loop(block, None, hir::LoopSource::Loop, span), + span, + }) + }; + hir::Arm { hir_id, pat, guard, body, span } } /// Lower an `async` construct to a coroutine that implements `Future`. @@ -613,9 +625,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); // Resume argument type: `ResumeTy` - let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); - let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None); + let unstable_span = self.mark_span_with_reason( + DesugaringKind::Async, + span, + Some(self.allow_gen_future.clone()), + ); + let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span); let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Path(resume_ty), @@ -736,7 +751,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::Async, span, - self.allow_gen_future.clone(), + Some(self.allow_gen_future.clone()), ); self.lower_attrs( inner_hir_id, @@ -773,17 +788,17 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.coroutine_kind { Some(hir::CoroutineKind::Async(_)) => {} Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => { - self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { + return hir::ExprKind::Err(self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { await_kw_span, item_span: self.current_item, - }); + })); } } let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None); let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, full_span, - self.allow_gen_future.clone(), + Some(self.allow_gen_future.clone()), ); let expr = self.lower_expr_mut(expr); let expr_hir_id = expr.hir_id; @@ -792,8 +807,11 @@ impl<'hir> LoweringContext<'_, 'hir> { // debuggers and debugger extensions expect it to be called `__awaitee`. They use // this name to identify what is being awaited by a suspended async functions. let awaitee_ident = Ident::with_dummy_span(sym::__awaitee); - let (awaitee_pat, awaitee_pat_hid) = - self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT); + let (awaitee_pat, awaitee_pat_hid) = self.pat_ident_binding_mode( + gen_future_span, + awaitee_ident, + hir::BindingAnnotation::MUT, + ); let task_context_ident = Ident::with_dummy_span(sym::_task_context); @@ -810,25 +828,22 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr_ident_mut(span, task_context_ident, task_context_hid) } else { // Use of `await` outside of an async context, we cannot use `task_context` here. - self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no task_context hir id")) + self.expr_err(span, self.tcx.sess.span_delayed_bug(span, "no task_context hir id")) }; let new_unchecked = self.expr_call_lang_item_fn_mut( span, hir::LangItem::PinNewUnchecked, arena_vec![self; ref_mut_awaitee], - Some(expr_hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( gen_future_span, hir::LangItem::GetContext, arena_vec![self; task_context], - Some(expr_hir_id), ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, arena_vec![self; new_unchecked, get_context], - Some(expr_hir_id), ); self.arena.alloc(self.expr_unsafe(call)) }; @@ -841,12 +856,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (x_pat, x_pat_hid) = self.pat_ident(gen_future_span, x_ident); let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid); let ready_field = self.single_pat_field(gen_future_span, x_pat); - let ready_pat = self.pat_lang_item_variant( - span, - hir::LangItem::PollReady, - ready_field, - Some(expr_hir_id), - ); + let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field); let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); @@ -857,12 +867,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `::std::task::Poll::Pending => {}` let pending_arm = { - let pending_pat = self.pat_lang_item_variant( - span, - hir::LangItem::PollPending, - &[], - Some(expr_hir_id), - ); + let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); let empty_block = self.expr_block_empty(span); self.arm(pending_pat, empty_block) }; @@ -920,7 +925,6 @@ impl<'hir> LoweringContext<'_, 'hir> { span, hir::LangItem::IntoFutureIntoFuture, arena_vec![self; expr], - Some(expr_hir_id), ); // match { @@ -947,9 +951,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); - let (body_id, coroutine_option) = self.with_new_scopes(move |this| { - let prev = this.current_item; - this.current_item = Some(fn_decl_span); + let (body_id, coroutine_option) = self.with_new_scopes(fn_decl_span, move |this| { let mut coroutine_kind = None; let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr_mut(body); @@ -957,8 +959,7 @@ impl<'hir> LoweringContext<'_, 'hir> { e }); let coroutine_option = - this.coroutine_movability_for_fn(&decl, fn_decl_span, coroutine_kind, movability); - this.current_item = prev; + this.coroutine_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); (body_id, coroutine_option) }); @@ -1044,7 +1045,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let outer_decl = FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - let body = self.with_new_scopes(|this| { + let body = self.with_new_scopes(fn_decl_span, |this| { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); @@ -1055,7 +1056,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_id = this.lower_fn_body(&outer_decl, |this| { let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output { let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock); - Some(hir::FnRetTy::Return(this.lower_ty(&ty, &itctx))) + Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx))) } else { None }; @@ -1066,7 +1067,7 @@ impl<'hir> LoweringContext<'_, 'hir> { async_ret_ty, body.span, hir::CoroutineSource::Closure, - |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), + |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), ); let hir_id = this.lower_node_id(inner_closure_id); this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); @@ -1154,7 +1155,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .alloc_from_iter(std::iter::once(destructure_let).chain(assignments.into_iter())); // Wrap everything in a block. - hir::ExprKind::Block(&self.block_all(whole_span, stmts, None), None) + hir::ExprKind::Block(self.block_all(whole_span, stmts, None), None) } /// If the given expression is a path to a tuple struct, returns that path. @@ -1377,8 +1378,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> { let e1 = self.lower_expr_mut(e1); let e2 = self.lower_expr_mut(e2); - let fn_path = - hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); + let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span)); let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path))); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) } @@ -1411,7 +1411,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fields = self.arena.alloc_from_iter( e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map( |(s, e)| { - let expr = self.lower_expr(&e); + let expr = self.lower_expr(e); let ident = Ident::new(s, self.lower_span(e.span)); self.expr_field(ident, expr, e.span) }, @@ -1419,7 +1419,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ExprKind::Struct( - self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), + self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))), fields, None, ) @@ -1507,7 +1507,9 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.coroutine_kind { Some(hir::CoroutineKind::Gen(_)) => {} Some(hir::CoroutineKind::Async(_)) => { - self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }); + return hir::ExprKind::Err( + self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }), + ); } Some(hir::CoroutineKind::Coroutine) | None => { if !self.tcx.features().coroutines { @@ -1588,7 +1590,6 @@ impl<'hir> LoweringContext<'_, 'hir> { head_span, hir::LangItem::IteratorNext, arena_vec![self; ref_mut_iter], - None, ); let arms = arena_vec![self; none_arm, some_arm]; @@ -1617,7 +1618,6 @@ impl<'hir> LoweringContext<'_, 'hir> { head_span, hir::LangItem::IntoIterIntoIter, arena_vec![self; head], - None, ) }; @@ -1655,13 +1655,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); let try_span = self.tcx.sess.source_map().end_point(span); let try_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, try_span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); // `Try::branch()` @@ -1673,7 +1673,6 @@ impl<'hir> LoweringContext<'_, 'hir> { unstable_span, hir::LangItem::TryTraitBranch, arena_vec![self; sub_expr], - None, ) }; @@ -1755,7 +1754,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::YeetExpr, span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); let from_yeet_expr = self.wrap_in_try_constructor( @@ -1878,9 +1877,8 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], - hir_id: Option, ) -> hir::Expr<'hir> { - let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id)); + let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item)); self.expr_call_mut(span, path, args) } @@ -1889,21 +1887,12 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], - hir_id: Option, ) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id)) + self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args)) } - fn expr_lang_item_path( - &mut self, - span: Span, - lang_item: hir::LangItem, - hir_id: Option, - ) -> hir::Expr<'hir> { - self.expr( - span, - hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)), - ) + fn expr_lang_item_path(&mut self, span: Span, lang_item: hir::LangItem) -> hir::Expr<'hir> { + self.expr(span, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span)))) } /// `::name` @@ -1916,7 +1905,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let path = hir::ExprKind::Path(hir::QPath::TypeRelative( self.arena.alloc(self.ty( span, - hir::TyKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), + hir::TyKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))), )), self.arena.alloc(hir::PathSegment::new( Ident::new(name, span), diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index c7d0719e71abb..8fa2cae43bfdd 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -267,7 +267,7 @@ fn make_count<'hir>( ctx.expr( sp, hir::ExprKind::Err( - ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count"), + ctx.tcx.sess.span_delayed_bug(sp, "lowered bad format_args count"), ), ) } @@ -306,7 +306,7 @@ fn make_format_spec<'hir>( } Err(_) => ctx.expr( sp, - hir::ExprKind::Err(ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count")), + hir::ExprKind::Err(ctx.tcx.sess.span_delayed_bug(sp, "lowered bad format_args count")), ), }; let &FormatOptions { @@ -338,8 +338,8 @@ fn make_format_spec<'hir>( | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4 | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5; let flags = ctx.expr_u32(sp, flags); - let precision = make_count(ctx, sp, &precision, argmap); - let width = make_count(ctx, sp, &width, argmap); + let precision = make_count(ctx, sp, precision, argmap); + let width = make_count(ctx, sp, width, argmap); let format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( sp, hir::LangItem::FormatPlaceholder, diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index eff362f3ff0cd..1741611fb11c5 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::{Span, DUMMY_SP}; /// A visitor that walks over the HIR and collects `Node`s into a HIR map. -pub(super) struct NodeCollector<'a, 'hir> { +struct NodeCollector<'a, 'hir> { tcx: TyCtxt<'hir>, bodies: &'a SortedMap>, @@ -47,7 +47,7 @@ pub(super) fn index_hir<'hir>( match item { OwnerNode::Crate(citem) => { - collector.visit_mod(&citem, citem.spans.inner_span, hir::CRATE_HIR_ID) + collector.visit_mod(citem, citem.spans.inner_span, hir::CRATE_HIR_ID) } OwnerNode::Item(item) => collector.visit_item(item), OwnerNode::TraitItem(item) => collector.visit_trait_item(item), @@ -89,7 +89,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } } - self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node: node }); + self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node }); } fn with_parent(&mut self, parent_node_id: HirId, f: F) { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c73d2382db802..80854c8a6c08b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -3,11 +3,9 @@ use super::ResolverAstLoweringExt; use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{FnDeclKind, LoweringContext, ParamMode}; -use hir::definitions::DefPathData; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; -use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -55,42 +53,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { owner: NodeId, f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, ) { - let allow_gen_future = Some(if self.tcx.features().async_fn_track_caller { - [sym::gen_future, sym::closure_track_caller][..].into() - } else { - [sym::gen_future][..].into() - }); - let mut lctx = LoweringContext { - // Pseudo-globals. - tcx: self.tcx, - resolver: self.resolver, - arena: self.tcx.hir_arena, - - // HirId handling. - bodies: Vec::new(), - attrs: SortedMap::default(), - children: Vec::default(), - current_hir_id_owner: hir::CRATE_OWNER_ID, - item_local_id_counter: hir::ItemLocalId::new(0), - node_id_to_local_id: Default::default(), - trait_map: Default::default(), - - // Lowering state. - catch_scope: None, - loop_scope: None, - is_in_loop_condition: false, - is_in_trait_impl: false, - is_in_dyn_type: false, - coroutine_kind: None, - task_context: None, - current_item: None, - impl_trait_defs: Vec::new(), - impl_trait_bounds: Vec::new(), - allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), - allow_gen_future, - generics_def_id_map: Default::default(), - host_param_id: None, - }; + let mut lctx = LoweringContext::new(self.tcx, self.resolver); lctx.with_hir_id_owner(owner, |lctx| f(lctx)); for (def_id, info) in lctx.children { @@ -136,39 +99,9 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { let def_id = self.resolver.node_id_to_def_id[&item.id]; - let parent_id = self.tcx.local_parent(def_id); let parent_hir = self.lower_node(parent_id).unwrap(); - self.with_lctx(item.id, |lctx| { - // Evaluate with the lifetimes in `params` in-scope. - // This is used to track which lifetimes have already been defined, - // and which need to be replicated when lowering an async fn. - - match parent_hir.node().expect_item().kind { - hir::ItemKind::Impl(impl_) => { - lctx.is_in_trait_impl = impl_.of_trait.is_some(); - } - hir::ItemKind::Trait(_, _, generics, _, _) if lctx.tcx.features().effects => { - lctx.host_param_id = generics - .params - .iter() - .find(|param| { - parent_hir - .attrs - .get(param.hir_id.local_id) - .iter() - .any(|attr| attr.has_name(sym::rustc_host)) - }) - .map(|param| param.def_id); - } - _ => {} - } - - match ctxt { - AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), - AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)), - } - }) + self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir)) } fn lower_foreign_item(&mut self, item: &ForeignItem) { @@ -268,27 +201,24 @@ impl<'hir> LoweringContext<'_, 'hir> { body, .. }) => { - self.with_new_scopes(|this| { - this.current_item = Some(ident.span); - + self.with_new_scopes(ident.span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future` here because lower_body // only cares about the input argument patterns in the function // declaration (decl), not the return types. - let asyncness = header.asyncness; - let body_id = this.lower_maybe_async_body( + let coro_kind = header.coro_kind; + let body_id = this.lower_maybe_coroutine_body( span, hir_id, - &decl, - asyncness, + decl, + coro_kind, body.as_deref(), ); let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, header.constness, id, &itctx, |this| { - let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id) + this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, coro_kind) }); let sig = hir::FnSig { decl, @@ -329,7 +259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { - let guar = this.tcx.sess.delay_span_bug( + let guar = this.tcx.sess.span_delayed_bug( span, "expected to lower type alias type, but it was missing", ); @@ -485,7 +415,9 @@ impl<'hir> LoweringContext<'_, 'hir> { } ItemKind::MacroDef(MacroDef { body, macro_rules }) => { let body = P(self.lower_delim_args(body)); - let macro_kind = self.resolver.decl_macro_kind(self.local_def_id(id)); + let DefKind::Macro(macro_kind) = self.tcx.def_kind(self.local_def_id(id)) else { + unreachable!() + }; let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules }); hir::ItemKind::Macro(macro_def, macro_kind) } @@ -614,6 +546,41 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + fn lower_assoc_item( + &mut self, + item: &AssocItem, + ctxt: AssocCtxt, + parent_hir: &'hir hir::OwnerInfo<'hir>, + ) -> hir::OwnerNode<'hir> { + // Evaluate with the lifetimes in `params` in-scope. + // This is used to track which lifetimes have already been defined, + // and which need to be replicated when lowering an async fn. + + match parent_hir.node().expect_item().kind { + hir::ItemKind::Impl(impl_) => { + self.is_in_trait_impl = impl_.of_trait.is_some(); + } + hir::ItemKind::Trait(_, _, generics, _, _) if self.tcx.features().effects => { + self.host_param_id = generics + .params + .iter() + .find(|param| { + matches!( + param.kind, + hir::GenericParamKind::Const { is_host_effect: true, .. } + ) + }) + .map(|param| param.def_id); + } + _ => {} + } + + match ctxt { + AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)), + AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)), + } + } + fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = self.lower_node_id(i.id); let owner_id = hir_id.expect_owner(); @@ -744,7 +711,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind, has_default) = match &i.kind { AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => { let (generics, kind) = self.lower_generics( - &generics, + generics, Const::No, i.id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -761,27 +728,30 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, kind, expr.is_some()) } AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => { - let asyncness = sig.header.asyncness; let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( generics, sig, i.id, FnDeclKind::Trait, - asyncness.opt_return_id(), + sig.header.coro_kind, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => { - let asyncness = sig.header.asyncness; - let body_id = - self.lower_maybe_async_body(i.span, hir_id, &sig.decl, asyncness, Some(&body)); + let body_id = self.lower_maybe_coroutine_body( + i.span, + hir_id, + &sig.decl, + sig.header.coro_kind, + Some(body), + ); let (generics, sig) = self.lower_method_sig( generics, sig, i.id, FnDeclKind::Trait, - asyncness.opt_return_id(), + sig.header.coro_kind, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) } @@ -857,7 +827,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics( - &generics, + generics, Const::No, i.id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -870,13 +840,11 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ), AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => { - self.current_item = Some(i.span); - let asyncness = sig.header.asyncness; - let body_id = self.lower_maybe_async_body( + let body_id = self.lower_maybe_coroutine_body( i.span, hir_id, &sig.decl, - asyncness, + sig.header.coro_kind, body.as_deref(), ); let (generics, sig) = self.lower_method_sig( @@ -884,7 +852,7 @@ impl<'hir> LoweringContext<'_, 'hir> { sig, i.id, if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, - asyncness.opt_return_id(), + sig.header.coro_kind, ); (generics, hir::ImplItemKind::Fn(sig, body_id)) @@ -899,7 +867,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { - let guar = this.tcx.sess.delay_span_bug( + let guar = this.tcx.sess.span_delayed_bug( i.span, "expected to lower associated type, but it was missing", ); @@ -1032,7 +1000,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> { match block { Some(block) => self.lower_block_expr(block), - None => self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no block")), + None => self.expr_err(span, self.tcx.sess.span_delayed_bug(span, "no block")), } } @@ -1042,23 +1010,29 @@ impl<'hir> LoweringContext<'_, 'hir> { &[], match expr { Some(expr) => this.lower_expr_mut(expr), - None => this.expr_err(span, this.tcx.sess.delay_span_bug(span, "no block")), + None => this.expr_err(span, this.tcx.sess.span_delayed_bug(span, "no block")), }, ) }) } - fn lower_maybe_async_body( + /// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or + /// `gen {}` block as appropriate. + fn lower_maybe_coroutine_body( &mut self, span: Span, fn_id: hir::HirId, decl: &FnDecl, - asyncness: Async, + coro_kind: Option, body: Option<&Block>, ) -> hir::BodyId { - let (closure_id, body) = match (asyncness, body) { - (Async::Yes { closure_id, .. }, Some(body)) => (closure_id, body), - _ => return self.lower_fn_body_block(span, decl, body), + let (Some(coro_kind), Some(body)) = (coro_kind, body) else { + return self.lower_fn_body_block(span, decl, body); + }; + let closure_id = match coro_kind { + CoroutineKind::Async { closure_id, .. } | CoroutineKind::Gen { closure_id, .. } => { + closure_id + } }; self.lower_body(|this| { @@ -1200,44 +1174,54 @@ impl<'hir> LoweringContext<'_, 'hir> { parameters.push(new_parameter); } - let async_expr = this.make_async_expr( - CaptureBy::Value, - closure_id, - None, - body.span, - hir::CoroutineSource::Fn, - |this| { - // Create a block from the user's function body: - let user_body = this.lower_block_expr(body); + let mkbody = |this: &mut LoweringContext<'_, 'hir>| { + // Create a block from the user's function body: + let user_body = this.lower_block_expr(body); - // Transform into `drop-temps { }`, an expression: - let desugared_span = - this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); - let user_body = - this.expr_drop_temps(desugared_span, this.arena.alloc(user_body)); + // Transform into `drop-temps { }`, an expression: + let desugared_span = + this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); + let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body)); - // As noted above, create the final block like - // - // ``` - // { - // let $param_pattern = $raw_param; - // ... - // drop-temps { } - // } - // ``` - let body = this.block_all( - desugared_span, - this.arena.alloc_from_iter(statements), - Some(user_body), - ); + // As noted above, create the final block like + // + // ``` + // { + // let $param_pattern = $raw_param; + // ... + // drop-temps { } + // } + // ``` + let body = this.block_all( + desugared_span, + this.arena.alloc_from_iter(statements), + Some(user_body), + ); - this.expr_block(body) - }, - ); + this.expr_block(body) + }; + let coroutine_expr = match coro_kind { + CoroutineKind::Async { .. } => this.make_async_expr( + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + closure_id, + None, + body.span, + hir::CoroutineSource::Fn, + mkbody, + ), + CoroutineKind::Gen { .. } => this.make_gen_expr( + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + closure_id, + None, + body.span, + hir::CoroutineSource::Fn, + mkbody, + ), + }; let hir_id = this.lower_node_id(closure_id); this.maybe_forward_track_caller(body.span, fn_id, hir_id); - let expr = hir::Expr { hir_id, kind: async_expr, span: this.lower_span(body.span) }; + let expr = hir::Expr { hir_id, kind: coroutine_expr, span: this.lower_span(body.span) }; (this.arena.alloc_from_iter(parameters), expr) }) @@ -1249,21 +1233,26 @@ impl<'hir> LoweringContext<'_, 'hir> { sig: &FnSig, id: NodeId, kind: FnDeclKind, - is_async: Option<(NodeId, Span)>, + coro_kind: Option, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, sig.header.constness, id, &itctx, |this| { - this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async) + this.lower_fn_decl(&sig.decl, id, sig.span, kind, coro_kind) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { + let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coro_kind { + hir::IsAsync::Async(span) + } else { + hir::IsAsync::NotAsync + }; hir::FnHeader { unsafety: self.lower_unsafety(h.unsafety), - asyncness: self.lower_asyncness(h.asyncness), + asyncness: asyncness, constness: self.lower_constness(h.constness), abi: self.lower_extern(h.ext), } @@ -1305,13 +1294,6 @@ impl<'hir> LoweringContext<'_, 'hir> { }); } - fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync { - match a { - Async::Yes { span, .. } => hir::IsAsync::Async(span), - Async::No => hir::IsAsync::NotAsync, - } - } - pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness { match c { Const::Yes(_) => hir::Constness::Const, @@ -1389,26 +1371,17 @@ impl<'hir> LoweringContext<'_, 'hir> { let host_param_parts = if let Const::Yes(span) = constness && self.tcx.features().effects { - if let Some(param) = - generics.params.iter().find(|x| x.attrs.iter().any(|x| x.has_name(sym::rustc_host))) - { - // user has manually specified a `rustc_host` param, in this case, we set - // the param id so that lowering logic can use that. But we don't create - // another host param, so this gives `None`. - self.host_param_id = Some(self.local_def_id(param.id)); - None - } else { - let param_node_id = self.next_node_id(); - let hir_id = self.next_id(); - let def_id = self.create_def( - self.local_def_id(parent_node_id), - param_node_id, - DefPathData::TypeNs(sym::host), - span, - ); - self.host_param_id = Some(def_id); - Some((span, hir_id, def_id)) - } + let param_node_id = self.next_node_id(); + let hir_id = self.next_id(); + let def_id = self.create_def( + self.local_def_id(parent_node_id), + param_node_id, + sym::host, + DefKind::ConstParam, + span, + ); + self.host_param_id = Some(def_id); + Some((span, hir_id, def_id)) } else { None }; @@ -1462,8 +1435,8 @@ impl<'hir> LoweringContext<'_, 'hir> { if let Some((span, hir_id, def_id)) = host_param_parts { let const_node_id = self.next_node_id(); - let anon_const: LocalDefId = - self.create_def(def_id, const_node_id, DefPathData::AnonConst, span); + let anon_const = + self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span); let const_id = self.next_id(); let const_expr_id = self.next_id(); @@ -1472,19 +1445,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id))); - let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(); - - let attrs = self.arena.alloc_from_iter([Attribute { - kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new( - sym::rustc_host, - span, - )))), - span, - id: attr_id, - style: AttrStyle::Outer, - }]); - self.attrs.insert(hir_id.local_id, attrs); - let const_body = self.lower_body(|this| { ( &[], @@ -1526,6 +1486,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: const_id, body: const_body, }), + is_host_effect: true, }, colon_span: None, pure_wrt_drop: false, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a88493acf982f..5dda8f5a6a328 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -30,12 +30,11 @@ //! get confused if the spans from leaf AST nodes occur in multiple places //! in the HIR, especially for multiple identifiers. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![feature(box_patterns)] #![feature(let_chains)] -#![feature(never_type)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -55,14 +54,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{ - DiagnosticArgFromDisplay, DiagnosticMessage, Handler, StashKey, SubdiagnosticMessage, -}; -use rustc_fluent_macro::fluent_messages; +use rustc_errors::{DiagnosticArgFromDisplay, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::{ @@ -70,7 +65,6 @@ use rustc_middle::{ ty::{ResolverAstLowering, TyCtxt}, }; use rustc_session::parse::{add_feature_diagnostics, feature_err}; -use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{DesugaringKind, Span, DUMMY_SP}; use smallvec::SmallVec; @@ -94,7 +88,7 @@ mod lifetime_collector; mod pat; mod path; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, @@ -136,8 +130,8 @@ struct LoweringContext<'a, 'hir> { /// NodeIds that are lowered inside the current HIR owner. node_id_to_local_id: FxHashMap, - allow_try_trait: Option>, - allow_gen_future: Option>, + allow_try_trait: Lrc<[Symbol]>, + allow_gen_future: Lrc<[Symbol]>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic @@ -148,6 +142,46 @@ struct LoweringContext<'a, 'hir> { host_param_id: Option, } +impl<'a, 'hir> LoweringContext<'a, 'hir> { + fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self { + Self { + // Pseudo-globals. + tcx, + resolver: resolver, + arena: tcx.hir_arena, + + // HirId handling. + bodies: Vec::new(), + attrs: SortedMap::default(), + children: Vec::default(), + current_hir_id_owner: hir::CRATE_OWNER_ID, + item_local_id_counter: hir::ItemLocalId::new(0), + node_id_to_local_id: Default::default(), + trait_map: Default::default(), + + // Lowering state. + catch_scope: None, + loop_scope: None, + is_in_loop_condition: false, + is_in_trait_impl: false, + is_in_dyn_type: false, + coroutine_kind: None, + task_context: None, + current_item: None, + impl_trait_defs: Vec::new(), + impl_trait_bounds: Vec::new(), + allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(), + allow_gen_future: if tcx.features().async_fn_track_caller { + [sym::gen_future, sym::closure_track_caller].into() + } else { + [sym::gen_future].into() + }, + generics_def_id_map: Default::default(), + host_param_id: None, + } + } +} + trait ResolverAstLoweringExt { fn legacy_const_generic_args(&self, expr: &Expr) -> Option>; fn get_partial_res(&self, id: NodeId) -> Option; @@ -156,7 +190,6 @@ trait ResolverAstLoweringExt { fn get_lifetime_res(&self, id: NodeId) -> Option; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId); - fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; } impl ResolverAstLoweringExt for ResolverAstLowering { @@ -220,10 +253,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering { let lifetimes = self.extra_lifetime_params_map.remove(&from).unwrap_or_default(); self.extra_lifetime_params_map.insert(to, lifetimes); } - - fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { - self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) - } } /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, @@ -443,11 +472,6 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { drop(ast_index); sess.time("drop_ast", || drop(krate)); - // Discard hygiene data, which isn't required after lowering to HIR. - if !sess.opts.unstable_opts.keep_hygiene_data { - rustc_span::hygiene::clear_syntax_context_map(); - } - // Don't hash unless necessary, because it's expensive. let opt_hir_hash = if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; @@ -474,19 +498,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, parent: LocalDefId, node_id: ast::NodeId, - data: DefPathData, + name: Symbol, + def_kind: DefKind, span: Span, ) -> LocalDefId { debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); assert!( self.opt_local_def_id(node_id).is_none(), - "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", + "adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}", node_id, - data, + def_kind, self.tcx.hir().def_key(self.local_def_id(node_id)), ); - let def_id = self.tcx.at(span).create_def(parent, data).def_id(); + let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id(); debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); self.resolver.node_id_to_def_id.insert(node_id, def_id); @@ -504,7 +529,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name /// resolver (if any). fn orig_opt_local_def_id(&self, node: NodeId) -> Option { - self.resolver.node_id_to_def_id.get(&node).map(|local_def_id| *local_def_id) + self.resolver.node_id_to_def_id.get(&node).copied() } /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name @@ -547,7 +572,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.generics_def_id_map .iter() .rev() - .find_map(|map| map.get(&local_def_id).map(|local_def_id| *local_def_id)) + .find_map(|map| map.get(&local_def_id).copied()) .unwrap_or(local_def_id) } @@ -737,10 +762,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_import_res(id).present_items() } - fn diagnostic(&self) -> &Handler { - self.tcx.sess.diagnostic() - } - /// Reuses the span but adds information like the kind of the desugaring and features that are /// allowed inside this span. fn mark_span_with_reason( @@ -787,7 +808,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let _def_id = self.create_def( self.current_hir_id_owner.def_id, param, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), + kw::UnderscoreLifetime, + DefKind::LifetimeParam, ident.span, ); debug!(?_def_id); @@ -851,7 +873,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { result } - fn with_new_scopes(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + fn with_new_scopes(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T { + let current_item = self.current_item; + self.current_item = Some(scope_span); + let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; @@ -863,6 +888,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.is_in_loop_condition = was_in_loop_condition; + self.current_item = current_item; + ret } @@ -1162,7 +1189,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: &ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { - ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), + ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)), ast::GenericArg::Type(ty) => { match &ty.kind { TyKind::Infer if self.tcx.features().generic_arg_infer => { @@ -1199,7 +1226,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let def_id = self.create_def( parent_def_id.def_id, node_id, - DefPathData::AnonConst, + kw::Empty, + DefKind::AnonConst, span, ); @@ -1211,7 +1239,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }; - let ct = self.with_new_scopes(|this| hir::AnonConst { + let ct = self.with_new_scopes(span, |this| hir::AnonConst { def_id, hir_id: this.lower_node_id(node_id), body: this.lower_const_body(path_expr.span, Some(&path_expr)), @@ -1226,10 +1254,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => {} } - GenericArg::Type(self.lower_ty(&ty, itctx)) + GenericArg::Type(self.lower_ty(ty, itctx)) } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { - value: self.lower_anon_const(&ct), + value: self.lower_anon_const(ct), span: self.lower_span(ct.value.span), is_desugared_from_effects: false, }), @@ -1272,7 +1300,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime_bound = this.elided_dyn_bound(t.span); (bounds, lifetime_bound) }); - let kind = hir::TyKind::TraitObject(bounds, &lifetime_bound, TraitObjectSyntax::None); + let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None); return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() }; } @@ -1293,7 +1321,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => { - hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered")) + hir::TyKind::Err(self.tcx.sess.span_delayed_bug(t.span, "TyKind::Err lowered")) } // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS #[allow(rustc::untranslatable_diagnostic)] @@ -1374,7 +1402,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericBound::Trait( ty, modifier @ (TraitBoundModifier::None - | TraitBoundModifier::MaybeConst + | TraitBoundModifier::MaybeConst(_) | TraitBoundModifier::Negative), ) => { Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness())) @@ -1436,7 +1464,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.create_def( self.current_hir_id_owner.def_id, *def_node_id, - DefPathData::TypeNs(ident.name), + ident.name, + DefKind::TyParam, span, ); let (param, bounds, path) = self.lower_universal_param_and_bounds( @@ -1476,7 +1505,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), TyKind::CVarArgs => { - let guar = self.tcx.sess.delay_span_bug( + let guar = self.tcx.sess.span_delayed_bug( t.span, "`TyKind::CVarArgs` should have been handled elsewhere", ); @@ -1556,7 +1585,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` // example, we only need to duplicate lifetimes that appear in the // bounds, since those are the only ones that are captured by the opaque. - lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds) + lifetime_collector::lifetimes_in_bounds(self.resolver, bounds) } } hir::OpaqueTyOrigin::AsyncFn(..) => { @@ -1589,7 +1618,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_def_id = self.create_def( self.current_hir_id_owner.def_id, opaque_ty_node_id, - DefPathData::ImplTrait, + kw::Empty, + DefKind::OpaqueTy, opaque_ty_span, ); debug!(?opaque_ty_def_id); @@ -1618,7 +1648,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.tcx .sess - .delay_span_bug(lifetime.ident.span, "no def-id for fresh lifetime"); + .span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime"); continue; } } @@ -1643,7 +1673,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let duplicated_lifetime_def_id = self.create_def( opaque_ty_def_id, duplicated_lifetime_node_id, - DefPathData::LifetimeNs(lifetime.ident.name), + lifetime.ident.name, + DefKind::LifetimeParam, lifetime.ident.span, ); captured_to_synthesized_mapping.insert(old_def_id, duplicated_lifetime_def_id); @@ -1747,13 +1778,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })) } - // Lowers a function declaration. - // - // `decl`: the unlowered (AST) function declaration. - // `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given `NodeId`. - // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future` in the - // return type. This is used for `async fn` declarations. The `NodeId` is the ID of the - // return type `impl Trait` item, and the `Span` points to the `async` keyword. + /// Lowers a function declaration. + /// + /// `decl`: the unlowered (AST) function declaration. + /// + /// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given + /// `NodeId`. + /// + /// `transform_return_type`: if `Some`, applies some conversion to the return type, such as is + /// needed for `async fn` and `gen fn`. See [`CoroutineKind`] for more details. #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, @@ -1761,7 +1794,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn_node_id: NodeId, fn_span: Span, kind: FnDeclKind, - make_ret_async: Option<(NodeId, Span)>, + coro: Option, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1790,11 +1823,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_ty_direct(¶m.ty, &itctx) })); - let output = if let Some((ret_id, _span)) = make_ret_async { - let fn_def_id = self.local_def_id(fn_node_id); - self.lower_async_fn_ret_ty(&decl.output, fn_def_id, ret_id, kind, fn_span) - } else { - match &decl.output { + let output = match coro { + Some(coro) => { + let fn_def_id = self.local_def_id(fn_node_id); + self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, coro, kind, fn_span) + } + None => match &decl.output { FnRetTy::Ty(ty) => { let context = if kind.return_impl_trait_allowed() { let fn_def_id = self.local_def_id(fn_node_id); @@ -1818,7 +1852,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::FnRetTy::Return(self.lower_ty(ty, &context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), - } + }, }; self.arena.alloc(hir::FnDecl { @@ -1857,17 +1891,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `fn_node_id`: `NodeId` of the parent function (used to create child impl trait definition) // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created #[instrument(level = "debug", skip(self))] - fn lower_async_fn_ret_ty( + fn lower_coroutine_fn_ret_ty( &mut self, output: &FnRetTy, fn_def_id: LocalDefId, - opaque_ty_node_id: NodeId, + coro: CoroutineKind, fn_kind: FnDeclKind, fn_span: Span, ) -> hir::FnRetTy<'hir> { let span = self.lower_span(fn_span); let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); + let opaque_ty_node_id = match coro { + CoroutineKind::Async { return_impl_trait_id, .. } + | CoroutineKind::Gen { return_impl_trait_id, .. } => return_impl_trait_id, + }; + let captured_lifetimes: Vec<_> = self .resolver .take_extra_lifetime_params(opaque_ty_node_id) @@ -1883,15 +1922,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, opaque_ty_span, |this| { - let future_bound = this.lower_async_fn_output_type_to_future_bound( + let bound = this.lower_coroutine_fn_output_type_to_bound( output, + coro, span, ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), fn_kind, }, ); - arena_vec![this; future_bound] + arena_vec![this; bound] }, ); @@ -1900,9 +1940,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Transforms `-> T` into `Future`. - fn lower_async_fn_output_type_to_future_bound( + fn lower_coroutine_fn_output_type_to_bound( &mut self, output: &FnRetTy, + coro: CoroutineKind, span: Span, nested_impl_trait_context: ImplTraitContext, ) -> hir::GenericBound<'hir> { @@ -1917,17 +1958,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; - // "" + // "<$assoc_ty_name = T>" + let (assoc_ty_name, trait_lang_item) = match coro { + CoroutineKind::Async { .. } => (hir::FN_OUTPUT_NAME, hir::LangItem::Future), + CoroutineKind::Gen { .. } => (hir::ITERATOR_ITEM_NAME, hir::LangItem::Iterator), + }; + let future_args = self.arena.alloc(hir::GenericArgs { args: &[], - bindings: arena_vec![self; self.output_ty_binding(span, output_ty)], + bindings: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, span, output_ty)], parenthesized: hir::GenericArgsParentheses::No, span_ext: DUMMY_SP, }); hir::GenericBound::LangItemTrait( - // ::std::future::Future - hir::LangItem::Future, + trait_lang_item, self.lower_span(span), self.next_id(), future_args, @@ -2072,14 +2117,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ty, kw_span: _, default } => { - let ty = self.lower_ty( - &ty, - &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), - ); + let ty = self + .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), - hir::GenericParamKind::Const { ty, default }, + hir::GenericParamKind::Const { ty, default, is_host_effect: false }, ) } } @@ -2217,7 +2260,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { - self.with_new_scopes(|this| hir::AnonConst { + self.with_new_scopes(c.value.span, |this| hir::AnonConst { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), @@ -2234,7 +2277,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier { match f { TraitBoundModifier::None => hir::TraitBoundModifier::None, - TraitBoundModifier::MaybeConst => hir::TraitBoundModifier::MaybeConst, + TraitBoundModifier::MaybeConst(_) => hir::TraitBoundModifier::MaybeConst, TraitBoundModifier::Negative => { if self.tcx.features().negative_bounds { @@ -2311,21 +2354,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field, None) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field) } fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field, None) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field) } fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field, None) + self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field) } fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> { - self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None) + self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[]) } fn single_pat_field( @@ -2348,9 +2391,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, lang_item: hir::LangItem, fields: &'hir [hir::PatField<'hir>], - hir_id: Option, ) -> &'hir hir::Pat<'hir> { - let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id); + let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span)); self.pat(span, hir::PatKind::Struct(qpath, fields, false)) } @@ -2482,9 +2524,10 @@ impl<'hir> GenericArgsCtor<'hir> { let hir_id = lcx.next_id(); let Some(host_param_id) = lcx.host_param_id else { - lcx.tcx - .sess - .delay_span_bug(span, "no host param id for call in const yet no errors reported"); + lcx.tcx.sess.span_delayed_bug( + span, + "no host param id for call in const yet no errors reported", + ); return; }; @@ -2507,17 +2550,14 @@ impl<'hir> GenericArgsCtor<'hir> { }) }); - let attr_id = lcx.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(); - let attr = lcx.arena.alloc(Attribute { - kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))), + let def_id = lcx.create_def( + lcx.current_hir_id_owner.def_id, + id, + kw::Empty, + DefKind::AnonConst, span, - id: attr_id, - style: AttrStyle::Outer, - }); - lcx.attrs.insert(hir_id.local_id, std::slice::from_ref(attr)); + ); - let def_id = - lcx.create_def(lcx.current_hir_id_owner.def_id, id, DefPathData::AnonConst, span); lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); self.args.push(hir::GenericArg::Const(hir::ConstArg { value: hir::AnonConst { def_id, hir_id, body }, diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index d66bba517e019..4b1c057cdbf1d 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -108,7 +108,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { } } -pub fn lifetimes_in_bounds( +pub(crate) fn lifetimes_in_bounds( resolver: &ResolverAstLowering, bounds: &GenericBounds, ) -> Vec { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index a30f264bc7dc7..017314ee4d14a 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -18,12 +18,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(self.lower_pat_mut(pattern)) } - pub(crate) fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { + fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { ensure_sufficient_stack(|| { // loop here to avoid recursion let node = loop { match &pattern.kind { PatKind::Wild => break hir::PatKind::Wild, + PatKind::Never => break hir::PatKind::Never, PatKind::Ident(binding_mode, ident, sub) => { let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(s)); break self.lower_pat_ident(pattern, *binding_mode, *ident, lower_sub); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 899f92a995821..7ab0805d08667 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -139,7 +139,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // We should've returned in the for loop above. - self.diagnostic().span_bug( + self.tcx.sess.diagnostic().span_bug( p.span, format!( "lower_qpath: no final extension segment in {}..{}", @@ -372,10 +372,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // ``` FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { if self.tcx.features().impl_trait_in_fn_trait_return { - self.lower_ty(&ty, itctx) + self.lower_ty(ty, itctx) } else { self.lower_ty( - &ty, + ty, &ImplTraitContext::FeatureGated( ImplTraitPosition::FnTraitReturn, sym::impl_trait_in_fn_trait_return, @@ -384,12 +384,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } FnRetTy::Ty(ty) => { - self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; - let binding = self.output_ty_binding(output_ty.span, output_ty); + let binding = self.assoc_ty_binding(hir::FN_OUTPUT_NAME, output_ty.span, output_ty); ( GenericArgsCtor { args, @@ -401,13 +401,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) } - /// An associated type binding `Output = $ty`. - pub(crate) fn output_ty_binding( + /// An associated type binding `$assoc_ty_name = $ty`. + pub(crate) fn assoc_ty_binding( &mut self, + assoc_ty_name: rustc_span::Symbol, span: Span, ty: &'hir hir::Ty<'hir>, ) -> hir::TypeBinding<'hir> { - let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME); + let ident = Ident::with_dummy_span(assoc_ty_name); let kind = hir::TypeBindingKind::Equality { term: ty.into() }; let args = arena_vec![self;]; let bindings = arena_vec![self;]; diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 0001394c8d386..99e79f65fb4ab 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -itertools = "0.10.1" +itertools = "0.11" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index d22bae816ef41..876126b02ea95 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -218,9 +218,12 @@ ast_passes_static_without_body = .suggestion = provide a definition for the static ast_passes_tilde_const_disallowed = `~const` is not allowed here - .trait = trait objects cannot have `~const` trait bounds .closure = closures cannot have `~const` trait bounds .function = this function is not `const`, so it cannot have `~const` trait bounds + .trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + .impl = this impl is not `const`, so it cannot have `~const` trait bounds + .object = trait objects cannot have `~const` trait bounds + .item = this item cannot have `~const` trait bounds ast_passes_trait_fn_const = functions in traits cannot be declared const diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 3d0513c89230d..554ed36b814e6 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -40,6 +40,9 @@ enum SelfSemantic { enum DisallowTildeConstContext<'a> { TraitObject, Fn(FnKind<'a>), + Trait(Span), + Impl(Span), + Item, } struct AstValidator<'a> { @@ -110,18 +113,6 @@ impl<'a> AstValidator<'a> { self.disallow_tilde_const = old; } - fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) { - self.with_tilde_const(None, f) - } - - fn with_banned_tilde_const( - &mut self, - ctx: DisallowTildeConstContext<'a>, - f: impl FnOnce(&mut Self), - ) { - self.with_tilde_const(Some(ctx), f) - } - fn check_type_alias_where_clause_location( &mut self, ty_alias: &TyAlias, @@ -173,7 +164,7 @@ impl<'a> AstValidator<'a> { self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)) } TyKind::TraitObject(..) => self - .with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| { + .with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| { visit::walk_ty(this, t) }), TyKind::Path(qself, path) => { @@ -230,7 +221,7 @@ impl<'a> AstValidator<'a> { } fn err_handler(&self) -> &rustc_errors::Handler { - &self.session.diagnostic() + self.session.diagnostic() } fn check_lifetime(&self, ident: Ident) { @@ -631,7 +622,7 @@ impl<'a> AstValidator<'a> { data: data.span, constraint_spans: errors::EmptyLabelManySpans(constraint_spans), arg_spans2: errors::EmptyLabelManySpans(arg_spans), - suggestion: self.correct_generic_order_suggestion(&data), + suggestion: self.correct_generic_order_suggestion(data), constraint_len, args_len, }); @@ -747,7 +738,7 @@ fn validate_generic_param_order( if !bounds.is_empty() { ordered_params += ": "; - ordered_params += &pprust::bounds_to_string(&bounds); + ordered_params += &pprust::bounds_to_string(bounds); } match kind { @@ -845,11 +836,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { this.visit_vis(&item.vis); this.visit_ident(item.ident); - if let Const::Yes(_) = constness { - this.with_tilde_const_allowed(|this| this.visit_generics(generics)); - } else { - this.visit_generics(generics); - } + let disallowed = matches!(constness, Const::No) + .then(|| DisallowTildeConstContext::Impl(item.span)); + this.with_tilde_const(disallowed, |this| this.visit_generics(generics)); this.visit_trait_ref(t); this.visit_ty(self_ty); @@ -863,10 +852,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { polarity, defaultness, constness, - generics: _, + generics, of_trait: None, self_ty, - items: _, + items, }) => { let error = |annotation_span, annotation, only_trait: bool| errors::InherentImplCannot { @@ -898,6 +887,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let &Const::Yes(span) = constness { self.err_handler().emit_err(error(span, "`const`", true)); } + + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + self.with_tilde_const(None, |this| this.visit_generics(generics)); + self.visit_ty(self_ty); + walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl); + walk_list!(self, visit_attribute, &item.attrs); + return; // Avoid visiting again. } ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => { self.check_defaultness(item.span, *defaultness); @@ -978,8 +975,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // context for the supertraits. this.visit_vis(&item.vis); this.visit_ident(item.ident); - this.visit_generics(generics); - this.with_tilde_const_allowed(|this| { + let disallowed = + (!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span)); + this.with_tilde_const(disallowed, |this| { + this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) }); walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); @@ -999,16 +998,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Struct(vdata, generics) => match vdata { - // Duplicating the `Visitor` logic allows catching all cases - // of `Anonymous(Struct, Union)` outside of a field struct or union. - // - // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it - // encounters, and only on `ItemKind::Struct` and `ItemKind::Union` - // it uses `visit_ty_common`, which doesn't contain that specific check. VariantData::Struct(fields, ..) => { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); + // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); walk_list!(self, visit_attribute, &item.attrs); return; @@ -1024,6 +1018,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); + // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); walk_list!(self, visit_attribute, &item.attrs); return; @@ -1208,22 +1203,28 @@ impl<'a> Visitor<'a> for AstValidator<'a> { (BoundKind::TraitObject, TraitBoundModifier::Maybe) => { self.err_handler().emit_err(errors::OptionalTraitObject { span: poly.span }); } - (_, TraitBoundModifier::MaybeConst) + (_, &TraitBoundModifier::MaybeConst(span)) if let Some(reason) = &self.disallow_tilde_const => { let reason = match reason { - DisallowTildeConstContext::TraitObject => { - errors::TildeConstReason::TraitObject - } DisallowTildeConstContext::Fn(FnKind::Closure(..)) => { errors::TildeConstReason::Closure } DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => { errors::TildeConstReason::Function { ident: ident.span } } + &DisallowTildeConstContext::Trait(span) => { + errors::TildeConstReason::Trait { span } + } + &DisallowTildeConstContext::Impl(span) => { + errors::TildeConstReason::Impl { span } + } + DisallowTildeConstContext::TraitObject => { + errors::TildeConstReason::TraitObject + } + DisallowTildeConstContext::Item => errors::TildeConstReason::Item, }; - self.err_handler() - .emit_err(errors::TildeConstDisallowed { span: bound.span(), reason }); + self.err_handler().emit_err(errors::TildeConstDisallowed { span, reason }); } (_, TraitBoundModifier::MaybeConstMaybe) => { self.err_handler().emit_err(errors::OptionalConstExclusive { @@ -1267,13 +1268,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_c_variadic_type(fk); - // Functions cannot both be `const async` + // Functions cannot both be `const async` or `const gen` if let Some(&FnHeader { constness: Const::Yes(cspan), - asyncness: Async::Yes { span: aspan, .. }, + coro_kind: + Some( + CoroutineKind::Async { span: aspan, .. } + | CoroutineKind::Gen { span: aspan, .. }, + ), .. }) = fk.header() { + // FIXME(gen_blocks): Report a different error for `const gen` self.err_handler().emit_err(errors::ConstAndAsync { spans: vec![cspan, aspan], cspan, @@ -1328,7 +1334,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl); let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk)); - self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); } @@ -1397,18 +1402,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } match &item.kind { - AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) - if ctxt == AssocCtxt::Trait => - { - self.visit_vis(&item.vis); - self.visit_ident(item.ident); - walk_list!(self, visit_attribute, &item.attrs); - self.with_tilde_const_allowed(|this| { - this.visit_generics(generics); - walk_list!(this, visit_param_bound, bounds, BoundKind::Bound); - }); - walk_list!(self, visit_ty, ty); - } AssocItemKind::Fn(box Fn { sig, generics, body, .. }) if self.in_const_trait_or_impl || ctxt == AssocCtxt::Trait @@ -1461,9 +1454,7 @@ fn deny_equality_constraints( id: rustc_ast::node_id::DUMMY_NODE_ID, ident: *ident, gen_args, - kind: AssocConstraintKind::Equality { - term: predicate.rhs_ty.clone().into(), - }, + kind: AssocConstraintKind::Equality { term: predicate.rhs_ty.clone().into() }, span: ident.span, }); // Add `` to `Foo`. @@ -1476,11 +1467,7 @@ fn deny_equality_constraints( }, empty_args => { *empty_args = Some( - AngleBracketedArgs { - span: ident.span, - args: thin_vec![arg], - } - .into(), + AngleBracketedArgs { span: ident.span, args: thin_vec![arg] }.into(), ); } } @@ -1552,7 +1539,7 @@ pub fn check_crate( in_const_trait_or_impl: false, has_proc_macro_decls: false, outer_impl_trait: None, - disallow_tilde_const: None, + disallow_tilde_const: Some(DisallowTildeConstContext::Item), is_impl_trait_banned: false, lint_buffer: lints, }; diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index d14b62d6bdc66..7f6fcb493171c 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -551,8 +551,6 @@ pub struct TildeConstDisallowed { #[derive(Subdiagnostic)] pub enum TildeConstReason { - #[note(ast_passes_trait)] - TraitObject, #[note(ast_passes_closure)] Closure, #[note(ast_passes_function)] @@ -560,6 +558,20 @@ pub enum TildeConstReason { #[primary_span] ident: Span, }, + #[note(ast_passes_trait)] + Trait { + #[primary_span] + span: Span, + }, + #[note(ast_passes_impl)] + Impl { + #[primary_span] + span: Span, + }, + #[note(ast_passes_object)] + TraitObject, + #[note(ast_passes_item)] + Item, } #[derive(Diagnostic)] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index e1cf0a2589d3f..897f35a5c4ad9 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -88,7 +88,7 @@ impl<'a> PostExpansionVisitor<'a> { } } - match abi::is_enabled(&self.features, span, symbol_unescaped.as_str()) { + match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) { Ok(()) => (), Err(abi::AbiDisabled::Unstable { feature, explain }) => { feature_err_issue( @@ -102,7 +102,7 @@ impl<'a> PostExpansionVisitor<'a> { } Err(abi::AbiDisabled::Unrecognized) => { if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) { - self.sess.parse_sess.span_diagnostic.delay_span_bug( + self.sess.diagnostic().span_delayed_bug( span, format!( "unrecognized ABI not caught in lowering: {}", @@ -182,7 +182,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { .. }) = attr_info { - gate_alt!(self, has_feature(&self.features), *name, attr.span, *descr); + gate_alt!(self, has_feature(self.features), *name, attr.span, *descr); } // Check unstable flavors of the `#[doc]` attribute. if attr.has_name(sym::doc) { @@ -300,7 +300,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => { - self.check_impl_trait(&ty, false) + self.check_impl_trait(ty, false) } _ => {} @@ -515,7 +515,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { } }; } - gate_all!(c_str_literals, "`c\"..\"` literals are experimental"); gate_all!( if_let_guard, "`if let` guards are experimental", @@ -555,6 +554,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(explicit_tail_calls, "`become` expression is experimental"); gate_all!(generic_const_items, "generic const items are experimental"); gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); + gate_all!(never_patterns, "`!` patterns are experimental"); if !visitor.features.negative_bounds { for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() { @@ -627,7 +627,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate) if all_stable { err.sugg = Some(attr.span); } - sess.parse_sess.span_diagnostic.emit_err(err); + sess.diagnostic().emit_err(err); } } } diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 5147e672f5f37..ba09183374e10 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -4,9 +4,9 @@ //! //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![allow(internal_features)] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_is_partitioned)] @@ -15,13 +15,10 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - pub mod ast_validation; mod errors; pub mod feature_gate; pub mod node_count; pub mod show_span; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index af1524c8baa71..12a08f06558ba 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +itertools = "0.11" rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 475bdb0237866..670f2a4583583 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -1,11 +1,9 @@ -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![feature(associated_type_bounds)] #![feature(box_patterns)] -#![feature(with_negative_coherence)] #![recursion_limit = "256"] mod helpers; diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index 7ab8c3eaba227..96f5eff68901f 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -165,20 +165,20 @@ enum IndentStyle { } #[derive(Clone, Copy, Default, PartialEq)] -pub struct BreakToken { +pub(crate) struct BreakToken { offset: isize, blank_space: isize, pre_break: Option, } #[derive(Clone, Copy, PartialEq)] -pub struct BeginToken { +pub(crate) struct BeginToken { indent: IndentStyle, breaks: Breaks, } -#[derive(Clone, PartialEq)] -pub enum Token { +#[derive(PartialEq)] +pub(crate) enum Token { // In practice a string token contains either a `&'static str` or a // `String`. `Cow` is overkill for this because we never modify the data, // but it's more convenient than rolling our own more specialized type. @@ -229,7 +229,6 @@ pub struct Printer { last_printed: Option, } -#[derive(Clone)] struct BufEntry { token: Token, size: isize, @@ -251,16 +250,16 @@ impl Printer { } } - pub fn last_token(&self) -> Option<&Token> { + pub(crate) fn last_token(&self) -> Option<&Token> { self.last_token_still_buffered().or_else(|| self.last_printed.as_ref()) } - pub fn last_token_still_buffered(&self) -> Option<&Token> { + pub(crate) fn last_token_still_buffered(&self) -> Option<&Token> { self.buf.last().map(|last| &last.token) } /// Be very careful with this! - pub fn replace_last_token_still_buffered(&mut self, token: Token) { + pub(crate) fn replace_last_token_still_buffered(&mut self, token: Token) { self.buf.last_mut().unwrap().token = token; } @@ -314,7 +313,7 @@ impl Printer { } } - pub fn offset(&mut self, offset: isize) { + pub(crate) fn offset(&mut self, offset: isize) { if let Some(BufEntry { token: Token::Break(token), .. }) = &mut self.buf.last_mut() { token.offset += offset; } diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs index 93310dd45c575..c4c4fdce7fef2 100644 --- a/compiler/rustc_ast_pretty/src/pp/convenience.rs +++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs @@ -66,7 +66,7 @@ impl Printer { } } - pub fn hardbreak_tok_offset(off: isize) -> Token { + pub(crate) fn hardbreak_tok_offset(off: isize) -> Token { Token::Break(BreakToken { offset: off, blank_space: SIZE_INFINITY, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e71f421659e2e..1ad28ffbf2bb6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1,4 +1,7 @@ -mod delimited; +//! AST pretty printing. +//! +//! Note that HIR pretty printing is layered on top of this crate. + mod expr; mod item; @@ -23,8 +26,6 @@ use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use std::borrow::Cow; use thin_vec::ThinVec; -pub use self::delimited::IterDelimited; - pub enum MacHeader<'a> { Path(&'a ast::Path), Keyword(&'static str), @@ -46,8 +47,7 @@ pub trait PpAnn { fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {} } -#[derive(Copy, Clone)] -pub struct NoAnn; +struct NoAnn; impl PpAnn for NoAnn {} @@ -64,11 +64,11 @@ impl<'a> Comments<'a> { } // FIXME: This shouldn't probably clone lmao - pub fn next(&self) -> Option { + fn next(&self) -> Option { self.comments.get(self.current).cloned() } - pub fn trailing_comment( + fn trailing_comment( &self, span: rustc_span::Span, next_pos: Option, @@ -95,7 +95,7 @@ pub struct State<'a> { ann: &'a (dyn PpAnn + 'a), } -pub(crate) const INDENT_UNIT: isize = 4; +const INDENT_UNIT: isize = 4; /// Requires you to pass an input filename and reader so that /// it can scan the input text for comments to copy forward. @@ -146,37 +146,49 @@ pub fn print_crate<'a>( s.s.eof() } -/// This makes printed token streams look slightly nicer, -/// and also addresses some specific regressions described in #63896 and #73345. -fn space_between(prev: &TokenTree, curr: &TokenTree) -> bool { - if let TokenTree::Token(token, _) = prev { - // No space after these tokens, e.g. `x.y`, `$e` - // (The carets point to `prev`.) ^ ^ - if matches!(token.kind, token::Dot | token::Dollar) { - return false; - } - if let token::DocComment(comment_kind, ..) = token.kind { - return comment_kind != CommentKind::Line; - } - } - match curr { - // No space before these tokens, e.g. `foo,`, `println!`, `x.y` - // (The carets point to `curr`.) ^ ^ ^ +/// Should two consecutive tokens be printed with a space between them? +/// +/// Note: some old proc macros parse pretty-printed output, so changes here can +/// break old code. For example: +/// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,` +/// - #73345: `#[allow(unused)]` must be printed rather than `# [allow(unused)]` +/// +fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { + use token::*; + use Delimiter::*; + use TokenTree::Delimited as Del; + use TokenTree::Token as Tok; + + // Each match arm has one or more examples in comments. The default is to + // insert space between adjacent tokens, except for the cases listed in + // this match. + match (tt1, tt2) { + // No space after line doc comments. + (Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false, + + // `.` + ANYTHING: `x.y`, `tup.0` + // `$` + ANYTHING: `$e` + (Tok(Token { kind: Dot | Dollar, .. }, _), _) => false, + + // ANYTHING + `,`: `foo,` + // ANYTHING + `.`: `x.y`, `tup.0` + // ANYTHING + `!`: `foo! { ... }` // - // FIXME: having `Not` here works well for macro invocations like - // `println!()`, but is bad when `!` means "logical not" or "the never - // type", where the lack of space causes ugliness like this: - // `Fn() ->!`, `x =! y`, `if! x { f(); }`. - TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot), - // No space before parentheses if preceded by these tokens, e.g. `foo(...)` - TokenTree::Delimited(_, Delimiter::Parenthesis, _) => { - !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _)) - } - // No space before brackets if preceded by these tokens, e.g. `#[...]` - TokenTree::Delimited(_, Delimiter::Bracket, _) => { - !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _)) - } - TokenTree::Delimited(..) => true, + // FIXME: Incorrect cases: + // - Logical not: `x =! y`, `if! x { f(); }` + // - Never type: `Fn() ->!` + (_, Tok(Token { kind: Comma | Dot | Not, .. }, _)) => false, + + // IDENT + `(`: `f(3)` + // + // FIXME: Incorrect cases: + // - Let: `let(a, b) = (1, 2)` + (Tok(Token { kind: Ident(..), .. }, _), Del(_, Parenthesis, _)) => false, + + // `#` + `[`: `#[attr]` + (Tok(Token { kind: Pound, .. }, _), Del(_, Bracket, _)) => false, + + _ => true, } } @@ -208,7 +220,7 @@ fn doc_comment_to_string( } } -pub fn literal_to_string(lit: token::Lit) -> String { +fn literal_to_string(lit: token::Lit) -> String { let token::Lit { kind, symbol, suffix } = lit; let mut out = match kind { token::Byte => format!("b'{symbol}'"), @@ -248,11 +260,17 @@ impl std::ops::DerefMut for State<'_> { } } +/// This trait is used for both AST and HIR pretty-printing. pub trait PrintState<'a>: std::ops::Deref + std::ops::DerefMut { fn comments(&mut self) -> &mut Option>; - fn print_ident(&mut self, ident: Ident); + fn ann_post(&mut self, ident: Ident); fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool); + fn print_ident(&mut self, ident: Ident) { + self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); + self.ann_post(ident) + } + fn strsep( &mut self, sep: &'static str, @@ -389,15 +407,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } } - fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) { - self.print_token_literal(lit.as_token_lit(), lit.span) - } - - fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) { - self.maybe_print_comment(span.lo()); - self.word(token_lit.to_string()) - } - fn print_string(&mut self, st: &str, style: ast::StrStyle) { let st = match style { ast::StrStyle::Cooked => format!("\"{}\"", st.escape_debug()), @@ -408,30 +417,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.word(st) } - fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) { - self.print_string(sym.as_str(), style); - } - fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true) } - fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool { - self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) - } - fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true) } - fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { - self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true) - } - - fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { - self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) - } - fn print_either_attributes( &mut self, attrs: &[ast::Attribute], @@ -455,10 +448,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere printed } - fn print_attribute(&mut self, attr: &ast::Attribute) { - self.print_attribute_inline(attr, false) - } - fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) { if !is_inline { self.hardbreak_if_not_bol(); @@ -513,33 +502,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.end(); } - fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) { - match item { - ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi), - ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit), - } - } - - fn print_meta_item(&mut self, item: &ast::MetaItem) { - self.ibox(INDENT_UNIT); - match &item.kind { - ast::MetaItemKind::Word => self.print_path(&item.path, false, 0), - ast::MetaItemKind::NameValue(value) => { - self.print_path(&item.path, false, 0); - self.space(); - self.word_space("="); - self.print_meta_item_lit(value); - } - ast::MetaItemKind::List(items) => { - self.print_path(&item.path, false, 0); - self.popen(); - self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i)); - self.pclose(); - } - } - self.end(); - } - /// This doesn't deserve to be called "pretty" printing, but it should be /// meaning-preserving. A quick hack that might help would be to look at the /// spans embedded in the TTs to decide where to put spaces and newlines. @@ -813,7 +775,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } token::Eof => "".into(), - token::Interpolated(ref nt) => self.nonterminal_to_string(nt).into(), + token::Interpolated(ref nt) => self.nonterminal_to_string(&nt.0).into(), } } @@ -831,17 +793,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere Self::to_string(|s| s.print_type(ty)) } - fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String { - Self::to_string(|s| s.print_type_bounds(bounds)) - } - - fn where_bound_predicate_to_string( - &self, - where_bound_predicate: &ast::WhereBoundPredicate, - ) -> String { - Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate)) - } - fn pat_to_string(&self, pat: &ast::Pat) -> String { Self::to_string(|s| s.print_pat(pat)) } @@ -854,14 +805,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere Self::to_string(|s| s.print_meta_item_lit(lit)) } - fn tt_to_string(&self, tt: &TokenTree) -> String { - Self::to_string(|s| s.print_tt(tt, false)) - } - - fn tts_to_string(&self, tokens: &TokenStream) -> String { - Self::to_string(|s| s.print_tts(tokens, false)) - } - fn stmt_to_string(&self, stmt: &ast::Stmt) -> String { Self::to_string(|s| s.print_stmt(stmt)) } @@ -870,26 +813,10 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere Self::to_string(|s| s.print_item(i)) } - fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String { - Self::to_string(|s| s.print_assoc_item(i)) - } - - fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String { - Self::to_string(|s| s.print_foreign_item(i)) - } - - fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String { - Self::to_string(|s| s.print_generic_params(generic_params)) - } - fn path_to_string(&self, p: &ast::Path) -> String { Self::to_string(|s| s.print_path(p, false, 0)) } - fn path_segment_to_string(&self, p: &ast::PathSegment) -> String { - Self::to_string(|s| s.print_path_segment(p, false)) - } - fn vis_to_string(&self, v: &ast::Visibility) -> String { Self::to_string(|s| s.print_visibility(v)) } @@ -904,22 +831,10 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere }) } - fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String { - Self::to_string(|s| s.print_meta_list_item(li)) - } - fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String { Self::to_string(|s| s.print_attr_item(ai, ai.path.span)) } - fn attribute_to_string(&self, attr: &ast::Attribute) -> String { - Self::to_string(|s| s.print_attribute(attr)) - } - - fn param_to_string(&self, arg: &ast::Param) -> String { - Self::to_string(|s| s.print_param(arg, false)) - } - fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { let mut printer = State::new(); f(&mut printer); @@ -932,9 +847,8 @@ impl<'a> PrintState<'a> for State<'a> { &mut self.comments } - fn print_ident(&mut self, ident: Ident) { - self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); - self.ann.post(self, AnnNode::Ident(&ident)) + fn ann_post(&mut self, ident: Ident) { + self.ann.post(self, AnnNode::Ident(&ident)); } fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) { @@ -967,13 +881,8 @@ impl<'a> State<'a> { State { s: pp::Printer::new(), comments: None, ann: &NoAnn } } - pub(crate) fn commasep_cmnt( - &mut self, - b: Breaks, - elts: &[T], - mut op: F, - mut get_span: G, - ) where + fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G) + where F: FnMut(&mut State<'_>, &T), G: FnMut(&T) -> rustc_span::Span, { @@ -993,7 +902,7 @@ impl<'a> State<'a> { self.end(); } - pub(crate) fn commasep_exprs(&mut self, b: Breaks, exprs: &[P]) { + fn commasep_exprs(&mut self, b: Breaks, exprs: &[P]) { self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span) } @@ -1066,11 +975,11 @@ impl<'a> State<'a> { } ast::TyKind::AnonStruct(fields) => { self.head("struct"); - self.print_record_struct_body(&fields, ty.span); + self.print_record_struct_body(fields, ty.span); } ast::TyKind::AnonUnion(fields) => { self.head("union"); - self.print_record_struct_body(&fields, ty.span); + self.print_record_struct_body(fields, ty.span); } ast::TyKind::Paren(typ) => { self.popen(); @@ -1144,7 +1053,7 @@ impl<'a> State<'a> { self.print_trait_ref(&t.trait_ref) } - pub(crate) fn print_stmt(&mut self, st: &ast::Stmt) { + fn print_stmt(&mut self, st: &ast::Stmt) { self.maybe_print_comment(st.span.lo()); match &st.kind { ast::StmtKind::Local(loc) => { @@ -1199,19 +1108,19 @@ impl<'a> State<'a> { self.maybe_print_trailing_comment(st.span, None) } - pub(crate) fn print_block(&mut self, blk: &ast::Block) { + fn print_block(&mut self, blk: &ast::Block) { self.print_block_with_attrs(blk, &[]) } - pub(crate) fn print_block_unclosed_indent(&mut self, blk: &ast::Block) { + fn print_block_unclosed_indent(&mut self, blk: &ast::Block) { self.print_block_maybe_unclosed(blk, &[], false) } - pub(crate) fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) { + fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) { self.print_block_maybe_unclosed(blk, attrs, true) } - pub(crate) fn print_block_maybe_unclosed( + fn print_block_maybe_unclosed( &mut self, blk: &ast::Block, attrs: &[ast::Attribute], @@ -1245,7 +1154,7 @@ impl<'a> State<'a> { } /// Print a `let pat = expr` expression. - pub(crate) fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) { + fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) { self.word("let "); self.print_pat(pat); self.space(); @@ -1254,7 +1163,7 @@ impl<'a> State<'a> { self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) } - pub(crate) fn print_mac(&mut self, m: &ast::MacCall) { + fn print_mac(&mut self, m: &ast::MacCall) { self.print_mac_common( Some(MacHeader::Path(&m.path)), true, @@ -1395,7 +1304,7 @@ impl<'a> State<'a> { self.pclose(); } - pub(crate) fn print_local_decl(&mut self, loc: &ast::Local) { + fn print_local_decl(&mut self, loc: &ast::Local) { self.print_pat(&loc.pat); if let Some(ty) = &loc.ty { self.word_space(":"); @@ -1403,7 +1312,7 @@ impl<'a> State<'a> { } } - pub(crate) fn print_name(&mut self, name: Symbol) { + fn print_name(&mut self, name: Symbol) { self.word(name.to_string()); self.ann.post(self, AnnNode::Name(&name)) } @@ -1427,13 +1336,14 @@ impl<'a> State<'a> { } } - pub(crate) fn print_pat(&mut self, pat: &ast::Pat) { + fn print_pat(&mut self, pat: &ast::Pat) { self.maybe_print_comment(pat.span.lo()); self.ann.pre(self, AnnNode::Pat(pat)); /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match &pat.kind { PatKind::Wild => self.word("_"), + PatKind::Never => self.word("!"), PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, sub) => { if *by_ref == ByRef::Yes { self.word_nbsp("ref"); @@ -1580,9 +1490,14 @@ impl<'a> State<'a> { } } - pub(crate) fn print_asyncness(&mut self, asyncness: ast::Async) { - if asyncness.is_async() { - self.word_nbsp("async"); + fn print_coro_kind(&mut self, coro_kind: ast::CoroutineKind) { + match coro_kind { + ast::CoroutineKind::Gen { .. } => { + self.word_nbsp("gen"); + } + ast::CoroutineKind::Async { .. } => { + self.word_nbsp("async"); + } } } @@ -1606,7 +1521,7 @@ impl<'a> State<'a> { TraitBoundModifier::Maybe => { self.word("?"); } - TraitBoundModifier::MaybeConst => { + TraitBoundModifier::MaybeConst(_) => { self.word_space("~const"); } TraitBoundModifier::MaybeConstNegative => { @@ -1625,11 +1540,11 @@ impl<'a> State<'a> { } } - pub(crate) fn print_lifetime(&mut self, lifetime: ast::Lifetime) { + fn print_lifetime(&mut self, lifetime: ast::Lifetime) { self.print_name(lifetime.ident.name) } - pub(crate) fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) { + fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) { for (i, bound) in bounds.iter().enumerate() { if i != 0 { self.word(" + "); @@ -1641,7 +1556,7 @@ impl<'a> State<'a> { } } - pub(crate) fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) { + fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) { if generic_params.is_empty() { return; } @@ -1705,12 +1620,12 @@ impl<'a> State<'a> { } } - pub(crate) fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) { + fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) { self.print_mutability(mt.mutbl, print_const); self.print_type(&mt.ty) } - pub(crate) fn print_param(&mut self, input: &ast::Param, is_closure: bool) { + fn print_param(&mut self, input: &ast::Param, is_closure: bool) { self.ibox(INDENT_UNIT); self.print_outer_attributes_inline(&input.attrs); @@ -1738,7 +1653,7 @@ impl<'a> State<'a> { self.end(); } - pub(crate) fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) { + fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) { if let ast::FnRetTy::Ty(ty) = fn_ret_ty { self.space_if_not_bol(); self.ibox(INDENT_UNIT); @@ -1749,7 +1664,7 @@ impl<'a> State<'a> { } } - pub(crate) fn print_ty_fn( + fn print_ty_fn( &mut self, ext: ast::Extern, unsafety: ast::Unsafe, @@ -1773,9 +1688,9 @@ impl<'a> State<'a> { self.end(); } - pub(crate) fn print_fn_header_info(&mut self, header: ast::FnHeader) { + fn print_fn_header_info(&mut self, header: ast::FnHeader) { self.print_constness(header.constness); - self.print_asyncness(header.asyncness); + header.coro_kind.map(|coro_kind| self.print_coro_kind(coro_kind)); self.print_unsafety(header.unsafety); match header.ext { @@ -1793,24 +1708,107 @@ impl<'a> State<'a> { self.word("fn") } - pub(crate) fn print_unsafety(&mut self, s: ast::Unsafe) { + fn print_unsafety(&mut self, s: ast::Unsafe) { match s { ast::Unsafe::No => {} ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"), } } - pub(crate) fn print_constness(&mut self, s: ast::Const) { + fn print_constness(&mut self, s: ast::Const) { match s { ast::Const::No => {} ast::Const::Yes(_) => self.word_nbsp("const"), } } - pub(crate) fn print_is_auto(&mut self, s: ast::IsAuto) { + fn print_is_auto(&mut self, s: ast::IsAuto) { match s { ast::IsAuto::Yes => self.word_nbsp("auto"), ast::IsAuto::No => {} } } + + fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) { + self.print_token_literal(lit.as_token_lit(), lit.span) + } + + fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) { + self.maybe_print_comment(span.lo()); + self.word(token_lit.to_string()) + } + + fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) { + self.print_string(sym.as_str(), style); + } + + fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool { + self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) + } + + fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { + self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) + } + + fn print_attribute(&mut self, attr: &ast::Attribute) { + self.print_attribute_inline(attr, false) + } + + fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) { + match item { + ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi), + ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit), + } + } + + fn print_meta_item(&mut self, item: &ast::MetaItem) { + self.ibox(INDENT_UNIT); + match &item.kind { + ast::MetaItemKind::Word => self.print_path(&item.path, false, 0), + ast::MetaItemKind::NameValue(value) => { + self.print_path(&item.path, false, 0); + self.space(); + self.word_space("="); + self.print_meta_item_lit(value); + } + ast::MetaItemKind::List(items) => { + self.print_path(&item.path, false, 0); + self.popen(); + self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i)); + self.pclose(); + } + } + self.end(); + } + + pub(crate) fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String { + Self::to_string(|s| s.print_type_bounds(bounds)) + } + + pub(crate) fn where_bound_predicate_to_string( + &self, + where_bound_predicate: &ast::WhereBoundPredicate, + ) -> String { + Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate)) + } + + pub(crate) fn tt_to_string(&self, tt: &TokenTree) -> String { + Self::to_string(|s| s.print_tt(tt, false)) + } + + pub(crate) fn tts_to_string(&self, tokens: &TokenStream) -> String { + Self::to_string(|s| s.print_tts(tokens, false)) + } + + pub(crate) fn path_segment_to_string(&self, p: &ast::PathSegment) -> String { + Self::to_string(|s| s.print_path_segment(p, false)) + } + + pub(crate) fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String { + Self::to_string(|s| s.print_meta_list_item(li)) + } + + pub(crate) fn attribute_to_string(&self, attr: &ast::Attribute) -> String { + Self::to_string(|s| s.print_attribute(attr)) + } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs b/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs deleted file mode 100644 index fe0640baaa1b0..0000000000000 --- a/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::iter::Peekable; -use std::mem; -use std::ops::Deref; - -pub struct Delimited { - is_first: bool, - iter: Peekable, -} - -pub trait IterDelimited: Iterator + Sized { - fn delimited(self) -> Delimited { - Delimited { is_first: true, iter: self.peekable() } - } -} - -impl IterDelimited for I {} - -pub struct IteratorItem { - value: T, - pub is_first: bool, - pub is_last: bool, -} - -impl Iterator for Delimited { - type Item = IteratorItem; - - fn next(&mut self) -> Option { - let value = self.iter.next()?; - let is_first = mem::replace(&mut self.is_first, false); - let is_last = self.iter.peek().is_none(); - Some(IteratorItem { value, is_first, is_last }) - } -} - -impl Deref for IteratorItem { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.value - } -} diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index e84af12d3f9c7..0e6c3628aacb6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -1,6 +1,6 @@ use crate::pp::Breaks::Inconsistent; -use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT}; - +use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; +use itertools::{Itertools, Position}; use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::util::literal::escape_byte_str_symbol; @@ -149,10 +149,12 @@ impl<'a> State<'a> { return; } self.cbox(0); - for field in fields.iter().delimited() { + for (pos, field) in fields.iter().with_position() { + let is_first = matches!(pos, Position::First | Position::Only); + let is_last = matches!(pos, Position::Last | Position::Only); self.maybe_print_comment(field.span.hi()); self.print_outer_attributes(&field.attrs); - if field.is_first { + if is_first { self.space_if_not_bol(); } if !field.is_shorthand { @@ -160,7 +162,7 @@ impl<'a> State<'a> { self.word_nbsp(":"); } self.print_expr(&field.expr); - if !field.is_last || has_rest { + if !is_last || has_rest { self.word_space(","); } else { self.trailing_comma_or_space(); @@ -253,12 +255,12 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(lhs, left_prec); self.space(); - self.word_space(op.node.to_string()); + self.word_space(op.node.as_str()); self.print_expr_maybe_paren(rhs, right_prec) } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) { - self.word(ast::UnOp::to_string(op)); + self.word(op.as_str()); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } @@ -279,7 +281,7 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } - pub fn print_expr(&mut self, expr: &ast::Expr) { + pub(super) fn print_expr(&mut self, expr: &ast::Expr) { self.print_expr_outer_attr_style(expr, true) } @@ -411,7 +413,7 @@ impl<'a> State<'a> { binder, capture_clause, constness, - asyncness, + coro_kind, movability, fn_decl, body, @@ -421,7 +423,7 @@ impl<'a> State<'a> { self.print_closure_binder(binder); self.print_constness(*constness); self.print_movability(*movability); - self.print_asyncness(*asyncness); + coro_kind.map(|coro_kind| self.print_coro_kind(coro_kind)); self.print_capture_clause(*capture_clause); self.print_fn_params_and_ret(fn_decl, true); @@ -468,7 +470,7 @@ impl<'a> State<'a> { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1); self.space(); - self.word(op.node.to_string()); + self.word(op.node.as_str()); self.word_space("="); self.print_expr_maybe_paren(rhs, prec); } @@ -629,28 +631,33 @@ impl<'a> State<'a> { self.print_expr(e); self.space(); } - self.word_space("=>"); - match &arm.body.kind { - ast::ExprKind::Block(blk, opt_label) => { - if let Some(label) = opt_label { - self.print_ident(label.ident); - self.word_space(":"); - } + if let Some(body) = &arm.body { + self.word_space("=>"); + + match &body.kind { + ast::ExprKind::Block(blk, opt_label) => { + if let Some(label) = opt_label { + self.print_ident(label.ident); + self.word_space(":"); + } - // The block will close the pattern's ibox. - self.print_block_unclosed_indent(blk); + // The block will close the pattern's ibox. + self.print_block_unclosed_indent(blk); - // If it is a user-provided unsafe block, print a comma after it. - if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { + // If it is a user-provided unsafe block, print a comma after it. + if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { + self.word(","); + } + } + _ => { + self.end(); // Close the ibox for the pattern. + self.print_expr(body); self.word(","); } } - _ => { - self.end(); // Close the ibox for the pattern. - self.print_expr(&arm.body); - self.word(","); - } + } else { + self.word(","); } self.end(); // Close enclosing cbox. } @@ -673,13 +680,13 @@ impl<'a> State<'a> { fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) { match capture_clause { - ast::CaptureBy::Value => self.word_space("move"), + ast::CaptureBy::Value { .. } => self.word_space("move"), ast::CaptureBy::Ref => {} } } } -pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String { +fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String { let mut template = "\"".to_string(); for piece in pieces { match piece { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 3393f034bc3b5..fd5b529b1d4de 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -1,8 +1,8 @@ use crate::pp::Breaks::Inconsistent; -use crate::pprust::state::delimited::IterDelimited; use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; use ast::StaticItem; +use itertools::{Itertools, Position}; use rustc_ast as ast; use rustc_ast::GenericBound; use rustc_ast::ModKind; @@ -20,7 +20,7 @@ impl<'a> State<'a> { } } - pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) { + fn print_foreign_item(&mut self, item: &ast::ForeignItem) { let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); @@ -368,7 +368,7 @@ impl<'a> State<'a> { self.nbsp(); if !bounds.is_empty() { self.word_nbsp("="); - self.print_type_bounds(&bounds); + self.print_type_bounds(bounds); } self.print_where_clause(&generics.where_clause); self.word(";"); @@ -518,7 +518,7 @@ impl<'a> State<'a> { } } - pub(crate) fn print_assoc_item(&mut self, item: &ast::AssocItem) { + fn print_assoc_item(&mut self, item: &ast::AssocItem) { let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); @@ -621,7 +621,7 @@ impl<'a> State<'a> { self.print_where_clause_parts(where_clause.has_where_token, &where_clause.predicates); } - pub(crate) fn print_where_clause_parts( + fn print_where_clause_parts( &mut self, has_where_token: bool, predicates: &[ast::WherePredicate], @@ -668,7 +668,7 @@ impl<'a> State<'a> { } } - pub fn print_where_bound_predicate( + pub(crate) fn print_where_bound_predicate( &mut self, where_bound_predicate: &ast::WhereBoundPredicate, ) { @@ -712,9 +712,10 @@ impl<'a> State<'a> { self.word("{"); self.zerobreak(); self.ibox(0); - for use_tree in items.iter().delimited() { + for (pos, use_tree) in items.iter().with_position() { + let is_last = matches!(pos, Position::Last | Position::Only); self.print_use_tree(&use_tree.0); - if !use_tree.is_last { + if !is_last { self.word(","); if let ast::UseTreeKind::Nested(_) = use_tree.0.kind { self.hardbreak(); diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index ad92d58551006..a6930fe0a17c7 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -552,7 +552,7 @@ pub fn cfg_matches( fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) { let gate = find_gated_cfg(|sym| sym == name); if let (Some(feats), Some(gated_cfg)) = (features, gate) { - gate_cfg(&gated_cfg, span, sess, feats); + gate_cfg(gated_cfg, span, sess, feats); } } @@ -945,7 +945,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}"); use ReprAttr::*; let mut acc = Vec::new(); - let diagnostic = &sess.parse_sess.span_diagnostic; + let diagnostic = sess.diagnostic(); if let Some(items) = attr.meta_item_list() { for item in items { @@ -985,7 +985,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { Ok(literal) => acc.push(ReprPacked(literal)), Err(message) => literal_error = Some(message), }; - } else if matches!(name, sym::C | sym::simd | sym::transparent) + } else if matches!(name, sym::Rust | sym::C | sym::simd | sym::transparent) || int_type_of_word(name).is_some() { recognised = true; @@ -1018,7 +1018,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { }); } else if matches!( meta_item.name_or_empty(), - sym::C | sym::simd | sym::transparent + sym::Rust | sym::C | sym::simd | sym::transparent ) || int_type_of_word(meta_item.name_or_empty()).is_some() { recognised = true; @@ -1043,7 +1043,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { ); } else if matches!( meta_item.name_or_empty(), - sym::C | sym::simd | sym::transparent + sym::Rust | sym::C | sym::simd | sym::transparent ) || int_type_of_word(meta_item.name_or_empty()).is_some() { recognised = true; @@ -1060,9 +1060,9 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { // Not a word we recognize. This will be caught and reported by // the `check_mod_attrs` pass, but this pass doesn't always run // (e.g. if we only pretty-print the source), so we have to gate - // the `delay_span_bug` call as follows: + // the `span_delayed_bug` call as follows: if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) { - diagnostic.delay_span_bug(item.span(), "unrecognized representation hint"); + diagnostic.span_delayed_bug(item.span(), "unrecognized representation hint"); } } } diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 868c041225581..3c5bcecddeaa4 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -4,9 +4,9 @@ //! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax` //! to this crate. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![feature(let_chains)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -14,9 +14,6 @@ #[macro_use] extern crate rustc_macros; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - mod builtin; mod session_diagnostics; @@ -29,4 +26,4 @@ pub use rustc_ast::attr::*; pub(crate) use rustc_session::HashStableContext; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml index fb54937a098f7..48af4e6f600be 100644 --- a/compiler/rustc_baked_icu_data/Cargo.toml +++ b/compiler/rustc_baked_icu_data/Cargo.toml @@ -7,9 +7,10 @@ edition = "2021" # tidy-alphabetical-start icu_list = "1.2" icu_locid = "1.2" +icu_locid_transform = "1.3.2" icu_provider = "1.2" icu_provider_adapters = "1.2" -zerovec = "0.9.4" +zerovec = "0.10.0" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs deleted file mode 100644 index 57f7496dcff8b..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated -type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: LocaleFallbackLikelySubtagsV1Marker as :: icu_provider :: DataMarker > :: Yokeable ; -pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> { - locale.is_empty().then(|| &UND) -} -static UND: DataStruct = include!("und.rs.data"); diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data deleted file mode 100644 index e4aaf50f5d674..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data +++ /dev/null @@ -1,66 +0,0 @@ -::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1 { - l2s: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap::from_parts_unchecked( - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") - }, - ) - }, - lr2s: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap2d::from_parts_unchecked( - unsafe { - ::zerovec::ZeroVec::from_bytes_unchecked( - b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0", - ) - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") - }, - ) - }, - l2r: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap::from_parts_unchecked( - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") - }, - ) - }, - ls2r: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap2d::from_parts_unchecked( - unsafe { - ::zerovec::ZeroVec::from_bytes_unchecked( - b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0", - ) - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") - }, - unsafe { - ::zerovec::ZeroVec::from_bytes_unchecked( - b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant", - ) - }, - unsafe { - ::zerovec::ZeroVec::from_bytes_unchecked( - b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0", - ) - }, - ) - }, -} diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/mod.rs deleted file mode 100644 index a485a5af64ca5..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -// @generated -pub mod likelysubtags_v1; -pub mod parents_v1; -pub mod supplement; diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs deleted file mode 100644 index ce04af868aa54..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated -type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: LocaleFallbackParentsV1Marker as :: icu_provider :: DataMarker > :: Yokeable ; -pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> { - locale.is_empty().then(|| &UND) -} -static UND: DataStruct = include!("und.rs.data"); diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data deleted file mode 100644 index a13646a0b925e..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data +++ /dev/null @@ -1,13 +0,0 @@ -::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1 { - parents: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap::from_parts_unchecked( - unsafe { - :: zerovec :: VarZeroVec :: from_bytes_unchecked (b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") - }, - unsafe { - :: zerovec :: ZeroVec :: from_bytes_unchecked (b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") - }, - ) - }, -} diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs deleted file mode 100644 index 9023647138b1b..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// @generated -type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: CollationFallbackSupplementV1Marker as :: icu_provider :: DataMarker > :: Yokeable ; -pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> { - locale.is_empty().then(|| &UND) -} -static UND: DataStruct = include!("und.rs.data"); diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data deleted file mode 100644 index 647f8f5160191..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data +++ /dev/null @@ -1,22 +0,0 @@ -::icu_provider_adapters::fallback::provider::LocaleFallbackSupplementV1 { - parents: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap::from_parts_unchecked( - unsafe { ::zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, - unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") }, - ) - }, - unicode_extension_defaults: unsafe { - #[allow(unused_unsafe)] - ::zerovec::ZeroMap2d::from_parts_unchecked( - unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(b"co") }, - unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, - unsafe { - ::zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") - }, - unsafe { - ::zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") - }, - ) - }, -} diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/mod.rs deleted file mode 100644 index 62957134f0755..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -// @generated -pub mod co_v1; diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data deleted file mode 100644 index 4bf244019ff19..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", & ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" & ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data deleted file mode 100644 index 84de7cd01a7e0..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data +++ /dev/null @@ -1,116 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), - special_case: Some(::icu_list::provider::SpecialCasePattern { - condition: unsafe { - ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( - if cfg!(target_endian = "little") { - b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" - } else { - b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" - }, - ) - }, - pattern: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - }), - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data deleted file mode 100644 index 79a97e50f5a86..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data deleted file mode 100644 index b976b6cb65aaf..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data deleted file mode 100644 index d76d567ebf875..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs deleted file mode 100644 index e20941f0c6767..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// @generated -type DataStruct = <::icu_list::provider::AndListV1Marker as ::icu_provider::DataMarker>::Yokeable; -pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> { - static KEYS: [&str; 12usize] = - ["en", "es", "fr", "it", "ja", "pt", "ru", "tr", "und", "zh", "zh-Hans", "zh-Hant"]; - static DATA: [&DataStruct; 12usize] = - [&EN, &ES, &FR, &IT, &JA, &PT, &RU, &TR, &UND, &ZH, &ZH, &ZH_HANT]; - KEYS.binary_search_by(|k| locale.strict_cmp(k.as_bytes()).reverse()) - .ok() - .map(|i| unsafe { *DATA.get_unchecked(i) }) -} -static EN: DataStruct = include!("en.rs.data"); -static ES: DataStruct = include!("es.rs.data"); -static FR: DataStruct = include!("fr.rs.data"); -static IT: DataStruct = include!("it.rs.data"); -static JA: DataStruct = include!("ja.rs.data"); -static PT: DataStruct = include!("pt.rs.data"); -static RU: DataStruct = include!("ru.rs.data"); -static TR: DataStruct = include!("tr.rs.data"); -static UND: DataStruct = include!("und.rs.data"); -static ZH_HANT: DataStruct = include!("zh-Hant.rs.data"); -static ZH: DataStruct = include!("zh.rs.data"); diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data deleted file mode 100644 index 3d8c89f9072fd..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data deleted file mode 100644 index 653ce28d615ad..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data deleted file mode 100644 index 9fa6eb56ade20..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data deleted file mode 100644 index 66b55c253688d..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data deleted file mode 100644 index 38da6ecf8152a..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data deleted file mode 100644 index d4dac1c386ece..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data +++ /dev/null @@ -1,50 +0,0 @@ -::icu_list::provider::ListFormatterPatternsV1([ - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, - ::icu_list::provider::ConditionalListJoinerPattern { - default: ::icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), - special_case: None, - }, -]) diff --git a/compiler/rustc_baked_icu_data/src/data/list/mod.rs b/compiler/rustc_baked_icu_data/src/data/list/mod.rs deleted file mode 100644 index 931822513cc06..0000000000000 --- a/compiler/rustc_baked_icu_data/src/data/list/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -// @generated -pub mod and_v1; diff --git a/compiler/rustc_baked_icu_data/src/data/macros.rs b/compiler/rustc_baked_icu_data/src/data/macros.rs new file mode 100644 index 0000000000000..bee309f9b8117 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros.rs @@ -0,0 +1,46 @@ +// @generated +/// Marks a type as a data provider. You can then use macros like +/// `impl_core_helloworld_v1` to add implementations. +/// +/// ```ignore +/// struct MyProvider; +/// const _: () = { +/// include!("path/to/generated/macros.rs"); +/// make_provider!(MyProvider); +/// impl_core_helloworld_v1!(MyProvider); +/// } +/// ``` +#[doc(hidden)] +#[macro_export] +macro_rules! __make_provider { + ($ name : ty) => { + #[clippy::msrv = "1.66"] + impl $name { + #[doc(hidden)] + #[allow(dead_code)] + pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); + } + }; +} +#[doc(inline)] +pub use __make_provider as make_provider; +#[macro_use] +#[path = "macros/fallback_likelysubtags_v1.data.rs"] +mod fallback_likelysubtags_v1; +#[doc(inline)] +pub use __impl_fallback_likelysubtags_v1 as impl_fallback_likelysubtags_v1; +#[macro_use] +#[path = "macros/fallback_parents_v1.data.rs"] +mod fallback_parents_v1; +#[doc(inline)] +pub use __impl_fallback_parents_v1 as impl_fallback_parents_v1; +#[macro_use] +#[path = "macros/fallback_supplement_co_v1.data.rs"] +mod fallback_supplement_co_v1; +#[doc(inline)] +pub use __impl_fallback_supplement_co_v1 as impl_fallback_supplement_co_v1; +#[macro_use] +#[path = "macros/list_and_v1.data.rs"] +mod list_and_v1; +#[doc(inline)] +pub use __impl_list_and_v1 as impl_list_and_v1; diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs new file mode 100644 index 0000000000000..1adb58743f727 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs @@ -0,0 +1,40 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_likelysubtags_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_LIKELYSUBTAGS_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1 { + l2s: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") }) + }, + lr2s: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") }) + }, + l2r: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") }) + }, + ls2r: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_LIKELYSUBTAGS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs new file mode 100644 index 0000000000000..6f8d6590b0857 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs @@ -0,0 +1,28 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_parents_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_PARENTS_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackParentsV1 { + parents: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_PARENTS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs new file mode 100644 index 0000000000000..02eec37ee09ff --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs @@ -0,0 +1,32 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_supplement_co_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_SUPPLEMENT_CO_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackSupplementV1 { + parents: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") }) + }, + unicode_extension_defaults: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"co") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_SUPPLEMENT_CO_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs new file mode 100644 index 0000000000000..186f706cdb285 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs @@ -0,0 +1,35 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_list_and_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + static EN_001: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static EN_IN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static IT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }]); + static PT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static FR: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static TR: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static ES: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }]); + static RU: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static UND: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static EN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", & ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" & ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static HI_LATN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }]); + static JA: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]); + static ZH_HK: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }]); + static ZH: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]); + static ZH_HANT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }]); + static VALUES: [&::Yokeable; 215usize] = [&EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_IN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &HI_LATN, &IT, &IT, &IT, &IT, &JA, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &RU, &RU, &RU, &RU, &RU, &RU, &TR, &TR, &UND, &ZH, &ZH_HK, &ZH, &ZH, &ZH, &ZH_HANT, &ZH_HK, &ZH]; + static KEYS: [&str; 215usize] = ["en", "en-001", "en-150", "en-AE", "en-AG", "en-AI", "en-AS", "en-AT", "en-AU", "en-BB", "en-BE", "en-BI", "en-BM", "en-BS", "en-BW", "en-BZ", "en-CA", "en-CC", "en-CH", "en-CK", "en-CM", "en-CX", "en-CY", "en-DE", "en-DG", "en-DK", "en-DM", "en-ER", "en-FI", "en-FJ", "en-FK", "en-FM", "en-GB", "en-GD", "en-GG", "en-GH", "en-GI", "en-GM", "en-GU", "en-GY", "en-HK", "en-IE", "en-IL", "en-IM", "en-IN", "en-IO", "en-JE", "en-JM", "en-KE", "en-KI", "en-KN", "en-KY", "en-LC", "en-LR", "en-LS", "en-MG", "en-MH", "en-MO", "en-MP", "en-MS", "en-MT", "en-MU", "en-MV", "en-MW", "en-MY", "en-NA", "en-NF", "en-NG", "en-NL", "en-NR", "en-NU", "en-NZ", "en-PG", "en-PH", "en-PK", "en-PN", "en-PR", "en-PW", "en-RW", "en-SB", "en-SC", "en-SD", "en-SE", "en-SG", "en-SH", "en-SI", "en-SL", "en-SS", "en-SX", "en-SZ", "en-TC", "en-TK", "en-TO", "en-TT", "en-TV", "en-TZ", "en-UG", "en-UM", "en-VC", "en-VG", "en-VI", "en-VU", "en-WS", "en-ZA", "en-ZM", "en-ZW", "es", "es-419", "es-AR", "es-BO", "es-BR", "es-BZ", "es-CL", "es-CO", "es-CR", "es-CU", "es-DO", "es-EA", "es-EC", "es-GQ", "es-GT", "es-HN", "es-IC", "es-MX", "es-NI", "es-PA", "es-PE", "es-PH", "es-PR", "es-PY", "es-SV", "es-US", "es-UY", "es-VE", "fr", "fr-BE", "fr-BF", "fr-BI", "fr-BJ", "fr-BL", "fr-CA", "fr-CD", "fr-CF", "fr-CG", "fr-CH", "fr-CI", "fr-CM", "fr-DJ", "fr-DZ", "fr-GA", "fr-GF", "fr-GN", "fr-GP", "fr-GQ", "fr-HT", "fr-KM", "fr-LU", "fr-MA", "fr-MC", "fr-MF", "fr-MG", "fr-ML", "fr-MQ", "fr-MR", "fr-MU", "fr-NC", "fr-NE", "fr-PF", "fr-PM", "fr-RE", "fr-RW", "fr-SC", "fr-SN", "fr-SY", "fr-TD", "fr-TG", "fr-TN", "fr-VU", "fr-WF", "fr-YT", "hi-Latn", "it", "it-CH", "it-SM", "it-VA", "ja", "pt", "pt-AO", "pt-CH", "pt-CV", "pt-GQ", "pt-GW", "pt-LU", "pt-MO", "pt-MZ", "pt-PT", "pt-ST", "pt-TL", "ru", "ru-BY", "ru-KG", "ru-KZ", "ru-MD", "ru-UA", "tr", "tr-CY", "und", "zh", "zh-HK", "zh-Hans", "zh-Hans-HK", "zh-Hans-MO", "zh-Hant", "zh-MO", "zh-SG"]; + if let Ok(payload) = KEYS.binary_search_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).map(|i| *unsafe { VALUES.get_unchecked(i) }) { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(payload)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::MissingLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/mod.rs b/compiler/rustc_baked_icu_data/src/data/mod.rs index 943187808b818..465689f0cb8d7 100644 --- a/compiler/rustc_baked_icu_data/src/data/mod.rs +++ b/compiler/rustc_baked_icu_data/src/data/mod.rs @@ -1,122 +1,31 @@ // @generated -#[clippy::msrv = "1.61"] -mod fallback; -#[clippy::msrv = "1.61"] -mod list; -#[clippy::msrv = "1.61"] -use icu_provider::prelude::*; -/// Implement [`DataProvider`] on the given struct using the data -/// hardcoded in this module. This allows the struct to be used with -/// `icu`'s `_unstable` constructors. -/// -/// This macro can only be called from its definition-site, i.e. right -/// after `include!`-ing the generated module. -/// -/// ```compile_fail -/// struct MyDataProvider; -/// include!("/path/to/generated/mod.rs"); -/// impl_data_provider(MyDataProvider); -/// ``` -#[allow(unused_macros)] +include!("macros.rs"); macro_rules! impl_data_provider { - ($ provider : path) => { - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_list::provider::AndListV1Marker> for $provider { - fn load(&self, req: DataRequest) -> Result, DataError> { - list::and_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| DataErrorKind::MissingLocale.with_req(::icu_list::provider::AndListV1Marker::KEY, req)) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::supplement::co_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale - .with_req(::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY, req) - }) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::likelysubtags_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale - .with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY, req) - }) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::parents_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY, req) - }) - } - } + ($ provider : ty) => { + make_provider!($provider); + impl_fallback_likelysubtags_v1!($provider); + impl_fallback_parents_v1!($provider); + impl_fallback_supplement_co_v1!($provider); + impl_list_and_v1!($provider); }; } -/// Implement [`AnyProvider`] on the given struct using the data -/// hardcoded in this module. This allows the struct to be used with -/// `icu`'s `_any` constructors. -/// -/// This macro can only be called from its definition-site, i.e. right -/// after `include!`-ing the generated module. -/// -/// ```compile_fail -/// struct MyAnyProvider; -/// include!("/path/to/generated/mod.rs"); -/// impl_any_provider(MyAnyProvider); -/// ``` #[allow(unused_macros)] macro_rules! impl_any_provider { - ($ provider : path) => { - #[clippy::msrv = "1.61"] - impl AnyProvider for $provider { - fn load_any(&self, key: DataKey, req: DataRequest) -> Result { - const ANDLISTV1MARKER: ::icu_provider::DataKeyHash = ::icu_list::provider::AndListV1Marker::KEY.hashed(); - const COLLATIONFALLBACKSUPPLEMENTV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY.hashed(); - const LOCALEFALLBACKLIKELYSUBTAGSV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY.hashed(); - const LOCALEFALLBACKPARENTSV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY.hashed(); + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + impl icu_provider::AnyProvider for $provider { + fn load_any(&self, key: icu_provider::DataKey, req: icu_provider::DataRequest) -> Result { match key.hashed() { - ANDLISTV1MARKER => list::and_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - COLLATIONFALLBACKSUPPLEMENTV1MARKER => fallback::supplement::co_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - LOCALEFALLBACKLIKELYSUBTAGSV1MARKER => fallback::likelysubtags_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - LOCALEFALLBACKPARENTSV1MARKER => fallback::parents_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - _ => return Err(DataErrorKind::MissingDataKey.with_req(key, req)), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + _ => Err(icu_provider::DataErrorKind::MissingDataKey.with_req(key, req)), } - .map(|payload| AnyResponse { payload: Some(payload), metadata: Default::default() }) - .ok_or_else(|| DataErrorKind::MissingLocale.with_req(key, req)) } } }; } -#[clippy::msrv = "1.61"] +#[clippy::msrv = "1.66"] pub struct BakedDataProvider; impl_data_provider!(BakedDataProvider); diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs index ae8c062d25d81..ffcb290685a19 100644 --- a/compiler/rustc_baked_icu_data/src/lib.rs +++ b/compiler/rustc_baked_icu_data/src/lib.rs @@ -20,9 +20,9 @@ //! --cldr-tag latest --icuexport-tag latest -o src/data //! ``` -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![allow(elided_lifetimes_in_paths)] mod data { diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 636817a7ce100..714f46270f92c 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1.5.0" -itertools = "0.10.1" +itertools = "0.11" polonius-engine = "0.13.0" rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -19,7 +19,6 @@ rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } -rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 0b44beeb004c4..948af03953718 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -71,7 +71,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { let kind = match self.kind { mir::BorrowKind::Shared => "", - mir::BorrowKind::Shallow => "shallow ", + mir::BorrowKind::Fake => "fake ", mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ", // FIXME: differentiate `TwoPhaseBorrow` mir::BorrowKind::Mut { @@ -107,7 +107,7 @@ impl LocalsStateAtExit { LocalsStateAtExit::AllAreInvalidated } else { let mut has_storage_dead = HasStorageDead(BitSet::new_empty(body.local_decls.len())); - has_storage_dead.visit_body(&body); + has_storage_dead.visit_body(body); let mut has_storage_dead_or_moved = has_storage_dead.0; for move_out in &move_data.moves { if let Some(index) = move_data.base_local(move_out.path) { @@ -128,7 +128,7 @@ impl<'tcx> BorrowSet<'tcx> { ) -> Self { let mut visitor = GatherBorrows { tcx, - body: &body, + body: body, location_map: Default::default(), activation_map: Default::default(), local_map: Default::default(), @@ -140,7 +140,7 @@ impl<'tcx> BorrowSet<'tcx> { ), }; - for (block, block_data) in traversal::preorder(&body) { + for (block, block_data) in traversal::preorder(body) { visitor.visit_basic_block_data(block, block_data); } diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs deleted file mode 100644 index 1f642099f0899..0000000000000 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ /dev/null @@ -1,248 +0,0 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] -use rustc_infer::infer::InferCtxt; -use rustc_middle::mir::visit::TyContext; -use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{ - Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, SourceInfo, Statement, - StatementKind, Terminator, TerminatorKind, UserTypeProjection, -}; -use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; - -use crate::{ - borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict, - region_infer::values::LivenessValues, -}; - -pub(super) fn generate_constraints<'tcx>( - infcx: &InferCtxt<'tcx>, - liveness_constraints: &mut LivenessValues, - all_facts: &mut Option, - location_table: &LocationTable, - body: &Body<'tcx>, - borrow_set: &BorrowSet<'tcx>, -) { - let mut cg = ConstraintGeneration { - borrow_set, - infcx, - liveness_constraints, - location_table, - all_facts, - body, - }; - - for (bb, data) in body.basic_blocks.iter_enumerated() { - cg.visit_basic_block_data(bb, data); - } -} - -/// 'cg = the duration of the constraint generation process itself. -struct ConstraintGeneration<'cg, 'tcx> { - infcx: &'cg InferCtxt<'tcx>, - all_facts: &'cg mut Option, - location_table: &'cg LocationTable, - liveness_constraints: &'cg mut LivenessValues, - borrow_set: &'cg BorrowSet<'tcx>, - body: &'cg Body<'tcx>, -} - -impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> { - /// We sometimes have `args` within an rvalue, or within a - /// call. Make them live at the location where they appear. - fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) { - self.add_regular_live_constraint(*args, location); - self.super_args(args); - } - - /// We sometimes have `region` within an rvalue, or within a - /// call. Make them live at the location where they appear. - fn visit_region(&mut self, region: ty::Region<'tcx>, location: Location) { - self.add_regular_live_constraint(region, location); - self.super_region(region); - } - - /// We sometimes have `ty` within an rvalue, or within a - /// call. Make them live at the location where they appear. - fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) { - match ty_context { - TyContext::ReturnTy(SourceInfo { span, .. }) - | TyContext::YieldTy(SourceInfo { span, .. }) - | TyContext::UserTy(span) - | TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => { - span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context); - } - TyContext::Location(location) => { - self.add_regular_live_constraint(ty, location); - } - } - - self.super_ty(ty); - } - - fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { - if let Some(all_facts) = self.all_facts { - let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - all_facts.cfg_edge.push(( - self.location_table.start_index(location), - self.location_table.mid_index(location), - )); - - all_facts.cfg_edge.push(( - self.location_table.mid_index(location), - self.location_table.start_index(location.successor_within_block()), - )); - - // If there are borrows on this now dead local, we need to record them as `killed`. - if let StatementKind::StorageDead(local) = statement.kind { - record_killed_borrows_for_local( - all_facts, - self.borrow_set, - self.location_table, - local, - location, - ); - } - } - - self.super_statement(statement, location); - } - - fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { - // When we see `X = ...`, then kill borrows of - // `(*X).foo` and so forth. - self.record_killed_borrows_for_place(*place, location); - - self.super_assign(place, rvalue, location); - } - - fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - if let Some(all_facts) = self.all_facts { - let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - all_facts.cfg_edge.push(( - self.location_table.start_index(location), - self.location_table.mid_index(location), - )); - - let successor_blocks = terminator.successors(); - all_facts.cfg_edge.reserve(successor_blocks.size_hint().0); - for successor_block in successor_blocks { - all_facts.cfg_edge.push(( - self.location_table.mid_index(location), - self.location_table.start_index(successor_block.start_location()), - )); - } - } - - // A `Call` terminator's return value can be a local which has borrows, - // so we need to record those as `killed` as well. - if let TerminatorKind::Call { destination, .. } = terminator.kind { - self.record_killed_borrows_for_place(destination, location); - } - - self.super_terminator(terminator, location); - } - - fn visit_ascribe_user_ty( - &mut self, - _place: &Place<'tcx>, - _variance: ty::Variance, - _user_ty: &UserTypeProjection, - _location: Location, - ) { - } -} - -impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> { - /// Some variable with type `live_ty` is "regular live" at - /// `location` -- i.e., it may be used later. This means that all - /// regions appearing in the type `live_ty` must be live at - /// `location`. - fn add_regular_live_constraint(&mut self, live_ty: T, location: Location) - where - T: TypeVisitable>, - { - debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location); - - self.infcx.tcx.for_each_free_region(&live_ty, |live_region| { - let vid = live_region.as_var(); - self.liveness_constraints.add_element(vid, location); - }); - } - - /// When recording facts for Polonius, records the borrows on the specified place - /// as `killed`. For example, when assigning to a local, or on a call's return destination. - fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) { - if let Some(all_facts) = self.all_facts { - let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - - // Depending on the `Place` we're killing: - // - if it's a local, or a single deref of a local, - // we kill all the borrows on the local. - // - if it's a deeper projection, we have to filter which - // of the borrows are killed: the ones whose `borrowed_place` - // conflicts with the `place`. - match place.as_ref() { - PlaceRef { local, projection: &[] } - | PlaceRef { local, projection: &[ProjectionElem::Deref] } => { - debug!( - "Recording `killed` facts for borrows of local={:?} at location={:?}", - local, location - ); - - record_killed_borrows_for_local( - all_facts, - self.borrow_set, - self.location_table, - local, - location, - ); - } - - PlaceRef { local, projection: &[.., _] } => { - // Kill conflicting borrows of the innermost local. - debug!( - "Recording `killed` facts for borrows of \ - innermost projected local={:?} at location={:?}", - local, location - ); - - if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { - for &borrow_index in borrow_indices { - let places_conflict = places_conflict::places_conflict( - self.infcx.tcx, - self.body, - self.borrow_set[borrow_index].borrowed_place, - place, - places_conflict::PlaceConflictBias::NoOverlap, - ); - - if places_conflict { - let location_index = self.location_table.mid_index(location); - all_facts.loan_killed_at.push((borrow_index, location_index)); - } - } - } - } - } - } - } -} - -/// When recording facts for Polonius, records the borrows on the specified local as `killed`. -fn record_killed_borrows_for_local( - all_facts: &mut AllFacts, - borrow_set: &BorrowSet<'_>, - location_table: &LocationTable, - local: Local, - location: Location, -) { - if let Some(borrow_indices) = borrow_set.local_map.get(&local) { - all_facts.loan_killed_at.reserve(borrow_indices.len()); - for &borrow_index in borrow_indices { - let location_index = location_table.mid_index(location); - all_facts.loan_killed_at.push((borrow_index, location_index)); - } - } -} diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index 315886bbe29ba..041ac75ec016e 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -122,6 +122,7 @@ rustc_index::newtype_index! { } rustc_index::newtype_index! { + #[orderable] #[debug_format = "ConstraintSccIndex({})"] pub struct ConstraintSccIndex {} } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 16814950b0d98..54f161ea9b449 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -109,6 +109,7 @@ impl_visitable! { } rustc_index::newtype_index! { + #[orderable] #[debug_format = "bw{}"] pub struct BorrowIndex {} } @@ -120,24 +121,24 @@ rustc_index::newtype_index! { /// `BorrowIndex`, and maps each such index to a `BorrowData` /// describing the borrow. These indexes are used for representing the /// borrows in compact bitvectors. -pub struct Borrows<'a, 'tcx> { +pub struct Borrows<'mir, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, + body: &'mir Body<'tcx>, - borrow_set: &'a BorrowSet<'tcx>, + borrow_set: &'mir BorrowSet<'tcx>, borrows_out_of_scope_at_location: FxIndexMap>, } -struct OutOfScopePrecomputer<'a, 'tcx> { +struct OutOfScopePrecomputer<'mir, 'tcx> { visited: BitSet, visit_stack: Vec, - body: &'a Body<'tcx>, - regioncx: &'a RegionInferenceContext<'tcx>, + body: &'mir Body<'tcx>, + regioncx: &'mir RegionInferenceContext<'tcx>, borrows_out_of_scope_at_location: FxIndexMap>, } -impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> { - fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { +impl<'mir, 'tcx> OutOfScopePrecomputer<'mir, 'tcx> { + fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self { OutOfScopePrecomputer { visited: BitSet::new_empty(body.basic_blocks.len()), visit_stack: vec![], @@ -240,17 +241,17 @@ pub fn calculate_borrows_out_of_scope_at_location<'tcx>( prec.borrows_out_of_scope_at_location } -struct PoloniusOutOfScopePrecomputer<'a, 'tcx> { +struct PoloniusOutOfScopePrecomputer<'mir, 'tcx> { visited: BitSet, visit_stack: Vec, - body: &'a Body<'tcx>, - regioncx: &'a RegionInferenceContext<'tcx>, + body: &'mir Body<'tcx>, + regioncx: &'mir RegionInferenceContext<'tcx>, loans_out_of_scope_at_location: FxIndexMap>, } -impl<'a, 'tcx> PoloniusOutOfScopePrecomputer<'a, 'tcx> { - fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { +impl<'mir, 'tcx> PoloniusOutOfScopePrecomputer<'mir, 'tcx> { + fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self { Self { visited: BitSet::new_empty(body.basic_blocks.len()), visit_stack: vec![], @@ -273,11 +274,10 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { ) { let sccs = self.regioncx.constraint_sccs(); let universal_regions = self.regioncx.universal_regions(); - let issuing_region_scc = sccs.scc(issuing_region); // We first handle the cases where the loan doesn't go out of scope, depending on the issuing // region's successors. - for scc in sccs.depth_first_search(issuing_region_scc) { + for successor in self.regioncx.region_graph().depth_first_search(issuing_region) { // 1. Via applied member constraints // // The issuing region can flow into the choice regions, and they are either: @@ -290,6 +290,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { // For additional insurance via fuzzing and crater, we verify that the constraint's min // choice indeed escapes the function. In the future, we could e.g. turn this check into // a debug assert and early return as an optimization. + let scc = sccs.scc(successor); for constraint in self.regioncx.applied_member_constraints(scc) { if universal_regions.is_universal_region(constraint.min_choice) { return; @@ -300,7 +301,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { // // If the issuing region outlives such a region, its loan escapes the function and // cannot go out of scope. We can early return. - if self.regioncx.scc_is_live_at_all_points(scc) { + if self.regioncx.is_region_live_at_all_points(successor) { return; } } @@ -403,12 +404,12 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { } } -impl<'a, 'tcx> Borrows<'a, 'tcx> { +impl<'mir, 'tcx> Borrows<'mir, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, - regioncx: &'a RegionInferenceContext<'tcx>, - borrow_set: &'a BorrowSet<'tcx>, + body: &'mir Body<'tcx>, + regioncx: &'mir RegionInferenceContext<'tcx>, + borrow_set: &'mir BorrowSet<'tcx>, ) -> Self { let mut borrows_out_of_scope_at_location = calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set); @@ -431,7 +432,8 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { assert_eq!( borrows_out_of_scope_at_location, polonius_prec.loans_out_of_scope_at_location, - "the loans out of scope must be the same as the borrows out of scope" + "polonius loan scopes differ from NLL borrow scopes, for body {:?}", + body.span, ); borrows_out_of_scope_at_location = polonius_prec.loans_out_of_scope_at_location; diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 201f0df123879..d0cf339e7ba41 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -49,7 +49,7 @@ pub fn categorize(context: PlaceContext) -> Option { // cross suspension points so this behavior is unproblematic. PlaceContext::MutatingUse(MutatingUseContext::Borrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | - PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow) | // `PlaceMention` and `AscribeUserType` both evaluate the place, which must not // contain dangling references. diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index cfcf31fce32bd..924e68fa91dac 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -10,6 +10,8 @@ use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _}; use rustc_infer::traits::ObligationCause; use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::RePlaceholder; +use rustc_middle::ty::Region; use rustc_middle::ty::RegionVid; use rustc_middle::ty::UniverseIndex; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -205,6 +207,8 @@ trait TypeOpInfo<'tcx> { let span = cause.span; let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region); + debug!(?nice_error); + if let Some(nice_error) = nice_error { mbcx.buffer_error(nice_error); } else { @@ -381,7 +385,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( error_region: Option>, ) -> Option> { // We generally shouldn't have errors here because the query was - // already run, but there's no point using `delay_span_bug` + // already run, but there's no point using `span_delayed_bug` // when we're going to emit an error here anyway. let _errors = ocx.select_all_or_error(); let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone()); @@ -404,19 +408,41 @@ fn try_extract_error_from_region_constraints<'tcx>( mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin, mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex, ) -> Option> { - let (sub_region, cause) = - region_constraints.constraints.iter().find_map(|(constraint, cause)| { - match *constraint { - Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => { - Some((sub, cause.clone())) - } - // FIXME: Should this check the universe of the var? - Constraint::VarSubReg(vid, sup) if sup == placeholder_region => { - Some((ty::Region::new_var(infcx.tcx, vid), cause.clone())) - } - _ => None, + let matches = + |a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) { + (RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound, + _ => a_region == b_region, + }; + let check = |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| { + match *constraint { + Constraint::RegSubReg(sub, sup) + if ((exact && sup == placeholder_region) + || (!exact && matches(sup, placeholder_region))) + && sup != sub => + { + Some((sub, cause.clone())) + } + // FIXME: Should this check the universe of the var? + Constraint::VarSubReg(vid, sup) + if ((exact && sup == placeholder_region) + || (!exact && matches(sup, placeholder_region))) => + { + Some((ty::Region::new_var(infcx.tcx, vid), cause.clone())) } - })?; + _ => None, + } + }; + let mut info = region_constraints + .constraints + .iter() + .find_map(|(constraint, cause)| check(constraint, cause, true)); + if info.is_none() { + info = region_constraints + .constraints + .iter() + .find_map(|(constraint, cause)| check(constraint, cause, false)); + } + let (sub_region, cause) = info?; debug!(?sub_region, "cause = {:#?}", cause); let error = match (error_region, *sub_region) { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 247200dcd2695..7bcad92ff337f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -413,7 +413,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (None, &[][..], 0) }; if let Some(def_id) = def_id - && let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id)) + && let Some(node) = hir.find(self.infcx.tcx.local_def_id_to_hir_id(def_id)) && let Some(fn_sig) = node.fn_sig() && let Some(ident) = node.ident() && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) @@ -445,7 +445,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { && let hir::ExprKind::Path(hir::QPath::LangItem( LangItem::IntoIterIntoIter, _, - _, )) = call_expr.kind { // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. @@ -490,7 +489,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut spans = vec![]; for init_idx in inits { let init = &self.move_data.inits[*init_idx]; - let span = init.span(&self.body); + let span = init.span(self.body); if !span.is_dummy() { spans.push(span); } @@ -518,7 +517,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let body = map.body(body_id); let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] }; - visitor.visit_body(&body); + visitor.visit_body(body); let mut show_assign_sugg = false; let isnt_initialized = if let InitializationRequiringAction::PartialAssignment @@ -614,7 +613,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let mut visitor = LetVisitor { decl_span, sugg_span: None }; - visitor.visit_body(&body); + visitor.visit_body(body); if let Some(span) = visitor.sugg_span { self.suggest_assign_value(&mut err, moved_place, span); } @@ -779,7 +778,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; }; // Try to find predicates on *generic params* that would allow copying `ty` - let ocx = ObligationCtxt::new(&self.infcx); + let ocx = ObligationCtxt::new(self.infcx); let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span)); let cause = ObligationCause::misc(span, self.mir_def_id()); @@ -856,7 +855,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &mut err, "", @@ -903,7 +902,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &mut err, "", @@ -1022,7 +1021,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None) } - (BorrowKind::Mut { .. }, BorrowKind::Shallow) => { + (BorrowKind::Mut { .. }, BorrowKind::Fake) => { if let Some(immutable_section_description) = self.classify_immutable_section(issued_borrow.assigned_place) { @@ -1114,11 +1113,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) } - (BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Shallow) - | ( - BorrowKind::Shallow, - BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow, - ) => unreachable!(), + (BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Fake) + | (BorrowKind::Fake, BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake) => { + unreachable!() + } }; if issued_spans == borrow_spans { @@ -1137,7 +1135,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }); } else { issued_spans.var_subdiag( - Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic), + Some(self.infcx.tcx.sess.diagnostic()), &mut err, Some(issued_borrow.kind), |kind, var_span| { @@ -1154,7 +1152,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); borrow_spans.var_subdiag( - Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic), + Some(self.infcx.tcx.sess.diagnostic()), &mut err, Some(gen_borrow_kind), |kind, var_span| { @@ -1175,7 +1173,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &mut err, first_borrow_desc, @@ -1347,11 +1345,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // }; // corresponding to the desugaring of a for loop `for in { }`. if let hir::ExprKind::Call(path, [arg]) = ex.kind - && let hir::ExprKind::Path(hir::QPath::LangItem( - LangItem::IntoIterIntoIter, - _, - _, - )) = path.kind + && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) = + path.kind && arg.span.contains(self.issue_span) { // Find `IntoIterator::into_iter()` @@ -1369,10 +1364,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }) = stmt.kind && let hir::ExprKind::Call(path, _args) = call.kind - && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _, _)) = + && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _)) = path.kind && let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind - && let hir::QPath::LangItem(LangItem::OptionSome, pat_span, _) = path + && let hir::QPath::LangItem(LangItem::OptionSome, pat_span) = path && call.span.contains(self.issue_span) { // Find `` and the span for the whole `for` loop. @@ -1579,8 +1574,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; }; let sig = args.as_closure().sig(); - let tupled_params = - tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b)); + let tupled_params = tcx.instantiate_bound_regions_with_erased( + sig.inputs().iter().next().unwrap().map_bound(|&b| b), + ); let ty::Tuple(params) = tupled_params.kind() else { return }; // Find the first argument with a matching type, get its name @@ -1932,7 +1928,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let place_desc = self.describe_place(borrow.borrowed_place.as_ref()); let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0)); - let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place); + let explanation = self.explain_why_borrow_contains_point(location, borrow, kind_place); debug!(?place_desc, ?explanation); @@ -2001,14 +1997,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (Some(name), explanation) => self.report_local_value_does_not_live_long_enough( location, &name, - &borrow, + borrow, drop_span, borrow_spans, explanation, ), (None, explanation) => self.report_temporary_value_does_not_live_long_enough( location, - &borrow, + borrow, drop_span, borrow_spans, proper_span, @@ -2076,8 +2072,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .map(|name| format!("function `{name}`")) .unwrap_or_else(|| { match &self.infcx.tcx.def_kind(self.mir_def_id()) { + DefKind::Closure + if self + .infcx + .tcx + .is_coroutine(self.mir_def_id().to_def_id()) => + { + "enclosing coroutine" + } DefKind::Closure => "enclosing closure", - DefKind::Coroutine => "enclosing coroutine", kind => bug!("expected closure or coroutine, found {:?}", kind), } .to_string() @@ -2098,7 +2101,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &mut err, "", @@ -2119,7 +2122,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &mut err, "", @@ -2180,7 +2183,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &mut err, "", @@ -2349,7 +2352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Applicability::MaybeIncorrect, ); } else { - err.note("the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used"); + err.note("the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used"); err.note("to learn more, visit "); } suggested = true; @@ -2365,7 +2368,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } explanation.add_explanation_to_diagnostic( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &mut err, "", @@ -2806,7 +2809,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let loan_span = loan_spans.args_or_use(); let descr_place = self.describe_any_place(place.as_ref()); - if loan.kind == BorrowKind::Shallow { + if loan.kind == BorrowKind::Fake { if let Some(section) = self.classify_immutable_section(loan.assigned_place) { let mut err = self.cannot_mutate_in_immutable_section( span, @@ -2842,7 +2845,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &mut err, "", @@ -3020,7 +3023,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } let mut visitor = FakeReadCauseFinder { place, cause: None }; - visitor.visit_body(&self.body); + visitor.visit_body(self.body); match visitor.cause { Some(FakeReadCause::ForMatchGuard) => Some("match guard"), Some(FakeReadCause::ForIndex) => Some("indexing expression"), @@ -3247,7 +3250,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> Option> { debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); let is_closure = self.infcx.tcx.is_closure(did.to_def_id()); - let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did); + let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did); let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?; // We need to work out which arguments to highlight. We do this by looking diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 8a930ca59a334..bed3df4809ddd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -5,12 +5,13 @@ use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::mir::{ Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::{self, RegionVid, TyCtxt}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{sym, DesugaringKind, Span}; use rustc_trait_selection::traits::error_reporting::FindExprBySpan; @@ -290,12 +291,69 @@ impl<'tcx> BorrowExplanation<'tcx> { } } + if let ConstraintCategory::Cast { unsize_to: Some(unsize_ty) } = category { + self.add_object_lifetime_default_note(tcx, err, unsize_ty); + } self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name); } _ => {} } } + fn add_object_lifetime_default_note( + &self, + tcx: TyCtxt<'tcx>, + err: &mut Diagnostic, + unsize_ty: Ty<'tcx>, + ) { + if let ty::Adt(def, args) = unsize_ty.kind() { + // We try to elaborate the object lifetime defaults and present those to the user. This should + // make it clear where the region constraint is coming from. + let generics = tcx.generics_of(def.did()); + + let mut has_dyn = false; + let mut failed = false; + + let elaborated_args = std::iter::zip(*args, &generics.params).map(|(arg, param)| { + if let Some(ty::Dynamic(obj, _, ty::DynKind::Dyn)) = arg.as_type().map(Ty::kind) { + let default = tcx.object_lifetime_default(param.def_id); + + let re_static = tcx.lifetimes.re_static; + + let implied_region = match default { + // This is not entirely precise. + ObjectLifetimeDefault::Empty => re_static, + ObjectLifetimeDefault::Ambiguous => { + failed = true; + re_static + } + ObjectLifetimeDefault::Param(param_def_id) => { + let index = generics.param_def_id_to_index[¶m_def_id] as usize; + args.get(index).and_then(|arg| arg.as_region()).unwrap_or_else(|| { + failed = true; + re_static + }) + } + ObjectLifetimeDefault::Static => re_static, + }; + + has_dyn = true; + + Ty::new_dynamic(tcx, obj, implied_region, ty::DynKind::Dyn).into() + } else { + arg + } + }); + let elaborated_ty = Ty::new_adt(tcx, *def, tcx.mk_args_from_iter(elaborated_args)); + + if has_dyn && !failed { + err.note(format!( + "due to object lifetime defaults, `{unsize_ty}` actually means `{elaborated_ty}`" + )); + } + } + } + fn add_lifetime_bound_suggestion_to_diagnostic( &self, err: &mut Diagnostic, @@ -364,7 +422,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { kind_place: Option<(WriteKind, Place<'tcx>)>, ) -> BorrowExplanation<'tcx> { let regioncx = &self.regioncx; - let body: &Body<'_> = &self.body; + let body: &Body<'_> = self.body; let tcx = self.infcx.tcx; let borrow_region_vid = borrow.region; diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 4b95b4783eb4b..1844e766a82b3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -10,7 +10,8 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::CoroutineKind; use rustc_index::IndexSlice; -use rustc_infer::infer::LateBoundRegionConversionTime; +use rustc_infer::infer::BoundRegionConversionTime; +use rustc_infer::traits::{FulfillmentErrorCode, SelectionError}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location, @@ -24,10 +25,9 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; use rustc_span::def_id::LocalDefId; use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx}; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::{ - type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause, -}; +use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _; +use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions; use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; @@ -124,7 +124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { diag.eager_subdiagnostic( - &self.infcx.tcx.sess.parse_sess.span_diagnostic, + self.infcx.tcx.sess.diagnostic(), OnClosureNote::InvokedTwice { place_name: &ty::place_to_string_for_capture( self.infcx.tcx, @@ -146,7 +146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { diag.eager_subdiagnostic( - &self.infcx.tcx.sess.parse_sess.span_diagnostic, + self.infcx.tcx.sess.diagnostic(), OnClosureNote::MovedTwice { place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place), span: *span, @@ -217,9 +217,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { projection: place.projection.split_at(index + 1).0, }) { let var_index = field.index(); - buf = self.upvars[var_index].place.to_string(self.infcx.tcx); + buf = self.upvars[var_index].to_string(self.infcx.tcx); ok = Ok(()); - if !self.upvars[var_index].by_ref { + if !self.upvars[var_index].is_by_ref() { buf.insert(0, '*'); } } else { @@ -250,7 +250,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { local, projection: place.projection.split_at(index + 1).0, }) { - buf = self.upvars[field.index()].place.to_string(self.infcx.tcx); + buf = self.upvars[field.index()].to_string(self.infcx.tcx); ok = Ok(()); } else { let field_name = self.describe_field( @@ -354,7 +354,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::Adt(def, _) => { let variant = if let Some(idx) = variant_index { assert!(def.is_enum()); - &def.variant(idx) + def.variant(idx) } else { def.non_enum_variant() }; @@ -462,7 +462,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // lifetimes without names with the value `'0`. if let ty::Ref(region, ..) = ty.kind() { match **region { - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::RePlaceholder(ty::PlaceholderRegion { bound: ty::BoundRegion { kind: br, .. }, .. @@ -482,7 +482,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let region = if let ty::Ref(region, ..) = ty.kind() { match **region { - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::RePlaceholder(ty::PlaceholderRegion { bound: ty::BoundRegion { kind: br, .. }, .. @@ -634,7 +634,7 @@ impl UseSpans<'_> { err.subdiagnostic(match kind { Some(kd) => match kd { rustc_middle::mir::BorrowKind::Shared - | rustc_middle::mir::BorrowKind::Shallow => { + | rustc_middle::mir::BorrowKind::Fake => { CaptureVarKind::Immut { kind_span: capture_kind_span } } @@ -851,7 +851,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { let Some((method_did, method_args)) = rustc_middle::util::find_self_call( self.infcx.tcx, - &self.body, + self.body, target_temp, location.block, ) else { @@ -958,7 +958,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "closure_span: def_id={:?} target_place={:?} places={:?}", def_id, target_place, places ); - let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = self.infcx.tcx.local_def_id_to_hir_id(def_id); let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind; debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr); if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr { @@ -1043,12 +1043,43 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } CallKind::Normal { self_arg, desugaring, method_did, method_args } => { let self_arg = self_arg.unwrap(); + let mut has_sugg = false; let tcx = self.infcx.tcx; + // Avoid pointing to the same function in multiple different + // error messages. + if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) { + self.explain_iterator_advancement_in_for_loop_if_applicable( + err, + span, + &move_spans, + ); + + let func = tcx.def_path_str(method_did); + err.subdiagnostic(CaptureReasonNote::FuncTakeSelf { + func, + place_name: place_name.clone(), + span: self_arg.span, + }); + } + let parent_did = tcx.parent(method_did); + let parent_self_ty = + matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. }) + .then_some(parent_did) + .and_then(|did| match tcx.type_of(did).instantiate_identity().kind() { + ty::Adt(def, ..) => Some(def.did()), + _ => None, + }); + let is_option_or_result = parent_self_ty.is_some_and(|def_id| { + matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result)) + }); + if is_option_or_result && maybe_reinitialized_locations_is_empty { + err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span }); + } if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring { let ty = moved_place.ty(self.body, tcx).ty; let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) { Some(def_id) => type_known_to_meet_bound_modulo_regions( - &self.infcx, + self.infcx, self.param_env, Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty), def_id, @@ -1108,72 +1139,92 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Erase and shadow everything that could be passed to the new infcx. let ty = moved_place.ty(self.body, tcx).ty; - if let ty::Adt(def, args) = ty.kind() + if let ty::Adt(def, args) = ty.peel_refs().kind() && Some(def.did()) == tcx.lang_items().pin_type() && let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind() && let self_ty = self.infcx.instantiate_binder_with_fresh_vars( fn_call_span, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, tcx.fn_sig(method_did).instantiate(tcx, method_args).input(0), ) && self.infcx.can_eq(self.param_env, ty, self_ty) { err.eager_subdiagnostic( - &self.infcx.tcx.sess.parse_sess.span_diagnostic, + self.infcx.tcx.sess.diagnostic(), CaptureReasonSuggest::FreshReborrow { span: move_span.shrink_to_hi(), }, ); + has_sugg = true; } - if let Some(clone_trait) = tcx.lang_items().clone_trait() - && let trait_ref = ty::TraitRef::new(tcx, clone_trait, [ty]) - && let o = Obligation::new( - tcx, - ObligationCause::dummy(), - self.param_env, - ty::Binder::dummy(trait_ref), - ) - && self.infcx.predicate_must_hold_modulo_regions(&o) - { - err.span_suggestion_verbose( - move_span.shrink_to_hi(), - "you can `clone` the value and consume it, but this might not be \ - your desired behavior", - ".clone()".to_string(), - Applicability::MaybeIncorrect, - ); + if let Some(clone_trait) = tcx.lang_items().clone_trait() { + let sugg = if moved_place + .iter_projections() + .any(|(_, elem)| matches!(elem, ProjectionElem::Deref)) + { + vec![ + // We use the fully-qualified path because `.clone()` can + // sometimes choose `<&T as Clone>` instead of `` + // when going through auto-deref, so this ensures that doesn't + // happen, causing suggestions for `.clone().clone()`. + (move_span.shrink_to_lo(), format!("<{ty} as Clone>::clone(&")), + (move_span.shrink_to_hi(), ")".to_string()), + ] + } else { + vec![(move_span.shrink_to_hi(), ".clone()".to_string())] + }; + if let Some(errors) = + self.infcx.could_impl_trait(clone_trait, ty, self.param_env) + && !has_sugg + { + let msg = match &errors[..] { + [] => "you can `clone` the value and consume it, but this \ + might not be your desired behavior" + .to_string(), + [error] => { + format!( + "you could `clone` the value and consume it, if \ + the `{}` trait bound could be satisfied", + error.obligation.predicate, + ) + } + [errors @ .., last] => { + format!( + "you could `clone` the value and consume it, if \ + the following trait bounds could be satisfied: {} \ + and `{}`", + errors + .iter() + .map(|e| format!("`{}`", e.obligation.predicate)) + .collect::>() + .join(", "), + last.obligation.predicate, + ) + } + }; + err.multipart_suggestion_verbose( + msg, + sugg.clone(), + Applicability::MaybeIncorrect, + ); + for error in errors { + if let FulfillmentErrorCode::CodeSelectionError( + SelectionError::Unimplemented, + ) = error.code + && let ty::PredicateKind::Clause(ty::ClauseKind::Trait( + pred, + )) = error.obligation.predicate.kind().skip_binder() + { + self.infcx.err_ctxt().suggest_derive( + &error.obligation, + err, + error.obligation.predicate.kind().rebind(pred), + ); + } + } + } } } - // Avoid pointing to the same function in multiple different - // error messages. - if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) { - self.explain_iterator_advancement_in_for_loop_if_applicable( - err, - span, - &move_spans, - ); - - let func = tcx.def_path_str(method_did); - err.subdiagnostic(CaptureReasonNote::FuncTakeSelf { - func, - place_name, - span: self_arg.span, - }); - } - let parent_did = tcx.parent(method_did); - let parent_self_ty = - matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. }) - .then_some(parent_did) - .and_then(|did| match tcx.type_of(did).instantiate_identity().kind() { - ty::Adt(def, ..) => Some(def.did()), - _ => None, - }); - let is_option_or_result = parent_self_ty.is_some_and(|def_id| { - matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result)) - }); - if is_option_or_result && maybe_reinitialized_locations_is_empty { - err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span }); - } } // Other desugarings takes &self, which cannot cause a move _ => {} diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 695ac6980cd71..43487b85a7b3b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -2,7 +2,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; -use rustc_span::{BytePos, Span}; +use rustc_span::{BytePos, ExpnKind, MacroKind, Span}; use crate::diagnostics::CapturedMessageOpt; use crate::diagnostics::{DescribePlaceOpt, UseSpans}; @@ -321,7 +321,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let deref_base = match deref_target_place.projection.as_ref() { [proj_base @ .., ProjectionElem::Deref] => { - PlaceRef { local: deref_target_place.local, projection: &proj_base } + PlaceRef { local: deref_target_place.local, projection: proj_base } } _ => bug!("deref_target_place is not a deref projection"), }; @@ -363,8 +363,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { format!("captured variable in an `{closure_kind}` closure"); let upvar = &self.upvars[upvar_field.unwrap().index()]; - let upvar_hir_id = upvar.place.get_root_variable(); - let upvar_name = upvar.place.to_string(self.infcx.tcx); + let upvar_hir_id = upvar.get_root_variable(); + let upvar_name = upvar.to_string(self.infcx.tcx); let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id); let place_name = self.describe_any_place(move_place.as_ref()); @@ -488,6 +488,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { args_span, } }); + + self.add_note_for_packed_struct_derive(err, original_path.local); } } } @@ -581,7 +583,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, ty: bind_to.ty, - place: &place_desc, + place: place_desc, span: binding_span, }); } @@ -594,4 +596,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); } } + + /// Adds an explanatory note if the move error occurs in a derive macro + /// expansion of a packed struct. + /// Such errors happen because derive macro expansions shy away from taking + /// references to the struct's fields since doing so would be undefined behaviour + fn add_note_for_packed_struct_derive(&self, err: &mut Diagnostic, local: Local) { + let local_place: PlaceRef<'tcx> = local.into(); + let local_ty = local_place.ty(self.body.local_decls(), self.infcx.tcx).ty.peel_refs(); + + if let Some(adt) = local_ty.ty_adt_def() + && adt.repr().packed() + && let ExpnKind::Macro(MacroKind::Derive, name) = + self.body.span.ctxt().outer_expn_data().kind + { + err.note(format!("`#[derive({name})]` triggers a move because taking references to the fields of a packed struct is undefined behaviour")); + } + } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index dde46eef6a0d3..8fe552708ed9c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -3,8 +3,9 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; +use rustc_infer::traits; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; -use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt}; +use rustc_middle::ty::{self, InstanceDef, ToPredicate, Ty, TyCtxt}; use rustc_middle::{ hir::place::PlaceBase, mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location}, @@ -12,6 +13,8 @@ use rustc_middle::{ use rustc_span::symbol::{kw, Symbol}; use rustc_span::{sym, BytePos, DesugaringKind, Span}; use rustc_target::abi::FieldIdx; +use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt; use crate::diagnostics::BorrowedContentSource; use crate::util::FindAssignments; @@ -66,7 +69,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { )); let imm_borrow_derefed = self.upvars[upvar_index.index()] - .place .place .deref_tys() .any(|ty| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not))); @@ -85,7 +87,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if self.is_upvar_field_projection(access_place.as_ref()).is_some() { reason = ", as it is not declared as mutable".to_string(); } else { - let name = self.upvars[upvar_index.index()].place.to_string(self.infcx.tcx); + let name = self.upvars[upvar_index.index()].to_string(self.infcx.tcx); reason = format!(", as `{name}` is not declared as mutable"); } } @@ -388,7 +390,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty )); - let captured_place = &self.upvars[upvar_index.index()].place; + let captured_place = self.upvars[upvar_index.index()]; err.span_label(span, format!("cannot {act}")); @@ -661,7 +663,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } let hir_map = self.infcx.tcx.hir(); let my_def = self.body.source.def_id(); - let my_hir = hir_map.local_def_id_to_hir_id(my_def.as_local().unwrap()); + let my_hir = self.infcx.tcx.local_def_id_to_hir_id(my_def.as_local().unwrap()); let Some(td) = self.infcx.tcx.impl_of_method(my_def).and_then(|x| self.infcx.tcx.trait_id_of_impl(x)) else { @@ -1213,6 +1215,103 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(hir_id) = hir_id && let Some(hir::Node::Local(local)) = hir_map.find(hir_id) { + let tables = self.infcx.tcx.typeck(def_id.as_local().unwrap()); + if let Some(clone_trait) = self.infcx.tcx.lang_items().clone_trait() + && let Some(expr) = local.init + && let ty = tables.node_type_opt(expr.hir_id) + && let Some(ty) = ty + && let ty::Ref(..) = ty.kind() + { + match self + .infcx + .could_impl_trait(clone_trait, ty.peel_refs(), self.param_env) + .as_deref() + { + Some([]) => { + // The type implements Clone. + err.span_help( + expr.span, + format!( + "you can `clone` the `{}` value and consume it, but this \ + might not be your desired behavior", + ty.peel_refs(), + ), + ); + } + None => { + if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) = + expr.kind + && segment.ident.name == sym::clone + { + err.span_help( + span, + format!( + "`{}` doesn't implement `Clone`, so this call clones \ + the reference `{ty}`", + ty.peel_refs(), + ), + ); + } + // The type doesn't implement Clone. + let trait_ref = ty::Binder::dummy(ty::TraitRef::new( + self.infcx.tcx, + clone_trait, + [ty.peel_refs()], + )); + let obligation = traits::Obligation::new( + self.infcx.tcx, + traits::ObligationCause::dummy(), + self.param_env, + trait_ref, + ); + self.infcx.err_ctxt().suggest_derive( + &obligation, + err, + trait_ref.to_predicate(self.infcx.tcx), + ); + } + Some(errors) => { + if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) = + expr.kind + && segment.ident.name == sym::clone + { + err.span_help( + span, + format!( + "`{}` doesn't implement `Clone` because its \ + implementations trait bounds could not be met, so \ + this call clones the reference `{ty}`", + ty.peel_refs(), + ), + ); + err.note(format!( + "the following trait bounds weren't met: {}", + errors + .iter() + .map(|e| e.obligation.predicate.to_string()) + .collect::>() + .join("\n"), + )); + } + // The type doesn't implement Clone because of unmet obligations. + for error in errors { + if let traits::FulfillmentErrorCode::CodeSelectionError( + traits::SelectionError::Unimplemented, + ) = error.code + && let ty::PredicateKind::Clause(ty::ClauseKind::Trait( + pred, + )) = error.obligation.predicate.kind().skip_binder() + { + self.infcx.err_ctxt().suggest_derive( + &error.obligation, + err, + error.obligation.predicate.kind().rebind(pred), + ); + } + } + } + } + } let (changing, span, sugg) = match local.ty { Some(ty) => ("changing", ty.span, message), None => { diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index b6eb9ae980e4e..94981c4558204 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -50,8 +50,8 @@ impl OutlivesSuggestionBuilder { // naming the `'self` lifetime in methods, etc. fn region_name_is_suggestable(name: &RegionName) -> bool { match name.source { - RegionNameSource::NamedEarlyBoundRegion(..) - | RegionNameSource::NamedFreeRegion(..) + RegionNameSource::NamedEarlyParamRegion(..) + | RegionNameSource::NamedLateParamRegion(..) | RegionNameSource::Static => true, // Don't give suggestions for upvars, closure return types, or other unnameable diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index a0a809123c0f9..759f5e910f70a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -35,7 +35,7 @@ use crate::session_diagnostics::{ LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, }; -use super::{OutlivesSuggestionBuilder, RegionName}; +use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; use crate::region_infer::{BlameConstraint, ExtraConstraintInfo}; use crate::{ nll::ConstraintDescription, @@ -53,7 +53,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { ConstraintCategory::Yield => "yielding this value ", ConstraintCategory::UseAsConst => "using this value as a constant ", ConstraintCategory::UseAsStatic => "using this value as a static ", - ConstraintCategory::Cast => "cast ", + ConstraintCategory::Cast { .. } => "cast ", ConstraintCategory::CallArgument(_) => "argument ", ConstraintCategory::TypeAnnotation => "type annotation ", ConstraintCategory::ClosureBounds => "closure body ", @@ -84,7 +84,7 @@ impl<'tcx> RegionErrors<'tcx> { #[track_caller] pub fn push(&mut self, val: impl Into>) { let val = val.into(); - self.1.sess.delay_span_bug(DUMMY_SP, format!("{val:?}")); + self.1.sess.span_delayed_bug(DUMMY_SP, format!("{val:?}")); self.0.push(val); } pub fn is_empty(&self) -> bool { @@ -95,6 +95,12 @@ impl<'tcx> RegionErrors<'tcx> { } } +impl std::fmt::Debug for RegionErrors<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("RegionErrors").field(&self.0).finish() + } +} + #[derive(Clone, Debug)] pub(crate) enum RegionErrorKind<'tcx> { /// A generic bound failure for a type test (`T: 'a`). @@ -181,8 +187,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// Returns `true` if a closure is inferred to be an `FnMut` closure. fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { - if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref() - && let ty::BoundRegionKind::BrEnv = free_region.bound_region + if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref() + && let ty::BoundRegionKind::BrEnv = late_param.bound_region && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty { return args.as_closure().kind() == ty::ClosureKind::FnMut; @@ -209,7 +215,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .map(|placeholder| { if let Some(id) = placeholder.bound.kind.get_id() && let Some(placeholder_id) = id.as_local() - && let gat_hir_id = hir.local_def_id_to_hir_id(placeholder_id) + && let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id) && let Some(generics_impl) = hir.get_parent(gat_hir_id).generics() { Some((gat_hir_id, generics_impl)) @@ -230,7 +236,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if bound_generic_params .iter() - .rfind(|bgp| hir.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id) + .rfind(|bgp| self.infcx.tcx.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id) .is_some() { for bound in *bounds { @@ -599,7 +605,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let captured_place = &self.upvars[upvar_field.index()].place; - let defined_hir = match captured_place.place.base { + let defined_hir = match captured_place.base { PlaceBase::Local(hirid) => Some(hirid), PlaceBase::Upvar(upvar) => Some(upvar.var_path.hir_id), _ => None, @@ -644,14 +650,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &self.upvars, errci.fr, ); let outlived_fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( self.infcx.tcx, - &self.body, + self.body, &self.local_names, &self.upvars, errci.outlived_fr, @@ -757,7 +763,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let err = LifetimeOutliveErr { span: *span }; let mut diag = self.infcx.tcx.sess.create_err(err); - let fr_name = self.give_region_a_name(*fr).unwrap(); + // In certain scenarios, such as the one described in issue #118021, + // we might encounter a lifetime that cannot be named. + // These situations are bound to result in errors. + // To prevent an immediate ICE, we opt to create a dummy name instead. + let fr_name = self.give_region_a_name(*fr).unwrap_or(RegionName { + name: kw::UnderscoreLifetime, + source: RegionNameSource::Static, + }); fr_name.highlight_region_name(&mut diag); let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap(); outlived_fr_name.highlight_region_name(&mut diag); @@ -958,7 +971,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { for found_did in found_dids { let mut traits = vec![]; let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); - hir_v.visit_ty(&self_ty); + hir_v.visit_ty(self_ty); debug!("trait spans found: {:?}", traits); for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); @@ -995,7 +1008,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .infcx .tcx .is_suitable_region(sub) - .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.boundregion)) + .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.bound_region)) else { return; }; @@ -1004,7 +1017,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .infcx .tcx .is_suitable_region(sup) - .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.boundregion)) + .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.bound_region)) else { return; }; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index d38cfbc54d7ac..977a5d5d50d61 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -23,14 +23,14 @@ pub(crate) struct RegionName { } /// Denotes the source of a region that is named by a `RegionName`. For example, a free region that -/// was named by the user would get `NamedFreeRegion` and `'static` lifetime would get `Static`. +/// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get `Static`. /// This helps to print the right kinds of diagnostics. #[derive(Debug, Clone)] pub(crate) enum RegionNameSource { /// A bound (not free) region that was instantiated at the def site (not an HRTB). - NamedEarlyBoundRegion(Span), + NamedEarlyParamRegion(Span), /// A free region that the user has a name (`'a`) for. - NamedFreeRegion(Span), + NamedLateParamRegion(Span), /// The `'static` region. Static, /// The free region corresponding to the environment of a closure. @@ -69,8 +69,8 @@ pub(crate) enum RegionNameHighlight { impl RegionName { pub(crate) fn was_named(&self) -> bool { match self.source { - RegionNameSource::NamedEarlyBoundRegion(..) - | RegionNameSource::NamedFreeRegion(..) + RegionNameSource::NamedEarlyParamRegion(..) + | RegionNameSource::NamedLateParamRegion(..) | RegionNameSource::Static => true, RegionNameSource::SynthesizedFreeEnvRegion(..) | RegionNameSource::AnonRegionFromArgument(..) @@ -85,8 +85,8 @@ impl RegionName { pub(crate) fn span(&self) -> Option { match self.source { RegionNameSource::Static => None, - RegionNameSource::NamedEarlyBoundRegion(span) - | RegionNameSource::NamedFreeRegion(span) + RegionNameSource::NamedEarlyParamRegion(span) + | RegionNameSource::NamedLateParamRegion(span) | RegionNameSource::SynthesizedFreeEnvRegion(span, _) | RegionNameSource::AnonRegionFromUpvar(span, _) | RegionNameSource::AnonRegionFromYieldTy(span, _) @@ -104,8 +104,8 @@ impl RegionName { pub(crate) fn highlight_region_name(&self, diag: &mut Diagnostic) { match &self.source { - RegionNameSource::NamedFreeRegion(span) - | RegionNameSource::NamedEarlyBoundRegion(span) => { + RegionNameSource::NamedLateParamRegion(span) + | RegionNameSource::NamedEarlyParamRegion(span) => { diag.span_label(*span, format!("lifetime `{self}` defined here")); } RegionNameSource::SynthesizedFreeEnvRegion(span, note) => { @@ -199,7 +199,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } pub(crate) fn mir_hir_id(&self) -> hir::HirId { - self.infcx.tcx.hir().local_def_id_to_hir_id(self.mir_def_id()) + self.infcx.tcx.local_def_id_to_hir_id(self.mir_def_id()) } /// Generate a synthetic region named `'N`, where `N` is the next value of the counter. Then, @@ -280,28 +280,31 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { debug!("give_region_a_name: error_region = {:?}", error_region); match *error_region { - ty::ReEarlyBound(ebr) => ebr.has_name().then(|| { + ty::ReEarlyParam(ebr) => ebr.has_name().then(|| { let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP); - RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyBoundRegion(span) } + RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyParamRegion(span) } }), ty::ReStatic => { Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static }) } - ty::ReFree(free_region) => match free_region.bound_region { + ty::ReLateParam(late_param) => match late_param.bound_region { ty::BoundRegionKind::BrNamed(region_def_id, name) => { // Get the span to point to, even if we don't use the name. let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP); debug!( "bound region named: {:?}, is_named: {:?}", name, - free_region.bound_region.is_named() + late_param.bound_region.is_named() ); - if free_region.bound_region.is_named() { + if late_param.bound_region.is_named() { // A named region that is actually named. - Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) }) + Some(RegionName { + name, + source: RegionNameSource::NamedLateParamRegion(span), + }) } else if tcx.asyncness(self.mir_hir_id().owner).is_async() { // If we spuriously thought that the region is named, we should let the // system generate a true name for error messages. Currently this can @@ -357,7 +360,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty::BoundRegionKind::BrAnon => None, }, - ty::ReLateBound(..) + ty::ReBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased @@ -384,7 +387,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys [implicit_inputs + argument_index]; let (_, span) = self.regioncx.get_argument_name_and_span_for_region( - &self.body, + self.body, &self.local_names, argument_index, ); @@ -616,8 +619,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { _, ) => { // HIR lowering sometimes doesn't catch this in erroneous - // programs, so we need to use delay_span_bug here. See #82126. - self.infcx.tcx.sess.delay_span_bug( + // programs, so we need to use span_delayed_bug here. See #82126. + self.infcx.tcx.sess.span_delayed_bug( hir_arg.span(), format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"), ); @@ -847,7 +850,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { &self, fr: RegionVid, ) -> Option { - let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else { + let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else { return None; }; if region.has_name() { @@ -862,7 +865,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let found = tcx .any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| { - *r == ty::ReEarlyBound(region) + *r == ty::ReEarlyParam(region) }); Some(RegionName { @@ -881,7 +884,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { &self, fr: RegionVid, ) -> Option { - let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else { + let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else { return None; }; if region.has_name() { @@ -943,7 +946,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { &self, clauses: &[ty::Clause<'tcx>], ty: Ty<'tcx>, - region: ty::EarlyBoundRegion, + region: ty::EarlyParamRegion, ) -> bool { let tcx = self.infcx.tcx; ty.walk().any(|arg| { @@ -956,7 +959,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty::ClauseKind::Projection(data) if data.projection_ty.self_ty() == ty => {} _ => return false, } - tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyBound(region)) + tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region)) }) } else { false diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 3a104c52431ed..28e07f2a81edd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -2,10 +2,9 @@ #![deny(rustc::diagnostic_outside_of_impl)] use crate::region_infer::RegionInferenceContext; -use crate::Upvar; use rustc_index::IndexSlice; use rustc_middle::mir::{Body, Local}; -use rustc_middle::ty::{RegionVid, TyCtxt}; +use rustc_middle::ty::{self, RegionVid, TyCtxt}; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -15,7 +14,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { tcx: TyCtxt<'tcx>, body: &Body<'tcx>, local_names: &IndexSlice>, - upvars: &[Upvar<'tcx>], + upvars: &[&ty::CapturedPlace<'tcx>], fr: RegionVid, ) -> Option<(Option, Span)> { debug!("get_var_name_and_span_for_region(fr={fr:?})"); @@ -66,10 +65,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn get_upvar_name_and_span_for_region( &self, tcx: TyCtxt<'tcx>, - upvars: &[Upvar<'tcx>], + upvars: &[&ty::CapturedPlace<'tcx>], upvar_index: usize, ) -> (Symbol, Span) { - let upvar_hir_id = upvars[upvar_index].place.get_root_variable(); + let upvar_hir_id = upvars[upvar_index].get_root_variable(); debug!("get_upvar_name_and_span_for_region: upvar_hir_id={upvar_hir_id:?}"); let upvar_name = tcx.hir().name(upvar_hir_id); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 1a74582389d1e..3d3fd412ae0d1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1,8 +1,8 @@ //! This query borrow-checks the MIR to (further) ensure it is not broken. #![allow(internal_features)] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(let_chains)] @@ -22,8 +22,7 @@ extern crate tracing; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; -use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; +use rustc_errors::{Diagnostic, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::{BitSet, ChunkedBitSet}; @@ -35,7 +34,7 @@ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::traits::DefiningAnchor; -use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use rustc_target::abi::FieldIdx; @@ -43,6 +42,7 @@ use rustc_target::abi::FieldIdx; use smallvec::SmallVec; use std::cell::RefCell; use std::collections::BTreeMap; +use std::marker::PhantomData; use std::ops::Deref; use std::rc::Rc; @@ -65,19 +65,18 @@ use self::path_utils::*; pub mod borrow_set; mod borrowck_errors; -mod constraint_generation; mod constraints; mod dataflow; mod def_use; mod diagnostics; mod facts; -mod invalidation; mod location; mod member_constraints; mod nll; mod path_utils; mod place_ext; mod places_conflict; +mod polonius; mod prefixes; mod region_infer; mod renumber; @@ -98,19 +97,10 @@ use places_conflict::{places_conflict, PlaceConflictBias}; use region_infer::RegionInferenceContext; use renumber::RegionCtxt; -fluent_messages! { "../messages.ftl" } - -// FIXME(eddyb) perhaps move this somewhere more centrally. -#[derive(Debug)] -struct Upvar<'tcx> { - place: CapturedPlace<'tcx>, - - /// If true, the capture is behind a reference. - by_ref: bool, -} +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } /// Associate some local constants with the `'tcx` lifetime -struct TyCtxtConsts<'tcx>(TyCtxt<'tcx>); +struct TyCtxtConsts<'tcx>(PhantomData<&'tcx ()>); impl<'tcx> TyCtxtConsts<'tcx> { const DEREF_PROJECTION: &'tcx [PlaceElem<'tcx>; 1] = &[ProjectionElem::Deref]; } @@ -135,7 +125,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { return tcx.arena.alloc(result); } - let hir_owner = tcx.hir().local_def_id_to_hir_id(def).owner; + let hir_owner = tcx.local_def_id_to_hir_id(def).owner; let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); @@ -193,18 +183,6 @@ fn do_mir_borrowck<'tcx>( infcx.set_tainted_by_errors(e); errors.set_tainted_by_errors(e); } - let upvars: Vec<_> = tcx - .closure_captures(def) - .iter() - .map(|&captured_place| { - let capture = captured_place.info.capture_kind; - let by_ref = match capture { - ty::UpvarCapture::ByValue => false, - ty::UpvarCapture::ByRef(..) => true, - }; - Upvar { place: captured_place.clone(), by_ref } - }) - .collect(); // Replace all regions with fresh inference variables. This // requires first making our own copy of the MIR. This copy will @@ -216,21 +194,20 @@ fn do_mir_borrowck<'tcx>( nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted); let body = &body_owned; // no further changes - let location_table_owned = LocationTable::new(body); - let location_table = &location_table_owned; + let location_table = LocationTable::new(body); - let move_data = MoveData::gather_moves(&body, tcx, param_env, |_| true); + let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); let promoted_move_data = promoted .iter_enumerated() - .map(|(idx, body)| (idx, MoveData::gather_moves(&body, tcx, param_env, |_| true))); + .map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, param_env, |_| true))); let mdpe = MoveDataParamEnv { move_data, param_env }; - let mut flow_inits = MaybeInitializedPlaces::new(tcx, &body, &mdpe) - .into_engine(tcx, &body) + let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) + .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint() - .into_results_cursor(&body); + .into_results_cursor(body); let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure(); let borrow_set = @@ -249,24 +226,24 @@ fn do_mir_borrowck<'tcx>( free_regions, body, &promoted, - location_table, + &location_table, param_env, &mut flow_inits, &mdpe.move_data, &borrow_set, - &upvars, + tcx.closure_captures(def), consumer_options, ); // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. - nll::dump_mir_results(&infcx, &body, ®ioncx, &opt_closure_req); + nll::dump_mir_results(&infcx, body, ®ioncx, &opt_closure_req); // We also have a `#[rustc_regions]` annotation that causes us to dump // information. nll::dump_annotation( &infcx, - &body, + body, ®ioncx, &opt_closure_req, &opaque_type_values, @@ -288,7 +265,7 @@ fn do_mir_borrowck<'tcx>( .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint(); - let flow_ever_inits = EverInitializedPlaces::new(tcx, body, &mdpe) + let flow_ever_inits = EverInitializedPlaces::new(body, &mdpe) .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint(); @@ -313,7 +290,7 @@ fn do_mir_borrowck<'tcx>( param_env, body: promoted_body, move_data: &move_data, - location_table, // no need to create a real one for the promoted, it is not used + location_table: &location_table, // no need to create a real one for the promoted, it is not used movable_coroutine, fn_self_span_reported: Default::default(), locals_are_invalidated_at_exit, @@ -324,7 +301,7 @@ fn do_mir_borrowck<'tcx>( used_mut: Default::default(), used_mut_upvars: SmallVec::new(), borrow_set: Rc::clone(&borrow_set), - upvars: Vec::new(), + upvars: &[], local_names: IndexVec::from_elem(None, &promoted_body.local_decls), region_names: RefCell::default(), next_region_name: RefCell::new(1), @@ -354,7 +331,7 @@ fn do_mir_borrowck<'tcx>( param_env, body, move_data: &mdpe.move_data, - location_table, + location_table: &location_table, movable_coroutine, locals_are_invalidated_at_exit, fn_self_span_reported: Default::default(), @@ -365,7 +342,7 @@ fn do_mir_borrowck<'tcx>( used_mut: Default::default(), used_mut_upvars: SmallVec::new(), borrow_set: Rc::clone(&borrow_set), - upvars, + upvars: tcx.closure_captures(def), local_names, region_names: RefCell::default(), next_region_name: RefCell::new(1), @@ -456,7 +433,7 @@ fn do_mir_borrowck<'tcx>( promoted, borrow_set, region_inference_context: regioncx, - location_table: polonius_input.as_ref().map(|_| location_table_owned), + location_table: polonius_input.as_ref().map(|_| location_table), input_facts: polonius_input, output_facts, })) @@ -584,7 +561,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> { borrow_set: Rc>, /// Information about upvars not necessarily preserved in types or MIR - upvars: Vec>, + upvars: &'tcx [&'tcx ty::CapturedPlace<'tcx>], /// Names of local (user) variables (extracted from `var_debug_info`). local_names: IndexVec>, @@ -846,7 +823,7 @@ use self::ReadOrWrite::{Activation, Read, Reservation, Write}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum ArtificialField { ArrayLength, - ShallowBorrow, + FakeBorrow, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -1041,9 +1018,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { flow_state: &Flows<'cx, 'tcx>, ) -> bool { let mut error_reported = false; - let tcx = self.infcx.tcx; - let body = self.body; - let borrow_set = self.borrow_set.clone(); + let borrow_set = Rc::clone(&self.borrow_set); // Use polonius output if it has been enabled. let mut polonius_output; @@ -1060,8 +1035,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { each_borrow_involving_path( self, - tcx, - body, + self.infcx.tcx, + self.body, location, (sd, place_span.0), &borrow_set, @@ -1085,18 +1060,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Control::Continue } - (Read(_), BorrowKind::Shared | BorrowKind::Shallow) - | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => { + (Read(_), BorrowKind::Shared | BorrowKind::Fake) + | (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => { Control::Continue } - (Reservation(_), BorrowKind::Shallow | BorrowKind::Shared) => { + (Reservation(_), BorrowKind::Fake | BorrowKind::Shared) => { // This used to be a future compatibility warning (to be // disallowed on NLL). See rust-lang/rust#56254 Control::Continue } - (Write(WriteKind::Move), BorrowKind::Shallow) => { + (Write(WriteKind::Move), BorrowKind::Fake) => { // Handled by initialization checks. Control::Continue } @@ -1204,8 +1179,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match rvalue { &Rvalue::Ref(_ /*rgn*/, bk, place) => { let access_kind = match bk { - BorrowKind::Shallow => { - (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) + BorrowKind::Fake => { + (Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk))) } BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), BorrowKind::Mut { .. } => { @@ -1226,7 +1201,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { flow_state, ); - let action = if bk == BorrowKind::Shallow { + let action = if bk == BorrowKind::Fake { InitializationRequiringAction::MatchOn } else { InitializationRequiringAction::Borrow @@ -1538,7 +1513,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if places_conflict::borrow_conflicts_with_place( self.infcx.tcx, - &self.body, + self.body, place, borrow.kind, root_place, @@ -1583,7 +1558,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // only mutable borrows should be 2-phase assert!(match borrow.kind { - BorrowKind::Shared | BorrowKind::Shallow => false, + BorrowKind::Shared | BorrowKind::Fake => false, BorrowKind::Mut { .. } => true, }); @@ -2142,24 +2117,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | WriteKind::Replace | WriteKind::StorageDeadOrDrop | WriteKind::MutableBorrow(BorrowKind::Shared) - | WriteKind::MutableBorrow(BorrowKind::Shallow), + | WriteKind::MutableBorrow(BorrowKind::Fake), ) | Write( WriteKind::Move | WriteKind::Replace | WriteKind::StorageDeadOrDrop | WriteKind::MutableBorrow(BorrowKind::Shared) - | WriteKind::MutableBorrow(BorrowKind::Shallow), + | WriteKind::MutableBorrow(BorrowKind::Fake), ) => { if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err() && !self.has_buffered_errors() { // rust-lang/rust#46908: In pure NLL mode this code path should be - // unreachable, but we use `delay_span_bug` because we can hit this when + // unreachable, but we use `span_delayed_bug` because we can hit this when // dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug` // enabled. We don't want to ICE for that case, as other errors will have // been emitted (#52262). - self.infcx.tcx.sess.delay_span_bug( + self.infcx.tcx.sess.span_delayed_bug( span, format!( "Accessing `{place:?}` with the kind `{kind:?}` shouldn't be possible", @@ -2173,7 +2148,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return false; } Read( - ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow) + ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake) | ReadKind::Copy, ) => { // Access authorized @@ -2193,7 +2168,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If this is a mutate access to an immutable local variable with no projections // report the error as an illegal reassignment let init = &self.move_data.inits[init_index]; - let assigned_span = init.span(&self.body); + let assigned_span = init.span(self.body); self.report_illegal_reassignment(location, (place, span), assigned_span, place); } else { self.report_mutability_error(place, span, the_place_err, error_access, location) @@ -2294,7 +2269,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // unique path to the `&mut` hir::Mutability::Mut => { let mode = match self.is_upvar_field_projection(place) { - Some(field) if self.upvars[field.index()].by_ref => { + Some(field) + if self.upvars[field.index()].is_by_ref() => + { is_local_mutation_allowed } _ => LocalMutationIsAllowed::Yes, @@ -2342,7 +2319,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place={:?}, place_base={:?}", upvar, is_local_mutation_allowed, place, place_base ); - match (upvar.place.mutability, is_local_mutation_allowed) { + match (upvar.mutability, is_local_mutation_allowed) { ( Mutability::Not, LocalMutationIsAllowed::No @@ -2451,7 +2428,7 @@ mod error { pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) { if let None = self.tainted_by_errors { - self.tainted_by_errors = Some(self.tcx.sess.delay_span_bug( + self.tainted_by_errors = Some(self.tcx.sess.span_delayed_bug( t.span.clone_ignoring_labels(), "diagnostic buffered but not emitted", )) diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs index 0e669abfd14aa..6f09393169f3d 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/location.rs @@ -20,6 +20,7 @@ pub struct LocationTable { } rustc_index::newtype_index! { + #[orderable] #[debug_format = "LocationIndex({})"] pub struct LocationIndex {} } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 0ea4401a87847..c88d9d81fe134 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -2,16 +2,17 @@ #![deny(rustc::diagnostic_outside_of_impl)] //! The entry point of the NLL borrow checker. +use polonius_engine::{Algorithm, Output}; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::LocalDefId; use rustc_index::IndexSlice; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; -use rustc_middle::mir::{ - Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, - START_BLOCK, -}; +use rustc_middle::mir::{Body, ClosureOutlivesSubject, ClosureRegionRequirements, Promoted}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::MoveData; +use rustc_mir_dataflow::ResultsCursor; use rustc_span::symbol::sym; use std::env; use std::io; @@ -19,25 +20,18 @@ use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; -use polonius_engine::{Algorithm, Output}; - -use rustc_mir_dataflow::impls::MaybeInitializedPlaces; -use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData}; -use rustc_mir_dataflow::ResultsCursor; - use crate::{ borrow_set::BorrowSet, - constraint_generation, consumers::ConsumerOptions, diagnostics::RegionErrors, facts::{AllFacts, AllFactsExt, RustcFacts}, - invalidation, location::LocationTable, + polonius, region_infer::{values::RegionValueElements, RegionInferenceContext}, renumber, type_check::{self, MirTypeckRegionConstraints, MirTypeckResults}, universal_regions::UniversalRegions, - BorrowckInferCtxt, Upvar, + BorrowckInferCtxt, }; pub type PoloniusOutput = Output; @@ -78,81 +72,6 @@ pub(crate) fn replace_regions_in_mir<'tcx>( universal_regions } -// This function populates an AllFacts instance with base facts related to -// MovePaths and needed for the move analysis. -fn populate_polonius_move_facts( - all_facts: &mut AllFacts, - move_data: &MoveData<'_>, - location_table: &LocationTable, - body: &Body<'_>, -) { - all_facts - .path_is_var - .extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l))); - - for (child, move_path) in move_data.move_paths.iter_enumerated() { - if let Some(parent) = move_path.parent { - all_facts.child_path.push((child, parent)); - } - } - - let fn_entry_start = - location_table.start_index(Location { block: START_BLOCK, statement_index: 0 }); - - // initialized_at - for init in move_data.inits.iter() { - match init.location { - InitLocation::Statement(location) => { - let block_data = &body[location.block]; - let is_terminator = location.statement_index == block_data.statements.len(); - - if is_terminator && init.kind == InitKind::NonPanicPathOnly { - // We are at the terminator of an init that has a panic path, - // and where the init should not happen on panic - - for successor in block_data.terminator().successors() { - if body[successor].is_cleanup { - continue; - } - - // The initialization happened in (or rather, when arriving at) - // the successors, but not in the unwind block. - let first_statement = Location { block: successor, statement_index: 0 }; - all_facts - .path_assigned_at_base - .push((init.path, location_table.start_index(first_statement))); - } - } else { - // In all other cases, the initialization just happens at the - // midpoint, like any other effect. - all_facts - .path_assigned_at_base - .push((init.path, location_table.mid_index(location))); - } - } - // Arguments are initialized on function entry - InitLocation::Argument(local) => { - assert!(body.local_kind(local) == LocalKind::Arg); - all_facts.path_assigned_at_base.push((init.path, fn_entry_start)); - } - } - } - - for (local, path) in move_data.rev_lookup.iter_locals_enumerated() { - if body.local_kind(local) != LocalKind::Arg { - // Non-arguments start out deinitialised; we simulate this with an - // initial move: - all_facts.path_moved_at_base.push((path, fn_entry_start)); - } - } - - // moved_out_at - // deinitialisation is assumed to always happen! - all_facts - .path_moved_at_base - .extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); -} - /// Computes the (non-lexical) regions from the input MIR. /// /// This may result in errors being reported. @@ -166,7 +85,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>, move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, - upvars: &[Upvar<'tcx>], + upvars: &[&ty::CapturedPlace<'tcx>], consumer_options: Option, ) -> NllOutput<'tcx> { let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled(); @@ -179,70 +98,26 @@ pub(crate) fn compute_regions<'cx, 'tcx>( let universal_regions = Rc::new(universal_regions); - let elements = &Rc::new(RegionValueElements::new(&body)); + let elements = &Rc::new(RegionValueElements::new(body)); // Run the MIR type-checker. - let MirTypeckResults { - constraints, - universal_region_relations, - opaque_type_values, - live_loans, - } = type_check::type_check( - infcx, - param_env, - body, - promoted, - &universal_regions, - location_table, - borrow_set, - &mut all_facts, - flow_inits, - move_data, - elements, - upvars, - polonius_input, - ); - - if let Some(all_facts) = &mut all_facts { - let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation"); - all_facts.universal_region.extend(universal_regions.universal_regions()); - populate_polonius_move_facts(all_facts, move_data, location_table, &body); - - // Emit universal regions facts, and their relations, for Polonius. - // - // 1: universal regions are modeled in Polonius as a pair: - // - the universal region vid itself. - // - a "placeholder loan" associated to this universal region. Since they don't exist in - // the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index - // added to the existing number of loans, as if they succeeded them in the set. - // - let borrow_count = borrow_set.len(); - debug!( - "compute_regions: polonius placeholders, num_universals={}, borrow_count={}", - universal_regions.len(), - borrow_count + let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } = + type_check::type_check( + infcx, + param_env, + body, + promoted, + &universal_regions, + location_table, + borrow_set, + &mut all_facts, + flow_inits, + move_data, + elements, + upvars, + polonius_input, ); - for universal_region in universal_regions.universal_regions() { - let universal_region_idx = universal_region.index(); - let placeholder_loan_idx = borrow_count + universal_region_idx; - all_facts.placeholder.push((universal_region, placeholder_loan_idx.into())); - } - - // 2: the universal region relations `outlives` constraints are emitted as - // `known_placeholder_subset` facts. - for (fr1, fr2) in universal_region_relations.known_outlives() { - if fr1 != fr2 { - debug!( - "compute_regions: emitting polonius `known_placeholder_subset` \ - fr1={:?}, fr2={:?}", - fr1, fr2 - ); - all_facts.known_placeholder_subset.push((fr1, fr2)); - } - } - } - // Create the region inference context, taking ownership of the // region inference data that was contained in `infcx`, and the // base constraints generated by the type-check. @@ -250,7 +125,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( let MirTypeckRegionConstraints { placeholder_indices, placeholder_index_to_region: _, - mut liveness_constraints, + liveness_constraints, outlives_constraints, member_constraints, universe_causes, @@ -258,13 +133,16 @@ pub(crate) fn compute_regions<'cx, 'tcx>( } = constraints; let placeholder_indices = Rc::new(placeholder_indices); - constraint_generation::generate_constraints( - infcx, - &mut liveness_constraints, + // If requested, emit legacy polonius facts. + polonius::emit_facts( &mut all_facts, + infcx.tcx, location_table, - &body, + body, borrow_set, + move_data, + &universal_regions, + &universal_region_relations, ); let mut regioncx = RegionInferenceContext::new( @@ -279,17 +157,12 @@ pub(crate) fn compute_regions<'cx, 'tcx>( type_tests, liveness_constraints, elements, - live_loans, ); - // Generate various additional constraints. - invalidation::generate_invalidates(infcx.tcx, &mut all_facts, location_table, body, borrow_set); - - let def_id = body.source.def_id(); - - // Dump facts if requested. + // If requested: dump NLL facts, and run legacy polonius analysis. let polonius_output = all_facts.as_ref().and_then(|all_facts| { if infcx.tcx.sess.opts.unstable_opts.nll_facts { + let def_id = body.source.def_id(); let def_path = infcx.tcx.def_path(def_id); let dir_path = PathBuf::from(&infcx.tcx.sess.opts.unstable_opts.nll_facts_dir) .join(def_path.to_filename_friendly_no_crate()); @@ -302,7 +175,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( let algorithm = Algorithm::from_str(&algorithm).unwrap(); debug!("compute_regions: using polonius algorithm {:?}", algorithm); let _prof_timer = infcx.tcx.prof.generic_activity("polonius_analysis"); - Some(Rc::new(Output::compute(&all_facts, algorithm, false))) + Some(Rc::new(Output::compute(all_facts, algorithm, false))) } else { None } @@ -310,17 +183,17 @@ pub(crate) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let (closure_region_requirements, nll_errors) = - regioncx.solve(infcx, param_env, &body, polonius_output.clone()); + regioncx.solve(infcx, param_env, body, polonius_output.clone()); if !nll_errors.is_empty() { // Suppress unhelpful extra errors in `infer_opaque_types`. - infcx.set_tainted_by_errors(infcx.tcx.sess.delay_span_bug( + infcx.set_tainted_by_errors(infcx.tcx.sess.span_delayed_bug( body.span, "`compute_regions` tainted `infcx` with errors but did not emit any errors", )); } - let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values); + let remapped_opaque_tys = regioncx.infer_opaque_types(infcx, opaque_type_values); NllOutput { regioncx, @@ -407,7 +280,7 @@ pub(super) fn dump_annotation<'tcx>( let def_span = tcx.def_span(body.source.def_id()); let mut err = if let Some(closure_region_requirements) = closure_region_requirements { - let mut err = tcx.sess.diagnostic().span_note_diag(def_span, "external requirements"); + let mut err = tcx.sess.diagnostic().struct_span_note(def_span, "external requirements"); regioncx.annotate(tcx, &mut err); @@ -426,7 +299,7 @@ pub(super) fn dump_annotation<'tcx>( err } else { - let mut err = tcx.sess.diagnostic().span_note_diag(def_span, "no external requirements"); + let mut err = tcx.sess.diagnostic().struct_span_note(def_span, "no external requirements"); regioncx.annotate(tcx, &mut err); err diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index 51e318f085438..2d997dfadf004 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -4,7 +4,6 @@ use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; use crate::places_conflict; use crate::AccessDepth; use crate::BorrowIndex; -use crate::Upvar; use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::BorrowKind; use rustc_middle::mir::{BasicBlock, Body, Location, Place, PlaceRef, ProjectionElem}; @@ -150,7 +149,7 @@ pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool { /// of a closure type. pub(crate) fn is_upvar_field_projection<'tcx>( tcx: TyCtxt<'tcx>, - upvars: &[Upvar<'tcx>], + upvars: &[&rustc_middle::ty::CapturedPlace<'tcx>], place_ref: PlaceRef<'tcx>, body: &Body<'tcx>, ) -> Option { @@ -166,7 +165,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>( Some((place_base, ProjectionElem::Field(field, _ty))) => { let base_ty = place_base.ty(body, tcx).ty; if (base_ty.is_closure() || base_ty.is_coroutine()) - && (!by_ref || upvars[field.index()].by_ref) + && (!by_ref || upvars[field.index()].is_by_ref()) { Some(field) } else { diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 539d0837659c8..777ebf0d438dc 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -204,7 +204,7 @@ fn place_components_conflict<'tcx>( match (elem, &base_ty.kind(), access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) - | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => { + | (_, _, Shallow(Some(ArtificialField::FakeBorrow))) => { // The array length is like additional fields on the // type; it does not overlap any existing data there. // Furthermore, if cannot actually be a prefix of any @@ -273,10 +273,10 @@ fn place_components_conflict<'tcx>( // If the second example, where we did, then we still know // that the borrow can access a *part* of our place that // our access cares about, so we still have a conflict. - if borrow_kind == BorrowKind::Shallow + if borrow_kind == BorrowKind::Fake && borrow_place.projection.len() < access_place.projection.len() { - debug!("borrow_conflicts_with_place: shallow borrow"); + debug!("borrow_conflicts_with_place: fake borrow"); false } else { debug!("borrow_conflicts_with_place: full borrow, CONFLICT"); diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs similarity index 91% rename from compiler/rustc_borrowck/src/invalidation.rs rename to compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 7b5b52e39b121..232bd7418259e 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -14,34 +14,21 @@ use crate::{ ReadOrWrite, Reservation, Shallow, Write, WriteKind, }; -pub(super) fn generate_invalidates<'tcx>( +/// Emit `loan_invalidated_at` facts. +pub(super) fn emit_loan_invalidations<'tcx>( tcx: TyCtxt<'tcx>, - all_facts: &mut Option, + all_facts: &mut AllFacts, location_table: &LocationTable, body: &Body<'tcx>, borrow_set: &BorrowSet<'tcx>, ) { - if all_facts.is_none() { - // Nothing to do if we don't have any facts - return; - } - - if let Some(all_facts) = all_facts { - let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); - let dominators = body.basic_blocks.dominators(); - let mut ig = InvalidationGenerator { - all_facts, - borrow_set, - tcx, - location_table, - body: &body, - dominators, - }; - ig.visit_body(body); - } + let dominators = body.basic_blocks.dominators(); + let mut visitor = + LoanInvalidationsGenerator { all_facts, borrow_set, tcx, location_table, body, dominators }; + visitor.visit_body(body); } -struct InvalidationGenerator<'cx, 'tcx> { +struct LoanInvalidationsGenerator<'cx, 'tcx> { tcx: TyCtxt<'tcx>, all_facts: &'cx mut AllFacts, location_table: &'cx LocationTable, @@ -52,7 +39,7 @@ struct InvalidationGenerator<'cx, 'tcx> { /// Visits the whole MIR and generates `invalidates()` facts. /// Most of the code implementing this was stolen from `borrow_check/mod.rs`. -impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { +impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { self.check_activations(location); @@ -214,7 +201,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } } -impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { +impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> { /// Simulates mutation of a place. fn mutate_place(&mut self, location: Location, place: Place<'tcx>, kind: AccessDepth) { self.access_place( @@ -253,8 +240,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { match rvalue { &Rvalue::Ref(_ /*rgn*/, bk, place) => { let access_kind = match bk { - BorrowKind::Shallow => { - (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) + BorrowKind::Fake => { + (Shallow(Some(ArtificialField::FakeBorrow)), Read(ReadKind::Borrow(bk))) } BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))), BorrowKind::Mut { .. } => { @@ -348,20 +335,16 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { rw: ReadOrWrite, ) { debug!( - "invalidation::check_access_for_conflict(location={:?}, place={:?}, sd={:?}, \ - rw={:?})", + "check_access_for_conflict(location={:?}, place={:?}, sd={:?}, rw={:?})", location, place, sd, rw, ); - let tcx = self.tcx; - let body = self.body; - let borrow_set = self.borrow_set; each_borrow_involving_path( self, - tcx, - body, + self.tcx, + self.body, location, (sd, place), - borrow_set, + self.borrow_set, |_| true, |this, borrow_index, borrow| { match (rw, borrow.kind) { @@ -376,14 +359,14 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { // have already taken the reservation } - (Read(_), BorrowKind::Shallow | BorrowKind::Shared) - | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => { + (Read(_), BorrowKind::Fake | BorrowKind::Shared) + | (Read(ReadKind::Borrow(BorrowKind::Fake)), BorrowKind::Mut { .. }) => { // Reads don't invalidate shared or shallow borrows } (Read(_), BorrowKind::Mut { .. }) => { // Reading from mere reservations of mutable-borrows is OK. - if !is_active(&this.dominators, borrow, location) { + if !is_active(this.dominators, borrow, location) { // If the borrow isn't active yet, reads don't invalidate it assert!(allow_two_phase_borrow(borrow.kind)); return Control::Continue; @@ -422,7 +405,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { // only mutable borrows should be 2-phase assert!(match borrow.kind { - BorrowKind::Shared | BorrowKind::Shallow => false, + BorrowKind::Shared | BorrowKind::Fake => false, BorrowKind::Mut { .. } => true, }); diff --git a/compiler/rustc_borrowck/src/polonius/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/loan_kills.rs new file mode 100644 index 0000000000000..5df943837025e --- /dev/null +++ b/compiler/rustc_borrowck/src/polonius/loan_kills.rs @@ -0,0 +1,147 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::{ + Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, + Terminator, TerminatorKind, +}; +use rustc_middle::ty::TyCtxt; + +use crate::{borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict}; + +/// Emit `loan_killed_at` and `cfg_edge` facts at the same time. +pub(super) fn emit_loan_kills<'tcx>( + tcx: TyCtxt<'tcx>, + all_facts: &mut AllFacts, + location_table: &LocationTable, + body: &Body<'tcx>, + borrow_set: &BorrowSet<'tcx>, +) { + let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, all_facts, body }; + for (bb, data) in body.basic_blocks.iter_enumerated() { + visitor.visit_basic_block_data(bb, data); + } +} + +struct LoanKillsGenerator<'cx, 'tcx> { + tcx: TyCtxt<'tcx>, + all_facts: &'cx mut AllFacts, + location_table: &'cx LocationTable, + borrow_set: &'cx BorrowSet<'tcx>, + body: &'cx Body<'tcx>, +} + +impl<'cx, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'cx, 'tcx> { + fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { + // Also record CFG facts here. + self.all_facts.cfg_edge.push(( + self.location_table.start_index(location), + self.location_table.mid_index(location), + )); + + self.all_facts.cfg_edge.push(( + self.location_table.mid_index(location), + self.location_table.start_index(location.successor_within_block()), + )); + + // If there are borrows on this now dead local, we need to record them as `killed`. + if let StatementKind::StorageDead(local) = statement.kind { + self.record_killed_borrows_for_local(local, location); + } + + self.super_statement(statement, location); + } + + fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { + // When we see `X = ...`, then kill borrows of + // `(*X).foo` and so forth. + self.record_killed_borrows_for_place(*place, location); + self.super_assign(place, rvalue, location); + } + + fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { + // Also record CFG facts here. + self.all_facts.cfg_edge.push(( + self.location_table.start_index(location), + self.location_table.mid_index(location), + )); + + let successor_blocks = terminator.successors(); + self.all_facts.cfg_edge.reserve(successor_blocks.size_hint().0); + for successor_block in successor_blocks { + self.all_facts.cfg_edge.push(( + self.location_table.mid_index(location), + self.location_table.start_index(successor_block.start_location()), + )); + } + + // A `Call` terminator's return value can be a local which has borrows, + // so we need to record those as `killed` as well. + if let TerminatorKind::Call { destination, .. } = terminator.kind { + self.record_killed_borrows_for_place(destination, location); + } + + self.super_terminator(terminator, location); + } +} + +impl<'tcx> LoanKillsGenerator<'_, 'tcx> { + /// Records the borrows on the specified place as `killed`. For example, when assigning to a + /// local, or on a call's return destination. + fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) { + // Depending on the `Place` we're killing: + // - if it's a local, or a single deref of a local, + // we kill all the borrows on the local. + // - if it's a deeper projection, we have to filter which + // of the borrows are killed: the ones whose `borrowed_place` + // conflicts with the `place`. + match place.as_ref() { + PlaceRef { local, projection: &[] } + | PlaceRef { local, projection: &[ProjectionElem::Deref] } => { + debug!( + "Recording `killed` facts for borrows of local={:?} at location={:?}", + local, location + ); + + self.record_killed_borrows_for_local(local, location); + } + + PlaceRef { local, projection: &[.., _] } => { + // Kill conflicting borrows of the innermost local. + debug!( + "Recording `killed` facts for borrows of \ + innermost projected local={:?} at location={:?}", + local, location + ); + + if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { + for &borrow_index in borrow_indices { + let places_conflict = places_conflict::places_conflict( + self.tcx, + self.body, + self.borrow_set[borrow_index].borrowed_place, + place, + places_conflict::PlaceConflictBias::NoOverlap, + ); + + if places_conflict { + let location_index = self.location_table.mid_index(location); + self.all_facts.loan_killed_at.push((borrow_index, location_index)); + } + } + } + } + } + } + + /// Records the borrows on the specified local as `killed`. + fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) { + if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { + let location_index = self.location_table.mid_index(location); + self.all_facts.loan_killed_at.reserve(borrow_indices.len()); + for &borrow_index in borrow_indices { + self.all_facts.loan_killed_at.push((borrow_index, location_index)); + } + } + } +} diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs new file mode 100644 index 0000000000000..40126d50d57e6 --- /dev/null +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -0,0 +1,188 @@ +//! Functions dedicated to fact generation for the `-Zpolonius=legacy` datalog implementation. +//! +//! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature +//! parity. + +use rustc_middle::mir::{Body, LocalKind, Location, START_BLOCK}; +use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData}; + +use crate::borrow_set::BorrowSet; +use crate::facts::AllFacts; +use crate::location::LocationTable; +use crate::type_check::free_region_relations::UniversalRegionRelations; +use crate::universal_regions::UniversalRegions; + +mod loan_invalidations; +mod loan_kills; + +/// When requested, emit most of the facts needed by polonius: +/// - moves and assignments +/// - universal regions and their relations +/// - CFG points and edges +/// - loan kills +/// - loan invalidations +/// +/// The rest of the facts are emitted during typeck and liveness. +pub(crate) fn emit_facts<'tcx>( + all_facts: &mut Option, + tcx: TyCtxt<'tcx>, + location_table: &LocationTable, + body: &Body<'tcx>, + borrow_set: &BorrowSet<'tcx>, + move_data: &MoveData<'_>, + universal_regions: &UniversalRegions<'_>, + universal_region_relations: &UniversalRegionRelations<'_>, +) { + let Some(all_facts) = all_facts else { + // We don't do anything if there are no facts to fill. + return; + }; + let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); + emit_move_facts(all_facts, move_data, location_table, body); + emit_universal_region_facts( + all_facts, + borrow_set, + &universal_regions, + &universal_region_relations, + ); + emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set); + emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set); +} + +/// Emit facts needed for move/init analysis: moves and assignments. +fn emit_move_facts( + all_facts: &mut AllFacts, + move_data: &MoveData<'_>, + location_table: &LocationTable, + body: &Body<'_>, +) { + all_facts + .path_is_var + .extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l))); + + for (child, move_path) in move_data.move_paths.iter_enumerated() { + if let Some(parent) = move_path.parent { + all_facts.child_path.push((child, parent)); + } + } + + let fn_entry_start = + location_table.start_index(Location { block: START_BLOCK, statement_index: 0 }); + + // initialized_at + for init in move_data.inits.iter() { + match init.location { + InitLocation::Statement(location) => { + let block_data = &body[location.block]; + let is_terminator = location.statement_index == block_data.statements.len(); + + if is_terminator && init.kind == InitKind::NonPanicPathOnly { + // We are at the terminator of an init that has a panic path, + // and where the init should not happen on panic + + for successor in block_data.terminator().successors() { + if body[successor].is_cleanup { + continue; + } + + // The initialization happened in (or rather, when arriving at) + // the successors, but not in the unwind block. + let first_statement = Location { block: successor, statement_index: 0 }; + all_facts + .path_assigned_at_base + .push((init.path, location_table.start_index(first_statement))); + } + } else { + // In all other cases, the initialization just happens at the + // midpoint, like any other effect. + all_facts + .path_assigned_at_base + .push((init.path, location_table.mid_index(location))); + } + } + // Arguments are initialized on function entry + InitLocation::Argument(local) => { + assert!(body.local_kind(local) == LocalKind::Arg); + all_facts.path_assigned_at_base.push((init.path, fn_entry_start)); + } + } + } + + for (local, path) in move_data.rev_lookup.iter_locals_enumerated() { + if body.local_kind(local) != LocalKind::Arg { + // Non-arguments start out deinitialised; we simulate this with an + // initial move: + all_facts.path_moved_at_base.push((path, fn_entry_start)); + } + } + + // moved_out_at + // deinitialisation is assumed to always happen! + all_facts + .path_moved_at_base + .extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); +} + +/// Emit universal regions facts, and their relations. +fn emit_universal_region_facts( + all_facts: &mut AllFacts, + borrow_set: &BorrowSet<'_>, + universal_regions: &UniversalRegions<'_>, + universal_region_relations: &UniversalRegionRelations<'_>, +) { + // 1: universal regions are modeled in Polonius as a pair: + // - the universal region vid itself. + // - a "placeholder loan" associated to this universal region. Since they don't exist in + // the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index + // added to the existing number of loans, as if they succeeded them in the set. + // + all_facts.universal_region.extend(universal_regions.universal_regions()); + let borrow_count = borrow_set.len(); + debug!( + "emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}", + universal_regions.len(), + borrow_count + ); + + for universal_region in universal_regions.universal_regions() { + let universal_region_idx = universal_region.index(); + let placeholder_loan_idx = borrow_count + universal_region_idx; + all_facts.placeholder.push((universal_region, placeholder_loan_idx.into())); + } + + // 2: the universal region relations `outlives` constraints are emitted as + // `known_placeholder_subset` facts. + for (fr1, fr2) in universal_region_relations.known_outlives() { + if fr1 != fr2 { + debug!( + "emit_universal_region_facts: emitting polonius `known_placeholder_subset` \ + fr1={:?}, fr2={:?}", + fr1, fr2 + ); + all_facts.known_placeholder_subset.push((fr1, fr2)); + } + } +} + +/// Emit facts about loan invalidations. +fn emit_loan_invalidations_facts<'tcx>( + all_facts: &mut AllFacts, + tcx: TyCtxt<'tcx>, + location_table: &LocationTable, + body: &Body<'tcx>, + borrow_set: &BorrowSet<'tcx>, +) { + loan_invalidations::emit_loan_invalidations(tcx, all_facts, location_table, body, borrow_set); +} + +/// Emit facts about CFG points and edges, as well as locations where loans are killed. +fn emit_cfg_and_loan_kills_facts<'tcx>( + all_facts: &mut AllFacts, + tcx: TyCtxt<'tcx>, + location_table: &LocationTable, + body: &Body<'tcx>, + borrow_set: &BorrowSet<'tcx>, +) { + loan_kills::emit_loan_kills(tcx, all_facts, location_table, body, borrow_set); +} diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index 4d620ac9de615..cfbb2766c3397 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -67,7 +67,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { with_msg: &mut dyn FnMut(&str) -> io::Result<()>, ) -> io::Result<()> { for region in self.definitions.indices() { - let value = self.liveness_constraints.region_value_str(region); + let value = self.liveness_constraints.pretty_print_live_points(region); if value != "{}" { with_msg(&format!("{region:?} live at {value}"))?; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 05c2cbd49692c..b308cd82e547b 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -7,7 +7,6 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::scc::Sccs; use rustc_errors::Diagnostic; use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_index::bit_set::SparseBitMatrix; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::outlives::test_type_match; use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq}; @@ -22,18 +21,17 @@ use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; +use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph}; use crate::dataflow::BorrowIndex; use crate::{ - constraints::{ - graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet, - }, + constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet}, diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}, member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, nll::PoloniusOutput, region_infer::reverse_sccs::ReverseSccGraph, region_infer::values::{ - LivenessValues, PlaceholderIndices, PointIndex, RegionElement, RegionValueElements, - RegionValues, ToElementIndex, + LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues, + ToElementIndex, }, type_check::{free_region_relations::UniversalRegionRelations, Locations}, universal_regions::UniversalRegions, @@ -60,7 +58,7 @@ pub struct RegionInferenceContext<'tcx> { /// regions, these start out empty and steadily grow, though for /// each universally quantified region R they start out containing /// the entire CFG and `end(R)`. - liveness_constraints: LivenessValues, + liveness_constraints: LivenessValues, /// The outlives constraints computed by the type-check. constraints: Frozen>, @@ -121,9 +119,6 @@ pub struct RegionInferenceContext<'tcx> { /// Information about how the universally quantified regions in /// scope on this function relate to one another. universal_region_relations: Frozen>, - - /// The set of loans that are live at a given point in the CFG, when using `-Zpolonius=next`. - live_loans: SparseBitMatrix, } /// Each time that `apply_member_constraint` is successful, it appends @@ -152,6 +147,7 @@ pub(crate) struct AppliedMemberConstraint { pub(crate) member_constraint_index: NllMemberConstraintIndex, } +#[derive(Debug)] pub(crate) struct RegionDefinition<'tcx> { /// What kind of variable is this -- a free region? existential /// variable? etc. (See the `NllRegionVariableOrigin` for more @@ -333,9 +329,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { member_constraints_in: MemberConstraintSet<'tcx, RegionVid>, universe_causes: FxIndexMap>, type_tests: Vec>, - liveness_constraints: LivenessValues, + liveness_constraints: LivenessValues, elements: &Rc, - live_loans: SparseBitMatrix, ) -> Self { debug!("universal_regions: {:#?}", universal_regions); debug!("outlives constraints: {:#?}", outlives_constraints); @@ -360,7 +355,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut scc_values = RegionValues::new(elements, universal_regions.len(), &placeholder_indices); - for region in liveness_constraints.rows() { + for region in liveness_constraints.regions() { let scc = constraint_sccs.scc(region); scc_values.merge_liveness(scc, region, &liveness_constraints); } @@ -389,7 +384,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { type_tests, universal_regions, universal_region_relations, - live_loans, }; result.init_free_and_bound_regions(); @@ -688,6 +682,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { &mut errors_buffer, ); + debug!(?errors_buffer); + debug!(?outlives_requirements); + // In Polonius mode, the errors about missing universal region relations are in the output // and need to be emitted or propagated. Otherwise, we need to check whether the // constraints were too strong, and if so, emit or propagate those errors. @@ -701,10 +698,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer); } + debug!(?errors_buffer); + if errors_buffer.is_empty() { self.check_member_constraints(infcx, &mut errors_buffer); } + debug!(?errors_buffer); + let outlives_requirements = outlives_requirements.unwrap_or_default(); if outlives_requirements.is_empty() { @@ -1458,6 +1459,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { errors_buffer: &mut RegionErrors<'tcx>, ) { for (fr, fr_definition) in self.definitions.iter_enumerated() { + debug!(?fr, ?fr_definition); match fr_definition.origin { NllRegionVariableOrigin::FreeRegion => { // Go through each of the universal regions `fr` and check that @@ -1964,15 +1966,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { None } - /// Finds some region R such that `fr1: R` and `R` is live at `elem`. + /// Finds some region R such that `fr1: R` and `R` is live at `location`. #[instrument(skip(self), level = "trace", ret)] - pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid { + pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid { trace!(scc = ?self.constraint_sccs.scc(fr1)); trace!(universe = ?self.scc_universes[self.constraint_sccs.scc(fr1)]); self.find_constraint_paths_between_regions(fr1, |r| { - // First look for some `r` such that `fr1: r` and `r` is live at `elem` - trace!(?r, liveness_constraints=?self.liveness_constraints.region_value_str(r)); - self.liveness_constraints.contains(r, elem) + // First look for some `r` such that `fr1: r` and `r` is live at `location` + trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r)); + self.liveness_constraints.is_live_at(r, location) }) .or_else(|| { // If we fail to find that, we may find some `r` such that @@ -2293,19 +2295,21 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.constraint_sccs.as_ref() } - /// Returns whether the given SCC is live at all points: whether the representative is a + /// Access to the region graph, built from the outlives constraints. + pub(crate) fn region_graph(&self) -> RegionGraph<'_, 'tcx, graph::Normal> { + self.constraint_graph.region_graph(&self.constraints, self.universal_regions.fr_static) + } + + /// Returns whether the given region is considered live at all points: whether it is a /// placeholder or a free region. - pub(crate) fn scc_is_live_at_all_points(&self, scc: ConstraintSccIndex) -> bool { + pub(crate) fn is_region_live_at_all_points(&self, region: RegionVid) -> bool { // FIXME: there must be a cleaner way to find this information. At least, when // higher-ranked subtyping is abstracted away from the borrowck main path, we'll only // need to check whether this is a universal region. - let representative = self.scc_representatives[scc]; - let origin = self.var_infos[representative].origin; + let origin = self.region_definition(region).origin; let live_at_all_points = matches!( origin, - RegionVariableOrigin::Nll( - NllRegionVariableOrigin::Placeholder(_) | NllRegionVariableOrigin::FreeRegion - ) + NllRegionVariableOrigin::Placeholder(_) | NllRegionVariableOrigin::FreeRegion ); live_at_all_points } @@ -2315,7 +2319,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Note: for now, the sets of live loans is only available when using `-Zpolonius=next`. pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, location: Location) -> bool { let point = self.liveness_constraints.point_from_location(location); - self.live_loans.contains(point, loan_idx) + self.liveness_constraints.is_loan_live_at(loan_idx, point) } } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index fb0e5811c2679..c93cfa78832a2 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -36,7 +36,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// call `infer_opaque_definition_from_instantiation` to get the inferred /// type of `_Return<'_a>`. `infer_opaque_definition_from_instantiation` /// compares lifetimes directly, so we need to map the inference variables - /// back to concrete lifetimes: `'static`, `ReEarlyBound` or `ReFree`. + /// back to concrete lifetimes: `'static`, `ReEarlyParam` or `ReLateParam`. /// /// First we map all the lifetimes in the concrete type to an equal /// universal region that occurs in the concrete type's args, in this case @@ -386,7 +386,7 @@ fn check_opaque_type_parameter_valid( let arg_is_param = match arg.unpack() { GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), GenericArgKind::Lifetime(lt) if is_ty_alias => { - matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) + matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_)) } // FIXME(#113916): we can't currently check for unique lifetime params, // see that issue for more. We will also have to ignore unused lifetime diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 38452df32e9ed..dc3ee849d004a 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -11,6 +11,8 @@ use rustc_middle::ty::{self, RegionVid}; use std::fmt::Debug; use std::rc::Rc; +use crate::dataflow::BorrowIndex; + /// Maps between a `Location` and a `PointIndex` (and vice versa). pub(crate) struct RegionValueElements { /// For each basic block, how many points are contained within? @@ -90,6 +92,7 @@ impl RegionValueElements { rustc_index::newtype_index! { /// A single integer representing a `Location` in the MIR control-flow /// graph. Constructed efficiently from `RegionValueElements`. + #[orderable] #[debug_format = "PointIndex({})"] pub struct PointIndex {} } @@ -116,71 +119,132 @@ pub(crate) enum RegionElement { PlaceholderRegion(ty::PlaceholderRegion), } -/// When we initially compute liveness, we use an interval matrix storing -/// liveness ranges for each region-vid. -pub(crate) struct LivenessValues { +/// Records the CFG locations where each region is live. When we initially compute liveness, we use +/// an interval matrix storing liveness ranges for each region-vid. +pub(crate) struct LivenessValues { + /// The map from locations to points. elements: Rc, - points: SparseIntervalMatrix, + + /// For each region: the points where it is live. + points: SparseIntervalMatrix, + + /// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at + /// that point. + pub(crate) loans: Option, } -impl LivenessValues { - /// Creates a new set of "region values" that tracks causal information. - /// Each of the regions in num_region_variables will be initialized with an - /// empty set of points and no causal information. +/// Data used to compute the loans that are live at a given point in the CFG, when using +/// `-Zpolonius=next`. +pub(crate) struct LiveLoans { + /// The set of loans that flow into a given region. When individual regions are marked as live + /// in the CFG, these inflowing loans are recorded as live. + pub(crate) inflowing_loans: SparseBitMatrix, + + /// The set of loans that are live at a given point in the CFG. + pub(crate) live_loans: SparseBitMatrix, +} + +impl LiveLoans { + pub(crate) fn new(num_loans: usize) -> Self { + LiveLoans { + live_loans: SparseBitMatrix::new(num_loans), + inflowing_loans: SparseBitMatrix::new(num_loans), + } + } +} + +impl LivenessValues { + /// Create an empty map of regions to locations where they're live. pub(crate) fn new(elements: Rc) -> Self { - Self { points: SparseIntervalMatrix::new(elements.num_points), elements } + LivenessValues { + points: SparseIntervalMatrix::new(elements.num_points), + elements, + loans: None, + } } /// Iterate through each region that has a value in this set. - pub(crate) fn rows(&self) -> impl Iterator { + pub(crate) fn regions(&self) -> impl Iterator { self.points.rows() } - /// Adds the given element to the value for the given region. Returns whether - /// the element is newly added (i.e., was not already present). - pub(crate) fn add_element(&mut self, row: N, location: Location) -> bool { - debug!("LivenessValues::add(r={:?}, location={:?})", row, location); - let index = self.elements.point_from_location(location); - self.points.insert(row, index) + /// Records `region` as being live at the given `location`. + pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) { + debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location); + let point = self.elements.point_from_location(location); + self.points.insert(region, point); + + // When available, record the loans flowing into this region as live at the given point. + if let Some(loans) = self.loans.as_mut() { + if let Some(inflowing) = loans.inflowing_loans.row(region) { + loans.live_loans.union_row(point, inflowing); + } + } } - /// Adds all the elements in the given bit array into the given - /// region. Returns whether any of them are newly added. - pub(crate) fn add_elements(&mut self, row: N, locations: &IntervalSet) -> bool { - debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations); - self.points.union_row(row, locations) + /// Records `region` as being live at all the given `points`. + pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet) { + debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points); + self.points.union_row(region, points); + + // When available, record the loans flowing into this region as live at the given points. + if let Some(loans) = self.loans.as_mut() { + if let Some(inflowing) = loans.inflowing_loans.row(region) { + if !inflowing.is_empty() { + for point in points.iter() { + loans.live_loans.union_row(point, inflowing); + } + } + } + } } - /// Adds all the control-flow points to the values for `r`. - pub(crate) fn add_all_points(&mut self, row: N) { - self.points.insert_all_into_row(row); + /// Records `region` as being live at all the control-flow points. + pub(crate) fn add_all_points(&mut self, region: RegionVid) { + self.points.insert_all_into_row(region); } - /// Returns `true` if the region `r` contains the given element. - pub(crate) fn contains(&self, row: N, location: Location) -> bool { - let index = self.elements.point_from_location(location); - self.points.row(row).is_some_and(|r| r.contains(index)) + /// Returns whether `region` is marked live at the given `location`. + pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool { + let point = self.elements.point_from_location(location); + self.points.row(region).is_some_and(|r| r.contains(point)) + } + + /// Returns whether `region` is marked live at any location. + pub(crate) fn is_live_anywhere(&self, region: RegionVid) -> bool { + self.live_points(region).next().is_some() } - /// Returns an iterator of all the elements contained by the region `r` - pub(crate) fn get_elements(&self, row: N) -> impl Iterator + '_ { + /// Returns an iterator of all the points where `region` is live. + fn live_points(&self, region: RegionVid) -> impl Iterator + '_ { self.points - .row(row) + .row(region) .into_iter() .flat_map(|set| set.iter()) - .take_while(move |&p| self.elements.point_in_range(p)) - .map(move |p| self.elements.to_location(p)) + .take_while(|&p| self.elements.point_in_range(p)) } - /// Returns a "pretty" string value of the region. Meant for debugging. - pub(crate) fn region_value_str(&self, r: N) -> String { - region_value_str(self.get_elements(r).map(RegionElement::Location)) + /// For debugging purposes, returns a pretty-printed string of the points where the `region` is + /// live. + pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String { + pretty_print_region_elements( + self.live_points(region).map(|p| RegionElement::Location(self.elements.to_location(p))), + ) } #[inline] pub(crate) fn point_from_location(&self, location: Location) -> PointIndex { self.elements.point_from_location(location) } + + /// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`. + pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool { + self.loans + .as_ref() + .expect("Accessing live loans requires `-Zpolonius=next`") + .live_loans + .contains(point, loan_idx) + } } /// Maps from `ty::PlaceholderRegion` values that are used in the rest of @@ -307,7 +371,7 @@ impl RegionValues { /// `self[to] |= values[from]`, essentially: that is, take all the /// elements for the region `from` from `values` and add them to /// the region `to` in `self`. - pub(crate) fn merge_liveness(&mut self, to: N, from: M, values: &LivenessValues) { + pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) { if let Some(set) = values.points.row(from) { self.points.union_row(to, set); } @@ -376,7 +440,7 @@ impl RegionValues { /// Returns a "pretty" string value of the region. Meant for debugging. pub(crate) fn region_value_str(&self, r: N) -> String { - region_value_str(self.elements_contained_in(r)) + pretty_print_region_elements(self.elements_contained_in(r)) } } @@ -420,11 +484,12 @@ impl ToElementIndex for ty::PlaceholderRegion { } } -pub(crate) fn location_set_str( +/// For debugging purposes, returns a pretty-printed string of the given points. +pub(crate) fn pretty_print_points( elements: &RegionValueElements, points: impl IntoIterator, ) -> String { - region_value_str( + pretty_print_region_elements( points .into_iter() .take_while(|&p| elements.point_in_range(p)) @@ -433,7 +498,8 @@ pub(crate) fn location_set_str( ) } -fn region_value_str(elements: impl IntoIterator) -> String { +/// For debugging purposes, returns a pretty-printed string of the given region elements. +fn pretty_print_region_elements(elements: impl IntoIterator) -> String { let mut result = String::new(); result.push('{'); diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index ec0131c5349a1..a31d39e14cd28 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -28,6 +28,9 @@ pub fn renumber_mir<'tcx>( renumberer.visit_body(body); } +// FIXME(@lcnr): A lot of these variants overlap and it seems like +// this type is only used to decide which region should be used +// as representative. This should be cleaned up. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub(crate) enum RegionCtxt { Location(Location), diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index c84256f8ff321..4a76d877af0f5 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -7,7 +7,7 @@ use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::InferCtxt; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::OutlivesBound; -use rustc_middle::ty::{self, RegionVid, Ty}; +use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; @@ -303,7 +303,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { Locations::All(span), span, ConstraintCategory::Internal, - &mut self.constraints, + self.constraints, ) .convert_all(data); } @@ -321,6 +321,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { .map_err(|_: ErrorGuaranteed| debug!("failed to compute implied bounds {:?}", ty)) .ok()?; debug!(?bounds, ?constraints); + // Because of #109628, we may have unexpected placeholders. Ignore them! + // FIXME(#109628): panic in this case once the issue is fixed. + let bounds = bounds.into_iter().filter(|bound| !bound.has_placeholders()); self.add_outlives_bounds(bounds); constraints } diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index d053d0a4b3bad..8e141bb3864ce 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,7 +7,7 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). -use rustc_infer::infer::LateBoundRegionConversionTime; +use rustc_infer::infer::BoundRegionConversionTime; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -35,7 +35,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig); let user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( body.span, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, user_provided_sig, ); @@ -77,7 +77,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if argument_index + 1 >= body.local_decls.len() { self.tcx() .sess - .delay_span_bug(body.span, "found more normalized_input_ty than local_decls"); + .span_delayed_bug(body.span, "found more normalized_input_ty than local_decls"); break; } @@ -101,10 +101,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); // We will not have a universal_regions.yield_ty if we yield (by accident) - // outside of a coroutine and return an `impl Trait`, so emit a delay_span_bug + // outside of a coroutine and return an `impl Trait`, so emit a span_delayed_bug // because we don't want to panic in an assert here if we've already got errors. if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() { - self.tcx().sess.delay_span_bug( + self.tcx().sess.span_delayed_bug( body.span, format!( "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})", diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index a9ca94567878a..7433c94a0bcd1 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -80,7 +80,7 @@ impl LocalUseMap { live_locals.iter().for_each(|&local| locals_with_use_data[local] = true); LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data } - .visit_body(&body); + .visit_body(body); local_use_map } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index f1ad0ca55ccfd..dc4695fd2b058 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -1,7 +1,9 @@ use itertools::{Either, Itertools}; use rustc_data_structures::fx::FxHashSet; -use rustc_middle::mir::{Body, Local}; -use rustc_middle::ty::{RegionVid, TyCtxt}; +use rustc_middle::mir::visit::{TyContext, Visitor}; +use rustc_middle::mir::{Body, Local, Location, SourceInfo}; +use rustc_middle::ty::visit::TypeVisitable; +use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; @@ -11,7 +13,7 @@ use crate::{ constraints::OutlivesConstraintSet, facts::{AllFacts, AllFactsExt}, location::LocationTable, - region_infer::values::RegionValueElements, + region_infer::values::{LivenessValues, RegionValueElements}, universal_regions::UniversalRegions, }; @@ -42,11 +44,11 @@ pub(super) fn generate<'mir, 'tcx>( let free_regions = regions_that_outlive_free_regions( typeck.infcx.num_region_vars(), - &typeck.borrowck_context.universal_regions, + typeck.borrowck_context.universal_regions, &typeck.borrowck_context.constraints.outlives_constraints, ); let (relevant_live_locals, boring_locals) = - compute_relevant_live_locals(typeck.tcx(), &free_regions, &body); + compute_relevant_live_locals(typeck.tcx(), &free_regions, body); let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx()); let polonius_drop_used = facts_enabled.then(|| { @@ -65,6 +67,14 @@ pub(super) fn generate<'mir, 'tcx>( boring_locals, polonius_drop_used, ); + + // Mark regions that should be live where they appear within rvalues or within a call: like + // args, regions, and types. + record_regular_live_regions( + typeck.tcx(), + &mut typeck.borrowck_context.constraints.liveness_constraints, + body, + ); } // The purpose of `compute_relevant_live_locals` is to define the subset of `Local` @@ -132,3 +142,71 @@ fn regions_that_outlive_free_regions<'tcx>( // Return the final set of things we visited. outlives_free_region } + +/// Some variables are "regular live" at `location` -- i.e., they may be used later. This means that +/// all regions appearing in their type must be live at `location`. +fn record_regular_live_regions<'tcx>( + tcx: TyCtxt<'tcx>, + liveness_constraints: &mut LivenessValues, + body: &Body<'tcx>, +) { + let mut visitor = LiveVariablesVisitor { tcx, liveness_constraints }; + for (bb, data) in body.basic_blocks.iter_enumerated() { + visitor.visit_basic_block_data(bb, data); + } +} + +/// Visitor looking for regions that should be live within rvalues or calls. +struct LiveVariablesVisitor<'cx, 'tcx> { + tcx: TyCtxt<'tcx>, + liveness_constraints: &'cx mut LivenessValues, +} + +impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> { + /// We sometimes have `args` within an rvalue, or within a + /// call. Make them live at the location where they appear. + fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) { + self.record_regions_live_at(*args, location); + self.super_args(args); + } + + /// We sometimes have `region`s within an rvalue, or within a + /// call. Make them live at the location where they appear. + fn visit_region(&mut self, region: Region<'tcx>, location: Location) { + self.record_regions_live_at(region, location); + self.super_region(region); + } + + /// We sometimes have `ty`s within an rvalue, or within a + /// call. Make them live at the location where they appear. + fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) { + match ty_context { + TyContext::ReturnTy(SourceInfo { span, .. }) + | TyContext::YieldTy(SourceInfo { span, .. }) + | TyContext::UserTy(span) + | TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => { + span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context); + } + TyContext::Location(location) => { + self.record_regions_live_at(ty, location); + } + } + + self.super_ty(ty); + } +} + +impl<'cx, 'tcx> LiveVariablesVisitor<'cx, 'tcx> { + /// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that + /// all regions appearing in the type of `value` must be live at `location`. + fn record_regions_live_at(&mut self, value: T, location: Location) + where + T: TypeVisitable>, + { + debug!("record_regions_live_at(value={:?}, location={:?})", value, location); + self.tcx.for_each_free_region(&value, |live_region| { + let live_region_vid = live_region.as_var(); + self.liveness_constraints.add_location(live_region_vid, location); + }); + } +} diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index c621df37106b2..45f7b07fd5f93 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -100,7 +100,7 @@ pub(super) fn populate_access_facts<'a, 'tcx>( location_table, move_data, }; - extractor.visit_body(&body); + extractor.visit_body(body); facts.var_dropped_at.extend( dropped_at.iter().map(|&(local, location)| (local, location_table.mid_index(location))), diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index e616449ccd412..c718d57bec399 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -1,12 +1,12 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::WithSuccessors; -use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix}; +use rustc_index::bit_set::HybridBitSet; use rustc_index::interval::IntervalSet; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::for_liveness; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::traits::query::DropckOutlivesResult; -use rustc_middle::ty::{RegionVid, Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; @@ -16,9 +16,8 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex}; use rustc_mir_dataflow::ResultsCursor; -use crate::dataflow::BorrowIndex; use crate::{ - region_infer::values::{self, PointIndex, RegionValueElements}, + region_infer::values::{self, LiveLoans, PointIndex, RegionValueElements}, type_check::liveness::local_use_map::LocalUseMap, type_check::liveness::polonius, type_check::NormalizeLocation, @@ -49,22 +48,17 @@ pub(super) fn trace<'mir, 'tcx>( boring_locals: Vec, polonius_drop_used: Option>, ) { - debug!("trace()"); - let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body); // When using `-Zpolonius=next`, compute the set of loans that can reach a given region. - let num_loans = typeck.borrowck_context.borrow_set.len(); - let mut inflowing_loans = SparseBitMatrix::new(num_loans); if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() { - let borrowck_context = &typeck.borrowck_context; + let borrowck_context = &mut typeck.borrowck_context; let borrow_set = &borrowck_context.borrow_set; - let constraint_set = &borrowck_context.constraints.outlives_constraints; - - let num_region_vars = typeck.infcx.num_region_vars(); - let graph = constraint_set.graph(num_region_vars); + let mut live_loans = LiveLoans::new(borrow_set.len()); + let outlives_constraints = &borrowck_context.constraints.outlives_constraints; + let graph = outlives_constraints.graph(typeck.infcx.num_region_vars()); let region_graph = - graph.region_graph(&constraint_set, borrowck_context.universal_regions.fr_static); + graph.region_graph(outlives_constraints, borrowck_context.universal_regions.fr_static); // Traverse each issuing region's constraints, and record the loan as flowing into the // outlived region. @@ -75,9 +69,13 @@ pub(super) fn trace<'mir, 'tcx>( continue; } - inflowing_loans.insert(succ, loan); + live_loans.inflowing_loans.insert(succ, loan); } } + + // Store the inflowing loans in the liveness constraints: they will be used to compute live + // loans when liveness data is recorded there. + borrowck_context.constraints.liveness_constraints.loans = Some(live_loans); }; let cx = LivenessContext { @@ -88,7 +86,6 @@ pub(super) fn trace<'mir, 'tcx>( local_use_map, move_data, drop_data: FxIndexMap::default(), - inflowing_loans, }; let mut results = LivenessResults::new(cx); @@ -126,9 +123,6 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { /// Index indicating where each variable is assigned, used, or /// dropped. local_use_map: &'me LocalUseMap, - - /// Set of loans that flow into a given region, when using `-Zpolonius=next`. - inflowing_loans: SparseBitMatrix, } struct DropData<'tcx> { @@ -489,7 +483,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { } let move_paths = &self.flow_inits.analysis().move_data().move_paths; - move_paths[mpi].find_descendant(&move_paths, |mpi| state.contains(mpi)).is_some() + move_paths[mpi].find_descendant(move_paths, |mpi| state.contains(mpi)).is_some() } /// Returns `true` if the local variable (or some part of it) is initialized in @@ -519,14 +513,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { live_at: &IntervalSet, ) { debug!("add_use_live_facts_for(value={:?})", value); - - Self::make_all_regions_live( - self.elements, - &mut self.typeck, - value, - live_at, - &self.inflowing_loans, - ); + Self::make_all_regions_live(self.elements, self.typeck, value, live_at); } /// Some variable with type `live_ty` is "drop live" at `location` @@ -550,7 +537,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { dropped_local, dropped_ty, drop_locations, - values::location_set_str(self.elements, live_at.iter()), + values::pretty_print_points(self.elements, live_at.iter()), ); let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({ @@ -577,15 +564,8 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { // All things in the `outlives` array may be touched by // the destructor and must be live at this point. for &kind in &drop_data.dropck_result.kinds { - Self::make_all_regions_live( - self.elements, - &mut self.typeck, - kind, - live_at, - &self.inflowing_loans, - ); - - polonius::add_drop_of_var_derefs_origin(&mut self.typeck, dropped_local, &kind); + Self::make_all_regions_live(self.elements, self.typeck, kind, live_at); + polonius::add_drop_of_var_derefs_origin(self.typeck, dropped_local, &kind); } } @@ -594,20 +574,13 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeVisitable>, live_at: &IntervalSet, - inflowing_loans: &SparseBitMatrix, ) { debug!("make_all_regions_live(value={:?})", value); debug!( "make_all_regions_live: live_at={}", - values::location_set_str(elements, live_at.iter()), + values::pretty_print_points(elements, live_at.iter()), ); - // When using `-Zpolonius=next`, we want to record the loans that flow into this value's - // regions as being live at the given `live_at` points: this will be used to compute the - // location where a loan goes out of scope. - let num_loans = typeck.borrowck_context.borrow_set.len(); - let value_loans = &mut HybridBitSet::new_empty(num_loans); - value.visit_with(&mut for_liveness::FreeRegionsVisitor { tcx: typeck.tcx(), param_env: typeck.param_env, @@ -618,22 +591,9 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { .borrowck_context .constraints .liveness_constraints - .add_elements(live_region_vid, live_at); - - // There can only be inflowing loans for this region when we are using - // `-Zpolonius=next`. - if let Some(inflowing) = inflowing_loans.row(live_region_vid) { - value_loans.union(inflowing); - } + .add_points(live_region_vid, live_at); }, }); - - // Record the loans reaching the value. - if !value_loans.is_empty() { - for point in live_at.iter() { - typeck.borrowck_context.live_loans.union_row(point, value_loans); - } - } } fn compute_drop_data( diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9f30d9d8ba12b..ecc9905e33e85 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -14,14 +14,13 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::lang_items::LangItem; -use rustc_index::bit_set::SparseBitMatrix; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ - InferCtxt, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin, + BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, }; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; @@ -51,8 +50,6 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; -use crate::dataflow::BorrowIndex; -use crate::region_infer::values::PointIndex; use crate::session_diagnostics::{MoveUnsized, SimdShuffleLastConst}; use crate::{ borrow_set::BorrowSet, @@ -68,7 +65,7 @@ use crate::{ region_infer::TypeTest, type_check::free_region_relations::{CreateResult, UniversalRegionRelations}, universal_regions::{DefiningTy, UniversalRegions}, - BorrowckInferCtxt, Upvar, + BorrowckInferCtxt, }; macro_rules! span_mirbug { @@ -138,7 +135,7 @@ pub(crate) fn type_check<'mir, 'tcx>( flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, elements: &Rc, - upvars: &[Upvar<'tcx>], + upvars: &[&ty::CapturedPlace<'tcx>], use_polonius: bool, ) -> MirTypeckResults<'tcx> { let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body); @@ -166,9 +163,6 @@ pub(crate) fn type_check<'mir, 'tcx>( debug!(?normalized_inputs_and_output); - // When using `-Zpolonius=next`, liveness will record the set of live loans per point. - let mut live_loans = SparseBitMatrix::new(borrow_set.len()); - let mut borrowck_context = BorrowCheckContext { universal_regions, location_table, @@ -176,7 +170,6 @@ pub(crate) fn type_check<'mir, 'tcx>( all_facts, constraints: &mut constraints, upvars, - live_loans: &mut live_loans, }; let mut checker = TypeChecker::new( @@ -191,11 +184,11 @@ pub(crate) fn type_check<'mir, 'tcx>( checker.check_user_type_annotations(); let mut verifier = TypeVerifier::new(&mut checker, promoted); - verifier.visit_body(&body); + verifier.visit_body(body); checker.typeck_mir(body); - checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output); - checker.check_signature_annotation(&body); + checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output); + checker.check_signature_annotation(body); liveness::generate( &mut checker, @@ -232,7 +225,7 @@ pub(crate) fn type_check<'mir, 'tcx>( let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind()); if hidden_type.has_non_region_infer() { - let reported = infcx.tcx.sess.delay_span_bug( + let reported = infcx.tcx.sess.span_delayed_bug( decl.hidden_type.span, format!("could not resolve {:#?}", hidden_type.ty.kind()), ); @@ -243,7 +236,7 @@ pub(crate) fn type_check<'mir, 'tcx>( }) .collect(); - MirTypeckResults { constraints, universal_region_relations, opaque_type_values, live_loans } + MirTypeckResults { constraints, universal_region_relations, opaque_type_values } } fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { @@ -274,9 +267,9 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { #[track_caller] fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) { // We sometimes see MIR failures (notably predicate failures) due to - // the fact that we check rvalue sized predicates here. So use `delay_span_bug` + // the fact that we check rvalue sized predicates here. So use `span_delayed_bug` // to avoid reporting bugs in those cases. - tcx.sess.diagnostic().delay_span_bug(span, msg); + tcx.sess.diagnostic().span_delayed_bug(span, msg); } enum FieldAccessError { @@ -318,7 +311,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { .borrowck_context .constraints .liveness_constraints - .add_element(live_region_vid, location); + .add_location(live_region_vid, location); }); // HACK(compiler-errors): Constants that are gathered into Body.required_consts @@ -389,7 +382,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { self.cx.ascribe_user_type( constant.const_.ty(), UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }), - locations.span(&self.cx.body), + locations.span(self.cx.body), ); } } else if let Some(static_def_id) = constant.check_static_ptr(tcx) { @@ -553,7 +546,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let all_facts = &mut None; let mut constraints = Default::default(); let mut liveness_constraints = - LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body))); + LivenessValues::new(Rc::new(RegionValueElements::new(promoted_body))); // Don't try to add borrow_region facts for the promoted MIR let mut swap_constraints = |this: &mut Self| { @@ -570,7 +563,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { swap_constraints(self); - self.visit_body(&promoted_body); + self.visit_body(promoted_body); self.cx.typeck_mir(promoted_body); @@ -592,16 +585,16 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) } - for region in liveness_constraints.rows() { + for region in liveness_constraints.regions() { // If the region is live at at least one location in the promoted MIR, // then add a liveness constraint to the main MIR for this region // at the location provided as an argument to this method - if liveness_constraints.get_elements(region).next().is_some() { + if liveness_constraints.is_live_anywhere(region) { self.cx .borrowck_context .constraints .liveness_constraints - .add_element(region, location); + .add_location(region, location); } } } @@ -751,7 +744,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { PlaceContext::MutatingUse(_) => ty::Invariant, PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant, PlaceContext::NonMutatingUse( - Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | AddressOf + Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | AddressOf | Projection, ) => ty::Covariant, PlaceContext::NonUse(AscribeUserTy(variance)) => variance, @@ -857,11 +850,7 @@ struct BorrowCheckContext<'a, 'tcx> { all_facts: &'a mut Option, borrow_set: &'a BorrowSet<'tcx>, pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>, - upvars: &'a [Upvar<'tcx>], - - /// The set of loans that are live at a given point in the CFG, filled in by `liveness::trace`, - /// when using `-Zpolonius=next`. - pub(crate) live_loans: &'a mut SparseBitMatrix, + upvars: &'a [&'a ty::CapturedPlace<'tcx>], } /// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions @@ -870,9 +859,6 @@ pub(crate) struct MirTypeckResults<'tcx> { pub(crate) constraints: MirTypeckRegionConstraints<'tcx>, pub(crate) universal_region_relations: Frozen>, pub(crate) opaque_type_values: FxIndexMap, OpaqueHiddenType<'tcx>>, - - /// The set of loans that are live at a given point in the CFG, when using `-Zpolonius=next`. - pub(crate) live_loans: SparseBitMatrix, } /// A collection of region constraints that must be satisfied for the @@ -899,7 +885,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> { /// not otherwise appear in the MIR -- in particular, the /// late-bound regions that it instantiates at call-sites -- and /// hence it must report on their liveness constraints. - pub(crate) liveness_constraints: LivenessValues, + pub(crate) liveness_constraints: LivenessValues, pub(crate) outlives_constraints: OutlivesConstraintSet<'tcx>, @@ -1082,7 +1068,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); if result.is_err() { - self.infcx.tcx.sess.delay_span_bug( + self.infcx.tcx.sess.span_delayed_bug( self.body.span, "failed re-defining predefined opaques in mir typeck", ); @@ -1127,7 +1113,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations, locations.span(self.body), category, - &mut self.borrowck_context.constraints, + self.borrowck_context.constraints, ) .convert_all(data); } @@ -1202,7 +1188,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.infcx.tcx } - #[instrument(skip(self, body, location), level = "debug")] + #[instrument(skip(self, body), level = "debug")] fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) { let tcx = self.tcx(); debug!("stmt kind: {:?}", stmt.kind); @@ -1387,7 +1373,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return; } }; - let (sig, map) = tcx.replace_late_bound_regions(sig, |br| { + let (sig, map) = tcx.instantiate_bound_regions(sig, |br| { use crate::renumber::RegionCtxt; let region_ctxt_fn = || { @@ -1401,10 +1387,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }; self.infcx.next_region_var( - LateBoundRegion( + BoundRegion( term.source_info.span, br.kind, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, ), region_ctxt_fn, ) @@ -1443,7 +1429,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context .constraints .liveness_constraints - .add_element(region_vid, term_location); + .add_location(region_vid, term_location); } self.check_call_inputs(body, term, func, &sig, args, term_location, *call_source); @@ -1854,7 +1840,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { for op in ops { self.check_operand(op, location); } - self.check_aggregate_rvalue(&body, rvalue, ak, ops, location) + self.check_aggregate_rvalue(body, rvalue, ak, ops, location) } Rvalue::Repeat(operand, len) => { @@ -1934,7 +1920,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { *ty, ty_fn_ptr_from, location.to_locations(), - ConstraintCategory::Cast, + ConstraintCategory::Cast { unsize_to: None }, ) { span_mirbug!( self, @@ -1959,7 +1945,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { *ty, ty_fn_ptr_from, location.to_locations(), - ConstraintCategory::Cast, + ConstraintCategory::Cast { unsize_to: None }, ) { span_mirbug!( self, @@ -1988,7 +1974,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { *ty, ty_fn_ptr_from, location.to_locations(), - ConstraintCategory::Cast, + ConstraintCategory::Cast { unsize_to: None }, ) { span_mirbug!( self, @@ -2013,7 +1999,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.prove_trait_ref( trait_ref, location.to_locations(), - ConstraintCategory::Cast, + ConstraintCategory::Cast { + unsize_to: Some(tcx.fold_regions(ty, |r, _| { + if let ty::ReVar(_) = r.kind() { + tcx.lifetimes.re_erased + } else { + r + } + })), + }, ); } @@ -2033,7 +2027,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .iter() .map(|predicate| predicate.with_self_ty(tcx, self_ty)), location.to_locations(), - ConstraintCategory::Cast, + ConstraintCategory::Cast { unsize_to: None }, ); let outlives_predicate = tcx.mk_predicate(Binder::dummy( @@ -2044,7 +2038,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.prove_predicate( outlives_predicate, location.to_locations(), - ConstraintCategory::Cast, + ConstraintCategory::Cast { unsize_to: None }, ); } @@ -2065,7 +2059,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { *ty_from, *ty_to, location.to_locations(), - ConstraintCategory::Cast, + ConstraintCategory::Cast { unsize_to: None }, ) { span_mirbug!( self, @@ -2131,7 +2125,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { *ty_elem, *ty_to, location.to_locations(), - ConstraintCategory::Cast, + ConstraintCategory::Cast { unsize_to: None }, ) { span_mirbug!( self, @@ -2292,7 +2286,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } Rvalue::Ref(region, _borrow_kind, borrowed_place) => { - self.add_reborrow_constraint(&body, location, *region, borrowed_place); + self.add_reborrow_constraint(body, location, *region, borrowed_place); } Rvalue::BinaryOp( @@ -2504,7 +2498,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = self.infcx.tcx; let field = path_utils::is_upvar_field_projection( tcx, - &self.borrowck_context.upvars, + self.borrowck_context.upvars, borrowed_place.as_ref(), body, ); @@ -2660,13 +2654,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { location.to_locations(), DUMMY_SP, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. - &mut self.borrowck_context.constraints, + self.borrowck_context.constraints, ) - .apply_closure_requirements( - &closure_requirements, - def_id.to_def_id(), - args, - ); + .apply_closure_requirements(closure_requirements, def_id.to_def_id(), args); } // Now equate closure args to regions inherited from `typeck_root_def_id`. Fixes #98589. @@ -2674,8 +2664,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id); let parent_args = match tcx.def_kind(def_id) { + DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => { + args.as_coroutine().parent_args() + } DefKind::Closure => args.as_closure().parent_args(), - DefKind::Coroutine => args.as_coroutine().parent_args(), DefKind::InlineConst => args.as_inline_const().parent_args(), other => bug!("unexpected item {:?}", other), }; @@ -2706,7 +2698,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { debug!(?body.span); for (local, local_decl) in body.local_decls.iter_enumerated() { - self.check_local(&body, local, local_decl); + self.check_local(body, local, local_decl); } for (block, block_data) in body.basic_blocks.iter_enumerated() { @@ -2719,8 +2711,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { location.statement_index += 1; } - self.check_terminator(&body, block_data.terminator(), location); - self.check_iscleanup(&body, block_data); + self.check_terminator(body, block_data.terminator(), location); + self.check_iscleanup(body, block_data); } } } diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index c1f82e19c02e2..ee0bd13109bb6 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -107,12 +107,12 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> fn next_existential_region_var( &mut self, from_forall: bool, - _name: Option, + name: Option, ) -> ty::Region<'tcx> { let origin = NllRegionVariableOrigin::Existential { from_forall }; let reg_var = - self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(_name)); + self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(name)); reg_var } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 7897a5a63ba8f..2b83c7871396a 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -462,7 +462,6 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // "Liberate" the late-bound regions. These correspond to // "local" free regions. - let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty); let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars( @@ -665,7 +664,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv, }; - let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br); + let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); // The "inputs" of the closure in the @@ -738,18 +737,6 @@ trait InferCtxtExt<'tcx> { ) -> T where T: TypeFoldable>; - - fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope( - &self, - mir_def_id: LocalDefId, - indices: &mut UniversalRegionIndices<'tcx>, - ); - - fn replace_late_bound_regions_with_nll_infer_vars_in_item( - &self, - mir_def_id: LocalDefId, - indices: &mut UniversalRegionIndices<'tcx>, - ); } impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { @@ -781,10 +768,10 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { where T: TypeFoldable>, { - let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| { + let (value, _map) = self.tcx.instantiate_bound_regions(value, |br| { debug!(?br); let liberated_region = - ty::Region::new_free(self.tcx, all_outlive_scope.to_def_id(), br.kind); + ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), br.kind); let region_vid = { let name = match br.kind.get_name() { Some(name) => name, @@ -800,61 +787,13 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { }); value } - - /// Finds late-bound regions that do not appear in the parameter listing and adds them to the - /// indices vector. Typically, we identify late-bound regions as we process the inputs and - /// outputs of the closure/function. However, sometimes there are late-bound regions which do - /// not appear in the fn parameters but which are nonetheless in scope. The simplest case of - /// this are unused functions, like fn foo<'a>() { } (see e.g., #51351). Despite not being used, - /// users can still reference these regions (e.g., let x: &'a u32 = &22;), so we need to create - /// entries for them and store them in the indices map. This code iterates over the complete - /// set of late-bound regions and checks for any that we have not yet seen, adding them to the - /// inputs vector. - #[instrument(skip(self, indices))] - fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope( - &self, - mir_def_id: LocalDefId, - indices: &mut UniversalRegionIndices<'tcx>, - ) { - for_each_late_bound_region_in_recursive_scope(self.tcx, mir_def_id, |r| { - debug!(?r); - if !indices.indices.contains_key(&r) { - let region_vid = { - let name = r.get_name_or_anon(); - self.next_nll_region_var(FR, || RegionCtxt::LateBound(name)) - }; - - debug!(?region_vid); - indices.insert_late_bound_region(r, region_vid.as_var()); - } - }); - } - - #[instrument(skip(self, indices))] - fn replace_late_bound_regions_with_nll_infer_vars_in_item( - &self, - mir_def_id: LocalDefId, - indices: &mut UniversalRegionIndices<'tcx>, - ) { - for_each_late_bound_region_in_item(self.tcx, mir_def_id, |r| { - debug!(?r); - if !indices.indices.contains_key(&r) { - let region_vid = { - let name = r.get_name_or_anon(); - self.next_nll_region_var(FR, || RegionCtxt::LateBound(name)) - }; - - indices.insert_late_bound_region(r, region_vid.as_var()); - } - }); - } } impl<'tcx> UniversalRegionIndices<'tcx> { /// Initially, the `UniversalRegionIndices` map contains only the /// early-bound regions in scope. Once that is all setup, we come /// in later and instantiate the late-bound regions, and then we - /// insert the `ReFree` version of those into the map as + /// insert the `ReLateParam` version of those into the map as /// well. These are used for error reporting. fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) { debug!("insert_late_bound_region({:?}, {:?})", r, vid); @@ -929,11 +868,12 @@ fn for_each_late_bound_region_in_item<'tcx>( return; } - for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) { + for bound_var in tcx.late_bound_vars(tcx.local_def_id_to_hir_id(mir_def_id)) { let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; - let liberated_region = ty::Region::new_free(tcx, mir_def_id.to_def_id(), bound_region); + let liberated_region = + ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), bound_region); f(liberated_region); } } diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index c5991e0bc254e..6ac8e1ba7156a 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -35,7 +35,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { never_initialized_mut_locals: &mut never_initialized_mut_locals, mbcx: self, }; - visitor.visit_body(&visitor.mbcx.body); + visitor.visit_body(visitor.mbcx.body); } // Take the union of the existed `used_mut` set with those variables we've found were diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 070d50708ff1b..e13d217ef01ae 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -31,10 +31,7 @@ pub fn expand( { (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) } else { - ecx.sess - .parse_sess - .span_diagnostic - .emit_err(errors::AllocErrorMustBeFn { span: item.span() }); + ecx.sess.diagnostic().emit_err(errors::AllocErrorMustBeFn { span: item.span() }); return vec![orig_item]; }; diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index 37ac09ccdff4d..64be8da590281 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -47,7 +47,7 @@ impl MultiItemModifier for Expander { let template = AttributeTemplate { list: Some("path"), ..Default::default() }; validate_attr::check_builtin_meta_item( &ecx.sess.parse_sess, - &meta_item, + meta_item, ast::AttrStyle::Outer, sym::cfg_accessible, template, diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index f826c6e7712d2..ca26b7ed8270d 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -25,7 +25,7 @@ pub(crate) fn expand( annotatable: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); - warn_on_duplicate_attribute(&ecx, &annotatable, sym::cfg_eval); + warn_on_duplicate_attribute(ecx, &annotatable, sym::cfg_eval); vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable, ecx.current_expansion.lint_node_id)] } @@ -95,19 +95,19 @@ impl CfgFinder { fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool { let mut finder = CfgFinder { has_cfg_or_cfg_attr: false }; match annotatable { - Annotatable::Item(item) => finder.visit_item(&item), - Annotatable::TraitItem(item) => finder.visit_assoc_item(&item, visit::AssocCtxt::Trait), - Annotatable::ImplItem(item) => finder.visit_assoc_item(&item, visit::AssocCtxt::Impl), - Annotatable::ForeignItem(item) => finder.visit_foreign_item(&item), - Annotatable::Stmt(stmt) => finder.visit_stmt(&stmt), - Annotatable::Expr(expr) => finder.visit_expr(&expr), - Annotatable::Arm(arm) => finder.visit_arm(&arm), - Annotatable::ExprField(field) => finder.visit_expr_field(&field), - Annotatable::PatField(field) => finder.visit_pat_field(&field), - Annotatable::GenericParam(param) => finder.visit_generic_param(¶m), - Annotatable::Param(param) => finder.visit_param(¶m), - Annotatable::FieldDef(field) => finder.visit_field_def(&field), - Annotatable::Variant(variant) => finder.visit_variant(&variant), + Annotatable::Item(item) => finder.visit_item(item), + Annotatable::TraitItem(item) => finder.visit_assoc_item(item, visit::AssocCtxt::Trait), + Annotatable::ImplItem(item) => finder.visit_assoc_item(item, visit::AssocCtxt::Impl), + Annotatable::ForeignItem(item) => finder.visit_foreign_item(item), + Annotatable::Stmt(stmt) => finder.visit_stmt(stmt), + Annotatable::Expr(expr) => finder.visit_expr(expr), + Annotatable::Arm(arm) => finder.visit_arm(arm), + Annotatable::ExprField(field) => finder.visit_expr_field(field), + Annotatable::PatField(field) => finder.visit_pat_field(field), + Annotatable::GenericParam(param) => finder.visit_generic_param(param), + Annotatable::Param(param) => finder.visit_param(param), + Annotatable::FieldDef(field) => finder.visit_field_def(field), + Annotatable::Variant(variant) => finder.visit_variant(variant), Annotatable::Crate(krate) => finder.visit_crate(krate), }; finder.has_cfg_or_cfg_attr diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs index 7b75d7d84e4fc..3b1fde1f09703 100644 --- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs +++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs @@ -11,7 +11,7 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String]) for raw_attr in attrs { let mut parser = rustc_parse::new_parser_from_source_str( parse_sess, - FileName::cli_crate_attr_source_code(&raw_attr), + FileName::cli_crate_attr_source_code(raw_attr), raw_attr.clone(), ); diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index c4f5af384c1aa..96e9584c20955 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -19,8 +19,8 @@ fn invalid_type_err( let snippet = cx.sess.source_map().span_to_snippet(span).ok(); match ast::LitKind::from_token_lit(token_lit) { Ok(ast::LitKind::CStr(_, _)) => { - // FIXME(c_str_literals): should concatenation of C string literals - // include the null bytes in the end? + // Avoid ambiguity in handling of terminal `NUL` by refusing to + // concatenate C string literals as bytes. cx.emit_err(errors::ConcatCStrLit { span: span }); } Ok(ast::LitKind::Char(_)) => { @@ -159,7 +159,7 @@ pub fn expand_concat_bytes( accumulator.push(val); } Ok(ast::LitKind::ByteStr(ref bytes, _)) => { - accumulator.extend_from_slice(&bytes); + accumulator.extend_from_slice(bytes); } _ => { if !has_errors { diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 140853db695aa..5a77c3276e2a8 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -35,7 +35,7 @@ impl MultiItemModifier for Expander { AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; validate_attr::check_builtin_meta_item( &sess.parse_sess, - &meta_item, + meta_item, ast::AttrStyle::Outer, sym::derive, template, @@ -48,14 +48,14 @@ impl MultiItemModifier for Expander { NestedMetaItem::MetaItem(meta) => Some(meta), NestedMetaItem::Lit(lit) => { // Reject `#[derive("Debug")]`. - report_unexpected_meta_item_lit(sess, &lit); + report_unexpected_meta_item_lit(sess, lit); None } }) .map(|meta| { // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the // paths. - report_path_args(sess, &meta); + report_path_args(sess, meta); meta.path.clone() }) .map(|path| (path, dummy_annotatable(), None, self.0)) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index f3164bd2c2a74..7f5589210d41b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -136,7 +136,7 @@ fn cs_partial_cmp( && let Some(last) = arms.last_mut() && let PatKind::Wild = last.pat.kind { - last.body = expr2; + last.body = Some(expr2); expr1 } else { let eq_arm = cx.arm( diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 809f9838d20be..30c9b35bbacd3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -33,7 +33,7 @@ pub fn expand_deriving_debug( explicit_self: true, nonself_args: vec![(fmtr, sym::f)], ret_ty: Path(path_std!(fmt::Result)), - attributes: ast::AttrVec::new(), + attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless, combine_substructure: combine_substructure(Box::new(|a, b, c| { diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 07b172bc757b2..43874a242f26a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -127,18 +127,17 @@ fn extract_default_variant<'a>( [first, rest @ ..] => { let suggs = default_variants .iter() - .map(|variant| { - let spans = default_variants + .filter_map(|variant| { + let keep = attr::find_by_name(&variant.attrs, kw::Default)?.span; + let spans: Vec = default_variants .iter() - .filter_map(|v| { - if v.span == variant.span { - None - } else { - Some(attr::find_by_name(&v.attrs, kw::Default)?.span) - } + .flat_map(|v| { + attr::filter_by_name(&v.attrs, kw::Default) + .filter_map(|attr| (attr.span != keep).then_some(attr.span)) }) .collect(); - errors::MultipleDefaultsSugg { spans, ident: variant.ident } + (!spans.is_empty()) + .then_some(errors::MultipleDefaultsSugg { spans, ident: variant.ident }) }) .collect(); cx.emit_err(errors::MultipleDefaults { diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index aa1ce1b929d0f..23502b6eafc6d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -467,7 +467,7 @@ impl<'a> TraitDef<'a> { match item { Annotatable::Item(item) => { let is_packed = item.attrs.iter().any(|attr| { - for r in attr::find_repr_attrs(&cx.sess, attr) { + for r in attr::find_repr_attrs(cx.sess, attr) { if let attr::ReprPacked(_) = r { return true; } @@ -478,7 +478,7 @@ impl<'a> TraitDef<'a> { let newitem = match &item.kind { ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def( cx, - &struct_def, + struct_def, item.ident, generics, from_scratch, @@ -496,7 +496,7 @@ impl<'a> TraitDef<'a> { if self.supports_unions { self.expand_struct_def( cx, - &struct_def, + struct_def, item.ident, generics, from_scratch, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 2d5043112b67b..1a45c3279f751 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -182,7 +182,7 @@ impl Bounds { let params = self .bounds .iter() - .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, &bounds, self_ty, self_generics)) + .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, bounds, self_ty, self_generics)) .collect(); Generics { diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 92da0c069e51a..8c2fa6ee95f33 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -108,7 +108,7 @@ pub fn expand_env<'cx>( return DummyResult::any(sp); } - Some(value) => cx.expr_str(sp, value), + Some(value) => cx.expr_str(span, value), }; MacEager::expr(e) } diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index fde4270334b67..0a3af2c2e1330 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::{ - AddToDiagnostic, DiagnosticBuilder, EmissionGuarantee, Handler, IntoDiagnostic, MultiSpan, + AddToDiagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, SingleLabelManySpans, }; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -446,9 +446,9 @@ pub(crate) struct EnvNotDefinedWithUserMessage { } // Hand-written implementation to support custom user messages. -impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage { +impl<'a> IntoDiagnostic<'a> for EnvNotDefinedWithUserMessage { #[track_caller] - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> { + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { #[expect( rustc::untranslatable_diagnostic, reason = "cannot translate user-provided messages" @@ -801,8 +801,8 @@ pub(crate) struct AsmClobberNoReg { pub(crate) clobbers: Vec, } -impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg { - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> { +impl<'a> IntoDiagnostic<'a> for AsmClobberNoReg { + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let mut diag = handler.struct_diagnostic(crate::fluent_generated::builtin_macros_asm_clobber_no_reg); diag.set_span(self.spans.clone()); diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 214fed8e2d827..c5fd535b03620 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -547,7 +547,7 @@ fn make_format_args( span: arg_name.span.into(), msg: format!("named argument `{}` is not used by name", arg_name.name).into(), node_id: rustc_ast::CRATE_NODE_ID, - lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY), + lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY), diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally { position_sp_to_replace, position_sp_for_msg, @@ -617,16 +617,22 @@ fn report_missing_placeholders( let placeholders = pieces .iter() .filter_map(|piece| { - if let parse::Piece::NextArgument(argument) = piece && let ArgumentNamed(binding) = argument.position { - let span = fmt_span.from_inner(InnerSpan::new(argument.position_span.start, argument.position_span.end)); + if let parse::Piece::NextArgument(argument) = piece + && let ArgumentNamed(binding) = argument.position + { + let span = fmt_span.from_inner(InnerSpan::new( + argument.position_span.start, + argument.position_span.end, + )); Some((span, binding)) - } else { None } + } else { + None + } }) .collect::>(); if !placeholders.is_empty() { - if let Some(mut new_diag) = - report_redundant_format_arguments(ecx, &args, used, placeholders) + if let Some(mut new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders) { diag.cancel(); new_diag.emit(); @@ -666,30 +672,22 @@ fn report_missing_placeholders( if explained.contains(&sub) { continue; } - explained.insert(sub.clone()); + explained.insert(sub); if !found_foreign { found_foreign = true; show_doc_note = true; } - if let Some(inner_sp) = pos { - let sp = fmt_span.from_inner(inner_sp); + let sp = fmt_span.from_inner(pos); - if success { - suggestions.push((sp, trn)); - } else { - diag.span_note( - sp, - format!("format specifiers use curly braces, and {}", trn), - ); - } + if success { + suggestions.push((sp, trn)); } else { - if success { - diag.help(format!("`{}` should be written as `{}`", sub, trn)); - } else { - diag.note(format!("`{}` should use curly braces, and {}", sub, trn)); - } + diag.span_note( + sp, + format!("format specifiers use curly braces, and {}", trn), + ); } } diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index 2fc8a07636687..307e582d65ef6 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -19,10 +19,10 @@ pub(crate) mod printf { } } - pub fn position(&self) -> Option { + pub fn position(&self) -> InnerSpan { match self { - Substitution::Format(fmt) => Some(fmt.position), - &Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)), + Substitution::Format(fmt) => fmt.position, + &Substitution::Escape((start, end)) => InnerSpan::new(start, end), } } @@ -302,10 +302,9 @@ pub(crate) mod printf { fn next(&mut self) -> Option { let (mut sub, tail) = parse_next_substitution(self.s)?; self.s = tail; - if let Some(InnerSpan { start, end }) = sub.position() { - sub.set_position(start + self.pos, end + self.pos); - self.pos += end; - } + let InnerSpan { start, end } = sub.position(); + sub.set_position(start + self.pos, end + self.pos); + self.pos += end; Some(sub) } @@ -629,9 +628,9 @@ pub mod shell { } } - pub fn position(&self) -> Option { + pub fn position(&self) -> InnerSpan { let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self; - Some(InnerSpan::new(pos.0, pos.1)) + InnerSpan::new(pos.0, pos.1) } pub fn set_position(&mut self, start: usize, end: usize) { @@ -664,10 +663,9 @@ pub mod shell { fn next(&mut self) -> Option { let (mut sub, tail) = parse_next_substitution(self.s)?; self.s = tail; - if let Some(InnerSpan { start, end }) = sub.position() { - sub.set_position(start + self.pos, end + self.pos); - self.pos += end; - } + let InnerSpan { start, end } = sub.position(); + sub.set_position(start + self.pos, end + self.pos); + self.pos += end; Some(sub) } diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 33392edf06086..6dc75e3ba4cbb 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -34,10 +34,7 @@ pub fn expand( { (item, true, ecx.with_def_site_ctxt(ty.span)) } else { - ecx.sess - .parse_sess - .span_diagnostic - .emit_err(errors::AllocMustStatics { span: item.span() }); + ecx.sess.diagnostic().emit_err(errors::AllocMustStatics { span: item.span() }); return vec![orig_item]; }; diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index d84742c9b8293..f60b73fbe9b13 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -1,9 +1,9 @@ //! This crate contains implementations of built-in macros and other code generating facilities //! injecting code into the crate before it is lowered to HIR. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] #![feature(box_patterns)] @@ -23,10 +23,8 @@ extern crate tracing; use crate::deriving::*; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; -use rustc_fluent_macro::fluent_messages; use rustc_span::symbol::sym; mod alloc_error_handler; @@ -59,7 +57,7 @@ pub mod proc_macro_harness; pub mod standard_library_imports; pub mod test_harness; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { let mut register = |name, kind| resolver.register_builtin_macro(name, kind); diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index f7bafa2856e4d..7ae4b1b59dcde 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -133,7 +133,7 @@ pub fn expand_include<'cx>( let r = base::parse_expr(&mut self.p)?; if self.p.token != token::Eof { self.p.sess.buffer_lint( - &INCOMPLETE_INCLUDE, + INCOMPLETE_INCLUDE, self.p.token.span, self.node_id, "include macro expected single expression in source", @@ -189,7 +189,7 @@ pub fn expand_include_str( match cx.source_map().load_binary_file(&file) { Ok(bytes) => match std::str::from_utf8(&bytes) { Ok(src) => { - let interned_src = Symbol::intern(&src); + let interned_src = Symbol::intern(src); base::MacEager::expr(cx.expr_str(sp, interned_src)) } Err(_) => { diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 6d55603c70837..81433155ecfd0 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -26,7 +26,7 @@ pub fn expand_test_case( anno_item: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::test_case); - warn_on_duplicate_attribute(&ecx, &anno_item, sym::test_case); + warn_on_duplicate_attribute(ecx, &anno_item, sym::test_case); if !ecx.ecfg.should_test { return vec![]; @@ -79,7 +79,7 @@ pub fn expand_test( item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::test); - warn_on_duplicate_attribute(&cx, &item, sym::test); + warn_on_duplicate_attribute(cx, &item, sym::test); expand_test_or_bench(cx, attr_sp, item, false) } @@ -90,7 +90,7 @@ pub fn expand_bench( item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::bench); - warn_on_duplicate_attribute(&cx, &item, sym::bench); + warn_on_duplicate_attribute(cx, &item, sym::bench); expand_test_or_bench(cx, attr_sp, item, true) } @@ -134,9 +134,9 @@ pub fn expand_test_or_bench( // will fail. We shouldn't try to expand in this case because the errors // would be spurious. let check_result = if is_bench { - check_bench_signature(cx, &item, &fn_) + check_bench_signature(cx, &item, fn_) } else { - check_test_signature(cx, &item, &fn_) + check_test_signature(cx, &item, fn_) }; if check_result.is_err() { return if is_stmt { @@ -389,7 +389,7 @@ pub fn expand_test_or_bench( } fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) { - let diag = &cx.sess.parse_sess.span_diagnostic; + let diag = cx.sess.diagnostic(); let msg = "the `#[test]` attribute may only be used on a non-associated function"; let mut err = match item.map(|i| &i.kind) { // These were a warning before #92959 and need to continue being that to avoid breaking @@ -466,7 +466,7 @@ fn should_ignore_message(i: &ast::Item) -> Option { fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { match attr::find_by_name(&i.attrs, sym::should_panic) { Some(attr) => { - let sd = &cx.sess.parse_sess.span_diagnostic; + let sd = cx.sess.diagnostic(); match attr.meta_item_list() { // Handle #[should_panic(expected = "foo")] @@ -535,16 +535,20 @@ fn check_test_signature( f: &ast::Fn, ) -> Result<(), ErrorGuaranteed> { let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); - let sd = &cx.sess.parse_sess.span_diagnostic; + let sd = cx.sess.diagnostic(); if let ast::Unsafe::Yes(span) = f.sig.header.unsafety { return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" })); } - if let ast::Async::Yes { span, .. } = f.sig.header.asyncness { + if let Some(ast::CoroutineKind::Async { span, .. }) = f.sig.header.coro_kind { return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" })); } + if let Some(ast::CoroutineKind::Gen { span, .. }) = f.sig.header.coro_kind { + return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "gen" })); + } + // If the termination trait is active, the compiler will check that the output // type implements the `Termination` trait as `libtest` enforces that. let has_output = match &f.sig.decl.output { @@ -579,7 +583,7 @@ fn check_bench_signature( // N.B., inadequate check, but we're running // well before resolve, can't get too deep. if f.sig.decl.inputs.len() != 1 { - return Err(cx.sess.parse_sess.span_diagnostic.emit_err(errors::BenchSig { span: i.span })); + return Err(cx.sess.diagnostic().emit_err(errors::BenchSig { span: i.span })); } Ok(()) } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index c7999a226c7d9..380556c3ca5f0 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -60,7 +60,7 @@ pub fn inject( // Do this here so that the test_runner crate attribute gets marked as used // even in non-test builds - let test_runner = get_test_runner(span_diagnostic, &krate); + let test_runner = get_test_runner(span_diagnostic, krate); if sess.is_test_crate() { let panic_strategy = match (panic_strategy, sess.opts.unstable_opts.panic_abort_tests) { @@ -372,7 +372,7 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P { let ecx = &cx.ext_cx; let mut tests = cx.test_cases.clone(); - tests.sort_by(|a, b| a.name.as_str().cmp(&b.name.as_str())); + tests.sort_by(|a, b| a.name.as_str().cmp(b.name.as_str())); ecx.expr_array_ref( sp, diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 9463a1418ce31..eeaf00004e630 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -10,7 +10,7 @@ pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, na let template = AttributeTemplate { word: true, ..Default::default() }; validate_attr::check_builtin_meta_item( &ecx.sess.parse_sess, - &meta_item, + meta_item, AttrStyle::Outer, name, template, diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml index 12aa69d3c7956..bd3b051185b46 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml @@ -35,6 +35,10 @@ jobs: steps: - uses: actions/checkout@v3 + - name: CPU features + if: matrix.os == 'ubuntu-latest' + run: cat /proc/cpuinfo + - name: Cache cargo target dir uses: actions/cache@v3 with: diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index 47d9a3b93f729..05dc28d074530 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -66,6 +66,10 @@ jobs: steps: - uses: actions/checkout@v3 + - name: CPU features + if: matrix.os == 'ubuntu-latest' + run: cat /proc/cpuinfo + - name: Cache cargo target dir uses: actions/cache@v3 with: @@ -136,6 +140,9 @@ jobs: steps: - uses: actions/checkout@v3 + - name: CPU features + run: cat /proc/cpuinfo + - name: Prepare dependencies run: ./y.sh prepare @@ -159,6 +166,9 @@ jobs: steps: - uses: actions/checkout@v3 + - name: CPU features + run: cat /proc/cpuinfo + - name: Cache cargo target dir uses: actions/cache@v3 with: diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml index b49dc3aff7aaa..cb5dd51fee310 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml @@ -11,6 +11,9 @@ jobs: steps: - uses: actions/checkout@v3 + - name: CPU features + run: cat /proc/cpuinfo + - name: Cache cargo target dir uses: actions/cache@v3 with: @@ -31,6 +34,9 @@ jobs: steps: - uses: actions/checkout@v3 + - name: CPU features + run: cat /proc/cpuinfo + - name: Cache cargo target dir uses: actions/cache@v3 with: diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index dcb6cc57584cf..901d1dbea66b3 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -21,9 +21,9 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arbitrary" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" [[package]] name = "bitflags" @@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f773437307980ac0f424bf9b9a5d0cd21a0f17248c6860c9a65bec8b5975f3fe" +checksum = "76eb38f2af690b5a4411d9a8782b6d77dabff3ca939e0518453ab9f9a4392d41" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443c2ac50e97fb7de1a0f862753fce3f27215558811a6fcee508eb0c3747fa79" +checksum = "39526c036b92912417e8931f52c1e235796688068d3efdbbd8b164f299d19156" dependencies = [ "bumpalo", "cranelift-bforest", @@ -75,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b174c411480c79ce0793c55042fa51bec27e486381d103a53cab3b480cb2db" +checksum = "fdb0deedc9fccf2db53a5a3c9c9d0163e44143b0d004dca9bf6ab6a0024cd79a" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fa0151a528066a369de6debeea4d4b23a32aba68b5add8c46d3dc8091ff434" +checksum = "cea2d1b274e45aa8e61e9103efa1ba82d4b5a19d12bd1fd10744c3b7380ba3ff" [[package]] name = "cranelift-control" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8adf1e6398493c9bea1190e37d28a0eb0eca5fddbc80e01e506cda34db92b1f" +checksum = "6ea5977559a71e63db79a263f0e81a89b996e8a38212c4281e37dd1dbaa8b65c" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4917e2ed3bb5fe87d0ed88395ca6d644018d119a034faedd1f3e1f2c33cd52b2" +checksum = "2f871ada808b58158d84dfc43a6a2e2d2756baaf4ed1c51fd969ca8330e6ca5c" [[package]] name = "cranelift-frontend" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aaadf1e7cf28886bbf046eaf7ef538997bc8a7e020e578ea4957b39da87d5a1" +checksum = "e8e6890f587ef59824b3debe577e68fdf9b307b3808c54b8d93a18fd0b70941b" dependencies = [ "cranelift-codegen", "log", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67fda31b9d69eaa1c49a2081939454c45857596a9d45af6744680541c628b4c" +checksum = "a8d5fc6d5d3b52d1917002b17a8ecce448c2621b5bf394bb4e77e2f676893537" [[package]] name = "cranelift-jit" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bf32710628e7ff298739f1ed80a0bfdafc0c6a3e284c4540b23f18e8889d4b" +checksum = "e8a2d7744f743f59d9646d7589ad22ea17ed0d71e04906eb77c31e99bc13bd8b" dependencies = [ "anyhow", "cranelift-codegen", @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d693e93a0fbf56b4bc93cffe6b107c2e52f070e1111950505fc8c83ac440b9d" +checksum = "b96cb196334698e612c197d7d0ae59af5e07667306ec20d7be414717db400873" dependencies = [ "anyhow", "cranelift-codegen", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76fb52ba71be98312f35e798d9e98e45ab2586f27584231bf7c644fa9501e8af" +checksum = "3e10c2e7faa65d4ae7de9a83b44f2c31aca7dc638e17d0a79572fdf8103d720b" dependencies = [ "cranelift-codegen", "libc", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.101.2" +version = "0.102.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2551b2e185022b89e9efa5e04c0f17f679b86ef73d9f7feabc48b608ff23120d" +checksum = "83ce94e18756058af8a66e3c0ba1123ae15517c72162d8060d0cb0974642adf2" dependencies = [ "anyhow", "cranelift-codegen", @@ -295,9 +295,9 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "regalloc2" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b4dcbd3a2ae7fb94b5813fa0e957c6ab51bf5d0a8ee1b69e0c2d0f1e6eb8485" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" dependencies = [ "hashbrown 0.13.2", "log", @@ -374,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "14.0.2" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0980a96b16abbdaf829858d2389697b1d6cfc6a903873fd74b7e47a6b1045584" +checksum = "b73ad1395eda136baec5ece7e079e0536a82ef73488e345456cc9b89858ad0ec" dependencies = [ "cfg-if", "libc", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 30db10f745715..20fcd22273219 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.101.2", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.101.2" } -cranelift-module = { version = "0.101.2" } -cranelift-native = { version = "0.101.2" } -cranelift-jit = { version = "0.101.2", optional = true } -cranelift-object = { version = "0.101.2" } +cranelift-codegen = { version = "0.102", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.102" } +cranelift-module = { version = "0.102" } +cranelift-native = { version = "0.102" } +cranelift-jit = { version = "0.102", optional = true } +cranelift-object = { version = "0.102" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 5664cbe7d4fac..ca6ecdf1d0e88 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -5,8 +5,48 @@ This has the potential to improve compilation times in debug mode. If your project doesn't use any of the things listed under "Not yet supported", it should work fine. If not please open an issue. +## Download using Rustup + +The Cranelift codegen backend is distributed in nightly builds on Linux and x86_64 macOS. If you want to +install it using Rustup, you can do that by running: + +```bash +$ rustup component add rustc-codegen-cranelift-preview --toolchain nightly +``` + +Once it is installed, you can enable it with one of the following approaches: +- `CARGO_PROFILE_DEV_CODEGEN_BACKEND=cranelift cargo +nightly build -Zcodegen-backend` +- `RUSTFLAGS="-Zcodegen-backend=cranelift" cargo +nightly build` +- Add the following to `.cargo/config.toml`: + ```toml + [unstable] + codegen-backend = true + + [profile.dev] + codegen-backend = "cranelift" + ``` +- Add the following to `Cargo.toml`: + ```toml + # This line needs to come before anything else in Cargo.toml + cargo-features = ["codegen-backend"] + + [profile.dev] + codegen-backend = "cranelift" + ``` + +## Precompiled builds + +You can also download a pre-built version from the [releases] page. +Extract the `dist` directory in the archive anywhere you want. +If you want to use `cargo clif build` instead of having to specify the full path to the `cargo-clif` executable, you can add the `bin` subdirectory of the extracted `dist` directory to your `PATH`. +(tutorial [for Windows](https://stackoverflow.com/a/44272417), and [for Linux/MacOS](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path/26059#26059)). + +[releases]: https://github.com/rust-lang/rustc_codegen_cranelift/releases/tag/dev + ## Building and testing +If you want to build the backend manually, you can download it from GitHub and build it yourself: + ```bash $ git clone https://github.com/rust-lang/rustc_codegen_cranelift $ cd rustc_codegen_cranelift @@ -22,15 +62,6 @@ $ ./test.sh For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.sh`. -## Precompiled builds - -Alternatively you can download a pre built version from the [releases] page. -Extract the `dist` directory in the archive anywhere you want. -If you want to use `cargo clif build` instead of having to specify the full path to the `cargo-clif` executable, you can add the `bin` subdirectory of the extracted `dist` directory to your `PATH`. -(tutorial [for Windows](https://stackoverflow.com/a/44272417), and [for Linux/MacOS](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path/26059#26059)). - -[releases]: https://github.com/rust-lang/rustc_codegen_cranelift/releases/tag/dev - ## Usage rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects. @@ -76,8 +107,6 @@ configuration options. ## Not yet supported -* Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041)) - * On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`. * SIMD ([tracked here](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported) * Unwinding on panics ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1677), `-Cpanic=abort` is enabled by default) diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index 1e24d1b113fe6..3309a0a6abd1f 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -99,6 +99,20 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ TestCase::build_bin_and_run("aot.mod_bench", "example/mod_bench.rs", &[]), TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]), TestCase::build_bin("aot.issue-59326", "example/issue-59326.rs"), + TestCase::custom("aot.polymorphize_coroutine", &|runner| { + runner.run_rustc(&["example/polymorphize_coroutine.rs", "-Zpolymorphize"]); + runner.run_out_command("polymorphize_coroutine", &[]); + }), + TestCase::build_bin_and_run("aot.neon", "example/neon.rs", &[]), + TestCase::custom("aot.gen_block_iterate", &|runner| { + runner.run_rustc([ + "example/gen_block_iterate.rs", + "--edition", + "2024", + "-Zunstable-options", + ]); + runner.run_out_command("gen_block_iterate", &[]); + }), ]; pub(crate) static RAND_REPO: GitRepo = GitRepo::github( @@ -456,6 +470,9 @@ impl<'a> TestRunner<'a> { cmd.arg("--target"); cmd.arg(&self.target_compiler.triple); cmd.arg("-Cpanic=abort"); + cmd.arg("-Zunstable-options"); + cmd.arg("--check-cfg=cfg(no_unstable_features)"); + cmd.arg("--check-cfg=cfg(jit)"); cmd.args(args); cmd } diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt index 7ff805e58d967..0b7cac1883761 100644 --- a/compiler/rustc_codegen_cranelift/config.txt +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -42,6 +42,9 @@ aot.float-minmax-pass aot.mod_bench aot.issue-72793 aot.issue-59326 +aot.polymorphize_coroutine +aot.neon +aot.gen_block_iterate testsuite.extended_sysroot test.rust-random/rand diff --git a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs new file mode 100644 index 0000000000000..14bd23e77ea01 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs @@ -0,0 +1,36 @@ +// Copied from https://github.com/rust-lang/rust/blob/46455dc65069387f2dc46612f13fd45452ab301a/tests/ui/coroutine/gen_block_iterate.rs +// revisions: next old +//compile-flags: --edition 2024 -Zunstable-options +//[next] compile-flags: -Ztrait-solver=next +// run-pass +#![feature(gen_blocks)] + +fn foo() -> impl Iterator { + gen { yield 42; for x in 3..6 { yield x } } +} + +fn moved() -> impl Iterator { + let mut x = "foo".to_string(); + gen move { + yield 42; + if x == "foo" { return } + x.clear(); + for x in 3..6 { yield x } + } +} + +fn main() { + let mut iter = foo(); + assert_eq!(iter.next(), Some(42)); + assert_eq!(iter.next(), Some(3)); + assert_eq!(iter.next(), Some(4)); + assert_eq!(iter.next(), Some(5)); + assert_eq!(iter.next(), None); + // `gen` blocks are fused + assert_eq!(iter.next(), None); + + let mut iter = moved(); + assert_eq!(iter.next(), Some(42)); + assert_eq!(iter.next(), None); + +} diff --git a/compiler/rustc_codegen_cranelift/example/neon.rs b/compiler/rustc_codegen_cranelift/example/neon.rs new file mode 100644 index 0000000000000..bad26947967dc --- /dev/null +++ b/compiler/rustc_codegen_cranelift/example/neon.rs @@ -0,0 +1,234 @@ +// Most of these tests are copied from https://github.com/japaric/stdsimd/blob/0f4413d01c4f0c3ffbc5a69e9a37fbc7235b31a9/coresimd/arm/neon.rs + +#![feature(portable_simd)] + +#[cfg(target_arch = "aarch64")] +use std::arch::aarch64::*; +use std::mem::transmute; +use std::simd::*; + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_s8() { + let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]); + let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); + let e = i8x8::from([-2, -4, 5, 7, 0, 2, 4, 6]); + let r: i8x8 = transmute(vpmin_s8(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_s16() { + let a = i16x4::from([1, 2, 3, -4]); + let b = i16x4::from([0, 3, 2, 5]); + let e = i16x4::from([1, -4, 0, 2]); + let r: i16x4 = transmute(vpmin_s16(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_s32() { + let a = i32x2::from([1, -2]); + let b = i32x2::from([0, 3]); + let e = i32x2::from([-2, 0]); + let r: i32x2 = transmute(vpmin_s32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); + let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); + let e = u8x8::from([1, 3, 5, 7, 0, 2, 4, 6]); + let r: u8x8 = transmute(vpmin_u8(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_u16() { + let a = u16x4::from([1, 2, 3, 4]); + let b = u16x4::from([0, 3, 2, 5]); + let e = u16x4::from([1, 3, 0, 2]); + let r: u16x4 = transmute(vpmin_u16(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_u32() { + let a = u32x2::from([1, 2]); + let b = u32x2::from([0, 3]); + let e = u32x2::from([1, 0]); + let r: u32x2 = transmute(vpmin_u32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmin_f32() { + let a = f32x2::from([1., -2.]); + let b = f32x2::from([0., 3.]); + let e = f32x2::from([-2., 0.]); + let r: f32x2 = transmute(vpmin_f32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_s8() { + let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]); + let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); + let e = i8x8::from([1, 3, 6, 8, 3, 5, 7, 9]); + let r: i8x8 = transmute(vpmax_s8(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_s16() { + let a = i16x4::from([1, 2, 3, -4]); + let b = i16x4::from([0, 3, 2, 5]); + let e = i16x4::from([2, 3, 3, 5]); + let r: i16x4 = transmute(vpmax_s16(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_s32() { + let a = i32x2::from([1, -2]); + let b = i32x2::from([0, 3]); + let e = i32x2::from([1, 3]); + let r: i32x2 = transmute(vpmax_s32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); + let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); + let e = u8x8::from([2, 4, 6, 8, 3, 5, 7, 9]); + let r: u8x8 = transmute(vpmax_u8(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_u16() { + let a = u16x4::from([1, 2, 3, 4]); + let b = u16x4::from([0, 3, 2, 5]); + let e = u16x4::from([2, 4, 3, 5]); + let r: u16x4 = transmute(vpmax_u16(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_u32() { + let a = u32x2::from([1, 2]); + let b = u32x2::from([0, 3]); + let e = u32x2::from([2, 3]); + let r: u32x2 = transmute(vpmax_u32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpmax_f32() { + let a = f32x2::from([1., -2.]); + let b = f32x2::from([0., 3.]); + let e = f32x2::from([1., 3.]); + let r: f32x2 = transmute(vpmax_f32(transmute(a), transmute(b))); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_s16() { + let a = i16x4::from([1, 2, 3, 4]); + let b = i16x4::from([0, -1, -2, -3]); + let r: i16x4 = transmute(vpadd_s16(transmute(a), transmute(b))); + let e = i16x4::from([3, 7, -1, -5]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_s32() { + let a = i32x2::from([1, 2]); + let b = i32x2::from([0, -1]); + let r: i32x2 = transmute(vpadd_s32(transmute(a), transmute(b))); + let e = i32x2::from([3, -1]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_s8() { + let a = i8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); + let b = i8x8::from([0, -1, -2, -3, -4, -5, -6, -7]); + let r: i8x8 = transmute(vpadd_s8(transmute(a), transmute(b))); + let e = i8x8::from([3, 7, 11, 15, -1, -5, -9, -13]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_u16() { + let a = u16x4::from([1, 2, 3, 4]); + let b = u16x4::from([30, 31, 32, 33]); + let r: u16x4 = transmute(vpadd_u16(transmute(a), transmute(b))); + let e = u16x4::from([3, 7, 61, 65]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_u32() { + let a = u32x2::from([1, 2]); + let b = u32x2::from([30, 31]); + let r: u32x2 = transmute(vpadd_u32(transmute(a), transmute(b))); + let e = u32x2::from([3, 61]); + assert_eq!(r, e); +} +#[cfg(target_arch = "aarch64")] +unsafe fn test_vpadd_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); + let b = u8x8::from([30, 31, 32, 33, 34, 35, 36, 37]); + let r: u8x8 = transmute(vpadd_u8(transmute(a), transmute(b))); + let e = u8x8::from([3, 7, 11, 15, 61, 65, 69, 73]); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vqsub_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]); + let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]); + let r: u8x8 = transmute(vqsub_u8(transmute(a), transmute(b))); + let e = u8x8::from([0, 1, 2, 3, 0, 0, 0, 218]); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +unsafe fn test_vqadd_u8() { + let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]); + let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]); + let r: u8x8 = transmute(vqadd_u8(transmute(a), transmute(b))); + let e = u8x8::from([31, 3, 4, 5, 39, 0xff, 43, 0xff]); + assert_eq!(r, e); +} + +#[cfg(target_arch = "aarch64")] +fn main() { + unsafe { + test_vpmin_s8(); + test_vpmin_s16(); + test_vpmin_s32(); + test_vpmin_u8(); + test_vpmin_u16(); + test_vpmin_u32(); + test_vpmin_f32(); + test_vpmax_s8(); + test_vpmax_s16(); + test_vpmax_s32(); + test_vpmax_u8(); + test_vpmax_u16(); + test_vpmax_u32(); + test_vpmax_f32(); + + test_vpadd_s16(); + test_vpadd_s32(); + test_vpadd_s8(); + test_vpadd_u16(); + test_vpadd_u32(); + test_vpadd_u8(); + + test_vqsub_u8(); + test_vqadd_u8(); + } +} + +#[cfg(not(target_arch = "aarch64"))] +fn main() {} diff --git a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs new file mode 100644 index 0000000000000..c965b34e13b90 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs @@ -0,0 +1,16 @@ +#![feature(coroutines, coroutine_trait)] + +use std::ops::Coroutine; +use std::pin::Pin; + +fn main() { + run_coroutine::(); +} + +fn run_coroutine() { + let mut coroutine = || { + yield; + return; + }; + Pin::new(&mut coroutine).resume(()); +} diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml index 9902bca8eab27..8a690bada0df5 100644 --- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml +++ b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.100" +version = "0.1.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c0f24437059853f0fa64afc51f338f93647a3de4cf3358ba1bb4171a199775" +checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242" dependencies = [ "cc", "rustc-std-workspace-core", @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" dependencies = [ "rustc-std-workspace-core", ] @@ -415,7 +415,6 @@ dependencies = [ name = "unwind" version = "0.0.0" dependencies = [ - "cc", "cfg-if", "compiler_builtins", "core", diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 7e3eaacf8ef08..2997816d96c7a 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-10-29" +channel = "nightly-2023-11-25" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml index ebeca8662a519..0f884187adddb 100644 --- a/compiler/rustc_codegen_cranelift/rustfmt.toml +++ b/compiler/rustc_codegen_cranelift/rustfmt.toml @@ -1,4 +1,7 @@ -ignore = ["y.rs"] +ignore = [ + "y.rs", + "example/gen_block_iterate.rs", # uses edition 2024 +] # Matches rustfmt.toml of rustc version = "Two" diff --git a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs index 33d51bdddeaf9..550f20515536e 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs @@ -27,7 +27,7 @@ fn main() { args.push(codegen_backend_arg); } if !passed_args.iter().any(|arg| { - arg == "--sysroot" || arg.to_str().map(|s| s.starts_with("--sysroot=")) == Some(true) + arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot=")) }) { args.push(OsString::from("--sysroot")); args.push(OsString::from(sysroot.to_str().unwrap())); diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs index 10582cc7bb320..f7d1bdbc4c6ff 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs @@ -27,7 +27,7 @@ fn main() { args.push(codegen_backend_arg); } if !passed_args.iter().any(|arg| { - arg == "--sysroot" || arg.to_str().map(|s| s.starts_with("--sysroot=")) == Some(true) + arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot=")) }) { args.push(OsString::from("--sysroot")); args.push(OsString::from(sysroot.to_str().unwrap())); diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index e62788f2e507d..355282911c255 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -46,7 +46,7 @@ case $1 in git pull origin master branch=sync_cg_clif-$(date +%Y-%m-%d) git checkout -b "$branch" - "$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/bjorn3/rustc_codegen_cranelift.git master + "$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/rust-lang/rustc_codegen_cranelift.git master git push -u my "$branch" # immediately merge the merge commit into cg_clif to prevent merge conflicts when syncing diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index bbb8a010d965f..731828caae2c4 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -1,15 +1,17 @@ #!/usr/bin/env bash set -e +# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we +# the LLVM backend isn't compiled in here. +export CG_CLIF_FORCE_GNU_AS=1 + # Compiletest expects all standard library paths to start with /rustc/FAKE_PREFIX. # CG_CLIF_STDLIB_REMAP_PATH_PREFIX will cause cg_clif's build system to pass # --remap-path-prefix to handle this. -# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we -# the LLVM backend isn't compiled in here. -CG_CLIF_FORCE_GNU_AS=1 CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build +CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build echo "[SETUP] Rust fork" -git clone https://github.com/rust-lang/rust.git || true +git clone https://github.com/rust-lang/rust.git --filter=tree:0 || true pushd rust git fetch git checkout -- . diff --git a/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh b/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh index a8f6d7a202486..791d457993de3 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh @@ -11,7 +11,5 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src} cp ../Cargo.* compiler/rustc_codegen_cranelift/ cp -r ../src compiler/rustc_codegen_cranelift/src -# CG_CLIF_FORCE_GNU_AS will force usage of as instead of the LLVM backend of rustc as we -# the LLVM backend isn't compiled in here. -CG_CLIF_FORCE_GNU_AS=1 ./x.py build --stage 1 library/std +./x.py build --stage 1 library/std popd diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index c4572e035258d..0ff1473da4313 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -383,6 +383,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( args, ret_place, target, + source_info.span, ); return; } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 91b1547cb6ea6..71557d49ef2c3 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -456,7 +456,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { ); } - crate::inline_asm::codegen_inline_asm( + crate::inline_asm::codegen_inline_asm_terminator( fx, source_info.span, template, diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs index 20f2ee4c76a57..978891f2b0db5 100644 --- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs +++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs @@ -64,7 +64,7 @@ impl ConcurrencyLimiter { // Make sure to drop the mutex guard first to prevent poisoning the mutex. drop(state); if let Some(err) = err { - handler.fatal(err).raise(); + handler.fatal(err); } else { // The error was already emitted, but compilation continued. Raise a silent // fatal error. diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index b0853d30e03b8..65f7ee6999a7c 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -1,10 +1,13 @@ //! Handling of `static`s, `const`s and promoted allocations +use std::cmp::Ordering; + use cranelift_module::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{read_target_uint, AllocId, GlobalAlloc, Scalar}; use rustc_middle::mir::ConstValue; +use rustc_middle::ty::ScalarInt; use crate::prelude::*; @@ -123,7 +126,8 @@ pub(crate) fn codegen_const_value<'tcx>( } } Scalar::Ptr(ptr, _size) => { - let (alloc_id, offset) = ptr.into_parts(); // we know the `offset` is relative + let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative + let alloc_id = prov.alloc_id(); let base_addr = match fx.tcx.global_alloc(alloc_id) { GlobalAlloc::Memory(alloc) => { let data_id = data_id_for_alloc_id( @@ -371,7 +375,8 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec(); data.define(bytes.into_boxed_slice()); - for &(offset, alloc_id) in alloc.provenance().ptrs().iter() { + for &(offset, prov) in alloc.provenance().ptrs().iter() { + let alloc_id = prov.alloc_id(); let addend = { let endianness = tcx.data_layout.endian; let offset = offset.bytes() as usize; @@ -430,9 +435,9 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant pub(crate) fn mir_operand_get_const_val<'tcx>( fx: &FunctionCx<'_, '_, 'tcx>, operand: &Operand<'tcx>, -) -> Option> { +) -> Option { match operand { - Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).0), + Operand::Constant(const_) => eval_mir_constant(fx, const_).0.try_to_scalar_int(), // FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored // inside a temporary before being passed to the intrinsic requiring the const argument. // This code tries to find a single constant defining definition of the referenced local. @@ -440,7 +445,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( if !place.projection.is_empty() { return None; } - let mut computed_const_val = None; + let mut computed_scalar_int = None; for bb_data in fx.mir.basic_blocks.iter() { for stmt in &bb_data.statements { match &stmt.kind { @@ -456,22 +461,38 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( operand, ty, ) => { - if computed_const_val.is_some() { + if computed_scalar_int.is_some() { return None; // local assigned twice } if !matches!(ty.kind(), ty::Uint(_) | ty::Int(_)) { return None; } - let const_val = mir_operand_get_const_val(fx, operand)?; - if fx.layout_of(*ty).size - != const_val.try_to_scalar_int()?.size() + let scalar_int = mir_operand_get_const_val(fx, operand)?; + let scalar_int = match fx + .layout_of(*ty) + .size + .cmp(&scalar_int.size()) { - return None; - } - computed_const_val = Some(const_val); + Ordering::Equal => scalar_int, + Ordering::Less => match ty.kind() { + ty::Uint(_) => ScalarInt::try_from_uint( + scalar_int.try_to_uint(scalar_int.size()).unwrap(), + fx.layout_of(*ty).size, + ) + .unwrap(), + ty::Int(_) => ScalarInt::try_from_int( + scalar_int.try_to_int(scalar_int.size()).unwrap(), + fx.layout_of(*ty).size, + ) + .unwrap(), + _ => unreachable!(), + }, + Ordering::Greater => return None, + }; + computed_scalar_int = Some(scalar_int); } Rvalue::Use(operand) => { - computed_const_val = mir_operand_get_const_val(fx, operand) + computed_scalar_int = mir_operand_get_const_val(fx, operand) } _ => return None, } @@ -522,7 +543,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( TerminatorKind::Call { .. } => {} } } - computed_const_val + computed_scalar_int } } } diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 331649b2ec24f..25d14319f5791 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -10,10 +10,10 @@ use target_lexicon::BinaryFormat; use crate::prelude::*; -enum CInlineAsmOperand<'tcx> { +pub(crate) enum CInlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, - value: CValue<'tcx>, + value: Value, }, Out { reg: InlineAsmRegOrRegClass, @@ -23,7 +23,7 @@ enum CInlineAsmOperand<'tcx> { InOut { reg: InlineAsmRegOrRegClass, _late: bool, - in_value: CValue<'tcx>, + in_value: Value, out_place: Option>, }, Const { @@ -34,7 +34,7 @@ enum CInlineAsmOperand<'tcx> { }, } -pub(crate) fn codegen_inline_asm<'tcx>( +pub(crate) fn codegen_inline_asm_terminator<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span, template: &[InlineAsmTemplatePiece], @@ -42,12 +42,12 @@ pub(crate) fn codegen_inline_asm<'tcx>( options: InlineAsmOptions, destination: Option, ) { - // FIXME add .eh_frame unwind info directives - // Used by panic_abort on Windows, but uses a syntax which only happens to work with // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for // the LLVM backend. - if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { + if template.len() == 1 + && template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) + { fx.bcx.ins().trap(TrapCode::User(1)); return; } @@ -55,9 +55,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( let operands = operands .into_iter() .map(|operand| match *operand { - InlineAsmOperand::In { reg, ref value } => { - CInlineAsmOperand::In { reg, value: crate::base::codegen_operand(fx, value) } - } + InlineAsmOperand::In { reg, ref value } => CInlineAsmOperand::In { + reg, + value: crate::base::codegen_operand(fx, value).load_scalar(fx), + }, InlineAsmOperand::Out { reg, late, ref place } => CInlineAsmOperand::Out { reg, late, @@ -67,7 +68,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( CInlineAsmOperand::InOut { reg, _late: late, - in_value: crate::base::codegen_operand(fx, in_value), + in_value: crate::base::codegen_operand(fx, in_value).load_scalar(fx), out_place: out_place.map(|place| crate::base::codegen_place(fx, place)), } } @@ -132,15 +133,33 @@ pub(crate) fn codegen_inline_asm<'tcx>( }) .collect::>(); - let mut inputs = Vec::new(); - let mut outputs = Vec::new(); + codegen_inline_asm_inner(fx, template, &operands, options); + + match destination { + Some(destination) => { + let destination_block = fx.get_block(destination); + fx.bcx.ins().jump(destination_block, &[]); + } + None => { + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + } + } +} + +pub(crate) fn codegen_inline_asm_inner<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + template: &[InlineAsmTemplatePiece], + operands: &[CInlineAsmOperand<'tcx>], + options: InlineAsmOptions, +) { + // FIXME add .eh_frame unwind info directives let mut asm_gen = InlineAssemblyGenerator { tcx: fx.tcx, arch: fx.tcx.sess.asm_arch.unwrap(), enclosing_def_id: fx.instance.def_id(), template, - operands: &operands, + operands, options, registers: Vec::new(), stack_slots_clobber: Vec::new(), @@ -162,10 +181,12 @@ pub(crate) fn codegen_inline_asm<'tcx>( let generated_asm = asm_gen.generate_asm_wrapper(&asm_name); fx.cx.global_asm.push_str(&generated_asm); + let mut inputs = Vec::new(); + let mut outputs = Vec::new(); for (i, operand) in operands.iter().enumerate() { match operand { CInlineAsmOperand::In { reg: _, value } => { - inputs.push((asm_gen.stack_slots_input[i].unwrap(), value.load_scalar(fx))); + inputs.push((asm_gen.stack_slots_input[i].unwrap(), *value)); } CInlineAsmOperand::Out { reg: _, late: _, place } => { if let Some(place) = place { @@ -173,7 +194,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( } } CInlineAsmOperand::InOut { reg: _, _late: _, in_value, out_place } => { - inputs.push((asm_gen.stack_slots_input[i].unwrap(), in_value.load_scalar(fx))); + inputs.push((asm_gen.stack_slots_input[i].unwrap(), *in_value)); if let Some(out_place) = out_place { outputs.push((asm_gen.stack_slots_output[i].unwrap(), *out_place)); } @@ -183,16 +204,6 @@ pub(crate) fn codegen_inline_asm<'tcx>( } call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs); - - match destination { - Some(destination) => { - let destination_block = fx.get_block(destination); - fx.bcx.ins().jump(destination_block, &[]); - } - None => { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - } - } } struct InlineAssemblyGenerator<'a, 'tcx> { @@ -634,8 +645,21 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { ) { match arch { InlineAsmArch::X86_64 => { - write!(generated_asm, " mov [rbx+0x{:x}], ", offset.bytes()).unwrap(); - reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); + match reg { + InlineAsmReg::X86(reg) + if reg as u32 >= X86InlineAsmReg::xmm0 as u32 + && reg as u32 <= X86InlineAsmReg::xmm15 as u32 => + { + // rustc emits x0 rather than xmm0 + write!(generated_asm, " movups [rbx+0x{:x}], ", offset.bytes()).unwrap(); + write!(generated_asm, "xmm{}", reg as u32 - X86InlineAsmReg::xmm0 as u32) + .unwrap(); + } + _ => { + write!(generated_asm, " mov [rbx+0x{:x}], ", offset.bytes()).unwrap(); + reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); + } + } generated_asm.push('\n'); } InlineAsmArch::AArch64 => { @@ -660,8 +684,24 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { ) { match arch { InlineAsmArch::X86_64 => { - generated_asm.push_str(" mov "); - reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); + match reg { + InlineAsmReg::X86(reg) + if reg as u32 >= X86InlineAsmReg::xmm0 as u32 + && reg as u32 <= X86InlineAsmReg::xmm15 as u32 => + { + // rustc emits x0 rather than xmm0 + write!( + generated_asm, + " movups xmm{}", + reg as u32 - X86InlineAsmReg::xmm0 as u32 + ) + .unwrap(); + } + _ => { + generated_asm.push_str(" mov "); + reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap() + } + } writeln!(generated_asm, ", [rbx+0x{:x}]", offset.bytes()).unwrap(); } InlineAsmArch::AArch64 => { @@ -717,7 +757,12 @@ fn call_inline_asm<'tcx>( fx.bcx.ins().call(inline_asm_func, &[stack_slot_addr]); for (offset, place) in outputs { - let ty = fx.clif_type(place.layout().ty).unwrap(); + let ty = if place.layout().ty.is_simd() { + let (lane_count, lane_type) = place.layout().ty.simd_size_and_type(fx.tcx); + fx.clif_type(lane_type).unwrap().by(lane_count.try_into().unwrap()).unwrap() + } else { + fx.clif_type(place.layout().ty).unwrap() + }; let value = stack_slot.offset(fx, i32::try_from(offset.bytes()).unwrap().into()).load( fx, ty, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index c169476099806..659e6c133ef5e 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -12,6 +12,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( args: &[mir::Operand<'tcx>], ret: CPlace<'tcx>, target: Option, + span: Span, ) { if intrinsic.starts_with("llvm.aarch64") { return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call( @@ -31,6 +32,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( args, ret, target, + span, ); } @@ -51,6 +53,21 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( }); } + _ if intrinsic.starts_with("llvm.fma.v") => { + intrinsic_args!(fx, args => (x,y,z); intrinsic); + + simd_trio_for_each_lane( + fx, + x, + y, + z, + ret, + &|fx, _lane_ty, _res_lane_ty, lane_x, lane_y, lane_z| { + fx.bcx.ins().fma(lane_x, lane_y, lane_z) + }, + ); + } + _ => { fx.tcx .sess diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs index 0c211a06dc4a7..ee098be1fce6b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs @@ -44,7 +44,9 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } - _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") => { + _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") + || intrinsic.starts_with("llvm.aarch64.neon.uqadd.v") => + { intrinsic_args!(fx, args => (x, y); intrinsic); simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| { @@ -52,7 +54,9 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } - _ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") => { + _ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") + || intrinsic.starts_with("llvm.aarch64.neon.uqsub.v") => + { intrinsic_args!(fx, args => (x, y); intrinsic); simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| { @@ -156,6 +160,90 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } + _ if intrinsic.starts_with("llvm.aarch64.neon.umaxp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().umax(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.smaxp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().smax(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.uminp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().umin(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.sminp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().smin(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.fminp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().fmin(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.fmaxp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().fmax(x_lane, y_lane), + ); + } + + _ if intrinsic.starts_with("llvm.aarch64.neon.addp.v") => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + simd_horizontal_pair_for_each_lane( + fx, + x, + y, + ret, + &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| fx.bcx.ins().iadd(x_lane, y_lane), + ); + } + // FIXME generalize vector types "llvm.aarch64.neon.tbl1.v16i8" => { intrinsic_args!(fx, args => (t, idx); intrinsic); @@ -172,25 +260,6 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( } } - // FIXME generalize vector types - "llvm.aarch64.neon.umaxp.v16i8" => { - intrinsic_args!(fx, args => (a, b); intrinsic); - - // FIXME add helper for horizontal pairwise operations - for i in 0..8 { - let lane1 = a.value_lane(fx, i * 2).load_scalar(fx); - let lane2 = a.value_lane(fx, i * 2 + 1).load_scalar(fx); - let res = fx.bcx.ins().umax(lane1, lane2); - ret.place_lane(fx, i).to_ptr().store(fx, res, MemFlags::trusted()); - } - for i in 0..8 { - let lane1 = b.value_lane(fx, i * 2).load_scalar(fx); - let lane2 = b.value_lane(fx, i * 2 + 1).load_scalar(fx); - let res = fx.bcx.ins().umax(lane1, lane2); - ret.place_lane(fx, 8 + i).to_ptr().store(fx, res, MemFlags::trusted()); - } - } - /* _ if intrinsic.starts_with("llvm.aarch64.neon.sshl.v") || intrinsic.starts_with("llvm.aarch64.neon.sqshl.v") diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index ea5997a14bb74..07b95b7933d0a 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -1,7 +1,10 @@ //! Emulate x86 LLVM intrinsics +use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::ty::GenericArgsRef; +use rustc_target::asm::*; +use crate::inline_asm::{codegen_inline_asm_inner, CInlineAsmOperand}; use crate::intrinsics::*; use crate::prelude::*; @@ -12,24 +15,160 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( args: &[mir::Operand<'tcx>], ret: CPlace<'tcx>, target: Option, + span: Span, ) { match intrinsic { "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => { // Spin loop hint } + "llvm.x86.avx.vzeroupper" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_zeroupper&ig_expand=7218 + // Do nothing. It is a perf hint anyway. + } + // Used by is_x86_feature_detected!(); "llvm.x86.xgetbv" => { - // FIXME use the actual xgetbv instruction - intrinsic_args!(fx, args => (v); intrinsic); + intrinsic_args!(fx, args => (xcr_no); intrinsic); + + let xcr_no = xcr_no.load_scalar(fx); - let v = v.load_scalar(fx); + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + " + xgetbv + // out = rdx << 32 | rax + shl rdx, 32 + or rax, rdx + " + .to_string(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), + value: xcr_no, + }, + CInlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + late: true, + place: Some(ret), + }, + CInlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + late: true, + place: None, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } - // As of writing on XCR0 exists - fx.bcx.ins().trapnz(v, TrapCode::UnreachableCodeReached); + "llvm.x86.sse3.ldu.dq" | "llvm.x86.avx.ldu.dq.256" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_lddqu_si128&ig_expand=4009 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_lddqu_si256&ig_expand=4010 + intrinsic_args!(fx, args => (ptr); intrinsic); - let res = fx.bcx.ins().iconst(types::I64, 1 /* bit 0 must be set */); - ret.write_cvalue(fx, CValue::by_val(res, fx.layout_of(fx.tcx.types.i64))); + // FIXME correctly handle unalignedness + let val = CValue::by_ref(Pointer::new(ptr.load_scalar(fx)), ret.layout()); + ret.write_cvalue(fx, val); + } + + "llvm.x86.avx2.gather.d.d" + | "llvm.x86.avx2.gather.d.q" + | "llvm.x86.avx2.gather.d.ps" + | "llvm.x86.avx2.gather.d.pd" + | "llvm.x86.avx2.gather.d.d.256" + | "llvm.x86.avx2.gather.d.q.256" + | "llvm.x86.avx2.gather.d.ps.256" + | "llvm.x86.avx2.gather.d.pd.256" + | "llvm.x86.avx2.gather.q.d" + | "llvm.x86.avx2.gather.q.q" + | "llvm.x86.avx2.gather.q.ps" + | "llvm.x86.avx2.gather.q.pd" + | "llvm.x86.avx2.gather.q.d.256" + | "llvm.x86.avx2.gather.q.q.256" + | "llvm.x86.avx2.gather.q.ps.256" + | "llvm.x86.avx2.gather.q.pd.256" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_i64gather_pd&ig_expand=3818 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mask_i64gather_pd&ig_expand=3819 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_i64gather_pd&ig_expand=3821 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mask_i64gather_pd&ig_expand=3822 + // ... + + intrinsic_args!(fx, args => (src, ptr, index, mask, scale); intrinsic); + + let (src_lane_count, src_lane_ty) = src.layout().ty.simd_size_and_type(fx.tcx); + let (index_lane_count, index_lane_ty) = index.layout().ty.simd_size_and_type(fx.tcx); + let (mask_lane_count, mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(src_lane_ty, ret_lane_ty); + assert!(index_lane_ty.is_integral()); + assert_eq!(src_lane_count, mask_lane_count); + assert_eq!(src_lane_count, ret_lane_count); + + let lane_clif_ty = fx.clif_type(ret_lane_ty).unwrap(); + let index_lane_clif_ty = fx.clif_type(index_lane_ty).unwrap(); + let mask_lane_clif_ty = fx.clif_type(mask_lane_ty).unwrap(); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + + let ptr = ptr.load_scalar(fx); + let scale = scale.load_scalar(fx); + let scale = fx.bcx.ins().uextend(types::I64, scale); + for lane_idx in 0..std::cmp::min(src_lane_count, index_lane_count) { + let src_lane = src.value_lane(fx, lane_idx).load_scalar(fx); + let index_lane = index.value_lane(fx, lane_idx).load_scalar(fx); + let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx); + let mask_lane = + fx.bcx.ins().bitcast(mask_lane_clif_ty.as_int(), MemFlags::new(), mask_lane); + + let if_enabled = fx.bcx.create_block(); + let if_disabled = fx.bcx.create_block(); + let next = fx.bcx.create_block(); + let res_lane = fx.bcx.append_block_param(next, lane_clif_ty); + + let mask_lane = match mask_lane_clif_ty { + types::I32 | types::F32 => { + fx.bcx.ins().band_imm(mask_lane, 0x8000_0000u64 as i64) + } + types::I64 | types::F64 => { + fx.bcx.ins().band_imm(mask_lane, 0x8000_0000_0000_0000u64 as i64) + } + _ => unreachable!(), + }; + fx.bcx.ins().brif(mask_lane, if_enabled, &[], if_disabled, &[]); + fx.bcx.seal_block(if_enabled); + fx.bcx.seal_block(if_disabled); + + fx.bcx.switch_to_block(if_enabled); + let index_lane = if index_lane_clif_ty != types::I64 { + fx.bcx.ins().sextend(types::I64, index_lane) + } else { + index_lane + }; + let offset = fx.bcx.ins().imul(index_lane, scale); + let lane_ptr = fx.bcx.ins().iadd(ptr, offset); + let res = fx.bcx.ins().load(lane_clif_ty, MemFlags::trusted(), lane_ptr, 0); + fx.bcx.ins().jump(next, &[res]); + + fx.bcx.switch_to_block(if_disabled); + fx.bcx.ins().jump(next, &[src_lane]); + + fx.bcx.seal_block(next); + fx.bcx.switch_to_block(next); + + fx.bcx.ins().nop(); + + ret.place_lane(fx, lane_idx) + .write_cvalue(fx, CValue::by_val(res_lane, ret_lane_layout)); + } + + for lane_idx in std::cmp::min(src_lane_count, index_lane_count)..ret_lane_count { + let zero_lane = fx.bcx.ins().iconst(mask_lane_clif_ty.as_int(), 0); + let zero_lane = fx.bcx.ins().bitcast(mask_lane_clif_ty, MemFlags::new(), zero_lane); + ret.place_lane(fx, lane_idx) + .write_cvalue(fx, CValue::by_val(zero_lane, ret_lane_layout)); + } } "llvm.x86.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => { @@ -177,8 +316,12 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( } } } - "llvm.x86.avx2.vperm2i128" => { + "llvm.x86.avx2.vperm2i128" + | "llvm.x86.avx.vperm2f128.ps.256" + | "llvm.x86.avx.vperm2f128.pd.256" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permute2x128_si256 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permute2f128_ps + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_permute2f128_pd let (a, b, imm8) = match args { [a, b, imm8] => (a, b, imm8), _ => bug!("wrong number of args for intrinsic {intrinsic}"), @@ -187,19 +330,11 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let b = codegen_operand(fx, b); let imm8 = codegen_operand(fx, imm8).load_scalar(fx); - let a_0 = a.value_lane(fx, 0).load_scalar(fx); - let a_1 = a.value_lane(fx, 1).load_scalar(fx); - let a_low = fx.bcx.ins().iconcat(a_0, a_1); - let a_2 = a.value_lane(fx, 2).load_scalar(fx); - let a_3 = a.value_lane(fx, 3).load_scalar(fx); - let a_high = fx.bcx.ins().iconcat(a_2, a_3); + let a_low = a.value_typed_lane(fx, fx.tcx.types.u128, 0).load_scalar(fx); + let a_high = a.value_typed_lane(fx, fx.tcx.types.u128, 1).load_scalar(fx); - let b_0 = b.value_lane(fx, 0).load_scalar(fx); - let b_1 = b.value_lane(fx, 1).load_scalar(fx); - let b_low = fx.bcx.ins().iconcat(b_0, b_1); - let b_2 = b.value_lane(fx, 2).load_scalar(fx); - let b_3 = b.value_lane(fx, 3).load_scalar(fx); - let b_high = fx.bcx.ins().iconcat(b_2, b_3); + let b_low = b.value_typed_lane(fx, fx.tcx.types.u128, 0).load_scalar(fx); + let b_high = b.value_typed_lane(fx, fx.tcx.types.u128, 1).load_scalar(fx); fn select4( fx: &mut FunctionCx<'_, '_, '_>, @@ -224,28 +359,47 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let control0 = imm8; let res_low = select4(fx, a_high, a_low, b_high, b_low, control0); - let (res_0, res_1) = fx.bcx.ins().isplit(res_low); let control1 = fx.bcx.ins().ushr_imm(imm8, 4); let res_high = select4(fx, a_high, a_low, b_high, b_low, control1); - let (res_2, res_3) = fx.bcx.ins().isplit(res_high); - ret.place_lane(fx, 0).to_ptr().store(fx, res_0, MemFlags::trusted()); - ret.place_lane(fx, 1).to_ptr().store(fx, res_1, MemFlags::trusted()); - ret.place_lane(fx, 2).to_ptr().store(fx, res_2, MemFlags::trusted()); - ret.place_lane(fx, 3).to_ptr().store(fx, res_3, MemFlags::trusted()); + ret.place_typed_lane(fx, fx.tcx.types.u128, 0).to_ptr().store( + fx, + res_low, + MemFlags::trusted(), + ); + ret.place_typed_lane(fx, fx.tcx.types.u128, 1).to_ptr().store( + fx, + res_high, + MemFlags::trusted(), + ); } "llvm.x86.ssse3.pabs.b.128" | "llvm.x86.ssse3.pabs.w.128" | "llvm.x86.ssse3.pabs.d.128" => { - let a = match args { - [a] => a, - _ => bug!("wrong number of args for intrinsic {intrinsic}"), - }; - let a = codegen_operand(fx, a); + intrinsic_args!(fx, args => (a); intrinsic); simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { fx.bcx.ins().iabs(lane) }); } + "llvm.x86.sse2.cvttps2dq" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttps_epi32&ig_expand=2429 + intrinsic_args!(fx, args => (a); intrinsic); + let a = a.load_scalar(fx); + + // Using inline asm instead of fcvt_to_sint_sat as unrepresentable values are turned + // into 0x80000000 for which Cranelift doesn't have a native instruction. + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String(format!("cvttps2dq xmm0, xmm0"))], + &[CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } "llvm.x86.addcarry.32" | "llvm.x86.addcarry.64" => { intrinsic_args!(fx, args => (c_in, a, b); intrinsic); let c_in = c_in.load_scalar(fx); @@ -309,7 +463,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx.bcx.ins().sshr(a_lane, saturated_count) }); } - "llvm.x86.sse2.psad.bw" => { + "llvm.x86.sse2.psad.bw" | "llvm.x86.avx2.psad.bw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sad_epu8&ig_expand=5770 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sad_epu8&ig_expand=5771 intrinsic_args!(fx, args => (a, b); intrinsic); assert_eq!(a.layout(), b.layout()); @@ -325,9 +481,11 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( for out_lane_idx in 0..lane_count / 8 { let mut lane_diff_acc = fx.bcx.ins().iconst(types::I64, 0); - for lane_idx in out_lane_idx * 8..out_lane_idx * 8 + 1 { + for lane_idx in out_lane_idx * 8..out_lane_idx * 8 + 8 { let a_lane = a.value_lane(fx, lane_idx).load_scalar(fx); + let a_lane = fx.bcx.ins().uextend(types::I16, a_lane); let b_lane = b.value_lane(fx, lane_idx).load_scalar(fx); + let b_lane = fx.bcx.ins().uextend(types::I16, b_lane); let lane_diff = fx.bcx.ins().isub(a_lane, b_lane); let abs_lane_diff = fx.bcx.ins().iabs(lane_diff); @@ -340,7 +498,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); } } - "llvm.x86.ssse3.pmadd.ub.sw.128" => { + "llvm.x86.ssse3.pmadd.ub.sw.128" | "llvm.x86.avx2.pmadd.ub.sw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16&ig_expand=4267 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_maddubs_epi16&ig_expand=4270 intrinsic_args!(fx, args => (a, b); intrinsic); let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); @@ -379,7 +539,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); } } - "llvm.x86.sse2.pmadd.wd" => { + "llvm.x86.sse2.pmadd.wd" | "llvm.x86.avx2.pmadd.wd" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_madd_epi16&ig_expand=4231 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_madd_epi16&ig_expand=4234 intrinsic_args!(fx, args => (a, b); intrinsic); assert_eq!(a.layout(), b.layout()); @@ -394,12 +556,12 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let ret_lane_layout = fx.layout_of(fx.tcx.types.i32); for out_lane_idx in 0..lane_count / 2 { let a_lane0 = a.value_lane(fx, out_lane_idx * 2).load_scalar(fx); - let a_lane0 = fx.bcx.ins().uextend(types::I32, a_lane0); + let a_lane0 = fx.bcx.ins().sextend(types::I32, a_lane0); let b_lane0 = b.value_lane(fx, out_lane_idx * 2).load_scalar(fx); let b_lane0 = fx.bcx.ins().sextend(types::I32, b_lane0); let a_lane1 = a.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); - let a_lane1 = fx.bcx.ins().uextend(types::I32, a_lane1); + let a_lane1 = fx.bcx.ins().sextend(types::I32, a_lane1); let b_lane1 = b.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); let b_lane1 = fx.bcx.ins().sextend(types::I32, b_lane1); @@ -412,6 +574,792 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); } } + + "llvm.x86.ssse3.pmul.hr.sw.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16&ig_expand=4782 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i16); + assert_eq!(ret_lane_ty, fx.tcx.types.i16); + assert_eq!(lane_count, ret_lane_count); + + let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); + for out_lane_idx in 0..lane_count { + let a_lane = a.value_lane(fx, out_lane_idx).load_scalar(fx); + let a_lane = fx.bcx.ins().sextend(types::I32, a_lane); + let b_lane = b.value_lane(fx, out_lane_idx).load_scalar(fx); + let b_lane = fx.bcx.ins().sextend(types::I32, b_lane); + + let mul: Value = fx.bcx.ins().imul(a_lane, b_lane); + let shifted = fx.bcx.ins().ushr_imm(mul, 14); + let incremented = fx.bcx.ins().iadd_imm(shifted, 1); + let shifted_again = fx.bcx.ins().ushr_imm(incremented, 1); + + let res_lane = fx.bcx.ins().ireduce(types::I16, shifted_again); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.sse2.packuswb.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi16&ig_expand=4903 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i16); + assert_eq!(ret_lane_ty, fx.tcx.types.u8); + assert_eq!(lane_count * 2, ret_lane_count); + + let zero = fx.bcx.ins().iconst(types::I16, 0); + let max_u8 = fx.bcx.ins().iconst(types::I16, 255); + let ret_lane_layout = fx.layout_of(fx.tcx.types.u8); + + for idx in 0..lane_count { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.avx2.packuswb" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi16&ig_expand=4906 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i16); + assert_eq!(ret_lane_ty, fx.tcx.types.u8); + assert_eq!(lane_count * 2, ret_lane_count); + + let zero = fx.bcx.ins().iconst(types::I16, 0); + let max_u8 = fx.bcx.ins().iconst(types::I16, 255); + let ret_lane_layout = fx.layout_of(fx.tcx.types.u8); + + for idx in 0..lane_count / 2 { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, zero); + let sat = fx.bcx.ins().umin(sat, max_u8); + let res = fx.bcx.ins().ireduce(types::I8, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.sse2.packssdw.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32&ig_expand=4889 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i32); + assert_eq!(ret_lane_ty, fx.tcx.types.i16); + assert_eq!(lane_count * 2, ret_lane_count); + + let min_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MIN) as u32 as i64); + let max_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MAX) as u32 as i64); + let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); + + for idx in 0..lane_count { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().smin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().smin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.sse41.packusdw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi32&ig_expand=4912 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i32); + assert_eq!(ret_lane_ty, fx.tcx.types.u16); + assert_eq!(lane_count * 2, ret_lane_count); + + let min_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MIN)); + let max_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MAX)); + let ret_lane_layout = fx.layout_of(fx.tcx.types.u16); + + for idx in 0..lane_count { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_u16); + let sat = fx.bcx.ins().smin(sat, max_u16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_u16); + let sat = fx.bcx.ins().smin(sat, max_u16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.avx2.packssdw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi32&ig_expand=4892 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i32); + assert_eq!(ret_lane_ty, fx.tcx.types.i16); + assert_eq!(lane_count * 2, ret_lane_count); + + let min_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MIN) as u32 as i64); + let max_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MAX) as u32 as i64); + let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); + + for idx in 0..lane_count / 2 { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().smin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().smin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = a.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().smin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane); + } + + for idx in 0..lane_count / 2 { + let lane = b.value_lane(fx, idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min_i16); + let sat = fx.bcx.ins().smin(sat, max_i16); + let res = fx.bcx.ins().ireduce(types::I16, sat); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.fma.vfmaddsub.ps" + | "llvm.x86.fma.vfmaddsub.pd" + | "llvm.x86.fma.vfmaddsub.ps.256" + | "llvm.x86.fma.vfmaddsub.pd.256" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fmaddsub_ps&ig_expand=3205 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fmaddsub_pd&ig_expand=3181 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fmaddsub_ps&ig_expand=3209 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fmaddsub_pd&ig_expand=3185 + intrinsic_args!(fx, args => (a, b, c); intrinsic); + + assert_eq!(a.layout(), b.layout()); + assert_eq!(a.layout(), c.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert!(lane_ty.is_floating_point()); + assert!(ret_lane_ty.is_floating_point()); + assert_eq!(lane_count, ret_lane_count); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + + for idx in 0..lane_count { + let a_lane = a.value_lane(fx, idx).load_scalar(fx); + let b_lane = b.value_lane(fx, idx).load_scalar(fx); + let c_lane = c.value_lane(fx, idx).load_scalar(fx); + + let mul = fx.bcx.ins().fmul(a_lane, b_lane); + let res = if idx & 1 == 0 { + fx.bcx.ins().fsub(mul, c_lane) + } else { + fx.bcx.ins().fadd(mul, c_lane) + }; + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.fma.vfmsubadd.ps" + | "llvm.x86.fma.vfmsubadd.pd" + | "llvm.x86.fma.vfmsubadd.ps.256" + | "llvm.x86.fma.vfmsubadd.pd.256" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fmsubadd_ps&ig_expand=3325 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fmsubadd_pd&ig_expand=3301 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fmsubadd_ps&ig_expand=3329 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fmsubadd_pd&ig_expand=3305 + intrinsic_args!(fx, args => (a, b, c); intrinsic); + + assert_eq!(a.layout(), b.layout()); + assert_eq!(a.layout(), c.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert!(lane_ty.is_floating_point()); + assert!(ret_lane_ty.is_floating_point()); + assert_eq!(lane_count, ret_lane_count); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + + for idx in 0..lane_count { + let a_lane = a.value_lane(fx, idx).load_scalar(fx); + let b_lane = b.value_lane(fx, idx).load_scalar(fx); + let c_lane = c.value_lane(fx, idx).load_scalar(fx); + + let mul = fx.bcx.ins().fmul(a_lane, b_lane); + let res = if idx & 1 == 0 { + fx.bcx.ins().fadd(mul, c_lane) + } else { + fx.bcx.ins().fsub(mul, c_lane) + }; + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.fma.vfnmadd.ps" + | "llvm.x86.fma.vfnmadd.pd" + | "llvm.x86.fma.vfnmadd.ps.256" + | "llvm.x86.fma.vfnmadd.pd.256" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fnmadd_ps&ig_expand=3391 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fnmadd_pd&ig_expand=3367 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fnmadd_ps&ig_expand=3395 + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fnmadd_pd&ig_expand=3371 + intrinsic_args!(fx, args => (a, b, c); intrinsic); + + assert_eq!(a.layout(), b.layout()); + assert_eq!(a.layout(), c.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert!(lane_ty.is_floating_point()); + assert!(ret_lane_ty.is_floating_point()); + assert_eq!(lane_count, ret_lane_count); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + + for idx in 0..lane_count { + let a_lane = a.value_lane(fx, idx).load_scalar(fx); + let b_lane = b.value_lane(fx, idx).load_scalar(fx); + let c_lane = c.value_lane(fx, idx).load_scalar(fx); + + let mul = fx.bcx.ins().fmul(a_lane, b_lane); + let neg_mul = fx.bcx.ins().fneg(mul); + let res = fx.bcx.ins().fadd(neg_mul, c_lane); + + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, idx).write_cvalue(fx, res_lane); + } + } + + "llvm.x86.sse42.pcmpestri128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestri&ig_expand=939 + intrinsic_args!(fx, args => (a, la, b, lb, _imm8); intrinsic); + + let a = a.load_scalar(fx); + let la = la.load_scalar(fx); + let b = b.load_scalar(fx); + let lb = lb.load_scalar(fx); + + let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4]) + { + imm8 + } else { + fx.tcx.sess.span_fatal(span, "Index argument for `_mm_cmpestri` is not a constant"); + }; + + let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}"))], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + value: a, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + value: b, + }, + // Implicit argument to the pcmpestri intrinsic + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + value: la, + }, + // Implicit argument to the pcmpestri intrinsic + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + value: lb, + }, + // Implicit result of the pcmpestri intrinsic + CInlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), + late: true, + place: Some(ret), + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sse42.pcmpestrm128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cmpestrm&ig_expand=940 + intrinsic_args!(fx, args => (a, la, b, lb, _imm8); intrinsic); + + let a = a.load_scalar(fx); + let la = la.load_scalar(fx); + let b = b.load_scalar(fx); + let lb = lb.load_scalar(fx); + + let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[4]) + { + imm8 + } else { + fx.tcx.sess.span_fatal(span, "Index argument for `_mm_cmpestrm` is not a constant"); + }; + + let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}"))], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + value: b, + }, + // Implicit argument to the pcmpestri intrinsic + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + value: la, + }, + // Implicit argument to the pcmpestri intrinsic + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + value: lb, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.pclmulqdq" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_clmulepi64_si128&ig_expand=772 + intrinsic_args!(fx, args => (a, b, _imm8); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[2]) + { + imm8 + } else { + fx.tcx.sess.span_fatal( + span, + "Index argument for `_mm_clmulepi64_si128` is not a constant", + ); + }; + + let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}"))], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.aesni.aeskeygenassist" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aeskeygenassist_si128&ig_expand=261 + intrinsic_args!(fx, args => (a, _imm8); intrinsic); + + let a = a.load_scalar(fx); + + let imm8 = if let Some(imm8) = crate::constant::mir_operand_get_const_val(fx, &args[1]) + { + imm8 + } else { + fx.tcx.sess.span_fatal( + span, + "Index argument for `_mm_aeskeygenassist_si128` is not a constant", + ); + }; + + let imm8 = imm8.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", imm8)); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String(format!("aeskeygenassist xmm0, xmm0, {imm8}"))], + &[CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.aesni.aesimc" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesimc_si128&ig_expand=260 + intrinsic_args!(fx, args => (a); intrinsic); + + let a = a.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".to_string())], + &[CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.aesni.aesenc" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc_si128&ig_expand=252 + intrinsic_args!(fx, args => (a, round_key); intrinsic); + + let a = a.load_scalar(fx); + let round_key = round_key.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + value: round_key, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.aesni.aesenclast" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128&ig_expand=257 + intrinsic_args!(fx, args => (a, round_key); intrinsic); + + let a = a.load_scalar(fx); + let round_key = round_key.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + value: round_key, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.aesni.aesdec" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128&ig_expand=242 + intrinsic_args!(fx, args => (a, round_key); intrinsic); + + let a = a.load_scalar(fx); + let round_key = round_key.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + value: round_key, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.aesni.aesdeclast" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128&ig_expand=247 + intrinsic_args!(fx, args => (a, round_key); intrinsic); + + let a = a.load_scalar(fx); + let round_key = round_key.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + value: round_key, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha256rnds2" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256rnds2_epu32&ig_expand=5977 + intrinsic_args!(fx, args => (a, b, k); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + let k = k.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + // Implicit argument to the sha256rnds2 instruction + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), + value: k, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha256msg1" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256msg1_epu32&ig_expand=5975 + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha256msg2" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256msg2_epu32&ig_expand=5976 + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.avx.ptestz.256" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_testz_si256&ig_expand=6945 + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i64); + assert_eq!(ret.layout().ty, fx.tcx.types.i32); + assert_eq!(lane_count, 4); + + let a_lane0 = a.value_lane(fx, 0).load_scalar(fx); + let a_lane1 = a.value_lane(fx, 1).load_scalar(fx); + let a_lane2 = a.value_lane(fx, 2).load_scalar(fx); + let a_lane3 = a.value_lane(fx, 3).load_scalar(fx); + let b_lane0 = b.value_lane(fx, 0).load_scalar(fx); + let b_lane1 = b.value_lane(fx, 1).load_scalar(fx); + let b_lane2 = b.value_lane(fx, 2).load_scalar(fx); + let b_lane3 = b.value_lane(fx, 3).load_scalar(fx); + + let zero0 = fx.bcx.ins().band(a_lane0, b_lane0); + let zero1 = fx.bcx.ins().band(a_lane1, b_lane1); + let zero2 = fx.bcx.ins().band(a_lane2, b_lane2); + let zero3 = fx.bcx.ins().band(a_lane3, b_lane3); + + let all_zero0 = fx.bcx.ins().bor(zero0, zero1); + let all_zero1 = fx.bcx.ins().bor(zero2, zero3); + let all_zero = fx.bcx.ins().bor(all_zero0, all_zero1); + + let res = fx.bcx.ins().icmp_imm(IntCC::Equal, all_zero, 0); + let res = CValue::by_val( + fx.bcx.ins().uextend(types::I32, res), + fx.layout_of(fx.tcx.types.i32), + ); + ret.write_cvalue(fx, res); + } + _ => { fx.tcx .sess diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 83d5d53624eb1..bfeeb117ff5b3 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -132,6 +132,65 @@ fn simd_pair_for_each_lane<'tcx>( } } +fn simd_horizontal_pair_for_each_lane<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + x: CValue<'tcx>, + y: CValue<'tcx>, + ret: CPlace<'tcx>, + f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, Ty<'tcx>, Ty<'tcx>, Value, Value) -> Value, +) { + assert_eq!(x.layout(), y.layout()); + let layout = x.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + assert_eq!(lane_count, ret_lane_count); + + for lane_idx in 0..lane_count { + let src = if lane_idx < (lane_count / 2) { x } else { y }; + let src_idx = lane_idx % (lane_count / 2); + + let lhs_lane = src.value_lane(fx, src_idx * 2).load_scalar(fx); + let rhs_lane = src.value_lane(fx, src_idx * 2 + 1).load_scalar(fx); + + let res_lane = f(fx, lane_layout.ty, ret_lane_layout.ty, lhs_lane, rhs_lane); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane); + } +} + +fn simd_trio_for_each_lane<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + x: CValue<'tcx>, + y: CValue<'tcx>, + z: CValue<'tcx>, + ret: CPlace<'tcx>, + f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, Ty<'tcx>, Ty<'tcx>, Value, Value, Value) -> Value, +) { + assert_eq!(x.layout(), y.layout()); + let layout = x.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + let ret_lane_layout = fx.layout_of(ret_lane_ty); + assert_eq!(lane_count, ret_lane_count); + + for lane_idx in 0..lane_count { + let x_lane = x.value_lane(fx, lane_idx).load_scalar(fx); + let y_lane = y.value_lane(fx, lane_idx).load_scalar(fx); + let z_lane = z.value_lane(fx, lane_idx).load_scalar(fx); + + let res_lane = f(fx, lane_layout.ty, ret_lane_layout.ty, x_lane, y_lane, z_lane); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane); + } +} + fn simd_reduce<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, val: CValue<'tcx>, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index ea137c4ca1e8c..0bd211fd614f0 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -282,11 +282,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.tcx.sess.span_fatal(span, "Index argument for `simd_insert` is not a constant"); }; - let idx = idx_const - .try_to_bits(Size::from_bytes(4 /* u32*/)) - .unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); + let idx: u32 = idx_const + .try_to_u32() + .unwrap_or_else(|_| panic!("kind not scalar: {:?}", idx_const)); let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx); - if idx >= lane_count.into() { + if u64::from(idx) >= lane_count { fx.tcx.sess.span_fatal( fx.mir.span, format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count), @@ -331,10 +331,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; let idx = idx_const - .try_to_bits(Size::from_bytes(4 /* u32*/)) - .unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); + .try_to_u32() + .unwrap_or_else(|_| panic!("kind not scalar: {:?}", idx_const)); let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx); - if idx >= lane_count.into() { + if u64::from(idx) >= lane_count { fx.tcx.sess.span_fatal( fx.mir.span, format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count), diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index da84e54a91636..02c0dcb8b1bd2 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -58,11 +58,10 @@ use std::fmt; use std::io::Write; -use cranelift_codegen::{ - entity::SecondaryMap, - ir::entities::AnyEntity, - write::{FuncWriter, PlainWriter}, -}; +use cranelift_codegen::entity::SecondaryMap; +use cranelift_codegen::ir::entities::AnyEntity; +use cranelift_codegen::ir::Fact; +use cranelift_codegen::write::{FuncWriter, PlainWriter}; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::config::{OutputFilenames, OutputType}; @@ -155,8 +154,13 @@ impl FuncWriter for &'_ CommentWriter { _func: &Function, entity: AnyEntity, value: &dyn fmt::Display, + maybe_fact: Option<&Fact>, ) -> fmt::Result { - write!(w, " {} = {}", entity, value)?; + if let Some(fact) = maybe_fact { + write!(w, " {} ! {} = {}", entity, fact, value)?; + } else { + write!(w, " {} = {}", entity, value)?; + } if let Some(comment) = self.entity_comments.get(&entity) { writeln!(w, " ; {}", comment.replace('\n', "\n; ")) diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 5f0aa6c5581dd..f52f59716a8a5 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -243,6 +243,34 @@ impl<'tcx> CValue<'tcx> { let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); let lane_layout = fx.layout_of(lane_ty); assert!(lane_idx < lane_count); + + match self.0 { + CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => unreachable!(), + CValueInner::ByRef(ptr, None) => { + let field_offset = lane_layout.size * lane_idx; + let field_ptr = ptr.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()); + CValue::by_ref(field_ptr, lane_layout) + } + CValueInner::ByRef(_, Some(_)) => unreachable!(), + } + } + + /// Like [`CValue::value_field`] except using the passed type as lane type instead of the one + /// specified by the vector type. + pub(crate) fn value_typed_lane( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + lane_ty: Ty<'tcx>, + lane_idx: u64, + ) -> CValue<'tcx> { + let layout = self.1; + assert!(layout.ty.is_simd()); + let (orig_lane_count, orig_lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + assert!( + (lane_idx + 1) * lane_layout.size <= orig_lane_count * fx.layout_of(orig_lane_ty).size + ); + match self.0 { CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => unreachable!(), CValueInner::ByRef(ptr, None) => { @@ -301,7 +329,13 @@ impl<'tcx> CValue<'tcx> { let msb = fx.bcx.ins().iconst(types::I64, (const_val >> 64) as u64 as i64); fx.bcx.ins().iconcat(lsb, msb) } - ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Ref(..) | ty::RawPtr(..) => { + ty::Bool + | ty::Char + | ty::Uint(_) + | ty::Int(_) + | ty::Ref(..) + | ty::RawPtr(..) + | ty::FnPtr(..) => { let raw_val = const_val.size().truncate(const_val.to_bits(layout.size).unwrap()); fx.bcx.ins().iconst(clif_ty, raw_val as i64) } @@ -734,6 +768,34 @@ impl<'tcx> CPlace<'tcx> { } } + /// Like [`CPlace::place_field`] except using the passed type as lane type instead of the one + /// specified by the vector type. + pub(crate) fn place_typed_lane( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + lane_ty: Ty<'tcx>, + lane_idx: u64, + ) -> CPlace<'tcx> { + let layout = self.layout(); + assert!(layout.ty.is_simd()); + let (orig_lane_count, orig_lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let lane_layout = fx.layout_of(lane_ty); + assert!( + (lane_idx + 1) * lane_layout.size <= orig_lane_count * fx.layout_of(orig_lane_ty).size + ); + + match self.inner { + CPlaceInner::Var(_, _) => unreachable!(), + CPlaceInner::VarPair(_, _, _) => unreachable!(), + CPlaceInner::Addr(ptr, None) => { + let field_offset = lane_layout.size * lane_idx; + let field_ptr = ptr.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()); + CPlace::for_ptr(field_ptr, lane_layout) + } + CPlaceInner::Addr(_, Some(_)) => unreachable!(), + } + } + pub(crate) fn place_index( self, fx: &mut FunctionCx<'_, '_, 'tcx>, @@ -915,6 +977,32 @@ pub(crate) fn assert_assignable<'tcx>( } } } + (&ty::Coroutine(def_id_a, args_a, mov_a), &ty::Coroutine(def_id_b, args_b, mov_b)) + if def_id_a == def_id_b && mov_a == mov_b => + { + let mut types_a = args_a.types(); + let mut types_b = args_b.types(); + loop { + match (types_a.next(), types_b.next()) { + (Some(a), Some(b)) => assert_assignable(fx, a, b, limit - 1), + (None, None) => return, + (Some(_), None) | (None, Some(_)) => panic!("{:#?}/{:#?}", from_ty, to_ty), + } + } + } + (&ty::CoroutineWitness(def_id_a, args_a), &ty::CoroutineWitness(def_id_b, args_b)) + if def_id_a == def_id_b => + { + let mut types_a = args_a.types(); + let mut types_b = args_b.types(); + loop { + match (types_a.next(), types_b.next()) { + (Some(a), Some(b)) => assert_assignable(fx, a, b, limit - 1), + (None, None) => return, + (Some(_), None) | (None, Some(_)) => panic!("{:#?}/{:#?}", from_ty, to_ty), + } + } + } (ty::Param(_), _) | (_, ty::Param(_)) if fx.tcx.sess.opts.unstable_opts.polymorphize => { // No way to check if it is correct or not with polymorphization enabled } diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml index 65e7a697ab0df..308bc55ead71e 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml @@ -99,8 +99,10 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - ./y.sh build - cargo test + # TODO: remove --features master when it is back to the default. + ./y.sh build --features master + # TODO: remove --features master when it is back to the default. + cargo test --features master ./clean_all.sh - name: Prepare dependencies @@ -121,7 +123,8 @@ jobs: - name: Run tests run: | - ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} + # TODO: remove --features master when it is back to the default. + ./test.sh --features master --release --clean --build-sysroot ${{ matrix.commands }} duplicates: runs-on: ubuntu-latest diff --git a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml index 27864dcadd0fe..ae8de79b773db 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml @@ -21,11 +21,14 @@ jobs: libgccjit_version: - gcc: "libgccjit.so" artifacts_branch: "master" + # TODO: switch back to --no-default-features in the case of libgccjit 12 when the default is to enable + # master again. + extra: "--features master" - gcc: "libgccjit_without_int128.so" artifacts_branch: "master-without-128bit-integers" + extra: "--features master" - gcc: "libgccjit12.so" artifacts_branch: "gcc12" - extra: "--no-default-features" # FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin. # Not sure why it's not found otherwise. env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests' GCC_EXEC_PREFIX=/usr/lib/gcc/" diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml index 55ee0a212142e..4d9d7e23dc2b5 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml @@ -114,8 +114,10 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore --cross - ./y.sh build --target-triple m68k-unknown-linux-gnu - CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test + # TODO: remove --features master when it is back to the default. + ./y.sh build --target-triple m68k-unknown-linux-gnu --features master + # TODO: remove --features master when it is back to the default. + CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test --features master ./clean_all.sh - name: Prepare dependencies @@ -136,4 +138,5 @@ jobs: - name: Run tests run: | - ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} + # TODO: remove --features master when it is back to the default. + ./test.sh --release --features master --clean --build-sysroot ${{ matrix.commands }} diff --git a/compiler/rustc_codegen_gcc/.github/workflows/release.yml b/compiler/rustc_codegen_gcc/.github/workflows/release.yml index ae1134177a77e..43b90fcec9337 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/release.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/release.yml @@ -78,8 +78,10 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot - cargo test + # TODO: remove --features master when it is back to the default. + EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot --features master + # TODO: remove --features master when it is back to the default. + cargo test --features master ./clean_all.sh - name: Prepare dependencies @@ -102,4 +104,5 @@ jobs: - name: Run tests run: | - EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} + # TODO: remove --features master when it is back to the default. + EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} --features master diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml index 28ac3cb65422f..42109ba3e0245 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml @@ -92,8 +92,10 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - ./y.sh build --release --release-sysroot - cargo test + # TODO: remove `--features master` when it is back to the default. + ./y.sh build --release --release-sysroot --features master + # TODO: remove --features master when it is back to the default. + cargo test --features master - name: Clean if: ${{ !matrix.cargo_runner }} @@ -111,12 +113,14 @@ jobs: uses: actions-rs/cargo@v1.0.3 with: command: build - args: --release + # TODO: remove `--features master` when it is back to the default. + args: --release --features master - name: Run tests if: ${{ !matrix.cargo_runner }} run: | - ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore + # TODO: remove `--features master` when it is back to the default. + ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore --features master - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index b8e2e5d808044..ddfce5d59bde8 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -74,7 +74,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033" +source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421" dependencies = [ "gccjit_sys", ] @@ -82,7 +82,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033" +source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421" dependencies = [ "libc", ] @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "linux-raw-sys" diff --git a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh index 116fd36e7a7b3..ebc7dc375b125 100755 --- a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh +++ b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh @@ -28,3 +28,7 @@ fi # Copy files to sysroot mkdir -p sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ cp -r target/$TARGET_TRIPLE/$sysroot_channel/deps/* sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ +# Copy the source files to the sysroot (Rust for Linux needs this). +source_dir=sysroot/lib/rustlib/src/rust +mkdir -p $source_dir +cp -r sysroot_src/library/ $source_dir diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs index eaca7a987d6b8..f1c3701a946ec 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/build.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs @@ -194,6 +194,12 @@ fn build_sysroot( copier, )?; + // Copy the source files to the sysroot (Rust for Linux needs this). + let sysroot_src_path = "sysroot/lib/rustlib/src/rust"; + fs::create_dir_all(&sysroot_src_path) + .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_src_path, error))?; + run_command(&[&"cp", &"-r", &"sysroot_src/library/", &sysroot_src_path], None)?; + Ok(()) } diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs index 0f6325c8980e7..ad69409eb6590 100644 --- a/compiler/rustc_codegen_gcc/example/std_example.rs +++ b/compiler/rustc_codegen_gcc/example/std_example.rs @@ -1,3 +1,4 @@ +#![allow(internal_features)] #![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)] #[cfg(feature="master")] diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt b/compiler/rustc_codegen_gcc/failing-ui-tests12.txt index f91aa92531848..4af93939b0642 100644 --- a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt +++ b/compiler/rustc_codegen_gcc/failing-ui-tests12.txt @@ -38,3 +38,5 @@ tests/ui/target-feature/missing-plusminus.rs tests/ui/sse2.rs tests/ui/codegen/issue-79865-llvm-miscompile.rs tests/ui/intrinsics/intrinsics-integer.rs +tests/ui/std-backtrace.rs +tests/ui/mir/alignment/packed.rs diff --git a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch index 9520a5a39edcd..914ae986b50e7 100644 --- a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch +++ b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch @@ -1,6 +1,6 @@ -From 7bcd24ec6d4a96121874cb1ae5a23ea274aeff34 Mon Sep 17 00:00:00 2001 +From a5663265f797a43c502915c356fe7899c16cee92 Mon Sep 17 00:00:00 2001 From: None -Date: Thu, 19 Oct 2023 13:12:51 -0400 +Date: Sat, 18 Nov 2023 10:50:36 -0500 Subject: [PATCH] [core] Disable portable-simd test --- @@ -8,18 +8,18 @@ Subject: [PATCH] [core] Disable portable-simd test 1 file changed, 2 deletions(-) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs -index 5814ed4..194ad4c 100644 +index d0a119c..76fdece 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs -@@ -90,7 +90,6 @@ +@@ -89,7 +89,6 @@ + #![feature(never_type)] #![feature(unwrap_infallible)] - #![feature(pointer_byte_offsets)] #![feature(pointer_is_aligned)] -#![feature(portable_simd)] #![feature(ptr_metadata)] #![feature(lazy_cell)] #![feature(unsized_tuple_coercion)] -@@ -157,7 +156,6 @@ mod pin; +@@ -155,7 +154,6 @@ mod pin; mod pin_macro; mod ptr; mod result; @@ -28,5 +28,5 @@ index 5814ed4..194ad4c 100644 mod str; mod str_lossy; -- -2.42.0 +2.42.1 diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain index 205ec53b425bf..1962c217258a4 100644 --- a/compiler/rustc_codegen_gcc/rust-toolchain +++ b/compiler/rustc_codegen_gcc/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-10-21" +channel = "nightly-2023-11-17" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 5073066c1383c..b0788718da4d1 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -3,7 +3,6 @@ use std::env; use std::time::Instant; use gccjit::{ - Context, FunctionType, GlobalKind, }; @@ -18,8 +17,9 @@ use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoMethods; use rustc_session::config::DebugInfo; use rustc_span::Symbol; +use rustc_target::spec::PanicStrategy; -use crate::{LockedTargetInfo, gcc_util}; +use crate::{LockedTargetInfo, gcc_util, new_context}; use crate::GccContext; use crate::builder::Builder; use crate::context::CodegenCx; @@ -88,20 +88,18 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, LockedTargetInfo)) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let context = Context::default(); + let context = new_context(tcx); - context.add_command_line_option("-fexceptions"); - context.add_driver_option("-fexceptions"); + if tcx.sess.panic_strategy() == PanicStrategy::Unwind { + context.add_command_line_option("-fexceptions"); + context.add_driver_option("-fexceptions"); + } let disabled_features: HashSet<_> = tcx.sess.opts.cg.target_feature.split(',') .filter(|feature| feature.starts_with('-')) .map(|string| &string[1..]) .collect(); - if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { - context.add_command_line_option("-masm=intel"); - } - if !disabled_features.contains("avx") && tcx.sess.target.arch == "x86_64" { // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 93fe27e547aef..b7ddc410315c3 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -199,7 +199,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } } Scalar::Ptr(ptr, _size) => { - let (alloc_id, offset) = ptr.into_parts(); + let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative + let alloc_id = prov.alloc_id(); let base_addr = match self.tcx.global_alloc(alloc_id) { GlobalAlloc::Memory(alloc) => { diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index d8a1fd315c0a5..f06416b9bb5fe 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -285,7 +285,8 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl let pointer_size = dl.pointer_size.bytes() as usize; let mut next_offset = 0; - for &(offset, alloc_id) in alloc.provenance().ptrs().iter() { + for &(offset, prov) in alloc.provenance().ptrs().iter() { + let alloc_id = prov.alloc_id(); let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; @@ -313,7 +314,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl llvals.push(cx.scalar_to_backend( InterpScalar::from_pointer( - interpret::Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), + interpret::Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx, ), abi::Scalar::Initialized { value: Primitive::Pointer(address_space), valid_range: WrappingRange::full(dl.pointer_size) }, diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 4bf3b71f503d6..5fc4b12d7e699 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -111,8 +111,8 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { pub(crate) struct MissingFeatures; impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); + fn into_diagnostic(self, handler: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); if let Some(span) = self.span { diag.set_span(span); }; diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index ea8550d20f362..9b9b3ea4f8704 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -76,6 +76,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { a >> b } } + else if a_type.is_vector() && a_type.is_vector() { + a >> b + } else if a_native && !b_native { self.gcc_lshr(a, self.gcc_int_cast(b, a_type)) } @@ -144,7 +147,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn additive_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { let a_type = a.get_type(); let b_type = b.get_type(); - if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) { if a_type != b_type { if a_type.is_vector() { // Vector types need to be bitcast. @@ -158,6 +161,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.context.new_binary_op(None, operation, a_type, a, b) } else { + debug_assert!(a_type.dyncast_array().is_some()); + debug_assert!(b_type.dyncast_array().is_some()); let signed = a_type.is_compatible_with(self.i128_type); let func_name = match (operation, signed) { @@ -189,10 +194,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn multiplicative_operation(&self, operation: BinaryOp, operation_name: &str, signed: bool, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { let a_type = a.get_type(); let b_type = b.get_type(); - if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) { self.context.new_binary_op(None, operation, a_type, a, b) } else { + debug_assert!(a_type.dyncast_array().is_some()); + debug_assert!(b_type.dyncast_array().is_some()); let sign = if signed { "" @@ -337,6 +344,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn operation_with_overflow(&self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { let a_type = lhs.get_type(); let b_type = rhs.get_type(); + debug_assert!(a_type.dyncast_array().is_some()); + debug_assert!(b_type.dyncast_array().is_some()); let param_a = self.context.new_parameter(None, a_type, "a"); let param_b = self.context.new_parameter(None, b_type, "b"); let result_field = self.context.new_field(None, a_type, "result"); @@ -496,7 +505,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn gcc_xor(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { let a_type = a.get_type(); let b_type = b.get_type(); - if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + if a_type.is_vector() && b_type.is_vector() { + let b = self.bitcast_if_needed(b, a_type); + a ^ b + } + else if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { a ^ b } else { @@ -527,6 +540,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { a << b } } + else if a_type.is_vector() && a_type.is_vector() { + a << b + } else if a_native && !b_native { self.gcc_shl(a, self.gcc_int_cast(b, a_type)) } @@ -690,6 +706,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let a_native = self.is_native_int_type_or_bool(a_type); let b_native = self.is_native_int_type_or_bool(b_type); if a_type.is_vector() && b_type.is_vector() { + let b = self.bitcast_if_needed(b, a_type); self.context.new_binary_op(None, operation, a_type, a, b) } else if a_native && b_native { @@ -748,6 +765,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { return self.context.new_cast(None, value, dest_typ); } + debug_assert!(value_type.dyncast_array().is_some()); let name_suffix = match self.type_kind(dest_typ) { TypeKind::Float => "tisf", @@ -781,6 +799,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { return self.context.new_cast(None, value, dest_typ); } + debug_assert!(value_type.dyncast_array().is_some()); let name_suffix = match self.type_kind(value_type) { TypeKind::Float => "sfti", diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index a530fc994a22b..d54057615d2d8 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -12,9 +12,9 @@ * TODO(antoyo): remove the patches. */ -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![allow(internal_features)] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature( rustc_private, decl_macro, @@ -39,6 +39,8 @@ extern crate rustc_errors; extern crate rustc_fluent_macro; extern crate rustc_fs_util; extern crate rustc_hir; +#[cfg(feature="master")] +extern crate rustc_interface; extern crate rustc_macros; extern crate rustc_metadata; extern crate rustc_middle; @@ -86,7 +88,7 @@ use std::sync::atomic::Ordering; use gccjit::{Context, OptimizationLevel}; #[cfg(feature="master")] -use gccjit::TargetInfo; +use gccjit::{TargetInfo, Version}; #[cfg(not(feature="master"))] use gccjit::CType; use errors::LTONotSupported; @@ -99,8 +101,7 @@ use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods}; -use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; +use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::util::Providers; @@ -114,7 +115,7 @@ use tempfile::TempDir; use crate::back::lto::ModuleBuffer; use crate::gcc_util::target_cpu; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub struct PrintOnPanic String>(pub F); @@ -244,17 +245,33 @@ impl CodegenBackend for GccCodegenBackend { } } +fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { + let context = Context::default(); + if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { + context.add_command_line_option("-masm=intel"); + } + #[cfg(feature="master")] + { + let version = Version::get(); + let version = format!("{}.{}.{}", version.major, version.minor, version.patch); + context.set_output_ident(&format!("rustc version {} with libgccjit {}", + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), + version, + )); + } + // TODO(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. + context.add_command_line_option("-fno-asynchronous-unwind-tables"); + context +} + impl ExtraBackendMethods for GccCodegenBackend { fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module { let mut mods = GccContext { - context: Context::default(), + context: new_context(tcx), should_combine_object_files: false, temp_dir: None, }; - if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { - mods.context.add_command_line_option("-masm=intel"); - } unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); } mods } @@ -384,7 +401,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Locke .iter() .filter_map( |&(feature, gate)| { - if sess.is_nightly_build() || allow_unstable || gate.is_none() { Some(feature) } else { None } + if sess.is_nightly_build() || allow_unstable || gate.is_stable() { Some(feature) } else { None } }, ) .filter(|_feature| { diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 1d309eb908e3c..580ef9b06e703 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -10,7 +10,7 @@ test = false # tidy-alphabetical-start bitflags = "1.0" cstr = "0.2" -itertools = "0.10.5" +itertools = "0.11" libc = "0.2" measureme = "10.0.0" object = { version = "0.32.0", default-features = false, features = ["std", "read"] } diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index c0cfe39f1e0a4..7a86ddc7556a0 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -76,8 +76,8 @@ codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$ codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err} codegen_llvm_unknown_ctarget_feature = - unknown feature specified for `-Ctarget-feature`: `{$feature}` - .note = it is still passed through to the codegen backend + unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future .possible_feature = you might have meant: `{$rust_feature}` .consider_filing_feature_request = consider filing a feature request @@ -87,6 +87,10 @@ codegen_llvm_unknown_ctarget_feature_prefix = codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo +codegen_llvm_unstable_ctarget_feature = + unstable feature specified for `-Ctarget-feature`: `{$feature}` + .note = this feature is not stably supported; its behavior can change in the future + codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err} codegen_llvm_write_ir = failed to write LLVM IR to {$path} diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 6e3a4cae2f62b..b5f53f5183835 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -348,50 +348,18 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { PassMode::Direct(_) => { // ABI-compatible Rust types have the same `layout.abi` (up to validity ranges), // and for Scalar ABIs the LLVM type is fully determined by `layout.abi`, - // guarnateeing that we generate ABI-compatible LLVM IR. Things get tricky for - // aggregates... - if matches!(arg.layout.abi, abi::Abi::Aggregate { .. }) { - assert!( - arg.layout.is_sized(), - "`PassMode::Direct` for unsized type: {}", - arg.layout.ty - ); - // This really shouldn't happen, since `immediate_llvm_type` will use - // `layout.fields` to turn this Rust type into an LLVM type. This means all - // sorts of Rust type details leak into the ABI. However wasm sadly *does* - // currently use this mode so we have to allow it -- but we absolutely - // shouldn't let any more targets do that. - // (Also see .) - // - // The unstable abi `PtxKernel` also uses Direct for now. - // It needs to switch to something else before stabilization can happen. - // (See issue: https://github.com/rust-lang/rust/issues/117271) - assert!( - matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64") - || self.conv == Conv::PtxKernel, - "`PassMode::Direct` for aggregates only allowed on wasm and `extern \"ptx-kernel\"` fns\nProblematic type: {:#?}", - arg.layout, - ); - } + // guaranteeing that we generate ABI-compatible LLVM IR. arg.layout.immediate_llvm_type(cx) } PassMode::Pair(..) => { // ABI-compatible Rust types have the same `layout.abi` (up to validity ranges), // so for ScalarPair we can easily be sure that we are generating ABI-compatible // LLVM IR. - assert!( - matches!(arg.layout.abi, abi::Abi::ScalarPair(..)), - "PassMode::Pair for type {}", - arg.layout.ty - ); llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0, true)); llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack } => { - // `Indirect` with metadata is only for unsized types, and doesn't work with - // on-stack passing. - assert!(arg.layout.is_unsized() && !on_stack); + PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { // Construct the type of a (wide) pointer to `ty`, and pass its two fields. // Any two ABI-compatible unsized types have the same metadata type and // moreover the same metadata value leads to the same dynamic size and @@ -402,13 +370,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => { - assert!(arg.layout.is_sized()); - cx.type_ptr() - } + PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => cx.type_ptr(), PassMode::Cast { cast, pad_i32 } => { - // `Cast` means "transmute to `CastType`"; that only makes sense for sized types. - assert!(arg.layout.is_sized()); // add padding if *pad_i32 { llargument_tys.push(Reg::i32().llvm_type(cx)); @@ -530,7 +493,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { PassMode::Cast { cast, pad_i32: _ } => { cast.attrs.apply_attrs_to_callsite( llvm::AttributePlace::ReturnValue, - &bx.cx, + bx.cx, callsite, ); } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index db5c1388ef846..798014d668e22 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -67,7 +67,7 @@ pub(crate) unsafe fn codegen( llcx, llmod, "__rust_alloc_error_handler", - &alloc_error_handler_name(alloc_error_handler_kind), + alloc_error_handler_name(alloc_error_handler_kind), &[usize, usize], // size, align None, true, diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index b6c01545f308c..481741bb1277a 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -4,7 +4,7 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::config::OptLevel; +use rustc_session::config::{FunctionReturn, OptLevel}; use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi; use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector}; @@ -118,6 +118,15 @@ pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attr Some(llvm::CreateAttrStringValue(cx.llcx, "frame-pointer", attr_value)) } +fn function_return_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { + let function_return_attr = match cx.sess().opts.unstable_opts.function_return { + FunctionReturn::Keep => return None, + FunctionReturn::ThunkExtern => AttributeKind::FnRetThunkExtern, + }; + + Some(function_return_attr.create_attr(cx.llcx)) +} + /// Tell LLVM what instrument function to insert. #[inline] fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attribute; 4]> { @@ -136,7 +145,7 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attr attrs.push(llvm::CreateAttrStringValue( cx.llcx, "instrument-function-entry-inlined", - &mcount_name, + mcount_name, )); } if let Some(options) = &cx.sess().opts.unstable_opts.instrument_xray { @@ -331,8 +340,9 @@ pub fn from_fn_attrs<'ll, 'tcx>( to_add.push(llvm::CreateAttrString(cx.llcx, "use-sample-profile")); } - // FIXME: none of these three functions interact with source level attributes. + // FIXME: none of these functions interact with source level attributes. to_add.extend(frame_pointer_type_attr(cx)); + to_add.extend(function_return_attr(cx)); to_add.extend(instrument_function_attr(cx)); to_add.extend(nojumptables_attr(cx)); to_add.extend(probestack_attr(cx)); @@ -459,7 +469,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( // If this function is an import from the environment but the wasm // import has a specific module/name, apply them here. if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) { - to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-module", &module)); + to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-module", module)); let name = codegen_fn_attrs.link_name.unwrap_or_else(|| cx.tcx.item_name(instance.def_id())); diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index f33075a887963..cf47c94a81ff8 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -68,7 +68,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { ) -> io::Result<()> { let mut archive = archive.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") { - if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? { + if let Some(new_archive) = try_extract_macho_fat_archive(self.sess, &archive)? { archive = new_archive } } diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 8655aeec13dd6..abc33a045982a 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -25,6 +25,7 @@ use std::ffi::{CStr, CString}; use std::fs::File; use std::io; use std::iter; +use std::mem::ManuallyDrop; use std::path::Path; use std::slice; use std::sync::Arc; @@ -59,7 +60,7 @@ fn prepare_lto( }; let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| { - if info.level.is_below_threshold(export_threshold) || info.used { + if info.level.is_below_threshold(export_threshold) || info.used || info.used_compiler { Some(CString::new(name.as_str()).unwrap()) } else { None @@ -734,7 +735,7 @@ pub unsafe fn optimize_thin_module( let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _; let mut module = ModuleCodegen { - module_llvm: ModuleLlvm { llmod_raw, llcx, tm }, + module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) }, name: thin_module.name().to_string(), kind: ModuleKind::Regular, }; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 9d5204034def0..1a567c0fce816 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -124,7 +124,7 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMach let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }; target_machine_factory( - &tcx.sess, + tcx.sess, tcx.backend_optimization_level(()), tcx.global_backend_features(()), )(config) @@ -571,7 +571,6 @@ pub(crate) unsafe fn llvm_optimize( unroll_loops, config.vectorize_slp, config.vectorize_loop, - config.no_builtins, config.emit_lifetime_markers, sanitizer_options.as_ref(), pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), @@ -686,7 +685,6 @@ pub(crate) unsafe fn codegen( unsafe fn with_codegen<'ll, F, R>( tm: &'ll llvm::TargetMachine, llmod: &'ll llvm::Module, - no_builtins: bool, f: F, ) -> R where @@ -694,7 +692,7 @@ pub(crate) unsafe fn codegen( { let cpm = llvm::LLVMCreatePassManager(); llvm::LLVMAddAnalysisPasses(tm, cpm); - llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); + llvm::LLVMRustAddLibraryInfo(cpm, llmod); f(cpm) } @@ -797,7 +795,7 @@ pub(crate) unsafe fn codegen( } else { llmod }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, |cpm| { write_output_file( diag_handler, tm, @@ -832,7 +830,7 @@ pub(crate) unsafe fn codegen( (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()), }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, |cpm| { write_output_file( diag_handler, tm, @@ -990,11 +988,7 @@ unsafe fn embed_bitcode( // reason (see issue #90326 for historical background). let is_aix = target_is_aix(cgcx); let is_apple = target_is_apple(cgcx); - if is_apple - || is_aix - || cgcx.opts.target_triple.triple().starts_with("wasm") - || cgcx.opts.target_triple.triple().starts_with("asmjs") - { + if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") { // We don't need custom section flags, create LLVM globals. let llconst = common::bytes_in_context(llcx, bitcode); let llglobal = llvm::LLVMAddGlobal( @@ -1110,7 +1104,7 @@ fn record_llvm_cgu_instructions_stats(prof: &SelfProfilerRef, llmod: &llvm::Modu } let raw_stats = - llvm::build_string(|s| unsafe { llvm::LLVMRustModuleInstructionStats(&llmod, s) }) + llvm::build_string(|s| unsafe { llvm::LLVMRustModuleInstructionStats(llmod, s) }) .expect("cannot get module instruction stats"); #[derive(serde::Deserialize)] diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 7b259055d40b5..acd85dd9a2d93 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -489,6 +489,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { #[instrument(level = "trace", skip(self))] fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> { + if place.layout.is_unsized() { + let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {}); + if matches!(tail.kind(), ty::Foreign(..)) { + // Unsized locals and, at least conceptually, even unsized arguments must be copied + // around, which requires dynamically determining their size. Therefore, we cannot + // allow `extern` types here. Consult t-opsem before removing this check. + panic!("unsized locals must not be `extern` types"); + } + } assert_eq!(place.llextra.is_some(), place.layout.is_unsized()); if place.layout.is_zst() { diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index d5778757caae7..e675362ac338c 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -59,10 +59,10 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> // To avoid this, we set the Storage Class to "DllImport" so that // LLVM will prefix the name with `__imp_`. Ideally, we'd like the // existing logic below to set the Storage Class, but it has an - // exemption for MinGW for backwards compatability. + // exemption for MinGW for backwards compatibility. let llfn = cx.declare_fn( &common::i686_decorated_name( - &dllimport, + dllimport, common::is_mingw_gnu_toolchain(&tcx.sess.target), true, ), diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 0b0816c27b6df..8173e41aff457 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -203,6 +203,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetGlobalConstant(g, True); + llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global); llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage); } (s.to_owned(), g) @@ -245,8 +246,8 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } Scalar::Ptr(ptr, _size) => { - let (alloc_id, offset) = ptr.into_parts(); - let (base_addr, base_addr_space) = match self.tcx.global_alloc(alloc_id) { + let (prov, offset) = ptr.into_parts(); + let (base_addr, base_addr_space) = match self.tcx.global_alloc(prov.alloc_id()) { GlobalAlloc::Memory(alloc) => { let init = const_alloc_to_llvm(self, alloc); let alloc = alloc.inner(); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 307c1264dc1be..21ff267ca6746 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -72,7 +72,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation< } let mut next_offset = 0; - for &(offset, alloc_id) in alloc.provenance().ptrs().iter() { + for &(offset, prov) in alloc.provenance().ptrs().iter() { let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; @@ -92,13 +92,10 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation< .expect("const_alloc_to_llvm: could not read relocation pointer") as u64; - let address_space = cx.tcx.global_alloc(alloc_id).address_space(cx); + let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx); llvals.push(cx.scalar_to_backend( - InterpScalar::from_pointer( - Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), - &cx.tcx, - ), + InterpScalar::from_pointer(Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx), Scalar::Initialized { value: Primitive::Pointer(address_space), valid_range: WrappingRange::full(dl.pointer_size), @@ -187,7 +184,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( { cx.declare_global( &common::i686_decorated_name( - &dllimport, + dllimport, common::is_mingw_gnu_toolchain(&cx.tcx.sess.target), true, ), diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 4dd6372b5e045..92a8c00510b94 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -134,18 +134,6 @@ pub unsafe fn create_module<'ll>( let mut target_data_layout = sess.target.data_layout.to_string(); let llvm_version = llvm_util::get_version(); - if llvm_version < (16, 0, 0) { - if sess.target.arch == "s390x" { - // LLVM 16 data layout changed to always set 64-bit vector alignment, - // which is conditional in earlier LLVM versions. - // https://reviews.llvm.org/D131158 for the discussion. - target_data_layout = target_data_layout.replace("-v128:64", ""); - } else if sess.target.arch == "riscv64" { - // LLVM 16 introduced this change so as to produce more efficient code. - // See https://reviews.llvm.org/D116735 for the discussion. - target_data_layout = target_data_layout.replace("-n32:64-", "-n64-"); - } - } if llvm_version < (17, 0, 0) { if sess.target.arch.starts_with("powerpc") { // LLVM 17 specifies function pointer alignment for ppc: @@ -351,6 +339,16 @@ pub unsafe fn create_module<'ll>( ); } + // Set module flag to enable Windows EHCont Guard (/guard:ehcont). + if sess.opts.unstable_opts.ehcont_guard { + llvm::LLVMRustAddModuleFlag( + llmod, + llvm::LLVMModFlagBehavior::Warning, + "ehcontguard\0".as_ptr() as *const _, + 1, + ) + } + // Insert `llvm.ident` metadata. // // On the wasm targets it will get hooked up to the "producer" sections @@ -368,6 +366,24 @@ pub unsafe fn create_module<'ll>( llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1), ); + // Add module flags specified via -Z llvm_module_flag + for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag { + let key = format!("{key}\0"); + let behavior = match behavior.as_str() { + "error" => llvm::LLVMModFlagBehavior::Error, + "warning" => llvm::LLVMModFlagBehavior::Warning, + "require" => llvm::LLVMModFlagBehavior::Require, + "override" => llvm::LLVMModFlagBehavior::Override, + "append" => llvm::LLVMModFlagBehavior::Append, + "appendunique" => llvm::LLVMModFlagBehavior::AppendUnique, + "max" => llvm::LLVMModFlagBehavior::Max, + "min" => llvm::LLVMModFlagBehavior::Min, + // We already checked this during option parsing + _ => unreachable!(), + }; + llvm::LLVMRustAddModuleFlag(llmod, behavior, key.as_ptr().cast(), *value) + } + llmod } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 274e0aeaaba4f..51df14df644e0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -176,7 +176,7 @@ impl GlobalFileTable { // compilation directory can be combined with the relative paths // to get absolute paths, if needed. use rustc_session::RemapFileNameExt; - let working_dir: &str = &tcx.sess.opts.working_dir.for_codegen(&tcx.sess).to_string_lossy(); + let working_dir: &str = &tcx.sess.opts.working_dir.for_codegen(tcx.sess).to_string_lossy(); llvm::build_byte_buffer(|buffer| { coverageinfo::write_filenames_section_to_buffer( @@ -189,8 +189,6 @@ impl GlobalFileTable { } rustc_index::newtype_index! { - // Tell the newtype macro to not generate `Encode`/`Decode` impls. - #[custom_encodable] struct LocalFileId {} } @@ -375,10 +373,7 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) { // just "functions", like consts, statics, etc. Filter those out. // If `ignore_unused_generics` was specified, filter out any // generic functions from consideration as well. - if !matches!( - kind, - DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Coroutine - ) { + if !matches!(kind, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) { return None; } if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 865bf01c8c1e0..cf78fc56b498c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -853,7 +853,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( use rustc_session::RemapFileNameExt; let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); - let work_dir = tcx.sess.opts.working_dir.for_codegen(&tcx.sess).to_string_lossy(); + let work_dir = tcx.sess.opts.working_dir.for_codegen(tcx.sess).to_string_lossy(); let flags = "\0"; let output_filenames = tcx.output_filenames(()); let split_name = if tcx.sess.target_can_use_split_dwarf() { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index ca7bfbeac25ce..7ef185250a38c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -715,7 +715,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>( coroutine_type_and_layout, coroutine_type_di_node, coroutine_layout, - &common_upvar_names, + common_upvar_names, ); let span = coroutine_layout.variant_source_info[variant_index].span; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 7eff52b857f8e..130ca2727e4ca 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -197,7 +197,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( coroutine_type_and_layout, coroutine_type_di_node, coroutine_layout, - &common_upvar_names, + common_upvar_names, ), source_info, } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 665d195790c2d..57ea13ddcd6a8 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -5,7 +5,7 @@ use std::path::Path; use crate::fluent_generated as fluent; use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{ - DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, Handler, IntoDiagnostic, + DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, FatalError, Handler, IntoDiagnostic, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -26,6 +26,13 @@ pub(crate) struct UnknownCTargetFeature<'a> { pub rust_feature: PossibleFeature<'a>, } +#[derive(Diagnostic)] +#[diag(codegen_llvm_unstable_ctarget_feature)] +#[note] +pub(crate) struct UnstableCTargetFeature<'a> { + pub feature: &'a str, +} + #[derive(Subdiagnostic)] pub(crate) enum PossibleFeature<'a> { #[help(codegen_llvm_possible_feature)] @@ -94,13 +101,13 @@ pub(crate) struct DynamicLinkingWithLTO; pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); -impl IntoDiagnostic<'_, EM> for ParseTargetMachineConfig<'_> { - fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> { - let diag: DiagnosticBuilder<'_, EM> = self.0.into_diagnostic(sess); +impl IntoDiagnostic<'_, FatalError> for ParseTargetMachineConfig<'_> { + fn into_diagnostic(self, handler: &'_ Handler) -> DiagnosticBuilder<'_, FatalError> { + let diag: DiagnosticBuilder<'_, FatalError> = self.0.into_diagnostic(handler); let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message"); - let message = sess.eagerly_translate_to_string(message.clone(), diag.args()); + let message = handler.eagerly_translate_to_string(message.clone(), diag.args()); - let mut diag = sess.struct_diagnostic(fluent::codegen_llvm_parse_target_machine_config); + let mut diag = handler.struct_diagnostic(fluent::codegen_llvm_parse_target_machine_config); diag.set_arg("error", message); diag } @@ -117,8 +124,8 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { pub(crate) struct MissingFeatures; impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); + fn into_diagnostic(self, handler: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); if let Some(span) = self.span { diag.set_span(span); }; @@ -176,8 +183,8 @@ pub enum LlvmError<'a> { pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String); -impl IntoDiagnostic<'_, EM> for WithLlvmError<'_> { - fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> { +impl IntoDiagnostic<'_, G> for WithLlvmError<'_> { + fn into_diagnostic(self, handler: &'_ Handler) -> DiagnosticBuilder<'_, G> { use LlvmError::*; let msg_with_llvm_err = match &self.0 { WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err, @@ -194,7 +201,7 @@ impl IntoDiagnostic<'_, EM> for WithLlvmError<'_> { PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err, ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, }; - let mut diag = self.0.into_diagnostic(sess); + let mut diag = self.0.into_diagnostic(handler); diag.set_primary_message(msg_with_llvm_err); diag.set_arg("llvm_err", self.1); diag diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 8a6a5f79b3bb9..915cf31de08fb 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -4,9 +4,9 @@ //! //! This API is completely unstable and subject to change. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(exact_size_is_empty)] #![feature(extern_types)] @@ -40,8 +40,7 @@ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::{CodegenResults, CompiledModule}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, FatalError, Handler, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; +use rustc_errors::{ErrorGuaranteed, FatalError, Handler}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; @@ -53,6 +52,7 @@ use rustc_span::symbol::Symbol; use std::any::Any; use std::ffi::CStr; use std::io::Write; +use std::mem::ManuallyDrop; mod back { pub mod archive; @@ -92,7 +92,7 @@ mod type_of; mod va_arg; mod value; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } #[derive(Clone)] pub struct LlvmCodegenBackend(()); @@ -104,7 +104,7 @@ struct TimeTraceProfiler { impl TimeTraceProfiler { fn new(enabled: bool) -> Self { if enabled { - unsafe { llvm::LLVMTimeTraceProfilerInitialize() } + unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() } } TimeTraceProfiler { enabled } } @@ -113,7 +113,7 @@ impl TimeTraceProfiler { impl Drop for TimeTraceProfiler { fn drop(&mut self) { if self.enabled { - unsafe { llvm::LLVMTimeTraceProfilerFinishThread() } + unsafe { llvm::LLVMRustTimeTraceProfilerFinishThread() } } } } @@ -408,8 +408,9 @@ pub struct ModuleLlvm { llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, - // independent from llcx and llmod_raw, resources get disposed by drop impl - tm: OwnedTargetMachine, + // This field is `ManuallyDrop` because it is important that the `TargetMachine` + // is disposed prior to the `Context` being disposed otherwise UAFs can occur. + tm: ManuallyDrop, } unsafe impl Send for ModuleLlvm {} @@ -420,7 +421,11 @@ impl ModuleLlvm { unsafe { let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names()); let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; - ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) } + ModuleLlvm { + llmod_raw, + llcx, + tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)), + } } } @@ -428,7 +433,11 @@ impl ModuleLlvm { unsafe { let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names()); let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; - ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) } + ModuleLlvm { + llmod_raw, + llcx, + tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)), + } } } @@ -449,7 +458,7 @@ impl ModuleLlvm { } }; - Ok(ModuleLlvm { llmod_raw, llcx, tm }) + Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) }) } } @@ -461,6 +470,7 @@ impl ModuleLlvm { impl Drop for ModuleLlvm { fn drop(&mut self) { unsafe { + ManuallyDrop::drop(&mut self.tm); llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 7fc02a95be0a9..6c3ccc9cf0dee 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -200,6 +200,7 @@ pub enum AttributeKind { AllocatedPointer = 38, AllocAlign = 39, SanitizeSafeStack = 40, + FnRetThunkExtern = 41, } /// LLVMIntPredicate @@ -823,11 +824,7 @@ pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) - pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; extern "C" { - pub fn LLVMRustInstallFatalErrorHandler(); - pub fn LLVMRustDisableSystemDialogsOnCrash(); - // Create and destroy contexts. - pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context; pub fn LLVMContextDispose(C: &'static mut Context); pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint; @@ -843,9 +840,6 @@ extern "C" { /// See Module::setModuleInlineAsm. pub fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t); - /// See llvm::LLVMTypeKind::getTypeID. - pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind; - // Operations on integer types pub fn LLVMInt1TypeInContext(C: &Context) -> &Type; pub fn LLVMInt8TypeInContext(C: &Context) -> &Type; @@ -879,7 +873,6 @@ extern "C" { ) -> &'a Type; // Operations on array, pointer, and vector types (sequence types) - pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type; pub fn LLVMPointerTypeInContext(C: &Context, AddressSpace: c_uint) -> &Type; pub fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type; @@ -898,10 +891,7 @@ extern "C" { pub fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value); pub fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Node: &'a Value); pub fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); - pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata; - pub fn LLVMIsAFunction(Val: &Value) -> Option<&Value>; - pub fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool; // Operations on constants of any type pub fn LLVMConstNull(Ty: &Type) -> &Value; @@ -931,13 +921,6 @@ extern "C" { pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value; pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value; - pub fn LLVMRustConstIntGetZExtValue(ConstantVal: &ConstantInt, Value: &mut u64) -> bool; - pub fn LLVMRustConstInt128Get( - ConstantVal: &ConstantInt, - SExt: bool, - high: &mut u64, - low: &mut u64, - ) -> bool; // Operations on composite constants pub fn LLVMConstStringInContext( @@ -972,17 +955,11 @@ extern "C" { pub fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMGetAggregateElement(ConstantVal: &Value, Idx: c_uint) -> Option<&Value>; // Operations on global variables, functions, and aliases (globals) pub fn LLVMIsDeclaration(Global: &Value) -> Bool; - pub fn LLVMRustGetLinkage(Global: &Value) -> Linkage; - pub fn LLVMRustSetLinkage(Global: &Value, RustLinkage: Linkage); pub fn LLVMSetSection(Global: &Value, Section: *const c_char); - pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility; - pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility); - pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool); pub fn LLVMGetAlignment(Global: &Value) -> c_uint; pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint); pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass); @@ -991,13 +968,6 @@ extern "C" { pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>; pub fn LLVMAddGlobal<'a>(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value; pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>; - pub fn LLVMRustGetOrInsertGlobal<'a>( - M: &'a Module, - Name: *const c_char, - NameLen: size_t, - T: &'a Type, - ) -> &'a Value; - pub fn LLVMRustInsertPrivateGlobal<'a>(M: &'a Module, T: &'a Type) -> &'a Value; pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>; pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>; pub fn LLVMDeleteGlobal(GlobalVar: &Value); @@ -1007,16 +977,9 @@ extern "C" { pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode); pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool; pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool); - pub fn LLVMRustGetNamedValue( - M: &Module, - Name: *const c_char, - NameLen: size_t, - ) -> Option<&Value>; pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool); - pub fn LLVMRustSetTailCallKind(CallInst: &Value, TKC: TailCallKind); // Operations on attributes - pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute; pub fn LLVMCreateStringAttribute( C: &Context, Name: *const c_char, @@ -1024,31 +987,9 @@ extern "C" { Value: *const c_char, ValueLen: c_uint, ) -> &Attribute; - pub fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute; - pub fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute; - pub fn LLVMRustCreateDereferenceableOrNullAttr(C: &Context, bytes: u64) -> &Attribute; - pub fn LLVMRustCreateByValAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; - pub fn LLVMRustCreateStructRetAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; - pub fn LLVMRustCreateElementTypeAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; - pub fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute; - pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute; - pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute; - pub fn LLVMRustCreateMemoryEffectsAttr(C: &Context, effects: MemoryEffects) -> &Attribute; // Operations on functions - pub fn LLVMRustGetOrInsertFunction<'a>( - M: &'a Module, - Name: *const c_char, - NameLen: size_t, - FunctionTy: &'a Type, - ) -> &'a Value; pub fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint); - pub fn LLVMRustAddFunctionAttributes<'a>( - Fn: &'a Value, - index: c_uint, - Attrs: *const &'a Attribute, - AttrsLen: size_t, - ); // Operations on parameters pub fn LLVMIsAArgument(Val: &Value) -> Option<&Value>; @@ -1069,12 +1010,6 @@ extern "C" { // Operations on call sites pub fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint); - pub fn LLVMRustAddCallSiteAttributes<'a>( - Instr: &'a Value, - index: c_uint, - Attrs: *const &'a Attribute, - AttrsLen: size_t, - ); // Operations on load/store instructions (only) pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool); @@ -1112,18 +1047,6 @@ extern "C" { Else: &'a BasicBlock, NumCases: c_uint, ) -> &'a Value; - pub fn LLVMRustBuildInvoke<'a>( - B: &Builder<'a>, - Ty: &'a Type, - Fn: &'a Value, - Args: *const &'a Value, - NumArgs: c_uint, - Then: &'a BasicBlock, - Catch: &'a BasicBlock, - OpBundles: *const &OperandBundleDef<'a>, - NumOpBundles: c_uint, - Name: *const c_char, - ) -> &'a Value; pub fn LLVMBuildLandingPad<'a>( B: &Builder<'a>, Ty: &'a Type, @@ -1337,7 +1260,6 @@ extern "C" { pub fn LLVMBuildNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; pub fn LLVMBuildFNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; pub fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; - pub fn LLVMRustSetFastMath(Instr: &Value); // Memory pub fn LLVMBuildAlloca<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; @@ -1485,42 +1407,6 @@ extern "C" { // Miscellaneous instructions pub fn LLVMBuildPhi<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; - pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &Value; - pub fn LLVMRustBuildCall<'a>( - B: &Builder<'a>, - Ty: &'a Type, - Fn: &'a Value, - Args: *const &'a Value, - NumArgs: c_uint, - OpBundles: *const &OperandBundleDef<'a>, - NumOpBundles: c_uint, - ) -> &'a Value; - pub fn LLVMRustBuildMemCpy<'a>( - B: &Builder<'a>, - Dst: &'a Value, - DstAlign: c_uint, - Src: &'a Value, - SrcAlign: c_uint, - Size: &'a Value, - IsVolatile: bool, - ) -> &'a Value; - pub fn LLVMRustBuildMemMove<'a>( - B: &Builder<'a>, - Dst: &'a Value, - DstAlign: c_uint, - Src: &'a Value, - SrcAlign: c_uint, - Size: &'a Value, - IsVolatile: bool, - ) -> &'a Value; - pub fn LLVMRustBuildMemSet<'a>( - B: &Builder<'a>, - Dst: &'a Value, - DstAlign: c_uint, - Val: &'a Value, - Size: &'a Value, - IsVolatile: bool, - ) -> &'a Value; pub fn LLVMBuildSelect<'a>( B: &Builder<'a>, If: &'a Value, @@ -1568,6 +1454,202 @@ extern "C" { Name: *const c_char, ) -> &'a Value; + // Atomic Operations + pub fn LLVMBuildAtomicCmpXchg<'a>( + B: &Builder<'a>, + LHS: &'a Value, + CMP: &'a Value, + RHS: &'a Value, + Order: AtomicOrdering, + FailureOrder: AtomicOrdering, + SingleThreaded: Bool, + ) -> &'a Value; + + pub fn LLVMSetWeak(CmpXchgInst: &Value, IsWeak: Bool); + + pub fn LLVMBuildAtomicRMW<'a>( + B: &Builder<'a>, + Op: AtomicRmwBinOp, + LHS: &'a Value, + RHS: &'a Value, + Order: AtomicOrdering, + SingleThreaded: Bool, + ) -> &'a Value; + + pub fn LLVMBuildFence<'a>( + B: &Builder<'a>, + Order: AtomicOrdering, + SingleThreaded: Bool, + Name: *const c_char, + ) -> &'a Value; + + /// Writes a module to the specified path. Returns 0 on success. + pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; + + /// Creates a legacy pass manager -- only used for final codegen. + pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>; + + pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>); + + pub fn LLVMGetHostCPUFeatures() -> *mut c_char; + + pub fn LLVMDisposeMessage(message: *mut c_char); + + pub fn LLVMIsMultithreaded() -> Bool; + + pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type; + + pub fn LLVMStructSetBody<'a>( + StructTy: &'a Type, + ElementTypes: *const &'a Type, + ElementCount: c_uint, + Packed: Bool, + ); + + pub fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; + + pub fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr); + + pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>; +} + +#[link(name = "llvm-wrapper", kind = "static")] +extern "C" { + pub fn LLVMRustInstallFatalErrorHandler(); + pub fn LLVMRustDisableSystemDialogsOnCrash(); + + // Create and destroy contexts. + pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context; + + /// See llvm::LLVMTypeKind::getTypeID. + pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind; + + // Operations on array, pointer, and vector types (sequence types) + pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type; + + // Operations on all values + pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); + pub fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool; + + // Operations on scalar constants + pub fn LLVMRustConstIntGetZExtValue(ConstantVal: &ConstantInt, Value: &mut u64) -> bool; + pub fn LLVMRustConstInt128Get( + ConstantVal: &ConstantInt, + SExt: bool, + high: &mut u64, + low: &mut u64, + ) -> bool; + + // Operations on global variables, functions, and aliases (globals) + pub fn LLVMRustGetLinkage(Global: &Value) -> Linkage; + pub fn LLVMRustSetLinkage(Global: &Value, RustLinkage: Linkage); + pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility; + pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility); + pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool); + + // Operations on global variables + pub fn LLVMRustGetOrInsertGlobal<'a>( + M: &'a Module, + Name: *const c_char, + NameLen: size_t, + T: &'a Type, + ) -> &'a Value; + pub fn LLVMRustInsertPrivateGlobal<'a>(M: &'a Module, T: &'a Type) -> &'a Value; + pub fn LLVMRustGetNamedValue( + M: &Module, + Name: *const c_char, + NameLen: size_t, + ) -> Option<&Value>; + pub fn LLVMRustSetTailCallKind(CallInst: &Value, TKC: TailCallKind); + + // Operations on attributes + pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute; + pub fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute; + pub fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute; + pub fn LLVMRustCreateDereferenceableOrNullAttr(C: &Context, bytes: u64) -> &Attribute; + pub fn LLVMRustCreateByValAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; + pub fn LLVMRustCreateStructRetAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; + pub fn LLVMRustCreateElementTypeAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; + pub fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute; + pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute; + pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute; + pub fn LLVMRustCreateMemoryEffectsAttr(C: &Context, effects: MemoryEffects) -> &Attribute; + + // Operations on functions + pub fn LLVMRustGetOrInsertFunction<'a>( + M: &'a Module, + Name: *const c_char, + NameLen: size_t, + FunctionTy: &'a Type, + ) -> &'a Value; + pub fn LLVMRustAddFunctionAttributes<'a>( + Fn: &'a Value, + index: c_uint, + Attrs: *const &'a Attribute, + AttrsLen: size_t, + ); + + // Operations on call sites + pub fn LLVMRustAddCallSiteAttributes<'a>( + Instr: &'a Value, + index: c_uint, + Attrs: *const &'a Attribute, + AttrsLen: size_t, + ); + + pub fn LLVMRustBuildInvoke<'a>( + B: &Builder<'a>, + Ty: &'a Type, + Fn: &'a Value, + Args: *const &'a Value, + NumArgs: c_uint, + Then: &'a BasicBlock, + Catch: &'a BasicBlock, + OpBundles: *const &OperandBundleDef<'a>, + NumOpBundles: c_uint, + Name: *const c_char, + ) -> &'a Value; + + pub fn LLVMRustSetFastMath(Instr: &Value); + + // Miscellaneous instructions + pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &Value; + pub fn LLVMRustBuildCall<'a>( + B: &Builder<'a>, + Ty: &'a Type, + Fn: &'a Value, + Args: *const &'a Value, + NumArgs: c_uint, + OpBundles: *const &OperandBundleDef<'a>, + NumOpBundles: c_uint, + ) -> &'a Value; + pub fn LLVMRustBuildMemCpy<'a>( + B: &Builder<'a>, + Dst: &'a Value, + DstAlign: c_uint, + Src: &'a Value, + SrcAlign: c_uint, + Size: &'a Value, + IsVolatile: bool, + ) -> &'a Value; + pub fn LLVMRustBuildMemMove<'a>( + B: &Builder<'a>, + Dst: &'a Value, + DstAlign: c_uint, + Src: &'a Value, + SrcAlign: c_uint, + Size: &'a Value, + IsVolatile: bool, + ) -> &'a Value; + pub fn LLVMRustBuildMemSet<'a>( + B: &Builder<'a>, + Dst: &'a Value, + DstAlign: c_uint, + Val: &'a Value, + Size: &'a Value, + IsVolatile: bool, + ) -> &'a Value; + pub fn LLVMRustBuildVectorReduceFAdd<'a>( B: &Builder<'a>, Acc: &'a Value, @@ -1623,53 +1705,11 @@ extern "C" { Order: AtomicOrdering, ) -> &'a Value; - pub fn LLVMBuildAtomicCmpXchg<'a>( - B: &Builder<'a>, - LHS: &'a Value, - CMP: &'a Value, - RHS: &'a Value, - Order: AtomicOrdering, - FailureOrder: AtomicOrdering, - SingleThreaded: Bool, - ) -> &'a Value; + pub fn LLVMRustTimeTraceProfilerInitialize(); - pub fn LLVMSetWeak(CmpXchgInst: &Value, IsWeak: Bool); + pub fn LLVMRustTimeTraceProfilerFinishThread(); - pub fn LLVMBuildAtomicRMW<'a>( - B: &Builder<'a>, - Op: AtomicRmwBinOp, - LHS: &'a Value, - RHS: &'a Value, - Order: AtomicOrdering, - SingleThreaded: Bool, - ) -> &'a Value; - - pub fn LLVMBuildFence<'a>( - B: &Builder<'a>, - Order: AtomicOrdering, - SingleThreaded: Bool, - Name: *const c_char, - ) -> &'a Value; - - /// Writes a module to the specified path. Returns 0 on success. - pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; - - /// Creates a legacy pass manager -- only used for final codegen. - pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>; - - pub fn LLVMTimeTraceProfilerInitialize(); - - pub fn LLVMTimeTraceProfilerFinishThread(); - - pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char); - - pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>); - - pub fn LLVMGetHostCPUFeatures() -> *mut c_char; - - pub fn LLVMDisposeMessage(message: *mut c_char); - - pub fn LLVMIsMultithreaded() -> Bool; + pub fn LLVMRustTimeTraceProfilerFinish(FileName: *const c_char); /// Returns a string describing the last error caused by an LLVMRust* call. pub fn LLVMRustGetLastError() -> *const c_char; @@ -1680,15 +1720,6 @@ extern "C" { /// Print the statistics since static dtors aren't picking them up. pub fn LLVMRustPrintStatistics(size: *const size_t) -> *const c_char; - pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type; - - pub fn LLVMStructSetBody<'a>( - StructTy: &'a Type, - ElementTypes: *const &'a Type, - ElementCount: c_uint, - Packed: Bool, - ); - /// Prepares inline assembly. pub fn LLVMRustInlineAsm( Ty: &Type, @@ -1761,8 +1792,6 @@ extern "C" { ); pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool; - pub fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; - pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>; pub fn LLVMRustDIBuilderDispose<'a>(Builder: &'a mut DIBuilder<'a>); @@ -2052,8 +2081,6 @@ extern "C" { UniqueIdLen: size_t, ) -> &'a DIDerivedType; - pub fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr); - pub fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, @@ -2092,8 +2119,6 @@ extern "C" { #[allow(improper_ctypes)] pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); - pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>; - pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; pub fn LLVMRustPrintTargetCPUs( @@ -2138,13 +2163,8 @@ extern "C" { ArgsCstrBuff: *const c_char, ArgsCstrBuffLen: usize, ) -> *mut TargetMachine; - pub fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine); - pub fn LLVMRustAddLibraryInfo<'a>( - PM: &PassManager<'a>, - M: &'a Module, - DisableSimplifyLibCalls: bool, - ); + pub fn LLVMRustAddLibraryInfo<'a>(PM: &PassManager<'a>, M: &'a Module); pub fn LLVMRustWriteOutputFile<'a>( T: &'a TargetMachine, PM: &PassManager<'a>, @@ -2166,7 +2186,6 @@ extern "C" { UnrollLoops: bool, SLPVectorize: bool, LoopVectorize: bool, - DisableSimplifyLibCalls: bool, EmitLifetimeMarkers: bool, SanitizerOptions: Option<&SanitizerOptions>, PGOGenPath: *const c_char, @@ -2320,11 +2339,6 @@ extern "C" { len: usize, Identifier: *const c_char, ) -> Option<&Module>; - pub fn LLVMRustGetBitcodeSliceFromObjectData( - Data: *const u8, - len: usize, - out_len: &mut usize, - ) -> *const u8; pub fn LLVMRustGetSliceFromObjectDataByName( data: *const u8, len: usize, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 7c8ef67ffd10e..eb69efb0d5952 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,7 +1,7 @@ use crate::back::write::create_informational_target_machine; use crate::errors::{ PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, - UnknownCTargetFeaturePrefix, + UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; use libc::c_int; @@ -121,7 +121,7 @@ unsafe fn configure_llvm(sess: &Session) { } if sess.opts.unstable_opts.llvm_time_trace { - llvm::LLVMTimeTraceProfilerInitialize(); + llvm::LLVMRustTimeTraceProfilerInitialize(); } rustc_llvm::initialize_available_targets(); @@ -132,7 +132,7 @@ unsafe fn configure_llvm(sess: &Session) { pub fn time_trace_profiler_finish(file_name: &Path) { unsafe { let file_name = path_to_c_string(file_name); - llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr()); + llvm::LLVMRustTimeTraceProfilerFinish(file_name.as_ptr()); } } @@ -293,7 +293,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { supported_target_features(sess) .iter() .filter_map(|&(feature, gate)| { - if sess.is_nightly_build() || allow_unstable || gate.is_none() { + if sess.is_nightly_build() || allow_unstable || gate.is_stable() { Some(feature) } else { None @@ -531,25 +531,34 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { } impl Type { - pub fn i8_llcx(llcx: &llvm::Context) -> &Type { - unsafe { llvm::LLVMInt8TypeInContext(llcx) } - } - /// Creates an integer type with the given number of bits, e.g., i24 pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type { unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) } diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 712b6ed533303..624ce6d8813e7 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_target::abi::HasDataLayout; use rustc_target::abi::{Abi, Align, FieldsShape}; use rustc_target::abi::{Int, Pointer, F32, F64}; -use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants}; +use rustc_target::abi::{Scalar, Size, Variants}; use smallvec::{smallvec, SmallVec}; use std::fmt::Write; @@ -184,7 +184,6 @@ pub trait LayoutLlvmExt<'tcx> { immediate: bool, ) -> &'a Type; fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64; - fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option; fn scalar_copy_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<&'a Type>; } @@ -356,20 +355,6 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { } } - // FIXME(eddyb) this having the same name as `TyAndLayout::pointee_info_at` - // (the inherent method, which is lacking this caching logic) can result in - // the uncached version being called - not wrong, but potentially inefficient. - fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option { - if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) { - return pointee; - } - - let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset); - - cx.pointee_infos.borrow_mut().insert((self.ty, offset), result); - result - } - fn scalar_copy_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<&'a Type> { debug_assert!(self.is_sized()); diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 4dae49f81a386..3f2ed257d0830 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" ar_archive_writer = "0.1.5" bitflags = "1.2.1" cc = "1.0.69" -itertools = "0.10.1" -jobserver = "0.1.22" +itertools = "0.11" +jobserver = "0.1.27" pathdiff = "0.2.0" regex = "1.4" rustc_arena = { path = "../rustc_arena" } @@ -46,7 +46,7 @@ libc = "0.2.50" # tidy-alphabetical-end [dependencies.object] -version = "0.32.0" +version = "0.32.1" default-features = false features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write"] diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index 16bb7b12bd3c1..3d479c5c22d2f 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -149,7 +149,7 @@ impl<'tcx> AssertModuleSource<'tcx> { self.cgu_reuse_tracker.set_expectation( cgu_name, - &user_path, + user_path, attr.span, expected_reuse, comp_kind, diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 1c464b3eca497..4dc28adf336d4 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -175,8 +175,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { ) -> io::Result<()> { let mut archive_path = archive_path.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") { - if let Some(new_archive_path) = - try_extract_macho_fat_archive(&self.sess, &archive_path)? + if let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)? { archive_path = new_archive_path } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index bcbb75d959976..000b2748e4f93 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -44,7 +44,7 @@ use tempfile::Builder as TempFileBuilder; use itertools::Itertools; use std::cell::OnceCell; use std::collections::BTreeSet; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fs::{read, File, OpenOptions}; use std::io::{BufWriter, Write}; use std::ops::Deref; @@ -143,7 +143,7 @@ pub fn link_binary<'a>( } } if sess.opts.json_artifact_notifications { - sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link"); + sess.diagnostic().emit_artifact_notification(&out_filename, "link"); } if sess.prof.enabled() { @@ -270,14 +270,20 @@ pub fn each_linked_rlib( for &cnum in crates { match fmts.get(cnum.as_usize() - 1) { - Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue, - Some(_) => {} + Some(&Linkage::NotLinked | &Linkage::Dynamic) => continue, + Some(&Linkage::IncludedFromDylib) => { + // We always link crate `compiler_builtins` statically. When enabling LTO, we include it as well. + if info.compiler_builtins != Some(cnum) { + continue; + } + } + Some(&Linkage::Static) => {} None => return Err(errors::LinkRlibError::MissingFormat), } let crate_name = info.crate_name[&cnum]; let used_crate_source = &info.used_crate_source[&cnum]; if let Some((path, _)) = &used_crate_source.rlib { - f(cnum, &path); + f(cnum, path); } else { if used_crate_source.rmeta.is_some() { return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); @@ -520,11 +526,10 @@ fn link_staticlib<'a>( &codegen_results.crate_info, Some(CrateType::Staticlib), &mut |cnum, path| { - let lto = are_upstream_rust_objects_already_included(sess) - && !ignored_for_lto(sess, &codegen_results.crate_info, cnum); + let lto = are_upstream_rust_objects_already_included(sess); let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter(); - let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, &lib)); + let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib)); let relevant_libs: FxHashSet<_> = relevant.filter_map(|lib| lib.filename).collect(); let bundled_libs: FxHashSet<_> = native_libs.filter_map(|lib| lib.filename).collect(); @@ -689,7 +694,7 @@ fn link_dwarf_object<'a>( // Adding an executable is primarily done to make `thorin` check that all the referenced // dwarf objects are found in the end. package.add_executable( - &executable_out_filename, + executable_out_filename, thorin::MissingReferencedObjectBehaviour::Skip, )?; @@ -945,7 +950,7 @@ fn link_natively<'a>( { let is_vs_installed = windows_registry::find_vs_version().is_ok(); let has_linker = windows_registry::find_tool( - &sess.opts.target_triple.triple(), + sess.opts.target_triple.triple(), "link.exe", ) .is_some(); @@ -1033,19 +1038,19 @@ fn link_natively<'a>( SplitDebuginfo::Packed => link_dwarf_object(sess, codegen_results, out_filename), } - let strip = strip_value(sess); + let strip = sess.opts.cg.strip; if sess.target.is_like_osx { match (strip, crate_type) { (Strip::Debuginfo, _) => { - strip_symbols_with_external_utility(sess, "strip", &out_filename, Some("-S")) + strip_symbols_with_external_utility(sess, "strip", out_filename, Some("-S")) } // Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988) (Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => { - strip_symbols_with_external_utility(sess, "strip", &out_filename, Some("-x")) + strip_symbols_with_external_utility(sess, "strip", out_filename, Some("-x")) } (Strip::Symbols, _) => { - strip_symbols_with_external_utility(sess, "strip", &out_filename, None) + strip_symbols_with_external_utility(sess, "strip", out_filename, None) } (Strip::None, _) => {} } @@ -1059,7 +1064,7 @@ fn link_natively<'a>( match strip { // Always preserve the symbol table (-x). Strip::Debuginfo => { - strip_symbols_with_external_utility(sess, stripcmd, &out_filename, Some("-x")) + strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-x")) } // Strip::Symbols is handled via the --strip-all linker option. Strip::Symbols => {} @@ -1070,14 +1075,6 @@ fn link_natively<'a>( Ok(()) } -// Temporarily support both -Z strip and -C strip -fn strip_value(sess: &Session) -> Strip { - match (sess.opts.unstable_opts.strip, sess.opts.cg.strip) { - (s, Strip::None) => s, - (_, s) => s, - } -} - fn strip_symbols_with_external_utility<'a>( sess: &'a Session, util: &str, @@ -1253,35 +1250,17 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { // rpath to the library as well (the rpath should be absolute, see // PR #41352 for details). let filename = format!("rustc{channel}_rt.{name}"); - let path = find_sanitizer_runtime(&sess, &filename); + let path = find_sanitizer_runtime(sess, &filename); let rpath = path.to_str().expect("non-utf8 component in path"); linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); linker.link_dylib(&filename, false, true); } else { let filename = format!("librustc{channel}_rt.{name}.a"); - let path = find_sanitizer_runtime(&sess, &filename).join(&filename); + let path = find_sanitizer_runtime(sess, &filename).join(&filename); linker.link_whole_rlib(&path); } } -/// Returns a boolean indicating whether the specified crate should be ignored -/// during LTO. -/// -/// Crates ignored during LTO are not lumped together in the "massive object -/// file" that we create and are linked in their normal rlib states. See -/// comments below for what crates do not participate in LTO. -/// -/// It's unusual for a crate to not participate in LTO. Typically only -/// compiler-specific and unstable crates have a reason to not participate in -/// LTO. -pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool { - // If our target enables builtin function lowering in LLVM then the - // crates providing these functions don't participate in LTO (e.g. - // no_builtins or compiler builtins crates). - !sess.target.no_builtins - && (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum)) -} - /// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { fn infer_from( @@ -1485,7 +1464,7 @@ fn print_native_static_libs( sess.emit_note(errors::StaticLibraryNativeArtifacts); // Prefix for greppability // Note: This must not be translated as tools are allowed to depend on this exact string. - sess.note_without_error(format!("native-static-libs: {}", &lib_args.join(" "))); + sess.note(format!("native-static-libs: {}", &lib_args.join(" "))); } } } @@ -1693,7 +1672,7 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { // Returns true if linker is located within sysroot fn detect_self_contained_mingw(sess: &Session) -> bool { - let (linker, _) = linker_and_flavor(&sess); + let (linker, _) = linker_and_flavor(sess); // Assume `-C linker=rust-lld` as self-contained mode if linker == Path::new("rust-lld") { return true; @@ -1745,7 +1724,7 @@ fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfC LinkSelfContainedDefault::InferredForMingw => { sess.host == sess.target && sess.target.vendor != "uwp" - && detect_self_contained_mingw(&sess) + && detect_self_contained_mingw(sess) } } }; @@ -2251,9 +2230,9 @@ fn linker_with_args<'a>( // ------------ Late order-dependent options ------------ // Doesn't really make sense. - // FIXME: In practice built-in target specs use this for arbitrary order-independent options, - // introduce a target spec option for order-independent linker options, migrate built-in specs - // to it and remove the option. + // FIXME: In practice built-in target specs use this for arbitrary order-independent options. + // Introduce a target spec option for order-independent linker options, migrate built-in specs + // to it and remove the option. Currently the last holdout is wasm32-unknown-emscripten. add_post_link_args(cmd, sess, flavor); Ok(cmd.take_cmd()) @@ -2370,7 +2349,7 @@ fn add_order_independent_options( ); // Pass debuginfo, NatVis debugger visualizers and strip flags down to the linker. - cmd.debuginfo(strip_value(sess), &natvis_visualizers); + cmd.debuginfo(sess.opts.cg.strip, &natvis_visualizers); // We want to prevent the compiler from accidentally leaking in any system libraries, // so by default we tell linkers not to link to any default libraries. @@ -2386,6 +2365,11 @@ fn add_order_independent_options( cmd.control_flow_guard(); } + // OBJECT-FILES-NO, AUDIT-ORDER + if sess.opts.unstable_opts.ehcont_guard { + cmd.ehcont_guard(); + } + add_rpath_args(cmd, sess, codegen_results, out_filename); } @@ -2440,7 +2424,7 @@ fn add_native_libs_from_crate( // If rlib contains native libs as archives, unpack them to tmpdir. let rlib = &codegen_results.crate_info.used_crate_source[&cnum].rlib.as_ref().unwrap().0; archive_builder_builder - .extract_bundled_libs(rlib, tmpdir, &bundled_libs) + .extract_bundled_libs(rlib, tmpdir, bundled_libs) .unwrap_or_else(|e| sess.emit_fatal(e)); } @@ -2493,7 +2477,7 @@ fn add_native_libs_from_crate( cmd.link_whole_staticlib( name, verbatim, - &search_paths.get_or_init(|| archive_search_paths(sess)), + search_paths.get_or_init(|| archive_search_paths(sess)), ); } else { cmd.link_staticlib(name, verbatim) @@ -2530,7 +2514,7 @@ fn add_native_libs_from_crate( NativeLibKind::WasmImportModule => {} NativeLibKind::LinkArg => { if link_static { - cmd.arg(name); + cmd.linker_arg(OsStr::new(name), verbatim); } } } @@ -2727,7 +2711,7 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf { // already had `fix_windows_verbatim_for_gcc()` applied if needed. sysroot_lib_path } else { - fix_windows_verbatim_for_gcc(&lib_dir) + fix_windows_verbatim_for_gcc(lib_dir) } } @@ -2742,10 +2726,6 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf { // symbols). We must continue to include the rest of the rlib, however, as // it may contain static native libraries which must be linked in. // -// (*) Crates marked with `#![no_builtins]` don't participate in LTO and -// their bytecode wasn't included. The object files in those libraries must -// still be passed to the linker. -// // Note, however, that if we're not doing LTO we can just pass the rlib // blindly to the linker (fast) because it's fine if it's not actually // included as we're at the end of the dependency chain. @@ -2764,16 +2744,14 @@ fn add_static_crate<'a>( let mut link_upstream = |path: &Path| { let rlib_path = if let Some(dir) = path.parent() { let file_name = path.file_name().expect("rlib path has no file name path component"); - rehome_sysroot_lib_dir(sess, &dir).join(file_name) + rehome_sysroot_lib_dir(sess, dir).join(file_name) } else { fix_windows_verbatim_for_gcc(path) }; cmd.link_rlib(&rlib_path); }; - if !are_upstream_rust_objects_already_included(sess) - || ignored_for_lto(sess, &codegen_results.crate_info, cnum) - { + if !are_upstream_rust_objects_already_included(sess) { link_upstream(cratepath); return; } @@ -2787,8 +2765,6 @@ fn add_static_crate<'a>( let canonical_name = name.replace('-', "_"); let upstream_rust_objects_already_included = are_upstream_rust_objects_already_included(sess); - let is_builtins = - sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum); let mut archive = archive_builder_builder.new_archive_builder(sess); if let Err(error) = archive.add_archive( @@ -2801,13 +2777,12 @@ fn add_static_crate<'a>( let canonical = f.replace('-', "_"); let is_rust_object = - canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); + canonical.starts_with(&canonical_name) && looks_like_rust_object_file(f); // If we're performing LTO and this is a rust-generated object // file, then we don't need the object file as it's part of the - // LTO module. Note that `#![no_builtins]` is excluded from LTO, - // though, so we let that object file slide. - if upstream_rust_objects_already_included && is_rust_object && is_builtins { + // LTO module. + if upstream_rust_objects_already_included && is_rust_object { return true; } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 09434513e31e9..bb5f6e27e4d45 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -45,7 +45,7 @@ pub fn get_linker<'a>( self_contained: bool, target_cpu: &'a str, ) -> Box { - let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); + let msvc_tool = windows_registry::find_tool(sess.opts.target_triple.triple(), "link.exe"); // If our linker looks like a batch script on Windows then to execute this // we'll need to spawn `cmd` explicitly. This is primarily done to handle @@ -78,7 +78,7 @@ pub fn get_linker<'a>( if matches!(flavor, LinkerFlavor::Msvc(..)) && t.vendor == "uwp" { if let Some(ref tool) = msvc_tool { let original_path = tool.path(); - if let Some(ref root_lib_path) = original_path.ancestors().nth(4) { + if let Some(root_lib_path) = original_path.ancestors().nth(4) { let arch = match t.arch.as_ref() { "x86_64" => Some("x64"), "x86" => Some("x86"), @@ -185,6 +185,7 @@ pub trait Linker { fn optimize(&mut self); fn pgo_gen(&mut self); fn control_flow_guard(&mut self); + fn ehcont_guard(&mut self); fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]); fn no_crt_objects(&mut self); fn no_default_libraries(&mut self); @@ -195,6 +196,14 @@ pub trait Linker { fn add_no_exec(&mut self) {} fn add_as_needed(&mut self) {} fn reset_per_library_state(&mut self) {} + fn linker_arg(&mut self, arg: &OsStr, verbatim: bool) { + self.linker_args(&[arg], verbatim); + } + fn linker_args(&mut self, args: &[&OsStr], _verbatim: bool) { + args.into_iter().for_each(|a| { + self.cmd().arg(a); + }); + } } impl dyn Linker + '_ { @@ -222,38 +231,12 @@ pub struct GccLinker<'a> { } impl<'a> GccLinker<'a> { - /// Passes an argument directly to the linker. - /// - /// When the linker is not ld-like such as when using a compiler as a linker, the argument is - /// prepended by `-Wl,`. - fn linker_arg(&mut self, arg: impl AsRef) -> &mut Self { - self.linker_args(&[arg]); - self + fn linker_arg(&mut self, arg: impl AsRef) { + Linker::linker_arg(self, arg.as_ref(), false); } - - /// Passes a series of arguments directly to the linker. - /// - /// When the linker is ld-like, the arguments are simply appended to the command. When the - /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by - /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a - /// single argument is appended to the command to ensure that the order of the arguments is - /// preserved by the compiler. - fn linker_args(&mut self, args: &[impl AsRef]) -> &mut Self { - if self.is_ld { - args.into_iter().for_each(|a| { - self.cmd.arg(a); - }); - } else { - if !args.is_empty() { - let mut s = OsString::from("-Wl"); - for a in args { - s.push(","); - s.push(a); - } - self.cmd.arg(s); - } - } - self + fn linker_args(&mut self, args: &[impl AsRef]) { + let args_vec: Vec<&OsStr> = args.iter().map(|x| x.as_ref()).collect(); + Linker::linker_args(self, &args_vec, false); } fn takes_hints(&self) -> bool { @@ -360,6 +343,30 @@ impl<'a> GccLinker<'a> { } impl<'a> Linker for GccLinker<'a> { + /// Passes a series of arguments directly to the linker. + /// + /// When the linker is ld-like, the arguments are simply appended to the command. When the + /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by + /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a + /// single argument is appended to the command to ensure that the order of the arguments is + /// preserved by the compiler. + fn linker_args(&mut self, args: &[&OsStr], verbatim: bool) { + if self.is_ld || verbatim { + args.into_iter().for_each(|a| { + self.cmd.arg(a); + }); + } else { + if !args.is_empty() { + let mut s = OsString::from("-Wl"); + for a in args { + s.push(","); + s.push(a); + } + self.cmd.arg(s); + } + } + } + fn cmd(&mut self) -> &mut Command { &mut self.cmd } @@ -519,7 +526,7 @@ impl<'a> Linker for GccLinker<'a> { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = find_native_static_library(lib, verbatim, search_path, &self.sess); + let lib = find_native_static_library(lib, verbatim, search_path, self.sess); self.linker_arg(&lib); } } @@ -530,7 +537,7 @@ impl<'a> Linker for GccLinker<'a> { self.linker_arg("-force_load"); self.linker_arg(&lib); } else { - self.linker_arg("--whole-archive").cmd.arg(lib); + self.linker_args(&[OsString::from("--whole-archive"), lib.into()]); self.linker_arg("--no-whole-archive"); } } @@ -605,6 +612,8 @@ impl<'a> Linker for GccLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { // MacOS linker doesn't support stripping symbols directly anymore. if self.sess.target.is_like_osx { @@ -914,6 +923,12 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg("/guard:cf"); } + fn ehcont_guard(&mut self) { + if self.sess.target.pointer_width == 64 { + self.cmd.arg("/guard:ehcont"); + } + } + fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]) { match strip { Strip::None => { @@ -1127,6 +1142,8 @@ impl<'a> Linker for EmLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { // Preserve names or generate source maps depending on debug info // For more information see https://emscripten.org/docs/tools_reference/emcc.html#emcc-g @@ -1291,6 +1308,8 @@ impl<'a> Linker for WasmLd<'a> { } fn optimize(&mut self) { + // The -O flag is, as of late 2023, only used for merging of strings and debuginfo, and + // only differentiates -O0 and -O1. It does not apply to LTO. self.cmd.arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", @@ -1319,6 +1338,8 @@ impl<'a> Linker for WasmLd<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn no_crt_objects(&mut self) {} fn no_default_libraries(&mut self) {} @@ -1341,7 +1362,31 @@ impl<'a> Linker for WasmLd<'a> { fn subsystem(&mut self, _subsystem: &str) {} fn linker_plugin_lto(&mut self) { - // Do nothing for now + match self.sess.opts.cg.linker_plugin_lto { + LinkerPluginLto::Disabled => { + // Nothing to do + } + LinkerPluginLto::LinkerPluginAuto => { + self.push_linker_plugin_lto_args(); + } + LinkerPluginLto::LinkerPlugin(_) => { + self.push_linker_plugin_lto_args(); + } + } + } +} + +impl<'a> WasmLd<'a> { + fn push_linker_plugin_lto_args(&mut self) { + let opt_level = match self.sess.opts.optimize { + config::OptLevel::No => "O0", + config::OptLevel::Less => "O1", + config::OptLevel::Default => "O2", + config::OptLevel::Aggressive => "O3", + // wasm-ld only handles integer LTO opt levels. Use O2 + config::OptLevel::Size | config::OptLevel::SizeMin => "O2", + }; + self.cmd.arg(&format!("--lto-{opt_level}")); } } @@ -1472,6 +1517,8 @@ impl<'a> Linker for L4Bender<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn no_crt_objects(&mut self) {} } @@ -1590,7 +1637,7 @@ impl<'a> Linker for AixLinker<'a> { fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) { self.hint_static(); - let lib = find_native_static_library(lib, verbatim, search_path, &self.sess); + let lib = find_native_static_library(lib, verbatim, search_path, self.sess); self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); } @@ -1613,6 +1660,8 @@ impl<'a> Linker for AixLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { match strip { Strip::None => {} @@ -1835,6 +1884,8 @@ impl<'a> Linker for PtxLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {} fn subsystem(&mut self, _subsystem: &str) {} @@ -1931,6 +1982,8 @@ impl<'a> Linker for BpfLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { let path = tmpdir.join("symbols"); let res: io::Result<()> = try { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index cb60ed729c1bf..3e26e3653ea0c 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -12,9 +12,9 @@ use object::{ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; +use rustc_metadata::creader::MetadataLoader; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; -use rustc_session::cstore::MetadataLoader; use rustc_session::Session; use rustc_span::sym; use rustc_target::abi::Endian; @@ -226,6 +226,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option object::write::Mach build_version } +/// Is Apple's CPU subtype `arm64e`s +fn macho_is_arm64e(target: &Target) -> bool { + return target.llvm_target.starts_with("arm64e"); +} + pub enum MetadataPosition { First, Last, diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 9cd4394108a4a..f9ad8ca956329 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -54,8 +54,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap = tcx .reachable_set(()) @@ -105,8 +105,14 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap, _: LocalCrate) -> DefIdMap, _: LocalCrate) -> DefIdMap, _: LocalCrate) -> DefIdMap, cnum: CrateNum) -> FxHashMap( let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { - let source_file = in_incr_comp_dir(&incr_comp_session_dir, saved_path); + let source_file = in_incr_comp_dir(incr_comp_session_dir, saved_path); debug!( "copying preexisting module `{}` from {:?} to {}", module.name, @@ -914,7 +903,7 @@ fn execute_copy_from_cache_work_item( let object = load_from_incr_comp_dir( cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)), - &module.source.saved_files.get("o").expect("no saved object file in work product"), + module.source.saved_files.get("o").expect("no saved object file in work product"), ); let dwarf_object = module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| { @@ -924,7 +913,7 @@ fn execute_copy_from_cache_work_item( .expect( "saved dwarf object in work product but `split_dwarf_path` returned `None`", ); - load_from_incr_comp_dir(dwarf_obj_out, &saved_dwarf_object_file) + load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file) }); WorkItemResult::Finished(CompiledModule { @@ -1037,9 +1026,6 @@ fn start_executing_work( let mut each_linked_rlib_for_lto = Vec::new(); drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| { - if link::ignored_for_lto(sess, crate_info, cnum) { - return; - } each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); })); @@ -1870,7 +1856,7 @@ impl SharedEmitterMain { let mut err = match level { Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(), Level::Warning(_) => sess.struct_warn(msg), - Level::Note => sess.struct_note_without_error(msg), + Level::Note => sess.struct_note(msg), _ => bug!("Invalid inline asm diagnostic level"), }; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 198e5696357af..b87f4b6bf8907 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -148,10 +148,9 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( (&ty::Array(_, len), &ty::Slice(_)) => { cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all())) } - ( - &ty::Dynamic(ref data_a, _, src_dyn_kind), - &ty::Dynamic(ref data_b, _, target_dyn_kind), - ) if src_dyn_kind == target_dyn_kind => { + (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind)) + if src_dyn_kind == target_dyn_kind => + { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { @@ -322,8 +321,13 @@ pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( if lhs_sz < rhs_sz { bx.trunc(rhs, lhs_llty) } else if lhs_sz > rhs_sz { - // FIXME (#1877: If in the future shifting by negative - // values is no longer undefined then this is wrong. + // We zero-extend even if the RHS is signed. So e.g. `(x: i32) << -1i8` will zero-extend the + // RHS to `255i32`. But then we mask the shift amount to be within the size of the LHS + // anyway so the result is `31` as it should be. All the extra bits introduced by zext + // are masked off so their value does not matter. + // FIXME: if we ever support 512bit integers, this will be wrong! For such large integers, + // the extra bits introduced by zext are *not* all masked away any more. + assert!(lhs_sz <= 256); bx.zext(rhs, lhs_llty) } else { rhs @@ -453,8 +457,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx.set_frame_pointer_type(llfn); cx.apply_target_cpu_attr(llfn); - let llbb = Bx::append_block(&cx, llfn, "top"); - let mut bx = Bx::build(&cx, llbb); + let llbb = Bx::append_block(cx, llfn, "top"); + let mut bx = Bx::build(cx, llbb); bx.insert_reference_to_gdb_debug_scripts_section_global(); @@ -680,7 +684,7 @@ pub fn codegen_crate( // Calculate the CGU reuse let cgu_reuse = tcx.sess.time("find_cgu_reuse", || { - codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect::>() + codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, cgu)).collect::>() }); crate::assert_module_sources::assert_module_sources(tcx, &|cgu_reuse_tracker| { @@ -854,7 +858,6 @@ impl CrateInfo { local_crate_name, compiler_builtins, profiler_runtime: None, - is_no_builtins: Default::default(), native_libraries: Default::default(), used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(), crate_name: Default::default(), @@ -881,9 +884,6 @@ impl CrateInfo { if tcx.is_profiler_runtime(cnum) { info.profiler_runtime = Some(cnum); } - if tcx.is_no_builtins(cnum) { - info.is_no_builtins.insert(cnum); - } } // Handle circular dependencies in the standard library. @@ -891,9 +891,7 @@ impl CrateInfo { // If global LTO is enabled then almost everything (*) is glued into a single object file, // so this logic is not necessary and can cause issues on some targets (due to weak lang // item symbols being "privatized" to that object file), so we disable it. - // (*) Native libs, and `#[compiler_builtins]` and `#[no_builtins]` crates are not glued, - // and we assume that they cannot define weak lang items. This is not currently enforced - // by the compiler, but that's ok because all this stuff is unstable anyway. + // (*) Native libs are not glued, and we assume that they cannot define weak lang items. let target = &tcx.sess.target; if !are_upstream_rust_objects_already_included(tcx.sess) { let missing_weak_lang_items: FxHashSet = info diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 2e0840f2d1bc3..40a985cf255d5 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -57,7 +57,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { ); } - let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did)); + let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)); let mut codegen_fn_attrs = CodegenFnAttrs::new(); if tcx.should_inherit_track_caller(did) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; @@ -91,7 +91,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { Some(tcx.fn_sig(did)) } else { tcx.sess - .delay_span_bug(attr.span, "this attribute can only be applied to functions"); + .span_delayed_bug(attr.span, "this attribute can only be applied to functions"); None } }; @@ -477,9 +477,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { ) .emit(); InlineAttr::None - } else if list_contains_name(&items, sym::always) { + } else if list_contains_name(items, sym::always) { InlineAttr::Always - } else if list_contains_name(&items, sym::never) { + } else if list_contains_name(items, sym::never) { InlineAttr::Never } else { struct_span_err!( @@ -514,9 +514,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if items.len() != 1 { err(attr.span, "expected one argument"); OptimizeAttr::None - } else if list_contains_name(&items, sym::size) { + } else if list_contains_name(items, sym::size) { OptimizeAttr::Size - } else if list_contains_name(&items, sym::speed) { + } else if list_contains_name(items, sym::speed) { OptimizeAttr::Speed } else { err(items[0].span(), "invalid argument"); @@ -572,7 +572,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if !codegen_fn_attrs.no_sanitize.is_empty() { if codegen_fn_attrs.inline == InlineAttr::Always { if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) { - let hir_id = tcx.hir().local_def_id_to_hir_id(did); + let hir_id = tcx.local_def_id_to_hir_id(did); tcx.struct_span_lint_hir( lint::builtin::INLINE_NO_SANITIZE, hir_id, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 1a85eb8dd7970..8630e5623e168 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -216,7 +216,7 @@ fn push_debuginfo_type_name<'tcx>( output.push(']'); } } - ty::Dynamic(ref trait_data, ..) => { + ty::Dynamic(trait_data, ..) => { let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect(); let has_enclosing_parens = if cpp_like_debuginfo { @@ -249,7 +249,7 @@ fn push_debuginfo_type_name<'tcx>( .projection_bounds() .map(|bound| { let ExistentialProjection { def_id: item_def_id, term, .. } = - tcx.erase_late_bound_regions(bound); + tcx.instantiate_bound_regions_with_erased(bound); // FIXME(associated_const_equality): allow for consts here (item_def_id, term.ty().unwrap()) }) @@ -594,7 +594,7 @@ fn push_unqualified_item_name( DefPathData::CrateRoot => { output.push_str(tcx.crate_name(def_id.krate).as_str()); } - DefPathData::ClosureExpr => { + DefPathData::Closure => { let label = coroutine_kind_label(tcx.coroutine_kind(def_id)); push_disambiguated_special_name( diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 156c2904f4075..cd5eb77e06e8c 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,7 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(if_let_guard)] @@ -25,10 +25,8 @@ extern crate tracing; extern crate rustc_middle; use rustc_ast as ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_hir::def_id::CrateNum; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; @@ -60,7 +58,7 @@ pub mod mono_item; pub mod target_features; pub mod traits; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub struct ModuleCodegen { /// The name of the module. When the crate may be saved between @@ -159,7 +157,6 @@ pub struct CrateInfo { pub local_crate_name: Symbol, pub compiler_builtins: Option, pub profiler_runtime: Option, - pub is_no_builtins: FxHashSet, pub native_libraries: FxHashMap>, pub crate_name: FxHashMap, pub used_libraries: Vec, @@ -218,6 +215,7 @@ impl CodegenResults { sess: &Session, rlink_file: &Path, codegen_results: &CodegenResults, + outputs: &OutputFilenames, ) -> Result { let mut encoder = FileEncoder::new(rlink_file)?; encoder.emit_raw_bytes(RLINK_MAGIC); @@ -226,10 +224,14 @@ impl CodegenResults { encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()); encoder.emit_str(sess.cfg_version); Encodable::encode(codegen_results, &mut encoder); - encoder.finish() + Encodable::encode(outputs, &mut encoder); + encoder.finish().map_err(|(_path, err)| err) } - pub fn deserialize_rlink(sess: &Session, data: Vec) -> Result { + pub fn deserialize_rlink( + sess: &Session, + data: Vec, + ) -> Result<(Self, OutputFilenames), CodegenErrors> { // The Decodable machinery is not used here because it panics if the input data is invalid // and because its internal representation may change. if !data.starts_with(RLINK_MAGIC) { @@ -258,6 +260,7 @@ impl CodegenResults { } let codegen_results = CodegenResults::decode(&mut decoder); - Ok(codegen_results) + let outputs = OutputFilenames::decode(&mut decoder); + Ok((codegen_results, outputs)) } } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 53cc063e55a54..c1de9b76fe734 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -36,13 +36,13 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Arguments get assigned to by means of the function being called for arg in mir.args_iter() { - analyzer.assign(arg, DefLocation::Argument); + analyzer.define(arg, DefLocation::Argument); } // If there exists a local definition that dominates all uses of that local, // the definition should be visited first. Traverse blocks in an order that // is a topological sort of dominance partial order. - for (bb, data) in traversal::reverse_postorder(&mir) { + for (bb, data) in traversal::reverse_postorder(mir) { analyzer.visit_basic_block_data(bb, data); } @@ -74,7 +74,7 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { } impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { - fn assign(&mut self, local: mir::Local, location: DefLocation) { + fn define(&mut self, local: mir::Local, location: DefLocation) { let kind = &mut self.locals[local]; match *kind { LocalKind::ZST => {} @@ -162,7 +162,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue); if let Some(local) = place.as_local() { - self.assign(local, DefLocation::Body(location)); + self.define(local, DefLocation::Assignment(location)); if self.locals[local] != LocalKind::Memory { let decl_span = self.fx.mir.local_decls[local].source_info.span; if !self.fx.rvalue_creates_operand(rvalue, decl_span) { @@ -183,9 +183,14 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> fn visit_local(&mut self, local: mir::Local, context: PlaceContext, location: Location) { match context { - PlaceContext::MutatingUse(MutatingUseContext::Call) - | PlaceContext::MutatingUse(MutatingUseContext::Yield) => { - self.assign(local, DefLocation::Body(location)); + PlaceContext::MutatingUse(MutatingUseContext::Call) => { + let call = location.block; + let TerminatorKind::Call { target, .. } = + self.fx.mir.basic_blocks[call].terminator().kind + else { + bug!() + }; + self.define(local, DefLocation::CallReturn { call, target }); } PlaceContext::NonUse(_) @@ -197,7 +202,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> ) => match &mut self.locals[local] { LocalKind::ZST => {} LocalKind::Memory => {} - LocalKind::SSA(def) if def.dominates(location, &self.dominators) => {} + LocalKind::SSA(def) if def.dominates(location, self.dominators) => {} // Reads from uninitialized variables (e.g., in dead code, after // optimizations) require locals to be in (uninitialized) memory. // N.B., there can be uninitialized reads of a local visited after @@ -219,7 +224,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> | PlaceContext::NonMutatingUse( NonMutatingUseContext::Inspect | NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::AddressOf | NonMutatingUseContext::Projection, ) => { @@ -237,6 +242,8 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> } } } + + PlaceContext::MutatingUse(MutatingUseContext::Yield) => bug!(), } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 3d2d8f8b50990..a1662f25e1496 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { &self, fx: &'b mut FunctionCx<'a, 'tcx, Bx>, ) -> Option<&'b Bx::Funclet> { - let cleanup_kinds = (&fx.cleanup_kinds).as_ref()?; + let cleanup_kinds = fx.cleanup_kinds.as_ref()?; let funclet_bb = cleanup_kinds[self.bb].funclet_bb(self.bb)?; // If `landing_pad_for` hasn't been called yet to create the `Funclet`, // it has to be now. This may not seem necessary, as RPO should lead @@ -161,7 +161,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { ) -> MergingSucc { // If there is a cleanup block and the function we're calling can unwind, then // do an invoke, otherwise do a call. - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let fn_ty = bx.fn_decl_backend_type(fn_abi); let fn_attrs = if bx.tcx().def_kind(fx.instance.def_id()).has_codegen_attrs() { Some(bx.tcx().codegen_fn_attrs(fx.instance.def_id())) @@ -204,9 +204,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { let invokeret = bx.invoke( fn_ty, fn_attrs, - Some(&fn_abi), + Some(fn_abi), fn_ptr, - &llargs, + llargs, ret_llbb, unwind_block, self.funclet(fx), @@ -225,7 +225,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } MergingSucc::False } else { - let llret = bx.call(fn_ty, fn_attrs, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx)); + let llret = bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, llargs, self.funclet(fx)); if fx.mir[self.bb].is_cleanup { bx.apply_attrs_to_cleanup_callsite(llret); } @@ -273,7 +273,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { bx.codegen_inline_asm( template, - &operands, + operands, options, line_spans, instance, @@ -281,7 +281,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { ); MergingSucc::False } else { - bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None); + bx.codegen_inline_asm(template, operands, options, line_spans, instance, None); if let Some(target) = destination { self.funclet_br(fx, bx, target, mergeable_succ) @@ -318,7 +318,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { discr: &mir::Operand<'tcx>, targets: &SwitchTargets, ) { - let discr = self.codegen_operand(bx, &discr); + let discr = self.codegen_operand(bx, discr); let switch_ty = discr.layout.ty; let mut target_iter = targets.iter(); if target_iter.len() == 1 { @@ -498,7 +498,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args = &args[..1]; ( meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) - .get_fn(bx, vtable, ty, &fn_abi), + .get_fn(bx, vtable, ty, fn_abi), fn_abi, ) } @@ -540,7 +540,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { debug!("args' = {:?}", args); ( meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) - .get_fn(bx, meta.immediate(), ty, &fn_abi), + .get_fn(bx, meta.immediate(), ty, fn_abi), fn_abi, ) } @@ -864,7 +864,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // promotes any complex rvalues to constants. if i == 2 && intrinsic == sym::simd_shuffle { if let mir::Operand::Constant(constant) = arg { - let (llval, ty) = self.simd_shuffle_indices(&bx, constant); + let (llval, ty) = self.simd_shuffle_indices(bx, constant); return OperandRef { val: Immediate(llval), layout: bx.layout_of(ty), @@ -881,7 +881,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Self::codegen_intrinsic_call( bx, *instance.as_ref().unwrap(), - &fn_abi, + fn_abi, &args, dest, span, @@ -937,7 +937,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, meta, op.layout.ty, - &fn_abi, + fn_abi, )); llargs.push(data_ptr); continue 'make_args; @@ -948,7 +948,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, meta, op.layout.ty, - &fn_abi, + fn_abi, )); llargs.push(data_ptr); continue; @@ -975,7 +975,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, meta.immediate(), op.layout.ty, - &fn_abi, + fn_abi, )); llargs.push(data_ptr.llval); continue; @@ -1587,9 +1587,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item()); - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let fn_ty = bx.fn_decl_backend_type(fn_abi); - let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); + let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref()); bx.apply_attrs_to_cleanup_callsite(llret); bx.unreachable(); @@ -1662,10 +1662,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } else { - self.codegen_place( - bx, - mir::PlaceRef { local: dest.local, projection: &dest.projection }, - ) + self.codegen_place(bx, mir::PlaceRef { local: dest.local, projection: dest.projection }) }; if fn_ret.is_indirect() { if dest.align < dest.layout.align.abi { @@ -1696,7 +1693,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match dest { Nothing => (), - Store(dst) => bx.store_arg(&ret_abi, llval, dst), + Store(dst) => bx.store_arg(ret_abi, llval, dst), IndirectOperand(tmp, index) => { let op = bx.load_operand(tmp); tmp.storage_dead(bx); @@ -1708,7 +1705,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let op = if let PassMode::Cast { .. } = ret_abi.mode { let tmp = PlaceRef::alloca(bx, ret_abi.layout); tmp.storage_live(bx); - bx.store_arg(&ret_abi, llval, tmp); + bx.store_arg(ret_abi, llval, tmp); let op = bx.load_operand(tmp); tmp.storage_dead(bx); op diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 0dc30d21c5b40..14915e816ee9b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -398,7 +398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return }; let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } = - calculate_debuginfo_offset(bx, &var.projection, base.layout); + calculate_debuginfo_offset(bx, var.projection, base.layout); // When targeting MSVC, create extra allocas for arguments instead of pointing multiple // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records @@ -416,7 +416,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if should_create_individual_allocas { let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } = - calculate_debuginfo_offset(bx, &var.projection, base); + calculate_debuginfo_offset(bx, var.projection, base); // Create a variable which will be a pointer to the actual value let ptr_ty = Ty::new_ptr( diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index d0b799e087b2a..a6fcf1fd38c1f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -168,7 +168,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); - let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); + let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, mir); let start_llbb = Bx::append_block(cx, llfn, "start"); let mut start_bx = Bx::build(cx, start_llbb); @@ -180,7 +180,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } let cleanup_kinds = - base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir)); + base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(mir)); let cached_llbbs: IndexVec> = mir.basic_blocks @@ -261,7 +261,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( drop(start_bx); // Codegen the body of each block using reverse postorder - for (bb, _) in traversal::reverse_postorder(&mir) { + for (bb, _) in traversal::reverse_postorder(mir) { fx.codegen_block(bb); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 0ab2b7ecd9c80..d724f9503bb6c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -105,7 +105,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { bug!("from_const: invalid ScalarPair layout: {:#?}", layout); }; let a = Scalar::from_pointer( - Pointer::new(bx.tcx().reserve_and_set_memory_alloc(data), Size::ZERO), + Pointer::new(bx.tcx().reserve_and_set_memory_alloc(data).into(), Size::ZERO), &bx.tcx(), ); let a_llval = bx.scalar_to_backend( @@ -414,6 +414,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { // value is through `undef`/`poison`, and the store itself is useless. } OperandValue::Ref(r, None, source_align) => { + assert!(dest.layout.is_sized(), "cannot directly store unsized values"); if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. let ty = bx.backend_type(dest.layout); diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index eb590a45a63f2..83425dee1a8db 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -143,7 +143,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // Simple cases, which don't need DST adjustment: // * no metadata available - just log the case // * known alignment - sized types, `[T]`, `str` or a foreign type - // * packed struct - there is no alignment padding + // Note that looking at `field.align` is incorrect since that is not necessarily equal + // to the dynamic alignment of the type. match field.ty.kind() { _ if self.llextra.is_none() => { debug!( @@ -154,14 +155,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } _ if field.is_sized() => return simple(), ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(), - ty::Adt(def, _) => { - if def.repr().packed() { - // FIXME(eddyb) generalize the adjustment when we - // start supporting packing to larger alignments. - assert_eq!(self.layout.align.abi.bytes(), 1); - return simple(); - } - } _ => {} } @@ -186,7 +179,16 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { let unaligned_offset = bx.cx().const_usize(offset.bytes()); // Get the alignment of the field - let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta); + let (_, mut unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta); + + // For packed types, we need to cap alignment. + if let ty::Adt(def, _) = self.layout.ty.kind() + && let Some(packed) = def.repr().pack + { + let packed = bx.const_usize(packed.bytes()); + let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed); + unsized_align = bx.select(cmp, unsized_align, packed) + } // Bump the unaligned offset up to the appropriate alignment let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align); @@ -474,27 +476,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_base.project_index(bx, llindex) } mir::ProjectionElem::ConstantIndex { offset, from_end: false, min_length: _ } => { - let lloffset = bx.cx().const_usize(offset as u64); + let lloffset = bx.cx().const_usize(offset); cg_base.project_index(bx, lloffset) } mir::ProjectionElem::ConstantIndex { offset, from_end: true, min_length: _ } => { - let lloffset = bx.cx().const_usize(offset as u64); + let lloffset = bx.cx().const_usize(offset); let lllen = cg_base.len(bx.cx()); let llindex = bx.sub(lllen, lloffset); cg_base.project_index(bx, llindex) } mir::ProjectionElem::Subslice { from, to, from_end } => { - let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from as u64)); + let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from)); let projected_ty = PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx, *elem).ty; subslice.layout = bx.cx().layout_of(self.monomorphize(projected_ty)); if subslice.layout.is_unsized() { assert!(from_end, "slice subslices should be `from_end`"); - subslice.llextra = Some(bx.sub( - cg_base.llextra.unwrap(), - bx.cx().const_usize((from as u64) + (to as u64)), - )); + subslice.llextra = + Some(bx.sub(cg_base.llextra.unwrap(), bx.cx().const_usize(from + to))); } subslice diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 8e5019967a460..02b51dfe5bf7f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -702,7 +702,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let fn_ptr = bx.get_fn_addr(instance); let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let fn_ty = bx.fn_decl_backend_type(fn_abi); let fn_attrs = if bx.tcx().def_kind(instance.def_id()).has_codegen_attrs() { Some(bx.tcx().codegen_fn_attrs(instance.def_id())) } else { diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 6fbf992eda9ec..295e27691090c 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -34,7 +34,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } MonoItem::GlobalAsm(item_id) => { let item = cx.tcx().hir().item(item_id); - if let hir::ItemKind::GlobalAsm(ref asm) = item.kind { + if let hir::ItemKind::GlobalAsm(asm) = item.kind { let operands: Vec<_> = asm .operands .iter() @@ -88,7 +88,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } } MonoItem::Fn(instance) => { - base::codegen_instance::(&cx, instance); + base::codegen_instance::(cx, instance); } } @@ -119,10 +119,10 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { match *self { MonoItem::Static(def_id) => { - cx.predefine_static(def_id, linkage, visibility, &symbol_name); + cx.predefine_static(def_id, linkage, visibility, symbol_name); } MonoItem::Fn(instance) => { - cx.predefine_fn(instance, linkage, visibility, &symbol_name); + cx.predefine_fn(instance, linkage, visibility, symbol_name); } MonoItem::GlobalAsm(..) => {} } diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 9c053338c8537..d802816bb7561 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -19,141 +19,183 @@ use rustc_span::Span; /// Features that control behaviour of rustc, rather than the codegen. pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; +/// Stability information for target features. +#[derive(Debug, Clone, Copy)] +pub enum Stability { + /// This target feature is stable, it can be used in `#[target_feature]` and + /// `#[cfg(target_feature)]`. + Stable, + /// This target feature is unstable; using it in `#[target_feature]` or `#[cfg(target_feature)]` + /// requires enabling the given nightly feature. + Unstable(Symbol), +} +use Stability::*; + +impl Stability { + fn as_feature_name(self) -> Option { + match self { + Stable => None, + Unstable(s) => Some(s), + } + } + + pub fn is_stable(self) -> bool { + matches!(self, Stable) + } +} + +// Here we list target features that rustc "understands": they can be used in `#[target_feature]` +// and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with +// `-Ctarget-feature`. +// // When adding features to the below lists // check whether they're named already elsewhere in rust // e.g. in stdarch and whether the given name matches LLVM's -// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted +// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted. +// +// Also note that all target features listed here must be purely additive: for target_feature 1.1 to +// be sound, we can never allow features like `+soft-float` (on x86) to be controlled on a +// per-function level, since we would then allow safe calls from functions with `+soft-float` to +// functions without that feature! +// +// When adding a new feature, be particularly mindful of features that affect function ABIs. Those +// need to be treated very carefully to avoid introducing unsoundness! This often affects features +// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an +// example of this going wrong), but features enabling new SIMD registers are also a concern (see +// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong). +// +// Stabilizing a target feature requires t-lang approval. -const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const ARM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("aclass", Some(sym::arm_target_feature)), - ("aes", Some(sym::arm_target_feature)), - ("crc", Some(sym::arm_target_feature)), - ("d32", Some(sym::arm_target_feature)), - ("dotprod", Some(sym::arm_target_feature)), - ("dsp", Some(sym::arm_target_feature)), - ("fp-armv8", Some(sym::arm_target_feature)), - ("i8mm", Some(sym::arm_target_feature)), - ("mclass", Some(sym::arm_target_feature)), - ("neon", Some(sym::arm_target_feature)), - ("rclass", Some(sym::arm_target_feature)), - ("sha2", Some(sym::arm_target_feature)), + ("aclass", Unstable(sym::arm_target_feature)), + ("aes", Unstable(sym::arm_target_feature)), + ("crc", Unstable(sym::arm_target_feature)), + ("d32", Unstable(sym::arm_target_feature)), + ("dotprod", Unstable(sym::arm_target_feature)), + ("dsp", Unstable(sym::arm_target_feature)), + ("fp-armv8", Unstable(sym::arm_target_feature)), + ("i8mm", Unstable(sym::arm_target_feature)), + ("mclass", Unstable(sym::arm_target_feature)), + ("neon", Unstable(sym::arm_target_feature)), + ("rclass", Unstable(sym::arm_target_feature)), + ("sha2", Unstable(sym::arm_target_feature)), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. - ("thumb-mode", Some(sym::arm_target_feature)), - ("thumb2", Some(sym::arm_target_feature)), - ("trustzone", Some(sym::arm_target_feature)), - ("v5te", Some(sym::arm_target_feature)), - ("v6", Some(sym::arm_target_feature)), - ("v6k", Some(sym::arm_target_feature)), - ("v6t2", Some(sym::arm_target_feature)), - ("v7", Some(sym::arm_target_feature)), - ("v8", Some(sym::arm_target_feature)), - ("vfp2", Some(sym::arm_target_feature)), - ("vfp3", Some(sym::arm_target_feature)), - ("vfp4", Some(sym::arm_target_feature)), - ("virtualization", Some(sym::arm_target_feature)), + ("thumb-mode", Unstable(sym::arm_target_feature)), + ("thumb2", Unstable(sym::arm_target_feature)), + ("trustzone", Unstable(sym::arm_target_feature)), + ("v5te", Unstable(sym::arm_target_feature)), + ("v6", Unstable(sym::arm_target_feature)), + ("v6k", Unstable(sym::arm_target_feature)), + ("v6t2", Unstable(sym::arm_target_feature)), + ("v7", Unstable(sym::arm_target_feature)), + ("v8", Unstable(sym::arm_target_feature)), + ("vfp2", Unstable(sym::arm_target_feature)), + ("vfp3", Unstable(sym::arm_target_feature)), + ("vfp4", Unstable(sym::arm_target_feature)), + ("virtualization", Unstable(sym::arm_target_feature)), // tidy-alphabetical-end ]; -const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start // FEAT_AES - ("aes", None), + ("aes", Stable), // FEAT_BF16 - ("bf16", None), + ("bf16", Stable), // FEAT_BTI - ("bti", None), + ("bti", Stable), // FEAT_CRC - ("crc", None), + ("crc", Stable), // FEAT_DIT - ("dit", None), + ("dit", Stable), // FEAT_DotProd - ("dotprod", None), + ("dotprod", Stable), // FEAT_DPB - ("dpb", None), + ("dpb", Stable), // FEAT_DPB2 - ("dpb2", None), + ("dpb2", Stable), // FEAT_F32MM - ("f32mm", None), + ("f32mm", Stable), // FEAT_F64MM - ("f64mm", None), + ("f64mm", Stable), // FEAT_FCMA - ("fcma", None), + ("fcma", Stable), // FEAT_FHM - ("fhm", None), + ("fhm", Stable), // FEAT_FLAGM - ("flagm", None), + ("flagm", Stable), // FEAT_FP16 - ("fp16", None), + ("fp16", Stable), // FEAT_FRINTTS - ("frintts", None), + ("frintts", Stable), // FEAT_I8MM - ("i8mm", None), + ("i8mm", Stable), // FEAT_JSCVT - ("jsconv", None), + ("jsconv", Stable), // FEAT_LOR - ("lor", None), + ("lor", Stable), // FEAT_LSE - ("lse", None), + ("lse", Stable), // FEAT_MTE - ("mte", None), + ("mte", Stable), // FEAT_AdvSimd & FEAT_FP - ("neon", None), + ("neon", Stable), // FEAT_PAUTH (address authentication) - ("paca", None), + ("paca", Stable), // FEAT_PAUTH (generic authentication) - ("pacg", None), + ("pacg", Stable), // FEAT_PAN - ("pan", None), + ("pan", Stable), // FEAT_PMUv3 - ("pmuv3", None), + ("pmuv3", Stable), // FEAT_RAND - ("rand", None), + ("rand", Stable), // FEAT_RAS - ("ras", None), + ("ras", Stable), // FEAT_RCPC - ("rcpc", None), + ("rcpc", Stable), // FEAT_RCPC2 - ("rcpc2", None), + ("rcpc2", Stable), // FEAT_RDM - ("rdm", None), + ("rdm", Stable), // FEAT_SB - ("sb", None), + ("sb", Stable), // FEAT_SHA1 & FEAT_SHA256 - ("sha2", None), + ("sha2", Stable), // FEAT_SHA512 & FEAT_SHA3 - ("sha3", None), + ("sha3", Stable), // FEAT_SM3 & FEAT_SM4 - ("sm4", None), + ("sm4", Stable), // FEAT_SPE - ("spe", None), + ("spe", Stable), // FEAT_SSBS - ("ssbs", None), + ("ssbs", Stable), // FEAT_SVE - ("sve", None), + ("sve", Stable), // FEAT_SVE2 - ("sve2", None), + ("sve2", Stable), // FEAT_SVE2_AES - ("sve2-aes", None), + ("sve2-aes", Stable), // FEAT_SVE2_BitPerm - ("sve2-bitperm", None), + ("sve2-bitperm", Stable), // FEAT_SVE2_SHA3 - ("sve2-sha3", None), + ("sve2-sha3", Stable), // FEAT_SVE2_SM4 - ("sve2-sm4", None), + ("sve2-sm4", Stable), // FEAT_TME - ("tme", None), - ("v8.1a", Some(sym::aarch64_ver_target_feature)), - ("v8.2a", Some(sym::aarch64_ver_target_feature)), - ("v8.3a", Some(sym::aarch64_ver_target_feature)), - ("v8.4a", Some(sym::aarch64_ver_target_feature)), - ("v8.5a", Some(sym::aarch64_ver_target_feature)), - ("v8.6a", Some(sym::aarch64_ver_target_feature)), - ("v8.7a", Some(sym::aarch64_ver_target_feature)), + ("tme", Stable), + ("v8.1a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.2a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.3a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.4a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.5a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.6a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.7a", Unstable(sym::aarch64_ver_target_feature)), // FEAT_VHE - ("vh", None), + ("vh", Stable), // tidy-alphabetical-end ]; @@ -161,197 +203,197 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[ &["paca", "pacg"], // Together these represent `pauth` in LLVM ]; -const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("adx", None), - ("aes", None), - ("avx", None), - ("avx2", None), - ("avx512bf16", Some(sym::avx512_target_feature)), - ("avx512bitalg", Some(sym::avx512_target_feature)), - ("avx512bw", Some(sym::avx512_target_feature)), - ("avx512cd", Some(sym::avx512_target_feature)), - ("avx512dq", Some(sym::avx512_target_feature)), - ("avx512er", Some(sym::avx512_target_feature)), - ("avx512f", Some(sym::avx512_target_feature)), - ("avx512ifma", Some(sym::avx512_target_feature)), - ("avx512pf", Some(sym::avx512_target_feature)), - ("avx512vbmi", Some(sym::avx512_target_feature)), - ("avx512vbmi2", Some(sym::avx512_target_feature)), - ("avx512vl", Some(sym::avx512_target_feature)), - ("avx512vnni", Some(sym::avx512_target_feature)), - ("avx512vp2intersect", Some(sym::avx512_target_feature)), - ("avx512vpopcntdq", Some(sym::avx512_target_feature)), - ("bmi1", None), - ("bmi2", None), - ("cmpxchg16b", None), - ("ermsb", Some(sym::ermsb_target_feature)), - ("f16c", None), - ("fma", None), - ("fxsr", None), - ("gfni", Some(sym::avx512_target_feature)), - ("lzcnt", None), - ("movbe", None), - ("pclmulqdq", None), - ("popcnt", None), - ("rdrand", None), - ("rdseed", None), - ("rtm", Some(sym::rtm_target_feature)), - ("sha", None), - ("sse", None), - ("sse2", None), - ("sse3", None), - ("sse4.1", None), - ("sse4.2", None), - ("sse4a", Some(sym::sse4a_target_feature)), - ("ssse3", None), - ("tbm", Some(sym::tbm_target_feature)), - ("vaes", Some(sym::avx512_target_feature)), - ("vpclmulqdq", Some(sym::avx512_target_feature)), - ("xsave", None), - ("xsavec", None), - ("xsaveopt", None), - ("xsaves", None), + ("adx", Stable), + ("aes", Stable), + ("avx", Stable), + ("avx2", Stable), + ("avx512bf16", Unstable(sym::avx512_target_feature)), + ("avx512bitalg", Unstable(sym::avx512_target_feature)), + ("avx512bw", Unstable(sym::avx512_target_feature)), + ("avx512cd", Unstable(sym::avx512_target_feature)), + ("avx512dq", Unstable(sym::avx512_target_feature)), + ("avx512er", Unstable(sym::avx512_target_feature)), + ("avx512f", Unstable(sym::avx512_target_feature)), + ("avx512ifma", Unstable(sym::avx512_target_feature)), + ("avx512pf", Unstable(sym::avx512_target_feature)), + ("avx512vbmi", Unstable(sym::avx512_target_feature)), + ("avx512vbmi2", Unstable(sym::avx512_target_feature)), + ("avx512vl", Unstable(sym::avx512_target_feature)), + ("avx512vnni", Unstable(sym::avx512_target_feature)), + ("avx512vp2intersect", Unstable(sym::avx512_target_feature)), + ("avx512vpopcntdq", Unstable(sym::avx512_target_feature)), + ("bmi1", Stable), + ("bmi2", Stable), + ("cmpxchg16b", Stable), + ("ermsb", Unstable(sym::ermsb_target_feature)), + ("f16c", Stable), + ("fma", Stable), + ("fxsr", Stable), + ("gfni", Unstable(sym::avx512_target_feature)), + ("lzcnt", Stable), + ("movbe", Stable), + ("pclmulqdq", Stable), + ("popcnt", Stable), + ("rdrand", Stable), + ("rdseed", Stable), + ("rtm", Unstable(sym::rtm_target_feature)), + ("sha", Stable), + ("sse", Stable), + ("sse2", Stable), + ("sse3", Stable), + ("sse4.1", Stable), + ("sse4.2", Stable), + ("sse4a", Unstable(sym::sse4a_target_feature)), + ("ssse3", Stable), + ("tbm", Unstable(sym::tbm_target_feature)), + ("vaes", Unstable(sym::avx512_target_feature)), + ("vpclmulqdq", Unstable(sym::avx512_target_feature)), + ("xsave", Stable), + ("xsavec", Stable), + ("xsaveopt", Stable), + ("xsaves", Stable), // tidy-alphabetical-end ]; -const HEXAGON_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("hvx", Some(sym::hexagon_target_feature)), - ("hvx-length128b", Some(sym::hexagon_target_feature)), + ("hvx", Unstable(sym::hexagon_target_feature)), + ("hvx-length128b", Unstable(sym::hexagon_target_feature)), // tidy-alphabetical-end ]; -const POWERPC_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const POWERPC_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("altivec", Some(sym::powerpc_target_feature)), - ("power10-vector", Some(sym::powerpc_target_feature)), - ("power8-altivec", Some(sym::powerpc_target_feature)), - ("power8-vector", Some(sym::powerpc_target_feature)), - ("power9-altivec", Some(sym::powerpc_target_feature)), - ("power9-vector", Some(sym::powerpc_target_feature)), - ("vsx", Some(sym::powerpc_target_feature)), + ("altivec", Unstable(sym::powerpc_target_feature)), + ("power10-vector", Unstable(sym::powerpc_target_feature)), + ("power8-altivec", Unstable(sym::powerpc_target_feature)), + ("power8-vector", Unstable(sym::powerpc_target_feature)), + ("power9-altivec", Unstable(sym::powerpc_target_feature)), + ("power9-vector", Unstable(sym::powerpc_target_feature)), + ("vsx", Unstable(sym::powerpc_target_feature)), // tidy-alphabetical-end ]; -const MIPS_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const MIPS_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("fp64", Some(sym::mips_target_feature)), - ("msa", Some(sym::mips_target_feature)), - ("virt", Some(sym::mips_target_feature)), + ("fp64", Unstable(sym::mips_target_feature)), + ("msa", Unstable(sym::mips_target_feature)), + ("virt", Unstable(sym::mips_target_feature)), // tidy-alphabetical-end ]; -const RISCV_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const RISCV_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("a", None), - ("c", None), - ("d", Some(sym::riscv_target_feature)), - ("e", Some(sym::riscv_target_feature)), - ("f", Some(sym::riscv_target_feature)), - ("m", None), - ("relax", Some(sym::riscv_target_feature)), - ("unaligned-scalar-mem", Some(sym::riscv_target_feature)), - ("v", Some(sym::riscv_target_feature)), - ("zba", None), - ("zbb", None), - ("zbc", None), - ("zbkb", None), - ("zbkc", None), - ("zbkx", None), - ("zbs", None), - ("zdinx", Some(sym::riscv_target_feature)), - ("zfh", Some(sym::riscv_target_feature)), - ("zfhmin", Some(sym::riscv_target_feature)), - ("zfinx", Some(sym::riscv_target_feature)), - ("zhinx", Some(sym::riscv_target_feature)), - ("zhinxmin", Some(sym::riscv_target_feature)), - ("zk", None), - ("zkn", None), - ("zknd", None), - ("zkne", None), - ("zknh", None), - ("zkr", None), - ("zks", None), - ("zksed", None), - ("zksh", None), - ("zkt", None), + ("a", Stable), + ("c", Stable), + ("d", Unstable(sym::riscv_target_feature)), + ("e", Unstable(sym::riscv_target_feature)), + ("f", Unstable(sym::riscv_target_feature)), + ("m", Stable), + ("relax", Unstable(sym::riscv_target_feature)), + ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature)), + ("v", Unstable(sym::riscv_target_feature)), + ("zba", Stable), + ("zbb", Stable), + ("zbc", Stable), + ("zbkb", Stable), + ("zbkc", Stable), + ("zbkx", Stable), + ("zbs", Stable), + ("zdinx", Unstable(sym::riscv_target_feature)), + ("zfh", Unstable(sym::riscv_target_feature)), + ("zfhmin", Unstable(sym::riscv_target_feature)), + ("zfinx", Unstable(sym::riscv_target_feature)), + ("zhinx", Unstable(sym::riscv_target_feature)), + ("zhinxmin", Unstable(sym::riscv_target_feature)), + ("zk", Stable), + ("zkn", Stable), + ("zknd", Stable), + ("zkne", Stable), + ("zknh", Stable), + ("zkr", Stable), + ("zks", Stable), + ("zksed", Stable), + ("zksh", Stable), + ("zkt", Stable), // tidy-alphabetical-end ]; -const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("atomics", Some(sym::wasm_target_feature)), - ("bulk-memory", Some(sym::wasm_target_feature)), - ("exception-handling", Some(sym::wasm_target_feature)), - ("multivalue", Some(sym::wasm_target_feature)), - ("mutable-globals", Some(sym::wasm_target_feature)), - ("nontrapping-fptoint", Some(sym::wasm_target_feature)), - ("reference-types", Some(sym::wasm_target_feature)), - ("relaxed-simd", Some(sym::wasm_target_feature)), - ("sign-ext", Some(sym::wasm_target_feature)), - ("simd128", None), + ("atomics", Unstable(sym::wasm_target_feature)), + ("bulk-memory", Unstable(sym::wasm_target_feature)), + ("exception-handling", Unstable(sym::wasm_target_feature)), + ("multivalue", Unstable(sym::wasm_target_feature)), + ("mutable-globals", Unstable(sym::wasm_target_feature)), + ("nontrapping-fptoint", Unstable(sym::wasm_target_feature)), + ("reference-types", Unstable(sym::wasm_target_feature)), + ("relaxed-simd", Unstable(sym::wasm_target_feature)), + ("sign-ext", Unstable(sym::wasm_target_feature)), + ("simd128", Stable), // tidy-alphabetical-end ]; -const BPF_ALLOWED_FEATURES: &[(&str, Option)] = &[("alu32", Some(sym::bpf_target_feature))]; +const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))]; -const CSKY_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("10e60", Some(sym::csky_target_feature)), - ("2e3", Some(sym::csky_target_feature)), - ("3e3r1", Some(sym::csky_target_feature)), - ("3e3r2", Some(sym::csky_target_feature)), - ("3e3r3", Some(sym::csky_target_feature)), - ("3e7", Some(sym::csky_target_feature)), - ("7e10", Some(sym::csky_target_feature)), - ("cache", Some(sym::csky_target_feature)), - ("doloop", Some(sym::csky_target_feature)), - ("dsp1e2", Some(sym::csky_target_feature)), - ("dspe60", Some(sym::csky_target_feature)), - ("e1", Some(sym::csky_target_feature)), - ("e2", Some(sym::csky_target_feature)), - ("edsp", Some(sym::csky_target_feature)), - ("elrw", Some(sym::csky_target_feature)), - ("float1e2", Some(sym::csky_target_feature)), - ("float1e3", Some(sym::csky_target_feature)), - ("float3e4", Some(sym::csky_target_feature)), - ("float7e60", Some(sym::csky_target_feature)), - ("floate1", Some(sym::csky_target_feature)), - ("hard-tp", Some(sym::csky_target_feature)), - ("high-registers", Some(sym::csky_target_feature)), - ("hwdiv", Some(sym::csky_target_feature)), - ("mp", Some(sym::csky_target_feature)), - ("mp1e2", Some(sym::csky_target_feature)), - ("nvic", Some(sym::csky_target_feature)), - ("trust", Some(sym::csky_target_feature)), - ("vdsp2e60f", Some(sym::csky_target_feature)), - ("vdspv1", Some(sym::csky_target_feature)), - ("vdspv2", Some(sym::csky_target_feature)), + ("10e60", Unstable(sym::csky_target_feature)), + ("2e3", Unstable(sym::csky_target_feature)), + ("3e3r1", Unstable(sym::csky_target_feature)), + ("3e3r2", Unstable(sym::csky_target_feature)), + ("3e3r3", Unstable(sym::csky_target_feature)), + ("3e7", Unstable(sym::csky_target_feature)), + ("7e10", Unstable(sym::csky_target_feature)), + ("cache", Unstable(sym::csky_target_feature)), + ("doloop", Unstable(sym::csky_target_feature)), + ("dsp1e2", Unstable(sym::csky_target_feature)), + ("dspe60", Unstable(sym::csky_target_feature)), + ("e1", Unstable(sym::csky_target_feature)), + ("e2", Unstable(sym::csky_target_feature)), + ("edsp", Unstable(sym::csky_target_feature)), + ("elrw", Unstable(sym::csky_target_feature)), + ("float1e2", Unstable(sym::csky_target_feature)), + ("float1e3", Unstable(sym::csky_target_feature)), + ("float3e4", Unstable(sym::csky_target_feature)), + ("float7e60", Unstable(sym::csky_target_feature)), + ("floate1", Unstable(sym::csky_target_feature)), + ("hard-tp", Unstable(sym::csky_target_feature)), + ("high-registers", Unstable(sym::csky_target_feature)), + ("hwdiv", Unstable(sym::csky_target_feature)), + ("mp", Unstable(sym::csky_target_feature)), + ("mp1e2", Unstable(sym::csky_target_feature)), + ("nvic", Unstable(sym::csky_target_feature)), + ("trust", Unstable(sym::csky_target_feature)), + ("vdsp2e60f", Unstable(sym::csky_target_feature)), + ("vdspv1", Unstable(sym::csky_target_feature)), + ("vdspv2", Unstable(sym::csky_target_feature)), // tidy-alphabetical-end //fpu // tidy-alphabetical-start - ("fdivdu", Some(sym::csky_target_feature)), - ("fpuv2_df", Some(sym::csky_target_feature)), - ("fpuv2_sf", Some(sym::csky_target_feature)), - ("fpuv3_df", Some(sym::csky_target_feature)), - ("fpuv3_hf", Some(sym::csky_target_feature)), - ("fpuv3_hi", Some(sym::csky_target_feature)), - ("fpuv3_sf", Some(sym::csky_target_feature)), - ("hard-float", Some(sym::csky_target_feature)), - ("hard-float-abi", Some(sym::csky_target_feature)), + ("fdivdu", Unstable(sym::csky_target_feature)), + ("fpuv2_df", Unstable(sym::csky_target_feature)), + ("fpuv2_sf", Unstable(sym::csky_target_feature)), + ("fpuv3_df", Unstable(sym::csky_target_feature)), + ("fpuv3_hf", Unstable(sym::csky_target_feature)), + ("fpuv3_hi", Unstable(sym::csky_target_feature)), + ("fpuv3_sf", Unstable(sym::csky_target_feature)), + ("hard-float", Unstable(sym::csky_target_feature)), + ("hard-float-abi", Unstable(sym::csky_target_feature)), // tidy-alphabetical-end ]; -const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("d", Some(sym::loongarch_target_feature)), - ("f", Some(sym::loongarch_target_feature)), - ("lasx", Some(sym::loongarch_target_feature)), - ("lbt", Some(sym::loongarch_target_feature)), - ("lsx", Some(sym::loongarch_target_feature)), - ("lvz", Some(sym::loongarch_target_feature)), - ("ual", Some(sym::loongarch_target_feature)), + ("d", Unstable(sym::loongarch_target_feature)), + ("f", Unstable(sym::loongarch_target_feature)), + ("lasx", Unstable(sym::loongarch_target_feature)), + ("lbt", Unstable(sym::loongarch_target_feature)), + ("lsx", Unstable(sym::loongarch_target_feature)), + ("lvz", Unstable(sym::loongarch_target_feature)), + ("ual", Unstable(sym::loongarch_target_feature)), // tidy-alphabetical-end ]; @@ -359,7 +401,7 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option)] = &[ /// primitives may be documented. /// /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! -pub fn all_known_features() -> impl Iterator)> { +pub fn all_known_features() -> impl Iterator { std::iter::empty() .chain(ARM_ALLOWED_FEATURES.iter()) .chain(AARCH64_ALLOWED_FEATURES.iter()) @@ -375,7 +417,7 @@ pub fn all_known_features() -> impl Iterator &'static [(&'static str, Option)] { +pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Stability)] { match &*sess.target.arch { "arm" => ARM_ALLOWED_FEATURES, "aarch64" => AARCH64_ALLOWED_FEATURES, @@ -520,11 +562,11 @@ pub(crate) fn provide(providers: &mut Providers) { if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all - all_known_features().map(|(a, b)| (a.to_string(), b)).collect() + all_known_features().map(|(a, b)| (a.to_string(), b.as_feature_name())).collect() } else { supported_target_features(tcx.sess) .iter() - .map(|&(a, b)| (a.to_string(), b)) + .map(|&(a, b)| (a.to_string(), b.as_feature_name())) .collect() } }, diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index ac8123bc1be91..8e9907ed8bb03 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -9,6 +9,7 @@ use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_errors::ErrorGuaranteed; +use rustc_metadata::creader::MetadataLoaderDyn; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; @@ -16,7 +17,6 @@ use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::{ config::{self, OutputFilenames, PrintRequest}, - cstore::MetadataLoaderDyn, Session, }; use rustc_span::symbol::Symbol; @@ -104,11 +104,7 @@ pub trait CodegenBackend { outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed>; - /// This is called on the returned `Box` from `join_codegen` - /// - /// # Panics - /// - /// Panics when the passed `Box` was not returned by `join_codegen`. + /// This is called on the returned `CodegenResults` from `join_codegen` fn link( &self, sess: &Session, diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index f926da464e1c6..4a426ed16e541 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -461,6 +461,9 @@ const_eval_validation_uninhabited_val = {$front_matter}: encountered a value of const_eval_validation_uninit = {$front_matter}: encountered uninitialized memory, but {$expected} const_eval_validation_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in a `const` +const_eval_write_through_immutable_pointer = + writing through a pointer that was derived from a shared (immutable) reference + const_eval_write_to_read_only = writing to {$allocation} which is read-only const_eval_zst_pointer_out_of_bounds = diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index bf1e0a370734d..26cf3b3f2b0ed 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -1,14 +1,16 @@ use std::mem; use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg}; +use rustc_hir::CRATE_HIR_ID; use rustc_middle::mir::AssertKind; +use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::{layout::LayoutError, ConstInt}; use rustc_span::{ErrorGuaranteed, Span, Symbol, DUMMY_SP}; -use super::InterpCx; +use super::{CompileTimeInterpreter, InterpCx}; use crate::errors::{self, FrameNote, ReportErrorExt}; -use crate::interpret::{ErrorHandled, InterpError, InterpErrorInfo, Machine, MachineStopType}; +use crate::interpret::{ErrorHandled, InterpError, InterpErrorInfo, MachineStopType}; /// The CTFE machine has some custom error kinds. #[derive(Clone, Debug)] @@ -57,16 +59,20 @@ impl<'tcx> Into> for ConstEvalErrKind { } } -pub fn get_span_and_frames<'tcx, 'mir, M: Machine<'mir, 'tcx>>( - ecx: &InterpCx<'mir, 'tcx, M>, +pub fn get_span_and_frames<'tcx, 'mir>( + tcx: TyCtxtAt<'tcx>, + machine: &CompileTimeInterpreter<'mir, 'tcx>, ) -> (Span, Vec) where 'tcx: 'mir, { - let mut stacktrace = ecx.generate_stacktrace(); + let mut stacktrace = + InterpCx::>::generate_stacktrace_from_stack( + &machine.stack, + ); // Filter out `requires_caller_location` frames. - stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*ecx.tcx)); - let span = stacktrace.first().map(|f| f.span).unwrap_or(ecx.tcx.span); + stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*tcx)); + let span = stacktrace.first().map(|f| f.span).unwrap_or(tcx.span); let mut frames = Vec::new(); @@ -87,7 +93,7 @@ where let mut last_frame: Option = None; for frame_info in &stacktrace { - let frame = frame_info.as_note(*ecx.tcx); + let frame = frame_info.as_note(*tcx); match last_frame.as_mut() { Some(last_frame) if last_frame.span == frame.span @@ -148,7 +154,7 @@ where let mut err = tcx.sess.create_err(err); let msg = error.diagnostic_message(); - error.add_args(&tcx.sess.parse_sess.span_diagnostic, &mut err); + error.add_args(tcx.sess.diagnostic(), &mut err); // Use *our* span to label the interp error err.span_label(our_span, msg); @@ -156,3 +162,25 @@ where } } } + +/// Emit a lint from a const-eval situation. +// Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future! +pub(super) fn lint<'tcx, 'mir, L>( + tcx: TyCtxtAt<'tcx>, + machine: &CompileTimeInterpreter<'mir, 'tcx>, + lint: &'static rustc_session::lint::Lint, + decorator: impl FnOnce(Vec) -> L, +) where + L: for<'a> rustc_errors::DecorateLint<'a, ()>, +{ + let (span, frames) = get_span_and_frames(tcx, machine); + + tcx.emit_spanned_lint( + lint, + // We use the root frame for this so the crate that defines the const defines whether the + // lint is emitted. + machine.stack.first().and_then(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID), + span, + decorator(frames), + ); +} diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 13937a94198d0..9d22df50d4f34 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -155,8 +155,8 @@ pub(super) fn op_to_const<'tcx>( match immediate { Left(ref mplace) => { // We know `offset` is relative to the allocation, so we can use `into_parts`. - let (alloc_id, offset) = mplace.ptr().into_parts(); - let alloc_id = alloc_id.expect("cannot have `fake` place fot non-ZST type"); + let (prov, offset) = mplace.ptr().into_parts(); + let alloc_id = prov.expect("cannot have `fake` place for non-ZST type").alloc_id(); ConstValue::Indirect { alloc_id, offset } } // see comment on `let force_as_immediate` above @@ -178,8 +178,8 @@ pub(super) fn op_to_const<'tcx>( ); let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation"; // We know `offset` is relative to the allocation, so we can use `into_parts`. - let (alloc_id, offset) = a.to_pointer(ecx).expect(msg).into_parts(); - let alloc_id = alloc_id.expect(msg); + let (prov, offset) = a.to_pointer(ecx).expect(msg).into_parts(); + let alloc_id = prov.expect(msg).alloc_id(); let data = ecx.tcx.global_alloc(alloc_id).unwrap_memory(); assert!(offset == abi::Size::ZERO, "{}", msg); let meta = b.to_target_usize(ecx).expect(msg); @@ -314,7 +314,7 @@ pub fn eval_in_interpreter<'mir, 'tcx>( is_static: bool, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { let res = ecx.load_mir(cid.instance.def, cid.promoted); - match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) { + match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)) { Err(error) => { let (error, backtrace) = error.into_parts(); backtrace.print_backtrace(); @@ -338,7 +338,7 @@ pub fn eval_in_interpreter<'mir, 'tcx>( *ecx.tcx, error, None, - || super::get_span_and_frames(&ecx), + || super::get_span_and_frames(ecx.tcx, &ecx.machine), |span, frames| ConstEvalError { span, error_kind: kind, @@ -353,7 +353,7 @@ pub fn eval_in_interpreter<'mir, 'tcx>( let validation = const_validate_mplace(&ecx, &mplace, is_static, cid.promoted.is_some()); - let alloc_id = mplace.ptr().provenance.unwrap(); + let alloc_id = mplace.ptr().provenance.unwrap().alloc_id(); // Validation failed, report an error. if let Err(error) = validation { @@ -419,7 +419,7 @@ pub fn const_report_error<'mir, 'tcx>( *ecx.tcx, error, None, - || crate::const_eval::get_span_and_frames(ecx), + || crate::const_eval::get_span_and_frames(ecx.tcx, &ecx.machine), move |span, frames| errors::UndefinedBehavior { span, ub_note, frames, raw_bytes }, ) } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4b447229c5f61..9aaf6c510d509 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -1,30 +1,30 @@ -use rustc_hir::def::DefKind; -use rustc_hir::LangItem; -use rustc_middle::mir; -use rustc_middle::mir::interpret::PointerArithmetic; -use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::Span; use std::borrow::Borrow; +use std::fmt; use std::hash::Hash; use std::ops::ControlFlow; +use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::IndexEntry; -use std::fmt; - -use rustc_ast::Mutability; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; +use rustc_hir::LangItem; +use rustc_middle::mir; use rustc_middle::mir::AssertMessage; +use rustc_middle::query::TyCtxtAt; +use rustc_middle::ty; +use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; +use rustc_session::lint::builtin::WRITES_THROUGH_IMMUTABLE_POINTER; use rustc_span::symbol::{sym, Symbol}; +use rustc_span::Span; use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi as CallAbi; use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; use crate::interpret::{ - self, compile_time_machine, AllocId, ConstAllocation, FnArg, FnVal, Frame, ImmTy, InterpCx, - InterpResult, OpTy, PlaceTy, Pointer, Scalar, + self, compile_time_machine, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, FnVal, + Frame, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, PointerArithmetic, Scalar, }; use super::error::*; @@ -49,7 +49,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { pub(super) num_evaluated_steps: usize, /// The virtual call stack. - pub(super) stack: Vec>, + pub(super) stack: Vec>, /// We need to make sure consts never point to anything mutable, even recursively. That is /// relied on for pattern matching on consts with references. @@ -107,6 +107,14 @@ impl interpret::AllocMap for FxIndexMap { FxIndexMap::contains_key(self, k) } + #[inline(always)] + fn contains_key_ref(&self, k: &Q) -> bool + where + K: Borrow, + { + FxIndexMap::contains_key(self, k) + } + #[inline(always)] fn insert(&mut self, k: K, v: V) -> Option { FxIndexMap::insert(self, k, v) @@ -192,7 +200,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { &caller .file .name - .for_scope(&self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS) + .for_scope(self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS) .to_string_lossy(), ), u32::try_from(caller.line).unwrap(), @@ -383,7 +391,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, if ecx.tcx.is_ctfe_mir_available(def) { Ok(ecx.tcx.mir_for_ctfe(def)) } else if ecx.tcx.def_kind(def) == DefKind::AssocConst { - let guar = ecx.tcx.sess.delay_span_bug( + let guar = ecx.tcx.sess.span_delayed_bug( rustc_span::DUMMY_SP, "This is likely a const item that is missing from its impl", ); @@ -485,7 +493,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, }; let ptr = ecx.allocate_ptr( - Size::from_bytes(size as u64), + Size::from_bytes(size), align, interpret::MemoryKind::Machine(MemoryKind::Heap), )?; @@ -614,7 +622,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, let guard = ecx .tcx .sess - .delay_span_bug(span, "The deny lint should have already errored"); + .span_delayed_bug(span, "The deny lint should have already errored"); throw_inval!(AlreadyReported(guard.into())); } } else if new_steps > start && new_steps.is_power_of_two() { @@ -630,10 +638,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } #[inline(always)] - fn expose_ptr( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _ptr: Pointer, - ) -> InterpResult<'tcx> { + fn expose_ptr(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> { // This is only reachable with -Zunleash-the-miri-inside-of-you. throw_unsup_format!("exposing pointers is not possible at compile-time") } @@ -666,7 +671,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } fn before_access_global( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, machine: &Self, alloc_id: AllocId, alloc: ConstAllocation<'tcx>, @@ -703,6 +708,48 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } } + + fn retag_ptr_value( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + _kind: mir::RetagKind, + val: &ImmTy<'tcx, CtfeProvenance>, + ) -> InterpResult<'tcx, ImmTy<'tcx, CtfeProvenance>> { + // If it's a frozen shared reference that's not already immutable, make it immutable. + // (Do nothing on `None` provenance, that cannot store immutability anyway.) + if let ty::Ref(_, ty, mutbl) = val.layout.ty.kind() + && *mutbl == Mutability::Not + && val.to_scalar_and_meta().0.to_pointer(ecx)?.provenance.is_some_and(|p| !p.immutable()) + // That next check is expensive, that's why we have all the guards above. + && ty.is_freeze(*ecx.tcx, ecx.param_env) + { + let place = ecx.ref_to_mplace(val)?; + let new_place = place.map_provenance(|p| p.map(CtfeProvenance::as_immutable)); + Ok(ImmTy::from_immediate(new_place.to_ref(ecx), val.layout)) + } else { + Ok(val.clone()) + } + } + + fn before_memory_write( + tcx: TyCtxtAt<'tcx>, + machine: &mut Self, + _alloc_extra: &mut Self::AllocExtra, + (_alloc_id, immutable): (AllocId, bool), + range: AllocRange, + ) -> InterpResult<'tcx> { + if range.size == Size::ZERO { + // Nothing to check. + return Ok(()); + } + // Reject writes through immutable pointers. + if immutable { + super::lint(tcx, machine, WRITES_THROUGH_IMMUTABLE_POINTER, |frames| { + crate::errors::WriteThroughImmutablePointer { frames } + }); + } + // Everything else is fine. + Ok(()) + } } // Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index bda6a90550384..854fe9a0765f3 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -11,7 +11,7 @@ use rustc_middle::mir; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_span::DUMMY_SP; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{Abi, VariantIdx}; #[instrument(skip(ecx), level = "debug")] fn branches<'tcx>( @@ -97,11 +97,32 @@ pub(crate) fn const_to_valtree_inner<'tcx>( Ok(ty::ValTree::Leaf(val.assert_int())) } - // Raw pointers are not allowed in type level constants, as we cannot properly test them for - // equality at compile-time (see `ptr_guaranteed_cmp`). + ty::RawPtr(_) => { + // Not all raw pointers are allowed, as we cannot properly test them for + // equality at compile-time (see `ptr_guaranteed_cmp`). + // However we allow those that are just integers in disguise. + // First, get the pointer. Remember it might be wide! + let Ok(val) = ecx.read_immediate(place) else { + return Err(ValTreeCreationError::Other); + }; + // We could allow wide raw pointers where both sides are integers in the future, + // but for now we reject them. + if matches!(val.layout.abi, Abi::ScalarPair(..)) { + return Err(ValTreeCreationError::Other); + } + let val = val.to_scalar(); + // We are in the CTFE machine, so ptr-to-int casts will fail. + // This can only be `Ok` if `val` already is an integer. + let Ok(val) = val.try_to_int() else { + return Err(ValTreeCreationError::Other); + }; + // It's just a ScalarInt! + Ok(ty::ValTree::Leaf(val)) + } + // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to // agree with runtime equality tests. - ty::FnPtr(_) | ty::RawPtr(_) => Err(ValTreeCreationError::NonSupportedType), + ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType), ty::Ref(_, _, _) => { let Ok(derefd_place)= ecx.deref_pointer(place) else { @@ -222,12 +243,14 @@ pub fn valtree_to_const_value<'tcx>( assert!(valtree.unwrap_branch().is_empty()); mir::ConstValue::ZeroSized } - ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => match valtree { - ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)), - ty::ValTree::Branch(_) => bug!( - "ValTrees for Bool, Int, Uint, Float or Char should have the form ValTree::Leaf" - ), - }, + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char | ty::RawPtr(_) => { + match valtree { + ty::ValTree::Leaf(scalar_int) => mir::ConstValue::Scalar(Scalar::Int(scalar_int)), + ty::ValTree::Branch(_) => bug!( + "ValTrees for Bool, Int, Uint, Float, Char or RawPtr should have the form ValTree::Leaf" + ), + } + } ty::Ref(_, inner_ty, _) => { let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty); @@ -281,7 +304,6 @@ pub fn valtree_to_const_value<'tcx>( | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::FnPtr(_) - | ty::RawPtr(_) | ty::Str | ty::Slice(_) | ty::Dynamic(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()), @@ -365,7 +387,7 @@ fn valtree_into_mplace<'tcx>( debug!(?place_inner); valtree_into_mplace(ecx, &place_inner, *inner_valtree); - dump_place(&ecx, &place_inner); + dump_place(ecx, &place_inner); } debug!("dump of place_adjusted:"); diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index cc8f3387238d0..46fb64fd5b385 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -402,6 +402,13 @@ pub struct ConstEvalError { pub frame_notes: Vec, } +#[derive(LintDiagnostic)] +#[diag(const_eval_write_through_immutable_pointer)] +pub struct WriteThroughImmutablePointer { + #[subdiagnostic] + pub frames: Vec, +} + #[derive(Diagnostic)] #[diag(const_eval_nullary_intrinsic_fail)] pub struct NullaryIntrinsicError { @@ -437,7 +444,7 @@ pub trait ReportErrorExt { { ty::tls::with(move |tcx| { let mut builder = tcx.sess.struct_allow(DiagnosticMessage::Str(String::new().into())); - let handler = &tcx.sess.parse_sess.span_diagnostic; + let handler = tcx.sess.diagnostic(); let message = self.diagnostic_message(); self.add_args(handler, &mut builder); let s = handler.eagerly_translate_to_string(message, builder.args()); diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index f4cb12c8d4360..d296ff5928b36 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -256,7 +256,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let addr = addr.to_target_usize(self)?; // Then turn address into pointer. - let ptr = M::ptr_from_addr_cast(&self, addr)?; + let ptr = M::ptr_from_addr_cast(self, addr)?; Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(ptr, self), cast_to)) } diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index fd17367037438..d9f583c1d1f68 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -119,7 +119,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if matches!(ty.kind(), ty::Adt(def, ..) if def.variants().is_empty()) { throw_ub!(UninhabitedEnumVariantRead(index)) } - // For consisteny with `write_discriminant`, and to make sure that + // For consistency with `write_discriminant`, and to make sure that // `project_downcast` cannot fail due to strange layouts, we declare immediate UB // for uninhabited variants. if op.layout().for_variant(self, index).abi.is_uninhabited() { @@ -236,7 +236,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { variant } }; - // For consisteny with `write_discriminant`, and to make sure that `project_downcast` cannot fail due to strange layouts, we declare immediate UB for uninhabited variants. + // For consistency with `write_discriminant`, and to make sure that `project_downcast` cannot fail due to strange layouts, we declare immediate UB for uninhabited variants. if op.layout().for_variant(self, index).abi.is_uninhabited() { throw_ub!(UninhabitedEnumVariantRead(index)) } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 07cab5e3400ef..bbebf329d2659 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -7,7 +7,9 @@ use hir::CRATE_HIR_ID; use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::IndexVec; use rustc_middle::mir; -use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; +use rustc_middle::mir::interpret::{ + CtfeProvenance, ErrorHandled, InvalidMetaKind, ReportedErrorInfo, +}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers, @@ -20,9 +22,9 @@ use rustc_span::Span; use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout}; use super::{ - AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, - MemPlaceMeta, Memory, MemoryKind, OpTy, Operand, Place, PlaceTy, Pointer, PointerArithmetic, - Projectable, Provenance, Scalar, StackPopJump, + GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, + Memory, MemoryKind, OpTy, Operand, Place, PlaceTy, Pointer, PointerArithmetic, Projectable, + Provenance, Scalar, StackPopJump, }; use crate::errors; use crate::util; @@ -84,7 +86,7 @@ impl Drop for SpanGuard { } /// A stack frame. -pub struct Frame<'mir, 'tcx, Prov: Provenance = AllocId, Extra = ()> { +pub struct Frame<'mir, 'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> { //////////////////////////////////////////////////////////////////////////////// // Function and callsite information //////////////////////////////////////////////////////////////////////////////// @@ -156,7 +158,7 @@ pub enum StackPopCleanup { /// State of a local variable including a memoized layout #[derive(Clone)] -pub struct LocalState<'tcx, Prov: Provenance = AllocId> { +pub struct LocalState<'tcx, Prov: Provenance = CtfeProvenance> { value: LocalValue, /// Don't modify if `Some`, this is only used to prevent computing the layout twice. /// Avoids computing the layout of locals that are never actually initialized. @@ -173,8 +175,11 @@ impl std::fmt::Debug for LocalState<'_, Prov> { } /// Current value of a local variable +/// +/// This does not store the type of the local; the type is given by `body.local_decls` and can never +/// change, so by not storing here we avoid having to maintain that as an invariant. #[derive(Copy, Clone, Debug)] // Miri debug-prints these -pub(super) enum LocalValue { +pub(super) enum LocalValue { /// This local is not currently alive, and cannot be used at all. Dead, /// A normal, live local. @@ -279,14 +284,12 @@ impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> { impl<'tcx> fmt::Display for FrameInfo<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { - if tcx.def_key(self.instance.def_id()).disambiguated_data.data - == DefPathData::ClosureExpr - { + if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure { write!(f, "inside closure") } else { - // Note: this triggers a `good_path_bug` state, which means that if we ever get here - // we must emit a diagnostic. We should never display a `FrameInfo` unless we - // actually want to emit a warning or error to the user. + // Note: this triggers a `good_path_delayed_bug` state, which means that if we ever + // get here we must emit a diagnostic. We should never display a `FrameInfo` unless + // we actually want to emit a warning or error to the user. write!(f, "inside `{}`", self.instance) } }) @@ -296,12 +299,12 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> { impl<'tcx> FrameInfo<'tcx> { pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote { let span = self.span; - if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::ClosureExpr { + if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure { errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 } } else { let instance = format!("{}", self.instance); - // Note: this triggers a `good_path_bug` state, which means that if we ever get here - // we must emit a diagnostic. We should never display a `FrameInfo` unless we + // Note: this triggers a `good_path_delayed_bug` state, which means that if we ever get + // here we must emit a diagnostic. We should never display a `FrameInfo` unless we // actually want to emit a warning or error to the user. errors::FrameNote { where_: "instance", span, instance, times: 0 } } @@ -456,7 +459,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.stack() .iter() .find_map(|frame| frame.body.source.def_id().as_local()) - .map_or(CRATE_HIR_ID, |def_id| self.tcx.hir().local_def_id_to_hir_id(def_id)) + .map_or(CRATE_HIR_ID, |def_id| self.tcx.local_def_id_to_hir_id(def_id)) } /// Turn the given error into a human-readable string. Expects the string to be printed, so if @@ -470,7 +473,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { backtrace.print_backtrace(); // FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the // label and arguments from the InterpError. - let handler = &self.tcx.sess.parse_sess.span_diagnostic; + let handler = self.tcx.sess.diagnostic(); #[allow(rustc::untranslatable_diagnostic)] let mut diag = self.tcx.sess.struct_allow(""); let msg = e.diagnostic_message(); diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 3d90e95c09c79..7931789e4363b 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -18,7 +18,7 @@ use super::validity::RefTracking; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_middle::mir::interpret::InterpResult; +use rustc_middle::mir::interpret::{CtfeProvenance, InterpResult}; use rustc_middle::ty::{self, layout::TyAndLayout, Ty}; use rustc_ast::Mutability; @@ -34,7 +34,7 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine< 'mir, 'tcx, MemoryKind = T, - Provenance = AllocId, + Provenance = CtfeProvenance, ExtraFnVal = !, FrameExtra = (), AllocExtra = (), @@ -94,9 +94,9 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: // If the pointer is dangling (neither in local nor global memory), we leave it // to validation to error -- it has the much better error messages, pointing out where // in the value the dangling reference lies. - // The `delay_span_bug` ensures that we don't forget such a check in validation. + // The `span_delayed_bug` ensures that we don't forget such a check in validation. if tcx.try_get_global_alloc(alloc_id).is_none() { - tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer"); + tcx.sess.span_delayed_bug(ecx.tcx.span, "tried to intern dangling pointer"); } // treat dangling pointers like other statics // just to stop trying to recurse into them @@ -135,7 +135,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: alloc.mutability = Mutability::Not; }; // link the alloc id to the actual allocation - leftover_allocations.extend(alloc.provenance().ptrs().iter().map(|&(_, alloc_id)| alloc_id)); + leftover_allocations.extend(alloc.provenance().ptrs().iter().map(|&(_, prov)| prov.alloc_id())); let alloc = tcx.mk_const_alloc(alloc); tcx.set_alloc_id_memory(alloc_id, alloc); None @@ -178,20 +178,20 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind() { let ptr = mplace.meta().unwrap_meta().to_pointer(&tcx)?; - if let Some(alloc_id) = ptr.provenance { + if let Some(prov) = ptr.provenance { // Explicitly choose const mode here, since vtables are immutable, even // if the reference of the fat pointer is mutable. - self.intern_shallow(alloc_id, InternMode::Const, None); + self.intern_shallow(prov.alloc_id(), InternMode::Const, None); } else { // Validation will error (with a better message) on an invalid vtable pointer. // Let validation show the error message, but make sure it *does* error. tcx.sess - .delay_span_bug(tcx.span, "vtables pointers cannot be integer pointers"); + .span_delayed_bug(tcx.span, "vtables pointers cannot be integer pointers"); } } // Check if we have encountered this pointer+layout combination before. // Only recurse for allocation-backed pointers. - if let Some(alloc_id) = mplace.ptr().provenance { + if let Some(prov) = mplace.ptr().provenance { // Compute the mode with which we intern this. Our goal here is to make as many // statics as we can immutable so they can be placed in read-only memory by LLVM. let ref_mode = match self.mode { @@ -234,7 +234,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory InternMode::Const } }; - match self.intern_shallow(alloc_id, ref_mode, Some(referenced_ty)) { + match self.intern_shallow(prov.alloc_id(), ref_mode, Some(referenced_ty)) { // No need to recurse, these are interned already and statics may have // cycles, so we don't want to recurse there Some(IsStaticOrFn) => {} @@ -259,7 +259,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory // to avoid could be expensive: on the potentially larger types, arrays and slices, // rather than on all aggregates unconditionally. if matches!(mplace.layout.ty.kind(), ty::Array(..) | ty::Slice(..)) { - let Some((size, _align)) = self.ecx.size_and_align_of_mplace(&mplace)? else { + let Some((size, _align)) = self.ecx.size_and_align_of_mplace(mplace)? else { // We do the walk if we can't determine the size of the mplace: we may be // dealing with extern types here in the future. return Ok(true); @@ -353,7 +353,7 @@ pub fn intern_const_alloc_recursive< leftover_allocations, // The outermost allocation must exist, because we allocated it with // `Memory::allocate`. - ret.ptr().provenance.unwrap(), + ret.ptr().provenance.unwrap().alloc_id(), base_intern_mode, Some(ret.layout.ty), ); @@ -375,7 +375,7 @@ pub fn intern_const_alloc_recursive< match res { Ok(()) => {} Err(error) => { - ecx.tcx.sess.delay_span_bug( + ecx.tcx.sess.span_delayed_bug( ecx.tcx.span, format!( "error during interning should later cause validation failure: {}", @@ -431,7 +431,8 @@ pub fn intern_const_alloc_recursive< } let alloc = tcx.mk_const_alloc(alloc); tcx.set_alloc_id_memory(alloc_id, alloc); - for &(_, alloc_id) in alloc.inner().provenance().ptrs().iter() { + for &(_, prov) in alloc.inner().provenance().ptrs().iter() { + let alloc_id = prov.alloc_id(); if leftover_allocations.insert(alloc_id) { todo.push(alloc_id); } @@ -503,10 +504,11 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> // `allocate` picks a fresh AllocId that we will associate with its data below. let dest = self.allocate(layout, MemoryKind::Stack)?; f(self, &dest.clone().into())?; - let mut alloc = self.memory.alloc_map.remove(&dest.ptr().provenance.unwrap()).unwrap().1; + let mut alloc = + self.memory.alloc_map.remove(&dest.ptr().provenance.unwrap().alloc_id()).unwrap().1; alloc.mutability = Mutability::Not; let alloc = self.tcx.mk_const_alloc(alloc); - let alloc_id = dest.ptr().provenance.unwrap(); // this was just allocated, it must have provenance + let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance self.tcx.set_alloc_id_memory(alloc_id, alloc); Ok(alloc_id) } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index b23cafc193a05..c29f23b913f68 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -3,17 +3,22 @@ //! and miri. use rustc_hir::def_id::DefId; -use rustc_middle::mir::{ - self, - interpret::{Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar}, - BinOp, ConstValue, NonDivergingIntrinsic, -}; use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::{ + mir::{ + self, + interpret::{ + Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar, + }, + BinOp, ConstValue, NonDivergingIntrinsic, + }, + ty::layout::TyAndLayout, +}; use rustc_span::symbol::{sym, Symbol}; -use rustc_target::abi::{Abi, Primitive, Size}; +use rustc_target::abi::Size; use super::{ util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy, @@ -22,23 +27,6 @@ use super::{ use crate::fluent_generated as fluent; -fn numeric_intrinsic(name: Symbol, bits: u128, kind: Primitive) -> Scalar { - let size = match kind { - Primitive::Int(integer, _) => integer.size(), - _ => bug!("invalid `{}` argument: {:?}", name, bits), - }; - let extra = 128 - u128::from(size.bits()); - let bits_out = match name { - sym::ctpop => u128::from(bits.count_ones()), - sym::ctlz => u128::from(bits.leading_zeros()) - extra, - sym::cttz => u128::from((bits << extra).trailing_zeros()) - extra, - sym::bswap => (bits << extra).swap_bytes(), - sym::bitreverse => (bits << extra).reverse_bits(), - _ => bug!("not a numeric intrinsic: {}", name), - }; - Scalar::from_uint(bits_out, size) -} - /// Directly returns an `Allocation` containing an absolute path representation of the given type. pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> { let path = crate::util::type_name(tcx, ty); @@ -179,30 +167,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | sym::bswap | sym::bitreverse => { let ty = instance_args.type_at(0); - let layout_of = self.layout_of(ty)?; + let layout = self.layout_of(ty)?; let val = self.read_scalar(&args[0])?; - let bits = val.to_bits(layout_of.size)?; - let kind = match layout_of.abi { - Abi::Scalar(scalar) => scalar.primitive(), - _ => span_bug!( - self.cur_span(), - "{} called on invalid type {:?}", - intrinsic_name, - ty - ), - }; - let (nonzero, actual_intrinsic_name) = match intrinsic_name { - sym::cttz_nonzero => (true, sym::cttz), - sym::ctlz_nonzero => (true, sym::ctlz), - other => (false, other), - }; - if nonzero && bits == 0 { - throw_ub_custom!( - fluent::const_eval_call_nonzero_intrinsic, - name = intrinsic_name, - ); - } - let out_val = numeric_intrinsic(actual_intrinsic_name, bits, kind); + let out_val = self.numeric_intrinsic(intrinsic_name, val, layout)?; self.write_scalar(out_val, dest)?; } sym::saturating_add | sym::saturating_sub => { @@ -493,6 +460,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } + pub fn numeric_intrinsic( + &self, + name: Symbol, + val: Scalar, + layout: TyAndLayout<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty); + let bits = val.to_bits(layout.size)?; + let extra = 128 - u128::from(layout.size.bits()); + let bits_out = match name { + sym::ctpop => u128::from(bits.count_ones()), + sym::ctlz_nonzero | sym::cttz_nonzero if bits == 0 => { + throw_ub_custom!(fluent::const_eval_call_nonzero_intrinsic, name = name,); + } + sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra, + sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra, + sym::bswap => (bits << extra).swap_bytes(), + sym::bitreverse => (bits << extra).reverse_bits(), + _ => bug!("not a numeric intrinsic: {}", name), + }; + Ok(Scalar::from_uint(bits_out, layout.size)) + } + pub fn exact_div( &mut self, a: &ImmTy<'tcx, M::Provenance>, @@ -505,7 +495,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`. // First, check x % y != 0 (or if that computation overflows). - let (res, overflow) = self.overflowing_binary_op(BinOp::Rem, &a, &b)?; + let (res, overflow) = self.overflowing_binary_op(BinOp::Rem, a, b)?; assert!(!overflow); // All overflow is UB, so this should never return on overflow. if res.to_scalar().assert_bits(a.layout.size) != 0 { throw_ub_custom!( @@ -515,7 +505,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } // `Rem` says this is all right, so we can let `Div` do its job. - self.binop_ignore_overflow(BinOp::Div, &a, &b, dest) + self.binop_ignore_overflow(BinOp::Div, a, b, dest) } pub fn saturating_arith( diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 61fe9151d8b41..5e69965512b94 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -9,15 +9,17 @@ use std::hash::Hash; use rustc_apfloat::{Float, FloatConvert}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir; +use rustc_middle::query::TyCtxtAt; +use rustc_middle::ty; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; -use rustc_target::abi::Size; +use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi as CallAbi; use super::{ - AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx, - InterpResult, MPlaceTy, MemoryKind, OpTy, PlaceTy, Pointer, Provenance, + AllocBytes, AllocId, AllocKind, AllocRange, Allocation, ConstAllocation, CtfeProvenance, FnArg, + Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, MemoryKind, Misalignment, OpTy, PlaceTy, + Pointer, Provenance, }; /// Data returned by Machine::stack_pop, @@ -49,6 +51,14 @@ pub trait AllocMap { where K: Borrow; + /// Callers should prefer [`AllocMap::contains_key`] when it is possible to call because it may + /// be more efficient. This function exists for callers that only have a shared reference + /// (which might make it slightly less efficient than `contains_key`, e.g. if + /// the data is stored inside a `RefCell`). + fn contains_key_ref(&self, k: &Q) -> bool + where + K: Borrow; + /// Inserts a new entry into the map. fn insert(&mut self, k: K, v: V) -> Option; @@ -135,11 +145,18 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Whether memory accesses should be alignment-checked. fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; - /// Whether, when checking alignment, we should look at the actual address and thus support - /// custom alignment logic based on whatever the integer address happens to be. - /// - /// If this returns true, Provenance::OFFSET_IS_ADDR must be true. - fn use_addr_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; + /// Gives the machine a chance to detect more misalignment than the built-in checks would catch. + #[inline(always)] + fn alignment_check( + _ecx: &InterpCx<'mir, 'tcx, Self>, + _alloc_id: AllocId, + _alloc_align: Align, + _alloc_kind: AllocKind, + _offset: Size, + _align: Align, + ) -> Option { + None + } /// Whether to enforce the validity invariant for a specific layout. fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool; @@ -277,7 +294,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// `def_id` is `Some` if this is the "lazy" allocation of a static. #[inline] fn before_access_global( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, _machine: &Self, _alloc_id: AllocId, _allocation: ConstAllocation<'tcx>, @@ -372,7 +389,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// need to mutate. #[inline(always)] fn before_memory_read( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, _machine: &Self, _alloc_extra: &Self::AllocExtra, _prov: (AllocId, Self::ProvenanceExtra), @@ -384,7 +401,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Hook for performing extra checks on a memory write access. #[inline(always)] fn before_memory_write( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, _prov: (AllocId, Self::ProvenanceExtra), @@ -396,7 +413,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Hook for performing extra operations on a memory deallocation. #[inline(always)] fn before_memory_deallocation( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, _prov: (AllocId, Self::ProvenanceExtra), @@ -498,8 +515,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines /// (CTFE and ConstProp) use the same instance. Here, we share that code. pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { - type Provenance = AllocId; - type ProvenanceExtra = (); + type Provenance = CtfeProvenance; + type ProvenanceExtra = bool; // the "immutable" flag type ExtraFnVal = !; @@ -511,12 +528,6 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type FrameExtra = (); type Bytes = Box<[u8]>; - #[inline(always)] - fn use_addr_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { - // We do not support `use_addr`. - false - } - #[inline(always)] fn ignore_optional_overflow_checks(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { false @@ -558,14 +569,14 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { def_id: DefId, ) -> InterpResult<$tcx, Pointer> { // Use the `AllocId` associated with the `DefId`. Any actual *access* will fail. - Ok(Pointer::new(ecx.tcx.reserve_and_set_static_alloc(def_id), Size::ZERO)) + Ok(Pointer::new(ecx.tcx.reserve_and_set_static_alloc(def_id).into(), Size::ZERO)) } #[inline(always)] fn adjust_alloc_base_pointer( _ecx: &InterpCx<$mir, $tcx, Self>, - ptr: Pointer, - ) -> InterpResult<$tcx, Pointer> { + ptr: Pointer, + ) -> InterpResult<$tcx, Pointer> { Ok(ptr) } @@ -573,7 +584,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { fn ptr_from_addr_cast( _ecx: &InterpCx<$mir, $tcx, Self>, addr: u64, - ) -> InterpResult<$tcx, Pointer>> { + ) -> InterpResult<$tcx, Pointer>> { // Allow these casts, but make the pointer not dereferenceable. // (I.e., they behave like transmutation.) // This is correct because no pointers can ever be exposed in compile-time evaluation. @@ -583,10 +594,10 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { #[inline(always)] fn ptr_get_alloc( _ecx: &InterpCx<$mir, $tcx, Self>, - ptr: Pointer, + ptr: Pointer, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> { // We know `offset` is relative to the allocation, so we can use `into_parts`. - let (alloc_id, offset) = ptr.into_parts(); - Some((alloc_id, offset, ())) + let (prov, offset) = ptr.into_parts(); + Some((prov.alloc_id(), offset, prov.immutable())) } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 16905e93bf1f8..3fde6ae9b8ea6 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -22,8 +22,8 @@ use crate::fluent_generated as fluent; use super::{ alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckAlignMsg, - CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Misalignment, Pointer, - PointerArithmetic, Provenance, Scalar, + CheckInAllocMsg, CtfeProvenance, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, + Misalignment, Pointer, PointerArithmetic, Provenance, Scalar, }; #[derive(Debug, PartialEq, Copy, Clone)] @@ -58,6 +58,7 @@ impl fmt::Display for MemoryKind { } /// The return value of `get_alloc_info` indicates the "kind" of the allocation. +#[derive(Copy, Clone, PartialEq, Debug)] pub enum AllocKind { /// A regular live data allocation. LiveData, @@ -158,9 +159,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { #[inline] pub fn global_base_pointer( &self, - ptr: Pointer, + ptr: Pointer, ) -> InterpResult<'tcx, Pointer> { - let alloc_id = ptr.provenance; + let alloc_id = ptr.provenance.alloc_id(); // We need to handle `extern static`. match self.tcx.try_get_global_alloc(alloc_id) { Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => { @@ -338,7 +339,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Let the machine take some extra action let size = alloc.size(); M::before_memory_deallocation( - *self.tcx, + self.tcx, &mut self.machine, &mut alloc.extra, (alloc_id, prov), @@ -473,8 +474,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match self.ptr_try_get_alloc_id(ptr) { Err(addr) => offset_misalignment(addr, align), Ok((alloc_id, offset, _prov)) => { - let (_size, alloc_align, _kind) = self.get_alloc_info(alloc_id); - if M::use_addr_for_alignment_check(self) { + let (_size, alloc_align, kind) = self.get_alloc_info(alloc_id); + if let Some(misalign) = + M::alignment_check(self, alloc_id, alloc_align, kind, offset, align) + { + Some(misalign) + } else if M::Provenance::OFFSET_IS_ADDR { // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true. offset_misalignment(ptr.addr().bytes(), align) } else { @@ -501,6 +506,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { + /// This function is used by Miri's provenance GC to remove unreachable entries from the dead_alloc_map. + pub fn remove_unreachable_allocs(&mut self, reachable_allocs: &FxHashSet) { + // Unlike all the other GC helpers where we check if an `AllocId` is found in the interpreter or + // is live, here all the IDs in the map are for dead allocations so we don't + // need to check for liveness. + #[allow(rustc::potential_query_instability)] // Only used from Miri, not queries. + self.memory.dead_alloc_map.retain(|id, _| reachable_allocs.contains(id)); + } +} + /// Allocation accessors impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Helper function to obtain a global (tcx) allocation. @@ -545,7 +561,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (val, Some(def_id)) } }; - M::before_access_global(*self.tcx, &self.machine, id, alloc, def_id, is_write)?; + M::before_access_global(self.tcx, &self.machine, id, alloc, def_id, is_write)?; // We got tcx memory. Let the machine initialize its "extra" stuff. M::adjust_allocation( self, @@ -610,7 +626,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )?; if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc { let range = alloc_range(offset, size); - M::before_memory_read(*self.tcx, &self.machine, &alloc.extra, (alloc_id, prov), range)?; + M::before_memory_read(self.tcx, &self.machine, &alloc.extra, (alloc_id, prov), range)?; Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id })) } else { // Even in this branch we have to be sure that we actually access the allocation, in @@ -671,13 +687,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { { let parts = self.get_ptr_access(ptr, size)?; if let Some((alloc_id, offset, prov)) = parts { - let tcx = *self.tcx; + let tcx = self.tcx; // FIXME: can we somehow avoid looking up the allocation twice here? // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?; let range = alloc_range(offset, size); M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?; - Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id })) + Ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id })) } else { Ok(None) } @@ -692,6 +708,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok((&mut alloc.extra, machine)) } + /// Check whether an allocation is live. This is faster than calling + /// [`InterpCx::get_alloc_info`] if all you need to check is whether the kind is + /// [`AllocKind::Dead`] because it doesn't have to look up the type and layout of statics. + pub fn is_alloc_live(&self, id: AllocId) -> bool { + self.tcx.try_get_global_alloc(id).is_some() + || self.memory.alloc_map.contains_key_ref(&id) + || self.memory.extra_fn_ptr_map.contains_key(&id) + } + /// Obtain the size and alignment of an allocation, even if that allocation has /// been deallocated. pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) { @@ -1108,7 +1133,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); M::before_memory_read( - *tcx, + tcx, &self.machine, &src_alloc.extra, (src_alloc_id, src_prov), @@ -1138,7 +1163,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?; let dest_range = alloc_range(dest_offset, size * num_copies); M::before_memory_write( - *tcx, + tcx, extra, &mut dest_alloc.extra, (dest_alloc_id, dest_prov), diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 255dd1eba97f2..b39b219b46a14 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -13,9 +13,9 @@ use rustc_middle::{mir, ty}; use rustc_target::abi::{self, Abi, HasDataLayout, Size}; use super::{ - alloc_range, from_known_layout, mir_assign_valid_types, AllocId, Frame, InterpCx, InterpResult, - MPlaceTy, Machine, MemPlace, MemPlaceMeta, OffsetMode, PlaceTy, Pointer, Projectable, - Provenance, Scalar, + alloc_range, from_known_layout, mir_assign_valid_types, CtfeProvenance, Frame, InterpCx, + InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, OffsetMode, PlaceTy, Pointer, + Projectable, Provenance, Scalar, }; /// An `Immediate` represents a single immediate self-contained Rust value. @@ -26,7 +26,7 @@ use super::{ /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely /// defined on `Immediate`, and do not have to work with a `Place`. #[derive(Copy, Clone, Debug)] -pub enum Immediate { +pub enum Immediate { /// A single scalar value (must have *initialized* `Scalar` ABI). Scalar(Scalar), /// A pair of two scalar value (must have `ScalarPair` ABI where both fields are @@ -93,12 +93,23 @@ impl Immediate { Immediate::Uninit => bug!("Got uninit where a scalar pair was expected"), } } + + /// Returns the scalar from the first component and optionally the 2nd component as metadata. + #[inline] + #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980) + pub fn to_scalar_and_meta(self) -> (Scalar, MemPlaceMeta) { + match self { + Immediate::ScalarPair(val1, val2) => (val1, MemPlaceMeta::Meta(val2)), + Immediate::Scalar(val) => (val, MemPlaceMeta::None), + Immediate::Uninit => bug!("Got uninit where a scalar or scalar pair was expected"), + } + } } // ScalarPair needs a type to interpret, so we often have an immediate and a type together // as input for binary and cast operations. #[derive(Clone)] -pub struct ImmTy<'tcx, Prov: Provenance = AllocId> { +pub struct ImmTy<'tcx, Prov: Provenance = CtfeProvenance> { imm: Immediate, pub layout: TyAndLayout<'tcx>, } @@ -334,13 +345,13 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> { /// or still in memory. The latter is an optimization, to delay reading that chunk of /// memory and to avoid having to store arbitrary-sized data here. #[derive(Copy, Clone, Debug)] -pub(super) enum Operand { +pub(super) enum Operand { Immediate(Immediate), Indirect(MemPlace), } #[derive(Clone)] -pub struct OpTy<'tcx, Prov: Provenance = AllocId> { +pub struct OpTy<'tcx, Prov: Provenance = CtfeProvenance> { op: Operand, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, } @@ -750,17 +761,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?; let imm = match val_val { mir::ConstValue::Indirect { alloc_id, offset } => { - // We rely on mutability being set correctly in that allocation to prevent writes - // where none should happen. - let ptr = self.global_base_pointer(Pointer::new(alloc_id, offset))?; + // This is const data, no mutation allowed. + let ptr = self.global_base_pointer(Pointer::new( + CtfeProvenance::from(alloc_id).as_immutable(), + offset, + ))?; return Ok(self.ptr_to_mplace(ptr.into(), layout).into()); } mir::ConstValue::Scalar(x) => adjust_scalar(x)?.into(), mir::ConstValue::ZeroSized => Immediate::Uninit, mir::ConstValue::Slice { data, meta } => { - // We rely on mutability being set correctly in `data` to prevent writes - // where none should happen. - let ptr = Pointer::new(self.tcx.reserve_and_set_memory_alloc(data), Size::ZERO); + // This is const data, no mutation allowed. + let alloc_id = self.tcx.reserve_and_set_memory_alloc(data); + let ptr = Pointer::new(CtfeProvenance::from(alloc_id).as_immutable(), Size::ZERO); Immediate::new_slice(self.global_base_pointer(ptr)?.into(), meta, self) } }; diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index a3ba9530f9dc7..eef1542576466 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -20,7 +20,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right: &ImmTy<'tcx, M::Provenance>, dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let (val, overflowed) = self.overflowing_binary_op(op, &left, &right)?; + let (val, overflowed) = self.overflowing_binary_op(op, left, right)?; debug_assert_eq!( Ty::new_tup(self.tcx.tcx, &[val.layout.ty, self.tcx.types.bool]), dest.layout.ty, @@ -114,9 +114,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { use rustc_middle::mir::BinOp::*; // Performs appropriate non-deterministic adjustments of NaN results. - let adjust_nan = |f: F| -> F { - if f.is_nan() { M::generate_nan(self, &[l, r]) } else { f } - }; + let adjust_nan = + |f: F| -> F { if f.is_nan() { M::generate_nan(self, &[l, r]) } else { f } }; let val = match bin_op { Eq => ImmTy::from_bool(l == r, *self.tcx), @@ -157,41 +156,35 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Shift ops can have an RHS with a different numeric type. if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) { - let size = u128::from(left_layout.size.bits()); - // Even if `r` is signed, we treat it as if it was unsigned (i.e., we use its - // zero-extended form). This matches the codegen backend: - // . - // The overflow check is also ignorant to the sign: - // . - // This would behave rather strangely if we had integer types of size 256: a shift by - // -1i8 would actually shift by 255, but that would *not* be considered overflowing. A - // shift by -1i16 though would be considered overflowing. If we had integers of size - // 512, then a shift by -1i8 would even produce a different result than one by -1i16: - // the first shifts by 255, the latter by u16::MAX % 512 = 511. Lucky enough, our - // integers are maximally 128bits wide, so negative shifts *always* overflow and we have - // consistent results for the same value represented at different bit widths. - assert!(size <= 128); - let original_r = r; - let overflow = r >= size; - // The shift offset is implicitly masked to the type size, to make sure this operation - // is always defined. This is the one MIR operator that does *not* directly map to a - // single LLVM operation. See - // - // for the corresponding truncation in our codegen backends. - let r = r % size; - let r = u32::try_from(r).unwrap(); // we masked so this will always fit + let size = left_layout.size.bits(); + // The shift offset is implicitly masked to the type size. (This is the one MIR operator + // that does *not* directly map to a single LLVM operation.) Compute how much we + // actually shift and whether there was an overflow due to shifting too much. + let (shift_amount, overflow) = if right_layout.abi.is_signed() { + let shift_amount = self.sign_extend(r, right_layout) as i128; + let overflow = shift_amount < 0 || shift_amount >= i128::from(size); + let masked_amount = (shift_amount as u128) % u128::from(size); + debug_assert_eq!(overflow, shift_amount != (masked_amount as i128)); + (masked_amount, overflow) + } else { + let shift_amount = r; + let masked_amount = shift_amount % u128::from(size); + (masked_amount, shift_amount != masked_amount) + }; + let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit + // Compute the shifted result. let result = if left_layout.abi.is_signed() { let l = self.sign_extend(l, left_layout) as i128; let result = match bin_op { - Shl | ShlUnchecked => l.checked_shl(r).unwrap(), - Shr | ShrUnchecked => l.checked_shr(r).unwrap(), + Shl | ShlUnchecked => l.checked_shl(shift_amount).unwrap(), + Shr | ShrUnchecked => l.checked_shr(shift_amount).unwrap(), _ => bug!(), }; result as u128 } else { match bin_op { - Shl | ShlUnchecked => l.checked_shl(r).unwrap(), - Shr | ShrUnchecked => l.checked_shr(r).unwrap(), + Shl | ShlUnchecked => l.checked_shl(shift_amount).unwrap(), + Shr | ShrUnchecked => l.checked_shr(shift_amount).unwrap(), _ => bug!(), } }; @@ -200,7 +193,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if overflow && let Some(intrinsic_name) = throw_ub_on_overflow { throw_ub_custom!( fluent::const_eval_overflow_shift, - val = original_r, + val = if right_layout.abi.is_signed() { + (self.sign_extend(r, right_layout) as i128).to_string() + } else { + r.to_string() + }, name = intrinsic_name ); } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 09ffdec7de7d1..639b269ac257a 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -7,22 +7,21 @@ use std::assert_matches::assert_matches; use either::{Either, Left, Right}; use rustc_ast::Mutability; -use rustc_index::IndexSlice; use rustc_middle::mir; use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::Ty; -use rustc_target::abi::{Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_VARIANT}; +use rustc_target::abi::{Abi, Align, HasDataLayout, Size}; use super::{ - alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckAlignMsg, ImmTy, - Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, + alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, + ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer, PointerArithmetic, Projectable, Provenance, Readable, Scalar, }; #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] /// Information required for the sound usage of a `MemPlace`. -pub enum MemPlaceMeta { +pub enum MemPlaceMeta { /// The unsized payload (e.g. length for slices or vtable pointer for trait objects). Meta(Scalar), /// `Sized` types or unsized `extern type` @@ -50,7 +49,7 @@ impl MemPlaceMeta { } #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] -pub(super) struct MemPlace { +pub(super) struct MemPlace { /// The pointer can be a pure integer, with the `None` provenance. pub ptr: Pointer>, /// Metadata for unsized places. Interpretation is up to the type. @@ -101,7 +100,7 @@ impl MemPlace { /// A MemPlace with its layout. Constructing it is only possible in this module. #[derive(Clone, Hash, Eq, PartialEq)] -pub struct MPlaceTy<'tcx, Prov: Provenance = AllocId> { +pub struct MPlaceTy<'tcx, Prov: Provenance = CtfeProvenance> { mplace: MemPlace, pub layout: TyAndLayout<'tcx>, } @@ -180,7 +179,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for MPlaceTy<'tcx, Prov> { } #[derive(Copy, Clone, Debug)] -pub(super) enum Place { +pub(super) enum Place { /// A place referring to a value allocated in the `Memory` system. Ptr(MemPlace), @@ -196,7 +195,7 @@ pub(super) enum Place { } #[derive(Clone)] -pub struct PlaceTy<'tcx, Prov: Provenance = AllocId> { +pub struct PlaceTy<'tcx, Prov: Provenance = CtfeProvenance> { place: Place, // Keep this private; it helps enforce invariants. pub layout: TyAndLayout<'tcx>, } @@ -407,11 +406,7 @@ where let pointee_type = val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty; let layout = self.layout_of(pointee_type)?; - let (ptr, meta) = match **val { - Immediate::Scalar(ptr) => (ptr, MemPlaceMeta::None), - Immediate::ScalarPair(ptr, meta) => (ptr, MemPlaceMeta::Meta(meta)), - Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), - }; + let (ptr, meta) = val.to_scalar_and_meta(); // `ref_to_mplace` is called on raw pointers even if they don't actually get dereferenced; // we hence can't call `size_and_align_of` since that asserts more validity than we want. @@ -456,7 +451,7 @@ where ) -> InterpResult<'tcx, Option>> { let (size, _align) = self - .size_and_align_of_mplace(&mplace)? + .size_and_align_of_mplace(mplace)? .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); // We check alignment separately, and *after* checking everything else. // If an access is both OOB and misaligned, we want to see the bounds error. @@ -472,7 +467,7 @@ where ) -> InterpResult<'tcx, Option>> { let (size, _align) = self - .size_and_align_of_mplace(&mplace)? + .size_and_align_of_mplace(mplace)? .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); // We check alignment separately, and raise that error *after* checking everything else. // If an access is both OOB and misaligned, we want to see the bounds error. @@ -977,34 +972,6 @@ where Ok(self.ptr_with_meta_to_mplace(ptr.into(), MemPlaceMeta::Meta(meta), layout)) } - /// Writes the aggregate to the destination. - #[instrument(skip(self), level = "trace")] - pub fn write_aggregate( - &mut self, - kind: &mir::AggregateKind<'tcx>, - operands: &IndexSlice>, - dest: &PlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx> { - self.write_uninit(dest)?; - let (variant_index, variant_dest, active_field_index) = match *kind { - mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { - let variant_dest = self.project_downcast(dest, variant_index)?; - (variant_index, variant_dest, active_field_index) - } - _ => (FIRST_VARIANT, dest.clone(), None), - }; - if active_field_index.is_some() { - assert_eq!(operands.len(), 1); - } - for (field_index, operand) in operands.iter_enumerated() { - let field_index = active_field_index.unwrap_or(field_index); - let field_dest = self.project_field(&variant_dest, field_index.as_usize())?; - let op = self.eval_operand(operand, Some(field_dest.layout))?; - self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?; - } - self.write_discriminant(variant_index, dest) - } - pub fn raw_const_to_mplace( &self, raw: mir::ConstAlloc<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 6694c43c99260..4d9e296d5441b 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -163,7 +163,17 @@ where // With custom DSTS, this *will* execute user-defined code, but the same // happens at run-time so that's okay. match self.size_and_align_of(&base_meta, &field_layout)? { - Some((_, align)) => (base_meta, offset.align_to(align)), + Some((_, align)) => { + // For packed types, we need to cap alignment. + let align = if let ty::Adt(def, _) = base.layout().ty.kind() + && let Some(packed) = def.repr().pack + { + align.min(packed) + } else { + align + }; + (base_meta, offset.align_to(align)) + } None => { // For unsized types with an extern type tail we perform no adjustments. // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend. @@ -256,13 +266,13 @@ where } /// Iterates over all fields of an array. Much more efficient than doing the - /// same by repeatedly calling `operand_index`. + /// same by repeatedly calling `project_index`. pub fn project_array_fields<'a, P: Projectable<'tcx, M::Provenance>>( &self, base: &'a P, ) -> InterpResult<'tcx, ArrayIterator<'tcx, 'a, M::Provenance, P>> { let abi::FieldsShape::Array { stride, .. } = base.layout().fields else { - span_bug!(self.cur_span(), "operand_array_fields: expected an array layout"); + span_bug!(self.cur_span(), "project_array_fields: expected an array layout"); }; let len = base.len(self)?; let field_layout = base.layout().field(self, 0); diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index b6993d939c585..d48329b6c6946 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -4,11 +4,12 @@ use either::Either; +use rustc_index::IndexSlice; use rustc_middle::mir; -use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::LayoutOf; +use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; -use super::{ImmTy, InterpCx, Machine, Projectable}; +use super::{ImmTy, InterpCx, InterpResult, Machine, PlaceTy, Projectable, Scalar}; use crate::util; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { @@ -187,34 +188,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Repeat(ref operand, _) => { - let src = self.eval_operand(operand, None)?; - assert!(src.layout.is_sized()); - let dest = self.force_allocation(&dest)?; - let length = dest.len(self)?; - - if length == 0 { - // Nothing to copy... but let's still make sure that `dest` as a place is valid. - self.get_place_alloc_mut(&dest)?; - } else { - // Write the src to the first element. - let first = self.project_index(&dest, 0)?; - self.copy_op(&src, &first, /*allow_transmute*/ false)?; - - // This is performance-sensitive code for big static/const arrays! So we - // avoid writing each operand individually and instead just make many copies - // of the first element. - let elem_size = first.layout.size; - let first_ptr = first.ptr(); - let rest_ptr = first_ptr.offset(elem_size, self)?; - // No alignment requirement since `copy_op` above already checked it. - self.mem_copy_repeatedly( - first_ptr, - rest_ptr, - elem_size, - length - 1, - /*nonoverlapping:*/ true, - )?; - } + self.write_repeat(operand, &dest)?; } Len(place) => { @@ -307,6 +281,73 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } + /// Writes the aggregate to the destination. + #[instrument(skip(self), level = "trace")] + fn write_aggregate( + &mut self, + kind: &mir::AggregateKind<'tcx>, + operands: &IndexSlice>, + dest: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx> { + self.write_uninit(dest)?; // make sure all the padding ends up as uninit + let (variant_index, variant_dest, active_field_index) = match *kind { + mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { + let variant_dest = self.project_downcast(dest, variant_index)?; + (variant_index, variant_dest, active_field_index) + } + _ => (FIRST_VARIANT, dest.clone(), None), + }; + if active_field_index.is_some() { + assert_eq!(operands.len(), 1); + } + for (field_index, operand) in operands.iter_enumerated() { + let field_index = active_field_index.unwrap_or(field_index); + let field_dest = self.project_field(&variant_dest, field_index.as_usize())?; + let op = self.eval_operand(operand, Some(field_dest.layout))?; + self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?; + } + self.write_discriminant(variant_index, dest) + } + + /// Repeats `operand` into the destination. `dest` must have array type, and that type + /// determines how often `operand` is repeated. + fn write_repeat( + &mut self, + operand: &mir::Operand<'tcx>, + dest: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx> { + let src = self.eval_operand(operand, None)?; + assert!(src.layout.is_sized()); + let dest = self.force_allocation(&dest)?; + let length = dest.len(self)?; + + if length == 0 { + // Nothing to copy... but let's still make sure that `dest` as a place is valid. + self.get_place_alloc_mut(&dest)?; + } else { + // Write the src to the first element. + let first = self.project_index(&dest, 0)?; + self.copy_op(&src, &first, /*allow_transmute*/ false)?; + + // This is performance-sensitive code for big static/const arrays! So we + // avoid writing each operand individually and instead just make many copies + // of the first element. + let elem_size = first.layout.size; + let first_ptr = first.ptr(); + let rest_ptr = first_ptr.offset(elem_size, self)?; + // No alignment requirement since `copy_op` above already checked it. + self.mem_copy_repeatedly( + first_ptr, + rest_ptr, + elem_size, + length - 1, + /*nonoverlapping:*/ true, + )?; + } + + Ok(()) + } + /// Evaluate the given terminator. Will also adjust the stack frame and statement position accordingly. fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> { info!("{:?}", terminator.kind); diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index b54c668145638..e48506bd083ff 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -18,14 +18,14 @@ use rustc_target::abi::{ use rustc_target::spec::abi::Abi; use super::{ - AllocId, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Projectable, - Provenance, Scalar, StackPopCleanup, + CtfeProvenance, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, + Projectable, Provenance, Scalar, StackPopCleanup, }; use crate::fluent_generated as fluent; /// An argment passed to a function. #[derive(Clone, Debug)] -pub enum FnArg<'tcx, Prov: Provenance = AllocId> { +pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> { /// Pass a copy of the given operand. Copy(OpTy<'tcx, Prov>), /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and @@ -51,7 +51,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { match arg { FnArg::Copy(op) => Ok(op.clone()), - FnArg::InPlace(place) => self.place_to_op(&place), + FnArg::InPlace(place) => self.place_to_op(place), } } @@ -410,7 +410,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // so we implement a type-based check that reflects the guaranteed rules for ABI compatibility. if self.layout_compat(caller_abi.layout, callee_abi.layout)? { // Ensure that our checks imply actual ABI compatibility for this concrete call. - assert!(caller_abi.eq_abi(&callee_abi)); + assert!(caller_abi.eq_abi(callee_abi)); return Ok(true); } else { trace!( @@ -464,7 +464,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // We work with a copy of the argument for now; if this is in-place argument passing, we // will later protect the source it comes from. This means the callee cannot observe if we // did in-place of by-copy argument passing, except for pointer equality tests. - let caller_arg_copy = self.copy_fn_arg(&caller_arg)?; + let caller_arg_copy = self.copy_fn_arg(caller_arg)?; if !already_live { let local = callee_arg.as_local().unwrap(); let meta = caller_arg_copy.meta(); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index d21fef58f3f81..20f251d5c91ad 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -896,7 +896,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self }; // Run it. - match visitor.visit_value(&op) { + match visitor.visit_value(op) { Ok(()) => Ok(()), // Pass through validation failures and "invalid program" issues. Err(err) diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index fc21ad1f1834b..5c5a6e8db57a2 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -97,14 +97,14 @@ pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized { let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.0; trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout); // recurse with the inner type - return self.visit_field(&v, 0, &inner_mplace.into()); + return self.visit_field(v, 0, &inner_mplace.into()); } ty::Dynamic(_, _, ty::DynStar) => { // DynStar types. Very different from a dyn type (but strangely part of the // same variant in `TyKind`): These are pairs where the 2nd component is the // vtable, and the first component is the data (which must be ptr-sized). let data = self.ecx().unpack_dyn_star(v)?.0; - return self.visit_field(&v, 0, &data); + return self.visit_field(v, 0, &data); } // Slices do not need special handling here: they have `Array` field // placement with length 0, so we enter the `Array` case below which diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 1e21c49407074..d6c36ccc5ec8b 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -4,9 +4,9 @@ Rust MIR: a lowered representation of Rust. */ -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![deny(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(box_patterns)] @@ -39,11 +39,9 @@ pub mod util; pub use errors::ReportErrorExt; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_middle::{ty, util::Providers}; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { const_eval::provide(providers); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 135c99fefbc85..e604f4c1aecb8 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -22,7 +22,7 @@ use std::mem; use std::ops::{ControlFlow, Deref}; use super::ops::{self, NonConstOp, Status}; -use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop}; +use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; use super::resolver::FlowSensitiveAnalysis; use super::{ConstCx, Qualif}; use crate::const_eval::is_unstable_const_fn; @@ -35,7 +35,7 @@ type QualifResults<'mir, 'tcx, Q> = pub struct Qualifs<'mir, 'tcx> { has_mut_interior: Option>, needs_drop: Option>, - // needs_non_const_drop: Option>, + needs_non_const_drop: Option>, } impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { @@ -60,9 +60,9 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let ConstCx { tcx, body, .. } = *ccx; FlowSensitiveAnalysis::new(NeedsDrop, ccx) - .into_engine(tcx, &body) + .into_engine(tcx, body) .iterate_to_fixpoint() - .into_results_cursor(&body) + .into_results_cursor(body) }); needs_drop.seek_before_primary_effect(location); @@ -78,27 +78,25 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { local: Local, location: Location, ) -> bool { - // FIXME(effects) replace with `NeedsNonconstDrop` after const traits work again - /* let ty = ccx.body.local_decls[local].ty; - if !NeedsDrop::in_any_value_of_ty(ccx, ty) { + // Peeking into opaque types causes cycles if the current function declares said opaque + // type. Thus we avoid short circuiting on the type and instead run the more expensive + // analysis that looks at the actual usage within this function + if !ty.has_opaque_types() && !NeedsNonConstDrop::in_any_value_of_ty(ccx, ty) { return false; } let needs_non_const_drop = self.needs_non_const_drop.get_or_insert_with(|| { let ConstCx { tcx, body, .. } = *ccx; - FlowSensitiveAnalysis::new(NeedsDrop, ccx) - .into_engine(tcx, &body) + FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx) + .into_engine(tcx, body) .iterate_to_fixpoint() - .into_results_cursor(&body) + .into_results_cursor(body) }); needs_non_const_drop.seek_before_primary_effect(location); needs_non_const_drop.get().contains(local) - */ - - self.needs_drop(ccx, local, location) } /// Returns `true` if `local` is `HasMutInterior` at the given `Location`. @@ -122,9 +120,9 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let ConstCx { tcx, body, .. } = *ccx; FlowSensitiveAnalysis::new(HasMutInterior, ccx) - .into_engine(tcx, &body) + .into_engine(tcx, body) .iterate_to_fixpoint() - .into_results_cursor(&body) + .into_results_cursor(body) }); has_mut_interior.seek_before_primary_effect(location); @@ -170,9 +168,9 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => { let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx) - .into_engine(ccx.tcx, &ccx.body) + .into_engine(ccx.tcx, ccx.body) .iterate_to_fixpoint() - .into_results_cursor(&ccx.body); + .into_results_cursor(ccx.body); cursor.seek_after_primary_effect(return_loc); cursor.get().contains(RETURN_PLACE) @@ -225,7 +223,7 @@ impl<'mir, 'tcx> Deref for Checker<'mir, 'tcx> { type Target = ConstCx<'mir, 'tcx>; fn deref(&self) -> &Self::Target { - &self.ccx + self.ccx } } @@ -248,7 +246,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // `async` functions cannot be `const fn`. This is checked during AST lowering, so there's // no need to emit duplicate errors here. if self.ccx.is_async() || body.coroutine.is_some() { - tcx.sess.delay_span_bug(body.span, "`async` functions cannot be `const fn`"); + tcx.sess.span_delayed_bug(body.span, "`async` functions cannot be `const fn`"); return; } @@ -272,7 +270,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { } if !tcx.has_attr(def_id, sym::rustc_do_not_const_check) { - self.visit_body(&body); + self.visit_body(body); } // If we got through const-checking without emitting any "primary" errors, emit any @@ -357,7 +355,9 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { fn check_static(&mut self, def_id: DefId, span: Span) { if self.tcx.is_thread_local_static(def_id) { - self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`"); + self.tcx + .sess + .span_delayed_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`"); } self.check_op_spanned(ops::StaticAccess, span) } @@ -423,8 +423,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { BorrowKind::Shared => { PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) } - BorrowKind::Shallow => { - PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) + BorrowKind::Fake => { + PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow) } BorrowKind::Mut { .. } => { PlaceContext::MutatingUse(MutatingUseContext::Borrow) @@ -500,10 +500,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { self.check_mut_borrow(place.local, hir::BorrowKind::Raw) } - Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, place) + Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake, place) | Rvalue::AddressOf(Mutability::Not, place) => { let borrowed_place_has_mut_interior = qualifs::in_place::( - &self.ccx, + self.ccx, &mut |local| self.qualifs.has_mut_interior(self.ccx, local, location), place.as_ref(), ); @@ -1011,9 +1011,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let mut err_span = self.span; let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty; - // FIXME(effects) replace with `NeedsNonConstDrop` once we fix const traits let ty_needs_non_const_drop = - qualifs::NeedsDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place); + qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place); debug!(?ty_of_dropped_place, ?ty_needs_non_const_drop); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index e51082e1ec0e3..4f7e165c575f8 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -82,8 +82,8 @@ pub fn rustc_allow_const_fn_unstable( def_id: LocalDefId, feature_gate: Symbol, ) -> bool { - let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id)); - attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate) + let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id)); + attr::rustc_allow_const_fn_unstable(tcx.sess, attrs).any(|name| name == feature_gate) } /// Returns `true` if the given `const fn` is "const-stable". @@ -112,7 +112,7 @@ pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { None if is_parent_const_stable_trait(tcx, def_id) => { // Remove this when `#![feature(const_trait_impl)]` is stabilized, // returning `true` unconditionally. - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( tcx.def_span(def_id), "trait implementations cannot be const stable yet", ); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 40183baccf8fe..5bf9911269cbe 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -119,7 +119,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { match self_ty.kind() { Param(param_ty) => { debug!(?param_ty); - let caller_hir_id = tcx.hir().local_def_id_to_hir_id(caller); + let caller_hir_id = tcx.local_def_id_to_hir_id(caller); if let Some(generics) = tcx.hir().get(caller_hir_id).generics() { let constraint = with_no_trimmed_paths!(format!( "~const {}", @@ -129,7 +129,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { tcx, generics, err, - ¶m_ty.name.as_str(), + param_ty.name.as_str(), &constraint, None, None, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index aff256b3eadd6..5cd13783c2318 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -5,7 +5,7 @@ use rustc_span::{symbol::sym, Span}; use super::check::Qualifs; use super::ops::{self, NonConstOp}; -use super::qualifs::{NeedsDrop, Qualif}; +use super::qualifs::{NeedsNonConstDrop, Qualif}; use super::ConstCx; /// Returns `true` if we should use the more precise live drop checker that runs after drop @@ -54,7 +54,7 @@ impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { type Target = ConstCx<'mir, 'tcx>; fn deref(&self) -> &Self::Target { - &self.ccx + self.ccx } } @@ -83,8 +83,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { mir::TerminatorKind::Drop { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; - // FIXME(effects) use `NeedsNonConstDrop` - if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) { + if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) { // Instead of throwing a bug, we just return here. This is because we have to // run custom `const Drop` impls. return; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index de3186a53c165..d5f418e1710e3 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -23,8 +23,7 @@ pub fn in_any_value_of_ty<'tcx>( ConstQualifs { has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty), needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty), - // FIXME(effects) - needs_non_const_drop: NeedsDrop::in_any_value_of_ty(cx, ty), + needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty), custom_eq: CustomEq::in_any_value_of_ty(cx, ty), tainted_by_errors, } @@ -155,12 +154,27 @@ impl Qualif for NeedsNonConstDrop { return false; } - // FIXME(effects) constness + // FIXME(effects): If `destruct` is not a `const_trait`, + // or effects are disabled in this crate, then give up. + let destruct_def_id = cx.tcx.require_lang_item(LangItem::Destruct, Some(cx.body.span)); + if cx.tcx.generics_of(destruct_def_id).host_effect_index.is_none() + || !cx.tcx.features().effects + { + return NeedsDrop::in_any_value_of_ty(cx, ty); + } + let obligation = Obligation::new( cx.tcx, ObligationCause::dummy_with_span(cx.body.span), cx.param_env, - ty::TraitRef::from_lang_item(cx.tcx, LangItem::Destruct, cx.body.span, [ty]), + ty::TraitRef::new( + cx.tcx, + destruct_def_id, + [ + ty::GenericArg::from(ty), + ty::GenericArg::from(cx.tcx.expected_const_effect_param_for_body(cx.def_id())), + ], + ), ); let infcx = cx.tcx.infer_ctxt().build(); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index a137f84b73824..a23922c778ff0 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -105,7 +105,7 @@ where fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool { match kind { mir::BorrowKind::Mut { .. } => true, - mir::BorrowKind::Shared | mir::BorrowKind::Shallow => { + mir::BorrowKind::Shared | mir::BorrowKind::Fake => { self.shared_borrow_allows_mutation(place) } } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 0590297663873..8b2ea2dc21dd1 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -188,7 +188,7 @@ impl<'a, 'tcx> std::ops::Deref for Validator<'a, 'tcx> { type Target = ConstCx<'a, 'tcx>; fn deref(&self) -> &Self::Target { - &self.ccx + self.ccx } } @@ -229,7 +229,7 @@ impl<'tcx> Validator<'_, 'tcx> { let statement = &self.body[loc.block].statements[loc.statement_index]; match &statement.kind { StatementKind::Assign(box (_, rhs)) => qualifs::in_rvalue::( - &self.ccx, + self.ccx, &mut |l| self.qualif_local::(l), rhs, ), @@ -246,7 +246,7 @@ impl<'tcx> Validator<'_, 'tcx> { match &terminator.kind { TerminatorKind::Call { .. } => { let return_ty = self.body.local_decls[local].ty; - Q::in_any_value_of_ty(&self.ccx, return_ty) + Q::in_any_value_of_ty(self.ccx, return_ty) } kind => { span_bug!(terminator.source_info.span, "{:?} not promotable", kind); @@ -456,7 +456,7 @@ impl<'tcx> Validator<'_, 'tcx> { match kind { // Reject these borrow types just to be safe. // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase. - BorrowKind::Shallow | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => { + BorrowKind::Fake | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => { return Err(Unpromotable); } @@ -864,6 +864,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { }; // Use the underlying local for this (necessarily interior) borrow. + debug_assert!(region.is_erased()); let ty = local_decls[place.local].ty; let span = statement.source_info.span; @@ -873,8 +874,6 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() }, ); - *region = tcx.lifetimes.re_erased; - let mut projection = vec![PlaceElem::Deref]; projection.extend(place.projection); place.projection = tcx.mk_place_elems(&projection); @@ -1024,36 +1023,3 @@ pub fn promote_candidates<'tcx>( promotions } - -/// This function returns `true` if the function being called in the array -/// repeat expression is a `const` function. -pub fn is_const_fn_in_array_repeat_expression<'tcx>( - ccx: &ConstCx<'_, 'tcx>, - place: &Place<'tcx>, - body: &Body<'tcx>, -) -> bool { - match place.as_local() { - // rule out cases such as: `let my_var = some_fn(); [my_var; N]` - Some(local) if body.local_decls[local].is_user_variable() => return false, - None => return false, - _ => {} - } - - for block in body.basic_blocks.iter() { - if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) = - &block.terminator - { - if let Operand::Constant(box ConstOperand { const_, .. }) = func { - if let ty::FnDef(def_id, _) = *const_.ty().kind() { - if destination == place { - if ccx.tcx.is_const_fn(def_id) { - return true; - } - } - } - } - } - } - - false -} diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 4d71f76366768..eaf4abf39b740 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -128,9 +128,9 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> { #[track_caller] fn fail(&self, location: Location, msg: impl AsRef) { let span = self.body.source_info(location).span; - // We use `delay_span_bug` as we might see broken MIR when other errors have already + // We use `span_delayed_bug` as we might see broken MIR when other errors have already // occurred. - self.tcx.sess.diagnostic().delay_span_bug( + self.tcx.sess.diagnostic().span_delayed_bug( span, format!( "broken MIR in {:?} ({}) at {:?}:\n{}", @@ -285,6 +285,12 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> { UnwindAction::Unreachable | UnwindAction::Terminate(UnwindTerminateReason::Abi) => (), } } + + fn is_critical_call_edge(&self, target: Option, unwind: UnwindAction) -> bool { + let Some(target) = target else { return false }; + matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate(_)) + && self.body.basic_blocks.predecessors()[target].len() > 1 + } } impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { @@ -425,6 +431,22 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } self.check_unwind_edge(location, *unwind); + // The code generation assumes that there are no critical call edges. The assumption + // is used to simplify inserting code that should be executed along the return edge + // from the call. FIXME(tmiasko): Since this is a strictly code generation concern, + // the code generation should be responsible for handling it. + if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Optimized) + && self.is_critical_call_edge(*target, *unwind) + { + self.fail( + location, + format!( + "encountered critical edge in `Call` terminator {:?}", + terminator.kind, + ), + ); + } + // The call destination place and Operand::Move place used as an argument might be // passed by a reference to the callee. Consequently they must be non-overlapping // and cannot be packed. Currently this simply checks for duplicate places. @@ -549,7 +571,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { fn visit_source_scope(&mut self, scope: SourceScope) { if self.body.source_scopes.get(scope).is_none() { - self.tcx.sess.diagnostic().delay_span_bug( + self.tcx.sess.diagnostic().span_delayed_bug( self.body.span, format!( "broken MIR in {:?} ({}):\ninvalid source scope {:?}", @@ -848,11 +870,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } match rvalue { Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {} - Rvalue::Ref(_, BorrowKind::Shallow, _) => { + Rvalue::Ref(_, BorrowKind::Fake, _) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, - "`Assign` statement with a `Shallow` borrow should have been removed in runtime MIR", + "`Assign` statement with a `Fake` borrow should have been removed in runtime MIR", ); } } diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 2701fdbbd77f7..4732783a12d95 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -10,8 +10,8 @@ bitflags = "1.2.1" elsa = "=1.7.1" ena = "0.14.2" indexmap = { version = "2.0.0" } -itertools = "0.10.1" -jobserver_crate = { version = "0.1.13", package = "jobserver" } +itertools = "0.11" +jobserver_crate = { version = "0.1.27", package = "jobserver" } libc = "0.2" measureme = "10.0.0" rustc-hash = "1.1.0" @@ -47,6 +47,9 @@ features = [ memmap2 = "0.2.1" # tidy-alphabetical-end +[target.'cfg(any(target_arch = "powerpc", target_arch = "mips"))'.dependencies] +portable-atomic = "1.5.1" + [features] # tidy-alphabetical-start rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "rustc-rayon", "rustc-rayon-core"] diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 5dd414cfd41fa..4b819e1cbd615 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -23,6 +23,7 @@ struct PreOrderFrame { } rustc_index::newtype_index! { + #[orderable] struct PreorderIndex {} } diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index cf9312ea8fb64..b54d75f7ed703 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -492,7 +492,7 @@ where let returned_walk = return_value.take().into_iter().map(|walk| (*successor_node, Some(walk))); - let successor_walk = successors.by_ref().map(|successor_node| { + let successor_walk = successors.map(|successor_node| { debug!(?node, ?successor_node); (successor_node, self.inspect_node(successor_node)) }); diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs index 09baa3095a4d4..412e33aaa6551 100644 --- a/compiler/rustc_data_structures/src/jobserver.rs +++ b/compiler/rustc_data_structures/src/jobserver.rs @@ -1,40 +1,78 @@ pub use jobserver_crate::Client; -use std::sync::LazyLock; - -// We can only call `from_env` once per process - -// Note that this is unsafe because it may misinterpret file descriptors -// on Unix as jobserver file descriptors. We hopefully execute this near -// the beginning of the process though to ensure we don't get false -// positives, or in other words we try to execute this before we open -// any file descriptors ourselves. -// -// Pick a "reasonable maximum" if we don't otherwise have -// a jobserver in our environment, capping out at 32 so we -// don't take everything down by hogging the process run queue. -// The fixed number is used to have deterministic compilation -// across machines. -// -// Also note that we stick this in a global because there could be -// multiple rustc instances in this process, and the jobserver is -// per-process. -static GLOBAL_CLIENT: LazyLock = LazyLock::new(|| unsafe { - Client::from_env().unwrap_or_else(|| { - let client = Client::new(32).expect("failed to create jobserver"); - // Acquire a token for the main thread which we can release later - client.acquire_raw().ok(); - client - }) + +use jobserver_crate::{FromEnv, FromEnvErrorKind}; + +use std::sync::{LazyLock, OnceLock}; + +// We can only call `from_env_ext` once per process + +// We stick this in a global because there could be multiple rustc instances +// in this process, and the jobserver is per-process. +static GLOBAL_CLIENT: LazyLock> = LazyLock::new(|| { + // Note that this is unsafe because it may misinterpret file descriptors + // on Unix as jobserver file descriptors. We hopefully execute this near + // the beginning of the process though to ensure we don't get false + // positives, or in other words we try to execute this before we open + // any file descriptors ourselves. + let FromEnv { client, var } = unsafe { Client::from_env_ext(true) }; + + let error = match client { + Ok(client) => return Ok(client), + Err(e) => e, + }; + + if matches!( + error.kind(), + FromEnvErrorKind::NoEnvVar | FromEnvErrorKind::NoJobserver | FromEnvErrorKind::Unsupported + ) { + return Ok(default_client()); + } + + // Environment specifies jobserver, but it looks incorrect. + // Safety: `error.kind()` should be `NoEnvVar` if `var == None`. + let (name, value) = var.unwrap(); + Err(format!( + "failed to connect to jobserver from environment variable `{name}={:?}`: {error}", + value + )) }); +// Create a new jobserver if there's no inherited one. +fn default_client() -> Client { + // Pick a "reasonable maximum" capping out at 32 + // so we don't take everything down by hogging the process run queue. + // The fixed number is used to have deterministic compilation across machines. + let client = Client::new(32).expect("failed to create jobserver"); + + // Acquire a token for the main thread which we can release later + client.acquire_raw().ok(); + + client +} + +static GLOBAL_CLIENT_CHECKED: OnceLock = OnceLock::new(); + +pub fn initialize_checked(report_warning: impl FnOnce(&'static str)) { + let client_checked = match &*GLOBAL_CLIENT { + Ok(client) => client.clone(), + Err(e) => { + report_warning(e); + default_client() + } + }; + GLOBAL_CLIENT_CHECKED.set(client_checked).ok(); +} + +const ACCESS_ERROR: &str = "jobserver check should have been called earlier"; + pub fn client() -> Client { - GLOBAL_CLIENT.clone() + GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).clone() } pub fn acquire_thread() { - GLOBAL_CLIENT.acquire_raw().ok(); + GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).acquire_raw().ok(); } pub fn release_thread() { - GLOBAL_CLIENT.release_raw().ok(); + GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).release_raw().ok(); } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 5d7f385c6e4a6..3ef87684fa5d7 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,12 +10,11 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::untranslatable_diagnostic)] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![doc(rust_logo)] #![feature(allocator_api)] #![feature(array_windows)] #![feature(auto_traits)] @@ -34,6 +33,7 @@ #![feature(never_type)] #![feature(ptr_alignment_type)] #![feature(rustc_attrs)] +#![feature(rustdoc_internals)] #![feature(strict_provenance)] #![feature(test)] #![feature(thread_id_value)] @@ -127,6 +127,9 @@ impl Drop for OnDrop { } } +/// This is a marker for a fatal compiler error used with `resume_unwind`. +pub struct FatalErrorMarker; + /// Turns a closure that takes an `&mut Formatter` into something that can be display-formatted. pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display { struct Printer { diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index a8c442377fbc2..266e54604a6b4 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -138,7 +138,6 @@ cfg_match! { [std::sync::atomic::AtomicUsize] [std::sync::atomic::AtomicU8] [std::sync::atomic::AtomicU32] - [std::sync::atomic::AtomicU64] [std::backtrace::Backtrace] [std::io::Error] [std::fs::File] @@ -148,6 +147,18 @@ cfg_match! { [crate::owned_slice::OwnedSlice] ); + // PowerPC and MIPS platforms with 32-bit pointers do not + // have AtomicU64 type. + #[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))] + already_sync!( + [std::sync::atomic::AtomicU64] + ); + + #[cfg(any(target_arch = "powerpc", target_arch = "mips"))] + already_sync!( + [portable_atomic::AtomicU64] + ); + macro_rules! impl_dyn_sync { ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => { $(unsafe impl<$($generics2)*> DynSync for $ty {})* diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 29516fffd6a62..162dbd234d676 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -50,7 +50,7 @@ impl Sharded { #[inline] pub fn get_shard_by_value(&self, _val: &K) -> &Lock { match self { - Self::Single(single) => &single, + Self::Single(single) => single, #[cfg(parallel_compiler)] Self::Shards(..) => self.get_shard_by_hash(make_hash(_val)), } @@ -64,7 +64,7 @@ impl Sharded { #[inline] pub fn get_shard_by_index(&self, _i: usize) -> &Lock { match self { - Self::Single(single) => &single, + Self::Single(single) => single, #[cfg(parallel_compiler)] Self::Shards(shards) => { // SAFETY: The index gets ANDed with the shard mask, ensuring it is always inbounds. @@ -79,7 +79,7 @@ impl Sharded { pub fn lock_shard_by_value(&self, _val: &K) -> LockGuard<'_, T> { match self { Self::Single(single) => { - // Syncronization is disabled so use the `lock_assume_no_sync` method optimized + // Synchronization is disabled so use the `lock_assume_no_sync` method optimized // for that case. // SAFETY: We know `is_dyn_thread_safe` was false when creating the lock thus @@ -102,7 +102,7 @@ impl Sharded { pub fn lock_shard_by_index(&self, _i: usize) -> LockGuard<'_, T> { match self { Self::Single(single) => { - // Syncronization is disabled so use the `lock_assume_no_sync` method optimized + // Synchronization is disabled so use the `lock_assume_no_sync` method optimized // for that case. // SAFETY: We know `is_dyn_thread_safe` was false when creating the lock thus @@ -111,7 +111,7 @@ impl Sharded { } #[cfg(parallel_compiler)] Self::Shards(shards) => { - // Syncronization is enabled so use the `lock_assume_sync` method optimized + // Synchronization is enabled so use the `lock_assume_sync` method optimized // for that case. // SAFETY (get_unchecked): The index gets ANDed with the shard mask, ensuring it is diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index f957734b04d92..43221d70e21cf 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -265,7 +265,15 @@ cfg_match! { pub use std::sync::OnceLock; - pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64}; + pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32}; + + // PowerPC and MIPS platforms with 32-bit pointers do not + // have AtomicU64 type. + #[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))] + pub use std::sync::atomic::AtomicU64; + + #[cfg(any(target_arch = "powerpc", target_arch = "mips"))] + pub use portable_atomic::AtomicU64; pub use std::sync::Arc as Lrc; pub use std::sync::Weak as Weak; diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs index 339aebbf81aae..040a8aa6b6380 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -38,7 +38,7 @@ mod maybe_sync { lock: &'a Lock, marker: PhantomData<&'a mut T>, - /// The syncronization mode of the lock. This is explicitly passed to let LLVM relate it + /// The synchronization mode of the lock. This is explicitly passed to let LLVM relate it /// to the original lock operation. mode: Mode, } @@ -142,7 +142,7 @@ mod maybe_sync { .then(|| LockGuard { lock: self, marker: PhantomData, mode }) } - /// This acquires the lock assuming syncronization is in a specific mode. + /// This acquires the lock assuming synchronization is in a specific mode. /// /// Safety /// This method must only be called with `Mode::Sync` if `might_be_dyn_thread_safe` was diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index 5695d839d3eb1..7783de57fba7f 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -3,6 +3,8 @@ #![allow(dead_code)] +use crate::sync::IntoDynSyncSend; +use crate::FatalErrorMarker; use parking_lot::Mutex; use std::any::Any; use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; @@ -18,14 +20,17 @@ pub use enabled::*; /// continuing with unwinding. It's also used for the non-parallel code to ensure error message /// output match the parallel compiler for testing purposes. pub struct ParallelGuard { - panic: Mutex>>, + panic: Mutex>>>, } impl ParallelGuard { pub fn run(&self, f: impl FnOnce() -> R) -> Option { catch_unwind(AssertUnwindSafe(f)) .map_err(|err| { - *self.panic.lock() = Some(err); + let mut panic = self.panic.lock(); + if panic.is_none() || !(*err).is::() { + *panic = Some(IntoDynSyncSend(err)); + } }) .ok() } @@ -37,7 +42,7 @@ impl ParallelGuard { pub fn parallel_guard(f: impl FnOnce(&ParallelGuard) -> R) -> R { let guard = ParallelGuard { panic: Mutex::new(None) }; let ret = f(&guard); - if let Some(panic) = guard.panic.into_inner() { + if let Some(IntoDynSyncSend(panic)) = guard.panic.into_inner() { resume_unwind(panic); } ret @@ -106,14 +111,20 @@ mod enabled { parallel!(impl $fblock [$block, $($c,)*] [$($rest),*]) }; (impl $fblock:block [$($blocks:expr,)*] []) => { - ::rustc_data_structures::sync::scope(|s| { - $(let block = rustc_data_structures::sync::FromDyn::from(|| $blocks); - s.spawn(move |_| block.into_inner()());)* - (|| $fblock)(); + $crate::sync::parallel_guard(|guard| { + $crate::sync::scope(|s| { + $( + let block = $crate::sync::FromDyn::from(|| $blocks); + s.spawn(move |_| { + guard.run(move || block.into_inner()()); + }); + )* + guard.run(|| $fblock); + }); }); }; ($fblock:block, $($blocks:block),*) => { - if rustc_data_structures::sync::is_dyn_thread_safe() { + if $crate::sync::is_dyn_thread_safe() { // Reverse the order of the later blocks since Rayon executes them in reverse order // when using a single thread. This ensures the execution order matches that // of a single threaded rustc. @@ -146,11 +157,13 @@ mod enabled { if mode::is_dyn_thread_safe() { let oper_a = FromDyn::from(oper_a); let oper_b = FromDyn::from(oper_b); - let (a, b) = rayon::join( - move || FromDyn::from(oper_a.into_inner()()), - move || FromDyn::from(oper_b.into_inner()()), - ); - (a.into_inner(), b.into_inner()) + let (a, b) = parallel_guard(|guard| { + rayon::join( + move || guard.run(move || FromDyn::from(oper_a.into_inner()())), + move || guard.run(move || FromDyn::from(oper_b.into_inner()())), + ) + }); + (a.unwrap().into_inner(), b.unwrap().into_inner()) } else { super::disabled::join(oper_a, oper_b) } diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index ffafdba13cea1..b34d3dd904400 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -1,6 +1,7 @@ use parking_lot::Mutex; use std::cell::Cell; use std::cell::OnceCell; +use std::num::NonZeroUsize; use std::ops::Deref; use std::ptr; use std::sync::Arc; @@ -30,7 +31,7 @@ impl RegistryId { } struct RegistryData { - thread_limit: usize, + thread_limit: NonZeroUsize, threads: Mutex, } @@ -60,7 +61,7 @@ thread_local! { impl Registry { /// Creates a registry which can hold up to `thread_limit` threads. - pub fn new(thread_limit: usize) -> Self { + pub fn new(thread_limit: NonZeroUsize) -> Self { Registry(Arc::new(RegistryData { thread_limit, threads: Mutex::new(0) })) } @@ -73,7 +74,7 @@ impl Registry { /// Panics if the thread limit is hit or if the thread already has an associated registry. pub fn register(&self) { let mut threads = self.0.threads.lock(); - if *threads < self.0.thread_limit { + if *threads < self.0.thread_limit.get() { REGISTRY.with(|registry| { if registry.get().is_some() { drop(threads); @@ -126,7 +127,9 @@ impl WorkerLocal { { let registry = Registry::current(); WorkerLocal { - locals: (0..registry.0.thread_limit).map(|i| CacheAligned(initial(i))).collect(), + locals: (0..registry.0.thread_limit.get()) + .map(|i| CacheAligned(initial(i))) + .collect(), registry, } } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 27f08fe7eefba..acd93b0b2a60f 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1,8 +1,8 @@ // This crate is intentionally empty and a re-export of `rustc_driver_impl` to allow the code in // `rustc_driver_impl` to be compiled in parallel with other crates. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] pub use rustc_driver_impl::*; diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index da7c2440faad4..f2a8c54b6d541 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -16,7 +16,6 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_error_codes = { path = "../rustc_error_codes" } -rustc_error_messages = { path = "../rustc_error_messages" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } @@ -43,6 +42,7 @@ rustc_privacy = { path = "../rustc_privacy" } rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } +rustc_smir ={ path = "../rustc_smir" } rustc_span = { path = "../rustc_span" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index ee4337754a9c3..1f60400b5132d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -5,15 +5,14 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] #![feature(decl_macro)] #![feature(lazy_cell)] #![feature(let_chains)] #![feature(panic_update_hook)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -28,19 +27,19 @@ use rustc_data_structures::profiling::{ use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; use rustc_errors::{markdown, ColorConfig}; -use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, PResult, SubdiagnosticMessage}; +use rustc_errors::{ErrorGuaranteed, Handler, PResult}; use rustc_feature::find_gated_cfg; -use rustc_fluent_macro::fluent_messages; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; -use rustc_lint::{unerased_lint_store, LintStore}; +use rustc_lint::unerased_lint_store; +use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths}; -use rustc_session::cstore::MetadataLoader; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; use rustc_session::{config, EarlyErrorHandler, Session}; +use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::FileLoader; use rustc_span::symbol::sym; use rustc_span::FileName; @@ -101,7 +100,7 @@ use crate::session_diagnostics::{ RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead, }; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start @@ -113,7 +112,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE, rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, - rustc_error_messages::DEFAULT_LOCALE_RESOURCE, rustc_errors::DEFAULT_LOCALE_RESOURCE, rustc_expand::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, @@ -292,7 +290,7 @@ fn run_compiler( >, using_internal_features: Arc, ) -> interface::Result<()> { - let mut early_error_handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let mut default_handler = EarlyErrorHandler::new(ErrorOutputType::default()); // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by @@ -304,14 +302,14 @@ fn run_compiler( // the compiler with @empty_file as argv[0] and no more arguments. let at_args = at_args.get(1..).unwrap_or_default(); - let args = args::arg_expand_all(&early_error_handler, at_args); + let args = args::arg_expand_all(&default_handler, at_args); - let Some(matches) = handle_options(&early_error_handler, &args) else { return Ok(()) }; + let Some(matches) = handle_options(&default_handler, &args) else { return Ok(()) }; - let sopts = config::build_session_options(&mut early_error_handler, &matches); + let sopts = config::build_session_options(&mut default_handler, &matches); if let Some(ref code) = matches.opt_str("explain") { - handle_explain(&early_error_handler, diagnostics_registry(), code, sopts.color); + handle_explain(&default_handler, diagnostics_registry(), code, sopts.color); return Ok(()); } @@ -337,71 +335,56 @@ fn run_compiler( expanded_args: args, }; - match make_input(&early_error_handler, &matches.free) { + let has_input = match make_input(&default_handler, &matches.free) { Err(reported) => return Err(reported), Ok(Some(input)) => { config.input = input; - - callbacks.config(&mut config); + true // has input: normal compilation } Ok(None) => match matches.free.len() { - 0 => { - callbacks.config(&mut config); - - early_error_handler.abort_if_errors(); - - interface::run_compiler(config, |compiler| { - let sopts = &compiler.session().opts; - let handler = EarlyErrorHandler::new(sopts.error_format); - - if sopts.describe_lints { - let mut lint_store = - rustc_lint::new_lint_store(compiler.session().enable_internal_lints()); - let registered_lints = - if let Some(register_lints) = compiler.register_lints() { - register_lints(compiler.session(), &mut lint_store); - true - } else { - false - }; - describe_lints(compiler.session(), &lint_store, registered_lints); - return; - } - let should_stop = print_crate_info( - &handler, - &**compiler.codegen_backend(), - compiler.session(), - false, - ); - - if should_stop == Compilation::Stop { - return; - } - handler.early_error("no input filename given") - }); - return Ok(()); - } + 0 => false, // no input: we will exit early 1 => panic!("make_input should have provided valid inputs"), - _ => early_error_handler.early_error(format!( + _ => default_handler.early_error(format!( "multiple input filenames provided (first two filenames are `{}` and `{}`)", matches.free[0], matches.free[1], )), }, }; - early_error_handler.abort_if_errors(); + callbacks.config(&mut config); + + default_handler.abort_if_errors(); + drop(default_handler); interface::run_compiler(config, |compiler| { - let sess = compiler.session(); + let sess = &compiler.sess; + let codegen_backend = &*compiler.codegen_backend; + + // This implements `-Whelp`. It should be handled very early, like + // `--help`/`-Zhelp`/`-Chelp`. This is the earliest it can run, because + // it must happen after lints are registered, during session creation. + if sess.opts.describe_lints { + describe_lints(sess); + return sess.compile_status(); + } + let handler = EarlyErrorHandler::new(sess.opts.error_format); - let should_stop = print_crate_info(&handler, &**compiler.codegen_backend(), sess, true) - .and_then(|| { - list_metadata(&handler, sess, &*compiler.codegen_backend().metadata_loader()) - }) - .and_then(|| try_process_rlink(sess, compiler)); + if print_crate_info(&handler, codegen_backend, sess, has_input) == Compilation::Stop { + return sess.compile_status(); + } + + if !has_input { + handler.early_error("no input filename given"); // this is fatal + } + + if !sess.opts.unstable_opts.ls.is_empty() { + list_metadata(&handler, sess, &*codegen_backend.metadata_loader()); + return sess.compile_status(); + } - if should_stop == Compilation::Stop { + if sess.opts.unstable_opts.link_only { + process_rlink(sess, compiler); return sess.compile_status(); } @@ -417,12 +400,14 @@ fn run_compiler( Ok(()) })?; - // Make sure the `output_filenames` query is run for its side - // effects of writing the dep-info and reporting errors. - queries.global_ctxt()?.enter(|tcx| tcx.output_filenames(())); + queries.write_dep_info()?; } else { - let krate = queries.parse()?.steal(); - pretty::print(sess, *ppm, pretty::PrintExtra::AfterParsing { krate }); + let krate = queries.parse()?; + pretty::print( + sess, + *ppm, + pretty::PrintExtra::AfterParsing { krate: &*krate.borrow() }, + ); } trace!("finished pretty-printing"); return early_exit(); @@ -436,13 +421,6 @@ fn run_compiler( return early_exit(); } - if sess.opts.describe_lints { - queries - .global_ctxt()? - .enter(|tcx| describe_lints(sess, unerased_lint_store(tcx), true)); - return early_exit(); - } - // Make sure name resolution and macro expansion is run. queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering(())); @@ -450,9 +428,7 @@ fn run_compiler( return early_exit(); } - // Make sure the `output_filenames` query is run for its side - // effects of writing the dep-info and reporting errors. - queries.global_ctxt()?.enter(|tcx| tcx.output_filenames(())); + queries.write_dep_info()?; if sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1 @@ -470,30 +446,28 @@ fn run_compiler( return early_exit(); } - let ongoing_codegen = queries.ongoing_codegen()?; + let linker = queries.codegen_and_build_linker()?; + // This must run after monomorphization so that all generic types + // have been instantiated. if sess.opts.unstable_opts.print_type_sizes { sess.code_stats.print_type_sizes(); } if sess.opts.unstable_opts.print_vtable_sizes { - let crate_name = - compiler.session().opts.crate_name.as_deref().unwrap_or(""); + let crate_name = queries.global_ctxt()?.enter(|tcx| tcx.crate_name(LOCAL_CRATE)); sess.code_stats.print_vtable_sizes(crate_name); } - let linker = queries.linker(ongoing_codegen)?; Ok(Some(linker)) })?; + // Linking is done outside the `compiler.enter()` so that the + // `GlobalCtxt` within `Queries` can be freed as early as possible. if let Some(linker) = linker { let _timer = sess.timer("link"); - linker.link()? - } - - if sess.opts.unstable_opts.perf_stats { - sess.print_perf_stats(); + linker.link(sess, codegen_backend)? } if sess.opts.unstable_opts.print_fuel.is_some() { @@ -562,15 +536,6 @@ pub enum Compilation { Continue, } -impl Compilation { - fn and_then Compilation>(self, next: F) -> Compilation { - match self { - Compilation::Stop => Compilation::Stop, - Compilation::Continue => next(), - } - } -} - fn handle_explain(handler: &EarlyErrorHandler, registry: Registry, code: &str, color: ColorConfig) { let upper_cased_code = code.to_ascii_uppercase(); let normalised = @@ -675,44 +640,33 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { } } -fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation { - if sess.opts.unstable_opts.link_only { - if let Input::File(file) = &sess.io.input { - let outputs = compiler.build_output_filenames(sess, &[]); - let rlink_data = fs::read(file).unwrap_or_else(|err| { - sess.emit_fatal(RlinkUnableToRead { err }); - }); - let codegen_results = match CodegenResults::deserialize_rlink(sess, rlink_data) { - Ok(codegen) => codegen, - Err(err) => { - match err { - CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType), - CodegenErrors::EmptyVersionNumber => { - sess.emit_fatal(RLinkEmptyVersionNumber) - } - CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => { - sess.emit_fatal(RLinkEncodingVersionMismatch { - version_array, - rlink_version, - }) - } - CodegenErrors::RustcVersionMismatch { rustc_version } => { - sess.emit_fatal(RLinkRustcVersionMismatch { - rustc_version, - current_version: sess.cfg_version, - }) - } - }; - } - }; - let result = compiler.codegen_backend().link(sess, codegen_results, &outputs); - abort_on_err(result, sess); - } else { - sess.emit_fatal(RlinkNotAFile {}) - } - Compilation::Stop +fn process_rlink(sess: &Session, compiler: &interface::Compiler) { + assert!(sess.opts.unstable_opts.link_only); + if let Input::File(file) = &sess.io.input { + let rlink_data = fs::read(file).unwrap_or_else(|err| { + sess.emit_fatal(RlinkUnableToRead { err }); + }); + let (codegen_results, outputs) = match CodegenResults::deserialize_rlink(sess, rlink_data) { + Ok((codegen, outputs)) => (codegen, outputs), + Err(err) => { + match err { + CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType), + CodegenErrors::EmptyVersionNumber => sess.emit_fatal(RLinkEmptyVersionNumber), + CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => sess + .emit_fatal(RLinkEncodingVersionMismatch { version_array, rlink_version }), + CodegenErrors::RustcVersionMismatch { rustc_version } => { + sess.emit_fatal(RLinkRustcVersionMismatch { + rustc_version, + current_version: sess.cfg_version, + }) + } + }; + } + }; + let result = compiler.codegen_backend.link(sess, codegen_results, &outputs); + abort_on_err(result, sess); } else { - Compilation::Continue + sess.emit_fatal(RlinkNotAFile {}) } } @@ -720,25 +674,25 @@ fn list_metadata( handler: &EarlyErrorHandler, sess: &Session, metadata_loader: &dyn MetadataLoader, -) -> Compilation { - let ls_kinds = &sess.opts.unstable_opts.ls; - if !ls_kinds.is_empty() { - match sess.io.input { - Input::File(ref ifile) => { - let path = &(*ifile); - let mut v = Vec::new(); - locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v, ls_kinds) - .unwrap(); - safe_println!("{}", String::from_utf8(v).unwrap()); - } - Input::Str { .. } => { - handler.early_error("cannot list metadata for stdin"); - } +) { + match sess.io.input { + Input::File(ref ifile) => { + let path = &(*ifile); + let mut v = Vec::new(); + locator::list_file_metadata( + &sess.target, + path, + metadata_loader, + &mut v, + &sess.opts.unstable_opts.ls, + ) + .unwrap(); + safe_println!("{}", String::from_utf8(v).unwrap()); + } + Input::Str { .. } => { + handler.early_error("cannot list metadata for stdin"); } - return Compilation::Stop; } - - Compilation::Continue } fn print_crate_info( @@ -991,7 +945,7 @@ the command line flag directly. } /// Write to stdout lint command options, together with a list of all available lints -pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_lints: bool) { +pub fn describe_lints(sess: &Session) { safe_println!( " Available lint options: @@ -1017,6 +971,7 @@ Available lint options: lints } + let lint_store = unerased_lint_store(sess); let (loaded, builtin): (Vec<_>, _) = lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_loaded); let loaded = sort_lints(sess, loaded); @@ -1094,7 +1049,7 @@ Available lint options: print_lint_groups(builtin_groups, true); - match (loaded_lints, loaded.len(), loaded_groups.len()) { + match (sess.registered_lints, loaded.len(), loaded_groups.len()) { (false, 0, _) | (false, _, 0) => { safe_println!("Lint tools like Clippy can load additional lints and lint groups."); } @@ -1520,14 +1475,14 @@ fn report_ice( /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. pub fn init_rustc_env_logger(handler: &EarlyErrorHandler) { - init_env_logger(handler, "RUSTC_LOG"); + init_logger(handler, rustc_log::LoggerConfig::from_env("RUSTC_LOG")); } /// This allows tools to enable rust logging without having to magically match rustc's -/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var -/// other than `RUSTC_LOG`. -pub fn init_env_logger(handler: &EarlyErrorHandler, env: &str) { - if let Err(error) = rustc_log::init_env_logger(env) { +/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose +/// the values directly rather than having to set an environment variable. +pub fn init_logger(handler: &EarlyErrorHandler, cfg: rustc_log::LoggerConfig) { + if let Err(error) = rustc_log::init_logger(cfg) { handler.early_error(error.to_string()); } } diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 8c6fee8301301..7cd63bc6422c3 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -9,6 +9,7 @@ use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty}; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::{OutFileName, PpHirMode, PpMode, PpSourceMode}; use rustc_session::Session; +use rustc_smir::rustc_internal::pretty::write_smir_pretty; use rustc_span::symbol::Ident; use rustc_span::FileName; @@ -217,7 +218,7 @@ fn write_or_print(out: &str, sess: &Session) { // Extra data for pretty-printing, the form of which depends on what kind of // pretty-printing we are doing. pub enum PrintExtra<'tcx> { - AfterParsing { krate: ast::Crate }, + AfterParsing { krate: &'tcx ast::Crate }, NeedsAstMap { tcx: TyCtxt<'tcx> }, } @@ -325,6 +326,11 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { write_mir_graphviz(ex.tcx(), None, &mut out).unwrap(); String::from_utf8(out).unwrap() } + StableMir => { + let mut out = Vec::new(); + write_smir_pretty(ex.tcx(), &mut out).unwrap(); + String::from_utf8(out).unwrap() + } ThirTree => { let tcx = ex.tcx(); let mut out = String::new(); diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 6680e8875c3e3..1028d43f9c5ba 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -653,3 +653,4 @@ E0795: include_str!("./error_codes/E0795.md"), // E0721, // `await` keyword // E0723, // unstable feature in `const` context // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. +// E0744, // merged into E0728 diff --git a/compiler/rustc_error_codes/src/error_codes/E0744.md b/compiler/rustc_error_codes/src/error_codes/E0744.md index 9a8ef3b840dff..e56c45db1766e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0744.md +++ b/compiler/rustc_error_codes/src/error_codes/E0744.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + An unsupported expression was used inside a const context. Erroneous code example: -```compile_fail,edition2018,E0744 +```ignore (removed error code) const _: i32 = { async { 0 }.await }; diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md index 8b4b2dc87fd71..20f51441c2911 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0795.md +++ b/compiler/rustc_error_codes/src/error_codes/E0795.md @@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro. Erroneous code example: ```compile_fail,E0795 -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] let x = std::mem::offset_of!(Option, Some); ``` @@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option` can be found by specifying the field name `0`: ``` -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] let x: usize = std::mem::offset_of!(Option, Some.0); ``` diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 81ad661286e5d..dd2818116368b 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -1,6 +1,6 @@ -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![deny(rustdoc::invalid_codeblock_attributes)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index 1969feed48ff7..5b6b8b3f183f4 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -13,7 +13,6 @@ icu_provider_adapters = "1.2" intl-memoizer = "0.5.1" rustc_baked_icu_data = { path = "../rustc_baked_icu_data" } rustc_data_structures = { path = "../rustc_data_structures" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_error_messages/messages.ftl b/compiler/rustc_error_messages/messages.ftl deleted file mode 100644 index e629237444822..0000000000000 --- a/compiler/rustc_error_messages/messages.ftl +++ /dev/null @@ -1 +0,0 @@ -# satisfy tidy lint by having a line in this file diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 6249c1e79613a..fc544c31e8930 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -1,5 +1,5 @@ -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(let_chains)] #![feature(lazy_cell)] #![feature(rustc_attrs)] @@ -15,7 +15,6 @@ use fluent_bundle::FluentResource; use fluent_syntax::parser::ParserError; use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; -use rustc_fluent_macro::fluent_messages; use rustc_macros::{Decodable, Encodable}; use rustc_span::Span; use std::borrow::Cow; @@ -38,8 +37,6 @@ use intl_memoizer::IntlLangMemoizer; pub use fluent_bundle::{self, types::FluentType, FluentArgs, FluentError, FluentValue}; pub use unic_langid::{langid, LanguageIdentifier}; -fluent_messages! { "../messages.ftl" } - pub type FluentBundle = IntoDynSyncSend>; diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 203e529120b3e..da266bf9c63e4 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -138,7 +138,7 @@ impl AnnotateSnippetEmitterWriter { let message = self.translate_messages(messages, args); if let Some(source_map) = &self.source_map { // Make sure our primary file comes first - let primary_lo = if let Some(ref primary_span) = msp.primary_span().as_ref() { + let primary_lo = if let Some(primary_span) = msp.primary_span().as_ref() { if primary_span.is_dummy() { // FIXME(#59346): Not sure when this is the case and what // should be done if it happens @@ -203,7 +203,7 @@ impl AnnotateSnippetEmitterWriter { Slice { source, line_start: *line_index, - origin: Some(&file_name), + origin: Some(file_name), // FIXME(#59346): Not really sure when `fold` should be true or false fold: false, annotations: annotations diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 470f318eb33e3..6aaf4a0f5cff2 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -239,7 +239,7 @@ impl Diagnostic { } #[track_caller] - pub fn new_with_code>( + pub(crate) fn new_with_code>( level: Level, code: Option, message: M, @@ -281,7 +281,7 @@ impl Diagnostic { } } - pub fn update_unstable_expectation_id( + pub(crate) fn update_unstable_expectation_id( &mut self, unstable_to_stable: &FxHashMap, ) { @@ -307,14 +307,14 @@ impl Diagnostic { } /// Indicates whether this diagnostic should show up in cargo's future breakage report. - pub fn has_future_breakage(&self) -> bool { + pub(crate) fn has_future_breakage(&self) -> bool { match self.code { Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage, _ => false, } } - pub fn is_force_warn(&self) -> bool { + pub(crate) fn is_force_warn(&self) -> bool { match self.code { Some(DiagnosticId::Lint { is_force_warn, .. }) => is_force_warn, _ => false, @@ -391,29 +391,6 @@ impl Diagnostic { self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"") } - pub fn note_unsuccessful_coercion( - &mut self, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - ) -> &mut Self { - let mut msg: Vec<_> = - vec![(Cow::from("required when trying to coerce from type `"), Style::NoStyle)]; - msg.extend(expected.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle), - StringPart::Highlighted(ref s) => (Cow::from(s.clone()), Style::Highlight), - })); - msg.push((Cow::from("` to type '"), Style::NoStyle)); - msg.extend(found.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle), - StringPart::Highlighted(ref s) => (Cow::from(s.clone()), Style::Highlight), - })); - msg.push((Cow::from("`"), Style::NoStyle)); - - // For now, just attach these as notes - self.highlighted_note(msg); - self - } - pub fn note_expected_found_extra( &mut self, expected_label: &dyn fmt::Display, @@ -475,7 +452,7 @@ impl Diagnostic { self } - pub fn highlighted_note>( + fn highlighted_note>( &mut self, msg: Vec<(M, Style)>, ) -> &mut Self { @@ -572,14 +549,6 @@ impl Diagnostic { self } - /// Clear any existing suggestions. - pub fn clear_suggestions(&mut self) -> &mut Self { - if let Ok(suggestions) = &mut self.suggestions { - suggestions.clear(); - } - self - } - /// Helper for pushing to `self.suggestions`, if available (not disable). fn push_suggestion(&mut self, suggestion: CodeSuggestion) { if let Ok(suggestions) = &mut self.suggestions { @@ -777,17 +746,15 @@ impl Diagnostic { applicability: Applicability, style: SuggestionStyle, ) -> &mut Self { - let mut suggestions: Vec<_> = suggestions.into_iter().collect(); - suggestions.sort(); - - debug_assert!( - !(sp.is_empty() && suggestions.iter().any(|suggestion| suggestion.is_empty())), - "Span must not be empty and have no suggestion" - ); - let substitutions = suggestions .into_iter() - .map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] }) + .map(|snippet| { + debug_assert!( + !(sp.is_empty() && snippet.is_empty()), + "Span must not be empty and have no suggestion" + ); + Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] } + }) .collect(); self.push_suggestion(CodeSuggestion { substitutions, @@ -994,7 +961,7 @@ impl Diagnostic { /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by /// combining it with the primary message of the diagnostic (if translatable, otherwise it just /// passes the user's string along). - pub(crate) fn subdiagnostic_message_to_diagnostic_message( + fn subdiagnostic_message_to_diagnostic_message( &self, attr: impl Into, ) -> DiagnosticMessage { diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 85acf8ab5aaef..b8bd86a72e4df 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -18,18 +18,18 @@ use std::thread::panicking; /// Trait implemented by error types. This should not be implemented manually. Instead, use /// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic]. #[rustc_diagnostic_item = "IntoDiagnostic"] -pub trait IntoDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> { +pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> { /// Write out as a diagnostic out of `Handler`. #[must_use] - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>; + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G>; } -impl<'a, T, E> IntoDiagnostic<'a, E> for Spanned +impl<'a, T, G> IntoDiagnostic<'a, G> for Spanned where - T: IntoDiagnostic<'a, E>, - E: EmissionGuarantee, + T: IntoDiagnostic<'a, G>, + G: EmissionGuarantee, { - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, E> { + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> { let mut diag = self.node.into_diagnostic(handler); diag.set_span(self.span); diag @@ -116,26 +116,6 @@ pub trait EmissionGuarantee: Sized { } impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`Handler`]. - #[track_caller] - pub(crate) fn new_guaranteeing_error>( - handler: &'a Handler, - message: M, - ) -> Self { - Self { - inner: DiagnosticBuilderInner { - state: DiagnosticBuilderState::Emittable(handler), - diagnostic: Box::new(Diagnostic::new_with_code( - Level::Error { lint: false }, - None, - message, - )), - }, - _marker: PhantomData, - } - } - /// Discard the guarantee `.emit()` would return, in favor of having the /// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there /// is a common codepath handling both errors and warnings. @@ -189,35 +169,7 @@ impl EmissionGuarantee for ErrorGuaranteed { handler: &Handler, msg: impl Into, ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new_guaranteeing_error(handler, msg) - } -} - -impl<'a> DiagnosticBuilder<'a, ()> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`Handler`]. - #[track_caller] - pub(crate) fn new>( - handler: &'a Handler, - level: Level, - message: M, - ) -> Self { - let diagnostic = Diagnostic::new_with_code(level, None, message); - Self::new_diagnostic(handler, diagnostic) - } - - /// Creates a new `DiagnosticBuilder` with an already constructed - /// diagnostic. - #[track_caller] - pub(crate) fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> Self { - debug!("Created new diagnostic"); - Self { - inner: DiagnosticBuilderInner { - state: DiagnosticBuilderState::Emittable(handler), - diagnostic: Box::new(diagnostic), - }, - _marker: PhantomData, - } + DiagnosticBuilder::new(handler, Level::Error { lint: false }, msg) } } @@ -249,28 +201,6 @@ impl EmissionGuarantee for () { #[derive(Copy, Clone)] pub struct Noted; -impl<'a> DiagnosticBuilder<'a, Noted> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`Handler`]. - pub(crate) fn new_note(handler: &'a Handler, message: impl Into) -> Self { - let diagnostic = Diagnostic::new_with_code(Level::Note, None, message); - Self::new_diagnostic_note(handler, diagnostic) - } - - /// Creates a new `DiagnosticBuilder` with an already constructed - /// diagnostic. - pub(crate) fn new_diagnostic_note(handler: &'a Handler, diagnostic: Diagnostic) -> Self { - debug!("Created new diagnostic"); - Self { - inner: DiagnosticBuilderInner { - state: DiagnosticBuilderState::Emittable(handler), - diagnostic: Box::new(diagnostic), - }, - _marker: PhantomData, - } - } -} - impl EmissionGuarantee for Noted { fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { match db.inner.state { @@ -290,7 +220,7 @@ impl EmissionGuarantee for Noted { handler: &Handler, msg: impl Into, ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new_note(handler, msg) + DiagnosticBuilder::new(handler, Level::Note, msg) } } @@ -299,29 +229,6 @@ impl EmissionGuarantee for Noted { #[derive(Copy, Clone)] pub struct Bug; -impl<'a> DiagnosticBuilder<'a, Bug> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`Handler`]. - #[track_caller] - pub(crate) fn new_bug(handler: &'a Handler, message: impl Into) -> Self { - let diagnostic = Diagnostic::new_with_code(Level::Bug, None, message); - Self::new_diagnostic_bug(handler, diagnostic) - } - - /// Creates a new `DiagnosticBuilder` with an already constructed - /// diagnostic. - pub(crate) fn new_diagnostic_bug(handler: &'a Handler, diagnostic: Diagnostic) -> Self { - debug!("Created new diagnostic bug"); - Self { - inner: DiagnosticBuilderInner { - state: DiagnosticBuilderState::Emittable(handler), - diagnostic: Box::new(diagnostic), - }, - _marker: PhantomData, - } - } -} - impl EmissionGuarantee for Bug { fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { match db.inner.state { @@ -342,30 +249,7 @@ impl EmissionGuarantee for Bug { handler: &Handler, msg: impl Into, ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new_bug(handler, msg) - } -} - -impl<'a> DiagnosticBuilder<'a, !> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`Handler`]. - #[track_caller] - pub(crate) fn new_fatal(handler: &'a Handler, message: impl Into) -> Self { - let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message); - Self::new_diagnostic_fatal(handler, diagnostic) - } - - /// Creates a new `DiagnosticBuilder` with an already constructed - /// diagnostic. - pub(crate) fn new_diagnostic_fatal(handler: &'a Handler, diagnostic: Diagnostic) -> Self { - debug!("Created new diagnostic"); - Self { - inner: DiagnosticBuilderInner { - state: DiagnosticBuilderState::Emittable(handler), - diagnostic: Box::new(diagnostic), - }, - _marker: PhantomData, - } + DiagnosticBuilder::new(handler, Level::Bug, msg) } } @@ -389,36 +273,7 @@ impl EmissionGuarantee for ! { handler: &Handler, msg: impl Into, ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new_fatal(handler, msg) - } -} - -impl<'a> DiagnosticBuilder<'a, rustc_span::fatal_error::FatalError> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`Handler`]. - #[track_caller] - pub(crate) fn new_almost_fatal( - handler: &'a Handler, - message: impl Into, - ) -> Self { - let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message); - Self::new_diagnostic_almost_fatal(handler, diagnostic) - } - - /// Creates a new `DiagnosticBuilder` with an already constructed - /// diagnostic. - pub(crate) fn new_diagnostic_almost_fatal( - handler: &'a Handler, - diagnostic: Diagnostic, - ) -> Self { - debug!("Created new diagnostic"); - Self { - inner: DiagnosticBuilderInner { - state: DiagnosticBuilderState::Emittable(handler), - diagnostic: Box::new(diagnostic), - }, - _marker: PhantomData, - } + DiagnosticBuilder::new(handler, Level::Fatal, msg) } } @@ -442,7 +297,7 @@ impl EmissionGuarantee for rustc_span::fatal_error::FatalError { handler: &Handler, msg: impl Into, ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new_almost_fatal(handler, msg) + DiagnosticBuilder::new(handler, Level::Fatal, msg) } } @@ -484,6 +339,32 @@ impl DerefMut for DiagnosticBuilder<'_, G> { } impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { + /// Convenience function for internal use, clients should use one of the + /// `struct_*` methods on [`Handler`]. + #[track_caller] + pub(crate) fn new>( + handler: &'a Handler, + level: Level, + message: M, + ) -> Self { + let diagnostic = Diagnostic::new(level, message); + Self::new_diagnostic(handler, diagnostic) + } + + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + #[track_caller] + pub(crate) fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> Self { + debug!("Created new diagnostic"); + Self { + inner: DiagnosticBuilderInner { + state: DiagnosticBuilderState::Emittable(handler), + diagnostic: Box::new(diagnostic), + }, + _marker: PhantomData, + } + } + /// Emit the diagnostic. #[track_caller] pub fn emit(&mut self) -> G { @@ -634,12 +515,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { found_extra: &dyn fmt::Display, ) -> &mut Self); - forward!(pub fn note_unsuccessful_coercion( - &mut self, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - ) -> &mut Self); - forward!(pub fn note(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn note_once(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn span_note( @@ -668,7 +543,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { forward!(pub fn set_is_lint(&mut self,) -> &mut Self); forward!(pub fn disable_suggestions(&mut self,) -> &mut Self); - forward!(pub fn clear_suggestions(&mut self,) -> &mut Self); forward!(pub fn multipart_suggestion( &mut self, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6d95fbcfad00d..ba9cd02a9ece6 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1297,7 +1297,7 @@ impl EmitterWriter { buffer.append(line_number, line, style_or_override(*style, override_style)); } } else { - buffer.append(line_number, &text, style_or_override(*style, override_style)); + buffer.append(line_number, text, style_or_override(*style, override_style)); } } } @@ -1931,7 +1931,7 @@ impl EmitterWriter { self.draw_code_line( &mut buffer, &mut row_num, - &highlight_parts, + highlight_parts, line_pos + line_start, line, show_code_change, @@ -2338,7 +2338,7 @@ impl FileWithAnnotatedLines { let mut output = vec![]; let mut multiline_annotations = vec![]; - if let Some(ref sm) = emitter.source_map() { + if let Some(sm) = emitter.source_map() { for SpanLabel { span, is_primary, label } in msp.span_labels() { // If we don't have a useful span, pick the primary span if that exists. // Worst case we'll just print an error at the top of the main file. @@ -2362,11 +2362,7 @@ impl FileWithAnnotatedLines { let label = label.as_ref().map(|m| { normalize_whitespace( - &emitter - .translate_message(m, &args) - .map_err(Report::new) - .unwrap() - .to_string(), + &emitter.translate_message(m, args).map_err(Report::new).unwrap(), ) }); diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 0cb75c71b7346..aa3749334d97d 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -145,6 +145,25 @@ impl JsonEmitter { pub fn ignored_directories_in_source_blocks(self, value: Vec) -> Self { Self { ignored_directories_in_source_blocks: value, ..self } } + + fn emit(&mut self, val: EmitTyped<'_>) -> io::Result<()> { + if self.pretty { + serde_json::to_writer_pretty(&mut *self.dst, &val)? + } else { + serde_json::to_writer(&mut *self.dst, &val)? + }; + self.dst.write_all(b"\n")?; + self.dst.flush() + } +} + +#[derive(Serialize)] +#[serde(tag = "$message_type", rename_all = "snake_case")] +enum EmitTyped<'a> { + Diagnostic(Diagnostic), + Artifact(ArtifactNotification<'a>), + FutureIncompat(FutureIncompatReport<'a>), + UnusedExtern(UnusedExterns<'a, 'a, 'a>), } impl Translate for JsonEmitter { @@ -160,12 +179,7 @@ impl Translate for JsonEmitter { impl Emitter for JsonEmitter { fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) { let data = Diagnostic::from_errors_diagnostic(diag, self); - let result = if self.pretty { - writeln!(&mut self.dst, "{}", serde_json::to_string_pretty(&data).unwrap()) - } else { - writeln!(&mut self.dst, "{}", serde_json::to_string(&data).unwrap()) - } - .and_then(|_| self.dst.flush()); + let result = self.emit(EmitTyped::Diagnostic(data)); if let Err(e) = result { panic!("failed to print diagnostics: {e:?}"); } @@ -173,34 +187,28 @@ impl Emitter for JsonEmitter { fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { let data = ArtifactNotification { artifact: path, emit: artifact_type }; - let result = if self.pretty { - writeln!(&mut self.dst, "{}", serde_json::to_string_pretty(&data).unwrap()) - } else { - writeln!(&mut self.dst, "{}", serde_json::to_string(&data).unwrap()) - } - .and_then(|_| self.dst.flush()); + let result = self.emit(EmitTyped::Artifact(data)); if let Err(e) = result { panic!("failed to print notification: {e:?}"); } } fn emit_future_breakage_report(&mut self, diags: Vec) { - let data: Vec = diags + let data: Vec> = diags .into_iter() .map(|mut diag| { if diag.level == crate::Level::Allow { diag.level = crate::Level::Warning(None); } - FutureBreakageItem { diagnostic: Diagnostic::from_errors_diagnostic(&diag, self) } + FutureBreakageItem { + diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( + &diag, self, + )), + } }) .collect(); let report = FutureIncompatReport { future_incompat_report: data }; - let result = if self.pretty { - writeln!(&mut self.dst, "{}", serde_json::to_string_pretty(&report).unwrap()) - } else { - writeln!(&mut self.dst, "{}", serde_json::to_string(&report).unwrap()) - } - .and_then(|_| self.dst.flush()); + let result = self.emit(EmitTyped::FutureIncompat(report)); if let Err(e) = result { panic!("failed to print future breakage report: {e:?}"); } @@ -209,12 +217,7 @@ impl Emitter for JsonEmitter { fn emit_unused_externs(&mut self, lint_level: rustc_lint_defs::Level, unused_externs: &[&str]) { let lint_level = lint_level.as_str(); let data = UnusedExterns { lint_level, unused_extern_names: unused_externs }; - let result = if self.pretty { - writeln!(&mut self.dst, "{}", serde_json::to_string_pretty(&data).unwrap()) - } else { - writeln!(&mut self.dst, "{}", serde_json::to_string(&data).unwrap()) - } - .and_then(|_| self.dst.flush()); + let result = self.emit(EmitTyped::UnusedExtern(data)); if let Err(e) = result { panic!("failed to print unused externs: {e:?}"); } @@ -313,13 +316,15 @@ struct ArtifactNotification<'a> { } #[derive(Serialize)] -struct FutureBreakageItem { - diagnostic: Diagnostic, +struct FutureBreakageItem<'a> { + // Always EmitTyped::Diagnostic, but we want to make sure it gets serialized + // with "$message_type". + diagnostic: EmitTyped<'a>, } #[derive(Serialize)] -struct FutureIncompatReport { - future_incompat_report: Vec, +struct FutureIncompatReport<'a> { + future_incompat_report: Vec>, } // NOTE: Keep this in sync with the equivalent structs in rustdoc's diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index dd462cc64865f..daa8a7706eb47 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -3,14 +3,13 @@ //! This module contains the code for creating and emitting diagnostics. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(array_windows)] #![feature(extract_if)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(never_type)] -#![feature(result_option_inspect)] #![feature(rustc_attrs)] #![feature(yeet_expr)] #![feature(try_blocks)] @@ -42,7 +41,6 @@ pub use rustc_error_messages::{ fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, }; -use rustc_fluent_macro::fluent_messages; pub use rustc_lint_defs::{pluralize, Applicability}; use rustc_span::source_map::SourceMap; pub use rustc_span::ErrorGuaranteed; @@ -83,7 +81,7 @@ pub use snippet::Style; pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>; pub type PResult<'a, T> = Result>; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. // (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.) @@ -433,10 +431,10 @@ struct HandlerInner { warn_count: usize, deduplicated_err_count: usize, emitter: Box, - delayed_span_bugs: Vec, - delayed_good_path_bugs: Vec, + span_delayed_bugs: Vec, + good_path_delayed_bugs: Vec, /// This flag indicates that an expected diagnostic was emitted and suppressed. - /// This is used for the `delayed_good_path_bugs` check. + /// This is used for the `good_path_delayed_bugs` check. suppressed_expected_diag: bool, /// This set contains the `DiagnosticId` of all emitted diagnostics to avoid @@ -530,7 +528,7 @@ pub struct HandlerFlags { /// If true, immediately emit diagnostics that would otherwise be buffered. /// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`) pub dont_buffer_diagnostics: bool, - /// If true, immediately print bugs registered with `delay_span_bug`. + /// If true, immediately print bugs registered with `span_delayed_bug`. /// (rustc: see `-Z report-delayed-bugs`) pub report_delayed_bugs: bool, /// Show macro backtraces. @@ -547,20 +545,21 @@ impl Drop for HandlerInner { self.emit_stashed_diagnostics(); if !self.has_errors() { - let bugs = std::mem::replace(&mut self.delayed_span_bugs, Vec::new()); - self.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued"); + let bugs = std::mem::replace(&mut self.span_delayed_bugs, Vec::new()); + self.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued"); } - // FIXME(eddyb) this explains what `delayed_good_path_bugs` are! - // They're `delayed_span_bugs` but for "require some diagnostic happened" + // FIXME(eddyb) this explains what `good_path_delayed_bugs` are! + // They're `span_delayed_bugs` but for "require some diagnostic happened" // instead of "require some error happened". Sadly that isn't ideal, as // lints can be `#[allow]`'d, potentially leading to this triggering. // Also, "good path" should be replaced with a better naming. - if !self.has_any_message() && !self.suppressed_expected_diag && !std::thread::panicking() { - let bugs = std::mem::replace(&mut self.delayed_good_path_bugs, Vec::new()); + let has_any_message = self.err_count > 0 || self.lint_err_count > 0 || self.warn_count > 0; + if !has_any_message && !self.suppressed_expected_diag && !std::thread::panicking() { + let bugs = std::mem::replace(&mut self.good_path_delayed_bugs, Vec::new()); self.flush_delayed( bugs, - "no warnings or errors encountered even though `delayed_good_path_bugs` issued", + "no warnings or errors encountered even though `good_path_delayed_bugs` issued", ); } @@ -611,8 +610,8 @@ impl Handler { deduplicated_err_count: 0, deduplicated_warn_count: 0, emitter, - delayed_span_bugs: Vec::new(), - delayed_good_path_bugs: Vec::new(), + span_delayed_bugs: Vec::new(), + good_path_delayed_bugs: Vec::new(), suppressed_expected_diag: false, taught_diagnostics: Default::default(), emitted_diagnostic_codes: Default::default(), @@ -650,7 +649,7 @@ impl Handler { // This is here to not allow mutation of flags; // as of this writing it's only used in tests in librustc_middle. pub fn can_emit_warnings(&self) -> bool { - self.inner.lock().flags.can_emit_warnings + self.inner.borrow_mut().flags.can_emit_warnings } /// Resets the diagnostic error count as well as the cached emitted diagnostics. @@ -666,8 +665,8 @@ impl Handler { inner.deduplicated_warn_count = 0; // actually free the underlying memory (which `clear` would not do) - inner.delayed_span_bugs = Default::default(); - inner.delayed_good_path_bugs = Default::default(); + inner.span_delayed_bugs = Default::default(); + inner.good_path_delayed_bugs = Default::default(); inner.taught_diagnostics = Default::default(); inner.emitted_diagnostic_codes = Default::default(); inner.emitted_diagnostics = Default::default(); @@ -678,15 +677,45 @@ impl Handler { /// Retrieve a stashed diagnostic with `steal_diagnostic`. pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) { let mut inner = self.inner.borrow_mut(); - inner.stash((span.with_parent(None), key), diag); + + let key = (span.with_parent(None), key); + + if diag.is_error() { + if matches!(diag.level, Level::Error { lint: true }) { + inner.lint_err_count += 1; + } else { + inner.err_count += 1; + } + } else { + // Warnings are only automatically flushed if they're forced. + if diag.is_force_warn() { + inner.warn_count += 1; + } + } + + // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic + // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key. + // See the PR for a discussion. + inner.stashed_diagnostics.insert(key, diag); } /// Steal a previously stashed diagnostic with the given `Span` and [`StashKey`] as the key. pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option> { let mut inner = self.inner.borrow_mut(); - inner - .steal((span.with_parent(None), key)) - .map(|diag| DiagnosticBuilder::new_diagnostic(self, diag)) + let key = (span.with_parent(None), key); + let diag = inner.stashed_diagnostics.remove(&key)?; + if diag.is_error() { + if matches!(diag.level, Level::Error { lint: true }) { + inner.lint_err_count -= 1; + } else { + inner.err_count -= 1; + } + } else { + if diag.is_force_warn() { + inner.warn_count -= 1; + } + } + Some(DiagnosticBuilder::new_diagnostic(self, diag)) } pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool { @@ -850,7 +879,7 @@ impl Handler { &self, msg: impl Into, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - DiagnosticBuilder::new_guaranteeing_error(self, msg) + DiagnosticBuilder::new(self, Level::Error { lint: false }, msg) } /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors. @@ -917,7 +946,7 @@ impl Handler { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { - DiagnosticBuilder::new_fatal(self, msg) + DiagnosticBuilder::new(self, Level::Fatal, msg) } /// Construct a builder at the `Help` level with the `msg`. @@ -929,10 +958,7 @@ impl Handler { /// Construct a builder at the `Note` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_note_without_error( - &self, - msg: impl Into, - ) -> DiagnosticBuilder<'_, ()> { + pub fn struct_note(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { DiagnosticBuilder::new(self, Level::Note, msg) } @@ -972,11 +998,12 @@ impl Handler { span: impl Into, msg: impl Into, code: DiagnosticId, - ) { + ) -> ErrorGuaranteed { self.emit_diag_at_span( Diagnostic::new_with_code(Error { lint: false }, Some(code), msg), span, - ); + ) + .unwrap() } #[rustc_lint_diagnostics] @@ -1000,20 +1027,43 @@ impl Handler { self.inner.borrow_mut().span_bug(span, msg) } - /// For documentation on this, see `Session::delay_span_bug`. + /// For documentation on this, see `Session::span_delayed_bug`. + /// + /// Note: this function used to be called `delay_span_bug`. It was renamed + /// to match similar functions like `span_bug`, `span_err`, etc. #[track_caller] - pub fn delay_span_bug( + pub fn span_delayed_bug( &self, - span: impl Into, + sp: impl Into, msg: impl Into, ) -> ErrorGuaranteed { - self.inner.borrow_mut().delay_span_bug(span, msg) + let mut inner = self.inner.borrow_mut(); + + // This is technically `self.treat_err_as_bug()` but `span_delayed_bug` is called before + // incrementing `err_count` by one, so we need to +1 the comparing. + // FIXME: Would be nice to increment err_count in a more coherent way. + if inner.flags.treat_err_as_bug.is_some_and(|c| { + inner.err_count + inner.lint_err_count + inner.delayed_bug_count() + 1 >= c.get() + }) { + // FIXME: don't abort here if report_delayed_bugs is off + inner.span_bug(sp, msg.into()); + } + let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg.into()); + diagnostic.set_span(sp.into()); + inner.emit_diagnostic(&mut diagnostic).unwrap() } // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's // where the explanation of what "good path" is (also, it should be renamed). - pub fn delay_good_path_bug(&self, msg: impl Into) { - self.inner.borrow_mut().delay_good_path_bug(msg) + pub fn good_path_delayed_bug(&self, msg: impl Into) { + let mut inner = self.inner.borrow_mut(); + + let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); + if inner.flags.report_delayed_bugs { + inner.emit_diagnostic(&mut diagnostic); + } + let backtrace = std::backtrace::Backtrace::capture(); + inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); } #[track_caller] @@ -1023,17 +1073,13 @@ impl Handler { #[track_caller] #[rustc_lint_diagnostics] - pub fn span_note_without_error( - &self, - span: impl Into, - msg: impl Into, - ) { + pub fn span_note(&self, span: impl Into, msg: impl Into) { self.emit_diag_at_span(Diagnostic::new(Note, msg), span); } #[track_caller] #[rustc_lint_diagnostics] - pub fn span_note_diag( + pub fn struct_span_note( &self, span: Span, msg: impl Into, @@ -1043,35 +1089,34 @@ impl Handler { db } - // NOTE: intentionally doesn't raise an error so rustc_codegen_ssa only reports fatal errors in the main thread #[rustc_lint_diagnostics] - pub fn fatal(&self, msg: impl Into) -> FatalError { - self.inner.borrow_mut().fatal(msg) + pub fn fatal(&self, msg: impl Into) -> ! { + DiagnosticBuilder::::new(self, Fatal, msg).emit().raise() } #[rustc_lint_diagnostics] pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { - self.inner.borrow_mut().err(msg) + DiagnosticBuilder::::new(self, Error { lint: false }, msg).emit() } #[rustc_lint_diagnostics] pub fn warn(&self, msg: impl Into) { - let mut db = DiagnosticBuilder::new(self, Warning(None), msg); - db.emit(); + DiagnosticBuilder::<()>::new(self, Warning(None), msg).emit(); } #[rustc_lint_diagnostics] - pub fn note_without_error(&self, msg: impl Into) { - DiagnosticBuilder::new(self, Note, msg).emit(); + pub fn note(&self, msg: impl Into) { + DiagnosticBuilder::<()>::new(self, Note, msg).emit(); } pub fn bug(&self, msg: impl Into) -> ! { - self.inner.borrow_mut().bug(msg) + DiagnosticBuilder::::new(self, Bug, msg).emit(); + panic::panic_any(ExplicitBug); } #[inline] pub fn err_count(&self) -> usize { - self.inner.borrow().err_count() + self.inner.borrow().err_count } pub fn has_errors(&self) -> Option { @@ -1082,26 +1127,103 @@ impl Handler { } pub fn has_errors_or_lint_errors(&self) -> Option { - self.inner.borrow().has_errors_or_lint_errors().then(|| { + let inner = self.inner.borrow(); + let has_errors_or_lint_errors = inner.has_errors() || inner.lint_err_count > 0; + has_errors_or_lint_errors.then(|| { #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) } - pub fn has_errors_or_delayed_span_bugs(&self) -> Option { - self.inner.borrow().has_errors_or_delayed_span_bugs().then(|| { + + pub fn has_errors_or_span_delayed_bugs(&self) -> Option { + let inner = self.inner.borrow(); + let has_errors_or_span_delayed_bugs = + inner.has_errors() || !inner.span_delayed_bugs.is_empty(); + has_errors_or_span_delayed_bugs.then(|| { #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) } + pub fn is_compilation_going_to_fail(&self) -> Option { - self.inner.borrow().is_compilation_going_to_fail().then(|| { + let inner = self.inner.borrow(); + let will_fail = + inner.has_errors() || inner.lint_err_count > 0 || !inner.span_delayed_bugs.is_empty(); + will_fail.then(|| { #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) } pub fn print_error_count(&self, registry: &Registry) { - self.inner.borrow_mut().print_error_count(registry) + let mut inner = self.inner.borrow_mut(); + + inner.emit_stashed_diagnostics(); + + let warnings = match inner.deduplicated_warn_count { + 0 => Cow::from(""), + 1 => Cow::from("1 warning emitted"), + count => Cow::from(format!("{count} warnings emitted")), + }; + let errors = match inner.deduplicated_err_count { + 0 => Cow::from(""), + 1 => Cow::from("aborting due to 1 previous error"), + count => Cow::from(format!("aborting due to {count} previous errors")), + }; + if inner.treat_err_as_bug() { + return; + } + + match (errors.len(), warnings.len()) { + (0, 0) => return, + (0, _) => inner.emitter.emit_diagnostic(&Diagnostic::new( + Level::Warning(None), + DiagnosticMessage::Str(warnings), + )), + (_, 0) => { + inner.emit_diagnostic(&mut Diagnostic::new(Fatal, errors)); + } + (_, _) => { + inner.emit_diagnostic(&mut Diagnostic::new(Fatal, format!("{errors}; {warnings}"))); + } + } + + let can_show_explain = inner.emitter.should_show_explain(); + let are_there_diagnostics = !inner.emitted_diagnostic_codes.is_empty(); + if can_show_explain && are_there_diagnostics { + let mut error_codes = inner + .emitted_diagnostic_codes + .iter() + .filter_map(|x| match &x { + DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => { + Some(s.clone()) + } + _ => None, + }) + .collect::>(); + if !error_codes.is_empty() { + error_codes.sort(); + if error_codes.len() > 1 { + let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() }; + inner.failure_note(format!( + "Some errors have detailed explanations: {}{}", + error_codes[..limit].join(", "), + if error_codes.len() > 9 { "..." } else { "." } + )); + inner.failure_note(format!( + "For more information about an error, try \ + `rustc --explain {}`.", + &error_codes[0] + )); + } else { + inner.failure_note(format!( + "For more information about this error, try \ + `rustc --explain {}`.", + &error_codes[0] + )); + } + } + } } pub fn take_future_breakage_diagnostics(&self) -> Vec { @@ -1109,7 +1231,11 @@ impl Handler { } pub fn abort_if_errors(&self) { - self.inner.borrow_mut().abort_if_errors() + let mut inner = self.inner.borrow_mut(); + inner.emit_stashed_diagnostics(); + if inner.has_errors() { + FatalError.raise(); + } } /// `true` if we haven't taught a diagnostic with this code already. @@ -1118,11 +1244,11 @@ impl Handler { /// Used to suppress emitting the same error multiple times with extended explanation when /// calling `-Zteach`. pub fn must_teach(&self, code: &DiagnosticId) -> bool { - self.inner.borrow_mut().must_teach(code) + self.inner.borrow_mut().taught_diagnostics.insert(code.clone()) } pub fn force_print_diagnostic(&self, db: Diagnostic) { - self.inner.borrow_mut().force_print_diagnostic(db) + self.inner.borrow_mut().emitter.emit_diagnostic(&db); } pub fn emit_diagnostic(&self, diagnostic: &mut Diagnostic) -> Option { @@ -1206,12 +1332,11 @@ impl Handler { mut diag: Diagnostic, sp: impl Into, ) -> Option { - let mut inner = self.inner.borrow_mut(); - inner.emit_diagnostic(diag.set_span(sp)) + self.emit_diagnostic(diag.set_span(sp)) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { - self.inner.borrow_mut().emit_artifact_notification(path, artifact_type) + self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); } pub fn emit_future_breakage_report(&self, diags: Vec) { @@ -1230,7 +1355,7 @@ impl Handler { inner.bump_err_count(); } - inner.emit_unused_externs(lint_level, unused_externs) + inner.emitter.emit_unused_externs(lint_level, unused_externs) } pub fn update_unstable_expectation_id( @@ -1275,21 +1400,17 @@ impl Handler { } pub fn flush_delayed(&self) { - let mut inner = self.inner.lock(); - let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new()); - inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued"); + let mut inner = self.inner.borrow_mut(); + let bugs = std::mem::replace(&mut inner.span_delayed_bugs, Vec::new()); + inner.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued"); } } +// Note: we prefer implementing operations on `Handler`, rather than +// `HandlerInner`, whenever possible. This minimizes functions where +// `Handler::foo()` just borrows `inner` and forwards a call to +// `HanderInner::foo`. impl HandlerInner { - fn must_teach(&mut self, code: &DiagnosticId) -> bool { - self.taught_diagnostics.insert(code.clone()) - } - - fn force_print_diagnostic(&mut self, db: Diagnostic) { - self.emitter.emit_diagnostic(&db); - } - /// Emit all stashed diagnostics. fn emit_stashed_diagnostics(&mut self) -> Option { let has_errors = self.has_errors(); @@ -1323,6 +1444,11 @@ impl HandlerInner { // FIXME(eddyb) this should ideally take `diagnostic` by value. fn emit_diagnostic(&mut self, diagnostic: &mut Diagnostic) -> Option { + if matches!(diagnostic.level, Level::Error { .. } | Level::Fatal) && self.treat_err_as_bug() + { + diagnostic.level = Level::Bug; + } + // The `LintExpectationId` can be stable or unstable depending on when it was created. // Diagnostics created before the definition of `HirId`s are unstable and can not yet // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by @@ -1334,11 +1460,11 @@ impl HandlerInner { if diagnostic.level == Level::DelayedBug { // FIXME(eddyb) this should check for `has_errors` and stop pushing - // once *any* errors were emitted (and truncate `delayed_span_bugs` + // once *any* errors were emitted (and truncate `span_delayed_bugs` // when an error is first emitted, also), but maybe there's a case // in which that's not sound? otherwise this is really inefficient. let backtrace = std::backtrace::Backtrace::capture(); - self.delayed_span_bugs + self.span_delayed_bugs .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); if !self.flags.report_delayed_bugs { @@ -1438,159 +1564,18 @@ impl HandlerInner { guaranteed } - fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { - self.emitter.emit_artifact_notification(path, artifact_type); - } - - fn emit_unused_externs(&mut self, lint_level: rustc_lint_defs::Level, unused_externs: &[&str]) { - self.emitter.emit_unused_externs(lint_level, unused_externs); - } - fn treat_err_as_bug(&self) -> bool { self.flags.treat_err_as_bug.is_some_and(|c| { - self.err_count() + self.lint_err_count + self.delayed_bug_count() >= c.get() + self.err_count + self.lint_err_count + self.delayed_bug_count() >= c.get() }) } fn delayed_bug_count(&self) -> usize { - self.delayed_span_bugs.len() + self.delayed_good_path_bugs.len() - } - - fn print_error_count(&mut self, registry: &Registry) { - self.emit_stashed_diagnostics(); - - let warnings = match self.deduplicated_warn_count { - 0 => Cow::from(""), - 1 => Cow::from("1 warning emitted"), - count => Cow::from(format!("{count} warnings emitted")), - }; - let errors = match self.deduplicated_err_count { - 0 => Cow::from(""), - 1 => Cow::from("aborting due to previous error"), - count => Cow::from(format!("aborting due to {count} previous errors")), - }; - if self.treat_err_as_bug() { - return; - } - - match (errors.len(), warnings.len()) { - (0, 0) => return, - (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new( - Level::Warning(None), - DiagnosticMessage::Str(warnings), - )), - (_, 0) => { - let _ = self.fatal(errors); - } - (_, _) => { - let _ = self.fatal(format!("{errors}; {warnings}")); - } - } - - let can_show_explain = self.emitter.should_show_explain(); - let are_there_diagnostics = !self.emitted_diagnostic_codes.is_empty(); - if can_show_explain && are_there_diagnostics { - let mut error_codes = self - .emitted_diagnostic_codes - .iter() - .filter_map(|x| match &x { - DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => { - Some(s.clone()) - } - _ => None, - }) - .collect::>(); - if !error_codes.is_empty() { - error_codes.sort(); - if error_codes.len() > 1 { - let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() }; - self.failure(format!( - "Some errors have detailed explanations: {}{}", - error_codes[..limit].join(", "), - if error_codes.len() > 9 { "..." } else { "." } - )); - self.failure(format!( - "For more information about an error, try \ - `rustc --explain {}`.", - &error_codes[0] - )); - } else { - self.failure(format!( - "For more information about this error, try \ - `rustc --explain {}`.", - &error_codes[0] - )); - } - } - } - } - - fn stash(&mut self, key: (Span, StashKey), diagnostic: Diagnostic) { - // Track the diagnostic for counts, but don't panic-if-treat-err-as-bug - // yet; that happens when we actually emit the diagnostic. - if diagnostic.is_error() { - if matches!(diagnostic.level, Level::Error { lint: true }) { - self.lint_err_count += 1; - } else { - self.err_count += 1; - } - } else { - // Warnings are only automatically flushed if they're forced. - if diagnostic.is_force_warn() { - self.warn_count += 1; - } - } - - // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic - // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key. - // See the PR for a discussion. - self.stashed_diagnostics.insert(key, diagnostic); - } - - fn steal(&mut self, key: (Span, StashKey)) -> Option { - let diagnostic = self.stashed_diagnostics.remove(&key)?; - if diagnostic.is_error() { - if matches!(diagnostic.level, Level::Error { lint: true }) { - self.lint_err_count -= 1; - } else { - self.err_count -= 1; - } - } else { - if diagnostic.is_force_warn() { - self.warn_count -= 1; - } - } - Some(diagnostic) - } - - #[inline] - fn err_count(&self) -> usize { - self.err_count + self.span_delayed_bugs.len() + self.good_path_delayed_bugs.len() } fn has_errors(&self) -> bool { - self.err_count() > 0 - } - fn has_errors_or_lint_errors(&self) -> bool { - self.has_errors() || self.lint_err_count > 0 - } - fn has_errors_or_delayed_span_bugs(&self) -> bool { - self.has_errors() || !self.delayed_span_bugs.is_empty() - } - fn has_any_message(&self) -> bool { - self.err_count() > 0 || self.lint_err_count > 0 || self.warn_count > 0 - } - - fn is_compilation_going_to_fail(&self) -> bool { - self.has_errors() || self.lint_err_count > 0 || !self.delayed_span_bugs.is_empty() - } - - fn abort_if_errors(&mut self) { - self.emit_stashed_diagnostics(); - - if self.has_errors() { - FatalError.raise(); - } + self.err_count > 0 } #[track_caller] @@ -1603,64 +1588,10 @@ impl HandlerInner { self.emit_diagnostic(diag.set_span(sp)); } - /// For documentation on this, see `Session::delay_span_bug`. - #[track_caller] - fn delay_span_bug( - &mut self, - sp: impl Into, - msg: impl Into, - ) -> ErrorGuaranteed { - // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before - // incrementing `err_count` by one, so we need to +1 the comparing. - // FIXME: Would be nice to increment err_count in a more coherent way. - if self.flags.treat_err_as_bug.is_some_and(|c| { - self.err_count() + self.lint_err_count + self.delayed_bug_count() + 1 >= c.get() - }) { - // FIXME: don't abort here if report_delayed_bugs is off - self.span_bug(sp, msg.into()); - } - let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg.into()); - diagnostic.set_span(sp.into()); - self.emit_diagnostic(&mut diagnostic).unwrap() - } - - // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's - // where the explanation of what "good path" is (also, it should be renamed). - fn delay_good_path_bug(&mut self, msg: impl Into) { - let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg); - if self.flags.report_delayed_bugs { - self.emit_diagnostic(&mut diagnostic); - } - let backtrace = std::backtrace::Backtrace::capture(); - self.delayed_good_path_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); - } - - fn failure(&mut self, msg: impl Into) { + fn failure_note(&mut self, msg: impl Into) { self.emit_diagnostic(&mut Diagnostic::new(FailureNote, msg)); } - fn fatal(&mut self, msg: impl Into) -> FatalError { - self.emit(Fatal, msg); - FatalError - } - - fn err(&mut self, msg: impl Into) -> ErrorGuaranteed { - self.emit(Error { lint: false }, msg) - } - - /// Emit an error; level should be `Error` or `Fatal`. - fn emit(&mut self, level: Level, msg: impl Into) -> ErrorGuaranteed { - if self.treat_err_as_bug() { - self.bug(msg); - } - self.emit_diagnostic(&mut Diagnostic::new(level, msg)).unwrap() - } - - fn bug(&mut self, msg: impl Into) -> ! { - self.emit_diagnostic(&mut Diagnostic::new(Bug, msg)); - panic::panic_any(ExplicitBug); - } - fn flush_delayed( &mut self, bugs: impl IntoIterator, @@ -1731,7 +1662,7 @@ impl HandlerInner { fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { match ( - self.err_count() + self.lint_err_count, + self.err_count + self.lint_err_count, self.delayed_bug_count(), self.flags.treat_err_as_bug.map(|c| c.get()).unwrap(), ) { diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs index d3a08da628394..67e4963fddf7f 100644 --- a/compiler/rustc_errors/src/markdown/parse.rs +++ b/compiler/rustc_errors/src/markdown/parse.rs @@ -329,7 +329,7 @@ fn parse_with_end_pat<'a>( end_sep: &[u8], ignore_esc: bool, ) -> Option<(&'a [u8], &'a [u8])> { - // Find positions that start with the end seperator + // Find positions that start with the end separator for idx in (0..buf.len()).filter(|idx| buf[*idx..].starts_with(end_sep)) { if !ignore_esc && idx > 0 && buf[idx - 1] == b'\\' { continue; diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 8b93829623dbf..fc3f7b1d749d0 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -71,6 +71,8 @@ expand_macro_const_stability = .label = invalid const stability attribute .label2 = const stability attribute affects this macro +expand_macro_expands_to_match_arm = macros cannot expand to match arms + expand_malformed_feature_attribute = malformed `feature` attribute input .expected = expected just one word diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c4d2a374f0c67..74f46efb365b2 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -777,7 +777,7 @@ impl SyntaxExtension { attrs: &[ast::Attribute], ) -> SyntaxExtension { let allow_internal_unstable = - attr::allow_internal_unstable(sess, &attrs).collect::>(); + attr::allow_internal_unstable(sess, attrs).collect::>(); let allow_internal_unsafe = attr::contains_name(attrs, sym::allow_internal_unsafe); let local_inner_macros = attr::find_by_name(attrs, sym::macro_export) @@ -796,9 +796,9 @@ impl SyntaxExtension { ) }) .unwrap_or_else(|| (None, helper_attrs)); - let stability = attr::find_stability(&sess, attrs, span); - let const_stability = attr::find_const_stability(&sess, attrs, span); - let body_stability = attr::find_body_stability(&sess, attrs); + let stability = attr::find_stability(sess, attrs, span); + let const_stability = attr::find_const_stability(sess, attrs, span); + let body_stability = attr::find_body_stability(sess, attrs); if let Some((_, sp)) = const_stability { sess.emit_err(errors::MacroConstStability { span: sp, @@ -818,7 +818,7 @@ impl SyntaxExtension { allow_internal_unstable: (!allow_internal_unstable.is_empty()) .then(|| allow_internal_unstable.into()), stability: stability.map(|(s, _)| s), - deprecation: attr::find_deprecation(&sess, features, attrs).map(|(d, _)| d), + deprecation: attr::find_deprecation(sess, features, attrs).map(|(d, _)| d), helper_attrs, edition, builtin_name, @@ -1119,7 +1119,7 @@ impl<'a> ExtCtxt<'a> { sp: S, msg: impl Into, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg) + self.sess.diagnostic().struct_span_err(sp, msg) } #[track_caller] @@ -1143,15 +1143,10 @@ impl<'a> ExtCtxt<'a> { #[rustc_lint_diagnostics] #[track_caller] pub fn span_err>(&self, sp: S, msg: impl Into) { - self.sess.parse_sess.span_diagnostic.span_err(sp, msg); - } - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_warn>(&self, sp: S, msg: impl Into) { - self.sess.parse_sess.span_diagnostic.span_warn(sp, msg); + self.sess.diagnostic().span_err(sp, msg); } pub fn span_bug>(&self, sp: S, msg: impl Into) -> ! { - self.sess.parse_sess.span_diagnostic.span_bug(sp, msg); + self.sess.diagnostic().span_bug(sp, msg); } pub fn trace_macros_diag(&mut self) { for (span, notes) in self.expansions.iter() { @@ -1165,7 +1160,7 @@ impl<'a> ExtCtxt<'a> { self.expansions.clear(); } pub fn bug(&self, msg: &'static str) -> ! { - self.sess.parse_sess.span_diagnostic.bug(msg); + self.sess.diagnostic().bug(msg); } pub fn trace_macros(&self) -> bool { self.ecfg.trace_mac @@ -1286,9 +1281,8 @@ pub fn expr_to_string( /// Non-fatally assert that `tts` is empty. Note that this function /// returns even when `tts` is non-empty, macros that *need* to stop -/// compilation should call -/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be -/// done as rarely as possible). +/// compilation should call `cx.diagnostic().abort_if_errors()` +/// (this should be done as rarely as possible). pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) { if !tts.is_empty() { cx.emit_err(errors::TakesNoArguments { span, name }); @@ -1464,7 +1458,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool { if crate_matches { sess.buffer_lint_with_diagnostic( - &PROC_MACRO_BACK_COMPAT, + PROC_MACRO_BACK_COMPAT, item.ident.span, ast::CRATE_NODE_ID, "using an old version of `rental`", diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 7de46994434c5..853554b2dcd90 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -4,7 +4,7 @@ use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, use rustc_ast::{attr, token, util::literal}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use thin_vec::{thin_vec, ThinVec}; impl<'a> ExtCtxt<'a> { @@ -135,7 +135,7 @@ impl<'a> ExtCtxt<'a> { ast::GenericBound::Trait( self.poly_trait_ref(path.span, path), if is_const { - ast::TraitBoundModifier::MaybeConst + ast::TraitBoundModifier::MaybeConst(DUMMY_SP) } else { ast::TraitBoundModifier::None }, @@ -505,7 +505,7 @@ impl<'a> ExtCtxt<'a> { attrs: AttrVec::new(), pat, guard: None, - body: expr, + body: Some(expr), span, id: ast::DUMMY_NODE_ID, is_placeholder: false, @@ -547,7 +547,7 @@ impl<'a> ExtCtxt<'a> { binder: ast::ClosureBinder::NotPresent, capture_clause: ast::CaptureBy::Ref, constness: ast::Const::No, - asyncness: ast::Async::No, + coro_kind: None, movability: ast::Movability::Movable, fn_decl, body, diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index bef48765937f5..5ccef343b1723 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -74,7 +74,9 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) - // - E.g. enable `test_2018_feature` if `features_edition` is 2018 or higher let mut edition_enabled_features = FxHashSet::default(); for f in UNSTABLE_FEATURES { - if let Some(edition) = f.feature.edition && edition <= features_edition { + if let Some(edition) = f.feature.edition + && edition <= features_edition + { // FIXME(Manishearth) there is currently no way to set lib features by // edition. edition_enabled_features.insert(f.feature.name); @@ -251,8 +253,7 @@ impl<'a> StripUnconfigured<'a> { let trees: Vec<_> = stream .0 .iter() - .flat_map(|tree| { - match tree.clone() { + .flat_map(|tree| match tree.clone() { AttrTokenTree::Attributes(mut data) => { data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(&attr)); @@ -277,7 +278,6 @@ impl<'a> StripUnconfigured<'a> { AttrTokenTree::Token(token, spacing) => { Some(AttrTokenTree::Token(token, spacing)).into_iter() } - } }) .collect(); AttrTokenStream::new(trees) @@ -434,9 +434,9 @@ impl<'a> StripUnconfigured<'a> { } }; ( - parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| { + parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| { attr::cfg_matches( - &meta_item, + meta_item, &self.sess.parse_sess, self.lint_node_id, self.features, diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index d86632c47fc5d..6e919a8fa9f2f 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -304,6 +304,8 @@ pub(crate) struct IncompleteParse<'a> { pub label_span: Span, pub macro_path: &'a ast::Path, pub kind_name: &'a str, + #[note(expand_macro_expands_to_match_arm)] + pub expands_to_match_arm: Option<()>, #[suggestion( expand_suggestion_add_semi, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index f87f4aba2b9ea..47d4b802c0f45 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -435,7 +435,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { invocations = mem::take(&mut undetermined_invocations); force = !mem::replace(&mut progress, false); if force && self.monotonic { - self.cx.sess.delay_span_bug( + self.cx.sess.span_delayed_bug( invocations.last().unwrap().0.span(), "expansion entered force mode without producing any errors", ); @@ -955,12 +955,15 @@ pub fn ensure_complete_parse<'a>( _ => None, }; + let expands_to_match_arm = kind_name == "pattern" && parser.token == token::FatArrow; + parser.sess.emit_err(IncompleteParse { span: def_site_span, token, label_span: span, macro_path, kind_name, + expands_to_match_arm: expands_to_match_arm.then_some(()), add_semicolon, }); } @@ -1096,7 +1099,7 @@ impl InvocationCollectorNode for P { ModKind::Loaded(_, inline, _) => { // Inline `mod foo { ... }`, but we still need to push directories. let (dir_path, dir_ownership) = mod_dir_path( - &ecx.sess, + ecx.sess, ident, &attrs, &ecx.current_expansion.module, @@ -1111,7 +1114,7 @@ impl InvocationCollectorNode for P { let old_attrs_len = attrs.len(); let ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } = parse_external_mod( - &ecx.sess, + ecx.sess, ident, span, &ecx.current_expansion.module, @@ -1168,14 +1171,14 @@ impl InvocationCollectorNode for P { ast::UseTreeKind::Simple(_) => idents.push(ut.ident()), ast::UseTreeKind::Nested(nested) => { for (ut, _) in nested { - collect_use_tree_leaves(&ut, idents); + collect_use_tree_leaves(ut, idents); } } } } let mut idents = Vec::new(); - collect_use_tree_leaves(&ut, &mut idents); + collect_use_tree_leaves(ut, &mut idents); return idents; } @@ -1531,7 +1534,7 @@ impl InvocationCollectorNode for AstNodeWrapper, OptExprTag> { } } fn pre_flat_map_node_collect_attr(cfg: &StripUnconfigured<'_>, attr: &ast::Attribute) { - cfg.maybe_emit_expr_attr_err(&attr); + cfg.maybe_emit_expr_attr_err(attr); } } @@ -1580,7 +1583,7 @@ struct InvocationCollector<'a, 'b> { impl<'a, 'b> InvocationCollector<'a, 'b> { fn cfg(&self) -> StripUnconfigured<'_> { StripUnconfigured { - sess: &self.cx.sess, + sess: self.cx.sess, features: Some(self.cx.ecfg.features), config_tokens: false, lint_node_id: self.cx.current_expansion.lint_node_id, @@ -1693,7 +1696,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { if attr.is_doc_comment() { self.cx.sess.parse_sess.buffer_lint_with_diagnostic( - &UNUSED_DOC_COMMENTS, + UNUSED_DOC_COMMENTS, current_span, self.cx.current_expansion.lint_node_id, "unused doc comment", @@ -1705,7 +1708,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // eagerly evaluated. if attr_name != sym::cfg && attr_name != sym::cfg_attr { self.cx.sess.parse_sess.buffer_lint_with_diagnostic( - &UNUSED_ATTRIBUTES, + UNUSED_ATTRIBUTES, attr.span, self.cx.current_expansion.lint_node_id, format!("unused attribute `{attr_name}`"), diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 5a774164a4bb8..bed667048c855 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,5 +1,5 @@ -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(array_windows)] #![feature(associated_type_bounds)] #![feature(associated_type_defaults)] @@ -23,9 +23,6 @@ extern crate tracing; extern crate proc_macro as pm; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - mod placeholders; mod proc_macro_server; @@ -67,4 +64,4 @@ mod mut_visit { mod tests; } -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index e060375646c2d..8f80e6e2927ce 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -34,7 +34,7 @@ pub(super) fn failed_to_match_macro<'cx>( if try_success_result.is_ok() { // Nonterminal parser recovery might turn failed matches into successful ones, // but for that it must have emitted an error already - tracker.cx.sess.delay_span_bug(sp, "Macro matching returned a success on the second try"); + tracker.cx.sess.span_delayed_bug(sp, "Macro matching returned a success on the second try"); } if let Some(result) = tracker.result { @@ -67,6 +67,12 @@ pub(super) fn failed_to_match_macro<'cx>( && (matches!(expected_token.kind, TokenKind::Interpolated(_)) || matches!(token.kind, TokenKind::Interpolated(_))) { + if let TokenKind::Interpolated(node) = &expected_token.kind { + err.span_label(node.1, ""); + } + if let TokenKind::Interpolated(node) = &token.kind { + err.span_label(node.1, ""); + } err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens"); err.note("see for more information"); @@ -145,7 +151,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, Success(_) => { // Nonterminal parser recovery might turn failed matches into successful ones, // but for that it must have emitted an error already - self.cx.sess.delay_span_bug( + self.cx.sess.span_delayed_bug( self.root_span, "should not collect detailed info for successful macro match", ); diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 95f5bb2d2e230..42c91824baf50 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -650,6 +650,6 @@ fn buffer_lint( ) { // Macros loaded from other crates have dummy node ids. if node_id != DUMMY_NODE_ID { - sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message); + sess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message); } } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 7e85beaadcbcc..965beb9bf84ef 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -397,7 +397,7 @@ pub(crate) enum NamedMatch { MatchedTokenTree(rustc_ast::tokenstream::TokenTree), // A metavar match of any type other than `tt`. - MatchedNonterminal(Lrc), + MatchedNonterminal(Lrc<(Nonterminal, rustc_span::Span)>), } /// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison) @@ -483,7 +483,7 @@ impl TtParser { if matches!(t, Token { kind: DocComment(..), .. }) { mp.idx += 1; self.cur_mps.push(mp); - } else if token_name_eq(&t, token) { + } else if token_name_eq(t, token) { mp.idx += 1; self.next_mps.push(mp); } @@ -692,7 +692,7 @@ impl TtParser { Ok(nt) => nt, }; let m = match nt { - ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new(nt)), + ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new((nt, span))), ParseNtResult::Tt(tt) => MatchedTokenTree(tt), }; mp.push_match(next_metavar, seq_depth, m); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index ebdd3cb547c38..19734394382ca 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -213,7 +213,7 @@ fn expand_macro<'cx>( let arm_span = rhses[i].span(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = match transcribe(cx, &named_matches, &rhs, rhs_span, transparency) { + let mut tts = match transcribe(cx, &named_matches, rhs, rhs_span, transparency) { Ok(tts) => tts, Err(mut err) => { err.emit(); @@ -475,17 +475,14 @@ pub fn compile_declarative_macro( let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); - let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, s); + let mut err = sess.diagnostic().struct_span_err(sp, s); err.span_label(sp, msg); annotate_doc_comment(&mut err, sess.source_map(), sp); err.emit(); return dummy_syn_ext(); } Error(sp, msg) => { - sess.parse_sess - .span_diagnostic - .struct_span_err(sp.substitute_dummy(def.span), msg) - .emit(); + sess.diagnostic().struct_span_err(sp.substitute_dummy(def.span), msg).emit(); return dummy_syn_ext(); } ErrorReported(_) => { @@ -511,13 +508,13 @@ pub fn compile_declarative_macro( ) .pop() .unwrap(); - valid &= check_lhs_nt_follows(&sess.parse_sess, &def, &tt); + valid &= check_lhs_nt_follows(&sess.parse_sess, def, &tt); return tt; } - sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") + sess.diagnostic().span_bug(def.span, "wrong-structured lhs") }) .collect::>(), - _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"), + _ => sess.diagnostic().span_bug(def.span, "wrong-structured lhs"), }; let rhses = match &argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] { @@ -536,10 +533,10 @@ pub fn compile_declarative_macro( .pop() .unwrap(); } - sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs") + sess.diagnostic().span_bug(def.span, "wrong-structured rhs") }) .collect::>(), - _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"), + _ => sess.diagnostic().span_bug(def.span, "wrong-structured rhs"), }; for rhs in &rhses { @@ -595,7 +592,7 @@ pub fn compile_declarative_macro( mbe::TokenTree::Delimited(_, delimited) => { mbe::macro_parser::compute_locs(&delimited.tts) } - _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "malformed macro lhs"), + _ => sess.diagnostic().span_bug(def.span, "malformed macro lhs"), } }) .collect() @@ -648,10 +645,8 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool iter.next(); } let span = t.span.to(now.span); - sess.span_diagnostic.span_note_without_error( - span, - "doc comments are ignored in matcher position", - ); + sess.span_diagnostic + .span_note(span, "doc comments are ignored in matcher position"); } mbe::TokenTree::Sequence(_, sub_seq) if (sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore @@ -927,7 +922,7 @@ impl<'tt> TtHandle<'tt> { fn get(&'tt self) -> &'tt mbe::TokenTree { match self { TtHandle::TtRef(tt) => tt, - TtHandle::Token(token_tt) => &token_tt, + TtHandle::Token(token_tt) => token_tt, } } } @@ -1170,7 +1165,7 @@ fn check_matcher_core<'tt>( Some(NonterminalKind::PatParam { inferred: false }), )); sess.buffer_lint_with_diagnostic( - &RUST_2021_INCOMPATIBLE_OR_PATTERNS, + RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, ast::CRATE_NODE_ID, "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro", @@ -1407,7 +1402,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { match tt { - mbe::TokenTree::Token(token) => pprust::token_to_string(&token).into(), + mbe::TokenTree::Token(token) => pprust::token_to_string(token).into(), mbe::TokenTree::MetaVar(_, name) => format!("${name}"), mbe::TokenTree::MetaVarDecl(_, name, Some(kind)) => format!("${name}:{kind}"), mbe::TokenTree::MetaVarDecl(_, name, None) => format!("${name}:"), diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 6546199f5e6a7..6a99412fc5bcf 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -116,7 +116,7 @@ pub(super) fn parse( fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess, span: Span) { if !features.macro_metavar_expr { let msg = "meta-variable expressions are unstable"; - feature_err(&sess, sym::macro_metavar_expr, span, msg).emit(); + feature_err(sess, sym::macro_metavar_expr, span, msg).emit(); } } @@ -174,7 +174,7 @@ fn parse_tree<'a>( // The delimiter is `{`. This indicates the beginning // of a meta-variable expression (e.g. `${count(ident)}`). // Try to parse the meta-variable expression. - match MetaVarExpr::parse(&tts, delim_span.entire(), sess) { + match MetaVarExpr::parse(tts, delim_span.entire(), sess) { Err(mut err) => { err.emit(); // Returns early the same read `$` to avoid spanning @@ -242,10 +242,8 @@ fn parse_tree<'a>( // `tree` is followed by some other token. This is an error. Some(tokenstream::TokenTree::Token(token, _)) => { - let msg = format!( - "expected identifier, found `{}`", - pprust::token_to_string(&token), - ); + let msg = + format!("expected identifier, found `{}`", pprust::token_to_string(token),); sess.span_diagnostic.span_err(token.span, msg); TokenTree::MetaVar(token.span, Ident::empty()) } @@ -291,7 +289,7 @@ fn parse_kleene_op<'a>( span: Span, ) -> Result, Span> { match input.next() { - Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(&token) { + Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(token) { Some(op) => Ok(Ok((op, token.span))), None => Ok(Err(token.clone())), }, @@ -359,7 +357,7 @@ fn parse_sep_and_kleene_op<'a>( fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &ParseSess, token: &Token) { sess.span_diagnostic .span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token))); - sess.span_diagnostic.span_note_without_error( + sess.span_diagnostic.span_note( token.span, "`$$` and meta-variable expressions are not allowed inside macro parameter definitions", ); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 15e7ab3fe3ee6..bc03fc0d1b169 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -90,7 +90,7 @@ pub(super) fn transcribe<'a>( // We descend into the RHS (`src`), expanding things as we go. This stack contains the things // we have yet to expand/are still expanding. We start the stack off with the whole RHS. - let mut stack: SmallVec<[Frame<'_>; 1]> = smallvec![Frame::new(&src, src_span)]; + let mut stack: SmallVec<[Frame<'_>; 1]> = smallvec![Frame::new(src, src_span)]; // As we descend in the RHS, we will need to be able to match nested sequences of matchers. // `repeats` keeps track of where we are in matching at each level, with the last element being @@ -166,7 +166,7 @@ pub(super) fn transcribe<'a>( // and the matches in `interp` have the same shape. Otherwise, either the caller or the // macro writer has made a mistake. seq @ mbe::TokenTree::Sequence(_, delimited) => { - match lockstep_iter_size(&seq, interp, &repeats) { + match lockstep_iter_size(seq, interp, &repeats) { LockstepIterSize::Unconstrained => { return Err(cx.create_err(NoSyntaxVarsExprRepeat { span: seq.span() })); } @@ -250,7 +250,7 @@ pub(super) fn transcribe<'a>( // Replace meta-variable expressions with the result of their expansion. mbe::TokenTree::MetaVarExpr(sp, expr) => { - transcribe_metavar_expr(cx, expr, interp, &mut marker, &repeats, &mut result, &sp)?; + transcribe_metavar_expr(cx, expr, interp, &mut marker, &repeats, &mut result, sp)?; } // If we are entering a new delimiter, we push its contents to the `stack` to be @@ -529,7 +529,7 @@ fn transcribe_metavar_expr<'a>( match *expr { MetaVarExpr::Count(original_ident, depth_opt) => { let matched = matched_from_ident(cx, original_ident, interp)?; - let count = count_repetitions(cx, depth_opt, matched, &repeats, sp)?; + let count = count_repetitions(cx, depth_opt, matched, repeats, sp)?; let tt = TokenTree::token_alone( TokenKind::lit(token::Integer, sym::integer(count), None), visited_span(), diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index df6bdc6952bd3..a0dec89d63119 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -57,7 +57,7 @@ pub(crate) fn parse_external_mod( // We bail on the first error, but that error does not cause a fatal error... (1) let result: Result<_, ModError<'_>> = try { // Extract the file path and the new ownership. - let mp = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership)?; + let mp = mod_file_path(sess, ident, attrs, &module.dir_path, dir_ownership)?; dir_ownership = mp.dir_ownership; // Ensure file paths are acyclic. @@ -119,7 +119,7 @@ pub(crate) fn mod_dir_path( Inline::No => { // FIXME: This is a subset of `parse_external_mod` without actual parsing, // check whether the logic for unloaded, loaded and inline modules can be unified. - let file_path = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership) + let file_path = mod_file_path(sess, ident, attrs, &module.dir_path, dir_ownership) .map(|mp| { dir_ownership = mp.dir_ownership; mp.file_path diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 1292a8552303e..ded0baa9563e8 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -119,7 +119,7 @@ pub fn placeholder( }]), AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm { attrs: Default::default(), - body: expr_placeholder(), + body: Some(expr_placeholder()), guard: None, id, pat: pat(), diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index c617cd76e3cb0..d08026b9c140a 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -126,7 +126,7 @@ impl MultiItemModifier for DeriveProcMacro { Annotatable::Stmt(stmt) => token::NtStmt(stmt), _ => unreachable!(), }; - TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP) + TokenStream::token_alone(token::Interpolated(Lrc::new((nt, span))), DUMMY_SP) } else { item.to_tokens() }; @@ -156,7 +156,7 @@ impl MultiItemModifier for DeriveProcMacro { } }; - let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count(); + let error_count_before = ecx.sess.diagnostic().err_count(); let mut parser = rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive")); let mut items = vec![]; @@ -179,7 +179,7 @@ impl MultiItemModifier for DeriveProcMacro { } // fail if there have been errors emitted - if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before { + if ecx.sess.diagnostic().err_count() > error_count_before { ecx.sess.emit_err(errors::ProcMacroDeriveTokens { span }); } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index aa4c7a5313558..b057a645f8195 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -226,18 +226,23 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec trees - .push(TokenTree::Ident(Ident { sym: ident.name, is_raw, span: ident.span })), + Interpolated(ref nt) if let NtIdent(ident, is_raw) = &nt.0 => { + trees.push(TokenTree::Ident(Ident { + sym: ident.name, + is_raw: *is_raw, + span: ident.span, + })) + } Interpolated(nt) => { - let stream = TokenStream::from_nonterminal_ast(&nt); + let stream = TokenStream::from_nonterminal_ast(&nt.0); // A hack used to pass AST fragments to attribute and derive // macros as a single nonterminal token instead of a token // stream. Such token needs to be "unwrapped" and not // represented as a delimited group. // FIXME: It needs to be removed, but there are some // compatibility issues (see #73345). - if crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.sess()) { + if crate::base::nt_pretty_printing_compatibility_hack(&nt.0, rustc.sess()) { trees.extend(Self::from_internal((stream, rustc))); } else { trees.push(TokenTree::Group(Group { @@ -779,6 +784,6 @@ impl server::Server for Rustc<'_, '_> { } fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) { - f(&symbol.as_str()) + f(symbol.as_str()) } } diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index 9f52669e1880f..b4724b0e9d060 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -135,7 +135,7 @@ pub(crate) fn matches_codepattern(a: &str, b: &str) -> bool { /// Advances the given peekable `Iterator` until it reaches a non-whitespace character. fn scan_for_non_ws_or_end>(iter: &mut Peekable) { - while iter.peek().copied().map(rustc_lexer::is_whitespace) == Some(true) { + while iter.peek().copied().is_some_and(rustc_lexer::is_whitespace) { iter.next(); } } diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index f07022733d495..94e7914459321 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -65,7 +65,7 @@ declare_features! ( /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. (accepted, async_await, "1.39.0", Some(50547), None), /// Allows async functions to be declared, implemented, and used in traits. - (accepted, async_fn_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None), + (accepted, async_fn_in_trait, "1.75.0", Some(91611), None), /// Allows all literals in attribute lists and values of key-value pairs. (accepted, attr_literals, "1.30.0", Some(34981), None), /// Allows overloading augmented assignment operations like `a += b`. @@ -77,6 +77,8 @@ declare_features! ( (accepted, bindings_after_at, "1.56.0", Some(65490), None), /// Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720), None), + /// Allows `c"foo"` literals. + (accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723), None), /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. @@ -306,7 +308,7 @@ declare_features! ( /// Allows `#[repr(transparent)]` attribute on newtype structs. (accepted, repr_transparent, "1.28.0", Some(43036), None), /// Allows return-position `impl Trait` in traits. - (accepted, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None), + (accepted, return_position_impl_trait_in_trait, "1.75.0", Some(91611), None), /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), /// Allows `Self` in type definitions (RFC 2300). @@ -338,6 +340,9 @@ declare_features! ( /// Allows `#[track_caller]` to be used which provides /// accurate caller location reporting during panic (RFC 2091). (accepted, track_caller, "1.46.0", Some(47809), None), + /// Allows dyn upcasting trait objects via supertraits. + /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. + (accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991), None), /// Allows #[repr(transparent)] on univariant enums (RFC 2645). (accepted, transparent_enums, "1.42.0", Some(60405), None), /// Allows indexing tuples. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 214de3ca402ec..5523543cd4fb9 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -719,12 +719,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ and it is only intended to be used in `alloc`." ), - rustc_attr!( - rustc_host, AttributeType::Normal, template!(Word), ErrorFollowing, - "#[rustc_host] annotates const generic parameters as the `host` effect param, \ - and it is only intended for internal use and as a desugaring." - ), - BuiltinAttribute { name: sym::rustc_diagnostic_item, // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`. @@ -813,7 +807,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), rustc_attr!( TEST, rustc_error, Normal, - template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly + template!(Word, List: "span_delayed_bug_from_inside_query"), WarnFollowingWordOnly ), rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 070234df94c4f..73d51d9f80e6e 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -11,9 +11,9 @@ //! even if it is stabilized or removed, *do not remove it*. Instead, move the //! symbol to the `accepted` or `removed` modules respectively. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![feature(lazy_cell)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 03f92f69b41ef..c0d3fc3fae0f6 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -153,11 +153,14 @@ declare_features! ( (removed, panic_implementation, "1.28.0", Some(44489), None, Some("subsumed by `#[panic_handler]`")), /// Allows using `#![plugin(myplugin)]`. - (removed, plugin, "CURRENT_RUSTC_VERSION", Some(29597), None, + (removed, plugin, "1.75.0", Some(29597), None, Some("plugins are no longer supported")), /// Allows using `#[plugin_registrar]` on functions. (removed, plugin_registrar, "1.54.0", Some(29597), None, Some("plugins are no longer supported")), + /// Allows exhaustive integer pattern matching with `usize::MAX`/`isize::MIN`/`isize::MAX`. + (removed, precise_pointer_size_matching, "1.32.0", Some(56354), None, + Some("removed in favor of half-open ranges")), (removed, proc_macro_expr, "1.27.0", Some(54727), None, Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, proc_macro_gen, "1.27.0", Some(54727), None, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 11782e33d84bc..e68ab01738077 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -50,12 +50,16 @@ macro_rules! declare_features { }),+ ]; + const NUM_FEATURES: usize = UNSTABLE_FEATURES.len(); + /// A set of features to be used by later passes. #[derive(Clone, Default, Debug)] pub struct Features { /// `#![feature]` attrs for language features, for error reporting. + /// "declared" here means that the feature is actually enabled in the current crate. pub declared_lang_features: Vec<(Symbol, Span, Option)>, /// `#![feature]` attrs for non-language (library) features. + /// "declared" here means that the feature is actually enabled in the current crate. pub declared_lib_features: Vec<(Symbol, Span)>, /// `declared_lang_features` + `declared_lib_features`. pub declared_features: FxHashSet, @@ -82,8 +86,14 @@ macro_rules! declare_features { self.declared_features.insert(symbol); } - pub fn walk_feature_fields(&self, mut f: impl FnMut(&str, bool)) { - $(f(stringify!($feature), self.$feature);)+ + /// This is intended for hashing the set of active features. + /// + /// The expectation is that this produces much smaller code than other alternatives. + /// + /// Note that the total feature count is pretty small, so this is not a huge array. + #[inline] + pub fn all_features(&self) -> [u8; NUM_FEATURES] { + [$(self.$feature as u8),+] } /// Is the given feature explicitly declared, i.e. named in a @@ -125,9 +135,18 @@ macro_rules! declare_features { $( sym::$feature => status_to_enum!($status) == FeatureStatus::Internal, )* - // Accepted/removed features aren't in this file but are never internal - // (a removed feature might have been internal, but that's now irrelevant). - _ if self.declared_features.contains(&feature) => false, + _ if self.declared_features.contains(&feature) => { + // This could be accepted/removed, or a libs feature. + // Accepted/removed features aren't in this file but are never internal + // (a removed feature might have been internal, but that's now irrelevant). + // Libs features are internal if they end in `_internal` or `_internals`. + // As a special exception we also consider `core_intrinsics` internal; + // renaming that age-old feature is just not worth the hassle. + // We just always test the name; it's not a big deal if we accidentally hit + // an accepted/removed lang feature that way. + let name = feature.as_str(); + name == "core_intrinsics" || name.ends_with("_internal") || name.ends_with("_internals") + } _ => panic!("`{}` was not listed in `declare_features`", feature), } } @@ -147,7 +166,7 @@ macro_rules! declare_features { // was set. // // Note that the features are grouped into internal/user-facing and then -// sorted by version inside those groups. This is enforced with tidy. +// sorted alphabetically inside those groups. This is enforced with tidy. // // N.B., `tools/tidy/src/features.rs` parses this information directly out of the // source, so take care when modifying it. @@ -160,7 +179,7 @@ declare_features! ( // no-tracking-issue-start /// Allows using the `unadjusted` ABI; perma-unstable. - (unstable, abi_unadjusted, "1.16.0", None, None), + (internal, abi_unadjusted, "1.16.0", None, None), /// Allows using the `vectorcall` ABI. (unstable, abi_vectorcall, "1.7.0", None, None), /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. @@ -207,9 +226,6 @@ declare_features! ( (internal, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)), /// Added for testing unstable lints; perma-unstable. (internal, test_unstable_lint, "1.60.0", None, None), - /// Allows non-`unsafe` —and thus, unsound— access to `Pin` constructions. - /// Marked `internal` since perma-unstable and unsound. - (internal, unsafe_pin_internals, "1.60.0", None, None), /// Use for stable + negative coherence and strict coherence depending on trait's /// rustc_strict_coherence value. (unstable, with_negative_coherence, "1.60.0", None, None), @@ -346,8 +362,6 @@ declare_features! ( (unstable, async_fn_track_caller, "1.73.0", Some(110011), None), /// Allows builtin # foo() syntax (unstable, builtin_syntax, "1.71.0", Some(110680), None), - /// Allows `c"foo"` literals. - (unstable, c_str_literals, "1.71.0", Some(105723), None), /// Treat `extern "C"` function as nounwind. (unstable, c_unwind, "1.52.0", Some(74990), None), /// Allows using C-variadics. @@ -456,8 +470,10 @@ declare_features! ( (unstable, ffi_returns_twice, "1.34.0", Some(58314), None), /// Allows using `#[repr(align(...))]` on function items (unstable, fn_align, "1.53.0", Some(82232), None), + /// Support delegating implementation of functions to other already implemented functions. + (incomplete, fn_delegation, "CURRENT_RUSTC_VERSION", Some(118212), None), /// Allows defining gen blocks and `gen fn`. - (unstable, gen_blocks, "CURRENT_RUSTC_VERSION", Some(117078), None), + (unstable, gen_blocks, "1.75.0", Some(117078), None), /// Infer generic args for both consts and types. (unstable, generic_arg_infer, "1.55.0", Some(85077), None), /// An extension to the `generic_associated_types` feature, allowing incomplete features. @@ -490,6 +506,9 @@ declare_features! ( (incomplete, lazy_type_alias, "1.72.0", Some(112792), None), /// Allows `if/while p && let q = r && ...` chains. (unstable, let_chains, "1.37.0", Some(53667), None), + /// Allows using `#[link(kind = "link-arg", name = "...")]` + /// to pass custom arguments to the linker. + (unstable, link_arg_attribute, "CURRENT_RUSTC_VERSION", Some(99427), None), /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. (unstable, lint_reasons, "1.31.0", Some(54503), None), /// Give access to additional metadata about declarative macro meta-variables. @@ -510,6 +529,8 @@ declare_features! ( (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), /// Allow negative trait implementations. (unstable, negative_impls, "1.44.0", Some(68318), None), + /// Allows the `!` pattern. + (incomplete, never_patterns, "CURRENT_RUSTC_VERSION", Some(118155), None), /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. (unstable, never_type, "1.13.0", Some(35121), None), /// Allows diverging expressions to fall back to `!` rather than `()`. @@ -526,10 +547,10 @@ declare_features! ( /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. (unstable, object_safe_for_dispatch, "1.40.0", Some(43561), None), + /// Allows using enums in offset_of! + (unstable, offset_of_enum, "1.75.0", Some(106655), None), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882), None), - /// Allows exhaustive integer pattern matching on `usize` and `isize`. - (unstable, precise_pointer_size_matching, "1.32.0", Some(56354), None), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727), None), /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. @@ -560,9 +581,6 @@ declare_features! ( (unstable, thread_local, "1.0.0", Some(29594), None), /// Allows defining `trait X = A + B;` alias items. (unstable, trait_alias, "1.24.0", Some(41517), None), - /// Allows dyn upcasting trait objects via supertraits. - /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. - (unstable, trait_upcasting, "1.56.0", Some(65991), None), /// Allows for transmuting between arrays with sizes that contain generic consts. (unstable, transmute_generic_consts, "1.70.0", Some(109929), None), /// Allows #[repr(transparent)] on unions (RFC 2645). diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index 7479e4ef2b317..3b1b63455eddd 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -57,20 +57,20 @@ fn finish(body: TokenStream, resource: TokenStream) -> proc_macro::TokenStream { /// identifiers for different subdiagnostic kinds. pub mod _subdiag { /// Default for `#[help]` - pub const help: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); + pub const help: rustc_errors::SubdiagnosticMessage = + rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); /// Default for `#[note]` - pub const note: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); + pub const note: rustc_errors::SubdiagnosticMessage = + rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); /// Default for `#[warn]` - pub const warn: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn")); + pub const warn: rustc_errors::SubdiagnosticMessage = + rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn")); /// Default for `#[label]` - pub const label: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); + pub const label: rustc_errors::SubdiagnosticMessage = + rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); /// Default for `#[suggestion]` - pub const suggestion: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); + pub const suggestion: rustc_errors::SubdiagnosticMessage = + rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); } } } @@ -248,11 +248,8 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok format!("Constant referring to Fluent message `{name}` from `{crate_name}`"); constants.extend(quote! { #[doc = #docstr] - pub const #snake_name: crate::DiagnosticMessage = - crate::DiagnosticMessage::FluentIdentifier( - std::borrow::Cow::Borrowed(#name), - None - ); + pub const #snake_name: rustc_errors::DiagnosticMessage = + rustc_errors::DiagnosticMessage::FluentIdentifier(std::borrow::Cow::Borrowed(#name), None); }); for Attribute { id: Identifier { name: attr_name }, .. } in attributes { @@ -279,10 +276,8 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok ); constants.extend(quote! { #[doc = #msg] - pub const #snake_name: crate::SubdiagnosticMessage = - crate::SubdiagnosticMessage::FluentAttr( - std::borrow::Cow::Borrowed(#attr_name) - ); + pub const #snake_name: rustc_errors::SubdiagnosticMessage = + rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed(#attr_name)); }); } diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index 191fb787f706d..fc65d1eb8c4ce 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -1,7 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![allow(internal_features)] +#![feature(rustdoc_internals)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] #![deny(rustc::untranslatable_diagnostic)] @@ -61,6 +61,10 @@ mod fluent; /// ); /// err.emit(); /// ``` +/// +/// Note: any crate using this macro must also have a dependency on +/// `rustc_errors`, because the generated code refers to things from that +/// crate. #[proc_macro] pub fn fluent_messages(input: TokenStream) -> TokenStream { fluent::fluent_messages(input) diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 9cb279e3efdba..eba3215d93153 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -273,9 +273,9 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(allow(unused_variables), deny(warnings))) )] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] +#![allow(internal_features)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -522,33 +522,6 @@ impl<'a> LabelText<'a> { HtmlStr(ref s) => format!("<{s}>"), } } - - /// Decomposes content into string suitable for making EscStr that - /// yields same content as self. The result obeys the law - /// render(`lt`) == render(`EscStr(lt.pre_escaped_content())`) for - /// all `lt: LabelText`. - fn pre_escaped_content(self) -> Cow<'a, str> { - match self { - EscStr(s) => s, - LabelStr(s) => { - if s.contains('\\') { - s.escape_default().to_string().into() - } else { - s - } - } - HtmlStr(s) => s, - } - } - - /// Puts `suffix` on a line below this label, with a blank line separator. - pub fn suffix_line(self, suffix: LabelText<'_>) -> LabelText<'static> { - let mut prefix = self.pre_escaped_content().into_owned(); - let suffix = suffix.pre_escaped_content(); - prefix.push_str(r"\n\n"); - prefix.push_str(&suffix); - EscStr(prefix.into()) - } } pub type Nodes<'a, N> = Cow<'a, [N]>; diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index a72c4d0f18bc4..ac24c47d0b795 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -9,7 +9,6 @@ odht = { version = "0.3.1", features = ["nightly"] } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } -rustc_error_messages = { path = "../rustc_error_messages" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index e213623e06d91..f1f624269aee9 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -5,7 +5,6 @@ macro_rules! arena_types { ($macro:path) => ( $macro!([ // HIR types - [] hir_krate: rustc_hir::Crate<'tcx>, [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, [] owner_info: rustc_hir::OwnerInfo<'tcx>, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index ed1dc751fbab7..258d6710bc57f 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -1,3 +1,4 @@ +use crate::definitions::DefPathData; use crate::hir; use rustc_ast as ast; @@ -13,8 +14,7 @@ use std::array::IntoIter; use std::fmt::Debug; /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] -#[derive(HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum CtorOf { /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct. Struct, @@ -23,8 +23,7 @@ pub enum CtorOf { } /// What kind of constructor something is. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] -#[derive(HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum CtorKind { /// Constructor function automatically created by a tuple struct/variant. Fn, @@ -33,8 +32,7 @@ pub enum CtorKind { } /// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] -#[derive(HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum NonMacroAttrKind { /// Single-segment attribute defined by the language (`#[inline]`) Builtin(Symbol), @@ -48,8 +46,8 @@ pub enum NonMacroAttrKind { } /// What kind of definition something is; e.g., `mod` vs `struct`. -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] -#[derive(HashStable_Generic)] +/// `enum DefPathData` may need to be updated if a new variant is added here. +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum DefKind { // Type namespace Mod, @@ -118,7 +116,6 @@ pub enum DefKind { of_trait: bool, }, Closure, - Coroutine, } impl DefKind { @@ -161,7 +158,6 @@ impl DefKind { DefKind::Field => "field", DefKind::Impl { .. } => "implementation", DefKind::Closure => "closure", - DefKind::Coroutine => "coroutine", DefKind::ExternCrate => "extern crate", DefKind::GlobalAsm => "global assembly block", } @@ -220,7 +216,6 @@ impl DefKind { | DefKind::LifetimeParam | DefKind::ExternCrate | DefKind::Closure - | DefKind::Coroutine | DefKind::Use | DefKind::ForeignMod | DefKind::GlobalAsm @@ -228,9 +223,44 @@ impl DefKind { } } + pub fn def_path_data(self, name: Symbol) -> DefPathData { + match self { + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::TyParam + | DefKind::ExternCrate => DefPathData::TypeNs(name), + DefKind::Fn + | DefKind::Const + | DefKind::ConstParam + | DefKind::Static(..) + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Field => DefPathData::ValueNs(name), + DefKind::Macro(..) => DefPathData::MacroNs(name), + DefKind::LifetimeParam => DefPathData::LifetimeNs(name), + DefKind::Ctor(..) => DefPathData::Ctor, + DefKind::Use => DefPathData::Use, + DefKind::ForeignMod => DefPathData::ForeignMod, + DefKind::AnonConst => DefPathData::AnonConst, + DefKind::InlineConst => DefPathData::AnonConst, + DefKind::OpaqueTy => DefPathData::OpaqueTy, + DefKind::GlobalAsm => DefPathData::GlobalAsm, + DefKind::Impl { .. } => DefPathData::Impl, + DefKind::Closure => DefPathData::Closure, + } + } + #[inline] pub fn is_fn_like(self) -> bool { - matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Coroutine) + matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) } /// Whether `query get_codegen_attrs` should be used with this definition. @@ -240,7 +270,6 @@ impl DefKind { | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure - | DefKind::Coroutine | DefKind::Static(_) => true, DefKind::Mod | DefKind::Struct @@ -299,8 +328,7 @@ impl DefKind { /// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`] /// pointing to the definition of `str_to_string` in the current crate. // -#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] -#[derive(HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum Res { /// Definition having a unique ID (`DefId`), corresponds to something defined in user code. /// @@ -591,6 +619,8 @@ impl NonMacroAttrKind { } } + // Currently trivial, but exists in case a new kind is added in the future whose name starts + // with a vowel. pub fn article(self) -> &'static str { "a" } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 168b336e374fd..d222325475d33 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -246,6 +246,7 @@ impl DefPath { } } +/// New variants should only be added in synchronization with `enum DefKind`. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum DefPathData { // Root: these should only be used for the root nodes, because @@ -271,7 +272,7 @@ pub enum DefPathData { /// Something in the lifetime namespace. LifetimeNs(Symbol), /// A closure expression. - ClosureExpr, + Closure, // Subportions of items: /// Implicit constructor for a unit or tuple-like struct or enum variant. @@ -280,9 +281,7 @@ pub enum DefPathData { AnonConst, /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. - ImplTrait, - /// `impl Trait` generated associated type node. - ImplTraitAssocTy, + OpaqueTy, } impl Definitions { @@ -403,16 +402,17 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { + TypeNs(name) if name == kw::Empty => None, TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), - - Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst - | ImplTrait | ImplTraitAssocTy => None, + Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst + | OpaqueTy => None, } } pub fn name(&self) -> DefPathDataName { use self::DefPathData::*; match *self { + TypeNs(name) if name == kw::Empty => DefPathDataName::Anon { namespace: sym::opaque }, TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => { DefPathDataName::Named(name) } @@ -422,10 +422,10 @@ impl DefPathData { ForeignMod => DefPathDataName::Anon { namespace: kw::Extern }, Use => DefPathDataName::Anon { namespace: kw::Use }, GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm }, - ClosureExpr => DefPathDataName::Anon { namespace: sym::closure }, + Closure => DefPathDataName::Anon { namespace: sym::closure }, Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, - ImplTrait | ImplTraitAssocTy => DefPathDataName::Anon { namespace: sym::opaque }, + OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d88f165b9e538..3414b2f2412a9 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -7,13 +7,12 @@ use crate::LangItem; use rustc_ast as ast; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy}; -pub use rustc_ast::{BindingAnnotation, BorrowKind, ByRef, ImplPolarity, IsAuto}; -pub use rustc_ast::{CaptureBy, Movability, Mutability}; +pub use rustc_ast::{BinOp, BinOpKind, BindingAnnotation, BorrowKind, ByRef, CaptureBy}; +pub use rustc_ast::{ImplPolarity, IsAuto, Movability, Mutability, UnOp}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_error_messages::MultiSpan; use rustc_index::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::hygiene::MacroKind; @@ -76,13 +75,6 @@ impl ParamName { ParamName::Fresh | ParamName::Error => Ident::with_dummy_span(kw::UnderscoreLifetime), } } - - pub fn normalize_to_macros_2_0(&self) -> ParamName { - match *self { - ParamName::Plain(ident) => ParamName::Plain(ident.normalize_to_macros_2_0()), - param_name => param_name, - } - } } #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)] @@ -116,7 +108,7 @@ pub enum LifetimeName { } impl LifetimeName { - pub fn is_elided(&self) -> bool { + fn is_elided(&self) -> bool { match self { LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true, @@ -289,10 +281,6 @@ impl GenericArg<'_> { } } - pub fn is_synthetic(&self) -> bool { - matches!(self, GenericArg::Lifetime(lifetime) if lifetime.ident == Ident::empty()) - } - pub fn descr(&self) -> &'static str { match self { GenericArg::Lifetime(_) => "lifetime", @@ -368,11 +356,6 @@ impl<'hir> GenericArgs<'hir> { panic!("GenericArgs::inputs: not a `Fn(T) -> U`"); } - #[inline] - pub fn has_type_params(&self) -> bool { - self.args.iter().any(|arg| matches!(arg, GenericArg::Type(_))) - } - pub fn has_err(&self) -> bool { self.args.iter().any(|arg| match arg { GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err(_)), @@ -383,11 +366,6 @@ impl<'hir> GenericArgs<'hir> { }) } - #[inline] - pub fn num_type_params(&self) -> usize { - self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count() - } - #[inline] pub fn num_lifetime_params(&self) -> usize { self.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(_))).count() @@ -509,6 +487,7 @@ pub enum GenericParamKind<'hir> { ty: &'hir Ty<'hir>, /// Optional default value for the const generic param default: Option, + is_host_effect: bool, }, } @@ -589,14 +568,6 @@ impl<'hir> Generics<'hir> { self.params.iter().find(|¶m| name == param.name.ident().name) } - pub fn spans(&self) -> MultiSpan { - if self.params.is_empty() { - self.span.into() - } else { - self.params.iter().map(|p| p.span).collect::>().into() - } - } - /// If there are generic parameters, return where to introduce a new one. pub fn span_for_lifetime_suggestion(&self) -> Option { if let Some(first) = self.params.first() @@ -679,7 +650,7 @@ impl<'hir> Generics<'hir> { ) } - pub fn span_for_predicate_removal(&self, pos: usize) -> Span { + fn span_for_predicate_removal(&self, pos: usize) -> Span { let predicate = &self.predicates[pos]; let span = predicate.span(); @@ -812,7 +783,7 @@ pub struct WhereRegionPredicate<'hir> { impl<'hir> WhereRegionPredicate<'hir> { /// Returns `true` if `param_def_id` matches the `lifetime` of this predicate. - pub fn is_param_bound(&self, param_def_id: LocalDefId) -> bool { + fn is_param_bound(&self, param_def_id: LocalDefId) -> bool { self.lifetime.res == LifetimeName::Param(param_def_id) } } @@ -869,7 +840,7 @@ pub struct OwnerNodes<'tcx> { } impl<'tcx> OwnerNodes<'tcx> { - pub fn node(&self) -> OwnerNode<'tcx> { + fn node(&self) -> OwnerNode<'tcx> { use rustc_index::Idx; let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. @@ -1032,7 +1003,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, + Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), @@ -1059,7 +1030,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {} + Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {} Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), @@ -1085,6 +1056,23 @@ impl<'hir> Pat<'hir> { true }) } + + /// Whether this a never pattern. + pub fn is_never_pattern(&self) -> bool { + let mut is_never_pattern = false; + self.walk(|pat| match &pat.kind { + PatKind::Never => { + is_never_pattern = true; + false + } + PatKind::Or(s) => { + is_never_pattern = s.iter().all(|p| p.is_never_pattern()); + false + } + _ => true, + }); + is_never_pattern + } } /// A single field in a struct pattern. @@ -1172,6 +1160,9 @@ pub enum PatKind<'hir> { /// Invariant: `pats.len() >= 2`. Or(&'hir [Pat<'hir>]), + /// A never pattern `!`. + Never, + /// A path pattern for a unit struct/variant or a (maybe-associated) constant. Path(QPath<'hir>), @@ -1204,159 +1195,6 @@ pub enum PatKind<'hir> { Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]), } -#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] -pub enum BinOpKind { - /// The `+` operator (addition). - Add, - /// The `-` operator (subtraction). - Sub, - /// The `*` operator (multiplication). - Mul, - /// The `/` operator (division). - Div, - /// The `%` operator (modulus). - Rem, - /// The `&&` operator (logical and). - And, - /// The `||` operator (logical or). - Or, - /// The `^` operator (bitwise xor). - BitXor, - /// The `&` operator (bitwise and). - BitAnd, - /// The `|` operator (bitwise or). - BitOr, - /// The `<<` operator (shift left). - Shl, - /// The `>>` operator (shift right). - Shr, - /// The `==` operator (equality). - Eq, - /// The `<` operator (less than). - Lt, - /// The `<=` operator (less than or equal to). - Le, - /// The `!=` operator (not equal to). - Ne, - /// The `>=` operator (greater than or equal to). - Ge, - /// The `>` operator (greater than). - Gt, -} - -impl BinOpKind { - pub fn as_str(self) -> &'static str { - match self { - BinOpKind::Add => "+", - BinOpKind::Sub => "-", - BinOpKind::Mul => "*", - BinOpKind::Div => "/", - BinOpKind::Rem => "%", - BinOpKind::And => "&&", - BinOpKind::Or => "||", - BinOpKind::BitXor => "^", - BinOpKind::BitAnd => "&", - BinOpKind::BitOr => "|", - BinOpKind::Shl => "<<", - BinOpKind::Shr => ">>", - BinOpKind::Eq => "==", - BinOpKind::Lt => "<", - BinOpKind::Le => "<=", - BinOpKind::Ne => "!=", - BinOpKind::Ge => ">=", - BinOpKind::Gt => ">", - } - } - - pub fn is_lazy(self) -> bool { - matches!(self, BinOpKind::And | BinOpKind::Or) - } - - pub fn is_shift(self) -> bool { - matches!(self, BinOpKind::Shl | BinOpKind::Shr) - } - - pub fn is_comparison(self) -> bool { - match self { - BinOpKind::Eq - | BinOpKind::Lt - | BinOpKind::Le - | BinOpKind::Ne - | BinOpKind::Gt - | BinOpKind::Ge => true, - BinOpKind::And - | BinOpKind::Or - | BinOpKind::Add - | BinOpKind::Sub - | BinOpKind::Mul - | BinOpKind::Div - | BinOpKind::Rem - | BinOpKind::BitXor - | BinOpKind::BitAnd - | BinOpKind::BitOr - | BinOpKind::Shl - | BinOpKind::Shr => false, - } - } - - /// Returns `true` if the binary operator takes its arguments by value. - pub fn is_by_value(self) -> bool { - !self.is_comparison() - } -} - -impl Into for BinOpKind { - fn into(self) -> ast::BinOpKind { - match self { - BinOpKind::Add => ast::BinOpKind::Add, - BinOpKind::Sub => ast::BinOpKind::Sub, - BinOpKind::Mul => ast::BinOpKind::Mul, - BinOpKind::Div => ast::BinOpKind::Div, - BinOpKind::Rem => ast::BinOpKind::Rem, - BinOpKind::And => ast::BinOpKind::And, - BinOpKind::Or => ast::BinOpKind::Or, - BinOpKind::BitXor => ast::BinOpKind::BitXor, - BinOpKind::BitAnd => ast::BinOpKind::BitAnd, - BinOpKind::BitOr => ast::BinOpKind::BitOr, - BinOpKind::Shl => ast::BinOpKind::Shl, - BinOpKind::Shr => ast::BinOpKind::Shr, - BinOpKind::Eq => ast::BinOpKind::Eq, - BinOpKind::Lt => ast::BinOpKind::Lt, - BinOpKind::Le => ast::BinOpKind::Le, - BinOpKind::Ne => ast::BinOpKind::Ne, - BinOpKind::Ge => ast::BinOpKind::Ge, - BinOpKind::Gt => ast::BinOpKind::Gt, - } - } -} - -pub type BinOp = Spanned; - -#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] -pub enum UnOp { - /// The `*` operator (dereferencing). - Deref, - /// The `!` operator (logical negation). - Not, - /// The `-` operator (negation). - Neg, -} - -impl UnOp { - pub fn as_str(self) -> &'static str { - match self { - Self::Deref => "*", - Self::Not => "!", - Self::Neg => "-", - } - } - - /// Returns `true` if the unary operator takes its argument by value. - pub fn is_by_value(self) -> bool { - matches!(self, Self::Neg | Self::Not) - } -} - /// A statement. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Stmt<'hir> { @@ -1516,8 +1354,7 @@ impl<'hir> Body<'hir> { } /// The type of source expression that caused this coroutine to be created. -#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)] pub enum CoroutineKind { /// An explicit `async` block or the body of an async function. Async(CoroutineSource), @@ -1558,8 +1395,7 @@ impl fmt::Display for CoroutineKind { /// /// This helps error messages but is also used to drive coercions in /// type-checking (see #60424). -#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy, HashStable_Generic, Encodable, Decodable)] pub enum CoroutineSource { /// An explicit `async`/`gen` block written by the user. Block, @@ -2094,8 +1930,8 @@ pub enum QPath<'hir> { /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`. TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>), - /// Reference to a `#[lang = "foo"]` item. `HirId` of the inner expr. - LangItem(LangItem, Span, Option), + /// Reference to a `#[lang = "foo"]` item. + LangItem(LangItem, Span), } impl<'hir> QPath<'hir> { @@ -2104,7 +1940,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span), - QPath::LangItem(_, span, _) => span, + QPath::LangItem(_, span) => span, } } @@ -2114,17 +1950,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, _) => qself.span, - QPath::LangItem(_, span, _) => span, - } - } - - /// Returns the span of the last segment of this `QPath`. For example, `method` in - /// `<() as Trait>::method`. - pub fn last_segment_span(&self) -> Span { - match *self { - QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span, - QPath::TypeRelative(_, segment) => segment.ident.span, - QPath::LangItem(_, span, _) => span, + QPath::LangItem(_, span) => span, } } } @@ -2153,8 +1979,7 @@ pub enum LocalSource { } /// Hints at the original code for a `match _ { .. }`. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic, Encodable, Decodable)] pub enum MatchSource { /// A `match _ { .. }`. Normal, @@ -2314,6 +2139,35 @@ pub struct TraitItem<'hir> { pub defaultness: Defaultness, } +macro_rules! expect_methods_self_kind { + ( $( $name:ident, $ret_ty:ty, $pat:pat, $ret_val:expr; )* ) => { + $( + #[track_caller] + pub fn $name(&self) -> $ret_ty { + let $pat = &self.kind else { expect_failed(stringify!($ident), self) }; + $ret_val + } + )* + } +} + +macro_rules! expect_methods_self { + ( $( $name:ident, $ret_ty:ty, $pat:pat, $ret_val:expr; )* ) => { + $( + #[track_caller] + pub fn $name(&self) -> $ret_ty { + let $pat = self else { expect_failed(stringify!($ident), self) }; + $ret_val + } + )* + } +} + +#[track_caller] +fn expect_failed(ident: &'static str, found: T) -> ! { + panic!("{ident}: found {found:?}") +} + impl<'hir> TraitItem<'hir> { #[inline] pub fn hir_id(&self) -> HirId { @@ -2325,30 +2179,15 @@ impl<'hir> TraitItem<'hir> { TraitItemId { owner_id: self.owner_id } } - /// Expect an [`TraitItemKind::Const`] or panic. - #[track_caller] - pub fn expect_const(&self) -> (&'hir Ty<'hir>, Option) { - let TraitItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") }; - (ty, body) - } + expect_methods_self_kind! { + expect_const, (&'hir Ty<'hir>, Option), + TraitItemKind::Const(ty, body), (ty, *body); - /// Expect an [`TraitItemKind::Fn`] or panic. - #[track_caller] - pub fn expect_fn(&self) -> (&FnSig<'hir>, &TraitFn<'hir>) { - let TraitItemKind::Fn(ty, trfn) = &self.kind else { self.expect_failed("a function") }; - (ty, trfn) - } + expect_fn, (&FnSig<'hir>, &TraitFn<'hir>), + TraitItemKind::Fn(ty, trfn), (ty, trfn); - /// Expect an [`TraitItemKind::Type`] or panic. - #[track_caller] - pub fn expect_type(&self) -> (GenericBounds<'hir>, Option<&'hir Ty<'hir>>) { - let TraitItemKind::Type(bounds, ty) = self.kind else { self.expect_failed("a type") }; - (bounds, ty) - } - - #[track_caller] - fn expect_failed(&self, expected: &'static str) -> ! { - panic!("expected {expected} item, found {self:?}") + expect_type, (GenericBounds<'hir>, Option<&'hir Ty<'hir>>), + TraitItemKind::Type(bounds, ty), (bounds, *ty); } } @@ -2413,30 +2252,10 @@ impl<'hir> ImplItem<'hir> { ImplItemId { owner_id: self.owner_id } } - /// Expect an [`ImplItemKind::Const`] or panic. - #[track_caller] - pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) { - let ImplItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") }; - (ty, body) - } - - /// Expect an [`ImplItemKind::Fn`] or panic. - #[track_caller] - pub fn expect_fn(&self) -> (&FnSig<'hir>, BodyId) { - let ImplItemKind::Fn(ty, body) = &self.kind else { self.expect_failed("a function") }; - (ty, *body) - } - - /// Expect an [`ImplItemKind::Type`] or panic. - #[track_caller] - pub fn expect_type(&self) -> &'hir Ty<'hir> { - let ImplItemKind::Type(ty) = self.kind else { self.expect_failed("a type") }; - ty - } - - #[track_caller] - fn expect_failed(&self, expected: &'static str) -> ! { - panic!("expected {expected} item, found {self:?}") + expect_methods_self_kind! { + expect_const, (&'hir Ty<'hir>, BodyId), ImplItemKind::Const(ty, body), (ty, *body); + expect_fn, (&FnSig<'hir>, BodyId), ImplItemKind::Fn(ty, body), (ty, *body); + expect_type, &'hir Ty<'hir>, ImplItemKind::Type(ty), ty; } } @@ -2454,6 +2273,8 @@ pub enum ImplItemKind<'hir> { /// The name of the associated type for `Fn` return types. pub const FN_OUTPUT_NAME: Symbol = sym::Output; +/// The name of the associated type for `Iterator` item types. +pub const ITERATOR_ITEM_NAME: Symbol = sym::Item; /// Bind a type to an associated type (i.e., `A = Foo`). /// @@ -2579,8 +2400,7 @@ impl<'hir> Ty<'hir> { } /// Not represented directly in the AST; referred to by name through a `ty_path`. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] -#[derive(HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum PrimTy { Int(IntTy), Uint(UintTy), @@ -2860,8 +2680,7 @@ impl ImplicitSelfKind { } } -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] -#[derive(HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum IsAsync { Async(Span), NotAsync, @@ -3124,134 +2943,51 @@ impl<'hir> Item<'hir> { ItemId { owner_id: self.owner_id } } - /// Expect an [`ItemKind::ExternCrate`] or panic. - #[track_caller] - pub fn expect_extern_crate(&self) -> Option { - let ItemKind::ExternCrate(s) = self.kind else { self.expect_failed("an extern crate") }; - s - } + expect_methods_self_kind! { + expect_extern_crate, Option, ItemKind::ExternCrate(s), *s; - /// Expect an [`ItemKind::Use`] or panic. - #[track_caller] - pub fn expect_use(&self) -> (&'hir UsePath<'hir>, UseKind) { - let ItemKind::Use(p, uk) = self.kind else { self.expect_failed("a use") }; - (p, uk) - } + expect_use, (&'hir UsePath<'hir>, UseKind), ItemKind::Use(p, uk), (p, *uk); - /// Expect an [`ItemKind::Static`] or panic. - #[track_caller] - pub fn expect_static(&self) -> (&'hir Ty<'hir>, Mutability, BodyId) { - let ItemKind::Static(ty, mutbl, body) = self.kind else { self.expect_failed("a static") }; - (ty, mutbl, body) - } - /// Expect an [`ItemKind::Const`] or panic. - #[track_caller] - pub fn expect_const(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId) { - let ItemKind::Const(ty, gen, body) = self.kind else { self.expect_failed("a constant") }; - (ty, gen, body) - } - /// Expect an [`ItemKind::Fn`] or panic. - #[track_caller] - pub fn expect_fn(&self) -> (&FnSig<'hir>, &'hir Generics<'hir>, BodyId) { - let ItemKind::Fn(sig, gen, body) = &self.kind else { self.expect_failed("a function") }; - (sig, gen, *body) - } + expect_static, (&'hir Ty<'hir>, Mutability, BodyId), + ItemKind::Static(ty, mutbl, body), (ty, *mutbl, *body); - /// Expect an [`ItemKind::Macro`] or panic. - #[track_caller] - pub fn expect_macro(&self) -> (&ast::MacroDef, MacroKind) { - let ItemKind::Macro(def, mk) = &self.kind else { self.expect_failed("a macro") }; - (def, *mk) - } + expect_const, (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), + ItemKind::Const(ty, gen, body), (ty, gen, *body); - /// Expect an [`ItemKind::Mod`] or panic. - #[track_caller] - pub fn expect_mod(&self) -> &'hir Mod<'hir> { - let ItemKind::Mod(m) = self.kind else { self.expect_failed("a module") }; - m - } + expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, BodyId), + ItemKind::Fn(sig, gen, body), (sig, gen, *body); - /// Expect an [`ItemKind::ForeignMod`] or panic. - #[track_caller] - pub fn expect_foreign_mod(&self) -> (Abi, &'hir [ForeignItemRef]) { - let ItemKind::ForeignMod { abi, items } = self.kind else { - self.expect_failed("a foreign module") - }; - (abi, items) - } + expect_macro, (&ast::MacroDef, MacroKind), ItemKind::Macro(def, mk), (def, *mk); - /// Expect an [`ItemKind::GlobalAsm`] or panic. - #[track_caller] - pub fn expect_global_asm(&self) -> &'hir InlineAsm<'hir> { - let ItemKind::GlobalAsm(asm) = self.kind else { self.expect_failed("a global asm") }; - asm - } + expect_mod, &'hir Mod<'hir>, ItemKind::Mod(m), m; - /// Expect an [`ItemKind::TyAlias`] or panic. - #[track_caller] - pub fn expect_ty_alias(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>) { - let ItemKind::TyAlias(ty, gen) = self.kind else { self.expect_failed("a type alias") }; - (ty, gen) - } + expect_foreign_mod, (Abi, &'hir [ForeignItemRef]), + ItemKind::ForeignMod { abi, items }, (*abi, items); - /// Expect an [`ItemKind::OpaqueTy`] or panic. - #[track_caller] - pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> { - let ItemKind::OpaqueTy(ty) = &self.kind else { self.expect_failed("an opaque type") }; - ty - } + expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm(asm), asm; - /// Expect an [`ItemKind::Enum`] or panic. - #[track_caller] - pub fn expect_enum(&self) -> (&EnumDef<'hir>, &'hir Generics<'hir>) { - let ItemKind::Enum(def, gen) = &self.kind else { self.expect_failed("an enum") }; - (def, gen) - } + expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>), + ItemKind::TyAlias(ty, gen), (ty, gen); - /// Expect an [`ItemKind::Struct`] or panic. - #[track_caller] - pub fn expect_struct(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) { - let ItemKind::Struct(data, gen) = &self.kind else { self.expect_failed("a struct") }; - (data, gen) - } + expect_opaque_ty, &OpaqueTy<'hir>, ItemKind::OpaqueTy(ty), ty; - /// Expect an [`ItemKind::Union`] or panic. - #[track_caller] - pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) { - let ItemKind::Union(data, gen) = &self.kind else { self.expect_failed("a union") }; - (data, gen) - } + expect_enum, (&EnumDef<'hir>, &'hir Generics<'hir>), ItemKind::Enum(def, gen), (def, gen); - /// Expect an [`ItemKind::Trait`] or panic. - #[track_caller] - pub fn expect_trait( - self, - ) -> (IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]) { - let ItemKind::Trait(is_auto, unsafety, gen, bounds, items) = self.kind else { - self.expect_failed("a trait") - }; - (is_auto, unsafety, gen, bounds, items) - } + expect_struct, (&VariantData<'hir>, &'hir Generics<'hir>), + ItemKind::Struct(data, gen), (data, gen); - /// Expect an [`ItemKind::TraitAlias`] or panic. - #[track_caller] - pub fn expect_trait_alias(&self) -> (&'hir Generics<'hir>, GenericBounds<'hir>) { - let ItemKind::TraitAlias(gen, bounds) = self.kind else { - self.expect_failed("a trait alias") - }; - (gen, bounds) - } + expect_union, (&VariantData<'hir>, &'hir Generics<'hir>), + ItemKind::Union(data, gen), (data, gen); - /// Expect an [`ItemKind::Impl`] or panic. - #[track_caller] - pub fn expect_impl(&self) -> &'hir Impl<'hir> { - let ItemKind::Impl(imp) = self.kind else { self.expect_failed("an impl") }; - imp - } + expect_trait, + (IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), + ItemKind::Trait(is_auto, unsafety, gen, bounds, items), + (*is_auto, *unsafety, gen, bounds, items); - #[track_caller] - fn expect_failed(&self, expected: &'static str) -> ! { - panic!("expected {expected} item, found {self:?}") + expect_trait_alias, (&'hir Generics<'hir>, GenericBounds<'hir>), + ItemKind::TraitAlias(gen, bounds), (gen, bounds); + + expect_impl, &'hir Impl<'hir>, ItemKind::Impl(imp), imp; } } @@ -3280,8 +3016,7 @@ impl fmt::Display for Unsafety { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)] pub enum Constness { Const, NotConst, @@ -3566,6 +3301,15 @@ impl<'hir> OwnerNode<'hir> { } } + pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> { + match self { + OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) + | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) + | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig), + _ => None, + } + } + pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> { match self { OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) @@ -3615,32 +3359,11 @@ impl<'hir> OwnerNode<'hir> { } } - pub fn expect_item(self) -> &'hir Item<'hir> { - match self { - OwnerNode::Item(n) => n, - _ => panic!(), - } - } - - pub fn expect_foreign_item(self) -> &'hir ForeignItem<'hir> { - match self { - OwnerNode::ForeignItem(n) => n, - _ => panic!(), - } - } - - pub fn expect_impl_item(self) -> &'hir ImplItem<'hir> { - match self { - OwnerNode::ImplItem(n) => n, - _ => panic!(), - } - } - - pub fn expect_trait_item(self) -> &'hir TraitItem<'hir> { - match self { - OwnerNode::TraitItem(n) => n, - _ => panic!(), - } + expect_methods_self! { + expect_item, &'hir Item<'hir>, OwnerNode::Item(n), n; + expect_foreign_item, &'hir ForeignItem<'hir>, OwnerNode::ForeignItem(n), n; + expect_impl_item, &'hir ImplItem<'hir>, OwnerNode::ImplItem(n), n; + expect_trait_item, &'hir TraitItem<'hir>, OwnerNode::TraitItem(n), n; } } @@ -3893,196 +3616,33 @@ impl<'hir> Node<'hir> { } } - /// Get the fields for the tuple-constructor, - /// if this node is a tuple constructor, otherwise None - pub fn tuple_fields(&self) -> Option<&'hir [FieldDef<'hir>]> { - if let Node::Ctor(&VariantData::Tuple(fields, _, _)) = self { Some(fields) } else { None } - } - - /// Expect a [`Node::Param`] or panic. - #[track_caller] - pub fn expect_param(self) -> &'hir Param<'hir> { - let Node::Param(this) = self else { self.expect_failed("a parameter") }; - this - } - - /// Expect a [`Node::Item`] or panic. - #[track_caller] - pub fn expect_item(self) -> &'hir Item<'hir> { - let Node::Item(this) = self else { self.expect_failed("a item") }; - this - } - - /// Expect a [`Node::ForeignItem`] or panic. - #[track_caller] - pub fn expect_foreign_item(self) -> &'hir ForeignItem<'hir> { - let Node::ForeignItem(this) = self else { self.expect_failed("a foreign item") }; - this - } - - /// Expect a [`Node::TraitItem`] or panic. - #[track_caller] - pub fn expect_trait_item(self) -> &'hir TraitItem<'hir> { - let Node::TraitItem(this) = self else { self.expect_failed("a trait item") }; - this - } - - /// Expect a [`Node::ImplItem`] or panic. - #[track_caller] - pub fn expect_impl_item(self) -> &'hir ImplItem<'hir> { - let Node::ImplItem(this) = self else { self.expect_failed("an implementation item") }; - this - } - - /// Expect a [`Node::Variant`] or panic. - #[track_caller] - pub fn expect_variant(self) -> &'hir Variant<'hir> { - let Node::Variant(this) = self else { self.expect_failed("a variant") }; - this - } - - /// Expect a [`Node::Field`] or panic. - #[track_caller] - pub fn expect_field(self) -> &'hir FieldDef<'hir> { - let Node::Field(this) = self else { self.expect_failed("a field definition") }; - this - } - - /// Expect a [`Node::AnonConst`] or panic. - #[track_caller] - pub fn expect_anon_const(self) -> &'hir AnonConst { - let Node::AnonConst(this) = self else { self.expect_failed("an anonymous constant") }; - this - } - - /// Expect a [`Node::ConstBlock`] or panic. - #[track_caller] - pub fn expect_inline_const(self) -> &'hir ConstBlock { - let Node::ConstBlock(this) = self else { self.expect_failed("an inline constant") }; - this - } - - /// Expect a [`Node::Expr`] or panic. - #[track_caller] - pub fn expect_expr(self) -> &'hir Expr<'hir> { - let Node::Expr(this) = self else { self.expect_failed("an expression") }; - this - } - /// Expect a [`Node::ExprField`] or panic. - #[track_caller] - pub fn expect_expr_field(self) -> &'hir ExprField<'hir> { - let Node::ExprField(this) = self else { self.expect_failed("an expression field") }; - this - } - - /// Expect a [`Node::Stmt`] or panic. - #[track_caller] - pub fn expect_stmt(self) -> &'hir Stmt<'hir> { - let Node::Stmt(this) = self else { self.expect_failed("a statement") }; - this - } - - /// Expect a [`Node::PathSegment`] or panic. - #[track_caller] - pub fn expect_path_segment(self) -> &'hir PathSegment<'hir> { - let Node::PathSegment(this) = self else { self.expect_failed("a path segment") }; - this - } - - /// Expect a [`Node::Ty`] or panic. - #[track_caller] - pub fn expect_ty(self) -> &'hir Ty<'hir> { - let Node::Ty(this) = self else { self.expect_failed("a type") }; - this - } - - /// Expect a [`Node::TypeBinding`] or panic. - #[track_caller] - pub fn expect_type_binding(self) -> &'hir TypeBinding<'hir> { - let Node::TypeBinding(this) = self else { self.expect_failed("a type binding") }; - this - } - - /// Expect a [`Node::TraitRef`] or panic. - #[track_caller] - pub fn expect_trait_ref(self) -> &'hir TraitRef<'hir> { - let Node::TraitRef(this) = self else { self.expect_failed("a trait reference") }; - this - } - - /// Expect a [`Node::Pat`] or panic. - #[track_caller] - pub fn expect_pat(self) -> &'hir Pat<'hir> { - let Node::Pat(this) = self else { self.expect_failed("a pattern") }; - this - } - - /// Expect a [`Node::PatField`] or panic. - #[track_caller] - pub fn expect_pat_field(self) -> &'hir PatField<'hir> { - let Node::PatField(this) = self else { self.expect_failed("a pattern field") }; - this - } - - /// Expect a [`Node::Arm`] or panic. - #[track_caller] - pub fn expect_arm(self) -> &'hir Arm<'hir> { - let Node::Arm(this) = self else { self.expect_failed("an arm") }; - this - } - - /// Expect a [`Node::Block`] or panic. - #[track_caller] - pub fn expect_block(self) -> &'hir Block<'hir> { - let Node::Block(this) = self else { self.expect_failed("a block") }; - this - } - - /// Expect a [`Node::Local`] or panic. - #[track_caller] - pub fn expect_local(self) -> &'hir Local<'hir> { - let Node::Local(this) = self else { self.expect_failed("a local") }; - this - } - - /// Expect a [`Node::Ctor`] or panic. - #[track_caller] - pub fn expect_ctor(self) -> &'hir VariantData<'hir> { - let Node::Ctor(this) = self else { self.expect_failed("a constructor") }; - this - } - - /// Expect a [`Node::Lifetime`] or panic. - #[track_caller] - pub fn expect_lifetime(self) -> &'hir Lifetime { - let Node::Lifetime(this) = self else { self.expect_failed("a lifetime") }; - this - } - - /// Expect a [`Node::GenericParam`] or panic. - #[track_caller] - pub fn expect_generic_param(self) -> &'hir GenericParam<'hir> { - let Node::GenericParam(this) = self else { self.expect_failed("a generic parameter") }; - this - } - - /// Expect a [`Node::Crate`] or panic. - #[track_caller] - pub fn expect_crate(self) -> &'hir Mod<'hir> { - let Node::Crate(this) = self else { self.expect_failed("a crate") }; - this - } - - /// Expect a [`Node::Infer`] or panic. - #[track_caller] - pub fn expect_infer(self) -> &'hir InferArg { - let Node::Infer(this) = self else { self.expect_failed("an infer") }; - this - } - - #[track_caller] - fn expect_failed(&self, expected: &'static str) -> ! { - panic!("expected {expected} node, found {self:?}") + expect_methods_self! { + expect_param, &'hir Param<'hir>, Node::Param(n), n; + expect_item, &'hir Item<'hir>, Node::Item(n), n; + expect_foreign_item, &'hir ForeignItem<'hir>, Node::ForeignItem(n), n; + expect_trait_item, &'hir TraitItem<'hir>, Node::TraitItem(n), n; + expect_impl_item, &'hir ImplItem<'hir>, Node::ImplItem(n), n; + expect_variant, &'hir Variant<'hir>, Node::Variant(n), n; + expect_field, &'hir FieldDef<'hir>, Node::Field(n), n; + expect_anon_const, &'hir AnonConst, Node::AnonConst(n), n; + expect_inline_const, &'hir ConstBlock, Node::ConstBlock(n), n; + expect_expr, &'hir Expr<'hir>, Node::Expr(n), n; + expect_expr_field, &'hir ExprField<'hir>, Node::ExprField(n), n; + expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n; + expect_path_segment, &'hir PathSegment<'hir>, Node::PathSegment(n), n; + expect_ty, &'hir Ty<'hir>, Node::Ty(n), n; + expect_type_binding, &'hir TypeBinding<'hir>, Node::TypeBinding(n), n; + expect_trait_ref, &'hir TraitRef<'hir>, Node::TraitRef(n), n; + expect_pat, &'hir Pat<'hir>, Node::Pat(n), n; + expect_pat_field, &'hir PatField<'hir>, Node::PatField(n), n; + expect_arm, &'hir Arm<'hir>, Node::Arm(n), n; + expect_block, &'hir Block<'hir>, Node::Block(n), n; + expect_local, &'hir Local<'hir>, Node::Local(n), n; + expect_ctor, &'hir VariantData<'hir>, Node::Ctor(n), n; + expect_lifetime, &'hir Lifetime, Node::Lifetime(n), n; + expect_generic_param, &'hir GenericParam<'hir>, Node::GenericParam(n), n; + expect_crate, &'hir Mod<'hir>, Node::Crate(n), n; + expect_infer, &'hir InferArg, Node::Infer(n), n; } } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 34c6157793663..d339075c171d1 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -3,8 +3,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, use rustc_span::{def_id::DefPathHash, HashStableContext}; use std::fmt::{self, Debug}; -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[derive(Encodable, Decodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] pub struct OwnerId { pub def_id: LocalDefId, } @@ -73,8 +72,7 @@ impl ToStableHashKey for OwnerId { /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)] #[rustc_pass_by_value] pub struct HirId { pub owner: OwnerId, @@ -156,6 +154,8 @@ rustc_index::newtype_index! { /// an "item-like" to something else can be implemented by a `Vec` instead of a /// tree or hash map. #[derive(HashStable_Generic)] + #[encodable] + #[orderable] pub struct ItemLocalId {} } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8a67285598998..9cf1db166a581 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -660,7 +660,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, upper_bound); } - PatKind::Wild => (), + PatKind::Never | PatKind::Wild => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { walk_list!(visitor, visit_pat, prepatterns); walk_list!(visitor, visit_pat, slice_pattern); @@ -874,7 +874,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default), - GenericParamKind::Const { ref ty, ref default } => { + GenericParamKind::Const { ref ty, ref default, is_host_effect: _ } => { visitor.visit_ty(ty); if let Some(ref default) = default { visitor.visit_const_param_default(param.hir_id, default); diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 1d1a1ee886272..60f1449c177cb 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -233,7 +233,7 @@ language_item_table! { PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None; ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None; PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0); - PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0); + PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0); PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None; PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None; PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 094d5b1e77cf7..87de3c0870bc9 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -4,7 +4,6 @@ #![feature(associated_type_defaults)] #![feature(closure_track_caller)] -#![feature(const_btree_len)] #![feature(let_chains)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 8ab91bebcf672..139e1c0ac5fdc 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -1,8 +1,28 @@ +hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$ty_param_name}` + .label = ambiguous associated {$assoc_kind} `{$assoc_name}` + hir_analysis_ambiguous_lifetime_bound = ambiguous lifetime bound, explicit lifetime bound required -hir_analysis_assoc_bound_on_const = expected associated type, found {$descr} - .note = trait bounds not allowed on {$descr} +hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}` + +hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named -> + [true] an + *[false] a similarly named + } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}` +hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found +hir_analysis_assoc_item_not_found_other_sugg = `{$ty_param_name}` has the following associated {$assoc_kind} +hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}` +hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = and also change the associated {$assoc_kind} name +hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name + +hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got} + .label = unexpected {$got} + .expected_because_label = expected a {$expected} because of this associated {$expected} + .note = the associated {$assoc_kind} is defined here + .bound_on_assoc_const_label = bounds are not allowed on associated constants + +hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here hir_analysis_assoc_type_binding_not_allowed = associated type bindings are not allowed here @@ -280,10 +300,6 @@ hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is no hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}` -hir_analysis_return_type_notation_conflicting_bound = - ambiguous associated function `{$assoc_name}` for `{$ty_name}` - .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}` - hir_analysis_return_type_notation_equality_bound = return type notation is not allowed to use type equality @@ -294,9 +310,6 @@ hir_analysis_return_type_notation_illegal_param_type = return type notation is not allowed for functions that have type parameters .label = type parameter declared here -hir_analysis_return_type_notation_missing_method = - cannot find associated function `{$assoc_name}` for `{$ty_name}` - hir_analysis_return_type_notation_on_non_rpitit = return type notation used on function that is not `async` and does not return `impl Trait` .note = function returns `{$ty}`, which is not compatible with associated type return bounds diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 3e700f2da8696..dfec3c5e829a6 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -3,8 +3,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_lint_defs::Applicability; -use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self as ty, Ty}; use rustc_span::symbol::Ident; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; @@ -194,8 +193,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { self.add_bounds( param_ty, - ast_bounds.iter().filter(|bound| { - match filter { + ast_bounds.iter().filter(|bound| match filter { PredicateFilter::All | PredicateFilter::SelfOnly | PredicateFilter::SelfAndAssociatedTypeBounds => true, @@ -209,7 +207,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { false } } - } }), &mut bounds, ty::List::empty(), @@ -258,64 +255,49 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let tcx = self.tcx(); - let return_type_notation = - binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation; - - let candidate = if return_type_notation { - if self.trait_defines_associated_item_named( - trait_ref.def_id(), - ty::AssocKind::Fn, - binding.item_name, - ) { - trait_ref + let assoc_kind = + if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { + ty::AssocKind::Fn + } else if let ConvertedBindingKind::Equality(term) = binding.kind + && let ty::TermKind::Const(_) = term.node.unpack() + { + ty::AssocKind::Const } else { - self.one_bound_for_assoc_method( - traits::supertraits(tcx, trait_ref), - trait_ref.print_only_trait_path(), - binding.item_name, - path_span, - )? - } - } else if self.trait_defines_associated_item_named( + ty::AssocKind::Type + }; + + let candidate = if self.trait_defines_associated_item_named( trait_ref.def_id(), - ty::AssocKind::Type, + assoc_kind, binding.item_name, ) { - // Simple case: X is defined in the current trait. + // Simple case: The assoc item is defined in the current trait. trait_ref } else { // Otherwise, we have to walk through the supertraits to find - // those that do. - self.one_bound_for_assoc_type( + // one that does define it. + self.one_bound_for_assoc_item( || traits::supertraits(tcx, trait_ref), trait_ref.skip_binder().print_only_trait_name(), None, + assoc_kind, binding.item_name, path_span, - match binding.kind { - ConvertedBindingKind::Equality(term) => Some(term), - _ => None, - }, + Some(&binding), )? }; let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); - // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead - // of calling `filter_by_name_and_kind`. - let find_item_of_kind = |kind| { - tcx.associated_items(candidate.def_id()) - .filter_by_name_unhygienic(assoc_ident.name) - .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) - }; - let assoc_item = if return_type_notation { - find_item_of_kind(ty::AssocKind::Fn) - } else { - find_item_of_kind(ty::AssocKind::Type) - .or_else(|| find_item_of_kind(ty::AssocKind::Const)) - } - .expect("missing associated type"); + // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` + // instead of calling `filter_by_name_and_kind` which would needlessly normalize the + // `assoc_ident` again and again. + let assoc_item = tcx + .associated_items(candidate.def_id()) + .filter_by_name_unhygienic(assoc_ident.name) + .find(|i| i.kind == assoc_kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) + .expect("missing associated item"); if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { tcx.sess @@ -342,7 +324,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { .or_insert(binding.span); } - let projection_ty = if return_type_notation { + let projection_ty = if let ty::AssocKind::Fn = assoc_kind { let mut emitted_bad_param_err = false; // If we have an method return type bound, then we need to substitute // the method's early bound params with suitable late-bound params. @@ -350,7 +332,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let args = candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| { let subst = match param.kind { - ty::GenericParamDefKind::Lifetime => ty::Region::new_late_bound( + ty::GenericParamDefKind::Lifetime => ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { @@ -469,7 +451,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&projection_ty); let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); + tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty.node)); debug!(?late_bound_in_trait_ref); debug!(?late_bound_in_ty); @@ -494,77 +476,27 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } } - let assoc_item_def_id = projection_ty.skip_binder().def_id; - let def_kind = tcx.def_kind(assoc_item_def_id); match binding.kind { - ConvertedBindingKind::Equality(..) if return_type_notation => { + ConvertedBindingKind::Equality(..) if let ty::AssocKind::Fn = assoc_kind => { return Err(self.tcx().sess.emit_err( crate::errors::ReturnTypeNotationEqualityBound { span: binding.span }, )); } - ConvertedBindingKind::Equality(mut term) => { + ConvertedBindingKind::Equality(term) => { // "Desugar" a constraint like `T: Iterator` this to // the "projection predicate" for: // // `::Item = u32` - match (def_kind, term.unpack()) { - (DefKind::AssocTy, ty::TermKind::Ty(_)) - | (DefKind::AssocConst, ty::TermKind::Const(_)) => (), - (_, _) => { - let got = if let Some(_) = term.ty() { "type" } else { "constant" }; - let expected = tcx.def_descr(assoc_item_def_id); - let mut err = tcx.sess.struct_span_err( - binding.span, - format!("expected {expected} bound, found {got}"), - ); - err.span_note( - tcx.def_span(assoc_item_def_id), - format!("{expected} defined here"), - ); - - if let DefKind::AssocConst = def_kind - && let Some(t) = term.ty() - && (t.is_enum() || t.references_error()) - && tcx.features().associated_const_equality - { - err.span_suggestion( - binding.span, - "if equating a const, try wrapping with braces", - format!("{} = {{ const }}", binding.item_name), - Applicability::HasPlaceholders, - ); - } - let reported = err.emit(); - term = match def_kind { - DefKind::AssocTy => Ty::new_error(tcx, reported).into(), - DefKind::AssocConst => ty::Const::new_error( - tcx, - reported, - tcx.type_of(assoc_item_def_id) - .instantiate(tcx, projection_ty.skip_binder().args), - ) - .into(), - _ => unreachable!(), - }; - } - } bounds.push_projection_bound( tcx, - projection_ty - .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), + projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { + projection_ty, + term: term.node, + }), binding.span, ); } ConvertedBindingKind::Constraint(ast_bounds) => { - match def_kind { - DefKind::AssocTy => {} - _ => { - return Err(tcx.sess.emit_err(errors::AssocBoundOnConst { - span: assoc_ident.span, - descr: tcx.def_descr(assoc_item_def_id), - })); - } - } // "Desugar" a constraint like `T: Iterator` to // // `::Item: Debug` diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 32be7e0837b6d..13ad9a453b2bf 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -1,23 +1,22 @@ -use crate::astconv::AstConv; +use crate::astconv::{AstConv, ConvertedBindingKind}; use crate::errors::{ - AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, + self, AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, ParenthesizedFnTraitExpansion, }; +use crate::fluent_generated as fluent; use crate::traits::error_reporting::report_object_safety_error; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::FulfillmentError; -use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt}; +use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol, DUMMY_SP}; use rustc_trait_selection::traits::object_safety_violations_for_assoc_item; -use std::collections::BTreeSet; - impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// On missing type parameters, emit an E0393 error and provide a structured suggestion using /// the type parameter's name as a placeholder. @@ -99,83 +98,88 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - pub(crate) fn complain_about_assoc_type_not_found( + pub(super) fn complain_about_assoc_item_not_found( &self, all_candidates: impl Fn() -> I, ty_param_name: &str, ty_param_def_id: Option, + assoc_kind: ty::AssocKind, assoc_name: Ident, span: Span, + binding: Option<&super::ConvertedBinding<'_, 'tcx>>, ) -> ErrorGuaranteed where I: Iterator>, { + let tcx = self.tcx(); + + // First and foremost, provide a more user-friendly & “intuitive” error on kind mismatches. + if let Some(assoc_item) = all_candidates().find_map(|r| { + tcx.associated_items(r.def_id()) + .filter_by_name_unhygienic(assoc_name.name) + .find(|item| tcx.hygienic_eq(assoc_name, item.ident(tcx), r.def_id())) + }) { + return self.complain_about_assoc_kind_mismatch( + assoc_item, assoc_kind, assoc_name, span, binding, + ); + } + + let assoc_kind_str = super::assoc_kind_str(assoc_kind); + // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a // valid span, so we point at the whole path segment instead. let is_dummy = assoc_name.span == DUMMY_SP; - let mut err = struct_span_err!( - self.tcx().sess, - if is_dummy { span } else { assoc_name.span }, - E0220, - "associated type `{}` not found for `{}`", + let mut err = errors::AssocItemNotFound { + span: if is_dummy { span } else { assoc_name.span }, assoc_name, - ty_param_name - ); + assoc_kind: assoc_kind_str, + ty_param_name, + label: None, + sugg: None, + }; if is_dummy { - err.span_label(span, format!("associated type `{assoc_name}` not found")); - return err.emit(); + err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span }); + return tcx.sess.emit_err(err); } let all_candidate_names: Vec<_> = all_candidates() - .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order()) + .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order()) .filter_map(|item| { - if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type { - Some(item.name) - } else { - None - } + (!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name) }) .collect(); if let Some(suggested_name) = find_best_match_for_name(&all_candidate_names, assoc_name.name, None) { - err.span_suggestion( - assoc_name.span, - "there is an associated type with a similar name", + err.sugg = Some(errors::AssocItemNotFoundSugg::Similar { + span: assoc_name.span, + assoc_kind: assoc_kind_str, suggested_name, - Applicability::MaybeIncorrect, - ); - return err.emit(); + }); + return tcx.sess.emit_err(err); } // If we didn't find a good item in the supertraits (or couldn't get // the supertraits), like in ItemCtxt, then look more generally from // all visible traits. If there's one clear winner, just suggest that. - let visible_traits: Vec<_> = self - .tcx() + let visible_traits: Vec<_> = tcx .all_traits() .filter(|trait_def_id| { - let viz = self.tcx().visibility(*trait_def_id); + let viz = tcx.visibility(*trait_def_id); let def_id = self.item_def_id(); - viz.is_accessible_from(def_id, self.tcx()) + viz.is_accessible_from(def_id, tcx) }) .collect(); let wider_candidate_names: Vec<_> = visible_traits .iter() - .flat_map(|trait_def_id| { - self.tcx().associated_items(*trait_def_id).in_definition_order() - }) + .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order()) .filter_map(|item| { - if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type { - Some(item.name) - } else { - None - } + (!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name) }) .collect(); @@ -184,96 +188,155 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { if let [best_trait] = visible_traits .iter() + .copied() .filter(|trait_def_id| { - self.tcx() - .associated_items(*trait_def_id) + tcx.associated_items(trait_def_id) .filter_by_name_unhygienic(suggested_name) - .any(|item| item.kind == ty::AssocKind::Type) + .any(|item| item.kind == assoc_kind) }) .collect::>()[..] { - let trait_name = self.tcx().def_path_str(*best_trait); - let an = if suggested_name != assoc_name.name { "a similarly named" } else { "an" }; - err.span_label( - assoc_name.span, - format!( - "there is {an} associated type `{suggested_name}` in the \ - trait `{trait_name}`", - ), - ); - let hir = self.tcx().hir(); + let trait_name = tcx.def_path_str(best_trait); + err.label = Some(errors::AssocItemNotFoundLabel::FoundInOtherTrait { + span: assoc_name.span, + assoc_kind: assoc_kind_str, + trait_name: &trait_name, + suggested_name, + identically_named: suggested_name == assoc_name.name, + }); + let hir = tcx.hir(); if let Some(def_id) = ty_param_def_id - && let parent = hir.get_parent_item(hir.local_def_id_to_hir_id(def_id)) + && let parent = hir.get_parent_item(tcx.local_def_id_to_hir_id(def_id)) && let Some(generics) = hir.get_generics(parent.def_id) { - if generics.bounds_for_param(def_id) - .flat_map(|pred| pred.bounds.iter()) - .any(|b| match b { + if generics.bounds_for_param(def_id).flat_map(|pred| pred.bounds.iter()).any( + |b| match b { hir::GenericBound::Trait(t, ..) => { - t.trait_ref.trait_def_id().as_ref() == Some(best_trait) + t.trait_ref.trait_def_id() == Some(best_trait) } _ => false, - }) - { + }, + ) { // The type param already has a bound for `trait_name`, we just need to - // change the associated type. - err.span_suggestion_verbose( - assoc_name.span, - format!( - "change the associated type name to use `{suggested_name}` from \ - `{trait_name}`", - ), - suggested_name.to_string(), - Applicability::MaybeIncorrect, - ); - } else if suggest_constraining_type_param( - self.tcx(), - generics, - &mut err, - &ty_param_name, - &trait_name, - None, - None, - ) - && suggested_name != assoc_name.name + // change the associated item. + err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait { + span: assoc_name.span, + assoc_kind: assoc_kind_str, + suggested_name, + }); + return tcx.sess.emit_err(err); + } + + let mut err = tcx.sess.create_err(err); + if suggest_constraining_type_param( + tcx, + generics, + &mut err, + &ty_param_name, + &trait_name, + None, + None, + ) && suggested_name != assoc_name.name { // We suggested constraining a type parameter, but the associated type on it // was also not an exact match, so we also suggest changing it. err.span_suggestion_verbose( assoc_name.span, - "and also change the associated type name", + fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, suggested_name.to_string(), Applicability::MaybeIncorrect, ); } + return err.emit(); } - return err.emit(); + return tcx.sess.emit_err(err); } } // If we still couldn't find any associated type, and only one associated type exists, // suggests using it. - - if all_candidate_names.len() == 1 { + if let [candidate_name] = all_candidate_names.as_slice() { // this should still compile, except on `#![feature(associated_type_defaults)]` // where it could suggests `type A = Self::A`, thus recursing infinitely - let applicability = if self.tcx().features().associated_type_defaults { + let applicability = if tcx.features().associated_type_defaults { Applicability::Unspecified } else { Applicability::MaybeIncorrect }; - err.span_suggestion( - assoc_name.span, - format!("`{ty_param_name}` has the following associated type"), - all_candidate_names.first().unwrap().to_string(), + err.sugg = Some(errors::AssocItemNotFoundSugg::Other { + span: assoc_name.span, applicability, - ); + ty_param_name, + assoc_kind: assoc_kind_str, + suggested_name: *candidate_name, + }); } else { - err.span_label(assoc_name.span, format!("associated type `{assoc_name}` not found")); + err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_name.span }); } - err.emit() + tcx.sess.emit_err(err) + } + + fn complain_about_assoc_kind_mismatch( + &self, + assoc_item: &ty::AssocItem, + assoc_kind: ty::AssocKind, + ident: Ident, + span: Span, + binding: Option<&super::ConvertedBinding<'_, 'tcx>>, + ) -> ErrorGuaranteed { + let tcx = self.tcx(); + + let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind + && let Some(binding) = binding + && let ConvertedBindingKind::Constraint(_) = binding.kind + { + let lo = if binding.gen_args.span_ext.is_dummy() { + ident.span + } else { + binding.gen_args.span_ext + }; + Some(lo.between(span.shrink_to_hi())) + } else { + None + }; + + // FIXME(associated_const_equality): This has quite a few false positives and negatives. + let wrap_in_braces_sugg = if let Some(binding) = binding + && let ConvertedBindingKind::Equality(term) = binding.kind + && let ty::TermKind::Ty(ty) = term.node.unpack() + && (ty.is_enum() || ty.references_error()) + && tcx.features().associated_const_equality + { + Some(errors::AssocKindMismatchWrapInBracesSugg { + lo: term.span.shrink_to_lo(), + hi: term.span.shrink_to_hi(), + }) + } else { + None + }; + + // For equality bounds, we want to blame the term (RHS) instead of the item (LHS) since + // one can argue that that's more “untuitive” to the user. + let (span, expected_because_label, expected, got) = if let Some(binding) = binding + && let ConvertedBindingKind::Equality(term) = binding.kind + { + (term.span, Some(ident.span), assoc_item.kind, assoc_kind) + } else { + (ident.span, None, assoc_kind, assoc_item.kind) + }; + + tcx.sess.emit_err(errors::AssocKindMismatch { + span, + expected: super::assoc_kind_str(expected), + got: super::assoc_kind_str(got), + expected_because_label, + assoc_kind: super::assoc_kind_str(assoc_item.kind), + def_span: tcx.def_span(assoc_item.def_id), + bound_on_assoc_const_label, + wrap_in_braces_sugg, + }) } pub(crate) fn complain_about_ambiguous_inherent_assoc_type( @@ -506,23 +569,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// emit a generic note suggesting using a `where` clause to constraint instead. pub(crate) fn complain_about_missing_associated_types( &self, - associated_types: FxHashMap>, + associated_types: FxIndexMap>, potential_assoc_types: Vec, trait_bounds: &[hir::PolyTraitRef<'_>], ) { if associated_types.values().all(|v| v.is_empty()) { return; } + let tcx = self.tcx(); // FIXME: Marked `mut` so that we can replace the spans further below with a more // appropriate one, but this should be handled earlier in the span assignment. - let mut associated_types: FxHashMap> = associated_types + let mut associated_types: FxIndexMap> = associated_types .into_iter() .map(|(span, def_ids)| { (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect()) }) .collect(); - let mut names: FxHashMap> = Default::default(); + let mut names: FxIndexMap> = Default::default(); let mut names_len = 0; // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and @@ -585,6 +649,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + // We get all the associated items that _are_ set, + // so that we can check if any of their names match one of the ones we are missing. + // This would mean that they are shadowing the associated type we are missing, + // and we can then use their span to indicate this to the user. + let bound_names = trait_bounds + .iter() + .filter_map(|poly_trait_ref| { + let path = poly_trait_ref.trait_ref.path.segments.last()?; + let args = path.args?; + + Some(args.bindings.iter().filter_map(|binding| { + let ident = binding.ident; + let trait_def = path.res.def_id(); + let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind( + tcx, + ident, + ty::AssocKind::Type, + trait_def, + ); + + Some((ident.name, assoc_item?)) + })) + }) + .flatten() + .collect::>(); + let mut names = names .into_iter() .map(|(trait_, mut assocs)| { @@ -625,16 +715,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { *names.entry(item.name).or_insert(0) += 1; } let mut dupes = false; + let mut shadows = false; for item in assoc_items { let prefix = if names[&item.name] > 1 { let trait_def_id = item.container_id(tcx); dupes = true; format!("{}::", tcx.def_path_str(trait_def_id)) + } else if bound_names.get(&item.name).is_some_and(|x| x != &item) { + let trait_def_id = item.container_id(tcx); + shadows = true; + format!("{}::", tcx.def_path_str(trait_def_id)) } else { String::new() }; + + let mut is_shadowed = false; + + if let Some(assoc_item) = bound_names.get(&item.name) + && assoc_item != &item + { + is_shadowed = true; + + let rename_message = + if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" }; + err.span_label( + tcx.def_span(assoc_item.def_id), + format!("`{}{}` shadowed here{}", prefix, item.name, rename_message), + ); + } + + let rename_message = if is_shadowed { ", consider renaming it" } else { "" }; + if let Some(sp) = tcx.hir().span_if_local(item.def_id) { - err.span_label(sp, format!("`{}{}` defined here", prefix, item.name)); + err.span_label( + sp, + format!("`{}{}` defined here{}", prefix, item.name, rename_message), + ); } } if potential_assoc_types.len() == assoc_items.len() { @@ -642,8 +758,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // extra type arguments present. A suggesting to replace the generic args with // associated types is already emitted. already_has_generics_args_suggestion = true; - } else if let (Ok(snippet), false) = - (tcx.sess.source_map().span_to_snippet(*span), dupes) + } else if let (Ok(snippet), false, false) = + (tcx.sess.source_map().span_to_snippet(*span), dupes, shadows) { let types: Vec<_> = assoc_items.iter().map(|item| format!("{} = Type", item.name)).collect(); @@ -725,6 +841,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_help(where_constraints, where_msg); } } + err.emit(); } } diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index d29a27eced0e7..47fbed45b9132 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -243,6 +243,31 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( match (args_iter.peek(), params.peek()) { (Some(&arg), Some(¶m)) => { match (arg, ¶m.kind, arg_count.explicit_late_bound) { + ( + GenericArg::Const(hir::ConstArg { + is_desugared_from_effects: true, + .. + }), + GenericParamDefKind::Const { is_host_effect: false, .. } + | GenericParamDefKind::Type { .. } + | GenericParamDefKind::Lifetime, + _, + ) => { + // SPECIAL CASE FOR DESUGARED EFFECT PARAMS + // This comes from the following example: + // + // ``` + // #[const_trait] + // pub trait PartialEq {} + // impl const PartialEq for () {} + // ``` + // + // Since this is a const impl, we need to insert `` at the end of + // `PartialEq`'s generics, but this errors since `Rhs` isn't specified. + // To work around this, we infer all arguments until we reach the host param. + args.push(ctx.inferred_kind(Some(&args), param, infer_args)); + params.next(); + } (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) | ( GenericArg::Type(_) | GenericArg::Infer(_), diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index bc57bbcca62e8..14e810d133654 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -106,7 +106,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); } // check if the impl trait that we are considering is a impl of a local trait - self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); + self.maybe_lint_blanket_trait_impl(self_ty, &mut diag); diag.stash(self_ty.span, StashKey::TraitMissingMethod); } else { let msg = "trait objects without an explicit `dyn` are deprecated"; @@ -121,7 +121,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { sugg, Applicability::MachineApplicable, ); - self.maybe_lint_blanket_trait_impl(&self_ty, lint); + self.maybe_lint_blanket_trait_impl(self_ty, lint); lint }, ); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2fcb45ef8aa12..20d36a1b0690c 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -18,29 +18,30 @@ use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ - struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError, - MultiSpan, + error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + FatalError, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; -use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{ - self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, + self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; +use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{sym, BytePos, Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::wf::object_region_bounds; -use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt}; -use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_trait_selection::traits::{self, ObligationCtxt}; use std::fmt::Display; use std::slice; @@ -162,7 +163,7 @@ struct ConvertedBinding<'a, 'tcx> { #[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { - Equality(ty::Term<'tcx>), + Equality(Spanned>), Constraint(&'a [hir::GenericBound<'a>]), } @@ -239,7 +240,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def: Option<&ty::GenericParamDef>, ) -> ty::Region<'tcx> { let tcx = self.tcx(); - let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id)); + let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id)); match tcx.named_bound_var(lifetime.hir_id) { Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static, @@ -250,7 +251,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { var: ty::BoundVar::from_u32(index), kind: ty::BrNamed(def_id, name), }; - ty::Region::new_late_bound(tcx, debruijn, br) + ty::Region::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { @@ -258,12 +259,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local()); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion { def_id, index, name }) + ty::Region::new_early_param(tcx, ty::EarlyParamRegion { def_id, index, name }) } Some(rbv::ResolvedArg::Free(scope, id)) => { let name = lifetime_name(id.expect_local()); - ty::Region::new_free(tcx, scope, ty::BrNamed(id, name)) + ty::Region::new_late_param(tcx, scope, ty::BrNamed(id, name)) // (*) -- not late-bound, won't change } @@ -595,12 +596,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|binding| { let kind = match &binding.kind { hir::TypeBindingKind::Equality { term } => match term { - hir::Term::Ty(ty) => { - ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty).into()) - } + hir::Term::Ty(ty) => ConvertedBindingKind::Equality(respan( + ty.span, + self.ast_ty_to_ty(ty).into(), + )), hir::Term::Const(c) => { + let span = self.tcx().def_span(c.def_id); let c = Const::from_anon_const(self.tcx(), c.def_id); - ConvertedBindingKind::Equality(c.into()) + ConvertedBindingKind::Equality(respan(span, c.into())) } }, hir::TypeBindingKind::Constraint { bounds } => { @@ -720,9 +723,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // since we should have emitten an error for them earlier, and they will // not be well-formed! if polarity == ty::ImplPolarity::Negative { - self.tcx() - .sess - .delay_span_bug(binding.span, "negative trait bounds should not have bindings"); + self.tcx().sess.span_delayed_bug( + binding.span, + "negative trait bounds should not have bindings", + ); continue; } @@ -945,7 +949,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Applicability::MachineApplicable, ); } else { - match (types, traits) { + let mut types = types.to_vec(); + types.sort(); + let mut traits = traits.to_vec(); + traits.sort(); + match (&types[..], &traits[..]) { ([], []) => { err.span_suggestion_verbose( span, @@ -1051,7 +1059,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("find_bound_for_assoc_item: predicates={:#?}", predicates); let param_name = tcx.hir().ty_param_name(ty_param_def_id); - self.one_bound_for_assoc_type( + self.one_bound_for_assoc_item( || { traits::transitive_bounds_that_define_assoc_item( tcx, @@ -1063,6 +1071,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }, param_name, Some(ty_param_def_id), + ty::AssocKind::Type, assoc_name, span, None, @@ -1071,48 +1080,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Checks that `bounds` contains exactly one element and reports appropriate // errors otherwise. - #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)] - fn one_bound_for_assoc_type( + #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, binding), ret)] + fn one_bound_for_assoc_item( &self, all_candidates: impl Fn() -> I, ty_param_name: impl Display, ty_param_def_id: Option, + assoc_kind: ty::AssocKind, assoc_name: Ident, span: Span, - is_equality: Option>, + binding: Option<&ConvertedBinding<'_, 'tcx>>, ) -> Result, ErrorGuaranteed> where I: Iterator>, { + let tcx = self.tcx(); + let mut matching_candidates = all_candidates().filter(|r| { - self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name) - }); - let mut const_candidates = all_candidates().filter(|r| { - self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name) + self.trait_defines_associated_item_named(r.def_id(), assoc_kind, assoc_name) }); - let (mut bound, mut next_cand) = match (matching_candidates.next(), const_candidates.next()) - { - (Some(bound), _) => (bound, matching_candidates.next()), - (None, Some(bound)) => (bound, const_candidates.next()), - (None, None) => { - let reported = self.complain_about_assoc_type_not_found( - all_candidates, - &ty_param_name.to_string(), - ty_param_def_id, - assoc_name, - span, - ); - return Err(reported); - } + let Some(mut bound) = matching_candidates.next() else { + let reported = self.complain_about_assoc_item_not_found( + all_candidates, + &ty_param_name.to_string(), + ty_param_def_id, + assoc_kind, + assoc_name, + span, + binding, + ); + return Err(reported); }; debug!(?bound); // look for a candidate that is not the same as our first bound, disregarding // whether the bound is const. + let mut next_cand = matching_candidates.next(); while let Some(mut bound2) = next_cand { debug!(?bound2); - let tcx = self.tcx(); if bound2.bound_vars() != bound.bound_vars() { break; } @@ -1133,7 +1139,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg }); if unconsted_args.eq(bound2.skip_binder().args.iter()) { - next_cand = matching_candidates.next().or_else(|| const_candidates.next()); + next_cand = matching_candidates.next(); } else { break; } @@ -1142,51 +1148,53 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(bound2) = next_cand { debug!(?bound2); - let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates); - let mut err = if is_equality.is_some() { - // More specific Error Index entry. - struct_span_err!( - self.tcx().sess, - span, - E0222, - "ambiguous associated type `{}` in bounds of `{}`", - assoc_name, - ty_param_name - ) - } else { - struct_span_err!( - self.tcx().sess, - span, - E0221, - "ambiguous associated type `{}` in bounds of `{}`", - assoc_name, - ty_param_name - ) - }; - err.span_label(span, format!("ambiguous associated type `{assoc_name}`")); + let assoc_kind_str = assoc_kind_str(assoc_kind); + let ty_param_name = &ty_param_name.to_string(); + let mut err = tcx.sess.create_err(crate::errors::AmbiguousAssocItem { + span, + assoc_kind: assoc_kind_str, + assoc_name, + ty_param_name, + }); + // Provide a more specific error code index entry for equality bindings. + err.code( + if let Some(binding) = binding + && let ConvertedBindingKind::Equality(_) = binding.kind + { + error_code!(E0222) + } else { + error_code!(E0221) + }, + ); + // FIXME(#97583): Resugar equality bounds to type/const bindings. + // FIXME: Turn this into a structured, translateable & more actionable suggestion. let mut where_bounds = vec![]; - for bound in bounds { + for bound in [bound, bound2].into_iter().chain(matching_candidates) { let bound_id = bound.def_id(); - let bound_span = self - .tcx() + let bound_span = tcx .associated_items(bound_id) - .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id) - .and_then(|item| self.tcx().hir().span_if_local(item.def_id)); + .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id) + .and_then(|item| tcx.hir().span_if_local(item.def_id)); if let Some(bound_span) = bound_span { err.span_label( bound_span, - format!( - "ambiguous `{assoc_name}` from `{}`", - bound.print_only_trait_path(), - ), + format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),), ); - if let Some(constraint) = &is_equality { - where_bounds.push(format!( - " T: {trait}::{assoc_name} = {constraint}", - trait=bound.print_only_trait_path(), - )); + if let Some(binding) = binding { + match binding.kind { + ConvertedBindingKind::Equality(term) => { + // FIXME(#97583): This isn't syntactically well-formed! + where_bounds.push(format!( + " T: {trait}::{assoc_name} = {term}", + trait = bound.print_only_trait_path(), + term = term.node, + )); + } + // FIXME: Provide a suggestion. + ConvertedBindingKind::Constraint(_bounds) => {} + } } else { err.span_suggestion_verbose( span.with_hi(assoc_name.span.lo()), @@ -1197,7 +1205,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } else { err.note(format!( - "associated type `{ty_param_name}` could derive from `{}`", + "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`", bound.print_only_trait_path(), )); } @@ -1218,46 +1226,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ok(bound) } - #[instrument(level = "debug", skip(self, all_candidates, ty_name), ret)] - fn one_bound_for_assoc_method( - &self, - all_candidates: impl Iterator>, - ty_name: impl Display, - assoc_name: Ident, - span: Span, - ) -> Result, ErrorGuaranteed> { - let mut matching_candidates = all_candidates.filter(|r| { - self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name) - }); - - let candidate = match matching_candidates.next() { - Some(candidate) => candidate, - None => { - return Err(self.tcx().sess.emit_err( - crate::errors::ReturnTypeNotationMissingMethod { - span, - ty_name: ty_name.to_string(), - assoc_name: assoc_name.name, - }, - )); - } - }; - - if let Some(conflicting_candidate) = matching_candidates.next() { - return Err(self.tcx().sess.emit_err( - crate::errors::ReturnTypeNotationConflictingBound { - span, - ty_name: ty_name.to_string(), - assoc_name: assoc_name.name, - first_bound: candidate.print_only_trait_path(), - second_bound: conflicting_candidate.print_only_trait_path(), - }, - )); - } - - Ok(candidate) - } - // Create a type from a path to an associated type or to an enum variant. // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // and item_segment is the path segment for `D`. We return a type and a def for @@ -1415,11 +1383,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // trait reference. let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else { // A cycle error occurred, most likely. - let guar = tcx.sess.delay_span_bug(span, "expected cycle error"); + let guar = tcx.sess.span_delayed_bug(span, "expected cycle error"); return Err(guar); }; - self.one_bound_for_assoc_type( + self.one_bound_for_assoc_item( || { traits::supertraits( tcx, @@ -1428,6 +1396,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }, kw::SelfUpper, None, + ty::AssocKind::Type, assoc_ident, span, None, @@ -1508,15 +1477,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let trait_did = bound.def_id(); - let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did) - else { - // Assume that if it's not matched, there must be a const defined with the same name - // but it was used in a type position. - let msg = format!("found associated const `{assoc_ident}` when type was expected"); - let guar = tcx.sess.struct_span_err(span, msg).emit(); - return Err(guar); - }; - + let assoc_ty_did = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did).unwrap(); let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound); if let Some(variant_def_id) = variant_resolution { @@ -1602,134 +1563,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors // when inside of an ADT (#108491) or where clause. let param_env = tcx.param_env(block.owner); - let cause = ObligationCause::misc(span, block.owner.def_id); - let mut fulfillment_errors = Vec::new(); - let mut applicable_candidates: Vec<_> = infcx.probe(|_| { - // Regions are not considered during selection. - let self_ty = self_ty - .fold_with(&mut BoundVarEraser { tcx, universe: infcx.create_next_universe() }); - - struct BoundVarEraser<'tcx> { - tcx: TyCtxt<'tcx>, - universe: ty::UniverseIndex, - } + let mut universes = if self_ty.has_escaping_bound_vars() { + vec![None; self_ty.outer_exclusive_binder().as_usize()] + } else { + vec![] + }; - // FIXME(non_lifetime_binders): Don't assign the same universe to each placeholder. - impl<'tcx> TypeFolder> for BoundVarEraser<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } + let (impl_, (assoc_item, def_scope)) = + crate::traits::project::with_replaced_escaping_bound_vars( + infcx, + &mut universes, + self_ty, + |self_ty| { + self.select_inherent_assoc_type_candidates( + infcx, name, span, self_ty, param_env, candidates, + ) + }, + )?; + + self.check_assoc_ty(assoc_item, name, def_scope, block, span); + + // FIXME(fmease): Currently creating throwaway `parent_args` to please + // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to + // not require the parent args logic. + let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_); + let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args); + let args = tcx.mk_args_from_iter( + std::iter::once(ty::GenericArg::from(self_ty)) + .chain(args.into_iter().skip(parent_args.len())), + ); - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r } - } + let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args)); - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Bound(_, bv) => Ty::new_placeholder( - self.tcx, - ty::PlaceholderType { universe: self.universe, bound: bv }, - ), - _ => ty.super_fold_with(self), - } - } - - fn fold_const( - &mut self, - ct: ty::Const<'tcx>, - ) -> as rustc_type_ir::Interner>::Const { - assert!(!ct.ty().has_escaping_bound_vars()); - - match ct.kind() { - ty::ConstKind::Bound(_, bv) => ty::Const::new_placeholder( - self.tcx, - ty::PlaceholderConst { universe: self.universe, bound: bv }, - ct.ty(), - ), - _ => ct.super_fold_with(self), - } - } - } + Ok(Some((ty, assoc_item))) + } - let InferOk { value: self_ty, obligations } = - infcx.at(&cause, param_env).normalize(self_ty); + fn select_inherent_assoc_type_candidates( + &self, + infcx: &InferCtxt<'tcx>, + name: Ident, + span: Span, + self_ty: Ty<'tcx>, + param_env: ParamEnv<'tcx>, + candidates: Vec<(DefId, (DefId, DefId))>, + ) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> { + let tcx = self.tcx(); + let mut fulfillment_errors = Vec::new(); - candidates - .iter() - .copied() - .filter(|&(impl_, _)| { - infcx.probe(|_| { - let ocx = ObligationCtxt::new(&infcx); - ocx.register_obligations(obligations.clone()); - - let impl_args = infcx.fresh_args_for_item(span, impl_); - let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args); - let impl_ty = ocx.normalize(&cause, param_env, impl_ty); - - // Check that the self types can be related. - // FIXME(inherent_associated_types): Should we use `eq` here? Method probing uses - // `sup` for this situtation, too. What for? To constrain inference variables? - if ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() - { - return false; - } + let applicable_candidates: Vec<_> = candidates + .iter() + .copied() + .filter(|&(impl_, _)| { + infcx.probe(|_| { + let ocx = ObligationCtxt::new(infcx); + let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty); + + let impl_args = infcx.fresh_args_for_item(span, impl_); + let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args); + let impl_ty = ocx.normalize(&ObligationCause::dummy(), param_env, impl_ty); + + // Check that the self types can be related. + if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() { + return false; + } - // Check whether the impl imposes obligations we have to worry about. - let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args); - let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds); - let impl_obligations = traits::predicates_for_generics( - |_, _| cause.clone(), - param_env, - impl_bounds, - ); - ocx.register_obligations(impl_obligations); + // Check whether the impl imposes obligations we have to worry about. + let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args); + let impl_bounds = + ocx.normalize(&ObligationCause::dummy(), param_env, impl_bounds); + let impl_obligations = traits::predicates_for_generics( + |_, _| ObligationCause::dummy(), + param_env, + impl_bounds, + ); + ocx.register_obligations(impl_obligations); - let mut errors = ocx.select_where_possible(); - if !errors.is_empty() { - fulfillment_errors.append(&mut errors); - return false; - } + let mut errors = ocx.select_where_possible(); + if !errors.is_empty() { + fulfillment_errors.append(&mut errors); + return false; + } - true - }) + true }) - .collect() - }); + }) + .collect(); - if applicable_candidates.len() > 1 { - return Err(self.complain_about_ambiguous_inherent_assoc_type( + match &applicable_candidates[..] { + &[] => Err(self.complain_about_inherent_assoc_type_not_found( name, - applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(), + self_ty, + candidates, + fulfillment_errors, span, - )); - } + )), - if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() { - self.check_assoc_ty(assoc_item, name, def_scope, block, span); - - // FIXME(fmease): Currently creating throwaway `parent_args` to please - // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to - // not require the parent args logic. - let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_); - let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args); - let args = tcx.mk_args_from_iter( - std::iter::once(ty::GenericArg::from(self_ty)) - .chain(args.into_iter().skip(parent_args.len())), - ); - - let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args)); + &[applicable_candidate] => Ok(applicable_candidate), - return Ok(Some((ty, assoc_item))); + &[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_type( + name, + applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(), + span, + )), } - - Err(self.complain_about_inherent_assoc_type_not_found( - name, - self_ty, - candidates, - fulfillment_errors, - span, - )) } fn lookup_assoc_ty( @@ -1753,8 +1690,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let (ident, def_scope) = tcx.adjust_ident_and_get_scope(name, scope, block); - // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead - // of calling `find_by_name_and_kind`. + // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` + // instead of calling `filter_by_name_and_kind` which would needlessly normalize the + // `ident` again and again. let item = tcx.associated_items(scope).in_definition_order().find(|i| { i.kind.namespace() == Namespace::TypeNS && i.ident(tcx).normalize_to_macros_2_0() == ident @@ -1869,7 +1807,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let parent_def_id = def_id .as_local() - .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) + .map(|def_id| tcx.local_def_id_to_hir_id(def_id)) .map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id()); debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id); @@ -1973,7 +1911,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { types_and_spans[..types_and_spans.len() - 1] .iter() .map(|(x, _)| x.as_str()) - .intersperse(&", ") + .intersperse(", ") .collect::() ), [(only, _)] => only.to_string(), @@ -2396,7 +2334,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let e = self .tcx() .sess - .delay_span_bug(path.span, "path with `Res::Err` but no error emitted"); + .span_delayed_bug(path.span, "path with `Res::Err` but no error emitted"); self.set_tainted_by_errors(e); Ty::new_error(self.tcx(), e) } @@ -2543,7 +2481,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|(ty, _, _)| ty) .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } - &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => { + &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); let (args, _) = self.create_args_for_ast_path( span, @@ -2845,6 +2783,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// provided, if they provided one, and otherwise search the supertypes of trait bounds /// for region bounds. It may be that we can derive no bound at all, in which case /// we return `None`. + #[instrument(level = "debug", skip(self, span), ret)] fn compute_object_lifetime_bound( &self, span: Span, @@ -2853,8 +2792,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { let tcx = self.tcx(); - debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates); - // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = object_region_bounds(tcx, existential_predicates); @@ -2881,3 +2818,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Some(r) } } + +fn assoc_kind_str(kind: ty::AssocKind) -> &'static str { + match kind { + ty::AssocKind::Fn => "function", + ty::AssocKind::Const => "constant", + ty::AssocKind::Type => "type", + } +} diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 00ff3f836adf3..ce5426b51427f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -1,7 +1,7 @@ use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds}; use crate::bounds::Bounds; use crate::errors::TraitObjectDeclaredWithNoTraits; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -14,7 +14,6 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::{self, astconv_object_safety_violations}; use smallvec::{smallvec, SmallVec}; -use std::collections::BTreeSet; use super::AstConv; @@ -107,6 +106,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait here instead: `trait NewTrait: {} {{}}`", regular_traits .iter() + // FIXME: This should `print_sugared`, but also needs to integrate projection bounds... .map(|t| t.trait_ref().print_only_trait_path().to_string()) .collect::>() .join(" + "), @@ -148,8 +148,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - // Use a `BTreeSet` to keep output in a more consistent order. - let mut associated_types: FxHashMap> = FxHashMap::default(); + let mut associated_types: FxIndexMap> = FxIndexMap::default(); let regular_traits_refs_spans = trait_bounds .into_iter() @@ -327,7 +326,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { false }); if references_self { - let guar = tcx.sess.delay_span_bug( + let guar = tcx.sess.span_delayed_bug( span, "trait object projection bounds reference `Self`", ); diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 39db295044ed0..5fc500f480762 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -182,7 +182,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { } }; - let errors = fulfill_cx.select_where_possible(&self.infcx); + let errors = fulfill_cx.select_where_possible(self.infcx); if !errors.is_empty() { // This shouldn't happen, except for evaluate/fulfill mismatches, // but that's not a reason for an ICE (`predicate_may_hold` is conservative diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e61ca232de643..56e272b14bd61 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -130,7 +130,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b for field in &def.non_enum_variant().fields { let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args)) else { - tcx.sess.delay_span_bug(span, "could not normalize field type"); + tcx.sess.span_delayed_bug(span, "could not normalize field type"); continue; }; @@ -151,7 +151,8 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b return false; } else if field_ty.needs_drop(tcx, param_env) { // This should never happen. But we can get here e.g. in case of name resolution errors. - tcx.sess.delay_span_bug(span, "we should never accept maybe-dropping union fields"); + tcx.sess + .span_delayed_bug(span, "we should never accept maybe-dropping union fields"); } } } else { @@ -181,14 +182,14 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { } // Generic statics are rejected, but we still reach this case. Err(e) => { - tcx.sess.delay_span_bug(span, format!("{e:?}")); + tcx.sess.span_delayed_bug(span, format!("{e:?}")); return; } }; if layout.abi.is_uninhabited() { tcx.struct_span_lint_hir( UNINHABITED_STATIC, - tcx.hir().local_def_id_to_hir_id(def_id), + tcx.local_def_id_to_hir_id(def_id), span, "static of uninhabited type", |lint| { @@ -204,7 +205,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let item = tcx.hir().item(id); let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else { - tcx.sess.delay_span_bug(item.span, "expected opaque item"); + tcx.sess.span_delayed_bug(item.span, "expected opaque item"); return; }; @@ -222,11 +223,11 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() { return; } - if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, &origin).is_err() { + if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, origin).is_err() { return; } - let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin); + let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, origin); } /// Checks that an opaque type does not contain cycles. @@ -313,7 +314,7 @@ fn check_opaque_meets_bounds<'tcx>( Ok(()) => {} Err(ty_err) => { let ty_err = ty_err.to_string(tcx); - return Err(tcx.sess.delay_span_bug( + return Err(tcx.sess.span_delayed_bug( span, format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"), )); @@ -518,7 +519,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { DefKind::TyAlias => { let pty_ty = tcx.type_of(id.owner_id).instantiate_identity(); let generics = tcx.generics_of(id.owner_id); - check_type_params_are_used(tcx, &generics, pty_ty); + check_type_params_are_used(tcx, generics, pty_ty); } DefKind::ForeignMod => { let it = tcx.hir().item(id); @@ -655,7 +656,7 @@ pub(super) fn check_specialization_validity<'tcx>( if !tcx.is_impl_trait_in_trait(impl_item) { report_forbidden_specialization(tcx, impl_item, parent_impl); } else { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, format!("parent item: {parent_impl:?} not marked as default"), ); @@ -703,7 +704,7 @@ fn check_impl_items_against_trait<'tcx>( tcx.associated_item(trait_item_id) } else { // Checked in `associated_item`. - tcx.sess.delay_span_bug(tcx.def_span(impl_item), "missing associated item in trait"); + tcx.sess.span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait"); continue; }; match ty_impl_item.kind { @@ -753,8 +754,7 @@ fn check_impl_items_against_trait<'tcx>( leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait()); if !is_implemented_here { - let full_impl_span = - tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id)); + let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id)); match tcx.eval_default_body_stability(trait_item_id, full_impl_span) { EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable( tcx, @@ -811,8 +811,7 @@ fn check_impl_items_against_trait<'tcx>( } if !missing_items.is_empty() { - let full_impl_span = - tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id)); + let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id)); missing_items_err(tcx, impl_id, &missing_items, full_impl_span); } @@ -900,7 +899,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { let repr = def.repr(); if repr.packed() { for attr in tcx.get_attrs(def.did(), sym::repr) { - for r in attr::parse_repr_attr(&tcx.sess, attr) { + for r in attr::parse_repr_attr(tcx.sess, attr) { if let attr::ReprPacked(pack) = r && let Some(repr_pack) = repr.pack && pack as u64 != repr_pack.bytes() @@ -1083,7 +1082,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) if non_trivial_count > 0 || prev_non_exhaustive_1zst { tcx.struct_span_lint_hir( REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, - tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()), + tcx.local_def_id_to_hir_id(adt.did().expect_local()), span, "zero-sized fields in `repr(transparent)` cannot \ contain external non-exhaustive types", @@ -1150,8 +1149,8 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_)); let has_non_units = def.variants().iter().any(|var| !is_unit(var)); - let disr_units = def.variants().iter().any(|var| is_unit(&var) && has_disr(&var)); - let disr_non_unit = def.variants().iter().any(|var| !is_unit(&var) && has_disr(&var)); + let disr_units = def.variants().iter().any(|var| is_unit(var) && has_disr(var)); + let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var)); if disr_non_unit || (disr_units && has_non_units) { let mut err = struct_span_err!( @@ -1451,7 +1450,7 @@ fn opaque_type_cycle_error( label_match(capture.place.ty(), capture.get_path_span(tcx)); } // Label any coroutine locals that capture the opaque - if let DefKind::Coroutine = tcx.def_kind(closure_def_id) + if tcx.is_coroutine(closure_def_id) && let Some(coroutine_layout) = tcx.mir_coroutine_witnesses(closure_def_id) { for interior_ty in &coroutine_layout.field_tys { @@ -1468,8 +1467,11 @@ fn opaque_type_cycle_error( err.emit() } -pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { - debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Coroutine)); +pub(super) fn check_coroutine_obligations( + tcx: TyCtxt<'_>, + def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { + debug_assert!(tcx.is_coroutine(def_id.to_def_id())); let typeck = tcx.typeck(def_id); let param_env = tcx.param_env(def_id); @@ -1482,8 +1484,9 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { // typeck writeback gives us predicates with their regions erased. // As borrowck already has checked lifetimes, we do not need to do it again. .ignoring_regions() - // Bind opaque types to `def_id` as they should have been checked by borrowck. - .with_opaque_type_inference(DefiningAnchor::Bind(def_id)) + // Bind opaque types to type checking root, as they should have been checked by borrowck, + // but may show up in some cases, like when (root) obligations are stalled in the new solver. + .with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id)) .build(); let mut fulfillment_cx = >::new(&infcx); @@ -1513,6 +1516,16 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { let errors = fulfillment_cx.select_all_or_error(&infcx); debug!(?errors); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } + + // Check that any hidden types found when checking these stalled coroutine obligations + // are valid. + for (key, ty) in infcx.take_opaque_types() { + let hidden_type = infcx.resolve_vars_if_possible(ty.hidden_type); + let key = infcx.resolve_vars_if_possible(key); + sanity_check_found_hidden_type(tcx, key, hidden_type)?; + } + + Ok(()) } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 90babbb63a000..1412fd1a987cb 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -307,7 +307,7 @@ fn compare_method_predicate_entailment<'tcx>( debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed"); let emitted = report_trait_method_mismatch( - &infcx, + infcx, cause, terr, (trait_m, trait_sig), @@ -380,7 +380,7 @@ fn compare_method_predicate_entailment<'tcx>( if !errors.is_empty() { match check_implied_wf { CheckImpliedWfMode::Check => { - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id); + let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id); return compare_method_predicate_entailment( tcx, impl_m, @@ -410,7 +410,7 @@ fn compare_method_predicate_entailment<'tcx>( if !errors.is_empty() { // FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT // becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors` - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id); + let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id); match check_implied_wf { CheckImpliedWfMode::Check => { return compare_method_predicate_entailment( @@ -439,7 +439,7 @@ fn compare_method_predicate_entailment<'tcx>( } return Err(tcx .sess - .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")); + .span_delayed_bug(rustc_span::DUMMY_SP, "error should have been emitted")); } } } @@ -532,8 +532,8 @@ impl<'tcx> TypeFolder> for RemapLateBound<'_, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReFree(fr) = *r { - ty::Region::new_free( + if let ty::ReLateParam(fr) = *r { + ty::Region::new_late_param( self.tcx, fr.scope, self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region), @@ -667,7 +667,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let trait_to_impl_args = impl_trait_ref.args; - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id); + let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id); let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); let cause = ObligationCause::new( return_span, @@ -937,7 +937,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( remapped_types.insert(def_id, ty::EarlyBinder::bind(ty)); } Err(err) => { - let reported = tcx.sess.delay_span_bug( + let reported = tcx.sess.span_delayed_bug( return_span, format!("could not fully resolve: {ty} => {err:?}"), ); @@ -1078,20 +1078,20 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { region: ty::Region<'tcx>, ) -> Result, Self::Error> { match region.kind() { - // Remap all free regions, which correspond to late-bound regions in the function. - ty::ReFree(_) => {} + // Remap late-bound regions from the function. + ty::ReLateParam(_) => {} // Remap early-bound regions as long as they don't come from the `impl` itself, // in which case we don't really need to renumber them. - ty::ReEarlyBound(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {} + ty::ReEarlyParam(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {} _ => return Ok(region), } let e = if let Some(region) = self.map.get(®ion) { - if let ty::ReEarlyBound(e) = region.kind() { e } else { bug!() } + if let ty::ReEarlyParam(e) = region.kind() { e } else { bug!() } } else { let guar = match region.kind() { - ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) - | ty::ReFree(ty::FreeRegion { + ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. }) + | ty::ReLateParam(ty::LateParamRegion { bound_region: ty::BoundRegionKind::BrNamed(def_id, _), .. }) => { @@ -1114,14 +1114,16 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { .note(format!("hidden type inferred to be `{}`", self.ty)) .emit() } - _ => self.tcx.sess.delay_span_bug(DUMMY_SP, "should've been able to remap region"), + _ => { + self.tcx.sess.span_delayed_bug(DUMMY_SP, "should've been able to remap region") + } }; return Err(guar); }; - Ok(ty::Region::new_early_bound( + Ok(ty::Region::new_early_param( self.tcx, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: e.def_id, name: e.name, index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32, @@ -1140,7 +1142,7 @@ fn report_trait_method_mismatch<'tcx>( ) -> ErrorGuaranteed { let tcx = infcx.tcx; let (impl_err_span, trait_err_span) = - extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m); + extract_spans_for_error_reporting(infcx, terr, &cause, impl_m, trait_m); let mut diag = struct_span_err!( tcx.sess, @@ -1473,7 +1475,7 @@ fn compare_number_of_generics<'tcx>( // inheriting the generics from will also have mismatched arguments, and // we'll report an error for that instead. Delay a bug for safety, though. if trait_.is_impl_trait_in_trait() { - return Err(tcx.sess.delay_span_bug( + return Err(tcx.sess.span_delayed_bug( rustc_span::DUMMY_SP, "errors comparing numbers of generics of trait/impl functions were not emitted", )); @@ -2162,7 +2164,7 @@ pub(super) fn check_type_bounds<'tcx>( impl_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref); + let param_env = tcx.param_env(impl_ty.def_id); debug!(?param_env); let container_id = impl_ty.container_id(tcx); @@ -2217,8 +2219,14 @@ pub(super) fn check_type_bounds<'tcx>( .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations); + // Normalize predicates with the assumption that the GAT may always normalize + // to its definition type. This should be the param-env we use to *prove* the + // predicate too, but we don't do that because of performance issues. + // See . + let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref); for mut obligation in util::elaborate(tcx, obligations) { - let normalized_predicate = ocx.normalize(&normalize_cause, param_env, obligation.predicate); + let normalized_predicate = + ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate); debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); obligation.predicate = normalized_predicate; @@ -2339,7 +2347,7 @@ fn param_env_with_gat_bounds<'tcx>( let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Region(kind); bound_vars.push(bound_var); - ty::Region::new_late_bound( + ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index bc5029a1d5e47..86c38480d57c4 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -91,7 +91,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( // This opaque also needs to be from the impl method -- otherwise, // it's a refinement to a TAIT. - if !tcx.hir().get_if_local(impl_opaque.def_id).map_or(false, |node| { + if !tcx.hir().get_if_local(impl_opaque.def_id).is_some_and(|node| { matches!( node.expect_item().expect_opaque_ty().origin, hir::OpaqueTyOrigin::AsyncFn(def_id) | hir::OpaqueTyOrigin::FnReturn(def_id) @@ -153,7 +153,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( trait_m_sig.inputs_and_output, )); if !ocx.select_all_or_error().is_empty() { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, "encountered errors when checking RPITIT refinement (selection)", ); @@ -165,7 +165,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, "encountered errors when checking RPITIT refinement (regions)", ); @@ -173,7 +173,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( } // Resolve any lifetime variables that may have been introduced during normalization. let Ok((trait_bounds, impl_bounds)) = infcx.fully_resolve((trait_bounds, impl_bounds)) else { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, "encountered errors when checking RPITIT refinement (resolution)", ); diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index dda3f7425697b..58c77bb45cba3 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -66,7 +66,7 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro // already checked by coherence, but compilation may // not have been terminated. let span = tcx.def_span(drop_impl_did); - let reported = tcx.sess.delay_span_bug( + let reported = tcx.sess.span_delayed_bug( span, format!("should have been rejected by coherence check: {dtor_self_type}"), ); @@ -81,8 +81,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( self_type_did: DefId, adt_to_impl_args: GenericArgsRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyEarlyBound) - else { + let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyParam) else { return Ok(()); }; diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 6681292c93d13..947e50d31610c 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -42,7 +42,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); match tcx.hir().find(hir_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { generics.params.is_empty().not().then_some(generics.span) @@ -57,7 +57,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); match tcx.hir().find(hir_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { Some(generics.where_clause_span) @@ -79,7 +79,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); match tcx.hir().find(hir_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => { Some(fn_sig.decl.output.span()) @@ -194,7 +194,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { let start_def_id = start_def_id.expect_local(); - let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id); + let start_id = tcx.local_def_id_to_hir_id(start_def_id); let start_span = tcx.def_span(start_def_id); let start_t = tcx.type_of(start_def_id).instantiate_identity(); match start_t.kind() { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index c61719c1fd293..7ea21b24fc821 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -143,12 +143,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ]); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { - let region = ty::Region::new_late_bound( + let region = ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, ); - let env_region = ty::Region::new_late_bound( + let env_region = ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv }, @@ -225,25 +225,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), ), - sym::option_payload_ptr => { - let option_def_id = tcx.require_lang_item(hir::LangItem::Option, None); - let p0 = param(0); - ( - 1, - vec![Ty::new_ptr( - tcx, - ty::TypeAndMut { - ty: Ty::new_adt( - tcx, - tcx.adt_def(option_def_id), - tcx.mk_args_from_iter([ty::GenericArg::from(p0)].into_iter()), - ), - mutbl: hir::Mutability::Not, - }, - )], - Ty::new_ptr(tcx, ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }), - ) - } sym::ptr_mask => ( 1, vec![ @@ -411,7 +392,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { 1, vec![Ty::new_imm_ref( tcx, - ty::Region::new_late_bound(tcx, ty::INNERMOST, br), + ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0), )], Ty::new_projection(tcx, discriminant_def_id, tcx.mk_args(&[param(0).into()])), @@ -465,11 +446,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::raw_eq => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }; - let param_ty = Ty::new_imm_ref( - tcx, - ty::Region::new_late_bound(tcx, ty::INNERMOST, br), - param(0), - ); + let param_ty = + Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0)); (1, vec![param_ty; 2], tcx.types.bool) } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index cd7e991720454..2428fe6ae790a 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -281,7 +281,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) { let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id()); let Some(asm_arch) = self.tcx.sess.asm_arch else { - self.tcx.sess.delay_span_bug(DUMMY_SP, "target architecture does not support asm"); + self.tcx.sess.span_delayed_bug(DUMMY_SP, "target architecture does not support asm"); return; }; for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { @@ -307,7 +307,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Err(msg) = reg.validate( asm_arch, self.tcx.sess.relocation_model(), - &target_features, + target_features, &self.tcx.sess.target, op.is_clobber(), ) { @@ -382,7 +382,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, true, None, - &target_features, + target_features, ); } hir::InlineAsmOperand::Out { reg, late: _, expr } => { @@ -394,7 +394,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, None, - &target_features, + target_features, ); } } @@ -406,7 +406,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, None, - &target_features, + target_features, ); } hir::InlineAsmOperand::SplitInOut { reg, late: _, in_expr, out_expr } => { @@ -417,7 +417,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, true, None, - &target_features, + target_features, ); if let Some(out_expr) = out_expr { self.check_asm_operand_type( @@ -427,7 +427,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, Some((in_expr, in_ty)), - &target_features, + target_features, ); } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 15c5558fc0b0c..a81a2037214dc 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -128,7 +128,7 @@ fn get_owner_return_paths( tcx: TyCtxt<'_>, def_id: LocalDefId, ) -> Option<(LocalDefId, ReturnsVisitor<'_>)> { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let parent_id = tcx.hir().get_parent_item(hir_id).def_id; tcx.hir().find_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| { let body = tcx.hir().body(body_id); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 40b33117f7ccc..37b308f9f88d3 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -414,11 +414,11 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h // then we'll assign too low a count to any `yield` expressions // we encounter in 'right_expression' - they should really occur after all of the // expressions in 'left_expression'. - visitor.visit_expr(&right_expr); + visitor.visit_expr(right_expr); visitor.pessimistic_yield = prev_pessimistic; debug!("resolve_expr - restoring pessimistic_yield to {}", prev_pessimistic); - visitor.visit_expr(&left_expr); + visitor.visit_expr(left_expr); debug!("resolve_expr - fixing up counts to {}", visitor.expr_and_pat_count); // Remove and process any scopes pushed by the visitor @@ -582,7 +582,7 @@ fn resolve_local<'tcx>( // due to rule C. if let Some(expr) = init { - record_rvalue_scope_if_borrow_expr(visitor, &expr, blk_scope); + record_rvalue_scope_if_borrow_expr(visitor, expr, blk_scope); if let Some(pat) = pat { if is_binding_pat(pat) { @@ -645,25 +645,24 @@ fn resolve_local<'tcx>( match pat.kind { PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes, _), ..) => true, - PatKind::Struct(_, field_pats, _) => { - field_pats.iter().any(|fp| is_binding_pat(&fp.pat)) - } + PatKind::Struct(_, field_pats, _) => field_pats.iter().any(|fp| is_binding_pat(fp.pat)), PatKind::Slice(pats1, pats2, pats3) => { - pats1.iter().any(|p| is_binding_pat(&p)) - || pats2.iter().any(|p| is_binding_pat(&p)) - || pats3.iter().any(|p| is_binding_pat(&p)) + pats1.iter().any(|p| is_binding_pat(p)) + || pats2.iter().any(|p| is_binding_pat(p)) + || pats3.iter().any(|p| is_binding_pat(p)) } PatKind::Or(subpats) | PatKind::TupleStruct(_, subpats, _) - | PatKind::Tuple(subpats, _) => subpats.iter().any(|p| is_binding_pat(&p)), + | PatKind::Tuple(subpats, _) => subpats.iter().any(|p| is_binding_pat(p)), - PatKind::Box(subpat) => is_binding_pat(&subpat), + PatKind::Box(subpat) => is_binding_pat(subpat), PatKind::Ref(_, _) | PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), ..) | PatKind::Wild + | PatKind::Never | PatKind::Path(_) | PatKind::Lit(_) | PatKind::Range(_, _, _) => false, @@ -700,20 +699,20 @@ fn resolve_local<'tcx>( } hir::ExprKind::Struct(_, fields, _) => { for field in fields { - record_rvalue_scope_if_borrow_expr(visitor, &field.expr, blk_id); + record_rvalue_scope_if_borrow_expr(visitor, field.expr, blk_id); } } hir::ExprKind::Array(subexprs) | hir::ExprKind::Tup(subexprs) => { for subexpr in subexprs { - record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id); + record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); } } hir::ExprKind::Cast(subexpr, _) => { - record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id) + record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id) } hir::ExprKind::Block(block, _) => { if let Some(subexpr) = block.expr { - record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id); + record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); } } hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) => { @@ -795,13 +794,13 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); for param in body.params { - self.visit_pat(¶m.pat); + self.visit_pat(param.pat); } // The body of the every fn is a root scope. self.cx.parent = self.cx.var_parent; if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() { - self.visit_expr(&body.value) + self.visit_expr(body.value) } else { // Only functions have an outer terminating (drop) scope, while // temporaries in constant initializers may be 'static, but only @@ -822,7 +821,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { // (i.e., `'static`), which means that after `g` returns, it drops, // and all the associated destruction scope rules apply. self.cx.var_parent = None; - resolve_local(self, None, Some(&body.value)); + resolve_local(self, None, Some(body.value)); } if body.coroutine_kind.is_some() { @@ -849,7 +848,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { resolve_expr(self, ex); } fn visit_local(&mut self, l: &'tcx Local<'tcx>) { - resolve_local(self, Some(&l.pat), l.init) + resolve_local(self, Some(l.pat), l.init) } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 046983e90f7b9..3e805ab00b9c7 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -32,6 +32,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _ use rustc_trait_selection::traits::{ self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc, }; +use rustc_type_ir::TypeFlags; use std::cell::LazyCell; use std::ops::{ControlFlow, Deref}; @@ -117,10 +118,10 @@ where if tcx.sess.err_count() > 0 { return Err(err); } else { - // HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs causes an - // error (delay_span_bug) during normalization, without reporting an error, so we need to act as if - // no error happened, in order to let our callers continue and report an error later in - // check_impl_items_against_trait. + // HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs + // causes an error (span_delayed_bug) during normalization, without reporting an error, + // so we need to act as if no error happened, in order to let our callers continue and + // report an error later in check_impl_items_against_trait. return Ok(()); } } @@ -583,7 +584,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( // reflected in a where clause on the GAT itself. for (ty, ty_idx) in &types { // In our example, requires that `Self: 'a` - if ty_known_to_outlive(tcx, item_def_id, param_env, &wf_tys, *ty, *region_a) { + if ty_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *ty, *region_a) { debug!(?ty_idx, ?region_a_idx); debug!("required clause: {ty} must outlive {region_a}"); // Translate into the generic parameters of the GAT. In @@ -594,9 +595,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( // Same for the region. In our example, 'a corresponds // to the 'me parameter. let region_param = gat_generics.param_at(*region_a_idx, tcx); - let region_param = ty::Region::new_early_bound( + let region_param = ty::Region::new_early_param( tcx, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: region_param.def_id, index: region_param.index, name: region_param.name, @@ -622,14 +623,14 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b { continue; } - if region_known_to_outlive(tcx, item_def_id, param_env, &wf_tys, *region_a, *region_b) { + if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) { debug!(?region_a_idx, ?region_b_idx); debug!("required clause: {region_a} must outlive {region_b}"); // Translate into the generic parameters of the GAT. let region_a_param = gat_generics.param_at(*region_a_idx, tcx); - let region_a_param = ty::Region::new_early_bound( + let region_a_param = ty::Region::new_early_param( tcx, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: region_a_param.def_id, index: region_a_param.index, name: region_a_param.name, @@ -637,9 +638,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( ); // Same for the region. let region_b_param = gat_generics.param_at(*region_b_idx, tcx); - let region_b_param = ty::Region::new_early_bound( + let region_b_param = ty::Region::new_early_param( tcx, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: region_b_param.def_id, index: region_b_param.index, name: region_b_param.name, @@ -670,7 +671,7 @@ fn ty_known_to_outlive<'tcx>( ty: Ty<'tcx>, region: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| { + resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |infcx, region_bound_pairs| { let origin = infer::RelateParamBound(DUMMY_SP, ty, None); let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env); outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation); @@ -687,7 +688,7 @@ fn region_known_to_outlive<'tcx>( region_a: ty::Region<'tcx>, region_b: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |mut infcx, _| { + resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |mut infcx, _| { use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; let origin = infer::RelateRegionParamBound(DUMMY_SP); // `region_a: region_b` -> `region_b <= region_a` @@ -762,7 +763,7 @@ impl<'tcx> TypeVisitor> for GATSubstCollector<'tcx> { ty::Alias(ty::Projection, p) if p.def_id == self.gat => { for (idx, subst) in p.args.iter().enumerate() { match subst.unpack() { - GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => { + GenericArgKind::Lifetime(lt) if !lt.is_bound() => { self.regions.insert((lt, idx)); } GenericArgKind::Type(t) => { @@ -858,7 +859,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()), // Const parameters are well formed if their type is structural match. - hir::GenericParamKind::Const { ty: hir_ty, default: _ } => { + hir::GenericParamKind::Const { ty: hir_ty, default: _, is_host_effect: _ } => { let ty = tcx.type_of(param.def_id).instantiate_identity(); if tcx.features().adt_const_params { @@ -1039,7 +1040,7 @@ fn check_type_defn<'tcx>( let ty = tcx.erase_regions(ty); if ty.has_infer() { tcx.sess - .delay_span_bug(item.span, format!("inference variables in {ty:?}")); + .span_delayed_bug(item.span, format!("inference variables in {ty:?}")); // Just treat unresolved type expression as if it needs drop. true } else { @@ -1811,8 +1812,10 @@ fn check_variances_for_type_defn<'tcx>( // // if they aren't in the same order, then the user has written invalid code, and already // got an error about it (or I'm wrong about this) - tcx.sess - .delay_span_bug(hir_param.span, "hir generics and ty generics in different order"); + tcx.sess.span_delayed_bug( + hir_param.span, + "hir generics and ty generics in different order", + ); continue; } @@ -1877,7 +1880,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { continue; } // Match the existing behavior. - if pred.is_global() && !pred.has_late_bound_vars() { + if pred.is_global() && !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS) { let pred = self.normalize(span, None, pred); let hir_node = tcx.hir().find_by_def_id(self.body_def_id); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index e5e192e0079bd..f277badf275b7 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -550,7 +550,7 @@ fn infringing_fields_error( .entry((ty.clone(), predicate.clone())) .or_default() .push(origin.span()); - if let ty::RegionKind::ReEarlyBound(ebr) = *b + if let ty::RegionKind::ReEarlyParam(ebr) = *b && ebr.has_name() { bounds.push((b.to_string(), a.to_string(), None)); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 7205b7a21a823..3f8c0db8752d3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -198,7 +198,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // entire graph when there are many connected regions. rustc_index::newtype_index! { - #[custom_encodable] + #[orderable] pub struct RegionId {} } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 7eeb7837467fd..451004576292a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -58,7 +58,7 @@ fn do_orphan_check_impl<'tcx>( tr.path.span, trait_ref, impl_.self_ty.span, - &impl_.generics, + impl_.generics, err, )? } @@ -452,7 +452,13 @@ fn lint_auto_trait_impl<'tcx>( trait_ref: ty::TraitRef<'tcx>, impl_def_id: LocalDefId, ) { - assert_eq!(trait_ref.args.len(), 1); + if trait_ref.args.len() != 1 { + tcx.sess.diagnostic().span_delayed_bug( + tcx.def_span(impl_def_id), + "auto traits cannot have generic parameters", + ); + return; + } let self_ty = trait_ref.self_ty(); let (self_type_did, args) = match self_ty.kind() { ty::Adt(def, args) => (def.did(), args), @@ -491,7 +497,7 @@ fn lint_auto_trait_impl<'tcx>( tcx.struct_span_lint_hir( lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS, - tcx.hir().local_def_id_to_hir_id(impl_def_id), + tcx.local_def_id_to_hir_id(impl_def_id), tcx.def_span(impl_def_id), DelayDm(|| { format!( diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 6b18b0ebe9d1a..8a02bab92aaf7 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -23,7 +23,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { tcx.def_span(def_id), E0199, "implementing the trait `{}` is not unsafe", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared() ) .span_suggestion_verbose( item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)), @@ -40,13 +40,13 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { tcx.def_span(def_id), E0200, "the trait `{}` requires an `unsafe impl` declaration", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared() ) .note(format!( "the trait `{}` enforces invariants that the compiler can't check. \ Review the trait documentation and make sure this implementation \ upholds those invariants before adding the `unsafe` keyword", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared() )) .span_suggestion_verbose( item.span.shrink_to_lo(), @@ -69,7 +69,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "the trait `{}` enforces invariants that the compiler can't check. \ Review the trait documentation and make sure this implementation \ upholds those invariants before adding the `unsafe` keyword", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared() )) .span_suggestion_verbose( item.span.shrink_to_lo(), @@ -82,7 +82,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => { // Reported in AST validation - tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); + tcx.sess.span_delayed_bug(item.span, "unsafe negative impl"); } (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_)) | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 9636c6144461b..ae35d6ebd75ad 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -350,7 +350,7 @@ impl<'tcx> ItemCtxt<'tcx> { } pub fn hir_id(&self) -> hir::HirId { - self.tcx.hir().local_def_id_to_hir_id(self.item_def_id) + self.tcx.local_def_id_to_hir_id(self.item_def_id) } pub fn node(&self) -> hir::Node<'tcx> { @@ -440,10 +440,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { second: format!( "{}::", // Replace the existing lifetimes with a new named lifetime. - self.tcx.replace_late_bound_regions_uncached( + self.tcx.instantiate_bound_regions_uncached( poly_trait_ref, |_| { - ty::Region::new_early_bound(self.tcx, ty::EarlyBoundRegion { + ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion { def_id: item_def_id, index: 0, name: Symbol::intern(<_name), @@ -835,7 +835,7 @@ fn convert_variant( fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let Node::Item(item) = tcx.hir().get(hir_id) else { bug!(); }; @@ -1090,7 +1090,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { if let hir::FnRetTy::Return(ty) = output { if is_suggestable_infer_ty(ty) { - return Some(&*ty); + return Some(*ty); } } None @@ -1101,7 +1101,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder( def_id: LocalDefId, icx: &ItemCtxt<'tcx>, ) -> ty::PolyFnSig<'tcx> { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); match get_infer_ret_ty(&sig.decl.output) { Some(ty) => { @@ -1373,7 +1373,7 @@ fn impl_trait_ref( if let Some(ErrorGuaranteed { .. }) = check_impl_constness( tcx, tcx.is_const_trait_impl_raw(def_id.to_def_id()), - &ast_trait_ref, + ast_trait_ref, ) { // we have a const impl, but for a trait without `#[const_trait]`, so // without the host param. If we continue with the HIR trait ref, we get @@ -1383,7 +1383,7 @@ fn impl_trait_ref( let last_segment = path_segments.len() - 1; let mut args = *path_segments[last_segment].args(); let last_arg = args.args.len() - 1; - assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if tcx.has_attr(anon_const.value.def_id, sym::rustc_host))); + assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects)); args.args = &args.args[..args.args.len() - 1]; path_segments[last_segment].args = Some(&args); let path = hir::Path { @@ -1394,7 +1394,7 @@ fn impl_trait_ref( let trait_ref = hir::TraitRef { path: &path, hir_ref_id: ast_trait_ref.hir_ref_id }; icx.astconv().instantiate_mono_trait_ref(&trait_ref, selfty) } else { - icx.astconv().instantiate_mono_trait_ref(&ast_trait_ref, selfty) + icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) } }) .map(ty::EarlyBinder::bind) @@ -1519,7 +1519,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } else { hir::Unsafety::Unsafe }; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let fty = ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None); diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 3d60c57b9d5ad..114c5147e1193 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -9,12 +9,12 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{kw, Symbol}; -use rustc_span::{sym, Span}; +use rustc_span::Span; pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir().get(hir_id); let parent_def_id = match node { @@ -182,7 +182,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } let no_generics = hir::Generics::empty(); - let ast_generics = node.generics().unwrap_or(&no_generics); + let ast_generics = node.generics().unwrap_or(no_generics); let (opt_self, allow_defaults) = match node { Node::Item(item) => { match item.kind { @@ -298,13 +298,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { kind, }) } - GenericParamKind::Const { default, .. } => { - let is_host_param = tcx.has_attr(param.def_id, sym::rustc_host); - + GenericParamKind::Const { ty: _, default, is_host_effect } => { if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() - // `rustc_host` effect params are allowed to have defaults. - && !is_host_param + // `host` effect params are allowed to have defaults. + && !is_host_effect { tcx.sess.span_err( param.span, @@ -315,7 +313,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { let index = next_index(); - if is_host_param { + if is_host_effect { if let Some(idx) = host_effect_index { bug!("parent also has host effect param? index: {idx}, def: {def_id:?}"); } @@ -330,7 +328,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { pure_wrt_drop: param.pure_wrt_drop, kind: ty::GenericParamDefKind::Const { has_default: default.is_some(), - is_host_effect: is_host_param, + is_host_effect, }, }) } @@ -458,11 +456,11 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option match &item.kind { - hir::TraitItemKind::Fn(sig, _) => has_late_bound_regions(tcx, &item.generics, sig.decl), + hir::TraitItemKind::Fn(sig, _) => has_late_bound_regions(tcx, item.generics, sig.decl), _ => None, }, Node::ImplItem(item) => match &item.kind { - hir::ImplItemKind::Fn(sig, _) => has_late_bound_regions(tcx, &item.generics, sig.decl), + hir::ImplItemKind::Fn(sig, _) => has_late_bound_regions(tcx, item.generics, sig.decl), _ => None, }, Node::ForeignItem(item) => match item.kind { @@ -489,7 +487,7 @@ struct AnonConstInParamTyDetector { impl<'v> Visitor<'v> for AnonConstInParamTyDetector { fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - if let GenericParamKind::Const { ty, default: _ } = p.kind { + if let GenericParamKind::Const { ty, default: _, is_host_effect: _ } = p.kind { let prev = self.in_param_ty; self.in_param_ty = true; self.visit_ty(ty); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index d746e6dea7553..4d0fd2b691a9e 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -105,7 +105,7 @@ pub(super) fn explicit_item_bounds( None => {} } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let bounds = match tcx.hir().get(hir_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(bounds, _), diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 104da581e019d..ca9443225e294 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -134,7 +134,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen None => {} } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir().get(hir_id); let mut is_trait = None; @@ -290,7 +290,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } hir::WherePredicate::RegionPredicate(region_pred) => { - let r1 = icx.astconv().ast_region_to_region(®ion_pred.lifetime, None); + let r1 = icx.astconv().ast_region_to_region(region_pred.lifetime, None); predicates.extend(region_pred.bounds.iter().map(|bound| { let (r2, span) = match bound { hir::GenericBound::Outlives(lt) => { @@ -362,10 +362,10 @@ fn compute_bidirectional_outlives_predicates<'tcx>( ) { for param in opaque_own_params { let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()); - if let ty::ReEarlyBound(..) = *orig_lifetime { - let dup_lifetime = ty::Region::new_early_bound( + if let ty::ReEarlyParam(..) = *orig_lifetime { + let dup_lifetime = ty::Region::new_early_param( tcx, - ty::EarlyBoundRegion { def_id: param.def_id, index: param.index, name: param.name }, + ty::EarlyParamRegion { def_id: param.def_id, index: param.index, name: param.name }, ); let span = tcx.def_span(param.def_id); predicates.push(( @@ -412,7 +412,7 @@ fn const_evaluatable_predicates_of( } } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir().get(hir_id); let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; @@ -503,7 +503,7 @@ pub(super) fn explicit_predicates_of<'tcx>( } } else { if matches!(def_kind, DefKind::AnonConst) && tcx.features().generic_const_exprs { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let parent_def_id = tcx.hir().get_parent_item(hir_id); if let Some(defaulted_param_def_id) = @@ -571,7 +571,7 @@ pub(super) fn explicit_predicates_of<'tcx>( // To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent. // In the above example this is `foo::{opaque#0}` or `impl Iterator` - let parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent_def_id.def_id); + let parent_hir_id = tcx.local_def_id_to_hir_id(parent_def_id.def_id); // In the above example this is the function `foo` let item_def_id = tcx.hir().get_parent_item(parent_hir_id); @@ -631,7 +631,7 @@ pub(super) fn implied_predicates_with_filter( return tcx.super_predicates_of(trait_def_id); }; - let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id); + let trait_hir_id = tcx.local_def_id_to_hir_id(trait_def_id); let Node::Item(item) = tcx.hir().get(trait_hir_id) else { bug!("trait_node_id {} is not an item", trait_hir_id); @@ -691,7 +691,7 @@ pub(super) fn type_param_predicates( // written inline like `` or in a where-clause like // `where T: Foo`. - let param_id = tcx.hir().local_def_id_to_hir_id(def_id); + let param_id = tcx.local_def_id_to_hir_id(def_id); let param_owner = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(param_owner); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; @@ -712,11 +712,11 @@ pub(super) fn type_param_predicates( .unwrap_or_default(); let mut extend = None; - let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id); + let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id); let ast_generics = match tcx.hir().get(item_hir_id) { - Node::TraitItem(item) => &item.generics, + Node::TraitItem(item) => item.generics, - Node::ImplItem(item) => &item.generics, + Node::ImplItem(item) => item.generics, Node::Item(item) => { match item.kind { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 6424d1c793112..e939b7abd9031 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -295,7 +295,7 @@ fn late_arg_as_bound_arg<'tcx>( ) -> ty::BoundVariableKind { match arg { ResolvedArg::LateBound(_, _, def_id) => { - let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local())); + let name = tcx.hir().name(tcx.local_def_id_to_hir_id(def_id.expect_local())); match param.kind { GenericParamKind::Lifetime { .. } => { ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) @@ -335,7 +335,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // though this may happen when we call `poly_trait_ref_binder_info` with // an (erroneous, #113423) associated return type bound in an impl header. if !supertrait_bound_vars.is_empty() { - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( DUMMY_SP, format!( "found supertrait lifetimes without a binder to append \ @@ -565,7 +565,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let mut bound_vars = FxIndexMap::default(); debug!(?generics.params); for param in generics.params { - let (def_id, reg) = ResolvedArg::early(¶m); + let (def_id, reg) = ResolvedArg::early(param); bound_vars.insert(def_id, reg); } @@ -684,7 +684,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(), s: self.scope, }; - self.with(scope, |this| this.visit_ty(&mt.ty)); + self.with(scope, |this| this.visit_ty(mt.ty)); } hir::TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { // Resolve the lifetimes in the bounds to the lifetime defs in the generics. @@ -733,7 +733,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let def = self.map.defs.get(&lifetime.hir_id).cloned(); let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue }; let Some(def_id) = def_id.as_local() else { continue }; - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = self.tcx.local_def_id_to_hir_id(def_id); // Ensure that the parent of the def is an item, not HRTB let parent_id = self.tcx.hir().parent_id(hir_id); if !parent_id.is_owner() { @@ -775,7 +775,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } Type(bounds, ty) => { self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { - this.visit_generics(&trait_item.generics); + this.visit_generics(trait_item.generics); for bound in bounds { this.visit_param_bound(bound); } @@ -847,7 +847,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { hir::FnRetTy::DefaultReturn(_) => None, hir::FnRetTy::Return(ty) => Some(ty), }; - self.visit_fn_like_elision(&fd.inputs, output, matches!(fk, intravisit::FnKind::Closure)); + self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure)); intravisit::walk_fn_kind(self, fk); self.visit_nested_body(body_id) } @@ -894,7 +894,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }; self.with(scope, |this| { walk_list!(this, visit_generic_param, bound_generic_params); - this.visit_ty(&bounded_ty); + this.visit_ty(bounded_ty); walk_list!(this, visit_param_bound, bounds); }) } @@ -992,7 +992,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { self.visit_ty(ty); } } - GenericParamKind::Const { ty, default } => { + GenericParamKind::Const { ty, default, is_host_effect: _ } => { self.visit_ty(ty); if let Some(default) = default { self.visit_body(self.tcx.hir().body(default.body)); @@ -1061,7 +1061,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { { let BoundVarContext { tcx, map, .. } = self; let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope }; - let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); + let span = debug_span!("scope", scope = ?TruncatedScopeDebug(this.scope)); { let _enter = span.enter(); f(&mut this); @@ -1363,7 +1363,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( lifetime_ref.ident.span, format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,), ); @@ -1493,7 +1493,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( self.tcx.hir().span(hir_id), format!("could not resolve {param_def_id:?}"), ); @@ -1724,7 +1724,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } else { self.tcx .sess - .delay_span_bug(binding.ident.span, "bad return type notation here"); + .span_delayed_bug(binding.ident.span, "bad return type notation here"); vec![] }; self.with(scope, |this| { @@ -1848,8 +1848,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { - debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; let mut scope = self.scope; let lifetime = loop { @@ -2012,7 +2012,7 @@ fn is_late_bound_map( fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { debug!("r={:?}", r.kind()); - if let ty::RegionKind::ReEarlyBound(region) = r.kind() { + if let ty::RegionKind::ReEarlyParam(region) = r.kind() { self.arg_is_constrained[region.index as usize] = true; } @@ -2057,7 +2057,7 @@ fn is_late_bound_map( Some(true) => Some(arg), Some(false) => None, None => { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( *span, format!( "Incorrect generic arg count for alias {alias_def:?}" diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index d7bd2a7b17fc3..c4fc4dda069aa 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -18,7 +18,7 @@ mod opaque; fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { use hir::*; use rustc_middle::ty::Ty; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let Node::AnonConst(_) = tcx.hir().get(hir_id) else { panic!() }; @@ -350,7 +350,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder match item.kind { ItemKind::OpaqueTy(OpaqueTy { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index e8ab2651d7282..f11a953536dcc 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -41,7 +41,7 @@ pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) { /// ``` #[instrument(skip(tcx), level = "debug")] pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let scope = tcx.hir().get_defining_scope(hir_id); let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; @@ -278,7 +278,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied(); if let Some(mir_opaque_ty) = mir_opaque_ty { - let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id); + let scope = tcx.local_def_id_to_hir_id(owner_def_id); debug!(?scope); let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty }; diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index ed5e9dd2b5add..65d1ffa40e2ed 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -13,8 +13,8 @@ impl From for Parameter { } } -impl From for Parameter { - fn from(param: ty::EarlyBoundRegion) -> Self { +impl From for Parameter { + fn from(param: ty::EarlyParamRegion) -> Self { Parameter(param.index) } } @@ -73,7 +73,7 @@ impl<'tcx> TypeVisitor> for ParameterCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - if let ty::ReEarlyBound(data) = *r { + if let ty::ReEarlyParam(data) = *r { self.parameters.push(Parameter::from(data)); } ControlFlow::Continue(()) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index dd83b5b6f2c03..a47722936975e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -6,9 +6,121 @@ use rustc_errors::{ MultiSpan, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty}; +use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; +#[derive(Diagnostic)] +#[diag(hir_analysis_ambiguous_assoc_item)] +pub struct AmbiguousAssocItem<'a> { + #[primary_span] + #[label] + pub span: Span, + pub assoc_kind: &'static str, + pub assoc_name: Ident, + pub ty_param_name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_assoc_kind_mismatch)] +pub struct AssocKindMismatch { + #[primary_span] + #[label] + pub span: Span, + pub expected: &'static str, + pub got: &'static str, + #[label(hir_analysis_expected_because_label)] + pub expected_because_label: Option, + pub assoc_kind: &'static str, + #[note] + pub def_span: Span, + #[label(hir_analysis_bound_on_assoc_const_label)] + pub bound_on_assoc_const_label: Option, + #[subdiagnostic] + pub wrap_in_braces_sugg: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg, + applicability = "maybe-incorrect" +)] +pub struct AssocKindMismatchWrapInBracesSugg { + #[suggestion_part(code = "{{ ")] + pub lo: Span, + #[suggestion_part(code = " }}")] + pub hi: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_assoc_item_not_found, code = "E0220")] +pub struct AssocItemNotFound<'a> { + #[primary_span] + pub span: Span, + pub assoc_name: Ident, + pub assoc_kind: &'static str, + pub ty_param_name: &'a str, + #[subdiagnostic] + pub label: Option>, + #[subdiagnostic] + pub sugg: Option>, +} + +#[derive(Subdiagnostic)] +pub enum AssocItemNotFoundLabel<'a> { + #[label(hir_analysis_assoc_item_not_found_label)] + NotFound { + #[primary_span] + span: Span, + }, + #[label(hir_analysis_assoc_item_not_found_found_in_other_trait_label)] + FoundInOtherTrait { + #[primary_span] + span: Span, + assoc_kind: &'static str, + trait_name: &'a str, + suggested_name: Symbol, + identically_named: bool, + }, +} + +#[derive(Subdiagnostic)] + +pub enum AssocItemNotFoundSugg<'a> { + #[suggestion( + hir_analysis_assoc_item_not_found_similar_sugg, + code = "{suggested_name}", + applicability = "maybe-incorrect" + )] + Similar { + #[primary_span] + span: Span, + assoc_kind: &'static str, + suggested_name: Symbol, + }, + #[suggestion( + hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg, + code = "{suggested_name}", + style = "verbose", + applicability = "maybe-incorrect" + )] + SimilarInOtherTrait { + #[primary_span] + span: Span, + assoc_kind: &'static str, + suggested_name: Symbol, + }, + #[suggestion(hir_analysis_assoc_item_not_found_other_sugg, code = "{suggested_name}")] + Other { + #[primary_span] + span: Span, + #[applicability] + applicability: Applicability, + ty_param_name: &'a str, + assoc_kind: &'static str, + suggested_name: Symbol, + }, +} + #[derive(Diagnostic)] #[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")] pub struct UnrecognizedAtomicOperation<'a> { @@ -537,27 +649,6 @@ pub(crate) struct ReturnTypeNotationEqualityBound { pub span: Span, } -#[derive(Diagnostic)] -#[diag(hir_analysis_return_type_notation_missing_method)] -pub(crate) struct ReturnTypeNotationMissingMethod { - #[primary_span] - pub span: Span, - pub ty_name: String, - pub assoc_name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis_return_type_notation_conflicting_bound)] -#[note] -pub(crate) struct ReturnTypeNotationConflictingBound<'tcx> { - #[primary_span] - pub span: Span, - pub ty_name: String, - pub assoc_name: Symbol, - pub first_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, - pub second_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, -} - #[derive(Diagnostic)] #[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")] pub(crate) struct PlaceholderNotAllowedItemSignatures { @@ -954,15 +1045,6 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { pub return_ty: Ty<'tcx>, } -#[derive(Diagnostic)] -#[diag(hir_analysis_assoc_bound_on_const)] -#[note] -pub struct AssocBoundOnConst { - #[primary_span] - pub span: Span, - pub descr: &'static str, -} - #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside, code = "E0390")] #[help] diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index ca7679cfba06e..4ed1377e7fc8a 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -5,7 +5,7 @@ use rustc_hir::{ForeignItem, ForeignItemKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -25,11 +25,11 @@ fn diagnostic_hir_wf_check<'tcx>( WellFormedLoc::Ty(def_id) => def_id, WellFormedLoc::Param { function, param_idx: _ } => function, }; - let hir_id = hir.local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); // HIR wfcheck should only ever happen as part of improving an existing error tcx.sess - .delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!"); + .span_delayed_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!"); let icx = ItemCtxt::new(tcx, def_id); @@ -68,7 +68,13 @@ fn diagnostic_hir_wf_check<'tcx>( let infcx = self.tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(&infcx); - let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }); + let tcx_ty = self.icx.to_ty(ty); + // This visitor can walk into binders, resulting in the `tcx_ty` to + // potentially reference escaping bound variables. We simply erase + // those here. + let tcx_ty = self.tcx.fold_regions(tcx_ty, |r, _| { + if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } + }); let cause = traits::ObligationCause::new( ty.span, self.def_id, @@ -178,24 +184,3 @@ fn diagnostic_hir_wf_check<'tcx>( } visitor.cause } - -struct EraseAllBoundRegions<'tcx> { - tcx: TyCtxt<'tcx>, -} - -// Higher ranked regions are complicated. -// To make matters worse, the HIR WF check can instantiate them -// outside of a `Binder`, due to the way we (ab)use -// `ItemCtxt::to_ty`. To make things simpler, we just erase all -// of them, regardless of depth. At worse, this will give -// us an inaccurate span for an error message, but cannot -// lead to unsoundness (we call `delay_span_bug` at the start -// of `diagnostic_hir_wf_check`). -impl<'tcx> TypeFolder> for EraseAllBoundRegions<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { - if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r } - } -} diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 788121f7a304f..fff4a919e91f5 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -74,7 +74,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) if impl_self_ty.references_error() { // Don't complain about unconstrained type params when self ty isn't known due to errors. // (#36836) - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( tcx.def_span(impl_def_id), format!( "potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}", diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 2b8219c01c769..91cdffbbe4f69 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -57,9 +57,9 @@ This API is completely unstable and subject to change. #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(if_let_guard)] @@ -99,8 +99,6 @@ pub mod structured_errors; mod variance; use rustc_errors::ErrorGuaranteed; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_middle::middle; use rustc_middle::query::Providers; @@ -115,7 +113,7 @@ use astconv::{AstConv, OnlySelfBounds}; use bounds::Bounds; use rustc_hir::def::DefKind; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi`"; @@ -211,8 +209,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); - // HACK: `check_mod_type_wf` may spuriously emit errors due to `delay_span_bug`, even if those errors - // only actually get emitted in `check_mod_item_types`. + // HACK: `check_mod_type_wf` may spuriously emit errors due to `span_delayed_bug`, even if + // those errors only actually get emitted in `check_mod_item_types`. errs?; if tcx.features().rustc_attrs { diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index be9d076bd6eb0..c065f6e7e881e 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -18,7 +18,7 @@ pub fn provide(providers: &mut Providers) { } fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] { - let id = tcx.hir().local_def_id_to_hir_id(item_def_id); + let id = tcx.local_def_id_to_hir_id(item_def_id); if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.features().generic_const_exprs diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index a6410c944f778..8077acea52e44 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -80,6 +80,10 @@ pub(crate) fn insert_outlives_predicate<'tcx>( .or_insert(span); } + Component::Placeholder(_) => { + span_bug!(span, "Should not deduce placeholder outlives component"); + } + Component::Alias(alias_ty) => { // This would either arise from something like: // @@ -146,11 +150,11 @@ fn is_free_region(region: Region<'_>) -> bool { // These correspond to `T: 'a` relationships: // // struct Foo<'a, T> { - // field: &'a T, // this would generate a ReEarlyBound referencing `'a` + // field: &'a T, // this would generate a ReEarlyParam referencing `'a` // } // // We care about these, so fall through. - ty::ReEarlyBound(_) => true, + ty::ReEarlyParam(_) => true, // These correspond to `T: 'static` relationships which can be // rather surprising. @@ -167,13 +171,13 @@ fn is_free_region(region: Region<'_>) -> bool { // } // // The type above might generate a `T: 'b` bound, but we can - // ignore it. We can't put it on the struct header anyway. - ty::ReLateBound(..) => false, + // ignore it. We can't name this lifetime pn the struct header anyway. + ty::ReBound(..) => false, ty::ReError(_) => false, // These regions don't appear in types from type declarations: - ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReFree(..) => { + ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReLateParam(..) => { bug!("unexpected region in outlives inference: {:?}", region); } } diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 5f8b1ace68b77..f09594cbbc667 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -413,20 +413,22 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance: VarianceTermPtr<'a>, ) { match *region { - ty::ReEarlyBound(ref data) => { + ty::ReEarlyParam(ref data) => { self.add_constraint(current, data.index, variance); } ty::ReStatic => {} - ty::ReLateBound(..) => { - // Late-bound regions do not get substituted the same - // way early-bound regions do, so we skip them here. + ty::ReBound(..) => { + // Either a higher-ranked region inside of a type or a + // late-bound function parameter. + // + // We do not compute constraints for either of these. } ty::ReError(_) => {} - ty::ReFree(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => { + ty::ReLateParam(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => { // We don't expect to see anything but 'static or bound // regions when visiting member types or method types. bug!( diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 9fb39a0e93b6c..410706110c96e 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -106,7 +106,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc impl<'tcx> ty::TypeVisitor> for OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() { + if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() { self.variances[ebr.index as usize] = ty::Invariant; } ControlFlow::Continue(()) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1ce6bb6ca15fd..1c4534287ebf3 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1,3 +1,6 @@ +//! HIR pretty-printing is layered on top of AST pretty-printing. A number of +//! the definitions in this file have equivalents in `rustc_ast_pretty`. + #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -12,7 +15,7 @@ use rustc_hir::LifetimeParamKind; use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term}; use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}; use rustc_span::source_map::SourceMap; -use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol}; +use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{self, FileName}; use rustc_target::spec::abi::Abi; @@ -49,8 +52,8 @@ pub trait PpAnn { } pub struct NoAnn; + impl PpAnn for NoAnn {} -pub const NO_ANN: &dyn PpAnn = &NoAnn; impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> { fn nested(&self, state: &mut State<'_>, nested: Nested) { @@ -59,7 +62,7 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> { Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)), - Nested::Body(id) => state.print_expr(&self.body(id).value), + Nested::Body(id) => state.print_expr(self.body(id).value), Nested::BodyParamPat(id, i) => state.print_pat(self.body(id).params[i].pat), } } @@ -88,14 +91,14 @@ impl<'a> State<'a> { Node::AnonConst(a) => self.print_anon_const(a), Node::ConstBlock(a) => self.print_inline_const(a), Node::Expr(a) => self.print_expr(a), - Node::ExprField(a) => self.print_expr_field(&a), + Node::ExprField(a) => self.print_expr_field(a), Node::Stmt(a) => self.print_stmt(a), Node::PathSegment(a) => self.print_path_segment(a), Node::Ty(a) => self.print_type(a), Node::TypeBinding(a) => self.print_type_binding(a), Node::TraitRef(a) => self.print_trait_ref(a), Node::Pat(a) => self.print_pat(a), - Node::PatField(a) => self.print_patfield(&a), + Node::PatField(a) => self.print_patfield(a), Node::Arm(a) => self.print_arm(a), Node::Infer(_) => self.word("_"), Node::Block(a) => { @@ -136,9 +139,8 @@ impl<'a> PrintState<'a> for State<'a> { &mut self.comments } - fn print_ident(&mut self, ident: Ident) { - self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); - self.ann.post(self, AnnNode::Name(&ident.name)) + fn ann_post(&mut self, ident: Ident) { + self.ann.post(self, AnnNode::Name(&ident.name)); } fn print_generic_args(&mut self, _: &ast::GenericArgs, _colons_before_params: bool) { @@ -183,15 +185,15 @@ where } pub fn ty_to_string(ty: &hir::Ty<'_>) -> String { - to_string(NO_ANN, |s| s.print_type(ty)) + to_string(&NoAnn, |s| s.print_type(ty)) } pub fn qpath_to_string(segment: &hir::QPath<'_>) -> String { - to_string(NO_ANN, |s| s.print_qpath(segment, false)) + to_string(&NoAnn, |s| s.print_qpath(segment, false)) } pub fn pat_to_string(pat: &hir::Pat<'_>) -> String { - to_string(NO_ANN, |s| s.print_pat(pat)) + to_string(&NoAnn, |s| s.print_pat(pat)) } impl<'a> State<'a> { @@ -260,7 +262,7 @@ impl<'a> State<'a> { self.word("*"); self.print_mt(mt, true); } - hir::TyKind::Ref(ref lifetime, ref mt) => { + hir::TyKind::Ref(lifetime, ref mt) => { self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); @@ -281,7 +283,7 @@ impl<'a> State<'a> { } hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), - hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => { + hir::TyKind::TraitObject(bounds, lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { self.word_space("dyn"); } @@ -517,10 +519,10 @@ impl<'a> State<'a> { self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } - hir::ItemKind::Macro(ref macro_def, _) => { + hir::ItemKind::Macro(macro_def, _) => { self.print_mac_def(macro_def, &item.ident, item.span, |_| {}); } - hir::ItemKind::Mod(ref _mod) => { + hir::ItemKind::Mod(_mod) => { self.head("mod"); self.print_ident(item.ident); self.nbsp(); @@ -549,7 +551,7 @@ impl<'a> State<'a> { state.print_type(ty); }); } - hir::ItemKind::OpaqueTy(ref opaque_ty) => { + hir::ItemKind::OpaqueTy(opaque_ty) => { self.print_item_type(item, opaque_ty.generics, |state| { let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len()); for b in opaque_ty.bounds { @@ -1096,12 +1098,12 @@ impl<'a> State<'a> { self.space(); } self.cbox(INDENT_UNIT); - self.print_outer_attributes(&self.attrs(field.hir_id)); + self.print_outer_attributes(self.attrs(field.hir_id)); if !field.is_shorthand { self.print_ident(field.ident); self.word_space(":"); } - self.print_expr(&field.expr); + self.print_expr(field.expr); self.end() } @@ -1131,7 +1133,7 @@ impl<'a> State<'a> { args: &[hir::Expr<'_>], ) { let base_args = args; - self.print_expr_maybe_paren(&receiver, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX); self.word("."); self.print_ident(segment.ident); @@ -1217,7 +1219,7 @@ impl<'a> State<'a> { self.commasep(Consistent, &args, |s, arg| match *arg { AsmArg::Template(ref template) => s.print_string(template, ast::StrStyle::Cooked), AsmArg::Operand(op) => match *op { - hir::InlineAsmOperand::In { reg, ref expr } => { + hir::InlineAsmOperand::In { reg, expr } => { s.word("in"); s.popen(); s.word(format!("{reg}")); @@ -1236,7 +1238,7 @@ impl<'a> State<'a> { None => s.word("_"), } } - hir::InlineAsmOperand::InOut { reg, late, ref expr } => { + hir::InlineAsmOperand::InOut { reg, late, expr } => { s.word(if late { "inlateout" } else { "inout" }); s.popen(); s.word(format!("{reg}")); @@ -1244,7 +1246,7 @@ impl<'a> State<'a> { s.space(); s.print_expr(expr); } - hir::InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => { + hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, ref out_expr } => { s.word(if late { "inlateout" } else { "inout" }); s.popen(); s.word(format!("{reg}")); @@ -1350,7 +1352,7 @@ impl<'a> State<'a> { hir::ExprKind::AddrOf(k, m, expr) => { self.print_expr_addr_of(k, m, expr); } - hir::ExprKind::Lit(ref lit) => { + hir::ExprKind::Lit(lit) => { self.print_literal(lit); } hir::ExprKind::Cast(expr, ty) => { @@ -1516,7 +1518,7 @@ impl<'a> State<'a> { self.word("asm!"); self.print_inline_asm(asm); } - hir::ExprKind::OffsetOf(container, ref fields) => { + hir::ExprKind::OffsetOf(container, fields) => { self.word("offset_of!("); self.print_type(container); self.word(","); @@ -1621,7 +1623,7 @@ impl<'a> State<'a> { self.print_ident(item_segment.ident); self.print_generic_args(item_segment.args(), colons_before_params) } - hir::QPath::LangItem(lang_item, span, _) => { + hir::QPath::LangItem(lang_item, span) => { self.word("#[lang = \""); self.print_ident(Ident::new(lang_item.name(), span)); self.word("\"]"); @@ -1722,6 +1724,7 @@ impl<'a> State<'a> { // is that it doesn't matter match pat.kind { PatKind::Wild => self.word("_"), + PatKind::Never => self.word("!"), PatKind::Binding(BindingAnnotation(by_ref, mutbl), _, ident, sub) => { if by_ref == ByRef::Yes { self.word_nbsp("ref"); @@ -1764,7 +1767,7 @@ impl<'a> State<'a> { if !empty { self.space(); } - self.commasep_cmnt(Consistent, &fields, |s, f| s.print_patfield(f), |f| f.pat.span); + self.commasep_cmnt(Consistent, fields, |s, f| s.print_patfield(f), |f| f.pat.span); if etc { if !fields.is_empty() { self.word_space(","); @@ -1864,7 +1867,7 @@ impl<'a> State<'a> { self.space(); } self.cbox(INDENT_UNIT); - self.print_outer_attributes(&self.attrs(field.hir_id)); + self.print_outer_attributes(self.attrs(field.hir_id)); if !field.is_shorthand { self.print_ident(field.ident); self.word_nbsp(":"); @@ -2017,7 +2020,7 @@ impl<'a> State<'a> { fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) { match capture_clause { - hir::CaptureBy::Value => self.word_space("move"), + hir::CaptureBy::Value { .. } => self.word_space("move"), hir::CaptureBy::Ref => {} } } @@ -2123,7 +2126,7 @@ impl<'a> State<'a> { self.print_type(default); } } - GenericParamKind::Const { ty, ref default } => { + GenericParamKind::Const { ty, ref default, is_host_effect: _ } => { self.word_space(":"); self.print_type(ty); if let Some(default) = default { @@ -2164,7 +2167,7 @@ impl<'a> State<'a> { self.print_bounds(":", bounds); } hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - ref lifetime, + lifetime, bounds, .. }) => { diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 0062889d2445f..b0c60304424ad 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -19,7 +19,6 @@ rustc_infer = { path = "../rustc_infer" } rustc_lint = { path = "../rustc_lint" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 84e986488a6a4..e7cbbc713353f 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // #55810: Type check patterns first so we get types for all bindings. let scrut_span = scrut.span.find_ancestor_inside(expr.span).unwrap_or(scrut.span); for arm in arms { - self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut), None); + self.check_pat_top(arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut), None); } // Now typecheck the blocks. @@ -92,7 +92,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.diverges.set(Diverges::Maybe); - let arm_ty = self.check_expr_with_expectation(&arm.body, expected); + let arm_ty = self.check_expr_with_expectation(arm.body, expected); all_arms_diverge &= self.diverges.get(); let opt_suggest_box_span = prior_arm.and_then(|(_, prior_arm_ty, _)| { @@ -137,9 +137,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coercion.coerce_inner( self, &cause, - Some(&arm.body), + Some(arm.body), arm_ty, - |err| self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm), + |err| { + self.explain_never_type_coerced_to_unit(err, arm, arm_ty, prior_arm, expr); + }, false, ); @@ -177,6 +179,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { coercion.complete(self) } + fn explain_never_type_coerced_to_unit( + &self, + err: &mut Diagnostic, + arm: &hir::Arm<'tcx>, + arm_ty: Ty<'tcx>, + prior_arm: Option<(Option, Ty<'tcx>, Span)>, + expr: &hir::Expr<'tcx>, + ) { + if let hir::ExprKind::Block(block, _) = arm.body.kind + && let Some(expr) = block.expr + && let arm_tail_ty = self.node_ty(expr.hir_id) + && arm_tail_ty.is_never() + && !arm_ty.is_never() + { + err.span_label( + expr.span, + format!( + "this expression is of type `!`, but it is coerced to `{arm_ty}` due to its \ + surrounding expression", + ), + ); + self.suggest_mismatched_types_on_tail( + err, + expr, + arm_ty, + prior_arm.map_or(arm_tail_ty, |(_, ty, _)| ty), + expr.hir_id, + ); + } + self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm) + } + fn suggest_removing_semicolon_for_coerce( &self, diag: &mut Diagnostic, diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 6b6d1574b2bf6..a907acba0e030 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -6,9 +6,8 @@ use crate::errors; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, StashKey}; use rustc_hir as hir; -use rustc_hir::def::{self, CtorKind, DefKind, Namespace, Res}; +use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::HirId; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::{ infer, @@ -245,7 +244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { // Check for `self` receiver on the method, otherwise we can't use this as a `Fn*` trait. if !self.tcx.associated_item(ok.value.def_id).fn_has_self_parameter { - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( call_expr.span, "input to overloaded call fn is not a self receiver", ); @@ -260,9 +259,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else { // The `fn`/`fn_mut` lang item is ill-formed, which should have // caused an error elsewhere. - self.tcx - .sess - .delay_span_bug(call_expr.span, "input to call/call_mut is not a ref"); + self.tcx.sess.span_delayed_bug( + call_expr.span, + "input to call/call_mut is not a ref", + ); return None; }; @@ -373,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let (fn_sig, def_id) = match *callee_ty.kind() { ty::FnDef(def_id, args) => { - self.enforce_context_effects(call_expr.hir_id, call_expr.span, def_id, args); + self.enforce_context_effects(call_expr.span, def_id, args); let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args); // Unit testing: function items annotated with @@ -625,12 +625,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = callee_expr.kind + && let Res::Local(_) = path.res + && let [segment] = &path.segments[..] + { + for id in self.tcx.hir().items() { + if let Some(node) = self.tcx.hir().get_if_local(id.owner_id.into()) + && let hir::Node::Item(item) = node + && let hir::ItemKind::Fn(..) = item.kind + && item.ident.name == segment.ident.name + { + err.span_label( + self.tcx.def_span(id.owner_id), + "this function of the same name is available here, but it's shadowed by \ + the local binding", + ); + } + } + } + let mut inner_callee_path = None; let def = match callee_expr.kind { hir::ExprKind::Path(ref qpath) => { self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id) } - hir::ExprKind::Call(ref inner_callee, _) => { + hir::ExprKind::Call(inner_callee, _) => { if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind { inner_callee_path = Some(inner_qpath); self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id) @@ -751,7 +770,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[tracing::instrument(level = "debug", skip(self, span))] pub(super) fn enforce_context_effects( &self, - call_expr_hir: HirId, span: Span, callee_did: DefId, callee_args: GenericArgsRef<'tcx>, @@ -762,38 +780,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let generics = tcx.generics_of(callee_did); let Some(host_effect_index) = generics.host_effect_index else { return }; - // if the callee does have the param, we need to equate the param to some const - // value no matter whether the effects feature is enabled in the local crate, - // because inference will fail if we don't. - let mut host_always_on = - !tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you; - - // Compute the constness required by the context. - let context = tcx.hir().enclosing_body_owner(call_expr_hir); - let const_context = tcx.hir().body_const_context(context); - - let kind = tcx.def_kind(context.to_def_id()); - debug_assert_ne!(kind, DefKind::ConstParam); - - if tcx.has_attr(context.to_def_id(), sym::rustc_do_not_const_check) { - trace!("do not const check this context"); - host_always_on = true; - } - - let effect = match const_context { - _ if host_always_on => tcx.consts.true_, - Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => { - tcx.consts.false_ - } - Some(hir::ConstContext::ConstFn) => { - let host_idx = tcx - .generics_of(context) - .host_effect_index - .expect("ConstContext::Maybe must have host effect param"); - ty::GenericArgs::identity_for_item(tcx, context).const_at(host_idx) - } - None => tcx.consts.true_, - }; + let effect = tcx.expected_const_effect_param_for_body(self.body_id); trace!(?effect, ?generics, ?callee_args); @@ -826,7 +813,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected, ); - self.write_method_call(call_expr.hir_id, method_callee); + self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method_callee); output_type } } @@ -876,7 +863,11 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { adjustments.extend(autoref); fcx.apply_adjustments(self.callee_expr, adjustments); - fcx.write_method_call(self.call_expr.hir_id, method_callee); + fcx.write_method_call_and_enforce_effects( + self.call_expr.hir_id, + self.call_expr.span, + method_callee, + ); } None => { // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once` diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index ee23f47c2711c..d89af297560b4 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(match *t.kind() { ty::Slice(_) | ty::Str => Some(PointerKind::Length), - ty::Dynamic(ref tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())), + ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())), ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() { None => Some(PointerKind::Thin), Some(f) => { @@ -142,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let reported = self .tcx .sess - .delay_span_bug(span, format!("`{t:?}` should be sized but is not?")); + .span_delayed_bug(span, format!("`{t:?}` should be sized but is not?")); return Err(reported); } }) @@ -506,7 +506,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { }; SizedUnsizedCast { - sess: &fcx.tcx.sess, + sess: fcx.tcx.sess, span: self.span, expr_ty: self.expr_ty, cast_ty: fcx.ty_to_string(self.cast_ty), diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index b8a265d4971d2..0cd1ae2dbfe5c 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -34,7 +34,7 @@ pub(super) fn check_fn<'a, 'tcx>( can_be_coroutine: Option, params_can_be_unsized: bool, ) -> Option> { - let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id); + let fn_id = fcx.tcx.local_def_id_to_hir_id(fn_def_id); let tcx = fcx.tcx; let hir = tcx.hir(); @@ -76,7 +76,7 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.resume_yield_tys = Some((resume_ty, yield_ty)); } - GatherLocalsVisitor::new(&fcx).visit_body(body); + GatherLocalsVisitor::new(fcx).visit_body(body); // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` // (as it's created inside the body itself, not passed in from outside). @@ -94,7 +94,7 @@ pub(super) fn check_fn<'a, 'tcx>( for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() { // Check the pattern. let ty_span = try { inputs_hir?.get(idx)?.span }; - fcx.check_pat_top(¶m.pat, param_ty, ty_span, None, None); + fcx.check_pat_top(param.pat, param_ty, ty_span, None, None); // Check that argument is Sized. if !params_can_be_unsized { @@ -123,7 +123,7 @@ pub(super) fn check_fn<'a, 'tcx>( hir::FnRetTy::Return(ty) => ty.span, }; fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType); - fcx.check_return_expr(&body.value, false); + fcx.check_return_expr(body.value, false); // We insert the deferred_coroutine_interiors entry after visiting the body. // This ensures that all nested coroutines appear before the entry of this coroutine. @@ -156,7 +156,7 @@ pub(super) fn check_fn<'a, 'tcx>( // really expected to fail, since the coercions would have failed // earlier when trying to find a LUB. let coercion = fcx.ret_coercion.take().unwrap().into_inner(); - let mut actual_return_ty = coercion.complete(&fcx); + let mut actual_return_ty = coercion.complete(fcx); debug!("actual_return_ty = {:?}", actual_return_ty); if let ty::Dynamic(..) = declared_ret_ty.kind() { // We have special-cased the case where the function is declared @@ -214,7 +214,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> // build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !` let panic_info_ty = tcx.type_of(panic_info_did).instantiate( tcx, - &[ty::GenericArg::from(ty::Region::new_late_bound( + &[ty::GenericArg::from(ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon }, @@ -222,7 +222,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> ); let panic_info_ref_ty = Ty::new_imm_ref( tcx, - ty::Region::new_late_bound( + ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a70ead8e57d60..f0bb18df48c94 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{DefineOpaqueTypes, LateBoundRegionConversionTime}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; use rustc_infer::infer::{InferOk, InferResult}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; @@ -181,7 +181,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter_instantiated_copied(self.tcx, args) .map(|(c, s)| (c.as_predicate(), s)), ), - ty::Dynamic(ref object_type, ..) => { + ty::Dynamic(object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self); self.deduce_sig_from_projection(None, pb) @@ -558,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Instantiate (this part of..) S to S', i.e., with fresh variables. self.instantiate_binder_with_fresh_vars( hir_ty.span, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, // (*) binder moved to here supplied_sig.inputs().rebind(supplied_ty), ) @@ -583,7 +583,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let supplied_output_ty = self.instantiate_binder_with_fresh_vars( decl.output.span(), - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, supplied_sig.output(), ); let cause = &self.misc(decl.output.span()); @@ -624,13 +624,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { trace!("decl = {:#?}", decl); debug!(?body.coroutine_kind); - let hir_id = self.tcx.hir().local_def_id_to_hir_id(expr_def_id); + let hir_id = self.tcx.local_def_id_to_hir_id(expr_def_id); let bound_vars = self.tcx.late_bound_vars(hir_id); // First, convert the types that the user supplied (if any). let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); let supplied_return = match decl.output { - hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(&output), + hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(output), hir::FnRetTy::DefaultReturn(_) => match body.coroutine_kind { // In the case of the async block that we create for a function body, // we expect the return type of the block to match that of the enclosing @@ -651,9 +651,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ) } - Some(hir::CoroutineKind::Gen(hir::CoroutineSource::Fn)) => { - todo!("gen closures do not exist yet") - } + // For a `gen {}` block created as a `gen fn` body, we need the return type to be + // (). + Some(hir::CoroutineKind::Gen(hir::CoroutineSource::Fn)) => self.tcx.types.unit, _ => astconv.ty_infer(None, decl.output.span()), }, @@ -819,7 +819,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if let hir::FnRetTy::Return(ref output) = decl.output { - astconv.ast_ty_to_ty(&output); + astconv.ast_ty_to_ty(output); } let result = ty::Binder::dummy(self.tcx.mk_fn_sig( diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 6c03bc3b57ac6..7f56b3850dd8a 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -36,7 +36,9 @@ //! ``` use crate::FnCtxt; -use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ + struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -53,8 +55,7 @@ use rustc_middle::ty::adjustment::{ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, Ty, TypeAndMut}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeAndMut}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{self, DesugaringKind}; @@ -85,7 +86,7 @@ struct Coerce<'a, 'tcx> { impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> { type Target = FnCtxt<'a, 'tcx>; fn deref(&self) -> &Self::Target { - &self.fcx + self.fcx } } @@ -158,7 +159,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { if self.next_trait_solver() { if let Ok(res) = &res { for obligation in &res.obligations { - if !self.predicate_may_hold(&obligation) { + if !self.predicate_may_hold(obligation) { return Err(TypeError::Mismatch); } } @@ -626,7 +627,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { )]; let mut has_unsized_tuple_coercion = false; - let mut has_trait_upcasting_coercion = None; // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where @@ -694,13 +694,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // these here and emit a feature error if coercion doesn't fail // due to another reason. match impl_source { - traits::ImplSource::Builtin( - BuiltinImplSource::TraitUpcasting { .. }, - _, - ) => { - has_trait_upcasting_coercion = - Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1))); - } traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => { has_unsized_tuple_coercion = true; } @@ -711,21 +704,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } - if let Some((sub, sup)) = has_trait_upcasting_coercion - && !self.tcx().features().trait_upcasting - { - // Renders better when we erase regions, since they're not really the point here. - let (sub, sup) = self.tcx.erase_regions((sub, sup)); - let mut err = feature_err( - &self.tcx.sess.parse_sess, - sym::trait_upcasting, - self.cause.span, - format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"), - ); - err.note(format!("required when coercing `{source}` into `{target}`")); - err.emit(); - } - if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion { feature_err( &self.tcx.sess.parse_sess, @@ -1510,7 +1488,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expression, expression_ty, ), - Expressions::UpFront(ref coercion_sites) => fcx.try_find_coercion_lub( + Expressions::UpFront(coercion_sites) => fcx.try_find_coercion_lub( cause, &coercion_sites[0..self.pushed], self.merged_ty(), @@ -1572,7 +1550,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // any superfluous errors we might encounter while trying to // emit or provide suggestions on how to fix the initial error. fcx.set_tainted_by_errors( - fcx.tcx.sess.delay_span_bug(cause.span, "coercion error but no error emitted"), + fcx.tcx + .sess + .span_delayed_bug(cause.span, "coercion error but no error emitted"), ); let (expected, found) = if label_expression_as_expected { // In the case where this is a "forced unit", like @@ -1660,12 +1640,15 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { None, Some(coercion_error), ); - } - - if visitor.ret_exprs.len() > 0 - && let Some(expr) = expression - { - self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs); + if visitor.ret_exprs.len() > 0 { + self.note_unreachable_loop_return( + &mut err, + fcx.tcx, + &expr, + &visitor.ret_exprs, + expected, + ); + } } let reported = err.emit_unless(unsized_return); @@ -1678,8 +1661,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fn note_unreachable_loop_return( &self, err: &mut Diagnostic, + tcx: TyCtxt<'tcx>, expr: &hir::Expr<'tcx>, ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>, + ty: Ty<'tcx>, ) { let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else { return; @@ -1704,10 +1689,77 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { ret_exprs.len() - MAXITER )); } - err.help( - "return a value for the case when the loop has zero elements to iterate on, or \ - consider changing the return type to account for that possibility", - ); + let hir = tcx.hir(); + let item = hir.get_parent_item(expr.hir_id); + let ret_msg = "return a value for the case when the loop has zero elements to iterate on"; + let ret_ty_msg = + "otherwise consider changing the return type to account for that possibility"; + if let Some(node) = hir.find(item.into()) + && let Some(body_id) = node.body_id() + && let Some(sig) = node.fn_sig() + && let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind + && !ty.is_never() + { + let indentation = if let None = block.expr + && let [.., last] = &block.stmts[..] + { + tcx.sess.source_map().indentation_before(last.span).unwrap_or_else(String::new) + } else if let Some(expr) = block.expr { + tcx.sess.source_map().indentation_before(expr.span).unwrap_or_else(String::new) + } else { + String::new() + }; + if let None = block.expr + && let [.., last] = &block.stmts[..] + { + err.span_suggestion_verbose( + last.span.shrink_to_hi(), + ret_msg, + format!("\n{indentation}/* `{ty}` value */"), + Applicability::MaybeIncorrect, + ); + } else if let Some(expr) = block.expr { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + ret_msg, + format!("\n{indentation}/* `{ty}` value */"), + Applicability::MaybeIncorrect, + ); + } + let mut sugg = match sig.decl.output { + hir::FnRetTy::DefaultReturn(span) => { + vec![(span, " -> Option<()>".to_string())] + } + hir::FnRetTy::Return(ty) => { + vec![ + (ty.span.shrink_to_lo(), "Option<".to_string()), + (ty.span.shrink_to_hi(), ">".to_string()), + ] + } + }; + for ret_expr in ret_exprs { + match ret_expr.kind { + hir::ExprKind::Ret(Some(expr)) => { + sugg.push((expr.span.shrink_to_lo(), "Some(".to_string())); + sugg.push((expr.span.shrink_to_hi(), ")".to_string())); + } + hir::ExprKind::Ret(None) => { + sugg.push((ret_expr.span.shrink_to_hi(), " Some(())".to_string())); + } + _ => {} + } + } + if let None = block.expr + && let [.., last] = &block.stmts[..] + { + sugg.push((last.span.shrink_to_hi(), format!("\n{indentation}None"))); + } else if let Some(expr) = block.expr { + sugg.push((expr.span.shrink_to_hi(), format!("\n{indentation}None"))); + } + err.multipart_suggestion(ret_ty_msg, sugg, Applicability::MaybeIncorrect); + } else { + err.help(format!("{ret_msg}, {ret_ty_msg}")); + } } fn report_return_mismatched_types<'a>( @@ -1738,6 +1790,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // label pointing out the cause for the type coercion will be wrong // as prior return coercions would not be relevant (#57664). let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) { + fcx.suggest_missing_semicolon(&mut err, expr, expected, false); let pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id); if let (Some(cond_expr), true, false) = ( @@ -1772,7 +1825,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if blk_id.is_none() { fcx.suggest_missing_return_type( &mut err, - &fn_decl, + fn_decl, expected, found, can_suggest, @@ -1871,6 +1924,6 @@ impl AsCoercionSite for ! { impl AsCoercionSite for hir::Arm<'_> { fn as_coercion_site(&self) -> &hir::Expr<'_> { - &self.body + self.body } } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index acaa3e02f092f..8f63383488531 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -31,9 +31,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.annotate_alternative_method_deref(err, expr, error); + self.explain_self_literal(err, expr, expected, expr_ty); // Use `||` to give these suggestions a precedence let suggested = self.suggest_missing_parentheses(err, expr) + || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty) || self.suggest_remove_last_method_call(err, expr, expected) || self.suggest_associated_const(err, expr, expected) || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr) @@ -49,8 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_into(err, expr, expr_ty, expected) || self.suggest_floating_point_literal(err, expr, expected) || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected) - || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty) - || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty); + || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty); if !suggested { self.note_source_of_type_mismatch_constraint( @@ -183,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_predicates(obligations); None } - Err(e) => Some(self.err_ctxt().report_mismatched_types(&cause, expected, actual, e)), + Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)), } } @@ -255,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.adjust_expr_for_assert_eq_macro(&mut expr, &mut expected_ty_expr); - self.set_tainted_by_errors(self.tcx.sess.delay_span_bug( + self.set_tainted_by_errors(self.tcx.sess.span_delayed_bug( expr.span, "`TypeError` when attempting coercion but no error emitted", )); @@ -882,7 +883,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let container_id = pick.item.container_id(self.tcx); let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id)); for def_id in pick.import_ids { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = self.tcx.local_def_id_to_hir_id(def_id); path_span.push_span_label( self.tcx.hir().span(hir_id), format!("`{container}` imported here"), @@ -1027,6 +1028,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } + fn explain_self_literal( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'tcx>, + expected: Ty<'tcx>, + found: Ty<'tcx>, + ) { + match expr.peel_drop_temps().kind { + hir::ExprKind::Struct( + hir::QPath::Resolved( + None, + hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, span, .. }, + ), + .., + ) + | hir::ExprKind::Call( + hir::Expr { + kind: + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { + res: hir::def::Res::SelfTyAlias { alias_to, .. }, + span, + .. + }, + )), + .. + }, + .., + ) => { + if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }), + .. + })) = self.tcx.hir().get_if_local(*alias_to) + { + err.span_label(self_ty.span, "this is the type of the `Self` literal"); + } + if let ty::Adt(e_def, e_args) = expected.kind() + && let ty::Adt(f_def, _f_args) = found.kind() + && e_def == f_def + { + err.span_suggestion_verbose( + *span, + "use the type name directly", + self.tcx.value_path_str_with_args(*alias_to, e_args), + Applicability::MaybeIncorrect, + ); + } + } + _ => {} + } + } + fn note_wrong_return_ty_due_to_generic_arg( &self, err: &mut Diagnostic, diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index aff1baa19601d..74aec897f959e 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -626,7 +626,7 @@ pub struct SuggestConvertViaMethod<'tcx> { pub span: Span, #[suggestion_part(code = "")] pub borrow_removal_span: Option, - pub sugg: &'static str, + pub sugg: String, pub expected: Ty<'tcx>, pub found: Ty<'tcx>, } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a11fe10c01c74..7c157c0eae01d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -13,7 +13,7 @@ use crate::errors::{ YieldExprOutsideOfCoroutine, }; use crate::fatally_break_rust; -use crate::method::{MethodCallComponents, SelfSource}; +use crate::method::SelfSource; use crate::type_error_struct; use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation}; use crate::{ @@ -21,7 +21,7 @@ use crate::{ TupleArgumentsFlag::DontTupleArguments, }; use rustc_ast as ast; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, @@ -75,7 +75,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // coercions from ! to `expected`. if ty.is_never() { if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { - let reported = self.tcx().sess.delay_span_bug( + let reported = self.tcx().sess.span_delayed_bug( expr.span, "expression with never type wound up being adjusted", ); @@ -277,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; match expr.kind { - ExprKind::Lit(ref lit) => self.check_lit(&lit, expected), + ExprKind::Lit(ref lit) => self.check_lit(lit, expected), ExprKind::Binary(op, lhs, rhs) => self.check_binop(expr, op, lhs, rhs, expected), ExprKind::Assign(lhs, rhs, span) => { self.check_expr_assign(expr, expected, lhs, rhs, span) @@ -289,8 +289,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::AddrOf(kind, mutbl, oprnd) => { self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr) } - ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => { - self.check_lang_item_path(lang_item, expr, hir_id) + ExprKind::Path(QPath::LangItem(lang_item, _)) => { + self.check_lang_item_path(lang_item, expr) } ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]), ExprKind::InlineAsm(asm) => { @@ -298,9 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id)); self.check_expr_asm(asm) } - ExprKind::OffsetOf(container, ref fields) => { - self.check_offset_of(container, fields, expr) - } + ExprKind::OffsetOf(container, fields) => self.check_offset_of(container, fields, expr), ExprKind::Break(destination, ref expr_opt) => { self.check_expr_break(destination, expr_opt.as_deref(), expr) } @@ -319,17 +317,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_loop(body, source, expected, expr) } ExprKind::Match(discrim, arms, match_src) => { - self.check_match(expr, &discrim, arms, expected, match_src) + self.check_match(expr, discrim, arms, expected, match_src) } ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected), - ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected), - ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected), + ExprKind::Block(body, _) => self.check_block_with_expected(body, expected), + ExprKind::Call(callee, args) => self.check_call(expr, callee, args, expected), ExprKind::MethodCall(segment, receiver, args, _) => { self.check_method_call(expr, segment, receiver, args, expected) } ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr), ExprKind::Type(e, t) => { - let ascribed_ty = self.to_ty_saving_user_provided_ty(&t); + let ascribed_ty = self.to_ty_saving_user_provided_ty(t); let ty = self.check_expr_with_hint(e, ascribed_ty); self.demand_eqtype(e.span, ascribed_ty, ty); ascribed_ty @@ -347,7 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Struct(qpath, fields, ref base_expr) => { self.check_expr_struct(expr, expected, qpath, fields, base_expr) } - ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected), + ExprKind::Field(base, field) => self.check_field(expr, base, field, expected), ExprKind::Index(base, idx, brackets_span) => { self.check_expr_index(base, idx, expr, brackets_span) } @@ -368,7 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::UnOp::Not | hir::UnOp::Neg => expected, hir::UnOp::Deref => NoExpectation, }; - let mut oprnd_t = self.check_expr_with_expectation(&oprnd, expected_inner); + let mut oprnd_t = self.check_expr_with_expectation(oprnd, expected_inner); if !oprnd_t.references_error() { oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t); @@ -436,7 +434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }); let ty = - self.check_expr_with_expectation_and_needs(&oprnd, hint, Needs::maybe_mut_place(mutbl)); + self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl)); let tm = ty::TypeAndMut { ty, mutbl }; match kind { @@ -499,9 +497,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, lang_item: hir::LangItem, expr: &'tcx hir::Expr<'tcx>, - hir_id: Option, ) -> Ty<'tcx> { - self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1 + self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 } pub(crate) fn check_expr_path( @@ -512,12 +509,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let (res, opt_ty, segs) = - self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); + self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args)); let ty = match res { Res::Err => { self.suggest_assoc_method_call(segs); let e = - self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted"); + self.tcx.sess.span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); Ty::new_error(tcx, e) } @@ -528,14 +525,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, }; - if let ty::FnDef(did, callee_args) = *ty.kind() { + if let ty::FnDef(did, _) = *ty.kind() { let fn_sig = ty.fn_sig(tcx); - // HACK: whenever we get a FnDef in a non-const context, enforce effects to get the - // default `host = true` to avoid inference errors later. - if tcx.hir().body_const_context(self.body_id).is_none() { - self.enforce_context_effects(expr.hir_id, qpath.span(), did, callee_args); - } if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic && tcx.item_name(did) == sym::transmute { @@ -564,7 +556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); let input = self.instantiate_binder_with_fresh_vars( span, - infer::LateBoundRegionConversionTime::FnCall, + infer::BoundRegionConversionTime::FnCall, fn_sig.input(i), ); self.require_type_is_sized_deferred( @@ -582,7 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // with fresh vars. let output = self.instantiate_binder_with_fresh_vars( expr.span, - infer::LateBoundRegionConversionTime::FnCall, + infer::BoundRegionConversionTime::FnCall, fn_sig.output(), ); self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); @@ -626,15 +618,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - let coerce_to = match opt_coerce_to { - Some(c) => c, - None => { - // If the loop context is not a `loop { }`, then break with - // a value is illegal, and `opt_coerce_to` will be `None`. - // Return error in that case (#114529). - return Ty::new_misc_error(tcx); - } - }; + // If the loop context is not a `loop { }`, then break with + // a value is illegal, and `opt_coerce_to` will be `None`. + // Set expectation to error in that case and set tainted + // by error (#114529) + let coerce_to = opt_coerce_to.unwrap_or_else(|| { + let guar = tcx.sess.span_delayed_bug( + expr.span, + "illegal break with value found but no error reported", + ); + self.set_tainted_by_errors(guar); + Ty::new_error(tcx, guar) + }); // Recurse without `enclosing_breakables` borrowed. e_ty = self.check_expr_with_hint(e, coerce_to); @@ -660,7 +655,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Some(ref mut coerce) = ctxt.coerce { - if let Some(ref e) = expr_opt { + if let Some(e) = expr_opt { coerce.coerce(self, &cause, e, e_ty); } else { assert!(e_ty.is_unit()); @@ -669,11 +664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self, &cause, |mut err| { + self.suggest_missing_semicolon(&mut err, expr, e_ty, false); self.suggest_mismatched_types_on_tail( &mut err, expr, ty, e_ty, target_id, ); let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty })); - self.annotate_loop_expected_due_to_inference(&mut err, expr, error); + self.annotate_loop_expected_due_to_inference(err, expr, error); if let Some(val) = ty_kind_suggestion(ty) { err.span_suggestion_verbose( expr.span.shrink_to_hi(), @@ -959,12 +955,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); }); + self.check_for_missing_semi(lhs, &mut err); adjust_err(&mut err); err.emit(); } + /// Check if the expression that could not be assigned to was a typoed expression that + pub fn check_for_missing_semi( + &self, + expr: &'tcx hir::Expr<'tcx>, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + ) -> bool { + if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind + && let hir::BinOpKind::Mul = binop.node + && self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span)) + && rhs.is_syntactic_place_expr() + { + // v missing semicolon here + // foo() + // *bar = baz; + // (#80446). + err.span_suggestion_verbose( + lhs.span.shrink_to_hi(), + "you might have meant to write a semicolon here", + ";".to_string(), + Applicability::MachineApplicable, + ); + return true; + } + false + } + // Check if an expression `original_expr_id` comes from the condition of a while loop, /// as opposed from the body of a while loop, which we can naively check by iterating /// parents until we find a loop... @@ -1106,8 +1129,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The likely cause of this is `if foo = bar { .. }`. let actual_ty = Ty::new_unit(self.tcx); let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap(); - let lhs_ty = self.check_expr(&lhs); - let rhs_ty = self.check_expr(&rhs); + let lhs_ty = self.check_expr(lhs); + let rhs_ty = self.check_expr(rhs); let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) { (Applicability::MachineApplicable, true) } else if let ExprKind::Binary( @@ -1118,7 +1141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // if x == 1 && y == 2 { .. } // + - let actual_lhs_ty = self.check_expr(&rhs_expr); + let actual_lhs_ty = self.check_expr(rhs_expr); (Applicability::MaybeIncorrect, self.can_coerce(rhs_ty, actual_lhs_ty)) } else if let ExprKind::Binary( Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, @@ -1128,7 +1151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // if x == 1 && y == 2 { .. } // + - let actual_rhs_ty = self.check_expr(&lhs_expr); + let actual_rhs_ty = self.check_expr(lhs_expr); (Applicability::MaybeIncorrect, self.can_coerce(actual_rhs_ty, lhs_ty)) } else { (Applicability::MaybeIncorrect, false) @@ -1165,7 +1188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ty::new_error(self.tcx, reported); } - let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); + let lhs_ty = self.check_expr_with_needs(lhs, Needs::MutPlace); let suggest_deref_binop = |err: &mut Diagnostic, rhs_ty: Ty<'tcx>| { if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) { @@ -1192,7 +1215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This is (basically) inlined `check_expr_coercible_to_type`, but we want // to suggest an additional fixup here in `suggest_deref_binop`. - let rhs_ty = self.check_expr_with_hint(&rhs, lhs_ty); + let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty); if let (_, Some(mut diag)) = self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No) { @@ -1253,7 +1276,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let (ctxt, ()) = self.with_breakable_ctxt(expr.hir_id, ctxt, || { - self.check_block_no_value(&body); + self.check_block_no_value(body); }); if ctxt.may_break { @@ -1269,7 +1292,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // permit break with a value [1]. if ctxt.coerce.is_none() && !ctxt.may_break { // [1] - self.tcx.sess.delay_span_bug(body.span, "no coercion, but loop may not break"); + self.tcx.sess.span_delayed_bug(body.span, "no coercion, but loop may not break"); } ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| Ty::new_unit(self.tcx)) } @@ -1283,7 +1306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let rcvr_t = self.check_expr(&rcvr); + let rcvr_t = self.check_expr(rcvr); // no need to check for bot/err -- callee does that let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t); let span = segment.ident.span; @@ -1292,9 +1315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(method) => { // We could add a "consider `foo::`" suggestion here, but I wasn't able to // trigger this codepath causing `structurally_resolve_type` to emit an error. - - self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.args); - self.write_method_call(expr.hir_id, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); Ok(method) } Err(error) => { @@ -1305,7 +1326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { segment.ident, SelfSource::MethodCall(rcvr), error, - Some(MethodCallComponents { receiver: rcvr, args, full_expr: expr }), + Some(args), expected, false, ) { @@ -1317,7 +1338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Call the generic checker. - self.check_method_argument_types(span, expr, method, &args, DontTupleArguments, expected) + self.check_method_argument_types(span, expr, method, args, DontTupleArguments, expected) } fn check_expr_cast( @@ -1448,7 +1469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fcx = FnCtxt::new(self, self.param_env, def_id); crate::GatherLocalsVisitor::new(&fcx).visit_body(body); - let ty = fcx.check_expr_with_expectation(&body.value, expected); + let ty = fcx.check_expr_with_expectation(body.value, expected); fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized); fcx.write_ty(block.hir_id, ty); ty @@ -1477,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (element_ty, t) = match uty { Some(uty) => { - self.check_expr_coercible_to_type(&element, uty, None); + self.check_expr_coercible_to_type(element, uty, None); (uty, uty) } None => { @@ -1485,7 +1506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::MiscVariable, span: element.span, }); - let element_ty = self.check_expr_has_type_or_error(&element, ty, |_| {}); + let element_ty = self.check_expr_has_type_or_error(element, ty, |_| {}); (element_ty, ty) } }; @@ -1524,21 +1545,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => {} } - // If someone calls a const fn, they can extract that call out into a separate constant (or a const - // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck. - let is_const_fn = match element.kind { + // If someone calls a const fn or constructs a const value, they can extract that + // out into a separate constant (or a const block in the future), so we check that + // to tell them that in the diagnostic. Does not affect typeck. + let is_constable = match element.kind { hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() { - ty::FnDef(def_id, _) => tcx.is_const_fn(def_id), - _ => false, + ty::FnDef(def_id, _) if tcx.is_const_fn(def_id) => traits::IsConstable::Fn, + _ => traits::IsConstable::No, }, - _ => false, + hir::ExprKind::Path(qpath) => { + match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) { + Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor, + _ => traits::IsConstable::No, + } + } + _ => traits::IsConstable::No, }; // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we // don't copy that one element, we move it. Only check for Copy if the length is larger. if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) { let lang_item = self.tcx.require_lang_item(LangItem::Copy, None); - let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn }; + let code = traits::ObligationCauseCode::RepeatElementCopy { + is_constable, + elt_type: element_ty, + elt_span: element.span, + elt_stmt_span: self + .tcx + .hir() + .parent_iter(element.hir_id) + .find_map(|(_, node)| match node { + hir::Node::Item(it) => Some(it.span), + hir::Node::Stmt(stmt) => Some(stmt.span), + _ => None, + }) + .expect("array repeat expressions must be inside an item or statement"), + }; self.require_type_meets(element_ty, element.span, code, lang_item); } } @@ -1560,10 +1602,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { Some(fs) if i < fs.len() => { let ety = fs[i]; - self.check_expr_coercible_to_type(&e, ety, None); + self.check_expr_coercible_to_type(e, ety, None); ety } - _ => self.check_expr_with_expectation(&e, NoExpectation), + _ => self.check_expr_with_expectation(e, NoExpectation), }); let tuple = Ty::new_tup_from_iter(self.tcx, elt_ts_iter); if let Err(guar) = tuple.error_reported() { @@ -1689,9 +1731,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Make sure to give a type to the field even if there's // an error, so we can continue type-checking. - let ty = self.check_expr_with_hint(&field.expr, field_type); + let ty = self.check_expr_with_hint(field.expr, field_type); let (_, diag) = - self.demand_coerce_diag(&field.expr, ty, field_type, None, AllowTwoPhase::No); + self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No); if let Some(mut diag) = diag { if idx == ast_fields.len() - 1 { @@ -1849,7 +1891,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); if !private_fields.is_empty() { - self.report_private_fields(adt_ty, span, private_fields, ast_fields); + self.report_private_fields(adt_ty, span, expr.span, private_fields, ast_fields); } else { self.report_missing_fields( adt_ty, @@ -1869,10 +1911,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>, ) { for field in fields { - self.check_expr(&field.expr); + self.check_expr(field.expr); } if let Some(base) = *base_expr { - self.check_expr(&base); + self.check_expr(base); } } @@ -1885,7 +1927,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// 8 | foo::Foo {}; /// | ^^^^^^^^ missing `you_can_use_this_field` /// - /// error: aborting due to previous error + /// error: aborting due to 1 previous error /// ``` fn report_missing_fields( &self, @@ -2002,12 +2044,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// 8 | foo::Foo {}; /// | ^^^^^^^^ /// - /// error: aborting due to previous error + /// error: aborting due to 1 previous error /// ``` fn report_private_fields( &self, adt_ty: Ty<'tcx>, span: Span, + expr_span: Span, private_fields: Vec<&ty::FieldDef>, used_fields: &'tcx [hir::ExprField<'tcx>], ) { @@ -2047,11 +2090,87 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [] => unreachable!(), }; err.note(format!( - "... and other private field{s} {names}that {were} not provided", + "{}private field{s} {names}that {were} not provided", + if used_fields.is_empty() { "" } else { "...and other " }, s = pluralize!(remaining_private_fields_len), were = pluralize!("was", remaining_private_fields_len), )); } + + if let ty::Adt(def, _) = adt_ty.kind() { + let def_id = def.did(); + let mut items = self + .tcx + .inherent_impls(def_id) + .iter() + .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) + // Only assoc fn with no receivers. + .filter(|item| { + matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter + }) + .filter_map(|item| { + // Only assoc fns that return `Self` + let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder(); + let ret_ty = fn_sig.output(); + let ret_ty = + self.tcx.normalize_erasing_late_bound_regions(self.param_env, ret_ty); + if !self.can_eq(self.param_env, ret_ty, adt_ty) { + return None; + } + let input_len = fn_sig.inputs().skip_binder().len(); + let order = !item.name.as_str().starts_with("new"); + Some((order, item.name, input_len)) + }) + .collect::>(); + items.sort_by_key(|(order, _, _)| *order); + let suggestion = |name, args| { + format!( + "::{name}({})", + std::iter::repeat("_").take(args).collect::>().join(", ") + ) + }; + match &items[..] { + [] => {} + [(_, name, args)] => { + err.span_suggestion_verbose( + span.shrink_to_hi().with_hi(expr_span.hi()), + format!("you might have meant to use the `{name}` associated function"), + suggestion(name, *args), + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_suggestions( + span.shrink_to_hi().with_hi(expr_span.hi()), + "you might have meant to use an associated function to build this type", + items + .iter() + .map(|(_, name, args)| suggestion(name, *args)) + .collect::>(), + Applicability::MaybeIncorrect, + ); + } + } + if let Some(default_trait) = self.tcx.get_diagnostic_item(sym::Default) + && self + .infcx + .type_implements_trait(default_trait, [adt_ty], self.param_env) + .may_apply() + { + err.multipart_suggestion( + "consider using the `Default` trait", + vec![ + (span.shrink_to_lo(), "<".to_string()), + ( + span.shrink_to_hi().with_hi(expr_span.hi()), + " as std::default::Default>::default()".to_string(), + ), + ], + Applicability::MaybeIncorrect, + ); + } + } + err.emit(); } @@ -2068,7 +2187,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let guar = self .tcx .sess - .delay_span_bug(expr.span, "parser recovered but no error was emitted"); + .span_delayed_bug(expr.span, "parser recovered but no error was emitted"); self.set_tainted_by_errors(guar); return guar; } @@ -2143,7 +2262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(field_name) = find_best_match_for_name(&available_field_names, field.ident.name, None) { - err.span_suggestion( + err.span_label(field.ident.span, "unknown field"); + err.span_suggestion_verbose( field.ident.span, "a field with a similar name exists", field_name, @@ -2226,7 +2346,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match deref_base_ty.kind() { ty::Adt(base_def, args) if !base_def.is_enum() => { debug!("struct named {:?}", deref_base_ty); - let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id); + let body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id); let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id); let fields = &base_def.non_enum_variant().fields; @@ -2283,7 +2403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let guar = if field.name == kw::Empty { - self.tcx.sess.delay_span_bug(field.span, "field name with no name") + self.tcx.sess.span_delayed_bug(field.span, "field name with no name") } else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) { self.ban_take_value_of_method(expr, base_ty, field) } else if !base_ty.is_primitive_ty() { @@ -2372,35 +2492,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) { let Some(output_ty) = self.get_impl_future_output_ty(ty) else { + err.span_label(field_ident.span, "unknown field"); return; }; - let mut add_label = true; - if let ty::Adt(def, _) = output_ty.kind() { - // no field access on enum type - if !def.is_enum() { - if def - .non_enum_variant() - .fields - .iter() - .any(|field| field.ident(self.tcx) == field_ident) - { - add_label = false; - err.span_label( - field_ident.span, - "field not available in `impl Future`, but it is available in its `Output`", - ); - err.span_suggestion_verbose( - base.span.shrink_to_hi(), - "consider `await`ing on the `Future` and access the field of its `Output`", - ".await", - Applicability::MaybeIncorrect, - ); - } - } + let ty::Adt(def, _) = output_ty.kind() else { + err.span_label(field_ident.span, "unknown field"); + return; + }; + // no field access on enum type + if def.is_enum() { + err.span_label(field_ident.span, "unknown field"); + return; } - if add_label { - err.span_label(field_ident.span, format!("field not found in `{ty}`")); + if !def.non_enum_variant().fields.iter().any(|field| field.ident(self.tcx) == field_ident) { + err.span_label(field_ident.span, "unknown field"); + return; } + err.span_label( + field_ident.span, + "field not available in `impl Future`, but it is available in its `Output`", + ); + err.span_suggestion_verbose( + base.span.shrink_to_hi(), + "consider `await`ing on the `Future` and access the field of its `Output`", + ".await", + Applicability::MaybeIncorrect, + ); } fn ban_nonexisting_field( @@ -2423,16 +2540,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::RawPtr(..) => { self.suggest_first_deref_field(&mut err, expr, base, ident); } - ty::Adt(def, _) if !def.is_enum() => { - self.suggest_fields_on_recordish(&mut err, expr, def, ident); - } ty::Param(param_ty) => { + err.span_label(ident.span, "unknown field"); self.point_at_param_definition(&mut err, param_ty); } ty::Alias(ty::Opaque, _) => { self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs()); } - _ => {} + _ => { + err.span_label(ident.span, "unknown field"); + } } self.suggest_fn_call(&mut err, base, base_ty, |output_ty| { @@ -2576,7 +2693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let param_def_id = generic_param.def_id; let param_hir_id = match param_def_id.as_local() { - Some(x) => self.tcx.hir().local_def_id_to_hir_id(x), + Some(x) => self.tcx.local_def_id_to_hir_id(x), None => return, }; let param_span = self.tcx.hir().span(param_hir_id); @@ -2585,34 +2702,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(param_span, format!("type parameter '{param_name}' declared here")); } - fn suggest_fields_on_recordish( - &self, - err: &mut Diagnostic, - expr: &hir::Expr<'_>, - def: ty::AdtDef<'tcx>, - field: Ident, - ) { - let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]); - if let Some(suggested_field_name) = - find_best_match_for_name(&available_field_names, field.name, None) - { - err.span_suggestion( - field.span, - "a field with a similar name exists", - suggested_field_name, - Applicability::MaybeIncorrect, - ); - } else { - err.span_label(field.span, "unknown field"); - if !available_field_names.is_empty() { - err.note(format!( - "available fields are: {}", - self.name_series_display(available_field_names), - )); - } - } - } - fn maybe_suggest_array_indexing( &self, err: &mut Diagnostic, @@ -2621,6 +2710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: Ident, len: ty::Const<'tcx>, ) { + err.span_label(field.span, "unknown field"); if let (Some(len), Ok(user_index)) = (len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::()) && let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) @@ -2643,6 +2733,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base: &hir::Expr<'_>, field: Ident, ) { + err.span_label(field.span, "unknown field"); if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) { let msg = format!("`{base}` is a raw pointer; try dereferencing it"); let suggestion = format!("(*{base}).{field}"); @@ -2661,7 +2752,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = type_error_struct!( self.tcx().sess, - field.span, + span, expr_t, E0609, "no field `{field}` on type `{expr_t}`", @@ -2669,10 +2760,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // try to add a suggestion in case the field is a nested field of a field of the Adt let mod_id = self.tcx.parent_module(id).to_def_id(); - if let Some((fields, args)) = - self.get_field_candidates_considering_privacy(span, expr_t, mod_id) + let (ty, unwrap) = if let ty::Adt(def, args) = expr_t.kind() + && (self.tcx.is_diagnostic_item(sym::Result, def.did()) + || self.tcx.is_diagnostic_item(sym::Option, def.did())) + && let Some(arg) = args.get(0) + && let Some(ty) = arg.as_type() { - let candidate_fields: Vec<_> = fields + (ty, "unwrap().") + } else { + (expr_t, "") + }; + for (found_fields, args) in + self.get_field_candidates_considering_privacy(span, ty, mod_id, id) + { + let field_names = found_fields.iter().map(|field| field.name).collect::>(); + let mut candidate_fields: Vec<_> = found_fields + .into_iter() .filter_map(|candidate_field| { self.check_for_nested_field_satisfying( span, @@ -2681,17 +2784,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args, vec![], mod_id, + id, ) }) .map(|mut field_path| { field_path.pop(); field_path .iter() - .map(|id| id.name.to_ident_string()) - .collect::>() - .join(".") + .map(|id| format!("{}.", id.name.to_ident_string())) + .collect::() }) .collect::>(); + candidate_fields.sort(); let len = candidate_fields.len(); if len > 0 { @@ -2702,9 +2806,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if len > 1 { "some" } else { "one" }, if len > 1 { "have" } else { "has" }, ), - candidate_fields.iter().map(|path| format!("{path}.")), + candidate_fields.iter().map(|path| format!("{unwrap}{path}")), Applicability::MaybeIncorrect, ); + } else { + if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) { + err.span_suggestion_verbose( + field.span, + "a field with a similar name exists", + format!("{unwrap}{}", field_name), + Applicability::MaybeIncorrect, + ); + } else if !field_names.is_empty() { + let is = if field_names.len() == 1 { " is" } else { "s are" }; + err.note(format!( + "available field{is}: {}", + self.name_series_display(field_names), + )); + } } } err @@ -2733,33 +2852,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, base_ty: Ty<'tcx>, mod_id: DefId, - ) -> Option<(impl Iterator + 'tcx, GenericArgsRef<'tcx>)> { + hir_id: hir::HirId, + ) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> { debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty); - for (base_t, _) in self.autoderef(span, base_ty) { - match base_t.kind() { - ty::Adt(base_def, args) if !base_def.is_enum() => { - let tcx = self.tcx; - let fields = &base_def.non_enum_variant().fields; - // Some struct, e.g. some that impl `Deref`, have all private fields - // because you're expected to deref them to access the _real_ fields. - // This, for example, will help us suggest accessing a field through a `Box`. - if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { - continue; + self.autoderef(span, base_ty) + .filter_map(move |(base_t, _)| { + match base_t.kind() { + ty::Adt(base_def, args) if !base_def.is_enum() => { + let tcx = self.tcx; + let fields = &base_def.non_enum_variant().fields; + // Some struct, e.g. some that impl `Deref`, have all private fields + // because you're expected to deref them to access the _real_ fields. + // This, for example, will help us suggest accessing a field through a `Box`. + if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { + return None; + } + return Some(( + fields + .iter() + .filter(move |field| { + field.vis.is_accessible_from(mod_id, tcx) + && self.is_field_suggestable(field, hir_id, span) + }) + // For compile-time reasons put a limit on number of fields we search + .take(100) + .collect::>(), + *args, + )); } - return Some(( - fields - .iter() - .filter(move |field| field.vis.is_accessible_from(mod_id, tcx)) - // For compile-time reasons put a limit on number of fields we search - .take(100), - args, - )); + _ => None, } - _ => {} - } - } - None + }) + .collect() } /// This method is called after we have encountered a missing field error to recursively @@ -2772,6 +2897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { subst: GenericArgsRef<'tcx>, mut field_path: Vec, mod_id: DefId, + hir_id: HirId, ) -> Option> { debug!( "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}", @@ -2787,20 +2913,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let field_ty = candidate_field.ty(self.tcx, subst); if matches(candidate_field, field_ty) { return Some(field_path); - } else if let Some((nested_fields, subst)) = - self.get_field_candidates_considering_privacy(span, field_ty, mod_id) - { - // recursively search fields of `candidate_field` if it's a ty::Adt - for field in nested_fields { - if let Some(field_path) = self.check_for_nested_field_satisfying( - span, - matches, - field, - subst, - field_path.clone(), - mod_id, - ) { - return Some(field_path); + } else { + for (nested_fields, subst) in + self.get_field_candidates_considering_privacy(span, field_ty, mod_id, hir_id) + { + // recursively search fields of `candidate_field` if it's a ty::Adt + for field in nested_fields { + if let Some(field_path) = self.check_for_nested_field_satisfying( + span, + matches, + field, + subst, + field_path.clone(), + mod_id, + hir_id, + ) { + return Some(field_path); + } } } } @@ -2815,8 +2944,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, brackets_span: Span, ) -> Ty<'tcx> { - let base_t = self.check_expr(&base); - let idx_t = self.check_expr(&idx); + let base_t = self.check_expr(base); + let idx_t = self.check_expr(idx); if base_t.references_error() { base_t @@ -2829,7 +2958,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // two-phase not needed because index_ty is never mutable self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); self.select_obligations_where_possible(|errors| { - self.point_at_index_if_possible(errors, idx.span) + self.point_at_index(errors, idx.span); }); element_ty } @@ -2857,7 +2986,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: - if let ExprKind::Lit(ref lit) = idx.kind + if let ExprKind::Lit(lit) = idx.kind && let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node && i < types .len() @@ -2930,7 +3059,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - self.commit_if_ok(|_| { + self.commit_if_ok(|snapshot| { + let outer_universe = self.universe(); + let ocx = ObligationCtxt::new(self); let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id); let impl_trait_ref = @@ -2940,7 +3071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Match the impl self type against the base ty. If this fails, // we just skip this impl, since it's not particularly useful. let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref); - ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?; + ocx.eq(&cause, self.param_env, base_ty, impl_trait_ref.self_ty())?; // Register the impl's predicates. One of these predicates // must be unsatisfied, or else we wouldn't have gotten here @@ -2976,11 +3107,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args), ); - let errors = ocx.select_where_possible(); + let true_errors = ocx.select_where_possible(); + + // Do a leak check -- we can't really report report a useful error here, + // but it at least avoids an ICE when the error has to do with higher-ranked + // lifetimes. + self.leak_check(outer_universe, Some(snapshot))?; + + // Bail if we have ambiguity errors, which we can't report in a useful way. + let ambiguity_errors = ocx.select_all_or_error(); + if true_errors.is_empty() && !ambiguity_errors.is_empty() { + return Err(NoSolution); + } + // There should be at least one error reported. If not, we // will still delay a span bug in `report_fulfillment_errors`. Ok::<_, NoSolution>(( - self.err_ctxt().report_fulfillment_errors(errors), + self.err_ctxt().report_fulfillment_errors(true_errors), impl_trait_ref.args.type_at(1), element_ty, )) @@ -2988,16 +3131,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .ok() } - fn point_at_index_if_possible( - &self, - errors: &mut Vec>, - span: Span, - ) { + fn point_at_index(&self, errors: &mut Vec>, span: Span) { + let mut seen_preds = FxHashSet::default(); + // We re-sort here so that the outer most root obligations comes first, as we have the + // subsequent weird logic to identify *every* relevant obligation for proper deduplication + // of diagnostics. + errors.sort_by_key(|error| error.root_obligation.recursion_depth); for error in errors { - match error.obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) - if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => { + match ( + error.root_obligation.predicate.kind().skip_binder(), + error.obligation.predicate.kind().skip_binder(), + ) { + (ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)), _) + if self.tcx.lang_items().index_trait() == Some(predicate.trait_ref.def_id) => + { + seen_preds.insert(error.obligation.predicate.kind().skip_binder()); + } + (_, ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate))) + if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => + { + seen_preds.insert(error.obligation.predicate.kind().skip_binder()); } + (root, pred) if seen_preds.contains(&pred) || seen_preds.contains(&root) => {} _ => continue, } error.obligation.cause.span = span; @@ -3012,7 +3167,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { match self.resume_yield_tys { Some((resume_ty, yield_ty)) => { - self.check_expr_coercible_to_type(&value, yield_ty, None); + self.check_expr_coercible_to_type(value, yield_ty, None); resume_ty } @@ -3021,7 +3176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // information. Hence, we check the source of the yield expression here and check its // value's type against `()` (this check should always hold). None if src.is_await() => { - self.check_expr_coercible_to_type(&value, Ty::new_unit(self.tcx), None); + self.check_expr_coercible_to_type(value, Ty::new_unit(self.tcx), None); Ty::new_unit(self.tcx) } _ => { @@ -3115,20 +3270,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match container.kind() { ty::Adt(container_def, args) if container_def.is_enum() => { - let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id); + let block = self.tcx.local_def_id_to_hir_id(self.body_id); let (ident, _def_scope) = self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); - let Some((index, variant)) = container_def.variants() + if !self.tcx.features().offset_of_enum { + rustc_session::parse::feature_err( + &self.tcx.sess.parse_sess, + sym::offset_of_enum, + ident.span, + "using enums in offset_of is experimental", + ) + .emit(); + } + + let Some((index, variant)) = container_def + .variants() .iter_enumerated() - .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else { + .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) + else { let mut err = type_error_struct!( self.tcx().sess, ident.span, container, E0599, "no variant named `{ident}` found for enum `{container}`", - ); + ); err.span_label(field.span, "variant not found"); err.emit(); break; @@ -3140,7 +3307,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { container, E0795, "`{ident}` is an enum variant; expected field at end of `offset_of`", - ); + ); err.span_label(field.span, "enum variant"); err.emit(); break; @@ -3148,16 +3315,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (subident, sub_def_scope) = self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, block); - let Some((subindex, field)) = variant.fields + let Some((subindex, field)) = variant + .fields .iter_enumerated() - .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident) else { + .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident) + else { let mut err = type_error_struct!( self.tcx().sess, ident.span, container, E0609, "no field named `{subfield}` on enum variant `{container}::{ident}`", - ); + ); err.span_label(field.span, "this enum variant..."); err.span_label(subident.span, "...does not have this field"); err.emit(); @@ -3183,7 +3352,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } ty::Adt(container_def, args) => { - let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id); + let block = self.tcx.local_def_id_to_hir_id(self.body_id); let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 6be3ad6577bdb..c22b15231a155 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.walk_irrefutable_pat(¶m_place, param.pat); } - self.consume_expr(&body.value); + self.consume_expr(body.value); } fn tcx(&self) -> TyCtxt<'tcx> { @@ -237,10 +237,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.consume_exprs(exprs); } - hir::ExprKind::If(ref cond_expr, ref then_expr, ref opt_else_expr) => { + hir::ExprKind::If(cond_expr, then_expr, ref opt_else_expr) => { self.consume_expr(cond_expr); self.consume_expr(then_expr); - if let Some(ref else_expr) = *opt_else_expr { + if let Some(else_expr) = *opt_else_expr { self.consume_expr(else_expr); } } @@ -249,7 +249,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.walk_local(init, pat, None, |t| t.borrow_expr(init, ty::ImmBorrow)) } - hir::ExprKind::Match(ref discr, arms, _) => { + hir::ExprKind::Match(discr, arms, _) => { let discr_place = return_if_err!(self.mc.cat_expr(discr)); return_if_err!(self.maybe_read_scrutinee( discr, @@ -267,7 +267,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.consume_exprs(exprs); } - hir::ExprKind::AddrOf(_, m, ref base) => { + hir::ExprKind::AddrOf(_, m, base) => { // &base // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: @@ -379,7 +379,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // only the fn body we were given. } - hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr) => { self.consume_expr(expr); } } @@ -401,12 +401,17 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { mc.cat_pattern(discr_place.clone(), pat, |place, pat| { match &pat.kind { PatKind::Binding(.., opt_sub_pat) => { - // If the opt_sub_pat is None, than the binding does not count as + // If the opt_sub_pat is None, then the binding does not count as // a wildcard for the purpose of borrowing discr. if opt_sub_pat.is_none() { needs_to_be_read = true; } } + PatKind::Never => { + // A never pattern reads the value. + // FIXME(never_patterns): does this do what I expect? + needs_to_be_read = true; + } PatKind::Path(qpath) => { // A `Path` pattern is just a name like `Foo`. This is either a // named constant or else it refers to an ADT variant @@ -505,7 +510,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { )); self.walk_block(els) } - self.walk_irrefutable_pat(&expr_place, &pat); + self.walk_irrefutable_pat(&expr_place, pat); } /// Indicates that the value of `blk` will be consumed, meaning either copied or moved @@ -517,7 +522,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.walk_stmt(stmt); } - if let Some(ref tail_expr) = blk.expr { + if let Some(tail_expr) = blk.expr { self.consume_expr(tail_expr); } } @@ -533,7 +538,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // The struct path probably didn't resolve if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() { - self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field"); + self.tcx().sess.span_delayed_bug(field.span, "couldn't resolve index for field"); } } @@ -665,8 +670,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.walk_pat(discr_place, arm.pat, arm.guard.is_some()); match arm.guard { - Some(hir::Guard::If(ref e)) => self.consume_expr(e), - Some(hir::Guard::IfLet(ref l)) => { + Some(hir::Guard::If(e)) => self.consume_expr(e), + Some(hir::Guard::IfLet(l)) => { self.walk_local(l.init, l.pat, None, |t| t.borrow_expr(l.init, ty::ImmBorrow)) } None => {} @@ -848,7 +853,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // be a local variable PlaceBase::Local(*var_hir_id) }; - let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id); + let closure_hir_id = tcx.local_def_id_to_hir_id(closure_def_id); let place_with_id = PlaceWithHirId::new( capture_info .path_expr_id diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b5a07f0d3e9ec..1f2bd92a15c0d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -159,7 +159,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] - pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { + pub fn write_method_call_and_enforce_effects( + &self, + hir_id: hir::HirId, + span: Span, + method: MethodCallee<'tcx>, + ) { + self.enforce_context_effects(span, method.def_id, method.args); self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_args(hir_id, method.args); } @@ -271,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: currently we never try to compose autoderefs // and ReifyFnPointer/UnsafeFnPointer, but we could. _ => { - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( expr.span, format!( "while adjusting {:?}, can't compose {:?} and {:?}", @@ -505,7 +511,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) { let scope_tree = self.tcx.region_scope_tree(def_id); - let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, &scope_tree, def_id) }; + let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) }; let mut typeck_results = self.inh.typeck_results.borrow_mut(); typeck_results.rvalue_scopes = rvalue_scopes; } @@ -651,20 +657,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::NormalizesTo(..) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) - // N.B., this predicate is created by breaking down a - // `ClosureType: FnFoo()` predicate, where - // `ClosureType` represents some `Closure`. It can't - // possibly be referring to the current closure, - // because we haven't produced the `Closure` for - // this closure yet; this is exactly why the other - // code is looking for a self type of an unresolved - // inference variable. - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Ambiguous - => None, + | ty::PredicateKind::Ambiguous => None, }, ) } @@ -754,7 +751,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lang_item: hir::LangItem, span: Span, hir_id: hir::HirId, - expr_hir_id: Option, ) -> (Res, Ty<'tcx>) { let def_id = self.tcx.require_lang_item(lang_item, Some(span)); let def_kind = self.tcx.def_kind(def_id); @@ -771,7 +767,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let code = match lang_item { hir::LangItem::IntoFutureIntoFuture => { - Some(ObligationCauseCode::AwaitableExpr(expr_hir_id)) + if let hir::Node::Expr(into_future_call) = self.tcx.hir().get_parent(hir_id) + && let hir::ExprKind::Call(_, [arg0]) = &into_future_call.kind + { + Some(ObligationCauseCode::AwaitableExpr(arg0.hir_id)) + } else { + None + } } hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => { Some(ObligationCauseCode::ForLoopIterator) @@ -797,13 +799,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, + args: Option<&'tcx [hir::Expr<'tcx>]>, ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { debug!( "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", qpath, hir_id, span ); let (ty, qself, item_segment) = match *qpath { - QPath::Resolved(ref opt_qself, ref path) => { + QPath::Resolved(ref opt_qself, path) => { return ( path.res, opt_qself.as_ref().map(|qself| self.to_ty(qself)), @@ -855,7 +858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let guar = self .tcx .sess - .delay_span_bug(span, "method resolution should've emitted an error"); + .span_delayed_bug(span, "method resolution should've emitted an error"); let result = match error { method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), _ => Err(guar), @@ -898,7 +901,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, SelfSource::QPath(qself), error, - None, + args, Expectation::NoExpectation, trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021 ) { @@ -1185,7 +1188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx, span, def_id, - &generics, + generics, seg, IsMethodCall::No, ); @@ -1277,7 +1280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // going to infer the arguments for better error messages. if !self.infer_args_for_err.contains(&index) { // Check whether the user has provided generic arguments. - if let Some(ref data) = self.segments[index].args { + if let Some(data) = self.segments[index].args { return (Some(data), self.segments[index].infer_args); } } @@ -1405,7 +1408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Normalize only after registering type annotations. let args = self.normalize(span, args_raw); - self.add_required_obligations_for_hir(span, def_id, &args, hir_id); + self.add_required_obligations_for_hir(span, def_id, args, hir_id); // Substitute the values for the type parameters into the type of // the referenced item. @@ -1429,7 +1432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( span, format!( "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?", @@ -1472,7 +1475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let param_env = self.param_env; - let bounds = self.instantiate_bounds(span, def_id, &args); + let bounds = self.instantiate_bounds(span, def_id, args); for obligation in traits::predicates_for_generics( |idx, predicate_span| { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index facbeb8badfac..e3aca11fd03aa 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -495,7 +495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Whether it succeeded or failed, it likely made some amount of progress. // In the very worst case, it's just the same `expr` we originally passed in. let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code( - &error.obligation.cause.code(), + error.obligation.cause.code(), expr, ) { Ok(expr) => expr, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs index 7aadb95d9393e..566d407d23c12 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs @@ -4,11 +4,13 @@ use rustc_middle::ty::error::TypeError; use std::cmp; rustc_index::newtype_index! { + #[orderable] #[debug_format = "ExpectedIdx({})"] pub(crate) struct ExpectedIdx {} } rustc_index::newtype_index! { + #[orderable] #[debug_format = "ProvidedIdx({})"] pub(crate) struct ProvidedIdx {} } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 33dfa16a651fb..509596c1e90f8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -282,12 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: provided_arg.span, }); } else { - self.enforce_context_effects( - provided_arg.hir_id, - provided_arg.span, - def_id, - args, - ) + self.enforce_context_effects(provided_arg.span, def_id, args) } } } else { @@ -397,7 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for arg in provided_args.iter().skip(minimum_input_count) { // Make sure we've checked this expr at least once. - let arg_ty = self.check_expr(&arg); + let arg_ty = self.check_expr(arg); // If the function is c-style variadic, we skipped a bunch of arguments // so we need to check those, and write out the types @@ -522,7 +517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; // FIXME: taint after emitting errors and pass through an `ErrorGuaranteed` self.set_tainted_by_errors( - tcx.sess.delay_span_bug(call_span, "no errors reported for args"), + tcx.sess.span_delayed_bug(call_span, "no errors reported for args"), ); // Get the argument span in the context of the call span so that @@ -796,7 +791,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err); self.emit_coerce_suggestions( &mut err, - &provided_args[*provided_idx], + provided_args[*provided_idx], provided_ty, Expectation::rvalue_hint(self, expected_ty) .only_has_type(self) @@ -925,7 +920,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.emit_coerce_suggestions( &mut err, - &provided_args[provided_idx], + provided_args[provided_idx], provided_ty, Expectation::rvalue_hint(self, expected_ty) .only_has_type(self) @@ -1366,7 +1361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let variant = match def { Res::Err => { let guar = - self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted"); + self.tcx.sess.span_delayed_bug(path_span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(guar); return Err(guar); } @@ -1469,7 +1464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the initializer. if let Some(ref init) = decl.init { - let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init); + let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init); self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty); } @@ -1483,7 +1478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Type check the pattern. Override if necessary to avoid knock-on errors. - self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin)); + self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin)); let pat_ty = self.node_ty(decl.pat.hir_id); self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty); @@ -1525,13 +1520,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::StmtKind::Item(_) => {} hir::StmtKind::Expr(ref expr) => { // Check with expected type of `()`. - self.check_expr_has_type_or_error(&expr, Ty::new_unit(self.tcx), |err| { + self.check_expr_has_type_or_error(expr, Ty::new_unit(self.tcx), |err| { if expr.can_have_side_effects() { self.suggest_semicolon_at_end(expr.span, err); } }); } - hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Semi(expr) => { self.check_expr(expr); } } @@ -1820,12 +1815,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir_id: hir::HirId, ) -> (Res, RawTy<'tcx>) { match *qpath { - QPath::Resolved(ref maybe_qself, ref path) => { + QPath::Resolved(ref maybe_qself, path) => { let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw); let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true); (path.res, self.handle_raw_ty(path_span, ty)) } - QPath::TypeRelative(ref qself, ref segment) => { + QPath::TypeRelative(qself, segment) => { let ty = self.to_ty(qself); let result = self @@ -1842,8 +1837,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) } - QPath::LangItem(lang_item, span, id) => { - let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id); + QPath::LangItem(lang_item, span) => { + let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id); (res, self.handle_raw_ty(path_span, ty)) } } @@ -1864,35 +1859,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let ExprBindingObligation(_, _, hir_id, ..) = code && !fn_sig.output().is_unit() { - let mut block_num = 0; - let mut found_semi = false; - for (_, node) in self.tcx.hir().parent_iter(hir_id) { - match node { - hir::Node::Stmt(stmt) => if let hir::StmtKind::Semi(ref expr) = stmt.kind { + let mut block_num = 0; + let mut found_semi = false; + for (_, node) in self.tcx.hir().parent_iter(hir_id) { + match node { + hir::Node::Stmt(stmt) => { + if let hir::StmtKind::Semi(expr) = stmt.kind { let expr_ty = self.typeck_results.borrow().expr_ty(expr); let return_ty = fn_sig.output(); - if !matches!(expr.kind, hir::ExprKind::Ret(..)) && - self.can_coerce(expr_ty, return_ty) { + if !matches!(expr.kind, hir::ExprKind::Ret(..)) + && self.can_coerce(expr_ty, return_ty) + { found_semi = true; } - }, - hir::Node::Block(_block) => if found_semi { + } + } + hir::Node::Block(_block) => { + if found_semi { block_num += 1; } - hir::Node::Item(item) => if let hir::ItemKind::Fn(..) = item.kind { + } + hir::Node::Item(item) => { + if let hir::ItemKind::Fn(..) = item.kind { break; } - _ => {} } + _ => {} } - if block_num > 1 && found_semi { - diag.span_suggestion_verbose( - span.shrink_to_lo(), - "you might have meant to return this to infer its type parameters", - "return ", - Applicability::MaybeIncorrect, - ); - } + } + if block_num > 1 && found_semi { + diag.span_suggestion_verbose( + span.shrink_to_lo(), + "you might have meant to return this to infer its type parameters", + "return ", + Applicability::MaybeIncorrect, + ); + } } diag.emit(); } @@ -2031,7 +2033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.param_env, trait_ref, ); - match SelectionContext::new(&self).select(&obligation) { + match SelectionContext::new(self).select(&obligation) { Ok(Some(traits::ImplSource::UserDefined(impl_source))) => { Some(impl_source.impl_def_id) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index e93d180fc139e..072df1343ce65 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn sess(&self) -> &Session { - &self.tcx.sess + self.tcx.sess } /// Creates an `TypeErrCtxt` with a reference to the in-progress @@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { type Target = Inherited<'tcx>; fn deref(&self) -> &Self::Target { - &self.inh + self.inh } } @@ -238,7 +238,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { fn re_infer(&self, def: Option<&ty::GenericParamDef>, span: Span) -> Option> { let v = match def { - Some(def) => infer::EarlyBoundRegion(span, def.name), + Some(def) => infer::RegionParameterDefinition(span, def.name), None => infer::MiscVariable(span), }; Some(self.next_region_var(v)) @@ -289,7 +289,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let trait_ref = self.instantiate_binder_with_fresh_vars( span, - infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id), + infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id), poly_trait_ref, ); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index c43d4932fb9f2..2c9942caab22f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results .borrow() .liberated_fn_sigs() - .get(self.tcx.hir().local_def_id_to_hir_id(self.body_id)) + .get(self.tcx.local_def_id_to_hir_id(self.body_id)) .copied() } @@ -72,23 +72,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { blk_id: hir::HirId, ) -> bool { let expr = expr.peel_drop_temps(); - self.suggest_missing_semicolon(err, expr, expected, false); let mut pointing_at_return_type = false; if let hir::ExprKind::Break(..) = expr.kind { // `break` type mismatches provide better context for tail `loop` expressions. return false; } if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { - pointing_at_return_type = self.suggest_missing_return_type( - err, - &fn_decl, - expected, - found, - can_suggest, - fn_id, - ); + pointing_at_return_type = + self.suggest_missing_return_type(err, fn_decl, expected, found, can_suggest, fn_id); self.suggest_missing_break_or_return_expr( - err, expr, &fn_decl, expected, found, blk_id, fn_id, + err, expr, fn_decl, expected, found, blk_id, fn_id, ); } pointing_at_return_type @@ -449,12 +442,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected, ) }); + + let prefix_wrap = |sugg: &str| { + if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { + format!(": {}{}", name, sugg) + } else { + sugg.to_string() + } + }; + // FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`, // but those checks need to be a bit more delicate and the benefit is diminishing. if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref { + let sugg = prefix_wrap(".as_ref()"); err.subdiagnostic(errors::SuggestConvertViaMethod { span: expr.span.shrink_to_hi(), - sugg: ".as_ref()", + sugg, expected, found, borrow_removal_span, @@ -465,9 +468,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self.can_eq(self.param_env, deref_ty, peeled) && error_tys_equate_as_ref { + let sugg = prefix_wrap(".as_deref()"); err.subdiagnostic(errors::SuggestConvertViaMethod { span: expr.span.shrink_to_hi(), - sugg: ".as_deref()", + sugg, expected, found, borrow_removal_span, @@ -481,10 +485,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.can_eq(self.param_env, found, expected) }) { + let sugg = prefix_wrap(".map(|x| x.as_str())"); err.span_suggestion_verbose( expr.span.shrink_to_hi(), fluent::hir_typeck_convert_to_str, - ".map(|x| x.as_str())", + sugg, Applicability::MachineApplicable, ); return true; @@ -615,7 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } let pin_did = self.tcx.lang_items().pin_type(); - // This guards the `unwrap` and `mk_box` below. + // This guards the `new_box` below. if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() { return false; } @@ -635,12 +640,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.help("use `Box::pin`"); } _ => { + let prefix = if let Some(name) = + self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) + { + format!("{}: ", name) + } else { + String::new() + }; + let suggestion = vec![ + (expr.span.shrink_to_lo(), format!("{prefix}Box::pin(")), + (expr.span.shrink_to_hi(), ")".to_string()), + ]; err.multipart_suggestion( "you need to pin and box this expression", - vec![ - (expr.span.shrink_to_lo(), "Box::pin(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ], + suggestion, Applicability::MaybeIncorrect, ); } @@ -846,7 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into()); let ty = Binder::bind_with_vars(ty, bound_vars); let ty = self.normalize(hir_ty.span, ty); - let ty = self.tcx.erase_late_bound_regions(ty); + let ty = self.tcx.instantiate_bound_regions_with_erased(ty); if self.can_coerce(expected, ty) { err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, @@ -1023,7 +1036,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = self.astconv().ast_ty_to_ty(ty); let bound_vars = self.tcx.late_bound_vars(fn_id); - let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); + let ty = self + .tcx + .instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars)); let ty = match self.tcx.asyncness(fn_id.owner) { ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| { span_bug!(fn_decl.output.span(), "failed to get output type of async function") @@ -1219,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span = parent_callsite; } - let sugg = if expr.precedence().order() >= PREC_POSTFIX { + let mut sugg = if expr.precedence().order() >= PREC_POSTFIX { vec![(span.shrink_to_hi(), ".into()".to_owned())] } else { vec![ @@ -1227,6 +1242,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (span.shrink_to_hi(), ").into()".to_owned()), ] }; + if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { + sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name))); + } diag.multipart_suggestion( format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"), sugg, @@ -1601,6 +1619,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ); } else { + if let Some(errors) = + self.could_impl_trait(clone_trait_did, expected_ty, self.param_env) + { + match &errors[..] { + [] => {} + [error] => { + diag.help(format!( + "`Clone` is not implemented because the trait bound `{}` is \ + not satisfied", + error.obligation.predicate, + )); + } + [errors @ .., last] => { + diag.help(format!( + "`Clone` is not implemented because the following trait bounds \ + could not be satisfied: {} and `{}`", + errors + .iter() + .map(|e| format!("`{}`", e.obligation.predicate)) + .collect::>() + .join(", "), + last.obligation.predicate, + )); + } + } + for error in errors { + if let traits::FulfillmentErrorCode::CodeSelectionError( + traits::SelectionError::Unimplemented, + ) = error.code + && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = + error.obligation.predicate.kind().skip_binder() + { + self.infcx.err_ctxt().suggest_derive( + &error.obligation, + diag, + error.obligation.predicate.kind().rebind(pred), + ); + } + } + } self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]); } } @@ -1816,6 +1874,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ".expect(\"REASON\")", ) }; + + let sugg = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { + Some(ident) => format!(": {ident}{sugg}"), + None => sugg.to_string(), + }; + err.span_suggestion_verbose( expr.span.shrink_to_hi(), msg, @@ -2137,7 +2201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// opt.map(|param| { takes_ref(param) }); /// ``` fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Vec<(Span, String)>, &'static str)> { - let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind else { + let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind else { return None; }; @@ -2293,16 +2357,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if self.can_coerce(ref_ty, expected) { let mut sugg_sp = sp; - if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind { + if let hir::ExprKind::MethodCall(segment, receiver, args, _) = expr.kind { let clone_trait = self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span)); if args.is_empty() - && self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map( - |did| { + && self + .typeck_results + .borrow() + .type_dependent_def_id(expr.hir_id) + .is_some_and(|did| { let ai = self.tcx.associated_item(did); ai.trait_container(self.tcx) == Some(clone_trait) - }, - ) == Some(true) + }) && segment.ident.name == sym::clone { // If this expression had a clone call when suggesting borrowing @@ -2311,7 +2377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if let hir::ExprKind::Unary(hir::UnOp::Deref, ref inner) = expr.kind + if let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind && let Some(1) = self.deref_steps(expected, checked_ty) { // We have `*&T`, check if what was expected was `&T`. @@ -2326,14 +2392,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } - let needs_parens = match expr.kind { - // parenthesize if needed (Issue #46756) - hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, - // parenthesize borrows of range literals (Issue #54505) - _ if is_range_literal(expr) => true, - _ => false, - }; - if let Some((sugg, msg)) = self.can_use_as_ref(expr) { return Some(( sugg, @@ -2361,18 +2419,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let sugg = mutability.ref_prefix_str(); - let (sugg, verbose) = if needs_parens { - ( - vec![ - (sp.shrink_to_lo(), format!("{prefix}{sugg}(")), - (sp.shrink_to_hi(), ")".to_string()), - ], - false, - ) - } else { - (vec![(sp.shrink_to_lo(), format!("{prefix}{sugg}"))], true) + let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| { + let needs_parens = match expr.kind { + // parenthesize if needed (Issue #46756) + hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, + // parenthesize borrows of range literals (Issue #54505) + _ if is_range_literal(expr) => true, + _ => false, + }; + + if needs_parens { + ( + vec![ + (span.shrink_to_lo(), format!("{prefix}{sugg}(")), + (span.shrink_to_hi(), ")".to_string()), + ], + false, + ) + } else { + (vec![(span.shrink_to_lo(), format!("{prefix}{sugg}"))], true) + } }; + + // Suggest dereferencing the lhs for expressions such as `&T == T` + if let Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Binary(_, lhs, ..), + .. + })) = self.tcx.hir().find_parent(expr.hir_id) + && let &ty::Ref(..) = self.check_expr(lhs).kind() + { + let (sugg, verbose) = make_sugg(lhs, lhs.span, "*"); + + return Some(( + sugg, + "consider dereferencing the borrow".to_string(), + Applicability::MachineApplicable, + verbose, + false, + )); + } + + let sugg = mutability.ref_prefix_str(); + let (sugg, verbose) = make_sugg(expr, sp, sugg); return Some(( sugg, format!("consider {}borrowing here", mutability.mutably_str()), @@ -2382,11 +2470,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } } - ( - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr), - _, - &ty::Ref(_, checked, _), - ) if self.can_sub(self.param_env, checked, expected) => { + (hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr), _, &ty::Ref(_, checked, _)) + if self.can_sub(self.param_env, checked, expected) => + { let make_sugg = |start: Span, end: BytePos| { // skip `(` for tuples such as `(c) = (&123)`. // make sure we won't suggest like `(c) = 123)` which is incorrect. diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 0ad2c1d928438..0cca779b1560e 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -93,7 +93,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { fn declare(&mut self, decl: Declaration<'tcx>) { let local_ty = match decl.ty { Some(ref ty) => { - let o_ty = self.fcx.to_ty(&ty); + let o_ty = self.fcx.to_ty(ty); let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw)); diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index efd0b8577cf9a..281074a851926 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -75,7 +75,7 @@ impl<'tcx> Deref for Inherited<'tcx> { impl<'tcx> Inherited<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { - let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner; + let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; let infcx = tcx .infer_ctxt() diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 5d516eaf507e3..a3c77af62a7c7 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let to = normalize(to); trace!(?from, ?to); if from.has_non_region_infer() || to.has_non_region_infer() { - tcx.sess.delay_span_bug(span, "argument to transmute has inference variables"); + tcx.sess.span_delayed_bug(span, "argument to transmute has inference variables"); return; } // Transmutes that are only changing lifetimes are always ok. diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 46dcc455558be..29e4fd9239a31 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -52,11 +52,7 @@ use crate::expectation::Expectation; use crate::fn_ctxt::RawTy; use crate::gather_locals::GatherLocalsVisitor; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{ - struct_span_err, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan, - SubdiagnosticMessage, -}; -use rustc_fluent_macro::fluent_messages; +use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -71,7 +67,7 @@ use rustc_session::config; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } #[macro_export] macro_rules! type_error_struct { @@ -150,7 +146,7 @@ fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tc /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors. fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { let fallback = move || { - let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id)); + let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used") }; typeck_with_fallback(tcx, def_id, fallback) @@ -169,7 +165,7 @@ fn typeck_with_fallback<'tcx>( return tcx.typeck(typeck_root_def_id); } - let id = tcx.hir().local_def_id_to_hir_id(def_id); + let id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir().get(id); let span = tcx.hir().span(id); @@ -243,7 +239,7 @@ fn typeck_with_fallback<'tcx>( // Gather locals in statics (because of block expressions). GatherLocalsVisitor::new(&fcx).visit_body(body); - fcx.check_expr_coercible_to_type(&body.value, expected_type, None); + fcx.check_expr_coercible_to_type(body.value, expected_type, None); fcx.write_ty(id, expected_type); }; @@ -424,27 +420,27 @@ fn fatally_break_rust(tcx: TyCtxt<'_>) { MultiSpan::new(), "It looks like you're trying to break rust; would you like some ICE?", ); - handler.note_without_error("the compiler expectedly panicked. this is a feature."); - handler.note_without_error( + handler.note("the compiler expectedly panicked. this is a feature."); + handler.note( "we would appreciate a joke overview: \ https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675", ); - handler.note_without_error(format!( - "rustc {} running on {}", - tcx.sess.cfg_version, - config::host_triple(), - )); + handler.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),)); if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { - handler.note_without_error(format!("compiler flags: {}", flags.join(" "))); + handler.note(format!("compiler flags: {}", flags.join(" "))); if excluded_cargo_defaults { - handler.note_without_error("some of the compiler flags provided by cargo are hidden"); + handler.note("some of the compiler flags provided by cargo are hidden"); } } } +/// `expected` here is the expected number of explicit generic arguments on the trait. fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool { let generics = tcx.generics_of(trait_did); - generics.count() == expected + if generics.has_self { 1 } else { 0 } + generics.count() + == expected + + if generics.has_self { 1 } else { 0 } + + if generics.host_effect_index.is_some() { 1 } else { 0 } } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 337d12b2d5111..ebb15e072aaf5 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -66,25 +66,18 @@ use rustc_trait_selection::infer::InferCtxtExt; pub(crate) trait HirNode { fn hir_id(&self) -> hir::HirId; - fn span(&self) -> Span; } impl HirNode for hir::Expr<'_> { fn hir_id(&self) -> hir::HirId { self.hir_id } - fn span(&self) -> Span { - self.span - } } impl HirNode for hir::Pat<'_> { fn hir_id(&self) -> hir::HirId { self.hir_id } - fn span(&self) -> Span { - self.span - } } #[derive(Clone)] @@ -304,7 +297,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ) -> McResult> { let expr_ty = self.expr_ty(expr)?; match expr.kind { - hir::ExprKind::Unary(hir::UnOp::Deref, ref e_base) => { + hir::ExprKind::Unary(hir::UnOp::Deref, e_base) => { if self.typeck_results.is_method_call(expr) { self.cat_overloaded_place(expr, e_base) } else { @@ -313,7 +306,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } - hir::ExprKind::Field(ref base, _) => { + hir::ExprKind::Field(base, _) => { let base = self.cat_expr(base)?; debug!(?base); @@ -332,7 +325,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { )) } - hir::ExprKind::Index(ref base, _, _) => { + hir::ExprKind::Index(base, _, _) => { if self.typeck_results.is_method_call(expr) { // If this is an index implemented by a method call, then it // will include an implicit deref of the result. @@ -351,7 +344,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_res(expr.hir_id, expr.span, expr_ty, res) } - hir::ExprKind::Type(ref e, _) => self.cat_expr(e), + hir::ExprKind::Type(e, _) => self.cat_expr(e), hir::ExprKind::AddrOf(..) | hir::ExprKind::Call(..) @@ -547,7 +540,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let ty::Adt(adt_def, _) = ty.kind() else { self.tcx() .sess - .delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT"); + .span_delayed_bug(span, "struct or tuple struct pattern not applied to an ADT"); return Err(()); }; @@ -582,7 +575,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { _ => { self.tcx() .sess - .delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT"); + .span_delayed_bug(span, "struct or tuple struct pattern not applied to an ADT"); Err(()) } } @@ -595,7 +588,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { match ty.kind() { ty::Tuple(args) => Ok(args.len()), _ => { - self.tcx().sess.delay_span_bug(span, "tuple pattern not applied to a tuple"); + self.tcx().sess.span_delayed_bug(span, "tuple pattern not applied to a tuple"); Err(()) } } @@ -728,11 +721,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } - PatKind::Binding(.., Some(ref subpat)) => { + PatKind::Binding(.., Some(subpat)) => { self.cat_pattern_(place_with_id, subpat, op)?; } - PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => { + PatKind::Box(subpat) | PatKind::Ref(subpat, _) => { // box p1, &p1, &mut p1. we can ignore the mutability of // PatKind::Ref since that information is already contained // in the type. @@ -754,7 +747,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { for before_pat in before { self.cat_pattern_(elt_place.clone(), before_pat, op)?; } - if let Some(ref slice_pat) = *slice { + if let Some(slice_pat) = *slice { let slice_pat_ty = self.pat_ty_adjusted(slice_pat)?; let slice_place = self.cat_projection( pat, @@ -773,6 +766,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | PatKind::Binding(.., None) | PatKind::Lit(..) | PatKind::Range(..) + | PatKind::Never | PatKind::Wild => { // always ok } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 7c73f6a89cdb2..e7af7da205c61 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -93,16 +93,16 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { segment: &hir::PathSegment<'_>, ) -> ConfirmResult<'tcx> { // Adjust the self expression the user provided and obtain the adjusted type. - let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick); + let self_ty = self.adjust_self_ty(unadjusted_self_ty, pick); // Create substitutions for the method's type parameters. - let rcvr_args = self.fresh_receiver_args(self_ty, &pick); - let all_args = self.instantiate_method_args(&pick, segment, rcvr_args); + let rcvr_args = self.fresh_receiver_args(self_ty, pick); + let all_args = self.instantiate_method_args(pick, segment, rcvr_args); debug!("rcvr_args={rcvr_args:?}, all_args={all_args:?}"); // Create the final signature for the method, replacing late-bound regions. - let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_args); + let (method_sig, method_predicates) = self.instantiate_method_sig(pick, all_args); // If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that // something which derefs to `Self` actually implements the trait and the caller @@ -129,14 +129,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}", self_ty, method_sig_rcvr, method_sig, method_predicates ); - self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_args); + self.unify_receivers(self_ty, method_sig_rcvr, pick, all_args); let (method_sig, method_predicates) = self.normalize(self.span, (method_sig, method_predicates)); let method_sig = ty::Binder::dummy(method_sig); // Make sure nobody calls `drop()` explicitly. - self.enforce_illegal_method_limitations(&pick); + self.enforce_illegal_method_limitations(pick); // Add any trait/regions obligations specified on the method's type parameters. // We won't add these if we encountered an illegal sized bound, so that we can use diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 86a0e95de1dab..f820835acef96 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -7,7 +7,7 @@ mod prelude2021; pub mod probe; mod suggest; -pub use self::suggest::{MethodCallComponents, SelfSource}; +pub use self::suggest::SelfSource; pub use self::MethodError::*; use crate::errors::OpMethodGenericParams; @@ -385,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type parameters or early-bound regions. let tcx = self.tcx; let Some(method_item) = self.associated_value(trait_def_id, m_name) else { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( obligation.cause.span, "operator trait does not have corresponding operator method", ); @@ -393,7 +393,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if method_item.kind != ty::AssocKind::Fn { - self.tcx.sess.delay_span_bug(tcx.def_span(method_item.def_id), "not a method"); + self.tcx.sess.span_delayed_bug(tcx.def_span(method_item.def_id), "not a method"); return None; } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 74f469cb39cbf..4243bce377fb4 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -619,7 +619,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) { let is_accessible = if let Some(name) = self.method_name { let item = candidate.item; - let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id); + let hir_id = self.tcx.local_def_id_to_hir_id(self.body_id); let def_scope = self.tcx.adjust_ident_and_get_scope(name, item.container_id(self.tcx), hir_id).1; item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx) @@ -801,15 +801,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // a `&self` method will wind up with an argument type like `&dyn Trait`. let trait_ref = principal.with_self_ty(self.tcx, self_ty); self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| { - if new_trait_ref.has_non_region_late_bound() { - this.tcx.sess.delay_span_bug( + if new_trait_ref.has_non_region_bound_vars() { + this.tcx.sess.span_delayed_bug( this.span, "tried to select method from HRTB with non-lifetime bound vars", ); return; } - let new_trait_ref = this.erase_late_bound_regions(new_trait_ref); + let new_trait_ref = this.instantiate_bound_regions_with_erased(new_trait_ref); let (xform_self_ty, xform_ret_ty) = this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args); @@ -853,7 +853,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { let trait_ref = this.instantiate_binder_with_fresh_vars( this.span, - infer::LateBoundRegionConversionTime::FnCall, + infer::BoundRegionConversionTime::FnCall, poly_trait_ref, ); @@ -971,7 +971,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { let new_trait_ref = self.instantiate_binder_with_fresh_vars( self.span, - infer::LateBoundRegionConversionTime::FnCall, + infer::BoundRegionConversionTime::FnCall, bound_trait_ref, ); @@ -1135,7 +1135,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .fcx .probe_instantiate_query_response( self.span, - &self.orig_steps_var_values, + self.orig_steps_var_values, &step.self_ty, ) .unwrap_or_else(|_| { @@ -1509,7 +1509,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // match as well (or at least may match, sometimes we // don't have enough information to fully evaluate). match probe.kind { - InherentImplCandidate(ref args, ref ref_obligations) => { + InherentImplCandidate(args, ref ref_obligations) => { // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`, // see the reasons mentioned in the comments in `assemble_inherent_impl_probe` // for why this is necessary @@ -1799,9 +1799,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .iter() .find(|cand| self.matches_by_doc_alias(cand.def_id)) .map(|cand| cand.name) - }) - .unwrap(); - Ok(applicable_close_candidates.into_iter().find(|method| method.name == best_name)) + }); + Ok(best_name.and_then(|best_name| { + applicable_close_candidates.into_iter().find(|method| method.name == best_name) + })) } }) } @@ -1861,7 +1862,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // method yet. So create fresh variables here for those too, // if there are any. let generics = self.tcx.generics_of(method); - assert_eq!(args.len(), generics.parent_count as usize); + assert_eq!(args.len(), generics.parent_count); let xform_fn_sig = if generics.params.is_empty() { fn_sig.instantiate(self.tcx, args) @@ -1885,7 +1886,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn_sig.instantiate(self.tcx, args) }; - self.erase_late_bound_regions(xform_fn_sig) + self.instantiate_bound_regions_with_erased(xform_fn_sig) } /// Gets the type of an impl and generate substitutions with inference vars. @@ -1897,7 +1898,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } /// Replaces late-bound-regions bound by `value` with `'static` using - /// `ty::erase_late_bound_regions`. + /// `ty::instantiate_bound_regions_with_erased`. /// /// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of /// method matching. It is reasonable during the probe phase because we don't consider region @@ -1914,11 +1915,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// region got replaced with the same variable, which requires a bit more coordination /// and/or tracking the substitution and /// so forth. - fn erase_late_bound_regions(&self, value: ty::Binder<'tcx, T>) -> T + fn instantiate_bound_regions_with_erased(&self, value: ty::Binder<'tcx, T>) -> T where T: TypeFoldable>, { - self.tcx.erase_late_bound_regions(value) + self.tcx.instantiate_bound_regions_with_erased(value) } /// Determine if the given associated item type is relevant in the current context. @@ -1939,7 +1940,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let Some(local_def_id) = def_id.as_local() else { return false; }; - let hir_id = self.fcx.tcx.hir().local_def_id_to_hir_id(local_def_id); + let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id); let attrs = self.fcx.tcx.hir().attrs(hir_id); for attr in attrs { let sym::doc = attr.name_or_empty() else { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 12cc5ed2f1a55..143454c71e1c4 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1,6 +1,8 @@ //! Give useful errors and suggestions to users when an item can't be //! found or is otherwise invalid. +// ignore-tidy-filelength + use crate::errors; use crate::errors::{CandidateTraitNote, NoAssociatedItem}; use crate::Expectation; @@ -34,7 +36,7 @@ use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::DefIdSet; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; -use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span}; +use rustc_span::{edit_distance, ExpnKind, FileName, MacroKind, Span}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote; use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _; @@ -50,15 +52,6 @@ use rustc_hir::intravisit::Visitor; use std::cmp::{self, Ordering}; use std::iter; -/// After identifying that `full_expr` is a method call, we use this type to keep the expression's -/// components readily available to us to point at the right place in diagnostics. -#[derive(Debug, Clone, Copy)] -pub struct MethodCallComponents<'tcx> { - pub receiver: &'tcx hir::Expr<'tcx>, - pub args: &'tcx [hir::Expr<'tcx>], - pub full_expr: &'tcx hir::Expr<'tcx>, -} - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { let tcx = self.tcx; @@ -124,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: Ident, source: SelfSource<'tcx>, error: MethodError<'tcx>, - args: Option>, + args: Option<&'tcx [hir::Expr<'tcx>]>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> Option> { @@ -167,6 +160,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_candidates_on_method_error( rcvr_ty, item_name, + source, args, span, &mut err, @@ -266,23 +260,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn suggest_missing_writer( &self, rcvr_ty: Ty<'tcx>, - args: MethodCallComponents<'tcx>, + rcvr_expr: &hir::Expr<'tcx>, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty); let mut err = struct_span_err!( self.tcx.sess, - args.receiver.span, + rcvr_expr.span, E0599, "cannot write into `{}`", ty_str ); err.span_note( - args.receiver.span, + rcvr_expr.span, "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method", ); - if let ExprKind::Lit(_) = args.receiver.kind { + if let ExprKind::Lit(_) = rcvr_expr.kind { err.span_help( - args.receiver.span.shrink_to_lo(), + rcvr_expr.span.shrink_to_lo(), "a writer is needed before this format string", ); }; @@ -296,7 +290,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, item_name: Ident, source: SelfSource<'tcx>, - args: Option>, + args: Option<&'tcx [hir::Expr<'tcx>]>, sugg_span: Span, no_match_data: &mut NoMatchData<'tcx>, expected: Expectation<'tcx>, @@ -377,8 +371,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.is_diagnostic_item(sym::write_macro, def_id) || tcx.is_diagnostic_item(sym::writeln_macro, def_id) }) && item_name.name == Symbol::intern("write_fmt"); - let mut err = if is_write && let Some(args) = args { - self.suggest_missing_writer(rcvr_ty, args) + let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source { + self.suggest_missing_writer(rcvr_ty, rcvr_expr) } else { tcx.sess.create_err(NoAssociatedItem { span, @@ -409,6 +403,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.downgrade_to_delayed_bug(); } + if matches!(source, SelfSource::QPath(_)) && args.is_some() { + self.find_builder_fn(&mut err, rcvr_ty); + } + if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll { err.help(format!( "method `poll` found on `Pin<&mut {ty_str}>`, \ @@ -483,11 +481,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); probe.is_ok() }); - self.note_internal_mutation_in_method( &mut err, rcvr_expr, - expected.to_option(&self), + expected.to_option(self), rcvr_ty, ); } @@ -512,7 +509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if static_candidates.len() == 1 { self.suggest_associated_call_syntax( &mut err, - &static_candidates, + static_candidates, rcvr_ty, source, item_name, @@ -522,6 +519,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_candidates_on_method_error( rcvr_ty, item_name, + source, args, span, &mut err, @@ -532,6 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_candidates_on_method_error( rcvr_ty, item_name, + source, args, span, &mut err, @@ -814,7 +813,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: item_span, .. })) => { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( *item_span, "auto trait is invoked with no method error, but no error reported?", ); @@ -970,12 +969,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the following trait bounds were not satisfied:\n{bound_list}" )); } - self.suggest_derive(&mut err, &unsatisfied_predicates); + self.suggest_derive(&mut err, unsatisfied_predicates); unsatisfied_bounds = true; } } else if let ty::Adt(def, targs) = rcvr_ty.kind() - && let Some(args) = args + && let SelfSource::MethodCall(rcvr_expr) = source { // This is useful for methods on arbitrary self types that might have a simple // mutability difference, like calling a method on `Pin<&mut Self>` that is on @@ -998,8 +997,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty, &item_segment, span, - args.full_expr, - args.receiver, + tcx.hir().get_parent(rcvr_expr.hir_id).expect_expr(), + rcvr_expr, ) { err.span_note( tcx.def_span(method.def_id), @@ -1168,11 +1167,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, rcvr_ty, item_name, - args.map(|MethodCallComponents { args, .. }| args.len() + 1), + args.map(|args| args.len() + 1), source, no_match_data.out_of_scope_traits.clone(), - &unsatisfied_predicates, - &static_candidates, + unsatisfied_predicates, + static_candidates, unsatisfied_bounds, expected.only_has_type(self), trait_missing_method, @@ -1240,7 +1239,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } + // If an appropriate error source is not found, check method chain for possible candiates + if unsatisfied_predicates.is_empty() + && let Mode::MethodCall = mode + && let SelfSource::MethodCall(mut source_expr) = source + { + let mut stack_methods = vec![]; + while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, method_span) = + source_expr.kind + { + // Pop the matching receiver, to align on it's notional span + if let Some(prev_match) = stack_methods.pop() { + err.span_label( + method_span, + format!("{item_kind} `{item_name}` is available on `{prev_match}`"), + ); + } + let rcvr_ty = self.resolve_vars_if_possible( + self.typeck_results + .borrow() + .expr_ty_adjusted_opt(rcvr_expr) + .unwrap_or(Ty::new_misc_error(self.tcx)), + ); + for _matched_method in self.probe_for_name_many( + Mode::MethodCall, + item_name, + None, + IsSuggestion(true), + rcvr_ty, + source_expr.hir_id, + ProbeScope::TraitsInScope, + ) { + // found a match, push to stack + stack_methods.push(rcvr_ty); + } + source_expr = rcvr_expr; + } + // If there is a match at the start of the chain, add a label for it too! + if let Some(prev_match) = stack_methods.pop() { + err.span_label( + source_expr.span, + format!("{item_kind} `{item_name}` is available on `{prev_match}`"), + ); + } + } self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); return Some(err); } @@ -1249,7 +1292,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, rcvr_ty: Ty<'tcx>, item_name: Ident, - args: Option>, + self_source: SelfSource<'tcx>, + args: Option<&'tcx [hir::Expr<'tcx>]>, span: Span, err: &mut Diagnostic, sources: &mut Vec, @@ -1319,38 +1363,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(sugg_span) = sugg_span && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) - { - let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id); - - let ty = match item.kind { - ty::AssocKind::Const | ty::AssocKind::Type => impl_ty, - ty::AssocKind::Fn => self - .tcx - .fn_sig(item.def_id) - .instantiate_identity() - .inputs() - .skip_binder() - .get(0) - .filter(|ty| ty.is_ref() && !rcvr_ty.is_ref()) - .copied() - .unwrap_or(rcvr_ty), - }; - if let Some(sugg) = print_disambiguation_help( - item_name, - args, + && let Some(sugg) = print_disambiguation_help( + self.tcx, err, - path, - ty, - Some(impl_ty), - item.kind, - self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), - sugg_span, + self_source, + args, + trait_ref + .instantiate( + self.tcx, + self.fresh_args_for_item(sugg_span, impl_did), + ) + .with_self_ty(self.tcx, rcvr_ty), idx, - self.tcx.sess.source_map(), - item.fn_has_self_parameter, - ) { - suggs.push(sugg); - } + sugg_span, + item, + ) + { + suggs.push(sugg); } } CandidateSource::Trait(trait_did) => { @@ -1372,29 +1401,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_note(item_span, msg); None }; - if let Some(sugg_span) = sugg_span { - let path = self.tcx.def_path_str(trait_did); - if let Some(sugg) = print_disambiguation_help( - item_name, - args, + if let Some(sugg_span) = sugg_span + && let Some(sugg) = print_disambiguation_help( + self.tcx, err, - path, - rcvr_ty, - None, - item.kind, - self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id), - sugg_span, + self_source, + args, + ty::TraitRef::new( + self.tcx, + trait_did, + self.fresh_args_for_item(sugg_span, trait_did), + ) + .with_self_ty(self.tcx, rcvr_ty), idx, - self.tcx.sess.source_map(), - item.fn_has_self_parameter, - ) { - suggs.push(sugg); - } + sugg_span, + item, + ) + { + suggs.push(sugg); } } } } - if !suggs.is_empty() && let Some(span) = sugg_span { + if !suggs.is_empty() + && let Some(span) = sugg_span + { + suggs.sort(); err.span_suggestions( span.with_hi(item_name.span.lo()), "use fully-qualified syntax to disambiguate", @@ -1407,6 +1439,85 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Look at all the associated functions without receivers in the type's inherent impls + /// to look for builders that return `Self`, `Option` or `Result`. + fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>) { + let ty::Adt(adt_def, _) = rcvr_ty.kind() else { + return; + }; + let mut items = self + .tcx + .inherent_impls(adt_def.did()) + .iter() + .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) + // Only assoc fn with no receivers. + .filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter) + .filter_map(|item| { + // Only assoc fns that return `Self`, `Option` or `Result`. + let ret_ty = self.tcx.fn_sig(item.def_id).skip_binder().output(); + let ret_ty = self.tcx.instantiate_bound_regions_with_erased(ret_ty); + let ty::Adt(def, args) = ret_ty.kind() else { + return None; + }; + // Check for `-> Self` + if self.can_eq(self.param_env, ret_ty, rcvr_ty) { + return Some((item.def_id, ret_ty)); + } + // Check for `-> Option` or `-> Result` + if ![self.tcx.lang_items().option_type(), self.tcx.get_diagnostic_item(sym::Result)] + .contains(&Some(def.did())) + { + return None; + } + let arg = args.get(0)?.expect_ty(); + if self.can_eq(self.param_env, rcvr_ty, arg) { + Some((item.def_id, ret_ty)) + } else { + None + } + }) + .collect::>(); + let post = if items.len() > 5 { + let items_len = items.len(); + items.truncate(4); + format!("\nand {} others", items_len - 4) + } else { + String::new() + }; + match &items[..] { + [] => {} + [(def_id, ret_ty)] => { + err.span_note( + self.tcx.def_span(def_id), + format!( + "if you're trying to build a new `{rcvr_ty}`, consider using `{}` which \ + returns `{ret_ty}`", + self.tcx.def_path_str(def_id), + ), + ); + } + _ => { + let span: MultiSpan = items + .iter() + .map(|(def_id, _)| self.tcx.def_span(def_id)) + .collect::>() + .into(); + err.span_note( + span, + format!( + "if you're trying to build a new `{rcvr_ty}` consider using one of the \ + following associated functions:\n{}{post}", + items + .iter() + .map(|(def_id, _ret_ty)| self.tcx.def_path_str(def_id)) + .collect::>() + .join("\n") + ), + ); + } + } + } + /// Suggest calling `Ty::method` if `.method()` isn't found because the method /// doesn't take a `self` receiver. fn suggest_associated_call_syntax( @@ -1416,7 +1527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>, item_name: Ident, - args: Option>, + args: Option<&'tcx [hir::Expr<'tcx>]>, sugg_span: Span, ) { let mut has_unsuggestable_args = false; @@ -1490,7 +1601,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None }; let mut applicability = Applicability::MachineApplicable; - let args = if let Some(MethodCallComponents { receiver, args, .. }) = args { + let args = if let SelfSource::MethodCall(receiver) = source + && let Some(args) = args + { // The first arg is the same kind as the receiver let explicit_args = if first_arg.is_some() { std::iter::once(receiver).chain(args.iter()).collect::>() @@ -1609,7 +1722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) { if let Node::Expr(parent_expr) = parent { let lang_item = match parent_expr.kind { - ExprKind::Struct(ref qpath, _, _) => match **qpath { + ExprKind::Struct(qpath, _, _) => match *qpath { QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range), QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo), QPath::LangItem(LangItem::RangeToInclusive, ..) => { @@ -1617,7 +1730,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => None, }, - ExprKind::Call(ref func, _) => match func.kind { + ExprKind::Call(func, _) => match func.kind { // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => { Some(LangItem::RangeInclusiveStruct) @@ -1636,7 +1749,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { eps.len() > 0 && eps.last().is_some_and(|ep| ep.span.contains(span)) } // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. - hir::ExprKind::Call(ref func, ..) => func.span.contains(span), + hir::ExprKind::Call(func, ..) => func.span.contains(span), _ => false, }; @@ -1730,7 +1843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let concrete_type = if actual.is_integral() { "i32" } else { "f32" }; match expr.kind { - ExprKind::Lit(ref lit) => { + ExprKind::Lit(lit) => { // numeric literal let snippet = tcx .sess @@ -1834,7 +1947,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name }; - visitor.visit_body(&body); + visitor.visit_body(body); let parent = self.tcx.hir().parent_id(seg1.hir_id); if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) @@ -1871,69 +1984,73 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: Ident, return_type: Option>, ) { - if let SelfSource::MethodCall(expr) = source - && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id() - && let Some((fields, args)) = - self.get_field_candidates_considering_privacy(span, actual, mod_id) - { - let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)); + if let SelfSource::MethodCall(expr) = source { + let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id(); + for (fields, args) in + self.get_field_candidates_considering_privacy(span, actual, mod_id, expr.hir_id) + { + let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)); - let lang_items = self.tcx.lang_items(); - let never_mention_traits = [ - lang_items.clone_trait(), - lang_items.deref_trait(), - lang_items.deref_mut_trait(), - self.tcx.get_diagnostic_item(sym::AsRef), - self.tcx.get_diagnostic_item(sym::AsMut), - self.tcx.get_diagnostic_item(sym::Borrow), - self.tcx.get_diagnostic_item(sym::BorrowMut), - ]; - let candidate_fields: Vec<_> = fields - .filter_map(|candidate_field| { - self.check_for_nested_field_satisfying( - span, - &|_, field_ty| { - self.lookup_probe_for_diagnostic( - item_name, - field_ty, - call_expr, - ProbeScope::TraitsInScope, - return_type, - ) - .is_ok_and(|pick| { - !never_mention_traits - .iter() - .flatten() - .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id) - }) - }, - candidate_field, - args, - vec![], - mod_id, - ) - }) - .map(|field_path| { - field_path - .iter() - .map(|id| id.name.to_ident_string()) - .collect::>() - .join(".") - }) - .collect(); + let lang_items = self.tcx.lang_items(); + let never_mention_traits = [ + lang_items.clone_trait(), + lang_items.deref_trait(), + lang_items.deref_mut_trait(), + self.tcx.get_diagnostic_item(sym::AsRef), + self.tcx.get_diagnostic_item(sym::AsMut), + self.tcx.get_diagnostic_item(sym::Borrow), + self.tcx.get_diagnostic_item(sym::BorrowMut), + ]; + let mut candidate_fields: Vec<_> = fields + .into_iter() + .filter_map(|candidate_field| { + self.check_for_nested_field_satisfying( + span, + &|_, field_ty| { + self.lookup_probe_for_diagnostic( + item_name, + field_ty, + call_expr, + ProbeScope::TraitsInScope, + return_type, + ) + .is_ok_and(|pick| { + !never_mention_traits + .iter() + .flatten() + .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id) + }) + }, + candidate_field, + args, + vec![], + mod_id, + expr.hir_id, + ) + }) + .map(|field_path| { + field_path + .iter() + .map(|id| id.name.to_ident_string()) + .collect::>() + .join(".") + }) + .collect(); + candidate_fields.sort(); - let len = candidate_fields.len(); - if len > 0 { - err.span_suggestions( - item_name.span.shrink_to_lo(), - format!( - "{} of the expressions' fields {} a method of the same name", - if len > 1 { "some" } else { "one" }, - if len > 1 { "have" } else { "has" }, - ), - candidate_fields.iter().map(|path| format!("{path}.")), - Applicability::MaybeIncorrect, - ); + let len = candidate_fields.len(); + if len > 0 { + err.span_suggestions( + item_name.span.shrink_to_lo(), + format!( + "{} of the expressions' fields {} a method of the same name", + if len > 1 { "some" } else { "one" }, + if len > 1 { "have" } else { "has" }, + ), + candidate_fields.iter().map(|path| format!("{path}.")), + Applicability::MaybeIncorrect, + ); + } } } } @@ -2171,7 +2288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(def, _) if def.did().is_local() => { spans.push_span_label( self.tcx.def_span(def.did()), - format!("must implement `{}`", pred.trait_ref.print_only_trait_path()), + format!("must implement `{}`", pred.trait_ref.print_trait_sugared()), ); } _ => {} @@ -2182,7 +2299,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let msg = if preds.len() == 1 { format!( "an implementation of `{}` might be missing for `{}`", - preds[0].trait_ref.print_only_trait_path(), + preds[0].trait_ref.print_trait_sugared(), preds[0].self_ty() ) } else { @@ -2452,13 +2569,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.item_name(*trait_did), ) }); + let mut sugg: Vec<_> = path_strings.chain(glob_path_strings).collect(); + sugg.sort(); - err.span_suggestions( - span, - msg, - path_strings.chain(glob_path_strings), - Applicability::MaybeIncorrect, - ); + err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect); } fn suggest_valid_traits( @@ -2753,7 +2867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let id = item .def_id .as_local() - .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id)); + .map(|def_id| self.tcx.local_def_id_to_hir_id(def_id)); if let Some(hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(fn_sig, method), .. @@ -2843,7 +2957,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let type_param = generics.type_param(param, self.tcx); let hir = self.tcx.hir(); if let Some(def_id) = type_param.def_id.as_local() { - let id = hir.local_def_id_to_hir_id(def_id); + let id = self.tcx.local_def_id_to_hir_id(def_id); // Get the `hir::Param` to verify whether it already has any bounds. // We do this to avoid suggesting code that ends up as `T: FooBar`, // instead we suggest `T: Foo + Bar` in that case. @@ -3179,56 +3293,64 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { } fn print_disambiguation_help<'tcx>( - item_name: Ident, - args: Option>, + tcx: TyCtxt<'tcx>, err: &mut Diagnostic, - trait_name: String, - rcvr_ty: Ty<'_>, - impl_self_ty: Option>, - kind: ty::AssocKind, - def_kind_descr: &'static str, + source: SelfSource<'tcx>, + args: Option<&'tcx [hir::Expr<'tcx>]>, + trait_ref: ty::TraitRef<'tcx>, + candidate_idx: Option, span: Span, - candidate: Option, - source_map: &source_map::SourceMap, - fn_has_self_parameter: bool, + item: ty::AssocItem, ) -> Option { + let trait_ref = if item.fn_has_self_parameter { + trait_ref.print_only_trait_name().to_string() + } else { + format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name()) + }; Some( - if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args) + if matches!(item.kind, ty::AssocKind::Fn) + && let SelfSource::MethodCall(receiver) = source + && let Some(args) = args { + let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id); + let item_name = item.ident(tcx); + let rcvr_ref = tcx + .fn_sig(item.def_id) + .skip_binder() + .skip_binder() + .inputs() + .get(0) + .and_then(|ty| ty.ref_mutability()) + .map_or("", |mutbl| mutbl.ref_prefix_str()); let args = format!( "({}{})", - rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()), + rcvr_ref, std::iter::once(receiver) .chain(args.iter()) - .map(|arg| source_map + .map(|arg| tcx + .sess + .source_map() .span_to_snippet(arg.span) .unwrap_or_else(|_| { "_".to_owned() })) .collect::>() .join(", "), ); - let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty { - format!("<{impl_self_ty} as {trait_name}>") - } else { - trait_name - }; err.span_suggestion_verbose( span, format!( "disambiguate the {def_kind_descr} for {}", - if let Some(candidate) = candidate { + if let Some(candidate) = candidate_idx { format!("candidate #{candidate}") } else { "the candidate".to_string() }, ), - format!("{trait_name}::{item_name}{args}"), + format!("{trait_ref}::{item_name}{args}"), Applicability::HasPlaceholders, ); return None; - } else if let Some(impl_self_ty) = impl_self_ty { - format!("<{impl_self_ty} as {trait_name}>::") } else { - format!("{trait_name}::") + format!("{trait_ref}::") }, ) } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index d0d3b0e5b73cf..1e9387ef041b2 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -291,7 +291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .push(autoref); } } - self.write_method_call(expr.hir_id, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); method.sig.output() } @@ -379,6 +379,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (err, output_def_id) } }; + if self.check_for_missing_semi(expr, &mut err) + && let hir::Node::Expr(expr) = self.tcx.hir().get_parent(expr.hir_id) + && let hir::ExprKind::Assign(..) = expr.kind + { + // We defer to the later error produced by `check_lhs_assignable`. + err.delay_as_bug(); + } let suggest_deref_binop = |err: &mut DiagnosticBuilder<'_, _>, lhs_deref_ty: Ty<'tcx>| { @@ -774,7 +781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(op.is_by_value()); match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) { Ok(method) => { - self.write_method_call(ex.hir_id, method); + self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method); method.sig.output() } Err(errors) => { @@ -893,7 +900,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { self.tcx .sess - .delay_span_bug(span, "operator didn't have the right number of generic args"); + .span_delayed_bug(span, "operator didn't have the right number of generic args"); return Err(vec![]); } @@ -926,7 +933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This path may do some inference, so make sure we've really // doomed compilation so as to not accidentally stabilize new // inference or something here... - self.tcx.sess.delay_span_bug(span, "this path really should be doomed..."); + self.tcx.sess.span_delayed_bug(span, "this path really should be doomed..."); // Guide inference for the RHS expression if it's provided -- // this will allow us to better error reporting, at the expense // of making some error messages a bit more specific. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 50684482c0d55..b63bb1e00cb55 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -166,9 +166,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) { let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info; let path_res = match &pat.kind { - PatKind::Path(qpath) => { - Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span)) - } + PatKind::Path(qpath) => Some( + self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None), + ), _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); @@ -178,6 +178,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = match pat.kind { PatKind::Wild => expected, + // FIXME(never_patterns): check the type is uninhabited. If that is not possible within + // typeck, do that in a later phase. + PatKind::Never => expected, PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti), PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), PatKind::Binding(ba, var_id, _, sub) => { @@ -287,9 +290,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Box(_) | PatKind::Range(..) | PatKind::Slice(..) => AdjustMode::Peel, + // A never pattern behaves somewhat like a literal or unit variant. + PatKind::Never => AdjustMode::Peel, // String and byte-string literals result in types `&str` and `&[u8]` respectively. // All other literals result in non-reference types. - // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo {}`. + // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`. // // Call `resolve_vars_if_possible` here for inline const blocks. PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() { @@ -743,6 +748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Slice(..) => "binding", PatKind::Wild + | PatKind::Never | PatKind::Binding(..) | PatKind::Path(..) | PatKind::Box(..) @@ -872,7 +878,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info); // Type-check subpatterns. - if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, pat_info) { + if self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) { pat_ty } else { Ty::new_misc_error(self.tcx) @@ -893,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (res, opt_ty, segments) = path_resolution; match res { Res::Err => { - let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted"); + let e = tcx.sess.span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); return Ty::new_error(tcx, e); } @@ -1060,9 +1066,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Resolve the path and check the definition for errors. let (res, opt_ty, segments) = - self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); + self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None); if res == Res::Err { - let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted"); + let e = tcx.sess.span_delayed_bug(pat.span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); on_error(e); return Ty::new_error(tcx, e); @@ -1078,7 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let variant = match res { Res::Err => { - let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted"); + let e = tcx.sess.span_delayed_bug(pat.span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); on_error(e); return Ty::new_error(tcx, e); diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index 406434e09e68e..79e41ef922759 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span_bug!(expr.span, "input to deref is not a ref?"); } let ty = self.make_overloaded_place_return_type(method).ty; - self.write_method_call(expr.hir_id, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); Some(ty) } @@ -179,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.apply_adjustments(base_expr, adjustments); - self.write_method_call(expr.hir_id, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); return Some((input_ty, self.make_overloaded_place_return_type(method).ty)); } @@ -283,9 +283,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Gather up expressions we want to munge. let mut exprs = vec![expr]; - while let hir::ExprKind::Field(ref expr, _) - | hir::ExprKind::Index(ref expr, _, _) - | hir::ExprKind::Unary(hir::UnOp::Deref, ref expr) = exprs.last().unwrap().kind + while let hir::ExprKind::Field(expr, _) + | hir::ExprKind::Index(expr, _, _) + | hir::ExprKind::Unary(hir::UnOp::Deref, expr) = exprs.last().unwrap().kind { exprs.push(expr); } @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => return, }; debug!("convert_place_op_to_mutable: method={:?}", method); - self.write_method_call(expr.hir_id, method); + self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method); let ty::Ref(region, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() else { span_bug!(expr.span, "input to mutable place op is not a mut ref?"); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 75c70ec59fb79..c0a5818b9e5f9 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.compute_min_captures(closure_def_id, capture_information, span); - let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id); + let closure_hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id); if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) { self.perform_2229_migration_analysis(closure_def_id, body_id, capture_clause, span); @@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { origin = updated.1; let (place, capture_kind) = match capture_clause { - hir::CaptureBy::Value => adjust_for_move_closure(place, capture_kind), + hir::CaptureBy::Value { .. } => adjust_for_move_closure(place, capture_kind), hir::CaptureBy::Ref => adjust_for_non_move_closure(place, capture_kind), }; @@ -725,7 +725,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( closure_span, format!( "two identical projections: ({:?}, {:?})", @@ -763,7 +763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (migration_string, migrated_variables_concat) = migration_suggestion_for_2229(self.tcx, &need_migrations); - let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id); + let closure_hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id); let closure_head_span = self.tcx.def_span(closure_def_id); self.tcx.struct_span_lint_hir( lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, @@ -958,7 +958,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id)); let ty = match closure_clause { - hir::CaptureBy::Value => ty, // For move closure the capture kind should be by value + hir::CaptureBy::Value { .. } => ty, // For move closure the capture kind should be by value hir::CaptureBy::Ref => { // For non move closure the capture kind is the max capture kind of all captures // according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue @@ -1073,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match closure_clause { // Only migrate if closure is a move closure - hir::CaptureBy::Value => { + hir::CaptureBy::Value { .. } => { let mut diagnostics_info = FxIndexSet::default(); let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar"); @@ -1479,10 +1479,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the data will be moved out of this place, then the place will be truncated // at the first Deref in `adjust_upvar_borrow_kind_for_consume` and then moved into // the closure. - hir::CaptureBy::Value if !place.deref_tys().any(Ty::is_ref) => { + hir::CaptureBy::Value { .. } if !place.deref_tys().any(Ty::is_ref) => { ty::UpvarCapture::ByValue } - hir::CaptureBy::Value | hir::CaptureBy::Ref => ty::UpvarCapture::ByRef(ty::ImmBorrow), + hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => { + ty::UpvarCapture::ByRef(ty::ImmBorrow) + } } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 896aacc699312..cc617fd2d0be6 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -47,7 +47,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type only exists for constants and statics, not functions. match self.tcx.hir().body_owner_kind(item_def_id) { hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => { - let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(item_def_id); + let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id); wbcx.visit_node_id(body.value.span, item_hir_id); } hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (), @@ -218,7 +218,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // When encountering `return [0][0]` outside of a `fn` body we can encounter a base // that isn't in the type table. We assume more relevant errors have already been // emitted, so we delay an ICE if none have. (#64638) - self.tcx().sess.delay_span_bug(e.span, format!("bad base: `{base:?}`")); + self.tcx().sess.span_delayed_bug(e.span, format!("bad base: `{base:?}`")); } if let Some(base_ty) = base_ty && let ty::Ref(_, base_ty_inner, _) = *base_ty.kind() @@ -311,7 +311,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { // Nothing to write back here } hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => { - self.tcx().sess.delay_span_bug(p.span, format!("unexpected generic param: {p:?}")); + self.tcx() + .sess + .span_delayed_bug(p.span, format!("unexpected generic param: {p:?}")); } } } @@ -382,7 +384,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { .to_sorted(hcx, false) .into_iter() .map(|(&closure_def_id, data)| { - let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id); + let closure_hir_id = self.tcx().local_def_id_to_hir_id(closure_def_id); let data = self.resolve(*data, &closure_hir_id); (closure_def_id, data) }) @@ -407,7 +409,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { .map(|captured_place| { let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| { - self.tcx().hir().local_def_id_to_hir_id(closure_def_id) + self.tcx().local_def_id_to_hir_id(closure_def_id) }); self.resolve(captured_place.clone(), &locatable) }) @@ -433,7 +435,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let resolved_fake_reads = fake_reads .iter() .map(|(place, cause, hir_id)| { - let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id); + let locatable = self.tcx().local_def_id_to_hir_id(closure_def_id); let resolved_fake_read = self.resolve(place.clone(), &locatable); (resolved_fake_read, *cause, *hir_id) }) @@ -768,41 +770,22 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { } } -struct EraseEarlyRegions<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> TypeFolder> for EraseEarlyRegions<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.has_type_flags(ty::TypeFlags::HAS_FREE_REGIONS) { - ty.super_fold_with(self) - } else { - ty - } - } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if r.is_late_bound() { r } else { self.tcx.lifetimes.re_erased } - } -} - impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { fn interner(&self) -> TyCtxt<'tcx> { self.fcx.tcx } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + let tcx = self.fcx.tcx; match self.fcx.fully_resolve(t) { Ok(t) if self.fcx.next_trait_solver() => { // We must normalize erasing regions here, since later lints // expect that types that show up in the typeck are fully // normalized. - if let Ok(t) = self.fcx.tcx.try_normalize_erasing_regions(self.fcx.param_env, t) { + if let Ok(t) = tcx.try_normalize_erasing_regions(self.fcx.param_env, t) { t } else { - EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t) + tcx.fold_regions(t, |_, _| tcx.lifetimes.re_erased) } } Ok(t) => { @@ -810,7 +793,7 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { // (e.g. keep `for<'a>` named `for<'a>`). // This allows NLL to generate error messages that // refer to the higher-ranked lifetime names written by the user. - EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t) + tcx.fold_regions(t, |_, _| tcx.lifetimes.re_erased) } Err(_) => { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); @@ -822,7 +805,7 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - debug_assert!(!r.is_late_bound(), "Should not be resolving bound region."); + debug_assert!(!r.is_bound(), "Should not be resolving bound region."); self.fcx.tcx.lifetimes.re_erased } diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl index 5d885e07192dd..e74173b24a97b 100644 --- a/compiler/rustc_incremental/messages.ftl +++ b/compiler/rustc_incremental/messages.ftl @@ -30,8 +30,6 @@ incremental_create_lock = incremental compilation: could not create session directory lock file: {$lock_err} incremental_create_new = failed to create {$name} at `{$path}`: {$err} -incremental_decode_incr_cache = could not decode incremental cache: {$err} - incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err} incremental_delete_incompatible = diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 1b160eca92db7..a5e0654c81df6 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -122,7 +122,7 @@ impl<'tcx> IfThisChanged<'tcx> { fn process_attrs(&mut self, def_id: LocalDefId) { let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id()); - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = self.tcx.local_def_id_to_hir_id(def_id); let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { if attr.has_name(sym::rustc_if_this_changed) { @@ -231,13 +231,13 @@ fn dump_graph(query: &DepGraphQuery) { // Expect one of: "-> target", "source -> target", or "source ->". let edge_filter = EdgeFilter::new(&string).unwrap_or_else(|e| bug!("invalid filter: {}", e)); - let sources = node_set(&query, &edge_filter.source); - let targets = node_set(&query, &edge_filter.target); - filter_nodes(&query, &sources, &targets) + let sources = node_set(query, &edge_filter.source); + let targets = node_set(query, &edge_filter.target); + filter_nodes(query, &sources, &targets) } Err(_) => query.nodes().into_iter().map(|n| n.kind).collect(), }; - let edges = filter_edges(&query, &nodes); + let edges = filter_edges(query, &nodes); { // dump a .txt file with just the edges: diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index 05ed4f7598d4a..61bb0353a9f4b 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -270,12 +270,6 @@ pub struct LoadDepGraph { pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag(incremental_decode_incr_cache)] -pub struct DecodeIncrCache { - pub err: String, -} - #[derive(Diagnostic)] #[diag(incremental_write_dep_graph)] pub struct WriteDepGraph<'a> { diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index dde138973b931..367a15e144304 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -2,9 +2,9 @@ #![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -28,7 +28,4 @@ pub use persist::save_work_product_index; pub use persist::setup_dep_graph; pub use persist::LoadResult; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 5dd06c6ca4f40..eaf83b7ee5f4d 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -378,15 +378,15 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { }; self.checked_attrs.insert(attr.id); for label in assertion.clean.items().into_sorted_stable_ord() { - let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); + let dep_node = DepNode::from_label_string(self.tcx, label, def_path_hash).unwrap(); self.assert_clean(item_span, dep_node); } for label in assertion.dirty.items().into_sorted_stable_ord() { - let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); + let dep_node = DepNode::from_label_string(self.tcx, label, def_path_hash).unwrap(); self.assert_dirty(item_span, dep_node); } for label in assertion.loaded_from_disk.items().into_sorted_stable_ord() { - let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); + let dep_node = DepNode::from_label_string(self.tcx, label, def_path_hash).unwrap(); self.assert_loaded_from_disk(item_span, dep_node); } } diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 25bf83f64a086..b5742b97d0242 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -80,8 +80,8 @@ where ); debug!("save: data written to disk successfully"); } - Err(err) => { - sess.emit_err(errors::WriteNew { name, path: path_buf, err }); + Err((path, err)) => { + sess.emit_err(errors::WriteNew { name, path, err }); } } } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index f56fb0d0534be..92297a27a63ef 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -262,7 +262,7 @@ pub(crate) fn prepare_session_directory( directory." ); - sess.init_incr_comp_session(session_dir, directory_lock, false); + sess.init_incr_comp_session(session_dir, directory_lock); return Ok(()); }; @@ -276,7 +276,7 @@ pub(crate) fn prepare_session_directory( sess.emit_warning(errors::HardLinkFailed { path: &session_dir }); } - sess.init_incr_comp_session(session_dir, directory_lock, true); + sess.init_incr_comp_session(session_dir, directory_lock); return Ok(()); } else { debug!("copying failed - trying next directory"); @@ -312,7 +312,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option) { let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone(); - if let Some(_) = sess.has_errors_or_delayed_span_bugs() { + if let Some(_) = sess.has_errors_or_span_delayed_bugs() { // If there have been any errors during compilation, we don't want to // publish this session directory. Rather, we'll just delete it. @@ -499,7 +499,7 @@ fn lock_directory( } fn delete_session_dir_lock_file(sess: &Session, lock_file_path: &Path) { - if let Err(err) = safe_remove_file(&lock_file_path) { + if let Err(err) = safe_remove_file(lock_file_path) { sess.emit_warning(errors::DeleteLock { path: lock_file_path, err }); } } @@ -847,10 +847,10 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result< fn delete_old(sess: &Session, path: &Path) { debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); - if let Err(err) = safe_remove_dir_all(&path) { - sess.emit_warning(errors::SessionGcFailed { path: &path, err }); + if let Err(err) = safe_remove_dir_all(path) { + sess.emit_warning(errors::SessionGcFailed { path: path, err }); } else { - delete_session_dir_lock_file(sess, &lock_file_path(&path)); + delete_session_dir_lock_file(sess, &lock_file_path(path)); } } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index cbd55fe420563..f2c1d0b83aac3 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -30,8 +30,6 @@ pub enum LoadResult { DataOutOfDate, /// Loading the dep graph failed. LoadDepGraph(PathBuf, std::io::Error), - /// Decoding loaded incremental cache failed. - DecodeIncrCache(Box), } impl LoadResult { @@ -44,9 +42,7 @@ impl LoadResult { } ( Some(IncrementalStateAssertion::Loaded), - LoadResult::LoadDepGraph(..) - | LoadResult::DecodeIncrCache(..) - | LoadResult::DataOutOfDate, + LoadResult::LoadDepGraph(..) | LoadResult::DataOutOfDate, ) => { sess.emit_fatal(errors::AssertLoaded); } @@ -58,10 +54,6 @@ impl LoadResult { sess.emit_warning(errors::LoadDepGraph { path, err }); Default::default() } - LoadResult::DecodeIncrCache(err) => { - sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") }); - Default::default() - } LoadResult::DataOutOfDate => { if let Err(err) = delete_all_session_dir_contents(sess) { sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err }); @@ -107,7 +99,7 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProduct // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. - let path = dep_graph_path(&sess); + let path = dep_graph_path(sess); let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = UnordMap::default(); @@ -150,7 +142,6 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProduct match load_data(&path, sess) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err), - LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err), LoadResult::Ok { data: (bytes, start_pos) } => { let mut decoder = MemDecoder::new(&bytes, start_pos); let prev_commandline_args_hash = u64::decode(&mut decoder); diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index fa21320be263e..ff0953e9f7b44 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -32,7 +32,7 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { return; } // This is going to be deleted in finalize_session_directory, so let's not create it - if let Some(_) = sess.has_errors_or_delayed_span_bugs() { + if let Some(_) = sess.has_errors_or_span_delayed_bugs() { return; } @@ -50,9 +50,6 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { join( move || { sess.time("incr_comp_persist_dep_graph", || { - if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) { - sess.emit_err(errors::WriteDepGraph { path: &staging_dep_graph_path, err }); - } if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) { sess.emit_err(errors::MoveDepGraph { from: &staging_dep_graph_path, @@ -90,7 +87,7 @@ pub fn save_work_product_index( return; } // This is going to be deleted in finalize_session_directory, so let's not create it - if let Some(_) = sess.has_errors_or_delayed_span_bugs() { + if let Some(_) = sess.has_errors_or_span_delayed_bugs() { return; } diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index fb96bed5a7180..1ee3d13922b40 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -31,7 +31,7 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( } Err(err) => { sess.emit_warning(errors::CopyWorkProductToCache { - from: &path, + from: path, to: &path_in_incr_dir, err, }); diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index 856f8a67dd617..3a4c813b5d41b 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start arrayvec = { version = "0.7", default-features = false } +rustc_index_macros = { path = "../rustc_index_macros", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } rustc_serialize = { path = "../rustc_serialize", optional = true } smallvec = "1.8.1" @@ -14,5 +15,5 @@ smallvec = "1.8.1" [features] # tidy-alphabetical-start default = ["nightly"] -nightly = ["rustc_serialize", "rustc_macros"] +nightly = ["rustc_serialize", "rustc_macros", "rustc_index_macros/nightly"] # tidy-alphabetical-end diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index ece61ff12520c..d0b4889b45fa9 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -237,23 +237,12 @@ impl BitSet { new_word != word } - /// Gets a slice of the underlying words. - pub fn words(&self) -> &[Word] { - &self.words - } - /// Iterates over the indices of set bits in a sorted order. #[inline] pub fn iter(&self) -> BitIter<'_, T> { BitIter::new(&self.words) } - /// Duplicates the set as a hybrid set. - pub fn to_hybrid(&self) -> HybridBitSet { - // Note: we currently don't bother trying to make a Sparse set. - HybridBitSet::Dense(self.to_owned()) - } - /// Set `self = self | other`. In contrast to `union` returns `true` if the set contains at /// least one bit that is not in `other` (i.e. `other` is not a superset of `self`). /// @@ -1601,11 +1590,11 @@ impl BitMatrix { pub fn from_row_n(row: &BitSet, num_rows: usize) -> BitMatrix { let num_columns = row.domain_size(); let words_per_row = num_words(num_columns); - assert_eq!(words_per_row, row.words().len()); + assert_eq!(words_per_row, row.words.len()); BitMatrix { num_rows, num_columns, - words: iter::repeat(row.words()).take(num_rows).flatten().cloned().collect(), + words: iter::repeat(&row.words).take(num_rows).flatten().cloned().collect(), marker: PhantomData, } } @@ -1700,9 +1689,9 @@ impl BitMatrix { assert_eq!(with.domain_size(), self.num_columns); let (write_start, write_end) = self.range(write); let mut changed = false; - for (read_index, write_index) in iter::zip(0..with.words().len(), write_start..write_end) { + for (read_index, write_index) in iter::zip(0..with.words.len(), write_start..write_end) { let word = self.words[write_index]; - let new_word = word | with.words()[read_index]; + let new_word = word | with.words[read_index]; self.words[write_index] = new_word; changed |= word != new_word; } @@ -2002,54 +1991,6 @@ impl std::fmt::Debug for FiniteBitSet { } } -impl FiniteBitSetTy for u64 { - const DOMAIN_SIZE: u32 = 64; - - const FILLED: Self = Self::MAX; - const EMPTY: Self = Self::MIN; - - const ONE: Self = 1u64; - const ZERO: Self = 0u64; - - fn checked_shl(self, rhs: u32) -> Option { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:064b}", self.0) - } -} - -impl FiniteBitSetTy for u128 { - const DOMAIN_SIZE: u32 = 128; - - const FILLED: Self = Self::MAX; - const EMPTY: Self = Self::MIN; - - const ONE: Self = 1u128; - const ZERO: Self = 0u128; - - fn checked_shl(self, rhs: u32) -> Option { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:0128b}", self.0) - } -} - /// A fixed-sized bitset type represented by an integer type. Indices outwith than the range /// representable by `T` are considered set. #[derive(Copy, Clone, Eq, PartialEq, Decodable, Encodable)] diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 061c55c01506c..c5602392c538c 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -25,8 +25,7 @@ mod vec; pub use {idx::Idx, slice::IndexSlice, vec::IndexVec}; -#[cfg(feature = "rustc_macros")] -pub use rustc_macros::newtype_index; +pub use rustc_index_macros::newtype_index; /// Type size assertion. The first argument is a type and the second argument is its expected size. /// diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 99e72e49f8eb8..66c5cc774b224 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -137,10 +137,6 @@ impl IndexVec { self.raw.truncate(a) } - pub fn convert_index_type(self) -> IndexVec { - IndexVec::from_raw(self.raw) - } - /// Grows the index vector so that it contains an entry for /// `elem`; if that is already true, then has no /// effect. Otherwise, inserts new values as needed by invoking diff --git a/compiler/rustc_index/src/vec/tests.rs b/compiler/rustc_index/src/vec/tests.rs index cb0f0db220d97..381d79c24fcba 100644 --- a/compiler/rustc_index/src/vec/tests.rs +++ b/compiler/rustc_index/src/vec/tests.rs @@ -1,9 +1,8 @@ -#![allow(dead_code)] - // Allows the macro invocation below to work use crate as rustc_index; -rustc_macros::newtype_index! { +crate::newtype_index! { + #[orderable] #[max = 0xFFFF_FFFA] struct MyIdx {} } diff --git a/compiler/rustc_index_macros/Cargo.toml b/compiler/rustc_index_macros/Cargo.toml new file mode 100644 index 0000000000000..c4ca29db3c2dd --- /dev/null +++ b/compiler/rustc_index_macros/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "rustc_index_macros" +version = "0.0.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +synstructure = "0.13.0" +syn = { version = "2.0.9", features = ["full"] } +proc-macro2 = "1" +quote = "1" + +[features] +default = ["nightly"] +nightly = [] \ No newline at end of file diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs new file mode 100644 index 0000000000000..ac374a41eb6f7 --- /dev/null +++ b/compiler/rustc_index_macros/src/lib.rs @@ -0,0 +1,41 @@ +#![cfg_attr(feature = "nightly", feature(allow_internal_unstable))] +#![cfg_attr(feature = "nightly", allow(internal_features))] + +use proc_macro::TokenStream; + +mod newtype; + +/// Creates a struct type `S` that can be used as an index with +/// `IndexVec` and so on. +/// +/// There are two ways of interacting with these indices: +/// +/// - The `From` impls are the preferred way. So you can do +/// `S::from(v)` with a `usize` or `u32`. And you can convert back +/// to an integer with `u32::from(s)`. +/// +/// - Alternatively, you can use the methods `S::new(v)` and `s.index()` +/// to create/return a value. +/// +/// Internally, the index uses a u32, so the index must not exceed +/// `u32::MAX`. +/// +/// The impls provided by default are Clone, Copy, PartialEq, Eq, and Hash. +/// +/// Accepted attributes for customization: +/// - `#[derive(HashStable_Generic)]`/`#[derive(HashStable)]`: derives +/// `HashStable`, as normal. +/// - `#[encodable]`: derives `Encodable`/`Decodable`. +/// - `#[orderable]`: derives `PartialOrd`/`Ord`, plus step-related methods. +/// - `#[debug_format = "Foo({})"]`: derives `Debug` with particular output. +/// - `#[max = 0xFFFF_FFFD]`: specifies the max value, which allows niche +/// optimizations. The default max value is 0xFFFF_FF00. +/// - `#[gate_rustc_only]`: makes parts of the generated code nightly-only. +#[proc_macro] +#[cfg_attr( + feature = "nightly", + allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq) +)] +pub fn newtype_index(input: TokenStream) -> TokenStream { + newtype::newtype(input) +} diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs similarity index 92% rename from compiler/rustc_macros/src/newtype.rs rename to compiler/rustc_index_macros/src/newtype.rs index 72b47de1abc29..df1318c835e2b 100644 --- a/compiler/rustc_macros/src/newtype.rs +++ b/compiler/rustc_index_macros/src/newtype.rs @@ -22,17 +22,24 @@ impl Parse for Newtype { let mut debug_format: Option = None; let mut max = None; let mut consts = Vec::new(); - let mut encodable = true; - let mut ord = true; + let mut encodable = false; + let mut ord = false; + let mut gate_rustc_only = quote! {}; + let mut gate_rustc_only_cfg = quote! { all() }; attrs.retain(|attr| match attr.path().get_ident() { Some(ident) => match &*ident.to_string() { - "custom_encodable" => { - encodable = false; + "gate_rustc_only" => { + gate_rustc_only = quote! { #[cfg(feature = "nightly")] }; + gate_rustc_only_cfg = quote! { feature = "nightly" }; false } - "no_ord_impl" => { - ord = false; + "encodable" => { + encodable = true; + false + } + "orderable" => { + ord = true; false } "max" => { @@ -88,11 +95,13 @@ impl Parse for Newtype { let encodable_impls = if encodable { quote! { + #gate_rustc_only impl ::rustc_serialize::Decodable for #name { fn decode(d: &mut D) -> Self { Self::from_u32(d.read_u32()) } } + #gate_rustc_only impl ::rustc_serialize::Encodable for #name { fn encode(&self, e: &mut E) { e.emit_u32(self.private); @@ -110,6 +119,7 @@ impl Parse for Newtype { let step = if ord { quote! { + #gate_rustc_only impl ::std::iter::Step for #name { #[inline] fn steps_between(start: &Self, end: &Self) -> Option { @@ -131,6 +141,7 @@ impl Parse for Newtype { } // Safety: The implementation of `Step` upholds all invariants. + #gate_rustc_only unsafe impl ::std::iter::TrustedStep for #name {} } } else { @@ -148,6 +159,7 @@ impl Parse for Newtype { let spec_partial_eq_impl = if let Lit::Int(max) = &max { if let Ok(max_val) = max.base10_parse::() { quote! { + #gate_rustc_only impl core::option::SpecOptionPartialEq for #name { #[inline] fn eq(l: &Option, r: &Option) -> bool { @@ -173,8 +185,8 @@ impl Parse for Newtype { Ok(Self(quote! { #(#attrs)* #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)] - #[rustc_layout_scalar_valid_range_end(#max)] - #[rustc_pass_by_value] + #[cfg_attr(#gate_rustc_only_cfg, rustc_layout_scalar_valid_range_end(#max))] + #[cfg_attr(#gate_rustc_only_cfg, rustc_pass_by_value)] #vis struct #name { private: u32, } diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 00251a192264a..73a02a431dfc0 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -15,7 +15,6 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 3ff1a5c0c14b0..6a220243266d2 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -363,7 +363,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { return false; }; - let hir_id = self.tcx.hir().local_def_id_to_hir_id(anon_reg.def_id); + let hir_id = self.tcx.local_def_id_to_hir_id(anon_reg.def_id); let node = self.tcx.hir().get(hir_id); let is_impl = matches!(&node, hir::Node::ImplItem(_)); diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 57bc14ebcb3fe..3ee4710bdef62 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -17,7 +17,7 @@ impl<'a> DescriptionCtx<'a> { alt_span: Option, ) -> Option { let (span, kind, arg) = match *region { - ty::ReEarlyBound(ref br) => { + ty::ReEarlyParam(ref br) => { let scope = region.free_region_binding_scope(tcx).expect_local(); let span = if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) @@ -32,7 +32,7 @@ impl<'a> DescriptionCtx<'a> { (Some(span), "as_defined_anon", String::new()) } } - ty::ReFree(ref fr) => { + ty::ReLateParam(ref fr) => { if !fr.bound_region.is_named() && let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) { @@ -70,11 +70,14 @@ impl<'a> DescriptionCtx<'a> { ty::RePlaceholder(_) | ty::ReError(_) => return None, // FIXME(#13998) RePlaceholder should probably print like - // ReFree rather than dumping Debug output on the user. + // ReLateParam rather than dumping Debug output on the user. // // We shouldn't really be having unification failures with ReVar - // and ReLateBound though. - ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { + // and ReBound though. + // + // FIXME(@lcnr): figure out why we have to handle `ReBound` + // here, this feels somewhat off. + ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => { (alt_span, "revar", format!("{region:?}")) } }; diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 2797d07976113..09313cd9738c2 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -65,8 +65,15 @@ impl<'tcx> InferCtxt<'tcx> { /// Forks the inference context, creating a new inference context with the same inference /// variables in the same state. This can be used to "branch off" many tests from the same - /// common state. Used in coherence. + /// common state. pub fn fork(&self) -> Self { + self.fork_with_intercrate(self.intercrate) + } + + /// Forks the inference context, creating a new inference context with the same inference + /// variables in the same state, except possibly changing the intercrate mode. This can be + /// used to "branch off" many tests from the same common state. Used in negative coherence. + pub fn fork_with_intercrate(&self, intercrate: bool) -> Self { Self { tcx: self.tcx, defining_use_anchor: self.defining_use_anchor, @@ -81,7 +88,7 @@ impl<'tcx> InferCtxt<'tcx> { tainted_by_errors: self.tainted_by_errors.clone(), err_count_on_creation: self.err_count_on_creation, universe: self.universe.clone(), - intercrate: self.intercrate, + intercrate, next_trait_solver: self.next_trait_solver, } } @@ -441,7 +448,11 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)), + values: PolyTraitRefs(ExpectedFound::new( + a_is_expected, + ty::Binder::dummy(a), + ty::Binder::dummy(b), + )), } } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 0e2f9ba70fecb..473a3965885fe 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -9,11 +9,9 @@ use crate::infer::canonical::{ Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, OriginalQueryValues, }; use crate::infer::InferCtxt; -use rustc_middle::ty::flags::FlagComputation; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; -use std::sync::atomic::Ordering; use rustc_data_structures::fx::FxHashMap; use rustc_index::Idx; @@ -43,8 +41,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize(value, self, self.tcx, &CanonicalizeAllFreeRegions, query_state) } @@ -62,8 +58,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize( value, self, @@ -138,8 +132,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize( value, self, @@ -179,7 +171,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { match *r { - ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r, + ty::ReLateParam(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyParam(..) => r, ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region( CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) }, @@ -202,8 +194,8 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { // // rust-lang/rust#57464: `impl Trait` can leak local // scopes (in manner violating typeck). Therefore, use - // `delay_span_bug` to allow type error over an ICE. - canonicalizer.tcx.sess.delay_span_bug( + // `span_delayed_bug` to allow type error over an ICE. + canonicalizer.tcx.sess.span_delayed_bug( rustc_span::DUMMY_SP, format!("unexpected region in query response: `{r:?}`"), ); @@ -230,9 +222,13 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { match *r { - ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReError(_) => r, + ty::ReEarlyParam(_) + | ty::ReLateParam(_) + | ty::ReErased + | ty::ReStatic + | ty::ReError(_) => r, ty::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r), - ty::RePlaceholder(..) | ty::ReLateBound(..) => { + ty::RePlaceholder(..) | ty::ReBound(..) => { // We only expect region names that the user can type. bug!("unexpected region in query response: `{:?}`", r) } @@ -343,7 +339,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(index, ..) => { + ty::ReBound(index, ..) => { if index >= self.binder_index { bug!("escaping late-bound region during canonicalization"); } else { @@ -366,9 +362,9 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } ty::ReStatic - | ty::ReEarlyBound(..) + | ty::ReEarlyParam(..) | ty::ReError(_) - | ty::ReFree(_) + | ty::ReLateParam(_) | ty::RePlaceholder(..) | ty::ReErased => self.canonicalize_mode.canonicalize_free_region(self, r), } @@ -553,8 +549,11 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { _ => {} } - let flags = FlagComputation::for_const(ct); - if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { ct } + if ct.flags().intersects(self.needs_canonical_flags) { + ct.super_fold_with(self) + } else { + ct + } } } @@ -776,7 +775,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); let br = ty::BoundRegion { var, kind: ty::BrAnon }; - ty::Region::new_late_bound(self.interner(), self.binder_index, br) + ty::Region::new_bound(self.interner(), self.binder_index, br) } /// Given a type variable `ty_var` of the given kind, first check diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index ed101082130c6..6860d0de179ea 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -460,7 +460,7 @@ impl<'tcx> InferCtxt<'tcx> { } GenericArgKind::Lifetime(result_value) => { // e.g., here `result_value` might be `'?1` in the example above... - if let ty::ReLateBound(debruijn, br) = *result_value { + if let ty::ReBound(debruijn, br) = *result_value { // ... in which case we would set `canonical_vars[0]` to `Some('static)`. // We only allow a `ty::INNERMOST` index in substitutions. @@ -552,7 +552,7 @@ impl<'tcx> InferCtxt<'tcx> { // `query_response.var_values` after applying the substitution // `result_subst`. let substituted_query_response = |index: BoundVar| -> GenericArg<'tcx> { - query_response.substitute_projected(self.tcx, &result_subst, |v| v.var_values[index]) + query_response.substitute_projected(self.tcx, result_subst, |v| v.var_values[index]) }; // Unify the original value for each variable with the value diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 2a9e20b9f8f1d..bab21bc237a79 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -35,6 +35,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{AliasRelationDirection, TyVar}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::DUMMY_SP; @@ -175,7 +176,7 @@ impl<'tcx> InferCtxt<'tcx> { &mut OriginalQueryValues::default(), ); self.tcx.check_tys_might_be_eq(canonical).map_err(|_| { - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( DUMMY_SP, format!("cannot relate consts of different types (a={a:?}, b={b:?})",), ) @@ -326,7 +327,9 @@ impl<'tcx> InferCtxt<'tcx> { ) -> RelateResult<'tcx, ty::Const<'tcx>> { let span = self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span; - let Generalization { value, needs_wf: _ } = generalize::generalize( + // FIXME(generic_const_exprs): Occurs check failures for unevaluated + // constants and generic expressions are not yet handled correctly. + let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize( self, &mut CombineDelegate { infcx: self, span, param_env }, ct, @@ -445,7 +448,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { // `'?2` and `?3` are fresh region/type inference // variables. (Down below, we will relate `a_ty <: b_ty`, // adding constraints like `'x: '?2` and `?1 <: ?3`.) - let Generalization { value: b_ty, needs_wf } = generalize::generalize( + let Generalization { value_may_be_infer: b_ty, needs_wf } = generalize::generalize( self.infcx, &mut CombineDelegate { infcx: self.infcx, @@ -457,8 +460,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { ambient_variance, )?; - debug!(?b_ty); - self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty); + // Constrain `b_vid` to the generalized type `b_ty`. + if let &ty::Infer(TyVar(b_ty_vid)) = b_ty.kind() { + self.infcx.inner.borrow_mut().type_variables().equate(b_vid, b_ty_vid); + } else { + self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty); + } if needs_wf { self.obligations.push(Obligation::new( @@ -477,19 +484,65 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { // relations wind up attributed to the same spans. We need // to associate causes/spans with each of the relations in // the stack to get this right. - match ambient_variance { - ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty), - ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty), - ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance( - ty::Contravariant, - ty::VarianceDiagInfo::default(), - a_ty, - b_ty, - ), - ty::Variance::Bivariant => { - unreachable!("no code should be generalizing bivariantly (currently)") + if b_ty.is_ty_var() { + // This happens for cases like `::Assoc == ?0`. + // We can't instantiate `?0` here as that would result in a + // cyclic type. We instead delay the unification in case + // the alias can be normalized to something which does not + // mention `?0`. + if self.infcx.next_trait_solver() { + let (lhs, rhs, direction) = match ambient_variance { + ty::Variance::Invariant => { + (a_ty.into(), b_ty.into(), AliasRelationDirection::Equate) + } + ty::Variance::Covariant => { + (a_ty.into(), b_ty.into(), AliasRelationDirection::Subtype) + } + ty::Variance::Contravariant => { + (b_ty.into(), a_ty.into(), AliasRelationDirection::Subtype) + } + ty::Variance::Bivariant => unreachable!("bivariant generalization"), + }; + self.obligations.push(Obligation::new( + self.tcx(), + self.trace.cause.clone(), + self.param_env, + ty::PredicateKind::AliasRelate(lhs, rhs, direction), + )); + } else { + match a_ty.kind() { + &ty::Alias(ty::AliasKind::Projection, data) => { + // FIXME: This does not handle subtyping correctly, we could + // instead create a new inference variable for `a_ty`, emitting + // `Projection(a_ty, a_infer)` and `a_infer <: b_ty`. + self.obligations.push(Obligation::new( + self.tcx(), + self.trace.cause.clone(), + self.param_env, + ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() }, + )) + } + // The old solver only accepts projection predicates for associated types. + ty::Alias( + ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque, + _, + ) => return Err(TypeError::CyclicTy(a_ty)), + _ => bug!("generalizated `{a_ty:?} to infer, not an alias"), + } } - }?; + } else { + match ambient_variance { + ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty), + ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty), + ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance( + ty::Contravariant, + ty::VarianceDiagInfo::default(), + a_ty, + b_ty, + ), + ty::Variance::Bivariant => unreachable!("bivariant generalization"), + }?; + } Ok(()) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e4be435fded30..ecaf9f4e16937 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -131,13 +131,13 @@ pub struct TypeErrCtxt<'a, 'tcx> { impl Drop for TypeErrCtxt<'_, '_> { fn drop(&mut self) { - if let Some(_) = self.infcx.tcx.sess.has_errors_or_delayed_span_bugs() { + if let Some(_) = self.infcx.tcx.sess.has_errors_or_span_delayed_bugs() { // ok, emitted an error. } else { self.infcx .tcx .sess - .delay_good_path_bug("used a `TypeErrCtxt` without raising an error or lint"); + .good_path_delayed_bug("used a `TypeErrCtxt` without raising an error or lint"); } } } @@ -155,7 +155,7 @@ impl TypeErrCtxt<'_, '_> { impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> { type Target = InferCtxt<'tcx>; fn deref(&self) -> &InferCtxt<'tcx> { - &self.infcx + self.infcx } } @@ -168,17 +168,17 @@ pub(super) fn note_and_explain_region<'tcx>( alt_span: Option, ) { let (description, span) = match *region { - ty::ReEarlyBound(_) | ty::ReFree(_) | ty::RePlaceholder(_) | ty::ReStatic => { + ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => { msg_span_from_named_region(tcx, region, alt_span) } ty::ReError(_) => return, // We shouldn't really be having unification failures with ReVar - // and ReLateBound though. - ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { - (format!("lifetime `{region}`"), alt_span) - } + // and ReBound though. + // + // FIXME(@lcnr): Figure out whether this is reachable and if so, why. + ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => (format!("lifetime `{region}`"), alt_span), }; emit_msg_span(err, prefix, description, span, suffix); @@ -202,7 +202,7 @@ fn msg_span_from_named_region<'tcx>( alt_span: Option, ) -> (String, Option) { match *region { - ty::ReEarlyBound(ref br) => { + ty::ReEarlyParam(ref br) => { let scope = region.free_region_binding_scope(tcx).expect_local(); let span = if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) @@ -218,7 +218,7 @@ fn msg_span_from_named_region<'tcx>( }; (text, Some(span)) } - ty::ReFree(ref fr) => { + ty::ReLateParam(ref fr) => { if !fr.bound_region.is_named() && let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) { @@ -315,7 +315,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( // Explain the region we are capturing. match *hidden_region { - ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => { + ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => { // Assuming regionck succeeded (*), we ought to always be // capturing *some* region from the fn header, and hence it // ought to be free. So under normal circumstances, we will go @@ -517,7 +517,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.tcx .sess - .delay_span_bug(self.tcx.def_span(generic_param_scope), "expected region errors") + .span_delayed_bug(self.tcx.def_span(generic_param_scope), "expected region errors") } // This method goes through all the errors and try to group certain types @@ -860,7 +860,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.suggest_boxing_for_return_impl_trait( err, ret_sp, - prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s), + prior_arms.iter().chain(std::iter::once(&arm_span)).copied(), ); } } @@ -1019,8 +1019,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { /// ``` fn cmp_type_arg( &self, - mut t1_out: &mut DiagnosticStyledString, - mut t2_out: &mut DiagnosticStyledString, + t1_out: &mut DiagnosticStyledString, + t2_out: &mut DiagnosticStyledString, path: String, sub: &'tcx [ty::GenericArg<'tcx>], other_path: String, @@ -1031,13 +1031,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let sub = self.tcx.mk_args(sub); for (i, ta) in sub.types().enumerate() { if ta == other_ty { - self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty); + self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty); return Some(()); } if let ty::Adt(def, _) = ta.kind() { let path_ = self.tcx.def_path_str(def.did()); if path_ == other_path { - self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty); + self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty); return Some(()); } } @@ -1285,7 +1285,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if lifetimes.0 != lifetimes.1 { values.0.push_highlighted(l1); values.1.push_highlighted(l2); - } else if lifetimes.0.is_late_bound() { + } else if lifetimes.0.is_bound() { values.0.push_normal(l1); values.1.push_normal(l2); } else { @@ -1667,9 +1667,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .report(diag); (false, Mismatch::Fixed("signature")) } - ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => { - (false, Mismatch::Fixed("trait")) - } + ValuePairs::PolyTraitRefs(_) => (false, Mismatch::Fixed("trait")), ValuePairs::Aliases(infer::ExpectedFound { expected, .. }) => { (false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id))) } @@ -2219,22 +2217,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::Aliases(exp_found) => self.expected_found_str(exp_found), infer::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found), infer::ExistentialProjection(exp_found) => self.expected_found_str(exp_found), - infer::TraitRefs(exp_found) => { - let pretty_exp_found = ty::error::ExpectedFound { - expected: exp_found.expected.print_only_trait_path(), - found: exp_found.found.print_only_trait_path(), - }; - match self.expected_found_str(pretty_exp_found) { - Some((expected, found, _, _)) if expected == found => { - self.expected_found_str(exp_found) - } - ret => ret, - } - } infer::PolyTraitRefs(exp_found) => { let pretty_exp_found = ty::error::ExpectedFound { - expected: exp_found.expected.print_only_trait_path(), - found: exp_found.found.print_only_trait_path(), + expected: exp_found.expected.print_trait_sugared(), + found: exp_found.found.print_trait_sugared(), }; match self.expected_found_str(pretty_exp_found) { Some((expected, found, _, _)) if expected == found => { @@ -2351,6 +2337,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let labeled_user_string = match bound_kind { GenericKind::Param(ref p) => format!("the parameter type `{p}`"), + GenericKind::Placeholder(ref p) => format!("the placeholder type `{p:?}`"), GenericKind::Alias(ref p) => match p.kind(self.tcx) { ty::AliasKind::Projection | ty::AliasKind::Inherent => { format!("the associated type `{p}`") @@ -2364,7 +2351,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span, format!("{labeled_user_string} may not live long enough"), match sub.kind() { - ty::ReEarlyBound(_) | ty::ReFree(_) if sub.has_name() => error_code!(E0309), + ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309), ty::ReStatic => error_code!(E0310), _ => error_code!(E0311), }, @@ -2372,7 +2359,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { '_explain: { let (description, span) = match sub.kind() { - ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => { + ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => { msg_span_from_named_region(self.tcx, sub, Some(span)) } _ => (format!("lifetime `{sub}`"), Some(span)), @@ -2444,18 +2431,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let suggestion = if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") }; suggs.push((sp, suggestion)) - } else { - let generics = self.tcx.hir().get_generics(suggestion_scope).unwrap(); + } else if let Some(generics) = self.tcx.hir().get_generics(suggestion_scope) { let pred = format!("{bound_kind}: {lt_name}"); - let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred,); + let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred); suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion)) + } else { + let consider = format!("{msg} `{bound_kind}: {sub}`..."); + err.help(consider); } - err.multipart_suggestion_verbose( - format!("{msg}"), - suggs, - Applicability::MaybeIncorrect, // Issue #41966 - ); + if !suggs.is_empty() { + err.multipart_suggestion_verbose( + format!("{msg}"), + suggs, + Applicability::MaybeIncorrect, // Issue #41966 + ); + } } err @@ -2511,7 +2502,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let (lifetime_def_id, lifetime_scope) = match self.tcx.is_suitable_region(lifetime) { Some(info) if !lifetime.has_name() => { - (info.boundregion.get_id().unwrap().expect_local(), info.def_id) + (info.bound_region.get_id().unwrap().expect_local(), info.def_id) } _ => return lifetime.get_name_or_anon().to_string(), }; @@ -2710,8 +2701,8 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> { a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - if (a.is_var() && b.is_free_or_static()) - || (b.is_var() && a.is_free_or_static()) + if (a.is_var() && b.is_free()) + || (b.is_var() && a.is_free()) || (a.is_var() && b.is_var()) || a == b { @@ -2764,18 +2755,20 @@ impl<'tcx> InferCtxt<'tcx> { infer::AddrOfRegion(_) => " for borrow expression".to_string(), infer::Autoref(_) => " for autoref".to_string(), infer::Coercion(_) => " for automatic coercion".to_string(), - infer::LateBoundRegion(_, br, infer::FnCall) => { + infer::BoundRegion(_, br, infer::FnCall) => { format!(" for lifetime parameter {}in function call", br_string(br)) } - infer::LateBoundRegion(_, br, infer::HigherRankedType) => { + infer::BoundRegion(_, br, infer::HigherRankedType) => { format!(" for lifetime parameter {}in generic type", br_string(br)) } - infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!( + infer::BoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!( " for lifetime parameter {}in trait containing associated type `{}`", br_string(br), self.tcx.associated_item(def_id).name ), - infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{name}`"), + infer::RegionParameterDefinition(_, name) => { + format!(" for lifetime parameter `{name}`") + } infer::UpvarRegion(ref upvar_id, _) => { let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); format!(" for capture of `{var_name}` by closure") @@ -2902,9 +2895,6 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => { "const is compatible with trait" } - ExprAssignable => "expression is assignable", - IfExpression { .. } => "`if` and `else` have incompatible types", - IfExpressionWithNoElse => "`if` missing an `else` returns `()`", MainFunctionType => "`main` function has the correct type", StartFunctionType => "`#[start]` function has the correct type", LangFunctionType(_) => "lang item function has the correct type", @@ -2925,9 +2915,6 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> { CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat", CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => "type_compat", CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => "const_compat", - ExprAssignable => "expr_assignable", - IfExpression { .. } => "if_else_different", - IfExpressionWithNoElse => "no_else", MainFunctionType => "fn_main_correct_type", StartFunctionType => "fn_start_correct_type", LangFunctionType(_) => "fn_lang_correct_type", diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 4beb51da72ced..8fe6c1b0d86fd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -374,7 +374,7 @@ impl<'tcx> InferCtxt<'tcx> { multi_suggestions, bad_label, } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), + .into_diagnostic(self.tcx.sess.diagnostic()), TypeAnnotationNeeded::E0283 => AmbiguousImpl { span, source_kind, @@ -384,7 +384,7 @@ impl<'tcx> InferCtxt<'tcx> { multi_suggestions, bad_label, } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), + .into_diagnostic(self.tcx.sess.diagnostic()), TypeAnnotationNeeded::E0284 => AmbiguousReturn { span, source_kind, @@ -394,7 +394,7 @@ impl<'tcx> InferCtxt<'tcx> { multi_suggestions, bad_label, } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), + .into_diagnostic(self.tcx.sess.diagnostic()), } } } @@ -419,7 +419,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return self.bad_inference_failure_err(failure_span, arg_data, error_code); }; - let mut local_visitor = FindInferSourceVisitor::new(&self, typeck_results, arg); + let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg); if let Some(body_id) = self.tcx.hir().maybe_body_owned_by( self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(), ) { @@ -581,7 +581,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { multi_suggestions, bad_label: None, } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), + .into_diagnostic(self.tcx.sess.diagnostic()), TypeAnnotationNeeded::E0283 => AmbiguousImpl { span, source_kind, @@ -591,7 +591,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { multi_suggestions, bad_label: None, } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), + .into_diagnostic(self.tcx.sess.diagnostic()), TypeAnnotationNeeded::E0284 => AmbiguousReturn { span, source_kind, @@ -601,7 +601,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { multi_suggestions, bad_label: None, } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic), + .into_diagnostic(self.tcx.sess.diagnostic()), } } } @@ -1087,7 +1087,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { Box::new(segment.into_iter()) } - hir::QPath::LangItem(_, _, _) => Box::new(iter::empty()), + hir::QPath::LangItem(_, _) => Box::new(iter::empty()), } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index 1a60bab18dbda..f56d5d7d345b2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -70,9 +70,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let anon_reg_sub = self.tcx().is_suitable_region(sub)?; let scope_def_id_sup = anon_reg_sup.def_id; - let bregion_sup = anon_reg_sup.boundregion; + let bregion_sup = anon_reg_sup.bound_region; let scope_def_id_sub = anon_reg_sub.def_id; - let bregion_sub = anon_reg_sub.boundregion; + let bregion_sub = anon_reg_sub.bound_region; let ty_sup = find_anon_type(self.tcx(), sup, &bregion_sup)?; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 0df417d095013..ab928232d7451 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -26,7 +26,7 @@ pub fn find_anon_type<'tcx>( br: &ty::BoundRegionKind, ) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> { let anon_reg = tcx.is_suitable_region(region)?; - let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id); + let hir_id = tcx.local_def_id_to_hir_id(anon_reg.def_id); let fn_sig = tcx.hir().get(hir_id).fn_sig()?; fn_sig @@ -96,7 +96,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { } } - hir::TyKind::Ref(ref lifetime, _) => { + hir::TyKind::Ref(lifetime, _) => { // the lifetime of the Ref let hir_id = lifetime.hir_id; match (self.tcx.named_bound_var(hir_id), self.bound_region) { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index 6901955af65fd..df7907e1fd3af 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -81,7 +81,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { for matching_def_id in v.0 { let mut hir_v = super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id); - hir_v.visit_ty(&impl_self_ty); + hir_v.visit_ty(impl_self_ty); } if traits.is_empty() { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index c38e5b8cd09e5..d98ca995d71d4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -197,11 +197,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { value_pairs: &ValuePairs<'tcx>, ) -> Option> { let (expected_args, found_args, trait_def_id) = match value_pairs { - ValuePairs::TraitRefs(ExpectedFound { expected, found }) - if expected.def_id == found.def_id => - { - (expected.args, found.args, expected.def_id) - } ValuePairs::PolyTraitRefs(ExpectedFound { expected, found }) if expected.def_id() == found.def_id() => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index e2be6cf4280a1..81154415c1e54 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -78,7 +78,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { has_impl_path, impl_path, }); - if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { + if self.find_impl_on_dyn_trait(&mut err, param.param_ty, ctxt) { let reported = err.emit(); return Some(reported); } else { @@ -204,7 +204,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { && let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a // `'static` lifetime when called as a method on a binding: `bar.qux()`. - && self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) + && self.find_impl_on_dyn_trait(&mut err, param.param_ty, ctxt) { override_error_code = Some(ctxt.assoc_item.name); } @@ -530,7 +530,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { for found_did in found_dids { let mut traits = vec![]; let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); - hir_v.visit_ty(&self_ty); + hir_v.visit_ty(self_ty); for &span in &traits { let subdiag = DynTraitConstraintSuggestion { span, ident }; subdiag.add_to_diagnostic(err); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index cb51254a14b0c..b16d5c509e00c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ty::AssocKind::Fn => { let hir = self.tcx().hir(); if let Some(hir_id) = - assoc_item.def_id.as_local().map(|id| hir.local_def_id_to_hir_id(id)) + assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id)) { if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) { visitor.visit_fn_decl(decl); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index be6d1a3750cdb..155c03560256a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -41,8 +41,8 @@ pub fn find_param_with_region<'tcx>( replace_region: Region<'tcx>, ) -> Option> { let (id, bound_region) = match *anon_region { - ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), - ty::ReEarlyBound(ebr) => { + ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region), + ty::ReEarlyParam(ebr) => { (tcx.parent(ebr.def_id), ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name)) } _ => return None, // not a free region @@ -50,7 +50,7 @@ pub fn find_param_with_region<'tcx>( let hir = &tcx.hir(); let def_id = id.as_local()?; - let hir_id = hir.local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); // FIXME: use def_kind // Don't perform this on closures @@ -161,7 +161,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { && self .tcx() .opt_associated_item(scope_def_id.to_def_id()) - .map(|i| i.fn_has_self_parameter) - == Some(true) + .is_some_and(|i| i.fn_has_self_parameter) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 8d3cd23b7fa51..fed76cd65cf09 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -63,7 +63,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .add_to_diagnostic(err); } infer::CheckAssociatedTypeBounds { ref parent, .. } => { - self.note_region_origin(err, &parent); + self.note_region_origin(err, parent); } infer::AscribeUserTypeProvePredicate(span) => { RegionOriginNote::Plain { @@ -140,7 +140,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span, notes: reference_valid.into_iter().chain(content_valid).collect(), } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) + .into_diagnostic(self.tcx.sess.diagnostic()) } infer::RelateObjectBound(span) => { let object_valid = note_and_explain::RegionExplanation::new( @@ -161,7 +161,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span, notes: object_valid.into_iter().chain(pointer_valid).collect(), } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) + .into_diagnostic(self.tcx.sess.diagnostic()) } infer::RelateParamBound(span, ty, opt_span) => { let prefix = match *sub { @@ -177,7 +177,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.tcx, sub, opt_span, prefix, suffix, ); FulfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) + .into_diagnostic(self.tcx.sess.diagnostic()) } infer::RelateRegionParamBound(span) => { let param_instantiated = note_and_explain::RegionExplanation::new( @@ -198,7 +198,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span, notes: param_instantiated.into_iter().chain(param_must_outlive).collect(), } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) + .into_diagnostic(self.tcx.sess.diagnostic()) } infer::ReferenceOutlivesReferent(ty, span) => { let pointer_valid = note_and_explain::RegionExplanation::new( @@ -220,7 +220,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ty: self.resolve_vars_if_possible(ty), notes: pointer_valid.into_iter().chain(data_valid).collect(), } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) + .into_diagnostic(self.tcx.sess.diagnostic()) } infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { let mut err = self.report_extra_impl_obligation( @@ -281,7 +281,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span, notes: instantiated.into_iter().chain(must_outlive).collect(), } - .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) + .into_diagnostic(self.tcx.sess.diagnostic()) } }; if sub.is_error() || sup.is_error() { diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index a8ae43d52978d..b93fe02aaeab0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -87,7 +87,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { | (ty::Alias(ty::Projection, proj), ty::Param(p)) if !tcx.is_impl_trait_in_trait(proj.def_id) => { - let parent = tcx.generics_of(body_owner_def_id) + let parent = tcx + .generics_of(body_owner_def_id) .opt_type_param(p, tcx) .and_then(|param| { let p_def_id = param.def_id; @@ -104,7 +105,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); } p_def_id.as_local().and_then(|id| { - let local_id = tcx.hir().local_def_id_to_hir_id(id); + let local_id = tcx.local_def_id_to_hir_id(id); let generics = tcx.hir().find_parent(local_id)?.generics()?; Some((id, generics)) }) diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index fe18d00293aa3..aa5fe6d3f56cc 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -511,7 +511,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } let mut visitor = IfVisitor { err_span: span, found_if: false, result: false }; - visitor.visit_body(&body); + visitor.visit_body(body); if visitor.result { return Some(TypeErrorAdditionalDiags::AddLetForLetChains { span: span.shrink_to_lo(), @@ -572,8 +572,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let ty::Ref(expected_region, _, _) = expected.kind() && let ty::Ref(found_region, _, _) = found.kind() - && expected_region.is_late_bound() - && !found_region.is_late_bound() + && expected_region.is_bound() + && !found_region.is_bound() && let hir::TyKind::Infer = arg_hir.kind { // If the expected region is late bound, the found region is not, and users are asking compiler @@ -636,10 +636,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return None; } let last_stmt = blk.stmts.last()?; - let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else { + let hir::StmtKind::Semi(last_expr) = last_stmt.kind else { return None; }; - let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?; + let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(last_expr)?; let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) { _ if last_expr_ty.references_error() => return None, _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => { diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index ed1a2a1171909..0dde3082d48dc 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -22,8 +22,8 @@ impl<'a, 'tcx> RegionRelations<'a, 'tcx> { Self { tcx, free_regions } } - pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { - self.free_regions.lub_free_regions(self.tcx, r_a, r_b) + pub fn lub_param_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { + self.free_regions.lub_param_regions(self.tcx, r_a, r_b) } } @@ -59,7 +59,7 @@ impl<'tcx> FreeRegionMap<'tcx> { r_a: Region<'tcx>, r_b: Region<'tcx>, ) -> bool { - assert!(r_a.is_free_or_static() && r_b.is_free_or_static()); + assert!(r_a.is_free() && r_b.is_free()); let re_static = tcx.lifetimes.re_static; if self.check_relation(re_static, r_b) { // `'a <= 'static` is always true, and not stored in the @@ -80,15 +80,15 @@ impl<'tcx> FreeRegionMap<'tcx> { /// cases, this is more conservative than necessary, in order to /// avoid making arbitrary choices. See /// `TransitiveRelation::postdom_upper_bound` for more details. - pub fn lub_free_regions( + pub fn lub_param_regions( &self, tcx: TyCtxt<'tcx>, r_a: Region<'tcx>, r_b: Region<'tcx>, ) -> Region<'tcx> { - debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b); - assert!(r_a.is_free()); - assert!(r_b.is_free()); + debug!("lub_param_regions(r_a={:?}, r_b={:?})", r_a, r_b); + assert!(r_a.is_param()); + assert!(r_b.is_param()); let result = if r_a == r_b { r_a } else { @@ -97,7 +97,7 @@ impl<'tcx> FreeRegionMap<'tcx> { Some(r) => r, } }; - debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result); + debug!("lub_param_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result); result } } diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 35204478c54dd..11ab86277c1b1 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -110,13 +110,13 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(..) => { + ty::ReBound(..) => { // leave bound regions alone r } - ty::ReEarlyBound(..) - | ty::ReFree(_) + ty::ReEarlyParam(..) + | ty::ReLateParam(_) | ty::ReVar(_) | ty::RePlaceholder(..) | ty::ReStatic diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index 7e878ac06c7f2..8ca97ae1b8e5d 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -187,7 +187,7 @@ impl<'a, 'tcx> TypeFolder> for InferenceFudger<'a, 'tcx> { if self.type_vars.0.contains(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. - let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize; + let idx = vid.as_usize() - self.type_vars.0.start.as_usize(); let origin = self.type_vars.1[idx]; self.infcx.next_ty_var(origin) } else { @@ -236,7 +236,7 @@ impl<'a, 'tcx> TypeFolder> for InferenceFudger<'a, 'tcx> { if self.const_vars.0.contains(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. - let idx = (vid.index() - self.const_vars.0.start.index()) as usize; + let idx = vid.index() - self.const_vars.0.start.index(); let origin = self.const_vars.1[idx]; self.infcx.next_const_var(ct.ty(), origin) } else { diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs index 17fe3aa7b44c1..4b4017cec57ab 100644 --- a/compiler/rustc_infer/src/infer/generalize.rs +++ b/compiler/rustc_infer/src/infer/generalize.rs @@ -1,13 +1,16 @@ +use std::mem; + use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; -use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::visit::MaxUniverse; +use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; use rustc_span::Span; use crate::infer::nll_relate::TypeRelatingDelegate; -use crate::infer::type_variable::TypeVariableValue; +use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue}; use crate::infer::{InferCtxt, RegionVariableOrigin}; /// Attempts to generalize `term` for the type variable `for_vid`. @@ -38,27 +41,30 @@ pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into> root_vid, for_universe, root_term: term.into(), + in_alias: false, needs_wf: false, cache: Default::default(), }; assert!(!term.has_escaping_bound_vars()); - let value = generalizer.relate(term, term)?; + let value_may_be_infer = generalizer.relate(term, term)?; let needs_wf = generalizer.needs_wf; - Ok(Generalization { value, needs_wf }) + Ok(Generalization { value_may_be_infer, needs_wf }) } /// Abstracts the handling of region vars between HIR and MIR/NLL typechecking /// in the generalizer code. -pub trait GeneralizerDelegate<'tcx> { +pub(super) trait GeneralizerDelegate<'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx>; fn forbid_inference_vars() -> bool; + fn span(&self) -> Span; + fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>; } -pub struct CombineDelegate<'cx, 'tcx> { +pub(super) struct CombineDelegate<'cx, 'tcx> { pub infcx: &'cx InferCtxt<'tcx>, pub param_env: ty::ParamEnv<'tcx>, pub span: Span, @@ -73,6 +79,10 @@ impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> { false } + fn span(&self) -> Span { + self.span + } + fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { // FIXME: This is non-ideal because we don't give a // very descriptive origin for this region variable. @@ -93,6 +103,10 @@ where >::forbid_inference_vars() } + fn span(&self) -> Span { + >::span(&self) + } + fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { >::generalize_existential(self, universe) } @@ -139,6 +153,13 @@ struct Generalizer<'me, 'tcx, D> { cache: SsoHashMap, Ty<'tcx>>, + /// This is set once we're generalizing the arguments of an alias. + /// + /// This is necessary to correctly handle + /// `::Assoc>::Assoc == ?0`. This equality can + /// hold by either normalizing the outer or the inner associated type. + in_alias: bool, + /// See the field `needs_wf` in `Generalization`. needs_wf: bool, } @@ -193,7 +214,7 @@ where opt_variances, a_subst, b_subst, - true, + false, ) } } @@ -309,6 +330,44 @@ where } } + ty::Alias(kind, data) => { + // An occurs check failure inside of an alias does not mean + // that the types definitely don't unify. We may be able + // to normalize the alias after all. + // + // We handle this by lazily equating the alias and generalizing + // it to an inference variable. + let is_nested_alias = mem::replace(&mut self.in_alias, true); + let result = match self.relate(data, data) { + Ok(data) => Ok(Ty::new_alias(self.tcx(), kind, data)), + Err(e) => { + if is_nested_alias { + return Err(e); + } else { + let mut visitor = MaxUniverse::new(); + t.visit_with(&mut visitor); + let infer_replacement_is_complete = + self.for_universe.can_name(visitor.max_universe()) + && !t.has_escaping_bound_vars(); + if !infer_replacement_is_complete { + warn!("may incompletely handle alias type: {t:?}"); + } + + debug!("generalization failure in alias"); + Ok(self.infcx.next_ty_var_in_universe( + TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: self.delegate.span(), + }, + self.for_universe, + )) + } + } + }; + self.in_alias = is_nested_alias; + result + } + _ => relate::structurally_relate_tys(self, t, t), }?; @@ -327,7 +386,7 @@ where match *r { // Never make variables for regions bound within the type itself, // nor for erased regions. - ty::ReLateBound(..) | ty::ReErased => { + ty::ReBound(..) | ty::ReErased => { return Ok(r); } @@ -340,8 +399,8 @@ where ty::RePlaceholder(..) | ty::ReVar(..) | ty::ReStatic - | ty::ReEarlyBound(..) - | ty::ReFree(..) => { + | ty::ReEarlyParam(..) + | ty::ReLateParam(..) => { // see common code below } } @@ -456,8 +515,16 @@ where /// not only the generalized type, but also a bool flag /// indicating whether further WF checks are needed. #[derive(Debug)] -pub struct Generalization { - pub value: T, +pub(super) struct Generalization { + /// When generalizing `::Assoc` or + /// `::Assoc>>::Assoc` + /// for `?0` generalization returns an inference + /// variable. + /// + /// This has to be handled wotj care as it can + /// otherwise very easily result in infinite + /// recursion. + pub(super) value_may_be_infer: T, /// If true, then the generalized type may not be well-formed, /// even if the source type is well-formed, so we should add an @@ -484,5 +551,5 @@ pub struct Generalization { /// will force the calling code to check that `WF(Foo)` /// holds, which in turn implies that `?C::Item == ?D`. So once /// `?C` is constrained, that should suffice to restrict `?D`. - pub needs_wf: bool, + pub(super) needs_wf: bool, } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index bee0a978ad04f..b6e86e2b676d0 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -16,8 +16,8 @@ use rustc_data_structures::intern::Interned; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::ty::{ReEarlyBound, ReErased, ReError, ReFree, ReStatic}; -use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar}; +use rustc_middle::ty::{ReBound, RePlaceholder, ReVar}; +use rustc_middle::ty::{ReEarlyParam, ReErased, ReError, ReLateParam, ReStatic}; use rustc_middle::ty::{Region, RegionVid}; use rustc_span::Span; use std::fmt; @@ -378,7 +378,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // so it doesn't really matter if it's shorter or longer than an empty region ReError(_) => false, - ReLateBound(..) | ReErased => { + ReBound(..) | ReErased => { bug!("cannot relate region: {:?}", a); } @@ -390,7 +390,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { ); } - ReStatic | ReEarlyBound(_) | ReFree(_) => { + ReStatic | ReEarlyParam(_) | ReLateParam(_) => { // nothing lives longer than `'static` // All empty regions are less than early-bound, free, @@ -411,7 +411,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // so it doesn't really matter if it's shorter or longer than an empty region ReError(_) => false, - ReLateBound(..) | ReErased => { + ReBound(..) | ReErased => { bug!("cannot relate region: {:?}", b); } @@ -423,9 +423,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { ); } - ReStatic | ReEarlyBound(_) | ReFree(_) => { + ReStatic | ReEarlyParam(_) | ReLateParam(_) => { // nothing lives longer than `'static` - // All empty regions are less than early-bound, free, + // All empty regions are less than early-bound, late-bound, // and scope regions. true } @@ -450,8 +450,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // Check for the case where we know that `'b: 'static` -- in that case, // `a <= b` for all `a`. - let b_free_or_static = b.is_free_or_static(); - if b_free_or_static && sub_free_regions(tcx.lifetimes.re_static, b) { + if b.is_free() && sub_free_regions(tcx.lifetimes.re_static, b) { return true; } @@ -460,8 +459,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // `lub` relationship defined below, since sometimes the "lub" // is actually the `postdom_upper_bound` (see // `TransitiveRelation` for more details). - let a_free_or_static = a.is_free_or_static(); - if a_free_or_static && b_free_or_static { + if a.is_free() && b.is_free() { return sub_free_regions(a, b); } @@ -478,7 +476,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { #[instrument(level = "trace", skip(self), ret)] fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { match (*a, *b) { - (ReLateBound(..), _) | (_, ReLateBound(..)) | (ReErased, _) | (_, ReErased) => { + (ReBound(..), _) | (_, ReBound(..)) | (ReErased, _) | (_, ReErased) => { bug!("cannot relate region: LUB({:?}, {:?})", a, b); } @@ -501,8 +499,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { self.tcx().lifetimes.re_static } - (ReEarlyBound(_) | ReFree(_), ReEarlyBound(_) | ReFree(_)) => { - self.region_rels.lub_free_regions(a, b) + (ReEarlyParam(_) | ReLateParam(_), ReEarlyParam(_) | ReLateParam(_)) => { + self.region_rels.lub_param_regions(a, b) } // For these types, we cannot define any additional @@ -683,17 +681,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { for constraint in self.data.constraints.keys() { match *constraint { Constraint::VarSubVar(a_id, b_id) => { - graph.add_edge( - NodeIndex(a_id.index() as usize), - NodeIndex(b_id.index() as usize), - *constraint, - ); + graph.add_edge(NodeIndex(a_id.index()), NodeIndex(b_id.index()), *constraint); } Constraint::RegSubVar(_, b_id) => { - graph.add_edge(dummy_source, NodeIndex(b_id.index() as usize), *constraint); + graph.add_edge(dummy_source, NodeIndex(b_id.index()), *constraint); } Constraint::VarSubReg(a_id, _) => { - graph.add_edge(NodeIndex(a_id.index() as usize), dummy_sink, *constraint); + graph.add_edge(NodeIndex(a_id.index()), dummy_sink, *constraint); } Constraint::RegSubReg(..) => { // this would be an edge from `dummy_source` to @@ -723,13 +717,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { return; } - // We place free regions first because we are special casing - // SubSupConflict(ReFree, ReFree) when reporting error, and so + // We place late-bound regions first because we are special casing + // SubSupConflict(ReLateParam, ReLateParam) when reporting error, and so // the user will more likely get a specific suggestion. fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 { match *x.region { - ReEarlyBound(_) => 0, - ReFree(_) => 1, + ReEarlyParam(_) => 0, + ReLateParam(_) => 1, _ => 2, } } @@ -804,7 +798,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // Errors in earlier passes can yield error variables without // resolution errors here; delay ICE in favor of those errors. - self.tcx().sess.delay_span_bug( + self.tcx().sess.span_delayed_bug( self.var_infos[node_idx].origin.span(), format!( "collect_error_for_expanding_node() could not find \ @@ -880,7 +874,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { ) { debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir); - let source_node_index = NodeIndex(source_vid.index() as usize); + let source_node_index = NodeIndex(source_vid.index()); for (_, edge) in graph.adjacent_edges(source_node_index, dir) { match edge.data { Constraint::VarSubVar(from_vid, to_vid) => { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4ee897ffe9843..32c09e491c7ed 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,7 +1,7 @@ pub use self::at::DefineOpaqueTypes; pub use self::freshen::TypeFreshener; pub use self::lexical_region_resolve::RegionResolutionError; -pub use self::LateBoundRegionConversionTime::*; +pub use self::BoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; @@ -32,7 +32,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BoundVarReplacerDelegate; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::relate::RelateResult; -use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::visit::TypeVisitableExt; pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt}; use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; @@ -384,7 +384,6 @@ pub enum ValuePairs<'tcx> { Regions(ExpectedFound>), Terms(ExpectedFound>), Aliases(ExpectedFound>), - TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), PolySigs(ExpectedFound>), ExistentialTraitRef(ExpectedFound>), @@ -472,9 +471,9 @@ impl<'tcx> SubregionOrigin<'tcx> { } } -/// Times when we replace late-bound regions with variables: +/// Times when we replace bound regions with existentials: #[derive(Clone, Copy, Debug)] -pub enum LateBoundRegionConversionTime { +pub enum BoundRegionConversionTime { /// when a fn is called FnCall, @@ -508,11 +507,14 @@ pub enum RegionVariableOrigin { Coercion(Span), /// Region variables created as the values for early-bound regions. - EarlyBoundRegion(Span, Symbol), + /// + /// FIXME(@lcnr): This can also store a `DefId`, similar to + /// `TypeVariableOriginKind::TypeParameterDefinition`. + RegionParameterDefinition(Span, Symbol), - /// Region variables created for bound regions - /// in a function or method that is called. - LateBoundRegion(Span, ty::BoundRegionKind, LateBoundRegionConversionTime), + /// Region variables created when instantiating a binder with + /// existential variables, e.g. when calling a function or method. + BoundRegion(Span, ty::BoundRegionKind, BoundRegionConversionTime), UpvarRegion(ty::UpvarId, Span), @@ -903,12 +905,14 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) } - pub fn can_sub(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool + pub fn can_sub(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool where T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); - self.probe(|_| self.at(origin, param_env).sub(DefineOpaqueTypes::No, a, b).is_ok()) + self.probe(|_| { + self.at(origin, param_env).sub(DefineOpaqueTypes::No, expected, actual).is_ok() + }) } pub fn can_eq(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool @@ -1165,7 +1169,7 @@ impl<'tcx> InferCtxt<'tcx> { GenericParamDefKind::Lifetime => { // Create a region inference variable for the given // region parameter definition. - self.next_region_var(EarlyBoundRegion(span, param.name)).into() + self.next_region_var(RegionParameterDefinition(span, param.name)).into() } GenericParamDefKind::Type { .. } => { // Create a type inference variable for the given @@ -1401,17 +1405,6 @@ impl<'tcx> InferCtxt<'tcx> { value.fold_with(&mut r) } - /// Returns the first unresolved type or const variable contained in `T`. - pub fn first_unresolved_const_or_ty_var( - &self, - value: &T, - ) -> Option<(ty::Term<'tcx>, Option)> - where - T: TypeVisitable>, - { - value.visit_with(&mut resolve::UnresolvedTypeOrConstFinder::new(self)).break_value() - } - pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result, ty::UniverseIndex> { match self.inner.borrow_mut().const_unification_table().probe_value(vid).val { ConstVariableValue::Known { value } => Ok(value), @@ -1440,7 +1433,7 @@ impl<'tcx> InferCtxt<'tcx> { let guar = self .tcx .sess - .delay_span_bug(DUMMY_SP, format!("`{value:?}` is not fully resolved")); + .span_delayed_bug(DUMMY_SP, format!("`{value:?}` is not fully resolved")); Ok(self.tcx.fold_regions(value, |re, _| { if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re } })) @@ -1456,13 +1449,13 @@ impl<'tcx> InferCtxt<'tcx> { // variables in the current universe. // // Use this method if you'd like to find some substitution of the binder's - // variables (e.g. during a method call). If there isn't a [`LateBoundRegionConversionTime`] + // variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`] // that corresponds to your use case, consider whether or not you should // use [`InferCtxt::instantiate_binder_with_placeholders`] instead. pub fn instantiate_binder_with_fresh_vars( &self, span: Span, - lbrct: LateBoundRegionConversionTime, + lbrct: BoundRegionConversionTime, value: ty::Binder<'tcx, T>, ) -> T where @@ -1475,7 +1468,7 @@ impl<'tcx> InferCtxt<'tcx> { struct ToFreshVars<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, span: Span, - lbrct: LateBoundRegionConversionTime, + lbrct: BoundRegionConversionTime, map: FxHashMap>, } @@ -1485,7 +1478,7 @@ impl<'tcx> InferCtxt<'tcx> { .entry(br.var) .or_insert_with(|| { self.infcx - .next_region_var(LateBoundRegion(self.span, br.kind, self.lbrct)) + .next_region_var(BoundRegion(self.span, br.kind, self.lbrct)) .into() }) .expect_region() @@ -2041,8 +2034,8 @@ impl RegionVariableOrigin { | AddrOfRegion(a) | Autoref(a) | Coercion(a) - | EarlyBoundRegion(a, ..) - | LateBoundRegion(a, ..) + | RegionParameterDefinition(a, ..) + | BoundRegion(a, ..) | UpvarRegion(_, a) => a, Nll(..) => bug!("NLL variable used with `span`"), } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index c80491643913c..d707c30206df9 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -113,9 +113,6 @@ pub trait TypeRelatingDelegate<'tcx> { fn forbid_inference_vars() -> bool; } -#[derive(Copy, Clone)] -struct UniversallyQuantified(bool); - impl<'me, 'tcx, D> TypeRelating<'me, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, @@ -217,13 +214,17 @@ where } fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> { - let Generalization { value: ty, needs_wf: _ } = generalize::generalize( + let Generalization { value_may_be_infer: ty, needs_wf: _ } = generalize::generalize( self.infcx, &mut self.delegate, ty, for_vid, self.ambient_variance, )?; + + if ty.is_ty_var() { + span_bug!(self.delegate.span(), "occurs check failure in MIR typeck"); + } Ok(ty) } @@ -497,7 +498,7 @@ where // shouldn't ever fail. Instead, it unconditionally emits an // alias-relate goal. assert!(!self.infcx.next_trait_solver()); - self.tcx().sess.delay_span_bug( + self.tcx().sess.span_delayed_bug( self.delegate.span(), "failure to relate an opaque to itself should result in an error later on", ); @@ -555,7 +556,7 @@ where match b.kind() { ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { // Forbid inference variables in the RHS. - self.infcx.tcx.sess.delay_span_bug( + self.infcx.tcx.sess.span_delayed_bug( self.delegate.span(), format!("unexpected inference var {b:?}",), ); diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 7a5dec22fe049..82ab19550536c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -374,7 +374,7 @@ impl<'tcx> InferCtxt<'tcx> { /// in its defining scope. #[instrument(skip(self), level = "trace", ret)] pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { - let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id); let parent_def_id = match self.defining_use_anchor { DefiningAnchor::Bubble | DefiningAnchor::Error => return None, DefiningAnchor::Bind(bind) => bind, @@ -432,7 +432,7 @@ where fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { // ignore bound regions, keep visiting - ty::ReLateBound(_, _) => ControlFlow::Continue(()), + ty::ReBound(_, _) => ControlFlow::Continue(()), _ => { (self.op)(r); ControlFlow::Continue(()) @@ -447,7 +447,7 @@ where } match ty.kind() { - ty::Closure(_, ref args) => { + ty::Closure(_, args) => { // Skip lifetime parameters of the enclosing item(s) for upvar in args.as_closure().upvar_tys() { @@ -456,7 +456,7 @@ where args.as_closure().sig_as_fn_ptr_ty().visit_with(self); } - ty::Coroutine(_, ref args, _) => { + ty::Coroutine(_, args, _) => { // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. @@ -468,7 +468,7 @@ where args.as_coroutine().resume_ty().visit_with(self); } - ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref args, .. }) => { + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // Skip lifetime parameters that are not captures. let variances = self.tcx.variances_of(*def_id); @@ -575,7 +575,7 @@ impl<'tcx> InferCtxt<'tcx> { .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span }); if let Some(prev) = prev { obligations.extend( - self.at(&cause, param_env) + self.at(cause, param_env) .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? .obligations, ); @@ -671,7 +671,7 @@ impl<'tcx> InferCtxt<'tcx> { /// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. /// For the above example, this function returns `true` for `f1` and `false` for `f2`. fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool { - let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let mut hir_id = tcx.local_def_id_to_hir_id(def_id); // Named opaque types can be defined by any siblings or children of siblings. let scope = tcx.hir().get_defining_scope(opaque_hir_id); diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index a737761ba2282..715006a50d3da 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -41,7 +41,7 @@ impl<'tcx> Drop for OpaqueTypeStorage<'tcx> { fn drop(&mut self) { if !self.opaque_types.is_empty() { ty::tls::with(|tcx| { - tcx.sess.delay_span_bug(DUMMY_SP, format!("{:?}", self.opaque_types)) + tcx.sess.span_delayed_bug(DUMMY_SP, format!("{:?}", self.opaque_types)) }); } } diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 38819e8ad8a62..45df22d44e810 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -11,6 +11,7 @@ use smallvec::{smallvec, SmallVec}; pub enum Component<'tcx> { Region(ty::Region<'tcx>), Param(ty::ParamTy), + Placeholder(ty::PlaceholderType), UnresolvedInferenceVariable(ty::InferTy), // Projections like `T::Foo` are tricky because a constraint like @@ -97,12 +98,12 @@ fn compute_components<'tcx>( compute_components(tcx, element, out, visited); } - ty::Closure(_, ref args) => { + ty::Closure(_, args) => { let tupled_ty = args.as_closure().tupled_upvars_ty(); compute_components(tcx, tupled_ty, out, visited); } - ty::Coroutine(_, ref args, _) => { + ty::Coroutine(_, args, _) => { // Same as the closure case let tupled_ty = args.as_coroutine().tupled_upvars_ty(); compute_components(tcx, tupled_ty, out, visited); @@ -120,6 +121,10 @@ fn compute_components<'tcx>( out.push(Component::Param(p)); } + ty::Placeholder(p) => { + out.push(Component::Placeholder(p)); + } + // For projections, we prefer to generate an obligation like // `>::Foo: 'a`, because this gives the // regionck more ways to prove that it holds. However, @@ -176,7 +181,6 @@ fn compute_components<'tcx>( ty::Tuple(..) | // ... ty::FnPtr(_) | // OutlivesFunction (*) ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*) - ty::Placeholder(..) | ty::Bound(..) | ty::Error(_) => { // (*) Function pointers and trait objects are both binders. @@ -213,8 +217,8 @@ pub(super) fn compute_alias_components_recursive<'tcx>( compute_components(tcx, ty, out, visited); } GenericArgKind::Lifetime(lt) => { - // Ignore late-bound regions. - if !lt.is_late_bound() { + // Ignore higher ranked regions. + if !lt.is_bound() { out.push(Component::Region(lt)); } } @@ -241,8 +245,8 @@ fn compute_components_recursive<'tcx>( compute_components(tcx, ty, out, visited); } GenericArgKind::Lifetime(lt) => { - // Ignore late-bound regions. - if !lt.is_late_bound() { + // Ignore higher ranked regions. + if !lt.is_bound() { out.push(Component::Region(lt)); } } diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 47e3dd762b08b..f8dbfdde30c50 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -138,8 +138,8 @@ impl<'tcx> OutlivesEnvironmentBuilder<'tcx> { } OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) { ( - ty::ReStatic | ty::ReEarlyBound(_) | ty::ReFree(_), - ty::ReStatic | ty::ReEarlyBound(_) | ty::ReFree(_), + ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), + ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), ) => self.region_relation.add(r_a, r_b), (ty::ReError(_), _) | (_, ty::ReError(_)) => {} // FIXME(#109628): We shouldn't have existential variables in implied bounds. diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index 398ac94ee3685..52cc107ae52c3 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -37,7 +37,7 @@ where fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { // ignore bound regions, keep visiting - ty::ReLateBound(_, _) => ControlFlow::Continue(()), + ty::ReBound(_, _) => ControlFlow::Continue(()), _ => { (self.op)(r); ControlFlow::Continue(()) @@ -112,7 +112,9 @@ where }; for (idx, s) in args.iter().enumerate() { - if variances.map(|variances| variances[idx]) != Some(ty::Variance::Bivariant) { + if variances.map(|variances| variances[idx]) + != Some(ty::Variance::Bivariant) + { s.visit_with(self)?; } } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index f36802e128435..395830d937b80 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -136,7 +136,7 @@ impl<'tcx> InferCtxt<'tcx> { let outlives = &mut TypeOutlives::new( self, self.tcx, - &outlives_env.region_bound_pairs(), + outlives_env.region_bound_pairs(), None, outlives_env.param_env, ); @@ -243,15 +243,18 @@ where Component::Param(param_ty) => { self.param_ty_must_outlive(origin, region, *param_ty); } + Component::Placeholder(placeholder_ty) => { + self.placeholder_ty_must_outlive(origin, region, *placeholder_ty); + } Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty), Component::EscapingAlias(subcomponents) => { - self.components_must_outlive(origin, &subcomponents, region, category); + self.components_must_outlive(origin, subcomponents, region, category); } Component::UnresolvedInferenceVariable(v) => { // ignore this, we presume it will yield an error // later, since if a type variable is not resolved by // this point it never will be - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( origin.span(), format!("unresolved inference variable in outlives: {v:?}"), ); @@ -267,10 +270,28 @@ where region: ty::Region<'tcx>, param_ty: ty::ParamTy, ) { - let verify_bound = self.verify_bound.param_bound(param_ty); + let verify_bound = self.verify_bound.param_or_placeholder_bound(param_ty.to_ty(self.tcx)); self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound); } + #[instrument(level = "debug", skip(self))] + fn placeholder_ty_must_outlive( + &mut self, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region<'tcx>, + placeholder_ty: ty::PlaceholderType, + ) { + let verify_bound = self + .verify_bound + .param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty)); + self.delegate.push_verify( + origin, + GenericKind::Placeholder(placeholder_ty), + region, + verify_bound, + ); + } + #[instrument(level = "debug", skip(self))] fn alias_ty_must_outlive( &mut self, diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index 6f973ee37f5e9..959b34aa14574 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -48,7 +48,7 @@ pub fn extract_verify_if_eq<'tcx>( let verify_if_eq = verify_if_eq_b.skip_binder(); m.relate(verify_if_eq.ty, test_ty).ok()?; - if let ty::RegionKind::ReLateBound(depth, br) = verify_if_eq.bound.kind() { + if let ty::RegionKind::ReBound(depth, br) = verify_if_eq.bound.kind() { assert!(depth == ty::INNERMOST); match m.map.get(&br) { Some(&r) => Some(r), @@ -177,7 +177,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> { value: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { debug!("self.pattern_depth = {:?}", self.pattern_depth); - if let ty::RegionKind::ReLateBound(depth, br) = pattern.kind() + if let ty::RegionKind::ReBound(depth, br) = pattern.kind() && depth == self.pattern_depth { self.bind(br, value) diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 7f0a4717d88dc..ce619ae8a0d8c 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -37,11 +37,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } #[instrument(level = "debug", skip(self))] - pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> { + pub fn param_or_placeholder_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> { // Start with anything like `T: 'a` we can scrape from the // environment. If the environment contains something like // `for<'a> T: 'a`, then we know that `T` outlives everything. - let declared_bounds_from_env = self.declared_generic_bounds_from_env(param_ty); + let declared_bounds_from_env = self.declared_generic_bounds_from_env(ty); debug!(?declared_bounds_from_env); let mut param_bounds = vec![]; for declared_bound in declared_bounds_from_env { @@ -51,7 +51,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { param_bounds.push(VerifyBound::OutlivedBy(region)); } else { // This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here. - debug!("found that {param_ty:?} outlives any lifetime, returning empty vector"); + debug!("found that {ty:?} outlives any lifetime, returning empty vector"); return VerifyBound::AllBounds(vec![]); } } @@ -168,7 +168,10 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { ) -> VerifyBound<'tcx> { match *component { Component::Region(lt) => VerifyBound::OutlivedBy(lt), - Component::Param(param_ty) => self.param_bound(param_ty), + Component::Param(param_ty) => self.param_or_placeholder_bound(param_ty.to_ty(self.tcx)), + Component::Placeholder(placeholder_ty) => { + self.param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty)) + } Component::Alias(alias_ty) => self.alias_bound(alias_ty, visited), Component::EscapingAlias(ref components) => { self.bound_from_components(components, visited) @@ -177,7 +180,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // ignore this, we presume it will yield an error // later, since if a type variable is not resolved by // this point it never will be - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( rustc_span::DUMMY_SP, format!("unresolved inference variable in outlives: {v:?}"), ); @@ -195,9 +198,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// bounds, but all the bounds it returns can be relied upon. fn declared_generic_bounds_from_env( &self, - param_ty: ty::ParamTy, + generic_ty: Ty<'tcx>, ) -> Vec, ty::Region<'tcx>>>> { - let generic_ty = param_ty.to_ty(self.tcx); + assert!(matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_))); self.declared_generic_bounds_from_env_for_erased_ty(generic_ty) } diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index b6ff8f2f512de..e06596df7b94a 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -81,7 +81,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { return Ok(()); } - let mini_graph = &MiniGraph::new(tcx, &self, only_consider_snapshot); + let mini_graph = &MiniGraph::new(tcx, self, only_consider_snapshot); let mut leak_check = LeakCheck::new(tcx, outer_universe, max_universe, mini_graph, self); leak_check.assign_placeholder_values()?; @@ -341,11 +341,13 @@ impl<'tcx> SccUniverse<'tcx> { } rustc_index::newtype_index! { + #[orderable] #[debug_format = "LeakCheckNode({})"] struct LeakCheckNode {} } rustc_index::newtype_index! { + #[orderable] #[debug_format = "LeakCheckScc({})"] struct LeakCheckScc {} } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 3fa9a7333a453..cbd8040c9f10f 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -16,7 +16,7 @@ use rustc_index::IndexVec; use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion}; use rustc_middle::ty::ReStatic; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::ty::{ReLateBound, ReVar}; +use rustc_middle::ty::{ReBound, ReVar}; use rustc_middle::ty::{Region, RegionVid}; use rustc_span::Span; @@ -147,6 +147,7 @@ pub struct Verify<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] pub enum GenericKind<'tcx> { Param(ty::ParamTy), + Placeholder(ty::PlaceholderType), Alias(ty::AliasTy<'tcx>), } @@ -316,7 +317,7 @@ impl<'tcx> RegionConstraintStorage<'tcx> { match undo_entry { AddVar(vid) => { self.var_infos.pop().unwrap(); - assert_eq!(self.var_infos.len(), vid.index() as usize); + assert_eq!(self.var_infos.len(), vid.index()); } AddConstraint(ref constraint) => { self.data.constraints.remove(constraint); @@ -531,7 +532,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { debug!("origin = {:#?}", origin); match (*sub, *sup) { - (ReLateBound(..), _) | (_, ReLateBound(..)) => { + (ReBound(..), _) | (_, ReBound(..)) => { span_bug!(origin.span(), "cannot relate bound region: {:?} <= {:?}", sub, sup); } (_, ReStatic) => { @@ -662,12 +663,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { match *region { ty::ReStatic | ty::ReErased - | ty::ReFree(..) - | ty::ReEarlyBound(..) + | ty::ReLateParam(..) + | ty::ReEarlyParam(..) | ty::ReError(_) => ty::UniverseIndex::ROOT, ty::RePlaceholder(placeholder) => placeholder.universe, ty::ReVar(vid) => self.var_universe(vid), - ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region), + ty::ReBound(..) => bug!("universe(): encountered bound region {:?}", region), } } @@ -707,6 +708,7 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { GenericKind::Param(ref p) => write!(f, "{p:?}"), + GenericKind::Placeholder(ref p) => write!(f, "{p:?}"), GenericKind::Alias(ref p) => write!(f, "{p:?}"), } } @@ -716,6 +718,7 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { GenericKind::Param(ref p) => write!(f, "{p}"), + GenericKind::Placeholder(ref p) => write!(f, "{p:?}"), GenericKind::Alias(ref p) => write!(f, "{p}"), } } @@ -725,6 +728,7 @@ impl<'tcx> GenericKind<'tcx> { pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { GenericKind::Param(ref p) => p.to_ty(tcx), + GenericKind::Placeholder(ref p) => Ty::new_placeholder(tcx, *p), GenericKind::Alias(ref p) => p.to_ty(tcx), } } diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 18a9cb6b44b78..ece30bbba12ac 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -260,3 +260,85 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { } } } + +/////////////////////////////////////////////////////////////////////////// +// EAGER RESOLUTION + +/// Resolves ty, region, and const vars to their inferred values or their root vars. +pub struct EagerResolver<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, +} + +impl<'a, 'tcx> EagerResolver<'a, 'tcx> { + pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { + EagerResolver { infcx } + } +} + +impl<'tcx> TypeFolder> for EagerResolver<'_, 'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match *t.kind() { + ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) { + Ok(t) => t.fold_with(self), + Err(_) => Ty::new_var(self.infcx.tcx, self.infcx.root_var(vid)), + }, + ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid), + ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid), + _ => { + if t.has_infer() { + t.super_fold_with(self) + } else { + t + } + } + } + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match *r { + ty::ReVar(vid) => self + .infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(self.infcx.tcx, vid), + _ => r, + } + } + + fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { + match c.kind() { + ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { + // FIXME: we need to fold the ty too, I think. + match self.infcx.probe_const_var(vid) { + Ok(c) => c.fold_with(self), + Err(_) => { + ty::Const::new_var(self.infcx.tcx, self.infcx.root_const_var(vid), c.ty()) + } + } + } + ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { + debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool); + match self.infcx.probe_effect_var(vid) { + Some(c) => c.as_const(self.infcx.tcx), + None => ty::Const::new_infer( + self.infcx.tcx, + ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)), + self.infcx.tcx.types.bool, + ), + } + } + _ => { + if c.has_infer() { + c.super_fold_with(self) + } else { + c + } + } + } + } +} diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index bc83f8d3f9676..bd6f905c8241d 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -229,12 +229,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { /// Precondition: `vid` must not have been previously instantiated. pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) { let vid = self.root_var(vid); + debug_assert!(!ty.is_ty_var(), "instantiating ty var with var: {vid:?} {ty:?}"); debug_assert!(self.probe(vid).is_unknown()); debug_assert!( self.eq_relations().probe_value(vid).is_unknown(), - "instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}", - vid, - ty, + "instantiating type variable `{vid:?}` twice: new-value = {ty:?}, old-value={:?}", self.eq_relations().probe_value(vid) ); self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty }); diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 4a6d1bc682b39..221b78048cbc3 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -13,9 +13,9 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(control_flow_enum)] @@ -37,11 +37,8 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - mod errors; pub mod infer; pub mod traits; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 32966011932d1..b3cfd843ace3c 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -101,12 +101,19 @@ pub fn report_object_safety_error<'tcx>( to be resolvable dynamically; for more information visit \ ", ); + + // Only provide the help if its a local trait, otherwise it's not actionable. if trait_span.is_some() { let mut reported_violations: Vec<_> = reported_violations.into_iter().collect(); reported_violations.sort(); - for violation in reported_violations { - // Only provide the help if its a local trait, otherwise it's not actionable. - violation.solution(&mut err); + + let mut potential_solutions: Vec<_> = + reported_violations.into_iter().map(|violation| violation.solution()).collect(); + potential_solutions.sort(); + // Allows us to skip suggesting that the same item should be moved to another trait multiple times. + potential_solutions.dedup(); + for solution in potential_solutions { + solution.add_to(&mut err); } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 3c566e0dd6da6..50190058a7688 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -261,9 +261,14 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { fn elaborate(&mut self, elaboratable: &O) { let tcx = self.visited.tcx; - let bound_predicate = elaboratable.predicate().kind(); - match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { + // We only elaborate clauses. + let Some(clause) = elaboratable.predicate().as_clause() else { + return; + }; + + let bound_clause = clause.kind(); + match bound_clause.skip_binder() { + ty::ClauseKind::Trait(data) => { // Negative trait bounds do not imply any supertrait bounds if data.polarity == ty::ImplPolarity::Negative { return; @@ -280,52 +285,16 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { let obligations = predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { elaboratable.child_with_derived_cause( - clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), + clause.subst_supertrait(tcx, &bound_clause.rebind(data.trait_ref)), span, - bound_predicate.rebind(data), + bound_clause.rebind(data), index, ) }); debug!(?data, ?obligations, "super_predicates"); self.extend_deduped(obligations); } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => { - // Currently, we do not elaborate WF predicates, - // although we easily could. - } - ty::PredicateKind::ObjectSafe(..) => { - // Currently, we do not elaborate object-safe - // predicates. - } - ty::PredicateKind::Subtype(..) => { - // Currently, we do not "elaborate" predicates like `X <: Y`, - // though conceivably we might. - } - ty::PredicateKind::Coerce(..) => { - // Currently, we do not "elaborate" predicates like `X -> Y`, - // though conceivably we might. - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { - // Nothing to elaborate in a projection predicate. - } - ty::PredicateKind::ClosureKind(..) => { - // Nothing to elaborate when waiting for a closure's kind to be inferred. - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => { - // Currently, we do not elaborate const-evaluatable - // predicates. - } - ty::PredicateKind::ConstEquate(..) => { - // Currently, we do not elaborate const-equate - // predicates. - } - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => { - // Nothing to elaborate from `'a: 'b`. - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - ty_max, - r_min, - ))) => { + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => { // We know that `T: 'a` for some type `T`. We can // often elaborate this. For example, if we know that // `[U]: 'a`, that implies that `U: 'a`. Similarly, if @@ -340,7 +309,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { // consider this as evidence that `T: 'static`, but // I'm a bit wary of such constructions and so for now // I want to be conservative. --nmatsakis - if r_min.is_late_bound() { + if r_min.is_bound() { return; } @@ -351,7 +320,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { .into_iter() .filter_map(|component| match component { Component::Region(r) => { - if r.is_late_bound() { + if r.is_bound() { None } else { Some(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( @@ -365,6 +334,11 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min))) } + Component::Placeholder(p) => { + let ty = Ty::new_placeholder(tcx, p); + Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min))) + } + Component::UnresolvedInferenceVariable(_) => None, Component::Alias(alias_ty) => { @@ -383,15 +357,25 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { } }) .map(|clause| { - elaboratable.child(bound_predicate.rebind(clause).to_predicate(tcx)) + elaboratable.child(bound_clause.rebind(clause).to_predicate(tcx)) }), ); } - ty::PredicateKind::Ambiguous => {} - ty::PredicateKind::AliasRelate(..) => { - // No + ty::ClauseKind::RegionOutlives(..) => { + // Nothing to elaborate from `'a: 'b`. + } + ty::ClauseKind::WellFormed(..) => { + // Currently, we do not elaborate WF predicates, + // although we easily could. + } + ty::ClauseKind::Projection(..) => { + // Nothing to elaborate in a projection predicate. + } + ty::ClauseKind::ConstEvaluatable(..) => { + // Currently, we do not elaborate const-evaluatable + // predicates. } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => { + ty::ClauseKind::ConstArgHasType(..) => { // Nothing to elaborate } } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index fd587e53f9154..319e81758094d 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -40,6 +40,7 @@ rustc_privacy = { path = "../rustc_privacy" } rustc_query_impl = { path = "../rustc_query_impl" } rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } +rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index c4962707f69a8..6527e87d39627 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -1,7 +1,7 @@ use crate::util; use rustc_ast::token; -use rustc_ast::{self as ast, LitKind, MetaItemKind}; +use rustc_ast::{LitKind, MetaItemKind}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::defer; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -10,14 +10,12 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_lint::LintStore; +use rustc_middle::ty; use rustc_middle::util::Providers; -use rustc_middle::{bug, ty}; use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; -use rustc_session::config::{ - self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName, OutputFilenames, -}; +use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::parse::ParseSess; use rustc_session::{lint, CompilerIO, EarlyErrorHandler, Session}; @@ -38,33 +36,13 @@ pub type Result = result::Result; /// Can be used to run `rustc_interface` queries. /// Created by passing [`Config`] to [`run_compiler`]. pub struct Compiler { - pub(crate) sess: Lrc, - codegen_backend: Lrc, - pub(crate) register_lints: Option>, + pub sess: Session, + pub codegen_backend: Box, pub(crate) override_queries: Option, } -impl Compiler { - pub fn session(&self) -> &Lrc { - &self.sess - } - pub fn codegen_backend(&self) -> &Lrc { - &self.codegen_backend - } - pub fn register_lints(&self) -> &Option> { - &self.register_lints - } - pub fn build_output_filenames( - &self, - sess: &Session, - attrs: &[ast::Attribute], - ) -> OutputFilenames { - util::build_output_filenames(attrs, sess) - } -} - /// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`. -pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec) -> Cfg { +pub(crate) fn parse_cfg(handler: &Handler, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { let sess = ParseSess::with_silent_emitter(Some(format!( @@ -74,10 +52,14 @@ pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec) -> Cfg { macro_rules! error { ($reason: expr) => { - handler.early_error(format!( - concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), - s - )); + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + handler + .struct_fatal(format!( + concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), + s + )) + .emit(); }; } @@ -119,14 +101,13 @@ pub(crate) fn parse_cfg(handler: &EarlyErrorHandler, cfgs: Vec) -> Cfg { } /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. -pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) -> CheckCfg { +pub(crate) fn parse_check_cfg(handler: &Handler, specs: Vec) -> CheckCfg { // If any --check-cfg is passed then exhaustive_values and exhaustive_names // are enabled by default. let exhaustive_names = !specs.is_empty(); let exhaustive_values = !specs.is_empty(); let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; - let mut old_syntax = None; for s in specs { let sess = ParseSess::with_silent_emitter(Some(format!( "this error occurred on the command line: `--check-cfg={s}`" @@ -135,10 +116,14 @@ pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) - macro_rules! error { ($reason:expr) => { - handler.early_error(format!( - concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), - s - )) + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] + handler + .struct_fatal(format!( + concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), + s + )) + .emit() }; } @@ -164,162 +149,101 @@ pub(crate) fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec) - expected_error(); }; - let mut set_old_syntax = || { - // defaults are flipped for the old syntax - if old_syntax == None { - check_cfg.exhaustive_names = false; - check_cfg.exhaustive_values = false; - } - old_syntax = Some(true); - }; - - if meta_item.has_name(sym::names) { - set_old_syntax(); - - check_cfg.exhaustive_names = true; - for arg in args { - if arg.is_word() && let Some(ident) = arg.ident() { - check_cfg.expecteds.entry(ident.name).or_insert(ExpectedValues::Any); - } else { - error!("`names()` arguments must be simple identifiers"); - } - } - } else if meta_item.has_name(sym::values) { - set_old_syntax(); - - if let Some((name, values)) = args.split_first() { - if name.is_word() && let Some(ident) = name.ident() { - let expected_values = check_cfg - .expecteds - .entry(ident.name) - .and_modify(|expected_values| match expected_values { - ExpectedValues::Some(_) => {} - ExpectedValues::Any => { - // handle the case where names(...) was done - // before values by changing to a list - *expected_values = ExpectedValues::Some(FxHashSet::default()); - } - }) - .or_insert_with(|| ExpectedValues::Some(FxHashSet::default())); + if !meta_item.has_name(sym::cfg) { + expected_error(); + } - let ExpectedValues::Some(expected_values) = expected_values else { - bug!("`expected_values` should be a list a values") - }; + let mut names = Vec::new(); + let mut values: FxHashSet<_> = Default::default(); - for val in values { - if let Some(LitKind::Str(s, _)) = val.lit().map(|lit| &lit.kind) { - expected_values.insert(Some(*s)); - } else { - error!("`values()` arguments must be string literals"); - } - } + let mut any_specified = false; + let mut values_specified = false; + let mut values_any_specified = false; - if values.is_empty() { - expected_values.insert(None); - } - } else { - error!("`values()` first argument must be a simple identifier"); + for arg in args { + if arg.is_word() + && let Some(ident) = arg.ident() + { + if values_specified { + error!("`cfg()` names cannot be after values"); } - } else if args.is_empty() { - check_cfg.exhaustive_values = true; - } else { - expected_error(); - } - } else if meta_item.has_name(sym::cfg) { - old_syntax = Some(false); - - let mut names = Vec::new(); - let mut values: FxHashSet<_> = Default::default(); - - let mut any_specified = false; - let mut values_specified = false; - let mut values_any_specified = false; - - for arg in args { - if arg.is_word() && let Some(ident) = arg.ident() { - if values_specified { - error!("`cfg()` names cannot be after values"); - } - names.push(ident); - } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() { - if any_specified { - error!("`any()` cannot be specified multiple times"); - } - any_specified = true; - if !args.is_empty() { - error!("`any()` must be empty"); - } - } else if arg.has_name(sym::values) && let Some(args) = arg.meta_item_list() { - if names.is_empty() { - error!("`values()` cannot be specified before the names"); - } else if values_specified { - error!("`values()` cannot be specified multiple times"); - } - values_specified = true; - - for arg in args { - if let Some(LitKind::Str(s, _)) = arg.lit().map(|lit| &lit.kind) { - values.insert(Some(*s)); - } else if arg.has_name(sym::any) && let Some(args) = arg.meta_item_list() { - if values_any_specified { - error!("`any()` in `values()` cannot be specified multiple times"); - } - values_any_specified = true; - if !args.is_empty() { - error!("`any()` must be empty"); - } - } else { - error!("`values()` arguments must be string literals or `any()`"); + names.push(ident); + } else if arg.has_name(sym::any) + && let Some(args) = arg.meta_item_list() + { + if any_specified { + error!("`any()` cannot be specified multiple times"); + } + any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else if arg.has_name(sym::values) + && let Some(args) = arg.meta_item_list() + { + if names.is_empty() { + error!("`values()` cannot be specified before the names"); + } else if values_specified { + error!("`values()` cannot be specified multiple times"); + } + values_specified = true; + + for arg in args { + if let Some(LitKind::Str(s, _)) = arg.lit().map(|lit| &lit.kind) { + values.insert(Some(*s)); + } else if arg.has_name(sym::any) + && let Some(args) = arg.meta_item_list() + { + if values_any_specified { + error!("`any()` in `values()` cannot be specified multiple times"); } + values_any_specified = true; + if !args.is_empty() { + error!("`any()` must be empty"); + } + } else { + error!("`values()` arguments must be string literals or `any()`"); } - } else { - error!( - "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`" - ); } + } else { + error!("`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"); } + } - if values.is_empty() && !values_any_specified && !any_specified { - values.insert(None); - } else if !values.is_empty() && values_any_specified { - error!( - "`values()` arguments cannot specify string literals and `any()` at the same time" - ); - } + if values.is_empty() && !values_any_specified && !any_specified { + values.insert(None); + } else if !values.is_empty() && values_any_specified { + error!( + "`values()` arguments cannot specify string literals and `any()` at the same time" + ); + } - if any_specified { - if names.is_empty() - && values.is_empty() - && !values_specified - && !values_any_specified - { - check_cfg.exhaustive_names = false; - } else { - error!("`cfg(any())` can only be provided in isolation"); - } + if any_specified { + if names.is_empty() && values.is_empty() && !values_specified && !values_any_specified { + check_cfg.exhaustive_names = false; } else { - for name in names { - check_cfg - .expecteds - .entry(name.name) - .and_modify(|v| match v { - ExpectedValues::Some(v) if !values_any_specified => { - v.extend(values.clone()) - } - ExpectedValues::Some(_) => *v = ExpectedValues::Any, - ExpectedValues::Any => {} - }) - .or_insert_with(|| { - if values_any_specified { - ExpectedValues::Any - } else { - ExpectedValues::Some(values.clone()) - } - }); - } + error!("`cfg(any())` can only be provided in isolation"); } } else { - expected_error(); + for name in names { + check_cfg + .expecteds + .entry(name.name) + .and_modify(|v| match v { + ExpectedValues::Some(v) if !values_any_specified => { + v.extend(values.clone()) + } + ExpectedValues::Some(_) => *v = ExpectedValues::Any, + ExpectedValues::Any => {} + }) + .or_insert_with(|| { + if values_any_specified { + ExpectedValues::Any + } else { + ExpectedValues::Some(values.clone()) + } + }); + } } } @@ -392,19 +316,23 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se // Set parallel mode before thread pool creation, which will create `Lock`s. rustc_data_structures::sync::set_dyn_thread_safe_mode(config.opts.unstable_opts.threads > 1); + // Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread + let early_handler = EarlyErrorHandler::new(config.opts.error_format); + early_handler.initialize_checked_jobserver(); + util::run_in_thread_pool_with_globals( config.opts.edition, config.opts.unstable_opts.threads, || { crate::callbacks::setup_callbacks(); - let handler = EarlyErrorHandler::new(config.opts.error_format); + let early_handler = EarlyErrorHandler::new(config.opts.error_format); let codegen_backend = if let Some(make_codegen_backend) = config.make_codegen_backend { make_codegen_backend(&config.opts) } else { util::get_codegen_backend( - &handler, + &early_handler, &config.opts.maybe_sysroot, config.opts.unstable_opts.codegen_backend.as_deref(), ) @@ -421,7 +349,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se ) { Ok(bundle) => bundle, Err(e) => { - handler.early_error(format!("failed to load fluent bundle: {e}")); + early_handler.early_error(format!("failed to load fluent bundle: {e}")); } }; @@ -432,7 +360,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let target_override = codegen_backend.target_override(&config.opts); let mut sess = rustc_session::build_session( - &handler, + early_handler, config.opts, CompilerIO { input: config.input, @@ -454,12 +382,12 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se codegen_backend.init(&sess); - let cfg = parse_cfg(&handler, config.crate_cfg); + let cfg = parse_cfg(&sess.diagnostic(), config.crate_cfg); let mut cfg = config::build_configuration(&sess, cfg); util::add_configuration(&mut cfg, &mut sess, &*codegen_backend); sess.parse_sess.config = cfg; - let mut check_cfg = parse_check_cfg(&handler, config.crate_check_cfg); + let mut check_cfg = parse_check_cfg(&sess.diagnostic(), config.crate_check_cfg); check_cfg.fill_well_known(&sess.target); sess.parse_sess.check_config = check_cfg; @@ -473,12 +401,18 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se sess.opts.untracked_state_hash = hasher.finish() } - let compiler = Compiler { - sess: Lrc::new(sess), - codegen_backend: Lrc::from(codegen_backend), - register_lints: config.register_lints, - override_queries: config.override_queries, - }; + // Even though the session holds the lint store, we can't build the + // lint store until after the session exists. And we wait until now + // so that `register_lints` sees the fully initialized session. + let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); + if let Some(register_lints) = config.register_lints.as_deref() { + register_lints(&sess, &mut lint_store); + sess.registered_lints = true; + } + sess.lint_store = Some(Lrc::new(lint_store)); + + let compiler = + Compiler { sess, codegen_backend, override_queries: config.override_queries }; rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || { let r = { diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index ffa2667a351ef..cfa46447845a2 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -6,16 +6,12 @@ #![feature(let_chains)] #![feature(try_blocks)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - mod callbacks; mod errors; pub mod interface; @@ -32,4 +28,4 @@ pub use queries::Queries; #[cfg(test)] mod tests; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7d14d088e595e..09d92c2dfc0c2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -39,7 +39,7 @@ use std::any::Any; use std::ffi::OsString; use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; -use std::sync::{Arc, LazyLock}; +use std::sync::LazyLock; use std::{env, fs, iter}; pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { @@ -72,17 +72,6 @@ fn count_nodes(krate: &ast::Crate) -> usize { counter.count } -pub(crate) fn create_lint_store( - sess: &Session, - register_lints: Option, -) -> LintStore { - let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); - if let Some(register_lints) = register_lints { - register_lints(sess, &mut lint_store); - } - lint_store -} - fn pre_expansion_lint<'a>( sess: &Session, features: &Features, @@ -125,7 +114,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { } } -/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, +/// Runs the "early phases" of the compiler: initial `cfg` processing, /// syntax expansion, secondary `cfg` expansion, synthesis of a test /// harness if one is to be provided, injection of a dependency on the /// standard library and prelude, and name resolution. @@ -138,7 +127,7 @@ fn configure_and_expand( let tcx = resolver.tcx(); let sess = tcx.sess; let features = tcx.features(); - let lint_store = unerased_lint_store(tcx); + let lint_store = unerased_lint_store(tcx.sess); let crate_name = tcx.crate_name(LOCAL_CRATE); let lint_check_node = (&krate, pre_configured_attrs); pre_expansion_lint( @@ -161,7 +150,7 @@ fn configure_and_expand( ) }); - util::check_attr_crate_type(sess, pre_configured_attrs, &mut resolver.lint_buffer()); + util::check_attr_crate_type(sess, pre_configured_attrs, resolver.lint_buffer()); // Expand all macros krate = sess.time("macro_expand_crate", || { @@ -295,16 +284,16 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let mut lint_buffer = resolver.lint_buffer.steal(); if sess.opts.unstable_opts.input_stats { - eprintln!("Post-expansion node count: {}", count_nodes(&krate)); + eprintln!("Post-expansion node count: {}", count_nodes(krate)); } if sess.opts.unstable_opts.hir_stats { - hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS", "ast-stats-2"); + hir_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2"); } // Needs to go *after* expansion to be able to check the results of macro expansion. sess.time("complete_gated_feature_checking", || { - rustc_ast_passes::feature_gate::check_crate(&krate, sess, tcx.features()); + rustc_ast_passes::feature_gate::check_crate(krate, sess, tcx.features()); }); // Add all buffered lints from the `ParseSess` to the `Session`. @@ -317,6 +306,8 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing. sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| { + // We will soon sort, so the initial order does not matter. + #[allow(rustc::potential_query_instability)] let mut identifiers: Vec<_> = identifiers.drain().collect(); identifiers.sort_by_key(|&(key, _)| key); for (ident, mut spans) in identifiers.into_iter() { @@ -330,7 +321,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { } }); - let lint_store = unerased_lint_store(tcx); + let lint_store = unerased_lint_store(tcx.sess); rustc_lint::check_ast_node( sess, tcx.features(), @@ -442,6 +433,9 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P escape_dep_filename(&file.prefer_local().to_string()) }; + // The entries will be used to declare dependencies beween files in a + // Makefile-like output, so the iteration order does not matter. + #[allow(rustc::potential_query_instability)] let extra_tracked_files = file_depinfo.iter().map(|path_sym| normalize_path(PathBuf::from(path_sym.as_str()))); files.extend(extra_tracked_files); @@ -497,6 +491,8 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P // Emit special comments with information about accessed environment variables. let env_depinfo = sess.parse_sess.env_depinfo.borrow(); if !env_depinfo.is_empty() { + // We will soon sort, so the initial order does not matter. + #[allow(rustc::potential_query_instability)] let mut envs: Vec<_> = env_depinfo .iter() .map(|(k, v)| (escape_dep_env(*k), v.map(escape_dep_env))) @@ -530,13 +526,11 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P match result { Ok(_) => { if sess.opts.json_artifact_notifications { - sess.parse_sess - .span_diagnostic - .emit_artifact_notification(&deps_filename, "dep-info"); + sess.diagnostic().emit_artifact_notification(deps_filename, "dep-info"); } } Err(error) => { - sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error }); + sess.emit_fatal(errors::ErrorWritingDependencies { path: deps_filename, error }); } } } @@ -564,23 +558,27 @@ fn resolver_for_lowering<'tcx>( tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))) } -fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc { +pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) { + // Make sure name resolution and macro expansion is run for + // the side-effect of providing a complete set of all + // accessed files and env vars. + let _ = tcx.resolver_for_lowering(()); + let sess = tcx.sess; - let _timer = sess.timer("prepare_outputs"); - let (_, krate) = &*tcx.resolver_for_lowering(()).borrow(); + let _timer = sess.timer("write_dep_info"); let crate_name = tcx.crate_name(LOCAL_CRATE); - let outputs = util::build_output_filenames(&krate.attrs, sess); + let outputs = tcx.output_filenames(()); let output_paths = generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name); // Ensure the source file isn't accidentally overwritten during compilation. - if let Some(ref input_path) = sess.io.input.opt_path() { + if let Some(input_path) = sess.io.input.opt_path() { if sess.opts.will_create_output_file() { if output_contains_path(&output_paths, input_path) { sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path }); } - if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) { + if let Some(dir_path) = output_conflicts_with_dir(&output_paths) { sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory { input_path, dir_path, @@ -607,15 +605,12 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc { } } } - - outputs.into() } pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; providers.hir_crate = rustc_ast_lowering::lower_to_hir; - providers.output_filenames = output_filenames; providers.resolver_for_lowering = resolver_for_lowering; providers.early_lint_checks = early_lint_checks; proc_macro_decls::provide(providers); @@ -645,7 +640,6 @@ pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, crate_types: Vec, stable_crate_id: StableCrateId, - lint_store: Lrc, dep_graph: DepGraph, untracked: Untracked, gcx_cell: &'tcx OnceLock>, @@ -657,10 +651,10 @@ pub fn create_global_ctxt<'tcx>( // incr. comp. yet. dep_graph.assert_ignored(); - let sess = &compiler.session(); + let sess = &compiler.sess; let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); - let codegen_backend = compiler.codegen_backend(); + let codegen_backend = &compiler.codegen_backend; let mut providers = *DEFAULT_QUERY_PROVIDERS; codegen_backend.provide(&mut providers); @@ -676,7 +670,6 @@ pub fn create_global_ctxt<'tcx>( sess, crate_types, stable_crate_id, - lint_store, arena, hir_arena, untracked, @@ -769,7 +762,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); tcx.hir().par_body_owners(|def_id| { - if let rustc_hir::def::DefKind::Coroutine = tcx.def_kind(def_id) { + if tcx.is_coroutine(def_id.to_def_id()) { tcx.ensure().mir_coroutine_witnesses(def_id); tcx.ensure().check_coroutine_obligations(def_id); } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 3a5f788e8ddb6..e9611c74a6856 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -1,13 +1,14 @@ use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation}; use crate::interface::{Compiler, Result}; -use crate::{passes, util}; +use crate::{errors, passes, util}; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal}; +use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::setup_dep_graph; @@ -15,9 +16,11 @@ use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::{GlobalCtxt, TyCtxt}; +use rustc_serialize::opaque::FileEncodeResult; use rustc_session::config::{self, CrateType, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; -use rustc_session::{output::find_crate_name, Session}; +use rustc_session::output::find_crate_name; +use rustc_session::Session; use rustc_span::symbol::sym; use std::any::Any; use std::cell::{RefCell, RefMut}; @@ -83,7 +86,6 @@ pub struct Queries<'tcx> { hir_arena: WorkerLocal>, parse: Query, - pre_configure: Query<(ast::Crate, ast::AttrVec)>, // This just points to what's in `gcx_cell`. gcx: Query<&'tcx GlobalCtxt<'tcx>>, } @@ -96,29 +98,26 @@ impl<'tcx> Queries<'tcx> { arena: WorkerLocal::new(|_| Arena::default()), hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), parse: Default::default(), - pre_configure: Default::default(), gcx: Default::default(), } } - fn session(&self) -> &Lrc { - &self.compiler.sess - } - fn codegen_backend(&self) -> &Lrc { - self.compiler.codegen_backend() + pub fn finish(&self) -> FileEncodeResult { + if let Some(gcx) = self.gcx_cell.get() { gcx.finish() } else { Ok(0) } } pub fn parse(&self) -> Result> { - self.parse - .compute(|| passes::parse(self.session()).map_err(|mut parse_error| parse_error.emit())) + self.parse.compute(|| { + passes::parse(&self.compiler.sess).map_err(|mut parse_error| parse_error.emit()) + }) } - #[deprecated = "pre_configure may be made private in the future. If you need it please open an issue with your use case."] - pub fn pre_configure(&self) -> Result> { - self.pre_configure.compute(|| { + pub fn global_ctxt(&'tcx self) -> Result>> { + self.gcx.compute(|| { + let sess = &self.compiler.sess; + let mut krate = self.parse()?.steal(); - let sess = self.session(); rustc_builtin_macros::cmdline_attrs::inject( &mut krate, &sess.parse_sess, @@ -127,15 +126,6 @@ impl<'tcx> Queries<'tcx> { let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs); - Ok((krate, pre_configured_attrs)) - }) - } - - pub fn global_ctxt(&'tcx self) -> Result>> { - self.gcx.compute(|| { - let sess = self.session(); - #[allow(deprecated)] - let (krate, pre_configured_attrs) = self.pre_configure()?.steal(); // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. let crate_name = find_crate_name(sess, &pre_configured_attrs); @@ -146,12 +136,11 @@ impl<'tcx> Queries<'tcx> { sess.opts.cg.metadata.clone(), sess.cfg_version, ); + let outputs = util::build_output_filenames(&pre_configured_attrs, sess); let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?; - let lint_store = - Lrc::new(passes::create_lint_store(sess, self.compiler.register_lints.as_deref())); let cstore = FreezeLock::new(Box::new(CStore::new( - self.codegen_backend().metadata_loader(), + self.compiler.codegen_backend.metadata_loader(), stable_crate_id, )) as _); let definitions = FreezeLock::new(Definitions::new(stable_crate_id)); @@ -164,7 +153,6 @@ impl<'tcx> Queries<'tcx> { self.compiler, crate_types, stable_crate_id, - lint_store, dep_graph, untracked, &self.gcx_cell, @@ -183,25 +171,20 @@ impl<'tcx> Queries<'tcx> { crate_name, ))); feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); + feed.output_filenames(Arc::new(outputs)); + + let feed = tcx.feed_local_def_id(CRATE_DEF_ID); + feed.def_kind(DefKind::Mod); }); Ok(qcx) }) } - pub fn ongoing_codegen(&'tcx self) -> Result> { + pub fn write_dep_info(&'tcx self) -> Result<()> { self.global_ctxt()?.enter(|tcx| { - // Don't do code generation if there were any errors - self.session().compile_status()?; - - // If we have any delayed bugs, for example because we created TyKind::Error earlier, - // it's likely that codegen will only cause more ICEs, obscuring the original problem - self.session().diagnostic().flush_delayed(); - - // Hook for UI tests. - Self::check_for_rustc_errors_attr(tcx); - - Ok(passes::start_codegen(&**self.codegen_backend(), tcx)) - }) + passes::write_dep_info(tcx); + }); + Ok(()) } /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used @@ -211,16 +194,16 @@ impl<'tcx> Queries<'tcx> { let Some((def_id, _)) = tcx.entry_fn(()) else { return }; for attr in tcx.get_attrs(def_id, sym::rustc_error) { match attr.meta_item_list() { - // Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`. + // Check if there is a `#[rustc_error(span_delayed_bug_from_inside_query)]`. Some(list) if list.iter().any(|list_item| { matches!( list_item.ident().map(|i| i.name), - Some(sym::delay_span_bug_from_inside_query) + Some(sym::span_delayed_bug_from_inside_query) ) }) => { - tcx.ensure().trigger_delay_span_bug(def_id); + tcx.ensure().trigger_span_delayed_bug(def_id); } // Bare `#[rustc_error]`. @@ -238,68 +221,61 @@ impl<'tcx> Queries<'tcx> { } } - pub fn linker(&'tcx self, ongoing_codegen: Box) -> Result { - let sess = self.session().clone(); - let codegen_backend = self.codegen_backend().clone(); + pub fn codegen_and_build_linker(&'tcx self) -> Result { + self.global_ctxt()?.enter(|tcx| { + // Don't do code generation if there were any errors + self.compiler.sess.compile_status()?; - let (crate_hash, prepare_outputs, dep_graph) = self.global_ctxt()?.enter(|tcx| { - ( - if tcx.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None }, - tcx.output_filenames(()).clone(), - tcx.dep_graph.clone(), - ) - }); + // If we have any delayed bugs, for example because we created TyKind::Error earlier, + // it's likely that codegen will only cause more ICEs, obscuring the original problem + self.compiler.sess.diagnostic().flush_delayed(); - Ok(Linker { - sess, - codegen_backend, + // Hook for UI tests. + Self::check_for_rustc_errors_attr(tcx); - dep_graph, - prepare_outputs, - crate_hash, - ongoing_codegen, + let ongoing_codegen = passes::start_codegen(&*self.compiler.codegen_backend, tcx); + + Ok(Linker { + dep_graph: tcx.dep_graph.clone(), + output_filenames: tcx.output_filenames(()).clone(), + crate_hash: if tcx.needs_crate_hash() { + Some(tcx.crate_hash(LOCAL_CRATE)) + } else { + None + }, + ongoing_codegen, + }) }) } } pub struct Linker { - // compilation inputs - sess: Lrc, - codegen_backend: Lrc, - - // compilation outputs dep_graph: DepGraph, - prepare_outputs: Arc, + output_filenames: Arc, // Only present when incr. comp. is enabled. crate_hash: Option, ongoing_codegen: Box, } impl Linker { - pub fn link(self) -> Result<()> { - let (codegen_results, work_products) = self.codegen_backend.join_codegen( - self.ongoing_codegen, - &self.sess, - &self.prepare_outputs, - )?; + pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> { + let (codegen_results, work_products) = + codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)?; - self.sess.compile_status()?; + sess.compile_status()?; - let sess = &self.sess; - let dep_graph = self.dep_graph; sess.time("serialize_work_products", || { - rustc_incremental::save_work_product_index(sess, &dep_graph, work_products) + rustc_incremental::save_work_product_index(sess, &self.dep_graph, work_products) }); - let prof = self.sess.prof.clone(); - prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph)); + let prof = sess.prof.clone(); + prof.generic_activity("drop_dep_graph").run(move || drop(self.dep_graph)); // Now that we won't touch anything in the incremental compilation directory // any more, we can finalize it (which involves renaming it) - rustc_incremental::finalize_session_directory(&self.sess, self.crate_hash); + rustc_incremental::finalize_session_directory(sess, self.crate_hash); - if !self - .sess + if !sess .opts .output_types .keys() @@ -309,14 +285,19 @@ impl Linker { } if sess.opts.unstable_opts.no_link { - let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT); - CodegenResults::serialize_rlink(sess, &rlink_file, &codegen_results) - .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?; + let rlink_file = self.output_filenames.with_extension(config::RLINK_EXT); + CodegenResults::serialize_rlink( + sess, + &rlink_file, + &codegen_results, + &*self.output_filenames, + ) + .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?; return Ok(()); } let _timer = sess.prof.verbose_generic_activity("link_crate"); - self.codegen_backend.link(&self.sess, codegen_results, &self.prepare_outputs) + codegen_backend.link(sess, codegen_results, &self.output_filenames) } } @@ -325,6 +306,7 @@ impl Compiler { where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T, { + // Must declare `_timer` first so that it is dropped after `queries`. let mut _timer = None; let queries = Queries::new(self); let ret = f(&queries); @@ -337,15 +319,19 @@ impl Compiler { // after this point, they'll show up as "" in self-profiling data. { let _prof_timer = - queries.session().prof.generic_activity("self_profile_alloc_query_strings"); + queries.compiler.sess.prof.generic_activity("self_profile_alloc_query_strings"); gcx.enter(rustc_query_impl::alloc_self_profile_query_strings); } - self.session() - .time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); + self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); } - _timer = Some(self.session().timer("free_global_ctxt")); + // The timer's lifetime spans the dropping of `queries`, which contains + // the global context. + _timer = Some(self.sess.timer("free_global_ctxt")); + if let Err((path, error)) = queries.finish() { + self.sess.emit_err(errors::FailedWritingFile { path: &path, error }); + } ret } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 8e66083a390fc..ce58b2ab06170 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,11 +4,12 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, Input, - InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, - MirSpanview, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, - Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, - TraitSolver, WasiExecModel, + DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, + FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, + LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, OomStrategy, Options, + OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, + ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, TraitSolver, + WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -24,10 +25,12 @@ use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; use std::sync::Arc; -fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Session, Cfg) { +fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { + let mut early_handler = EarlyErrorHandler::new(ErrorOutputType::default()); + early_handler.initialize_checked_jobserver(); + let registry = registry::Registry::new(&[]); - let sessopts = build_session_options(handler, &matches); - let cfg = parse_cfg(handler, matches.opt_strs("cfg")); + let sessopts = build_session_options(&mut early_handler, &matches); let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, @@ -36,7 +39,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se temps_dir, }; let sess = build_session( - handler, + early_handler, sessopts, io, None, @@ -50,6 +53,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se Arc::default(), Default::default(), ); + let cfg = parse_cfg(&sess.diagnostic(), matches.opt_strs("cfg")); (sess, cfg) } @@ -116,8 +120,7 @@ fn assert_non_crate_hash_different(x: &Options, y: &Options) { fn test_switch_implies_cfg_test() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["--test".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, cfg) = mk_session(&mut handler, matches); + let (sess, cfg) = mk_session(matches); let cfg = build_configuration(&sess, cfg); assert!(cfg.contains(&(sym::test, None))); }); @@ -128,8 +131,7 @@ fn test_switch_implies_cfg_test() { fn test_switch_implies_cfg_test_unless_cfg_test() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, cfg) = mk_session(&mut handler, matches); + let (sess, cfg) = mk_session(matches); let cfg = build_configuration(&sess, cfg); let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test); assert!(test_items.next().is_some()); @@ -141,23 +143,20 @@ fn test_switch_implies_cfg_test_unless_cfg_test() { fn test_can_print_warnings() { rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, _) = mk_session(&mut handler, matches); + let (sess, _) = mk_session(matches); assert!(!sess.diagnostic().can_emit_warnings()); }); rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, _) = mk_session(&mut handler, matches); + let (sess, _) = mk_session(matches); assert!(sess.diagnostic().can_emit_warnings()); }); rustc_span::create_default_session_globals_then(|| { let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); - let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); - let (sess, _) = mk_session(&mut handler, matches); + let (sess, _) = mk_session(matches); assert!(sess.diagnostic().can_emit_warnings()); }); } @@ -679,7 +678,6 @@ fn test_unstable_options_tracking_hash() { untracked!(incremental_info, true); untracked!(incremental_verify_ich, true); untracked!(input_stats, true); - untracked!(keep_hygiene_data, true); untracked!(link_native_libraries, false); untracked!(llvm_time_trace, true); untracked!(ls, vec!["all".to_owned()]); @@ -691,7 +689,6 @@ fn test_unstable_options_tracking_hash() { untracked!(no_leak_check, true); untracked!(no_parallel_llvm, true); untracked!(parse_only, true); - untracked!(perf_stats, true); // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(print_codegen_stats, true); @@ -748,7 +745,7 @@ fn test_unstable_options_tracking_hash() { ); tracked!(codegen_backend, Some("abc".to_string())); tracked!(crate_attr, vec!["abc".to_string()]); - tracked!(cross_crate_inline_threshold, Some(200)); + tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); @@ -760,6 +757,7 @@ fn test_unstable_options_tracking_hash() { tracked!(flatten_format_args, false); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); + tracked!(function_return, FunctionReturn::ThunkExtern); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); tracked!(incremental_ignore_spans, true); @@ -771,6 +769,7 @@ fn test_unstable_options_tracking_hash() { tracked!(instrument_xray, Some(InstrumentXRay::default())); tracked!(link_directives, false); tracked!(link_only, true); + tracked!(llvm_module_flag, vec![("bar".to_string(), 123, "max".to_string())]); tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); tracked!(maximal_hir_to_mir_coverage, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 22d12793464a8..c9c7ffdd9371f 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -107,7 +107,7 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( use rustc_query_impl::QueryCtxt; use rustc_query_system::query::{deadlock, QueryContext}; - let registry = sync::Registry::new(threads); + let registry = sync::Registry::new(std::num::NonZeroUsize::new(threads).unwrap()); if !sync::is_dyn_thread_safe() { return run_in_thread_with_globals(edition, || { @@ -126,11 +126,8 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( .deadlock_handler(|| { // On deadlock, creates a new thread and forwards information in thread // locals to it. The new thread runs the deadlock handler. - let query_map = FromDyn::from(tls::with(|tcx| { - QueryCtxt::new(tcx) - .try_collect_active_jobs() - .expect("active jobs shouldn't be locked in deadlock handler") - })); + let query_map = + FromDyn::from(tls::with(|tcx| QueryCtxt::new(tcx).collect_active_jobs())); let registry = rayon_core::Registry::current(); thread::spawn(move || deadlock(query_map.into_inner(), ®istry)); }); @@ -415,7 +412,9 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec` instead, and only call `assume_init` after initialization is done @@ -496,8 +490,10 @@ lint_requested_level = requested on the command line with `{$level} {$lint_name} lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` -lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target - .label = target type is set here +lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion + .label = `{$self_ty}` implements `Deref` which conflicts with supertrait `{$supertrait_principal}` + .label2 = target type is a supertrait of `{$self_ty}` + .help = consider removing this implementation or replacing it with a method instead lint_suspicious_double_ref_clone = using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type @@ -523,6 +519,9 @@ lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::Manual lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op .label = this function will not propagate the caller location +lint_unit_bindings = binding has unit type `()` + .label = this pattern is inferred to be the unit type `()` + lint_unknown_gated_lint = unknown lint: `{$name}` .note = the `{$name}` lint is unstable diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6f6150a4172f5..64de5e92abfa8 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -33,7 +33,6 @@ use crate::{ BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasGenericBounds, BuiltinTypeAliasGenericBoundsSuggestion, BuiltinTypeAliasWhereClause, - BuiltinUnexpectedCliConfigName, BuiltinUnexpectedCliConfigValue, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, @@ -60,7 +59,6 @@ use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; -use rustc_session::config::ExpectedValues; use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; @@ -265,7 +263,7 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { continue; } if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind { - if cx.tcx.find_field_index(ident, &variant) + if cx.tcx.find_field_index(ident, variant) == Some(cx.typeck_results().field_index(fieldpat.hir_id)) { cx.emit_spanned_lint( @@ -509,7 +507,7 @@ impl MissingDoc { } } - let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id)); + let attrs = cx.tcx.hir().attrs(cx.tcx.local_def_id_to_hir_id(def_id)); let has_doc = attrs.iter().any(has_doc); if !has_doc { cx.emit_spanned_lint( @@ -635,21 +633,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } let (def, ty) = match item.kind { - hir::ItemKind::Struct(_, ref ast_generics) => { + hir::ItemKind::Struct(_, ast_generics) => { if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(item.owner_id); (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } - hir::ItemKind::Union(_, ref ast_generics) => { + hir::ItemKind::Union(_, ast_generics) => { if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(item.owner_id); (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } - hir::ItemKind::Enum(_, ref ast_generics) => { + hir::ItemKind::Enum(_, ast_generics) => { if !ast_generics.params.is_empty() { return; } @@ -1002,8 +1000,10 @@ impl EarlyLintPass for UnusedDocComment { } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { - let arm_span = arm.pat.span.with_hi(arm.body.span.hi()); - warn_if_doc(cx, arm_span, "match arms", &arm.attrs); + if let Some(body) = &arm.body { + let arm_span = arm.pat.span.with_hi(body.span.hi()); + warn_if_doc(cx, arm_span, "match arms", &arm.attrs); + } } fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat) { @@ -1029,7 +1029,7 @@ impl EarlyLintPass for UnusedDocComment { } fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { - warn_if_doc(cx, block.span, "blocks", &block.attrs()); + warn_if_doc(cx, block.span, "blocks", block.attrs()); } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { @@ -1119,7 +1119,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { } }; match it.kind { - hir::ItemKind::Fn(.., ref generics, _) => { + hir::ItemKind::Fn(.., generics, _) => { if let Some(no_mangle_attr) = attr::find_by_name(attrs, sym::no_mangle) { check_no_mangle_on_generic_fn(no_mangle_attr, None, generics, it.span); } @@ -1446,10 +1446,10 @@ declare_lint_pass!( impl TypeAliasBounds { pub(crate) fn is_type_variable_assoc(qpath: &hir::QPath<'_>) -> bool { match *qpath { - hir::QPath::TypeRelative(ref ty, _) => { + hir::QPath::TypeRelative(ty, _) => { // If this is a type variable, we found a `T::Assoc`. match ty.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { matches!(path.res, Res::Def(DefKind::TyParam, _)) } _ => false, @@ -1716,16 +1716,16 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns { } let (parentheses, endpoints) = match &pat.kind { - PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)), + PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(subpat)), _ => (false, matches_ellipsis_pat(pat)), }; if let Some((start, end, join)) = endpoints { if parentheses { self.node_id = Some(pat.id); - let end = expr_to_string(&end); + let end = expr_to_string(end); let replace = match start { - Some(start) => format!("&({}..={})", expr_to_string(&start), end), + Some(start) => format!("&({}..={})", expr_to_string(start), end), None => format!("&(..={end})"), }; if join.edition() >= Edition::Edition2021 { @@ -1910,7 +1910,7 @@ impl ExplicitOutlivesRequirements { .iter() .filter_map(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a { - ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b), + ty::ReEarlyParam(ebr) if ebr.def_id == def_id => Some(b), _ => None, }, _ => None, @@ -1953,7 +1953,7 @@ impl ExplicitOutlivesRequirements { let is_inferred = match tcx.named_bound_var(lifetime.hir_id) { Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives .iter() - .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })), + .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { ebr.def_id == def_id })), _ => false, }; @@ -2383,7 +2383,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { /// Determine if this expression is a "dangerous initialization". fn is_dangerous_init(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option { - if let hir::ExprKind::Call(ref path_expr, ref args) = expr.kind { + if let hir::ExprKind::Call(path_expr, args) = expr.kind { // Find calls to `mem::{uninitialized,zeroed}` methods. if let hir::ExprKind::Path(ref qpath) = path_expr.kind { let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; @@ -2400,7 +2400,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) { // This is a call to *some* method named `assume_init`. // See if the `self` parameter is one of the dangerous constructors. - if let hir::ExprKind::Call(ref path_expr, _) = receiver.kind { + if let hir::ExprKind::Call(path_expr, _) = receiver.kind { if let hir::ExprKind::Path(ref qpath) = path_expr.kind { let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; match cx.tcx.get_diagnostic_name(def_id) { @@ -2542,7 +2542,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { return variant_find_init_error( cx, ty, - &first_variant.0, + first_variant.0, args, "field of the only potentially inhabited enum variant", init, @@ -2648,13 +2648,13 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { /// test if expression is a null ptr fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { match &expr.kind { - rustc_hir::ExprKind::Cast(ref expr, ref ty) => { + rustc_hir::ExprKind::Cast(expr, ty) => { if let rustc_hir::TyKind::Ptr(_) = ty.kind { return is_zero(expr) || is_null_ptr(cx, expr); } } // check for call to `core::ptr::null` or `core::ptr::null_mut` - rustc_hir::ExprKind::Call(ref path, _) => { + rustc_hir::ExprKind::Call(path, _) => { if let rustc_hir::ExprKind::Path(ref qpath) = path.kind { if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() { return matches!( @@ -2672,7 +2672,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { /// test if expression is the literal `0` fn is_zero(expr: &hir::Expr<'_>) -> bool { match &expr.kind { - rustc_hir::ExprKind::Lit(ref lit) => { + rustc_hir::ExprKind::Lit(lit) => { if let LitKind::Int(a, _) = lit.node { return a == 0; } @@ -2889,26 +2889,3 @@ impl EarlyLintPass for SpecialModuleName { } } } - -pub use rustc_session::lint::builtin::UNEXPECTED_CFGS; - -declare_lint_pass!(UnexpectedCfgs => [UNEXPECTED_CFGS]); - -impl EarlyLintPass for UnexpectedCfgs { - fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { - let cfg = &cx.sess().parse_sess.config; - let check_cfg = &cx.sess().parse_sess.check_config; - for &(name, value) in cfg { - match check_cfg.expecteds.get(&name) { - Some(ExpectedValues::Some(values)) if !values.contains(&value) => { - let value = value.unwrap_or(kw::Empty); - cx.emit_lint(UNEXPECTED_CFGS, BuiltinUnexpectedCliConfigValue { name, value }); - } - None if check_cfg.exhaustive_names => { - cx.emit_lint(UNEXPECTED_CFGS, BuiltinUnexpectedCliConfigName { name }); - } - _ => { /* expected */ } - } - } - } -} diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index a5f4c5ff0459e..024e542d4afe4 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -36,7 +36,7 @@ use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, Ty use rustc_session::config::ExpectedValues; use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId}; use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId}; -use rustc_session::Session; +use rustc_session::{LintStoreMarker, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{BytePos, Span}; @@ -77,6 +77,8 @@ pub struct LintStore { lint_groups: FxHashMap<&'static str, LintGroup>, } +impl LintStoreMarker for LintStore {} + /// The target of the `by_name` map, which accounts for renaming/deprecation. #[derive(Debug)] enum TargetLint { @@ -385,7 +387,7 @@ impl LintStore { }; } Some(LintGroup { lint_ids, .. }) => { - return CheckLintNameResult::Tool(Ok(&lint_ids)); + return CheckLintNameResult::Tool(Ok(lint_ids)); } }, Some(Id(id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))), @@ -406,12 +408,12 @@ impl LintStore { if let Some(LintAlias { name, silent }) = depr { let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap(); return if *silent { - CheckLintNameResult::Ok(&lint_ids) + CheckLintNameResult::Ok(lint_ids) } else { - CheckLintNameResult::Tool(Err((Some(&lint_ids), (*name).to_string()))) + CheckLintNameResult::Tool(Err((Some(lint_ids), (*name).to_string()))) }; } - CheckLintNameResult::Ok(&lint_ids) + CheckLintNameResult::Ok(lint_ids) } }, Some(Id(id)) => CheckLintNameResult::Ok(slice::from_ref(id)), @@ -458,12 +460,12 @@ impl LintStore { if let Some(LintAlias { name, silent }) = depr { let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap(); return if *silent { - CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name))) + CheckLintNameResult::Tool(Err((Some(lint_ids), complete_name))) } else { - CheckLintNameResult::Tool(Err((Some(&lint_ids), (*name).to_string()))) + CheckLintNameResult::Tool(Err((Some(lint_ids), (*name).to_string()))) }; } - CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name))) + CheckLintNameResult::Tool(Err((Some(lint_ids), complete_name))) } }, Some(Id(id)) => { @@ -497,9 +499,6 @@ pub struct LateContext<'tcx> { /// Items accessible from the crate being checked. pub effective_visibilities: &'tcx EffectiveVisibilities, - /// The store of registered lints and the lint levels. - pub lint_store: &'tcx LintStore, - pub last_node_with_lint_attrs: hir::HirId, /// Generic type parameters in scope for the item we are in. @@ -515,21 +514,14 @@ pub struct EarlyContext<'a> { pub buffered: LintBuffer, } -pub trait LintPassObject: Sized {} - -impl LintPassObject for EarlyLintPassObject {} - -impl LintPassObject for LateLintPassObject<'_> {} - -pub trait LintContext: Sized { - type PassObject: LintPassObject; - +pub trait LintContext { fn sess(&self) -> &Session; - fn lints(&self) -> &LintStore; - /// Emit a lint at the appropriate level, with an optional associated span and an existing diagnostic. + /// Emit a lint at the appropriate level, with an optional associated span and an existing + /// diagnostic. /// - /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. + /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed + /// explanation. /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature #[rustc_lint_diagnostics] @@ -713,7 +705,7 @@ pub trait LintContext: Sized { db.note("see the asm section of Rust By Example for more information"); }, BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => { - let possibilities: Vec = sess.parse_sess.check_config.expecteds.keys().map(|s| *s).collect(); + let possibilities: Vec = sess.parse_sess.check_config.expecteds.keys().copied().collect(); // Suggest the most probable if we found one if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) { @@ -749,6 +741,8 @@ pub trait LintContext: Sized { } else { db.span_suggestion(name_span, "there is a config with a similar name", best_match, Applicability::MaybeIncorrect); } + } else if name == sym::feature && std::env::var_os("CARGO").is_some() { + db.help("consider defining some features in `Cargo.toml`"); } else if !possibilities.is_empty() { let mut possibilities = possibilities.iter() .map(Symbol::as_str) @@ -932,6 +926,10 @@ pub trait LintContext: Sized { if elided { "'static " } else { "'static" }, Applicability::MachineApplicable ); + }, + BuiltinLintDiagnostics::RedundantImportVisibility { max_vis, span } => { + db.span_note(span, format!("the most public imported item is `{max_vis}`")); + db.help("reduce the glob import's visibility or increase visibility of imported items"); } } // Rewrap `db`, and pass control to the user. @@ -1059,15 +1057,9 @@ impl<'a> EarlyContext<'a> { } impl<'tcx> LintContext for LateContext<'tcx> { - type PassObject = LateLintPassObject<'tcx>; - /// Gets the overall compiler `Session` object. fn sess(&self) -> &Session { - &self.tcx.sess - } - - fn lints(&self) -> &LintStore { - &*self.lint_store + self.tcx.sess } #[rustc_lint_diagnostics] @@ -1094,15 +1086,9 @@ impl<'tcx> LintContext for LateContext<'tcx> { } impl LintContext for EarlyContext<'_> { - type PassObject = EarlyLintPassObject; - /// Gets the overall compiler `Session` object. fn sess(&self) -> &Session { - &self.builder.sess() - } - - fn lints(&self) -> &LintStore { - self.builder.lint_store() + self.builder.sess() } #[rustc_lint_diagnostics] @@ -1149,7 +1135,7 @@ impl<'tcx> LateContext<'tcx> { /// bodies (e.g. for paths in `hir::Ty`), without any risk of ICE-ing. pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { match *qpath { - hir::QPath::Resolved(_, ref path) => path.res, + hir::QPath::Resolved(_, path) => path.res, hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self .maybe_typeck_results() .filter(|typeck_results| typeck_results.hir_owner == id.owner) diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index d2d99bc0da87d..98bafc0f2637e 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -5,7 +5,6 @@ use crate::{ use rustc_hir as hir; use rustc_middle::ty; -use rustc_session::lint::FutureIncompatibilityReason; use rustc_span::sym; use rustc_trait_selection::traits::supertraits; @@ -13,9 +12,6 @@ declare_lint! { /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the /// `Deref` implementation with a `dyn SuperTrait` type as `Output`. /// - /// These implementations will become shadowed when the `trait_upcasting` feature is stabilized. - /// The `deref` functions will no longer be called implicitly, so there might be behavior change. - /// /// ### Example /// /// ```rust,compile_fail @@ -44,47 +40,56 @@ declare_lint! { /// /// ### Explanation /// - /// The dyn upcasting coercion feature adds new coercion rules, taking priority - /// over certain other coercion rules, which will cause some behavior change. + /// The implicit dyn upcasting coercion take priority over those `Deref` impls. pub DEREF_INTO_DYN_SUPERTRAIT, Warn, - "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #89460 ", - }; + "`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion", } declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]); impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { + let tcx = cx.tcx; // `Deref` is being implemented for `t` if let hir::ItemKind::Impl(impl_) = item.kind + // the trait is a `Deref` implementation && let Some(trait_) = &impl_.of_trait - && let t = cx.tcx.type_of(item.owner_id).instantiate_identity() - && let opt_did @ Some(did) = trait_.trait_def_id() - && opt_did == cx.tcx.lang_items().deref_trait() - // `t` is `dyn t_principal` - && let ty::Dynamic(data, _, ty::Dyn) = t.kind() - && let Some(t_principal) = data.principal() + && let Some(did) = trait_.trait_def_id() + && Some(did) == tcx.lang_items().deref_trait() + // the self type is `dyn t_principal` + && let self_ty = tcx.type_of(item.owner_id).instantiate_identity() + && let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind() + && let Some(self_principal) = data.principal() // `::Target` is `dyn target_principal` - && let Some(target) = cx.get_associated_type(t, did, "Target") + && let Some(target) = cx.get_associated_type(self_ty, did, "Target") && let ty::Dynamic(data, _, ty::Dyn) = target.kind() && let Some(target_principal) = data.principal() // `target_principal` is a supertrait of `t_principal` - && supertraits(cx.tcx, t_principal.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self)) - .any(|sup| sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(cx.tcx, x)) == target_principal) + && let Some(supertrait_principal) = supertraits(tcx, self_principal.with_self_ty(tcx, self_ty)) + .find(|supertrait| supertrait.def_id() == target_principal.def_id()) { - let label = impl_ + // erase regions in self type for better diagnostic presentation + let (self_ty, target_principal, supertrait_principal) = + tcx.erase_regions((self_ty, target_principal, supertrait_principal)); + let label2 = impl_ .items .iter() .find_map(|i| (i.ident.name == sym::Target).then_some(i.span)) .map(|label| SupertraitAsDerefTargetLabel { label }); + let span = tcx.def_span(item.owner_id.def_id); cx.emit_spanned_lint( DEREF_INTO_DYN_SUPERTRAIT, - cx.tcx.def_span(item.owner_id.def_id), - SupertraitAsDerefTarget { t, target_principal, label }, + span, + SupertraitAsDerefTarget { + self_ty, + supertrait_principal: supertrait_principal.map_bound(|trait_ref| { + ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) + }), + target_principal, + label: span, + label2, + }, ); } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index d102e3a6c1508..7c4f81a4c3970 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -162,7 +162,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> // Explicitly check for lints associated with 'closure_id', since // it does not have a corresponding AST node if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk { - if let ast::Async::Yes { closure_id, .. } = sig.header.asyncness { + if let Some( + ast::CoroutineKind::Async { closure_id, .. } + | ast::CoroutineKind::Gen { closure_id, .. }, + ) = sig.header.coro_kind + { self.check_id(closure_id); } } @@ -223,7 +227,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> // it does not have a corresponding AST node match e.kind { ast::ExprKind::Closure(box ast::Closure { - asyncness: ast::Async::Yes { closure_id, .. }, + coro_kind: + Some( + ast::CoroutineKind::Async { closure_id, .. } + | ast::CoroutineKind::Gen { closure_id, .. }, + ), .. }) => self.check_id(closure_id), _ => {} @@ -350,7 +358,7 @@ impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) { where 'a: 'b, { - &self.1 + self.1 } fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>) where @@ -430,7 +438,7 @@ pub fn check_ast_node_inner<'a, T: EarlyLintPass>( // that was not lint-checked (perhaps it doesn't exist?). This is a bug. for (id, lints) in cx.context.buffered.map { for early_lint in lints { - sess.delay_span_bug( + sess.span_delayed_bug( early_lint.span, format!( "failed to process buffered lint here (dummy = {})", diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 740c90757e60f..047a214a8b24b 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -24,7 +24,7 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { // This check will always be true, since `lint_expectations` only // holds stable ids if let LintExpectationId::Stable { hir_id, .. } = id { - if !fulfilled_expectations.contains(&id) + if !fulfilled_expectations.contains(id) && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) { let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale }); diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index c8ec0458ba427..ea922785a954b 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -137,7 +137,7 @@ fn suggest_question_mark<'tcx>( // Check that the function/closure/constant we are in has a `Result` type. // Otherwise suggesting using `?` may not be a good idea. { - let ty = cx.typeck_results().expr_ty(&cx.tcx.hir().body(body_id).value); + let ty = cx.typeck_results().expr_ty(cx.tcx.hir().body(body_id).value); let ty::Adt(ret_adt, ..) = ty.kind() else { return false }; if !cx.tcx.is_diagnostic_item(sym::Result, ret_adt.did()) { return false; diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 86b3b4ad0ca95..31d9c0d33feee 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -341,8 +341,8 @@ fn structurally_same_type_impl<'tcx>( // We don't compare regions, but leaving bound regions around ICEs, so // we erase them. - let a_sig = tcx.erase_late_bound_regions(a_poly_sig); - let b_sig = tcx.erase_late_bound_regions(b_poly_sig); + let a_sig = tcx.instantiate_bound_regions_with_erased(a_poly_sig); + let b_sig = tcx.instantiate_bound_regions_with_erased(b_poly_sig); (a_sig.abi, a_sig.unsafety, a_sig.c_variadic) == (b_sig.abi, b_sig.unsafety, b_sig.c_variadic) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 2d86129c480c6..823ede1222c82 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -196,7 +196,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { } } else if !ty.span.from_expansion() && path.segments.len() > 1 - && let Some(ty) = is_ty_or_ty_ctxt(cx, &path) + && let Some(ty) = is_ty_or_ty_ctxt(cx, path) { cx.emit_spanned_lint( USAGE_OF_QUALIFIED_TY, diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 6c8b60c8d7413..caa015565914d 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -17,22 +17,25 @@ use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore}; use rustc_ast as ast; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::join; +use rustc_data_structures::sync::{join, Lrc}; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit as hir_visit; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::LintPass; +use rustc_session::Session; use rustc_span::Span; use std::any::Any; use std::cell::Cell; -/// Extract the `LintStore` from the query context. -/// This function exists because we've erased `LintStore` as `dyn Any` in the context. -pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { - let store: &dyn Any = &*tcx.lint_store; +/// Extract the [`LintStore`] from [`Session`]. +/// +/// This function exists because [`Session::lint_store`] is type-erased. +pub fn unerased_lint_store(sess: &Session) -> &LintStore { + let store: &Lrc<_> = sess.lint_store.as_ref().unwrap(); + let store: &dyn Any = &**store; store.downcast_ref().unwrap() } @@ -276,7 +279,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { let generics = self.context.generics.take(); - self.context.generics = Some(&trait_item.generics); + self.context.generics = Some(trait_item.generics); self.with_lint_attrs(trait_item.hir_id(), |cx| { cx.with_param_env(trait_item.owner_id, |cx| { lint_callback!(cx, check_trait_item, trait_item); @@ -288,7 +291,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { let generics = self.context.generics.take(); - self.context.generics = Some(&impl_item.generics); + self.context.generics = Some(impl_item.generics); self.with_lint_attrs(impl_item.hir_id(), |cx| { cx.with_param_env(impl_item.owner_id, |cx| { lint_callback!(cx, check_impl_item, impl_item); @@ -352,9 +355,8 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - effective_visibilities: &tcx.effective_visibilities(()), - lint_store: unerased_lint_store(tcx), - last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id), + effective_visibilities: tcx.effective_visibilities(()), + last_node_with_lint_attrs: tcx.local_def_id_to_hir_id(module_def_id.into()), generics: None, only_module: true, }; @@ -362,8 +364,11 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( // Note: `passes` is often empty. In that case, it's faster to run // `builtin_lints` directly rather than bundling it up into the // `RuntimeCombinedLateLintPass`. - let mut passes: Vec<_> = - unerased_lint_store(tcx).late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); + let mut passes: Vec<_> = unerased_lint_store(tcx.sess) + .late_module_passes + .iter() + .map(|mk_pass| (mk_pass)(tcx)) + .collect(); if passes.is_empty() { late_lint_mod_inner(tcx, module_def_id, context, builtin_lints); } else { @@ -400,7 +405,7 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { // Note: `passes` is often empty. let mut passes: Vec<_> = - unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); + unerased_lint_store(tcx.sess).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); if passes.is_empty() { return; @@ -411,8 +416,7 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { enclosing_body: None, cached_typeck_results: Cell::new(None), param_env: ty::ParamEnv::empty(), - effective_visibilities: &tcx.effective_visibilities(()), - lint_store: unerased_lint_store(tcx), + effective_visibilities: tcx.effective_visibilities(()), last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, only_module: false, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 0d20f6232db15..c1d4ed37627f2 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -56,7 +56,6 @@ struct LintLevelSets { } rustc_index::newtype_index! { - #[custom_encodable] // we don't need encoding struct LintStackIndex { const COMMAND_LINE = 0; } @@ -123,7 +122,7 @@ impl LintLevelSets { } fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { - let store = unerased_lint_store(tcx); + let store = unerased_lint_store(tcx.sess); let mut builder = LintLevelsBuilder { sess: tcx.sess, @@ -138,7 +137,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp }, warn_about_weird_lints: false, store, - registered_tools: &tcx.registered_tools(()), + registered_tools: tcx.registered_tools(()), }; builder.add_command_line(); @@ -152,7 +151,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp #[instrument(level = "trace", skip(tcx), ret)] fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap { - let store = unerased_lint_store(tcx); + let store = unerased_lint_store(tcx.sess); let attrs = tcx.hir_attrs(owner); let mut levels = LintLevelsBuilder { @@ -167,7 +166,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe }, warn_about_weird_lints: false, store, - registered_tools: &tcx.registered_tools(()), + registered_tools: tcx.registered_tools(()), }; if owner == hir::CRATE_OWNER_ID { @@ -548,10 +547,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { self.features } - pub(crate) fn lint_store(&self) -> &LintStore { - self.store - } - fn current_specs(&self) -> &FxHashMap { self.provider.current_specs() } @@ -609,7 +604,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let orig_level = level; let lint_flag_val = Symbol::intern(lint_name); - let Ok(ids) = self.store.find_lints(&lint_name) else { + let Ok(ids) = self.store.find_lints(lint_name) else { // errors already handled above continue; }; @@ -633,7 +628,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. fn insert_spec(&mut self, id: LintId, (mut level, src): LevelAndSource) { - let (old_level, old_src) = self.provider.get_lint_level(id.lint, &self.sess); + let (old_level, old_src) = self.provider.get_lint_level(id.lint, self.sess); if let Level::Expect(id) = &mut level && let LintExpectationId::Stable { .. } = id { @@ -741,7 +736,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if attr.has_name(sym::doc) && attr .meta_item_list() - .map_or(false, |l| ast::attr::list_contains_name(&l, sym::hidden)) + .is_some_and(|l| ast::attr::list_contains_name(&l, sym::hidden)) { self.insert(LintId::of(MISSING_DOCS), (Level::Allow, LintLevelSource::Default)); continue; @@ -933,12 +928,12 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { DeprecatedLintName { name, suggestion: sp, - replace: &new_lint_name, + replace: new_lint_name, }, ); let src = LintLevelSource::Node { - name: Symbol::intern(&new_lint_name), + name: Symbol::intern(new_lint_name), span: sp, reason, }; diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 54adedd3c0988..8e95a71e11f1e 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -27,8 +27,8 @@ #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(array_windows)] #![feature(box_patterns)] #![feature(control_flow_enum)] @@ -39,6 +39,7 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] +#![cfg_attr(bootstrap, feature(trait_upcasting))] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -85,12 +86,11 @@ mod redundant_semicolon; mod reference_casting; mod traits; mod types; +mod unit_bindings; mod unused; pub use array_into_iter::ARRAY_INTO_ITER; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_hir::def_id::LocalModDefId; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; @@ -123,6 +123,7 @@ use redundant_semicolon::*; use reference_casting::*; use traits::*; use types::*; +use unit_bindings::*; use unused::*; /// Useful for other parts of the compiler / Clippy. @@ -136,7 +137,7 @@ pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId}; pub use rustc_session::lint::{LintPass, LintVec}; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { levels::provide(providers); @@ -179,7 +180,6 @@ early_lint_methods!( IncompleteInternalFeatures: IncompleteInternalFeatures, RedundantSemicolons: RedundantSemicolons, UnusedDocComment: UnusedDocComment, - UnexpectedCfgs: UnexpectedCfgs, ] ] ); @@ -203,6 +203,7 @@ late_lint_methods!( InvalidReferenceCasting: InvalidReferenceCasting, // Depends on referenced function signatures in expressions UnusedResults: UnusedResults, + UnitBindings: UnitBindings, NonUpperCaseGlobals: NonUpperCaseGlobals, NonShorthandFieldPatterns: NonShorthandFieldPatterns, UnusedAllocation: UnusedAllocation, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 756899e50a8cd..9fda53c25334a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -250,7 +250,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { diag.span_label(self.label, fluent::lint_label); rustc_session::parse::add_feature_diagnostics( diag, - &self.parse_sess, + self.parse_sess, sym::async_fn_track_caller, ); diag @@ -553,33 +553,22 @@ pub enum BuiltinSpecialModuleNameUsed { Main, } -#[derive(LintDiagnostic)] -#[diag(lint_builtin_unexpected_cli_config_name)] -#[help] -pub struct BuiltinUnexpectedCliConfigName { - pub name: Symbol, -} - -#[derive(LintDiagnostic)] -#[diag(lint_builtin_unexpected_cli_config_value)] -#[help] -pub struct BuiltinUnexpectedCliConfigValue { - pub name: Symbol, - pub value: Symbol, -} - // deref_into_dyn_supertrait.rs #[derive(LintDiagnostic)] #[diag(lint_supertrait_as_deref_target)] +#[help] pub struct SupertraitAsDerefTarget<'a> { - pub t: Ty<'a>, + pub self_ty: Ty<'a>, + pub supertrait_principal: PolyExistentialTraitRef<'a>, pub target_principal: PolyExistentialTraitRef<'a>, + #[label] + pub label: Span, #[subdiagnostic] - pub label: Option, + pub label2: Option, } #[derive(Subdiagnostic)] -#[label(lint_label)] +#[label(lint_label2)] pub struct SupertraitAsDerefTargetLabel { #[primary_span] pub label: Span, @@ -1845,3 +1834,10 @@ impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag { fluent::lint_async_fn_in_trait } } + +#[derive(LintDiagnostic)] +#[diag(lint_unit_bindings)] +pub struct UnitBindingsDiag { + #[label] + pub label: Span, +} diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 62bb8c2c67d2b..4f92fcd71c63d 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -204,7 +204,7 @@ impl EarlyLintPass for NonAsciiIdents { // Get the skeleton as a `Symbol`. skeleton_buf.clear(); - skeleton_buf.extend(skeleton(&symbol_str)); + skeleton_buf.extend(skeleton(symbol_str)); let skeleton_sym = if *symbol_str == *skeleton_buf { symbol } else { diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index b218cc5789df1..f0e415492ae96 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -154,17 +154,13 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc let infcx = cx.tcx.infer_ctxt().build(); let suggest_display = is_str - || cx - .tcx - .get_diagnostic_item(sym::Display) - .map(|t| infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()) - == Some(true); + || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| { + infcx.type_implements_trait(t, [ty], cx.param_env).may_apply() + }); let suggest_debug = !suggest_display - && cx - .tcx - .get_diagnostic_item(sym::Debug) - .map(|t| infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()) - == Some(true); + && cx.tcx.get_diagnostic_item(sym::Debug).is_some_and(|t| { + infcx.type_implements_trait(t, [ty], cx.param_env).may_apply() + }); let suggest_panic_any = !is_str && panic == sym::std_panic_macro; diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 66dc726df8921..59f27a88aec63 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -334,7 +334,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name { Some(Ident::from_str(name)) } else { - attr::find_by_name(&cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name) + attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name) .and_then(|attr| attr.meta()) .and_then(|meta| { meta.name_value_literal().and_then(|lit| { @@ -473,7 +473,7 @@ impl NonUpperCaseGlobals { fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) { let name = ident.name.as_str(); if name.chars().any(|c| c.is_lowercase()) { - let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); + let uc = NonSnakeCase::to_snake_case(name).to_uppercase(); // We cannot provide meaningful suggestions // if the characters are in the category of "Lowercase Letter". let sub = if *name != uc { @@ -520,7 +520,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) { // Lint for constants that look like binding identifiers (#7526) - if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.kind { + if let PatKind::Path(hir::QPath::Resolved(None, path)) = p.kind { if let Res::Def(DefKind::Const, _) = path.res { if path.segments.len() == 1 { NonUpperCaseGlobals::check_upper_case( @@ -534,9 +534,9 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { } fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) { - if let GenericParamKind::Const { .. } = param.kind { - // `rustc_host` params are explicitly allowed to be lowercase. - if cx.tcx.has_attr(param.def_id, sym::rustc_host) { + if let GenericParamKind::Const { is_host_effect, .. } = param.kind { + // `host` params are explicitly allowed to be lowercase. + if is_host_effect { return; } NonUpperCaseGlobals::check_upper_case(cx, "const parameter", ¶m.name.ident()); diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index c24846ca93988..44b23b8bdc0c3 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { for (assoc_pred, assoc_pred_span) in cx .tcx .explicit_item_bounds(proj.projection_ty.def_id) - .iter_instantiated_copied(cx.tcx, &proj.projection_ty.args) + .iter_instantiated_copied(cx.tcx, proj.projection_ty.args) { let assoc_pred = assoc_pred.fold_with(proj_replacer); let Ok(assoc_pred) = traits::fully_normalize( diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index cad2cd7fa4c8b..fce750c9b558f 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -28,7 +28,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue { return; } } - if let Some(t) = path_for_pass_by_value(cx, &inner_ty) { + if let Some(t) = path_for_pass_by_value(cx, inner_ty) { cx.emit_spanned_lint( PASS_BY_VALUE, ty.span, diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index d44691b5e9bac..82483ac7dc0fd 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -155,7 +155,7 @@ fn is_cast_from_const_to_mut<'tcx>( let start_ty = cx.typeck_results().node_type(e.hir_id); if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() { - // If an UnsafeCell method is involved we need to additionaly check the + // If an UnsafeCell method is involved we need to additionally check the // inner type for the presence of the Freeze trait (ie does NOT contain // an UnsafeCell), since in that case we would incorrectly lint on valid casts. // diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index c04053d1865db..bae63ae171645 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -623,7 +623,7 @@ fn lint_nan<'tcx>( impl<'tcx> LateLintPass<'tcx> for TypeLimits { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) { match e.kind { - hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => { // Propagate negation, if the negation itself isn't negated if self.negated_expr_id != Some(e.hir_id) { self.negated_expr_id = Some(expr.hir_id); @@ -632,14 +632,14 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { } hir::ExprKind::Binary(binop, ref l, ref r) => { if is_comparison(binop) { - if !check_limits(cx, binop, &l, &r) { + if !check_limits(cx, binop, l, r) { cx.emit_spanned_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons); } else { lint_nan(cx, e, binop, l, r); } } } - hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit), + hir::ExprKind::Lit(lit) => lint_literal(cx, self, e, lit), _ => {} }; @@ -685,7 +685,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { ty::Int(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i128 = match lit.kind { - hir::ExprKind::Lit(ref li) => match li.node { + hir::ExprKind::Lit(li) => match li.node { ast::LitKind::Int( v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed, @@ -699,7 +699,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { ty::Uint(uint_ty) => { let (min, max): (u128, u128) = uint_ty_range(uint_ty); let lit_val: u128 = match lit.kind { - hir::ExprKind::Lit(ref li) => match li.node { + hir::ExprKind::Lit(li) => match li.node { ast::LitKind::Int(v, _) => v, _ => return true, }, @@ -1015,7 +1015,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // We can't completely trust `repr(C)` markings, so make sure the fields are actually safe. let mut all_phantom = !variant.fields.is_empty(); for field in &variant.fields { - all_phantom &= match self.check_field_type_for_ffi(cache, &field, args) { + all_phantom &= match self.check_field_type_for_ffi(cache, field, args) { FfiSafe => false, // `()` fields are FFI-safe! FfiUnsafe { ty, .. } if ty.is_unit() => false, @@ -1234,7 +1234,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - let sig = tcx.erase_late_bound_regions(sig); + let sig = tcx.instantiate_bound_regions_with_erased(sig); for arg in sig.inputs() { match self.check_type_for_ffi(cache, *arg) { FfiSafe => {} @@ -1391,7 +1391,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// types that have external ABIs, as these still need checked. fn check_fn(&mut self, def_id: LocalDefId, decl: &'tcx hir::FnDecl<'_>) { let sig = self.cx.tcx.fn_sig(def_id).instantiate_identity(); - let sig = self.cx.tcx.erase_late_bound_regions(sig); + let sig = self.cx.tcx.instantiate_bound_regions_with_erased(sig); for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { for (fn_ptr_ty, span) in self.find_fn_ptr_ty_with_external_abi(input_hir, *input_ty) { @@ -1399,7 +1399,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } - if let hir::FnRetTy::Return(ref ret_hir) = decl.output { + if let hir::FnRetTy::Return(ret_hir) = decl.output { for (fn_ptr_ty, span) in self.find_fn_ptr_ty_with_external_abi(ret_hir, sig.output()) { self.check_type_for_ffi_and_report_errors(span, fn_ptr_ty, false, true); } @@ -1409,13 +1409,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Check if a function's argument types and result type are "ffi-safe". fn check_foreign_fn(&mut self, def_id: LocalDefId, decl: &'tcx hir::FnDecl<'_>) { let sig = self.cx.tcx.fn_sig(def_id).instantiate_identity(); - let sig = self.cx.tcx.erase_late_bound_regions(sig); + let sig = self.cx.tcx.instantiate_bound_regions_with_erased(sig); for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) { self.check_type_for_ffi_and_report_errors(input_hir.span, *input_ty, false, false); } - if let hir::FnRetTy::Return(ref ret_hir) = decl.output { + if let hir::FnRetTy::Return(ret_hir) = decl.output { self.check_type_for_ffi_and_report_errors(ret_hir.span, sig.output(), false, true); } } @@ -1487,13 +1487,13 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations { let abi = cx.tcx.hir().get_foreign_abi(it.hir_id()); match it.kind { - hir::ForeignItemKind::Fn(ref decl, _, _) if !vis.is_internal_abi(abi) => { + hir::ForeignItemKind::Fn(decl, _, _) if !vis.is_internal_abi(abi) => { vis.check_foreign_fn(it.owner_id.def_id, decl); } - hir::ForeignItemKind::Static(ref ty, _) if !vis.is_internal_abi(abi) => { + hir::ForeignItemKind::Static(ty, _) if !vis.is_internal_abi(abi) => { vis.check_foreign_static(it.owner_id, ty.span); } - hir::ForeignItemKind::Fn(ref decl, _, _) => vis.check_fn(it.owner_id.def_id, decl), + hir::ForeignItemKind::Fn(decl, _, _) => vis.check_fn(it.owner_id.def_id, decl), hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => (), } } @@ -1705,7 +1705,7 @@ impl InvalidAtomicOrdering { sym::AtomicI64, sym::AtomicI128, ]; - if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind + if let ExprKind::MethodCall(method_path, _, args, _) = &expr.kind && recognized_names.contains(&method_path.ident.name) && let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && let Some(impl_did) = cx.tcx.impl_of_method(m_def_id) @@ -1766,7 +1766,7 @@ impl InvalidAtomicOrdering { } fn check_memory_fence(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Call(ref func, ref args) = expr.kind + if let ExprKind::Call(func, args) = expr.kind && let ExprKind::Path(ref func_qpath) = func.kind && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id() && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence)) diff --git a/compiler/rustc_lint/src/unit_bindings.rs b/compiler/rustc_lint/src/unit_bindings.rs new file mode 100644 index 0000000000000..c80889f3ae752 --- /dev/null +++ b/compiler/rustc_lint/src/unit_bindings.rs @@ -0,0 +1,72 @@ +use crate::lints::UnitBindingsDiag; +use crate::{LateLintPass, LintContext}; +use rustc_hir as hir; +use rustc_middle::ty::Ty; + +declare_lint! { + /// The `unit_bindings` lint detects cases where bindings are useless because they have + /// the unit type `()` as their inferred type. The lint is suppressed if the user explicitly + /// annotates the let binding with the unit type `()`, or if the let binding uses an underscore + /// wildcard pattern, i.e. `let _ = expr`, or if the binding is produced from macro expansions. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(unit_bindings)] + /// + /// fn foo() { + /// println!("do work"); + /// } + /// + /// pub fn main() { + /// let x = foo(); // useless binding + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Creating a local binding with the unit type `()` does not do much and can be a sign of a + /// user error, such as in this example: + /// + /// ```rust,no_run + /// fn main() { + /// let mut x = [1, 2, 3]; + /// x[0] = 5; + /// let y = x.sort(); // useless binding as `sort` returns `()` and not the sorted array. + /// println!("{:?}", y); // prints "()" + /// } + /// ``` + pub UNIT_BINDINGS, + Allow, + "binding is useless because it has the unit `()` type" +} + +declare_lint_pass!(UnitBindings => [UNIT_BINDINGS]); + +impl<'tcx> LateLintPass<'tcx> for UnitBindings { + fn check_local(&mut self, cx: &crate::LateContext<'tcx>, local: &'tcx hir::Local<'tcx>) { + // Suppress warning if user: + // - explicitly ascribes a type to the pattern + // - explicitly wrote `let pat = ();` + // - explicitly wrote `let () = init;`. + if !local.span.from_expansion() + && let Some(tyck_results) = cx.maybe_typeck_results() + && let Some(init) = local.init + && let init_ty = tyck_results.expr_ty(init) + && let local_ty = tyck_results.node_type(local.hir_id) + && init_ty == Ty::new_unit(cx.tcx) + && local_ty == Ty::new_unit(cx.tcx) + && local.ty.is_none() + && !matches!(init.kind, hir::ExprKind::Tup([])) + && !matches!(local.pat.kind, hir::PatKind::Tuple([], ..)) + { + cx.emit_spanned_lint( + UNIT_BINDINGS, + local.span, + UnitBindingsDiag { label: local.pat.span }, + ); + } + } +} diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 355855b8e2b3e..34cdee4ec5c1a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind - && let ty = cx.typeck_results().expr_ty(&await_expr) + && let ty = cx.typeck_results().expr_ty(await_expr) && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind() && cx.tcx.ty_is_opaque_future(ty) && let async_fn_def_id = cx.tcx.parent(*future_def_id) @@ -132,9 +132,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { return; } - let ty = cx.typeck_results().expr_ty(&expr); + let ty = cx.typeck_results().expr_ty(expr); - let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span); + let must_use_result = is_ty_must_use(cx, ty, expr, expr.span); let type_lint_emitted_or_suppressed = match must_use_result { Some(path) => { emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block); @@ -211,7 +211,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { expr_is_from_block: bool, ) -> bool { let maybe_def_id = match expr.kind { - hir::ExprKind::Call(ref callee, _) => { + hir::ExprKind::Call(callee, _) => { match callee.kind { hir::ExprKind::Path(ref qpath) => { match cx.qpath_res(qpath, callee.hir_id) { @@ -251,6 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { /// The root of the normal must_use lint with an optional message. Def(Span, DefId, Option), Boxed(Box), + Pinned(Box), Opaque(Box), TraitObject(Box), TupleElement(Vec<(usize, Self)>), @@ -284,8 +285,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { is_ty_must_use(cx, boxed_ty, expr, span) .map(|inner| MustUsePath::Boxed(Box::new(inner))) } + ty::Adt(def, args) if cx.tcx.lang_items().pin_type() == Some(def.did()) => { + let pinned_ty = args.type_at(0); + is_ty_must_use(cx, pinned_ty, expr, span) + .map(|inner| MustUsePath::Pinned(Box::new(inner))) + } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), - ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { + ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => { elaborate( cx.tcx, cx.tcx.explicit_item_bounds(def).instantiate_identity_iter_copied(), @@ -425,6 +431,18 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { expr_is_from_block, ); } + MustUsePath::Pinned(path) => { + let descr_pre = &format!("{descr_pre}pinned "); + emit_must_use_untranslated( + cx, + path, + descr_pre, + descr_post, + plural_len, + true, + expr_is_from_block, + ); + } MustUsePath::Opaque(path) => { let descr_pre = &format!("{descr_pre}implementer{plural_suffix} of "); emit_must_use_untranslated( @@ -638,7 +656,7 @@ trait UnusedDelimLint { ) -> bool { if followed_by_else { match inner.kind { - ast::ExprKind::Binary(op, ..) if op.node.lazy() => return true, + ast::ExprKind::Binary(op, ..) if op.node.is_lazy() => return true, _ if classify::expr_trailing_brace(inner).is_some() => return true, _ => {} } @@ -674,7 +692,7 @@ trait UnusedDelimLint { innermost = match &innermost.kind { ExprKind::AddrOf(_, _, expr) => expr, _ => { - if parser::contains_exterior_struct_lit(&innermost) { + if parser::contains_exterior_struct_lit(innermost) { return true; } else { break; @@ -703,7 +721,7 @@ trait UnusedDelimLint { return matches!(rhs.kind, ExprKind::Block(..)); } - _ => return parser::contains_exterior_struct_lit(&inner), + _ => return parser::contains_exterior_struct_lit(inner), } } } @@ -878,7 +896,7 @@ trait UnusedDelimLint { }; self.check_unused_delims_expr( cx, - &value, + value, ctx, followed_by_block, left_pos, @@ -901,7 +919,7 @@ trait UnusedDelimLint { StmtKind::Expr(ref expr) => { self.check_unused_delims_expr( cx, - &expr, + expr, UnusedDelimsCtx::BlockRetValue, false, None, @@ -998,7 +1016,7 @@ impl UnusedDelimLint for UnusedParens { rustc_span::source_map::Spanned { node, .. }, _, _, - ) if node.lazy())) + ) if node.is_lazy())) { self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw) } @@ -1095,15 +1113,17 @@ impl EarlyLintPass for UnusedParens { } ExprKind::Match(ref _expr, ref arm) => { for a in arm { - self.check_unused_delims_expr( - cx, - &a.body, - UnusedDelimsCtx::MatchArmExpr, - false, - None, - None, - true, - ); + if let Some(body) = &a.body { + self.check_unused_delims_expr( + cx, + body, + UnusedDelimsCtx::MatchArmExpr, + false, + None, + None, + true, + ); + } } } _ => {} @@ -1136,7 +1156,7 @@ impl EarlyLintPass for UnusedParens { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) // The other cases do not contain sub-patterns. - | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {}, + | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { self.check_unused_parens_pat(cx, p, false, false, keep_space); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 918e484b9f44d..e6e445c54b1e3 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -8,6 +8,135 @@ use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::symbol::sym; +declare_lint_pass! { + /// Does nothing as a lint pass, but registers some `Lint`s + /// that are used by other parts of the compiler. + HardwiredLints => [ + // tidy-alphabetical-start + ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, + AMBIGUOUS_ASSOCIATED_ITEMS, + AMBIGUOUS_GLOB_IMPORTS, + AMBIGUOUS_GLOB_REEXPORTS, + ARITHMETIC_OVERFLOW, + ASM_SUB_REGISTER, + BAD_ASM_STYLE, + BARE_TRAIT_OBJECTS, + BINDINGS_WITH_VARIANT_NAME, + BREAK_WITH_LABEL_AND_LOOP, + BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE, + CENUM_IMPL_DROP_CAST, + COHERENCE_LEAK_CHECK, + COINDUCTIVE_OVERLAP_IN_COHERENCE, + CONFLICTING_REPR_HINTS, + CONST_EVALUATABLE_UNCHECKED, + CONST_ITEM_MUTATION, + CONST_PATTERNS_WITHOUT_PARTIAL_EQ, + DEAD_CODE, + DEPRECATED, + DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + DEPRECATED_IN_FUTURE, + DEPRECATED_WHERE_CLAUSE_LOCATION, + DUPLICATE_MACRO_ATTRIBUTES, + ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, + ELIDED_LIFETIMES_IN_PATHS, + EXPORTED_PRIVATE_DEPENDENCIES, + FFI_UNWIND_CALLS, + FORBIDDEN_LINT_GROUPS, + FUNCTION_ITEM_REFERENCES, + FUZZY_PROVENANCE_CASTS, + HIDDEN_GLOB_REEXPORTS, + ILL_FORMED_ATTRIBUTE_INPUT, + ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, + IMPLIED_BOUNDS_ENTAILMENT, + INCOMPLETE_INCLUDE, + INDIRECT_STRUCTURAL_MATCH, + INEFFECTIVE_UNSTABLE_TRAIT_IMPL, + INLINE_NO_SANITIZE, + INVALID_DOC_ATTRIBUTES, + INVALID_MACRO_EXPORT_ARGUMENTS, + INVALID_TYPE_PARAM_DEFAULT, + IRREFUTABLE_LET_PATTERNS, + LARGE_ASSIGNMENTS, + LATE_BOUND_LIFETIME_ARGUMENTS, + LEGACY_DERIVE_HELPERS, + LONG_RUNNING_CONST_EVAL, + LOSSY_PROVENANCE_CASTS, + MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, + MACRO_USE_EXTERN_CRATE, + META_VARIABLE_MISUSE, + MISSING_ABI, + MISSING_FRAGMENT_SPECIFIER, + MUST_NOT_SUSPEND, + NAMED_ARGUMENTS_USED_POSITIONALLY, + NON_EXHAUSTIVE_OMITTED_PATTERNS, + NONTRIVIAL_STRUCTURAL_MATCH, + ORDER_DEPENDENT_TRAIT_OBJECTS, + OVERLAPPING_RANGE_ENDPOINTS, + PATTERNS_IN_FNS_WITHOUT_BODY, + POINTER_STRUCTURAL_MATCH, + PRIVATE_BOUNDS, + PRIVATE_INTERFACES, + PROC_MACRO_BACK_COMPAT, + PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, + PUB_USE_OF_PRIVATE_EXTERN_CRATE, + REFINING_IMPL_TRAIT, + RENAMED_AND_REMOVED_LINTS, + REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, + RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, + RUST_2021_INCOMPATIBLE_OR_PATTERNS, + RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, + RUST_2021_PRELUDE_COLLISIONS, + SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, + SINGLE_USE_LIFETIMES, + SOFT_UNSTABLE, + STABLE_FEATURES, + SUSPICIOUS_AUTO_TRAIT_IMPLS, + TEST_UNSTABLE_LINT, + TEXT_DIRECTION_CODEPOINT_IN_COMMENT, + TRIVIAL_CASTS, + TRIVIAL_NUMERIC_CASTS, + TYVAR_BEHIND_RAW_POINTER, + UNCONDITIONAL_PANIC, + UNCONDITIONAL_RECURSION, + UNDEFINED_NAKED_FUNCTION_ABI, + UNEXPECTED_CFGS, + UNFULFILLED_LINT_EXPECTATIONS, + UNINHABITED_STATIC, + UNKNOWN_CRATE_TYPES, + UNKNOWN_LINTS, + UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, + UNNAMEABLE_TEST_ITEMS, + UNNAMEABLE_TYPES, + UNREACHABLE_CODE, + UNREACHABLE_PATTERNS, + UNSAFE_OP_IN_UNSAFE_FN, + UNSTABLE_NAME_COLLISIONS, + UNSTABLE_SYNTAX_PRE_EXPANSION, + UNSUPPORTED_CALLING_CONVENTIONS, + UNUSED_ASSIGNMENTS, + UNUSED_ASSOCIATED_TYPE_BOUNDS, + UNUSED_ATTRIBUTES, + UNUSED_CRATE_DEPENDENCIES, + UNUSED_EXTERN_CRATES, + UNUSED_FEATURES, + UNUSED_IMPORTS, + UNUSED_LABELS, + UNUSED_LIFETIMES, + UNUSED_MACRO_RULES, + UNUSED_MACROS, + UNUSED_MUT, + UNUSED_QUALIFICATIONS, + UNUSED_TUPLE_STRUCT_FIELDS, + UNUSED_UNSAFE, + UNUSED_VARIABLES, + USELESS_DEPRECATED, + WARNINGS, + WHERE_CLAUSES_OBJECT_SAFETY, + WRITES_THROUGH_IMMUTABLE_POINTER, + // tidy-alphabetical-end + ] +} + declare_lint! { /// The `forbidden_lint_groups` lint detects violations of /// `forbid` applied to a lint group. Due to a bug in the compiler, @@ -2217,15 +2346,16 @@ declare_lint! { /// /// ### Explanation /// - /// Previous versions of Rust allowed function pointers and wide raw pointers in patterns. + /// Previous versions of Rust allowed function pointers and all raw pointers in patterns. /// While these work in many cases as expected by users, it is possible that due to /// optimizations pointers are "not equal to themselves" or pointers to different functions /// compare as equal during runtime. This is because LLVM optimizations can deduplicate /// functions if their bodies are the same, thus also making pointers to these functions point /// to the same location. Additionally functions may get duplicated if they are instantiated - /// in different crates and not deduplicated again via LTO. + /// in different crates and not deduplicated again via LTO. Pointer identity for memory + /// created by `const` is similarly unreliable. pub POINTER_STRUCTURAL_MATCH, - Allow, + Warn, "pointers are not structural-match", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, @@ -3134,7 +3264,7 @@ declare_lint! { /// ### Example /// /// ```text - /// rustc --check-cfg 'names()' + /// rustc --check-cfg 'cfg()' /// ``` /// /// ```rust,ignore (needs command line option) @@ -3145,7 +3275,7 @@ declare_lint! { /// This will produce: /// /// ```text - /// warning: unknown condition name used + /// warning: unexpected `cfg` condition name: `widnows` /// --> lint_example.rs:1:7 /// | /// 1 | #[cfg(widnows)] @@ -3156,9 +3286,10 @@ declare_lint! { /// /// ### Explanation /// - /// This lint is only active when a `--check-cfg='names(...)'` option has been passed - /// to the compiler and triggers whenever an unknown condition name or value is used. - /// The known condition include names or values passed in `--check-cfg`, `--cfg`, and some + /// This lint is only active when `--check-cfg` arguments are being passed + /// to the compiler and triggers whenever an unexpected condition name or value is used. + /// + /// The known condition include names or values passed in `--check-cfg`, and some /// well-knows names and values built into the compiler. pub UNEXPECTED_CFGS, Warn, @@ -3347,133 +3478,6 @@ declare_lint! { "name introduced by a private item shadows a name introduced by a public glob re-export", } -declare_lint_pass! { - /// Does nothing as a lint pass, but registers some `Lint`s - /// that are used by other parts of the compiler. - HardwiredLints => [ - // tidy-alphabetical-start - ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, - AMBIGUOUS_ASSOCIATED_ITEMS, - AMBIGUOUS_GLOB_IMPORTS, - AMBIGUOUS_GLOB_REEXPORTS, - ARITHMETIC_OVERFLOW, - ASM_SUB_REGISTER, - BAD_ASM_STYLE, - BARE_TRAIT_OBJECTS, - BINDINGS_WITH_VARIANT_NAME, - BREAK_WITH_LABEL_AND_LOOP, - BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE, - CENUM_IMPL_DROP_CAST, - COHERENCE_LEAK_CHECK, - COINDUCTIVE_OVERLAP_IN_COHERENCE, - CONFLICTING_REPR_HINTS, - CONST_EVALUATABLE_UNCHECKED, - CONST_ITEM_MUTATION, - CONST_PATTERNS_WITHOUT_PARTIAL_EQ, - DEAD_CODE, - DEPRECATED, - DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, - DEPRECATED_IN_FUTURE, - DEPRECATED_WHERE_CLAUSE_LOCATION, - DUPLICATE_MACRO_ATTRIBUTES, - ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, - ELIDED_LIFETIMES_IN_PATHS, - EXPORTED_PRIVATE_DEPENDENCIES, - FFI_UNWIND_CALLS, - FORBIDDEN_LINT_GROUPS, - FUNCTION_ITEM_REFERENCES, - FUZZY_PROVENANCE_CASTS, - HIDDEN_GLOB_REEXPORTS, - ILL_FORMED_ATTRIBUTE_INPUT, - ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, - IMPLIED_BOUNDS_ENTAILMENT, - INCOMPLETE_INCLUDE, - INDIRECT_STRUCTURAL_MATCH, - INEFFECTIVE_UNSTABLE_TRAIT_IMPL, - INLINE_NO_SANITIZE, - INVALID_DOC_ATTRIBUTES, - INVALID_MACRO_EXPORT_ARGUMENTS, - INVALID_TYPE_PARAM_DEFAULT, - IRREFUTABLE_LET_PATTERNS, - LARGE_ASSIGNMENTS, - LATE_BOUND_LIFETIME_ARGUMENTS, - LEGACY_DERIVE_HELPERS, - LONG_RUNNING_CONST_EVAL, - LOSSY_PROVENANCE_CASTS, - MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, - MACRO_USE_EXTERN_CRATE, - META_VARIABLE_MISUSE, - MISSING_ABI, - MISSING_FRAGMENT_SPECIFIER, - MUST_NOT_SUSPEND, - NAMED_ARGUMENTS_USED_POSITIONALLY, - NON_EXHAUSTIVE_OMITTED_PATTERNS, - NONTRIVIAL_STRUCTURAL_MATCH, - ORDER_DEPENDENT_TRAIT_OBJECTS, - OVERLAPPING_RANGE_ENDPOINTS, - PATTERNS_IN_FNS_WITHOUT_BODY, - POINTER_STRUCTURAL_MATCH, - PRIVATE_BOUNDS, - PRIVATE_INTERFACES, - PROC_MACRO_BACK_COMPAT, - PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, - PUB_USE_OF_PRIVATE_EXTERN_CRATE, - REFINING_IMPL_TRAIT, - RENAMED_AND_REMOVED_LINTS, - REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, - RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, - RUST_2021_INCOMPATIBLE_OR_PATTERNS, - RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, - RUST_2021_PRELUDE_COLLISIONS, - SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, - SINGLE_USE_LIFETIMES, - SOFT_UNSTABLE, - STABLE_FEATURES, - SUSPICIOUS_AUTO_TRAIT_IMPLS, - TEST_UNSTABLE_LINT, - TEXT_DIRECTION_CODEPOINT_IN_COMMENT, - TRIVIAL_CASTS, - TRIVIAL_NUMERIC_CASTS, - TYVAR_BEHIND_RAW_POINTER, - UNCONDITIONAL_PANIC, - UNCONDITIONAL_RECURSION, - UNDEFINED_NAKED_FUNCTION_ABI, - UNFULFILLED_LINT_EXPECTATIONS, - UNINHABITED_STATIC, - UNKNOWN_CRATE_TYPES, - UNKNOWN_LINTS, - UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, - UNNAMEABLE_TEST_ITEMS, - UNNAMEABLE_TYPES, - UNREACHABLE_CODE, - UNREACHABLE_PATTERNS, - UNSAFE_OP_IN_UNSAFE_FN, - UNSTABLE_NAME_COLLISIONS, - UNSTABLE_SYNTAX_PRE_EXPANSION, - UNSUPPORTED_CALLING_CONVENTIONS, - UNUSED_ASSIGNMENTS, - UNUSED_ASSOCIATED_TYPE_BOUNDS, - UNUSED_ATTRIBUTES, - UNUSED_CRATE_DEPENDENCIES, - UNUSED_EXTERN_CRATES, - UNUSED_FEATURES, - UNUSED_IMPORTS, - UNUSED_LABELS, - UNUSED_LIFETIMES, - UNUSED_MACRO_RULES, - UNUSED_MACROS, - UNUSED_MUT, - UNUSED_QUALIFICATIONS, - UNUSED_TUPLE_STRUCT_FIELDS, - UNUSED_UNSAFE, - UNUSED_VARIABLES, - USELESS_DEPRECATED, - WARNINGS, - WHERE_CLAUSES_OBJECT_SAFETY, - // tidy-alphabetical-end - ] -} - declare_lint! { /// The `long_running_const_eval` lint is emitted when const /// eval is running for a long time to ensure rustc terminates @@ -4618,3 +4622,37 @@ declare_lint! { reference: "issue #115010 ", }; } + +declare_lint! { + /// The `writes_through_immutable_pointer` lint detects writes through pointers derived from + /// shared references. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![feature(const_mut_refs)] + /// const WRITE_AFTER_CAST: () = unsafe { + /// let mut x = 0; + /// let ptr = &x as *const i32 as *mut i32; + /// *ptr = 0; + /// }; + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Shared references are immutable (when there is no `UnsafeCell` involved), + /// and writing through them or through pointers derived from them is Undefined Behavior. + /// The compiler recently learned to detect such Undefined Behavior during compile-time + /// evaluation, and in the future this will raise a hard error. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub WRITES_THROUGH_IMMUTABLE_POINTER, + Warn, + "shared references are immutable, and pointers derived from them must not be written to", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #X ", + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 878c1a65dbf6e..de0abe04611d7 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -583,6 +583,10 @@ pub enum BuiltinLintDiagnostics { elided: bool, span: Span, }, + RedundantImportVisibility { + span: Span, + max_vis: String, + }, } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index fe13162cd4a3c..4b0c1229da134 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -102,7 +102,7 @@ fn output(cmd: &mut Command) -> String { fn main() { for component in REQUIRED_COMPONENTS.iter().chain(OPTIONAL_COMPONENTS.iter()) { - println!("cargo:rustc-check-cfg=values(llvm_component,\"{component}\")"); + println!("cargo:rustc-check-cfg=cfg(llvm_component,values(\"{component}\"))"); } if tracked_env_var_os("RUST_CHECK").is_some() { @@ -242,6 +242,12 @@ fn main() { cmd.arg("--system-libs"); } + // We need libkstat for getHostCPUName on SPARC builds. + // See also: https://github.com/llvm/llvm-project/issues/64186 + if target.starts_with("sparcv9") && target.contains("solaris") { + println!("cargo:rustc-link-lib=kstat"); + } + if (target.starts_with("arm") && !target.contains("freebsd")) || target.starts_with("mips-") || target.starts_with("mipsel-") diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 3f2bf2c9b444d..5bfffc5d9117b 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -1,3 +1,5 @@ +#include "SuppressLLVMWarnings.h" + #include "llvm-c/BitReader.h" #include "llvm-c/Core.h" #include "llvm-c/Object.h" @@ -25,7 +27,6 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Vectorize.h" #define LLVM_VERSION_GE(major, minor) \ (LLVM_VERSION_MAJOR > (major) || \ @@ -43,11 +44,7 @@ #include "llvm/IR/IRPrintingPasses.h" #include "llvm/Linker/Linker.h" -#if LLVM_VERSION_GE(16, 0) #include "llvm/TargetParser/Triple.h" -#else -#include "llvm/ADT/Triple.h" -#endif extern "C" void LLVMRustSetLastError(const char *); @@ -94,6 +91,7 @@ enum LLVMRustAttribute { AllocatedPointer = 38, AllocAlign = 39, SanitizeSafeStack = 40, + FnRetThunkExtern = 41, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/compiler/rustc_llvm/llvm-wrapper/Linker.cpp b/compiler/rustc_llvm/llvm-wrapper/Linker.cpp index 8766e96f086d2..533df0f75f8f5 100644 --- a/compiler/rustc_llvm/llvm-wrapper/Linker.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/Linker.cpp @@ -1,3 +1,4 @@ +#include "SuppressLLVMWarnings.h" #include "llvm/Linker/Linker.h" #include "LLVMWrapper.h" diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 31565db1b7929..0edcac93b6224 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -60,17 +60,17 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) -extern "C" void LLVMTimeTraceProfilerInitialize() { +extern "C" void LLVMRustTimeTraceProfilerInitialize() { timeTraceProfilerInitialize( /* TimeTraceGranularity */ 0, /* ProcName */ "rustc"); } -extern "C" void LLVMTimeTraceProfilerFinishThread() { +extern "C" void LLVMRustTimeTraceProfilerFinishThread() { timeTraceProfilerFinishThread(); } -extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { +extern "C" void LLVMRustTimeTraceProfilerFinish(const char* FileName) { StringRef FN(FileName); std::error_code EC; raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways); @@ -204,11 +204,7 @@ enum class LLVMRustCodeModel { None, }; -#if LLVM_VERSION_LT(16, 0) -static Optional -#else static std::optional -#endif fromRust(LLVMRustCodeModel Model) { switch (Model) { case LLVMRustCodeModel::Tiny: @@ -222,11 +218,7 @@ fromRust(LLVMRustCodeModel Model) { case LLVMRustCodeModel::Large: return CodeModel::Large; case LLVMRustCodeModel::None: -#if LLVM_VERSION_LT(16, 0) - return None; -#else return std::nullopt; -#endif default: report_fatal_error("Bad CodeModel."); } @@ -452,7 +444,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( if (OutputObjFile) { Options.ObjectFilenameForDebug = OutputObjFile; } -#if LLVM_VERSION_GE(16, 0) if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) { Options.CompressDebugSections = DebugCompressionType::Zlib; } else if (!strcmp("zstd", DebugInfoCompression) && llvm::compression::zstd::isAvailable()) { @@ -460,7 +451,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( } else if (!strcmp("none", DebugInfoCompression)) { Options.CompressDebugSections = DebugCompressionType::None; } -#endif Options.RelaxELFRelocations = RelaxELFRelocations; Options.UseInitArray = UseInitArray; @@ -535,12 +525,9 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { // Unfortunately, the LLVM C API doesn't provide a way to create the // TargetLibraryInfo pass, so we use this method to do so. -extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, - bool DisableSimplifyLibCalls) { +extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M) { Triple TargetTriple(unwrap(M)->getTargetTriple()); TargetLibraryInfoImpl TLII(TargetTriple); - if (DisableSimplifyLibCalls) - TLII.disableAllFunctions(); unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII)); } @@ -707,7 +694,7 @@ LLVMRustOptimize( bool IsLinkerPluginLTO, bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers, bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize, - bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers, + bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage, const char *InstrProfileOutput, @@ -734,22 +721,14 @@ LLVMRustOptimize( bool DebugPassManager = false; PassInstrumentationCallbacks PIC; -#if LLVM_VERSION_LT(16, 0) - StandardInstrumentations SI(DebugPassManager); -#else StandardInstrumentations SI(TheModule->getContext(), DebugPassManager); -#endif SI.registerCallbacks(PIC); if (LlvmSelfProfiler){ LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback); } -#if LLVM_VERSION_LT(16, 0) - Optional PGOOpt; -#else std::optional PGOOpt; -#endif #if LLVM_VERSION_GE(17, 0) auto FS = vfs::getRealFileSystem(); #endif @@ -813,8 +792,6 @@ LLVMRustOptimize( Triple TargetTriple(TheModule->getTargetTriple()); std::unique_ptr TLII(new TargetLibraryInfoImpl(TargetTriple)); - if (DisableSimplifyLibCalls) - TLII->disableAllFunctions(); FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); PB.registerModuleAnalyses(MAM); @@ -882,12 +859,7 @@ LLVMRustOptimize( /*EagerChecks=*/true); OptimizerLastEPCallbacks.push_back( [Options](ModulePassManager &MPM, OptimizationLevel Level) { -#if LLVM_VERSION_LT(16, 0) - MPM.addPass(ModuleMemorySanitizerPass(Options)); - MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options))); -#else MPM.addPass(MemorySanitizerPass(Options)); -#endif } ); } @@ -912,11 +884,7 @@ LLVMRustOptimize( /*UseAfterScope=*/true, AsanDetectStackUseAfterReturnMode::Runtime, }; -#if LLVM_VERSION_LT(16, 0) - MPM.addPass(ModuleAddressSanitizerPass(opts)); -#else MPM.addPass(AddressSanitizerPass(opts)); -#endif } ); } @@ -1562,32 +1530,6 @@ LLVMRustParseBitcodeForLTO(LLVMContextRef Context, return wrap(std::move(*SrcOrError).release()); } -// Find the bitcode section in the object file data and return it as a slice. -// Fail if the bitcode section is present but empty. -// -// On success, the return value is the pointer to the start of the slice and -// `out_len` is filled with the (non-zero) length. On failure, the return value -// is `nullptr` and `out_len` is set to zero. -extern "C" const char* -LLVMRustGetBitcodeSliceFromObjectData(const char *data, - size_t len, - size_t *out_len) { - *out_len = 0; - - StringRef Data(data, len); - MemoryBufferRef Buffer(Data, ""); // The id is unused. - - Expected BitcodeOrError = - object::IRObjectFile::findBitcodeInMemBuffer(Buffer); - if (!BitcodeOrError) { - LLVMRustSetLastError(toString(BitcodeOrError.takeError()).c_str()); - return nullptr; - } - - *out_len = BitcodeOrError->getBufferSize(); - return BitcodeOrError->getBufferStart(); -} - // Find a section of an object file by name. Fail if the section is missing or // empty. extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 4390486b0deb1..b227dd76f02fb 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -14,18 +14,13 @@ #include "llvm/Remarks/RemarkSerializer.h" #include "llvm/Remarks/RemarkFormat.h" #include "llvm/Support/ToolOutputFile.h" -#if LLVM_VERSION_GE(16, 0) #include "llvm/Support/ModRef.h" -#endif #include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Pass.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Support/Signals.h" -#if LLVM_VERSION_LT(16, 0) -#include "llvm/ADT/Optional.h" -#endif #include @@ -283,6 +278,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::AllocAlign; case SanitizeSafeStack: return Attribute::SafeStack; + case FnRetThunkExtern: + return Attribute::FnRetThunkExtern; } report_fatal_error("bad AttributeKind"); } @@ -347,13 +344,7 @@ extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Asy } extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) { - return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, -#if LLVM_VERSION_LT(16, 0) - None -#else - std::nullopt -#endif - )); + return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, std::nullopt)); } // These values **must** match ffi::AllocKindFlags. @@ -416,7 +407,6 @@ enum class LLVMRustMemoryEffects { extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C, LLVMRustMemoryEffects Effects) { -#if LLVM_VERSION_GE(16, 0) switch (Effects) { case LLVMRustMemoryEffects::None: return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none())); @@ -428,18 +418,6 @@ extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C, default: report_fatal_error("bad MemoryEffects."); } -#else - switch (Effects) { - case LLVMRustMemoryEffects::None: - return wrap(Attribute::get(*unwrap(C), Attribute::ReadNone)); - case LLVMRustMemoryEffects::ReadOnly: - return wrap(Attribute::get(*unwrap(C), Attribute::ReadOnly)); - case LLVMRustMemoryEffects::InaccessibleMemOnly: - return wrap(Attribute::get(*unwrap(C), Attribute::InaccessibleMemOnly)); - default: - report_fatal_error("bad MemoryEffects."); - } -#endif } // Enable a fast-math flag @@ -726,18 +704,10 @@ enum class LLVMRustChecksumKind { SHA256, }; -#if LLVM_VERSION_LT(16, 0) -static Optional fromRust(LLVMRustChecksumKind Kind) { -#else static std::optional fromRust(LLVMRustChecksumKind Kind) { -#endif switch (Kind) { case LLVMRustChecksumKind::None: -#if LLVM_VERSION_LT(16, 0) - return None; -#else return std::nullopt; -#endif case LLVMRustChecksumKind::MD5: return DIFile::ChecksumKind::CSK_MD5; case LLVMRustChecksumKind::SHA1: @@ -810,17 +780,8 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile( const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, const char *Checksum, size_t ChecksumLen) { -#if LLVM_VERSION_LT(16, 0) - Optional llvmCSKind = fromRust(CSKind); -#else std::optional llvmCSKind = fromRust(CSKind); -#endif - -#if LLVM_VERSION_LT(16, 0) - Optional> CSInfo{}; -#else std::optional> CSInfo{}; -#endif if (llvmCSKind) CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen}); return wrap(Builder->createFile(StringRef(Filename, FilenameLen), @@ -983,6 +944,9 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticMemberType( unwrapDI(Ty), fromRust(Flags), unwrap(val), +#if LLVM_VERSION_GE(18, 0) + llvm::dwarf::DW_TAG_member, +#endif AlignInBits )); } @@ -1105,7 +1069,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( unwrapDI(Scope), StringRef(Name, NameLen), unwrapDI(File), LineNumber, SizeInBits, AlignInBits, DINodeArray(unwrapDI(Elements)), - unwrapDI(ClassTy), "", IsScoped)); + unwrapDI(ClassTy), +#if LLVM_VERSION_GE(18, 0) + /* RunTimeLang */ 0, +#endif + "", IsScoped)); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType( @@ -2046,17 +2014,9 @@ extern "C" bool LLVMRustIsNonGVFunctionPointerTy(LLVMValueRef V) { } extern "C" bool LLVMRustLLVMHasZlibCompressionForDebugSymbols() { -#if LLVM_VERSION_GE(16, 0) return llvm::compression::zlib::isAvailable(); -#else - return false; -#endif } extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() { -#if LLVM_VERSION_GE(16, 0) return llvm::compression::zstd::isAvailable(); -#else - return false; -#endif } diff --git a/compiler/rustc_llvm/llvm-wrapper/SuppressLLVMWarnings.h b/compiler/rustc_llvm/llvm-wrapper/SuppressLLVMWarnings.h new file mode 100644 index 0000000000000..56964e4eaa702 --- /dev/null +++ b/compiler/rustc_llvm/llvm-wrapper/SuppressLLVMWarnings.h @@ -0,0 +1,13 @@ +#ifndef _rustc_llvm_SuppressLLVMWarnings_h +#define _rustc_llvm_SuppressLLVMWarnings_h + +// LLVM currently generates many warnings when compiled using MSVC. These warnings make it difficult +// to diagnose real problems when working on C++ code, so we suppress them. + +#ifdef _MSC_VER +#pragma warning(disable:4530) // C++ exception handler used, but unwind semantics are not enabled. +#pragma warning(disable:4624) // 'xxx': destructor was implicitly defined as deleted +#pragma warning(disable:4244) // conversion from 'xxx' to 'yyy', possible loss of data +#endif + +#endif // _rustc_llvm_SuppressLLVMWarnings_h diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index bf00d11edf6d8..91f84692df8f5 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -7,6 +7,7 @@ // * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h // * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp +#include "SuppressLLVMWarnings.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/ObjectFile.h" diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 518c20c9fa8bf..ca0aec71052d0 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,9 +1,9 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] // NOTE: This crate only exists to allow linking on mingw targets. diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 0c9ec556549fa..e3464cb8a2df6 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -14,7 +14,7 @@ //! //! ``` //! fn main() { -//! rustc_log::init_env_logger("LOG").unwrap(); +//! rustc_log::init_logger(rustc_log::LoggerConfig::from_env("LOG")).unwrap(); //! //! let edition = rustc_span::edition::Edition::Edition2021; //! rustc_span::create_session_globals_then(edition, || { @@ -52,13 +52,36 @@ use tracing_subscriber::fmt::{ }; use tracing_subscriber::layer::SubscriberExt; -pub fn init_env_logger(env: &str) -> Result<(), Error> { - let filter = match env::var(env) { +/// The values of all the environment variables that matter for configuring a logger. +/// Errors are explicitly preserved so that we can share error handling. +pub struct LoggerConfig { + pub filter: Result, + pub color_logs: Result, + pub verbose_entry_exit: Result, + pub verbose_thread_ids: Result, + pub backtrace: Result, +} + +impl LoggerConfig { + pub fn from_env(env: &str) -> Self { + LoggerConfig { + filter: env::var(env), + color_logs: env::var(format!("{env}_COLOR")), + verbose_entry_exit: env::var(format!("{env}_ENTRY_EXIT")), + verbose_thread_ids: env::var(format!("{env}_THREAD_IDS")), + backtrace: env::var(format!("{env}_BACKTRACE")), + } + } +} + +/// Initialize the logger with the given values for the filter, coloring, and other options env variables. +pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { + let filter = match cfg.filter { Ok(env) => EnvFilter::new(env), _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), }; - let color_logs = match env::var(String::from(env) + "_COLOR") { + let color_logs = match cfg.color_logs { Ok(value) => match value.as_ref() { "always" => true, "never" => false, @@ -69,14 +92,14 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> { Err(VarError::NotUnicode(_value)) => return Err(Error::NonUnicodeColorValue), }; - let verbose_entry_exit = match env::var_os(String::from(env) + "_ENTRY_EXIT") { - None => false, - Some(v) => &v != "0", + let verbose_entry_exit = match cfg.verbose_entry_exit { + Ok(v) => &v != "0", + Err(_) => false, }; - let verbose_thread_ids = match env::var_os(String::from(env) + "_THREAD_IDS") { - None => false, - Some(v) => &v == "1", + let verbose_thread_ids = match cfg.verbose_thread_ids { + Ok(v) => &v == "1", + Err(_) => false, }; let layer = tracing_tree::HierarchicalLayer::default() @@ -91,7 +114,7 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> { .with_thread_names(verbose_thread_ids); let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); - match env::var(format!("{env}_BACKTRACE")) { + match cfg.backtrace { Ok(str) => { let fmt_layer = tracing_subscriber::fmt::layer() .with_writer(io::stderr) diff --git a/compiler/rustc_macros/src/current_version.rs b/compiler/rustc_macros/src/current_version.rs index 5e3b91c17bf6c..42ca60a6d8ab8 100644 --- a/compiler/rustc_macros/src/current_version.rs +++ b/compiler/rustc_macros/src/current_version.rs @@ -1,37 +1,16 @@ use proc_macro::TokenStream; use proc_macro2::Span; use quote::quote; -use syn::parse::{Parse, ParseStream}; -use syn::{parenthesized, parse_macro_input, LitStr, Token}; -pub struct Input { - variable: LitStr, -} - -mod kw { - syn::custom_keyword!(env); -} - -impl Parse for Input { - // Input syntax is `env!("CFG_RELEASE")` to facilitate grepping. - fn parse(input: ParseStream<'_>) -> syn::Result { - let paren; - input.parse::()?; - input.parse::()?; - parenthesized!(paren in input); - let variable: LitStr = paren.parse()?; - Ok(Input { variable }) - } -} - -pub(crate) fn current_version(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as Input); - - TokenStream::from(match RustcVersion::parse_env_var(&input.variable) { +pub(crate) fn current_version(_input: TokenStream) -> TokenStream { + let env_var = "CFG_RELEASE"; + TokenStream::from(match RustcVersion::parse_cfg_release(env_var) { Ok(RustcVersion { major, minor, patch }) => quote!( + // The produced literal has type `rustc_session::RustcVersion`. Self { major: #major, minor: #minor, patch: #patch } ), - Err(err) => syn::Error::new(Span::call_site(), err).into_compile_error(), + Err(err) => syn::Error::new(Span::call_site(), format!("{env_var} env var: {err}")) + .into_compile_error(), }) } @@ -42,8 +21,8 @@ struct RustcVersion { } impl RustcVersion { - fn parse_env_var(env_var: &LitStr) -> Result> { - let value = proc_macro::tracked_env::var(env_var.value())?; + fn parse_cfg_release(env_var: &str) -> Result> { + let value = proc_macro::tracked_env::var(env_var)?; Self::parse_str(&value) .ok_or_else(|| format!("failed to parse rustc version: {:?}", value).into()) } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 1a8174bfd9681..31ad9cdb21619 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -229,8 +229,8 @@ fn generate_test(slug: &syn::Path, structure: &Structure<'_>) -> TokenStream { } } use std::sync::atomic::{AtomicUsize, Ordering}; - // We need to make sure that the same diagnostic slug can be used multiple times without causing an - // error, so just have a global counter here. + // We need to make sure that the same diagnostic slug can be used multiple times without + // causing an error, so just have a global counter here. static COUNTER: AtomicUsize = AtomicUsize::new(0); let slug = slug.get_ident().unwrap(); let ident = quote::format_ident!("verify_{slug}_{}", COUNTER.fetch_add(1, Ordering::Relaxed)); diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index e9a5cd9de97b0..2755a161d91e7 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -53,6 +53,7 @@ pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. pub slug: SpannedOption, + /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. pub code: SpannedOption<()>, @@ -68,7 +69,7 @@ impl DiagnosticDeriveBuilder { /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions /// or attributes on the type itself when input is an enum. - pub fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream + pub(crate) fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream where F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream, { @@ -121,7 +122,7 @@ impl DiagnosticDeriveBuilder { impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Generates calls to `code` and similar functions based on the attributes on the type or /// variant. - pub fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { + pub(crate) fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let ast = variant.ast(); let attrs = &ast.attrs; let preamble = attrs.iter().map(|attr| { @@ -135,7 +136,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Generates calls to `span_label` and similar functions based on the attributes on fields or /// calls to `set_arg` when no attributes are present. - pub fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { + pub(crate) fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let mut body = quote! {}; // Generate `set_arg` calls first.. for binding in variant.bindings().iter().filter(|bi| should_generate_set_arg(bi.ast())) { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 877271ff0774c..0f9e68cdc5018 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -478,7 +478,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } - pub fn into_tokens(&mut self) -> Result { + pub(crate) fn into_tokens(&mut self) -> Result { let kind_slugs = self.identify_kind()?; if kind_slugs.is_empty() { if self.is_enum { diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 125632921816b..2700f02e33a66 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -17,7 +17,7 @@ use synstructure::{BindingInfo, VariantInfo}; use super::error::invalid_attr; thread_local! { - pub static CODE_IDENT_COUNT: RefCell = RefCell::new(0); + pub(crate) static CODE_IDENT_COUNT: RefCell = RefCell::new(0); } /// Returns an ident of the form `__code_N` where `N` is incremented once with every call. @@ -208,7 +208,7 @@ impl<'ty> FieldInnerTy<'ty> { } } - pub fn span(&self) -> proc_macro2::Span { + pub(crate) fn span(&self) -> proc_macro2::Span { match self { FieldInnerTy::Option(ty) | FieldInnerTy::Vec(ty) | FieldInnerTy::Plain(ty) => ty.span(), } @@ -537,7 +537,7 @@ impl fmt::Display for SuggestionKind { } impl SuggestionKind { - pub fn to_suggestion_style(&self) -> TokenStream { + pub(crate) fn to_suggestion_style(&self) -> TokenStream { match self { SuggestionKind::Normal => { quote! { rustc_errors::SuggestionStyle::ShowCode } diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 75a2f7009c258..2893937fc4a35 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -38,41 +38,80 @@ fn parse_attributes(field: &syn::Field) -> Attributes { attrs } -pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { - let generic: syn::GenericParam = parse_quote!(__CTX); - s.add_bounds(synstructure::AddBounds::Generics); - s.add_impl_generic(generic); - s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); - let body = s.each(|bi| { - let attrs = parse_attributes(bi.ast()); - if attrs.ignore { - quote! {} - } else if let Some(project) = attrs.project { - quote! { - (&#bi.#project).hash_stable(__hcx, __hasher); - } - } else { - quote! { - #bi.hash_stable(__hcx, __hasher); - } - } +pub(crate) fn hash_stable_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + hash_stable_derive_with_mode(s, HashStableMode::Normal) +} + +pub(crate) fn hash_stable_generic_derive( + s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { + hash_stable_derive_with_mode(s, HashStableMode::Generic) +} + +pub(crate) fn hash_stable_no_context_derive( + s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { + hash_stable_derive_with_mode(s, HashStableMode::NoContext) +} + +enum HashStableMode { + // Use the query-system aware stable hashing context. + Normal, + // Emit a generic implementation that uses a crate-local `StableHashingContext` + // trait, when the crate is upstream of `rustc_middle`. + Generic, + // Emit a hash-stable implementation that takes no context, + // and emits per-field where clauses for (almost-)perfect derives. + NoContext, +} + +fn hash_stable_derive_with_mode( + mut s: synstructure::Structure<'_>, + mode: HashStableMode, +) -> proc_macro2::TokenStream { + let generic: syn::GenericParam = match mode { + HashStableMode::Normal => parse_quote!('__ctx), + HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX), + }; + + // no_context impl is able to derive by-field, which is closer to a perfect derive. + s.add_bounds(match mode { + HashStableMode::Normal | HashStableMode::Generic => synstructure::AddBounds::Generics, + HashStableMode::NoContext => synstructure::AddBounds::Fields, }); - let discriminant = match s.ast().data { - syn::Data::Enum(_) => quote! { - ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); - }, - syn::Data::Struct(_) => quote! {}, - syn::Data::Union(_) => panic!("cannot derive on union"), + // For generic impl, add `where __CTX: HashStableContext`. + match mode { + HashStableMode::Normal => {} + HashStableMode::Generic => { + s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); + } + HashStableMode::NoContext => {} + } + + s.add_impl_generic(generic); + + let discriminant = hash_stable_discriminant(&mut s); + let body = hash_stable_body(&mut s); + + let context: syn::Type = match mode { + HashStableMode::Normal => { + parse_quote!(::rustc_query_system::ich::StableHashingContext<'__ctx>) + } + HashStableMode::Generic | HashStableMode::NoContext => parse_quote!(__CTX), }; s.bound_impl( - quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), + quote!( + ::rustc_data_structures::stable_hasher::HashStable< + #context + > + ), quote! { #[inline] fn hash_stable( &self, - __hcx: &mut __CTX, + __hcx: &mut #context, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { #discriminant match *self { #body } @@ -81,11 +120,18 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma ) } -pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { - let generic: syn::GenericParam = parse_quote!('__ctx); - s.add_bounds(synstructure::AddBounds::Generics); - s.add_impl_generic(generic); - let body = s.each(|bi| { +fn hash_stable_discriminant(s: &mut synstructure::Structure<'_>) -> proc_macro2::TokenStream { + match s.ast().data { + syn::Data::Enum(_) => quote! { + ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); + }, + syn::Data::Struct(_) => quote! {}, + syn::Data::Union(_) => panic!("cannot derive on union"), + } +} + +fn hash_stable_body(s: &mut synstructure::Structure<'_>) -> proc_macro2::TokenStream { + s.each(|bi| { let attrs = parse_attributes(bi.ast()); if attrs.ignore { quote! {} @@ -98,31 +144,5 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To #bi.hash_stable(__hcx, __hasher); } } - }); - - let discriminant = match s.ast().data { - syn::Data::Enum(_) => quote! { - ::std::mem::discriminant(self).hash_stable(__hcx, __hasher); - }, - syn::Data::Struct(_) => quote! {}, - syn::Data::Union(_) => panic!("cannot derive on union"), - }; - - s.bound_impl( - quote!( - ::rustc_data_structures::stable_hasher::HashStable< - ::rustc_query_system::ich::StableHashingContext<'__ctx>, - > - ), - quote! { - #[inline] - fn hash_stable( - &self, - __hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>, - __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { - #discriminant - match *self { #body } - } - }, - ) + }) } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 193dbd75fbd57..f558b74be9a99 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -19,13 +19,15 @@ mod current_version; mod diagnostics; mod hash_stable; mod lift; -mod newtype; mod query; mod serialize; mod symbols; mod type_foldable; mod type_visitable; +// Reads the rust version (e.g. "1.75.0") from the CFG_RELEASE env var and +// produces a `RustcVersion` literal containing that version (e.g. +// `RustcVersion { major: 1, minor: 75, patch: 0 }`). #[proc_macro] pub fn current_rustc_version(input: TokenStream) -> TokenStream { current_version::current_version(input) @@ -41,32 +43,18 @@ pub fn symbols(input: TokenStream) -> TokenStream { symbols::symbols(input.into()).into() } -/// Creates a struct type `S` that can be used as an index with -/// `IndexVec` and so on. -/// -/// There are two ways of interacting with these indices: -/// -/// - The `From` impls are the preferred way. So you can do -/// `S::from(v)` with a `usize` or `u32`. And you can convert back -/// to an integer with `u32::from(s)`. -/// -/// - Alternatively, you can use the methods `S::new(v)` and `s.index()` -/// to create/return a value. -/// -/// Internally, the index uses a u32, so the index must not exceed -/// `u32::MAX`. You can also customize things like the `Debug` impl, -/// what traits are derived, and so forth via the macro. -#[proc_macro] -#[allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq)] -pub fn newtype_index(input: TokenStream) -> TokenStream { - newtype::newtype(input) -} - decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); decl_derive!( [HashStable_Generic, attributes(stable_hasher)] => hash_stable::hash_stable_generic_derive ); +decl_derive!( + [HashStable_NoContext] => + /// `HashStable` implementation that has no `HashStableContext` bound and + /// which adds `where` bounds for `HashStable` based off of fields and not + /// generics. This is suitable for use in crates like `rustc_type_ir`. + hash_stable::hash_stable_no_context_derive +); decl_derive!([Decodable] => serialize::decodable_derive); decl_derive!([Encodable] => serialize::encodable_derive); diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index ba75517d7a66d..047066ac6815e 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -5,11 +5,16 @@ use syn::spanned::Spanned; pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; - if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - s.add_impl_generic(parse_quote! { 'tcx }); - } - s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder>}); - s.add_bounds(synstructure::AddBounds::Generics); + let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + quote! { > } + } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { + quote! { } + } else { + quote! {} + }; + + s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder #bound }); + s.add_bounds(synstructure::AddBounds::Fields); decodable_body(s, decoder_ty) } @@ -97,12 +102,17 @@ fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream { } pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { - if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - s.add_impl_generic(parse_quote! {'tcx}); - } + let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + quote! { > } + } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { + quote! { } + } else { + quote! {} + }; + let encoder_ty = quote! { __E }; - s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder>}); - s.add_bounds(synstructure::AddBounds::Generics); + s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder #bound }); + s.add_bounds(synstructure::AddBounds::Fields); encodable_body(s, encoder_ty, false) } diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 4129712a6b218..488d4504a2d11 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -19,7 +19,9 @@ //! ```bash //! cargo install cargo-expand # this is necessary only once //! cd compiler/rustc_span -//! cargo expand > /tmp/rustc_span.rs # it's a big file +//! # The specific version number in CFG_RELEASE doesn't matter. +//! # The output is large. +//! CFG_RELEASE="0.0.0" cargo +nightly expand > /tmp/rustc_span.rs //! ``` use proc_macro2::{Span, TokenStream}; @@ -83,7 +85,9 @@ impl Parse for Value { } } Expr::Macro(expr) => { - if expr.mac.path.is_ident("env") && let Ok(lit) = expr.mac.parse_body() { + if expr.mac.path.is_ident("env") + && let Ok(lit) = expr.mac.parse_body() + { return Ok(Value::Env(lit, expr.mac.clone())); } } @@ -318,13 +322,4 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { }; (output, errors.list) - - // To see the generated code, use the "cargo expand" command. - // Do this once to install: - // cargo install cargo-expand - // - // Then, cd to rustc_span and run: - // cargo expand > /tmp/rustc_span_expanded.rs - // - // and read that file. } diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index d1815717e220b..8da6f0007f03a 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -63,11 +63,8 @@ metadata_extern_location_not_file = metadata_fail_create_file_encoder = failed to create file encoder: {$err} -metadata_fail_seek_file = - failed to seek the file: {$err} - metadata_fail_write_file = - failed to write to the file: {$err} + failed to write to `{$path}`: {$err} metadata_failed_copy_to_stdout = failed to copy {$filename} to stdout: {$err} @@ -272,7 +269,7 @@ metadata_unknown_import_name_type = unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated metadata_unknown_link_kind = - unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib + unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib, link-arg .label = unknown link kind metadata_unknown_link_modifier = diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 14bbe65d5f1fc..301e3f2620dc1 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -7,8 +7,9 @@ use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob use rustc_ast::expand::allocator::{alloc_error_handler_name, global_fn_name, AllocatorKind}; use rustc_ast::{self as ast, *}; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::owned_slice::OwnedSlice; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard}; +use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard}; use rustc_expand::base::SyntaxExtension; use rustc_fs_util::try_canonicalize; use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE}; @@ -16,16 +17,14 @@ use rustc_hir::definitions::Definitions; use rustc_index::IndexVec; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, CrateType, ExternLocation}; -use rustc_session::cstore::{ - CrateDepKind, CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn, -}; +use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource}; use rustc_session::lint; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::spec::{PanicStrategy, TargetTriple}; +use rustc_target::spec::{PanicStrategy, Target, TargetTriple}; use proc_macro::bridge::client::ProcMacro; use std::error::Error; @@ -34,6 +33,17 @@ use std::path::Path; use std::time::Duration; use std::{cmp, iter}; +/// The backend's way to give the crate store access to the metadata in a library. +/// Note that it returns the raw metadata bytes stored in the library file, whether +/// it is compressed, uncompressed, some weird mix, etc. +/// rmeta files are backend independent and not handled here. +pub trait MetadataLoader { + fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result; + fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result; +} + +pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync; + pub struct CStore { metadata_loader: Box, @@ -257,7 +267,7 @@ impl CStore { let unused_externs = self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::>(); let unused_externs = unused_externs.iter().map(String::as_str).collect::>(); - tcx.sess.parse_sess.span_diagnostic.emit_unused_externs( + tcx.sess.diagnostic().emit_unused_externs( level, json_unused_externs.is_loud(), &unused_externs, @@ -427,7 +437,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let crate_metadata = CrateMetadata::new( self.sess, - &self.cstore, + self.cstore, metadata, crate_root, raw_proc_macros, @@ -515,7 +525,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { Err(err) => { let missing_core = self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); - err.report(&self.sess, span, missing_core); + err.report(self.sess, span, missing_core); None } } @@ -987,7 +997,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { self.report_unused_deps(krate); - info!("{:?}", CrateDump(&self.cstore)); + info!("{:?}", CrateDump(self.cstore)); } pub fn process_extern_crate( diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 70daee291e721..edc8d8532d3b2 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -307,15 +307,10 @@ pub struct FailCreateFileEncoder { pub err: Error, } -#[derive(Diagnostic)] -#[diag(metadata_fail_seek_file)] -pub struct FailSeekFile { - pub err: Error, -} - #[derive(Diagnostic)] #[diag(metadata_fail_write_file)] -pub struct FailWriteFile { +pub struct FailWriteFile<'a> { + pub path: &'a Path, pub err: Error, } diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 7eb2a347db214..c95ef01faa73f 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -91,10 +91,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { } }; if tcx.sess.opts.json_artifact_notifications { - tcx.sess - .parse_sess - .span_diagnostic - .emit_artifact_notification(&out_filename.as_path(), "metadata"); + tcx.sess.diagnostic().emit_artifact_notification(out_filename.as_path(), "metadata"); } (filename, None) } else { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index ec2517b581e3e..6c6c60af063fb 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,13 +1,13 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] #![feature(decl_macro)] #![feature(extract_if)] -#![cfg_attr(bootstrap, feature(generators))] -#![cfg_attr(not(bootstrap), feature(coroutines))] +#![feature(coroutines)] #![feature(iter_from_coroutine)] #![feature(let_chains)] +#![feature(if_let_guard)] #![feature(proc_macro_internals)] #![feature(macro_metavar_expr)] #![feature(min_specialization)] @@ -31,8 +31,6 @@ extern crate rustc_middle; extern crate tracing; pub use rmeta::provide; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; mod dependency_format; mod foreign_modules; @@ -48,4 +46,4 @@ pub use fs::{emit_wrapper_file, METADATA_FILENAME}; pub use native_libs::find_native_static_library; pub use rmeta::{encode_metadata, rendered_const, EncodedMetadata, METADATA_HEADER}; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 3a99ddc1b7aff..bcc124524eb91 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -212,7 +212,7 @@ //! no means all of the necessary details. Take a look at the rest of //! metadata::locator or metadata::creader for all the juicy details! -use crate::creader::Library; +use crate::creader::{Library, MetadataLoader}; use crate::errors; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; @@ -223,7 +223,7 @@ use rustc_data_structures::svh::Svh; use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_fs_util::try_canonicalize; use rustc_session::config; -use rustc_session::cstore::{CrateSource, MetadataLoader}; +use rustc_session::cstore::CrateSource; use rustc_session::filesearch::FileSearch; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; @@ -980,7 +980,7 @@ impl CrateError { for CrateMismatch { path, .. } in mismatches { sess.emit_err(errors::CrateLocationUnknownType { span, - path: &path, + path: path, crate_name, }); sess.emit_err(errors::LibFilenameForm { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index ab135851b8e04..b3760b1099b4b 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -160,6 +160,18 @@ impl<'tcx> Collector<'tcx> { } NativeLibKind::RawDylib } + "link-arg" => { + if !features.link_arg_attribute { + feature_err( + &sess.parse_sess, + sym::link_arg_attribute, + span, + "link kind `link-arg` is unstable", + ) + .emit(); + } + NativeLibKind::LinkArg + } kind => { sess.emit_err(errors::UnknownLinkKind { span, kind }); continue; @@ -470,7 +482,7 @@ impl<'tcx> Collector<'tcx> { } fn i686_arg_list_size(&self, item: DefId) -> usize { - let argument_types: &List> = self.tcx.erase_late_bound_regions( + let argument_types: &List> = self.tcx.instantiate_bound_regions_with_erased( self.tcx .type_of(item) .instantiate_identity() diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 354023cea9e07..5725a759fef80 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -21,6 +21,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; +use rustc_middle::middle::lib_features::LibFeatures; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -828,7 +829,7 @@ impl MetadataBlob { out, "{}{}", feature, - if let Some(since) = since { + if let FeatureStability::AcceptedSince(since) = since { format!(" since {since}") } else { String::new() @@ -849,7 +850,7 @@ impl MetadataBlob { ) -> io::Result<()> { let root = blob.get_root(); - let def_kind = root.tables.opt_def_kind.get(blob, item).unwrap(); + let def_kind = root.tables.def_kind.get(blob, item).unwrap(); let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob); let def_name = if item == CRATE_DEF_INDEX { rustc_span::symbol::kw::Crate @@ -1000,14 +1001,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn def_kind(self, item_id: DefIndex) -> DefKind { - self.root.tables.opt_def_kind.get(self, item_id).unwrap_or_else(|| { - bug!( - "CrateMetadata::def_kind({:?}): id not found, in crate {:?} with number {}", - item_id, - self.root.name(), - self.cnum, - ) - }) + self.root + .tables + .def_kind + .get(self, item_id) + .unwrap_or_else(|| self.missing("def_kind", item_id)) } fn get_span(self, index: DefIndex, sess: &Session) -> Span { @@ -1176,8 +1174,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } /// Iterates over all the stability attributes in the given crate. - fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option)] { - tcx.arena.alloc_from_iter(self.root.lib_features.decode(self)) + fn get_lib_features(self) -> LibFeatures { + LibFeatures { + stability: self + .root + .lib_features + .decode(self) + .map(|(sym, stab)| (sym, (stab, DUMMY_SP))) + .collect(), + } } /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 595d816e9493c..f6cd013d2ef16 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -231,7 +231,7 @@ provide! { tcx, def_id, other, cdata, lookup_deprecation_entry => { table } params_in_repr => { table } unused_generic_params => { cdata.root.tables.unused_generic_params.get(cdata, def_id.index) } - opt_def_kind => { table_direct } + def_kind => { cdata.def_kind(def_id.index) } impl_parent => { table } impl_polarity => { table_direct } defaultness => { table_direct } @@ -346,7 +346,7 @@ provide! { tcx, def_id, other, cdata, module_children => { tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess)) } - defined_lib_features => { cdata.get_lib_features(tcx) } + lib_features => { cdata.get_lib_features() } stability_implications => { cdata.get_stability_implications(tcx).iter().copied().collect() } @@ -394,7 +394,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { native_library: |tcx, id| { tcx.native_libraries(id.krate) .iter() - .filter(|lib| native_libs::relevant_lib(&tcx.sess, lib)) + .filter(|lib| native_libs::relevant_lib(tcx.sess, lib)) .find(|lib| { let Some(fm_id) = lib.foreign_module else { return false; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index de436c16ca924..ffb2375a7349b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,4 +1,4 @@ -use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile}; +use crate::errors::{FailCreateFileEncoder, FailWriteFile}; use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::TableBuilder; use crate::rmeta::*; @@ -25,6 +25,7 @@ use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportInfo, }; +use rustc_middle::middle::lib_features::FeatureStability; use rustc_middle::mir::interpret; use rustc_middle::query::LocalCrate; use rustc_middle::query::Providers; @@ -41,6 +42,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext}; use std::borrow::Borrow; use std::collections::hash_map::Entry; +use std::fs::File; use std::hash::Hash; use std::io::{Read, Seek, Write}; use std::num::NonZeroUsize; @@ -159,7 +161,7 @@ impl<'a, 'tcx> Encodable> for ExpnIndex { impl<'a, 'tcx> Encodable> for SyntaxContext { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) { - rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s); + rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_ctxt, s); } } @@ -656,10 +658,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let debugger_visualizers = stat!("debugger-visualizers", || self.encode_debugger_visualizers()); - // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode - // this as late as possible to give the prefetching as much time as possible to complete. + // Encode exported symbols info. This is prefetched in `encode_metadata`. let exported_symbols = stat!("exported-symbols", || { - self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE)) + self.encode_exported_symbols(tcx.exported_symbols(LOCAL_CRATE)) }); // Encode the hygiene data. @@ -693,15 +694,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE), has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), - has_default_lib_allocator: attr::contains_name(&attrs, sym::default_lib_allocator), + has_default_lib_allocator: attr::contains_name(attrs, sym::default_lib_allocator), proc_macro_data, debugger_visualizers, - compiler_builtins: attr::contains_name(&attrs, sym::compiler_builtins), - needs_allocator: attr::contains_name(&attrs, sym::needs_allocator), - needs_panic_runtime: attr::contains_name(&attrs, sym::needs_panic_runtime), - no_builtins: attr::contains_name(&attrs, sym::no_builtins), - panic_runtime: attr::contains_name(&attrs, sym::panic_runtime), - profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime), + compiler_builtins: attr::contains_name(attrs, sym::compiler_builtins), + needs_allocator: attr::contains_name(attrs, sym::needs_allocator), + needs_panic_runtime: attr::contains_name(attrs, sym::needs_panic_runtime), + no_builtins: attr::contains_name(attrs, sym::no_builtins), + panic_runtime: attr::contains_name(attrs, sym::panic_runtime), + profiler_runtime: attr::contains_name(attrs, sym::profiler_runtime), symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), crate_deps, @@ -855,8 +856,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::OpaqueTy | DefKind::Field | DefKind::Impl { .. } - | DefKind::Closure - | DefKind::Coroutine => true, + | DefKind::Closure => true, DefKind::ForeignMod | DefKind::GlobalAsm => false, } } @@ -896,8 +896,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::LifetimeParam - | DefKind::GlobalAsm - | DefKind::Coroutine => false, + | DefKind::GlobalAsm => false, } } @@ -932,8 +931,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Closure - | DefKind::Coroutine => false, + | DefKind::Closure => false, } } @@ -968,7 +966,6 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::GlobalAsm | DefKind::Impl { .. } | DefKind::Closure - | DefKind::Coroutine | DefKind::ExternCrate => false, } } @@ -1004,7 +1001,6 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure - | DefKind::Coroutine | DefKind::ExternCrate => false, } } @@ -1047,6 +1043,8 @@ fn should_encode_mir( | DefKind::AssocConst | DefKind::Static(..) | DefKind::Const => (true, false), + // Coroutines require optimized MIR to compute layout. + DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => (false, true), // Full-fledged functions + closures DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { let generics = tcx.generics_of(def_id); @@ -1060,8 +1058,6 @@ fn should_encode_mir( || tcx.is_const_default_method(def_id.to_def_id()); (is_const_fn, opt) } - // Coroutines require optimized MIR to compute layout. - DefKind::Coroutine => (false, true), // The others don't have MIR. _ => (false, false), } @@ -1097,7 +1093,6 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure - | DefKind::Coroutine | DefKind::ExternCrate => false, DefKind::TyAlias => tcx.type_alias_is_lazy(def_id), } @@ -1126,8 +1121,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::Impl { .. } | DefKind::Field | DefKind::TyParam - | DefKind::Closure - | DefKind::Coroutine => true, + | DefKind::Closure => true, DefKind::Mod | DefKind::ForeignMod | DefKind::ConstParam @@ -1156,7 +1150,6 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::AssocFn | DefKind::AssocConst | DefKind::Closure - | DefKind::Coroutine | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst => true, @@ -1217,7 +1210,6 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Impl { .. } | DefKind::AssocConst | DefKind::Closure - | DefKind::Coroutine | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst @@ -1256,7 +1248,6 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::OpaqueTy | DefKind::Impl { of_trait: false } | DefKind::ForeignTy - | DefKind::Coroutine | DefKind::ConstParam | DefKind::InlineConst | DefKind::AssocTy @@ -1291,7 +1282,6 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Impl { .. } | DefKind::AssocFn | DefKind::Closure - | DefKind::Coroutine | DefKind::ConstParam | DefKind::AssocTy | DefKind::TyParam @@ -1353,9 +1343,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for local_id in tcx.iter_local_def_id() { let def_id = local_id.to_def_id(); - let def_kind = tcx.opt_def_kind(local_id); - let Some(def_kind) = def_kind else { continue }; - self.tables.opt_def_kind.set_some(def_id.index, def_kind); + let def_kind = tcx.def_kind(local_id); + self.tables.def_kind.set_some(def_id.index, def_kind); if should_encode_span(def_kind) { let def_span = tcx.def_span(local_id); record!(self.tables.def_span[def_id] <- def_span); @@ -1392,7 +1381,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if should_encode_fn_sig(def_kind) { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } - if should_encode_generics(def_kind) { + // FIXME: Some anonymous constants produced by `#[rustc_legacy_const_generics]` + // do not have corresponding HIR nodes, so some queries usually making sense for + // anonymous constants will not work on them and panic. It's not clear whether it + // can cause any observable issues or not. + let anon_const_without_hir = def_kind == DefKind::AnonConst + && tcx.hir().find(tcx.local_def_id_to_hir_id(local_id)).is_none(); + if should_encode_generics(def_kind) && !anon_const_without_hir { let g = tcx.generics_of(def_id); record!(self.tables.generics_of[def_id] <- g); record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id)); @@ -1406,7 +1401,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } } - if should_encode_type(tcx, local_id, def_kind) { + if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir { record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); } if should_encode_constness(def_kind) { @@ -1446,8 +1441,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_info_for_assoc_item(def_id); } } - if let DefKind::Coroutine = def_kind { - let data = self.tcx.coroutine_kind(def_id).unwrap(); + if def_kind == DefKind::Closure + && let Some(data) = self.tcx.coroutine_kind(def_id) + { record!(self.tables.coroutine_kind[def_id] <- data); } if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind { @@ -1629,7 +1625,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] <- tcx.closure_saved_names_of_captured_variables(def_id)); - if let DefKind::Coroutine = self.tcx.def_kind(def_id) + if self.tcx.is_coroutine(def_id.to_def_id()) && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id) { record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); @@ -1656,7 +1652,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id)); - if let DefKind::Coroutine = self.tcx.def_kind(def_id) + if self.tcx.is_coroutine(def_id.to_def_id()) && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id) { record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); @@ -1727,9 +1723,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_macro(&mut self, def_id: LocalDefId) { let tcx = self.tcx; - let hir::ItemKind::Macro(ref macro_def, _) = tcx.hir().expect_item(def_id).kind else { - bug!() - }; + let hir::ItemKind::Macro(macro_def, _) = tcx.hir().expect_item(def_id).kind else { bug!() }; self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules); record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body); } @@ -1786,7 +1780,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.proc_macro_quoted_spans.set_some(i, span); } - self.tables.opt_def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod); + self.tables.def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod); record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id())); self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local()); let vis = tcx.local_visibility(CRATE_DEF_ID).map_id(|def_id| def_id.local_def_index); @@ -1807,7 +1801,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // so we manually encode just the information that we need for &proc_macro in &tcx.resolutions(()).proc_macros { let id = proc_macro; - let proc_macro = hir.local_def_id_to_hir_id(proc_macro); + let proc_macro = tcx.local_def_id_to_hir_id(proc_macro); let mut name = hir.name(proc_macro); let span = hir.span(proc_macro); // Proc-macros may have attributes like `#[allow_internal_unstable]`, @@ -1834,7 +1828,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { def_key.disambiguated_data.data = DefPathData::MacroNs(name); let def_id = id.to_def_id(); - self.tables.opt_def_kind.set_some(def_id.index, DefKind::Macro(macro_kind)); + self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind)); self.tables.proc_macro.set_some(def_id.index, macro_kind); self.encode_attrs(id); record!(self.tables.def_keys[def_id] <- def_key); @@ -1902,10 +1896,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_array(deps.iter().map(|(_, dep)| dep)) } - fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option)> { + fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> { empty_proc_macro!(self); let tcx = self.tcx; - let lib_features = tcx.lib_features(()); + let lib_features = tcx.lib_features(LOCAL_CRATE); self.lazy_array(lib_features.to_vec()) } @@ -2198,21 +2192,13 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { // there's no need to do dep-graph tracking for any of it. tcx.dep_graph.assert_ignored(); - join( - || encode_metadata_impl(tcx, path), - || { - if tcx.sess.threads() == 1 { - return; - } - // Prefetch some queries used by metadata encoding. - // This is not necessary for correctness, but is only done for performance reasons. - // It can be removed if it turns out to cause trouble or be detrimental to performance. - join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE)); - }, - ); -} + if tcx.sess.threads() != 1 { + // Prefetch some queries used by metadata encoding. + // This is not necessary for correctness, but is only done for performance reasons. + // It can be removed if it turns out to cause trouble or be detrimental to performance. + join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE)); + } -fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let mut encoder = opaque::FileEncoder::new(path) .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err })); encoder.emit_raw_bytes(METADATA_HEADER); @@ -2251,29 +2237,34 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { // culminating in the `CrateRoot` which points to all of it. let root = ecx.encode_crate_root(); - ecx.opaque.flush(); + // Make sure we report any errors from writing to the file. + // If we forget this, compilation can succeed with an incomplete rmeta file, + // causing an ICE when the rmeta file is read by another compilation. + if let Err((path, err)) = ecx.opaque.finish() { + tcx.sess.emit_err(FailWriteFile { path: &path, err }); + } + + let file = ecx.opaque.file(); + if let Err(err) = encode_root_position(file, root.position.get()) { + tcx.sess.emit_err(FailWriteFile { path: ecx.opaque.path(), err }); + } + + // Record metadata size for self-profiling + tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len()); +} - let mut file = ecx.opaque.file(); +fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> { // We will return to this position after writing the root position. let pos_before_seek = file.stream_position().unwrap(); // Encode the root position. let header = METADATA_HEADER.len(); - file.seek(std::io::SeekFrom::Start(header as u64)) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err })); - let pos = root.position.get(); - file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8]) - .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err })); + file.seek(std::io::SeekFrom::Start(header as u64))?; + file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])?; // Return to the position where we are before writing the root position. - file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap(); - - // Record metadata size for self-profiling - tcx.prof.artifact_size( - "crate_metadata", - "crate_metadata", - file.metadata().unwrap().len() as u64, - ); + file.seek(std::io::SeekFrom::Start(pos_before_seek))?; + Ok(()) } pub fn provide(providers: &mut Providers) { @@ -2386,31 +2377,36 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: hir::BodyId) -> String { } } - let classification = classify(value); - - if classification == Literal - && !value.span.from_expansion() - && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) - { - // For literals, we avoid invoking the pretty-printer and use the source snippet instead to - // preserve certain stylistic choices the user likely made for the sake legibility like + match classify(value) { + // For non-macro literals, we avoid invoking the pretty-printer and use the source snippet + // instead to preserve certain stylistic choices the user likely made for the sake of + // legibility, like: // // * hexadecimal notation // * underscores // * character escapes // // FIXME: This passes through `-/*spacer*/0` verbatim. - snippet - } else if classification == Simple { + Literal + if !value.span.from_expansion() + && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) => + { + snippet + } + // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and // other formatting artifacts. - id_to_string(&hir, body.hir_id) - } else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { + Literal | Simple => id_to_string(&hir, body.hir_id), + // FIXME: Omit the curly braces if the enclosing expression is an array literal // with a repeated element (an `ExprKind::Repeat`) as in such case it // would not actually need any disambiguation. - "{ _ }".to_owned() - } else { - "_".to_owned() + Complex => { + if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { + "{ _ }".to_owned() + } else { + "_".to_owned() + } + } } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9ae5c0af0b248..ea8ef50460e58 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -3,6 +3,7 @@ use decoder::Metadata; use def_path_hash_map::DefPathHashMapRef; use rustc_data_structures::fx::FxHashMap; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; +use rustc_middle::middle::lib_features::FeatureStability; use table::TableBuilder; use rustc_ast as ast; @@ -263,7 +264,7 @@ pub(crate) struct CrateRoot { crate_deps: LazyArray, dylib_dependency_formats: LazyArray>, - lib_features: LazyArray<(Symbol, Option)>, + lib_features: LazyArray<(Symbol, FeatureStability)>, stability_implications: LazyArray<(Symbol, Symbol)>, lang_items: LazyArray<(DefIndex, LangItem)>, lang_items_missing: LazyArray, @@ -404,7 +405,7 @@ define_tables! { // so we can take their names, visibilities etc from other encoded tables. module_children_non_reexports: Table>, associated_item_or_field_def_ids: Table>, - opt_def_kind: Table, + def_kind: Table, visibility: Table>>, def_span: Table>, def_ident_span: Table>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 027994c40ab72..7cdbcd9193cf7 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -167,7 +167,6 @@ fixed_size_enum! { ( Impl { of_trait: false } ) ( Impl { of_trait: true } ) ( Closure ) - ( Coroutine ) ( Static(ast::Mutability::Not) ) ( Static(ast::Mutability::Mut) ) ( Ctor(CtorOf::Struct, CtorKind::Fn) ) @@ -382,8 +381,8 @@ impl LazyArray { } fn from_bytes_impl(position: &[u8; 8], meta: &[u8; 8]) -> Option> { - let position = NonZeroUsize::new(u64::from_bytes(&position) as usize)?; - let len = u64::from_bytes(&meta) as usize; + let position = NonZeroUsize::new(u64::from_bytes(position) as usize)?; + let len = u64::from_bytes(meta) as usize; Some(LazyArray::from_position_and_num_elems(position, len)) } } @@ -497,7 +496,7 @@ impl> TableBui } LazyTable::from_position_and_encoded_size( - NonZeroUsize::new(pos as usize).unwrap(), + NonZeroUsize::new(pos).unwrap(), width, self.blocks.len(), ) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index dd761b4e31203..9b41b77928e67 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -27,19 +27,12 @@ macro_rules! arena_types { rustc_middle::mir::Promoted, rustc_middle::mir::Body<'tcx> >, - [decode] closure_debuginfo: - rustc_index::IndexVec< - rustc_target::abi::FieldIdx, - rustc_span::symbol::Symbol, - >, [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, - [decode] borrowck_result: - rustc_middle::mir::BorrowCheckResult<'tcx>, + [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>, [] resolver: rustc_data_structures::steal::Steal<( rustc_middle::ty::ResolverAstLowering, rustc_data_structures::sync::Lrc, )>, - [] output_filenames: std::sync::Arc, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, @@ -91,29 +84,23 @@ macro_rules! arena_types { rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>> >, - [] all_traits: Vec, [] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities, - [] foreign_module: rustc_session::cstore::ForeignModule, - [] foreign_modules: Vec, [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap, [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>, [decode] attribute: rustc_ast::Attribute, [] name_set: rustc_data_structures::unord::UnordSet, [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, - [] hir_id_set: rustc_hir::HirIdSet, // Interned types [] tys: rustc_type_ir::WithCachedTypeInfo>, - [] predicates: rustc_type_ir::WithCachedTypeInfo>, - [] consts: rustc_middle::ty::ConstData<'tcx>, + [] consts: rustc_type_ir::WithCachedTypeInfo>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena // (during lowering) and the `librustc_middle` arena (for decoding MIR) [decode] asm_template: rustc_ast::InlineAsmTemplatePiece, [decode] used_trait_imports: rustc_data_structures::unord::UnordSet, - [decode] registered_tools: rustc_middle::ty::RegisteredTools, [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet, [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, @@ -124,11 +111,9 @@ macro_rules! arena_types { rustc_hir::def_id::DefId, rustc_middle::ty::EarlyBinder> >, - [] bit_set_u32: rustc_index::bit_set::BitSet, [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>, [] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>, [decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap, - [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>), [] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem, [] mod_child: rustc_middle::metadata::ModChild, [] features: rustc_feature::Features, diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 76ef62f9f2728..dc0da165af67d 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -8,8 +8,8 @@ mod dep_node; pub use rustc_query_system::dep_graph::debug::EdgeFilter; pub use rustc_query_system::dep_graph::{ - debug::DepNodeFilter, hash_result, DepContext, DepGraphQuery, DepNodeColor, DepNodeIndex, Deps, - SerializedDepGraph, SerializedDepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct, WorkProductId, + debug::DepNodeFilter, hash_result, DepContext, DepGraphQuery, DepNodeIndex, Deps, + SerializedDepGraph, SerializedDepNodeIndex, TaskDepsRef, WorkProduct, WorkProductId, WorkProductMap, }; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 58c0c6bab4951..f407d30ac82a3 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -9,7 +9,7 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{par_for_each_in, try_par_for_each_in, DynSend, DynSync}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE}; -use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash}; +use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::*; use rustc_index::Idx; @@ -116,7 +116,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { let parent_id = parent_id.map_or(CRATE_OWNER_ID, |local_def_index| { let def_id = LocalDefId { local_def_index }; - self.map.local_def_id_to_hir_id(def_id).owner + self.map.tcx.local_def_id_to_hir_id(def_id).owner }); self.current_id = HirId::make_owner(parent_id.def_id); @@ -168,108 +168,6 @@ impl<'hir> Map<'hir> { self.tcx.definitions_untracked().def_path_hash(def_id) } - #[inline] - pub fn local_def_id_to_hir_id(self, def_id: impl Into) -> HirId { - self.tcx.local_def_id_to_hir_id(def_id.into()) - } - - /// Do not call this function directly. The query should be called. - pub(super) fn opt_def_kind(self, local_def_id: LocalDefId) -> Option { - let hir_id = self.local_def_id_to_hir_id(local_def_id); - let node = match self.find(hir_id) { - Some(node) => node, - None => match self.def_key(local_def_id).disambiguated_data.data { - // FIXME: Some anonymous constants do not have corresponding HIR nodes, - // so many local queries will panic on their def ids. `None` is currently - // returned here instead of `DefKind::{Anon,Inline}Const` to avoid such panics. - // Ideally all def ids should have `DefKind`s, we need to create the missing - // HIR nodes or feed relevant query results to achieve that. - DefPathData::AnonConst => return None, - _ => bug!("no HIR node for def id {local_def_id:?}"), - }, - }; - let def_kind = match node { - Node::Item(item) => match item.kind { - ItemKind::Static(_, mt, _) => DefKind::Static(mt), - ItemKind::Const(..) => DefKind::Const, - ItemKind::Fn(..) => DefKind::Fn, - ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), - ItemKind::Mod(..) => DefKind::Mod, - ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, - ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Enum(..) => DefKind::Enum, - ItemKind::Struct(..) => DefKind::Struct, - ItemKind::Union(..) => DefKind::Union, - ItemKind::Trait(..) => DefKind::Trait, - ItemKind::TraitAlias(..) => DefKind::TraitAlias, - ItemKind::ExternCrate(_) => DefKind::ExternCrate, - ItemKind::Use(..) => DefKind::Use, - ItemKind::ForeignMod { .. } => DefKind::ForeignMod, - ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, - ItemKind::Impl(impl_) => DefKind::Impl { of_trait: impl_.of_trait.is_some() }, - }, - Node::ForeignItem(item) => match item.kind { - ForeignItemKind::Fn(..) => DefKind::Fn, - ForeignItemKind::Static(_, mt) => DefKind::Static(mt), - ForeignItemKind::Type => DefKind::ForeignTy, - }, - Node::TraitItem(item) => match item.kind { - TraitItemKind::Const(..) => DefKind::AssocConst, - TraitItemKind::Fn(..) => DefKind::AssocFn, - TraitItemKind::Type(..) => DefKind::AssocTy, - }, - Node::ImplItem(item) => match item.kind { - ImplItemKind::Const(..) => DefKind::AssocConst, - ImplItemKind::Fn(..) => DefKind::AssocFn, - ImplItemKind::Type(..) => DefKind::AssocTy, - }, - Node::Variant(_) => DefKind::Variant, - Node::Ctor(variant_data) => { - let ctor_of = match self.find_parent(hir_id) { - Some(Node::Item(..)) => def::CtorOf::Struct, - Some(Node::Variant(..)) => def::CtorOf::Variant, - _ => unreachable!(), - }; - match variant_data.ctor_kind() { - Some(kind) => DefKind::Ctor(ctor_of, kind), - None => bug!("constructor node without a constructor"), - } - } - Node::AnonConst(_) => DefKind::AnonConst, - Node::ConstBlock(_) => DefKind::InlineConst, - Node::Field(_) => DefKind::Field, - Node::Expr(expr) => match expr.kind { - ExprKind::Closure(Closure { movability: None, .. }) => DefKind::Closure, - ExprKind::Closure(Closure { movability: Some(_), .. }) => DefKind::Coroutine, - _ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)), - }, - Node::GenericParam(param) => match param.kind { - GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam, - GenericParamKind::Type { .. } => DefKind::TyParam, - GenericParamKind::Const { .. } => DefKind::ConstParam, - }, - Node::Crate(_) => DefKind::Mod, - Node::Stmt(_) - | Node::PathSegment(_) - | Node::Ty(_) - | Node::TypeBinding(_) - | Node::Infer(_) - | Node::TraitRef(_) - | Node::Pat(_) - | Node::PatField(_) - | Node::ExprField(_) - | Node::Local(_) - | Node::Param(_) - | Node::Arm(_) - | Node::Lifetime(_) - | Node::Block(_) => span_bug!( - self.span(hir_id), - "unexpected node with def id {local_def_id:?}: {node:?}" - ), - }; - Some(def_kind) - } - /// Finds the id of the parent node to this one. /// /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`]. @@ -419,7 +317,7 @@ impl<'hir> Map<'hir> { #[track_caller] pub fn body_owned_by(self, id: LocalDefId) -> BodyId { self.maybe_body_owned_by(id).unwrap_or_else(|| { - let hir_id = self.local_def_id_to_hir_id(id); + let hir_id = self.tcx.local_def_id_to_hir_id(id); span_bug!( self.span(hir_id), "body_owned_by: {} has no associated body", @@ -445,7 +343,7 @@ impl<'hir> Map<'hir> { } DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, - DefKind::Closure | DefKind::Coroutine => BodyOwnerKind::Closure, + DefKind::Closure => BodyOwnerKind::Closure, DefKind::Static(mt) => BodyOwnerKind::Static(mt), dk => bug!("{:?} is not a body node: {:?}", def_id, dk), } @@ -531,9 +429,7 @@ impl<'hir> Map<'hir> { pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module.to_local_def_id()); match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) { - Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => { - (m, span, hir_id) - } + Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. })) => (m, span, hir_id), Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {node:?}"), } @@ -897,7 +793,7 @@ impl<'hir> Map<'hir> { #[inline] fn opt_ident(self, id: HirId) -> Option { - match self.get(id) { + match self.find(id)? { Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident), // A `Ctor` doesn't have an identifier itself, but its parent // struct/variant does. Compare with `hir::Map::opt_span`. @@ -1278,7 +1174,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ItemKind::ForeignMod { .. } => "foreign mod", ItemKind::GlobalAsm(..) => "global asm", ItemKind::TyAlias(..) => "ty", - ItemKind::OpaqueTy(ref opaque) => { + ItemKind::OpaqueTy(opaque) => { if opaque.in_trait { "opaque type in trait" } else { @@ -1314,10 +1210,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id)) } - Some(Node::Variant(ref variant)) => { + Some(Node::Variant(variant)) => { format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id)) } - Some(Node::Field(ref field)) => { + Some(Node::Field(field)) => { format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id)) } Some(Node::AnonConst(_)) => node_str("const"), @@ -1341,7 +1237,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ctor.ctor_def_id().map_or("".into(), |def_id| path_str(def_id)), ), Some(Node::Lifetime(_)) => node_str("lifetime"), - Some(Node::GenericParam(ref param)) => { + Some(Node::GenericParam(param)) => { format!("{id} (generic_param {})", path_str(param.def_id)) } Some(Node::Crate(..)) => String::from("(root_crate)"), diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index f28ec771169fd..a16317a0c670b 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -166,7 +166,7 @@ pub fn provide(providers: &mut Providers) { providers.hir_owner_parent = |tcx, id| { // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash. tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| { - let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent); + let mut parent_hir_id = tcx.local_def_id_to_hir_id(parent); parent_hir_id.local_id = tcx.hir_crate(()).owners[parent_hir_id.owner.def_id].unwrap().parenting[&id.def_id]; parent_hir_id @@ -176,16 +176,16 @@ pub fn provide(providers: &mut Providers) { tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) }; providers.def_span = |tcx, def_id| { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP) }; providers.def_ident_span = |tcx, def_id| { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.hir().opt_ident_span(hir_id) }; providers.fn_arg_names = |tcx, def_id| { let hir = tcx.hir(); - let hir_id = hir.local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); if let Some(body_id) = hir.maybe_body_owned_by(def_id) { tcx.arena.alloc_from_iter(hir.body_param_names(body_id)) } else if let Node::TraitItem(&TraitItem { @@ -202,7 +202,6 @@ pub fn provide(providers: &mut Providers) { span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", def_id); } }; - providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id); providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls; providers.expn_that_defined = |tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root()); diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 0b5426c3bb1a1..ef5a1caadb7bd 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,6 +23,8 @@ use rustc_macros::HashStable; use rustc_type_ir::Canonical as IrCanonical; +use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo; +pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind}; use smallvec::SmallVec; use std::ops::Index; @@ -33,6 +35,8 @@ use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt}; pub type Canonical<'tcx, V> = IrCanonical, V>; +pub type CanonicalVarInfo<'tcx> = IrCanonicalVarInfo>; + pub type CanonicalVarInfos<'tcx> = &'tcx List>; impl<'tcx> ty::TypeFoldable> for CanonicalVarInfos<'tcx> { @@ -63,7 +67,7 @@ impl CanonicalVarValues<'_> { pub fn is_identity(&self) -> bool { self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() { ty::GenericArgKind::Lifetime(r) => { - matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv) + matches!(*r, ty::ReBound(ty::INNERMOST, br) if br.var.as_usize() == bv) } ty::GenericArgKind::Type(ty) => { matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv) @@ -79,7 +83,7 @@ impl CanonicalVarValues<'_> { for arg in self.var_values { match arg.unpack() { ty::GenericArgKind::Lifetime(r) => { - if let ty::ReLateBound(ty::INNERMOST, br) = *r + if let ty::ReBound(ty::INNERMOST, br) = *r && var == br.var { var = var + 1; @@ -138,158 +142,6 @@ impl<'tcx> Default for OriginalQueryValues<'tcx> { } } -/// Information about a canonical variable that is included with the -/// canonical value. This is sufficient information for code to create -/// a copy of the canonical value in some other inference context, -/// with fresh inference variables replacing the canonical values. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct CanonicalVarInfo<'tcx> { - pub kind: CanonicalVarKind<'tcx>, -} - -impl<'tcx> CanonicalVarInfo<'tcx> { - pub fn universe(&self) -> ty::UniverseIndex { - self.kind.universe() - } - - #[must_use] - pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> { - CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) } - } - - pub fn is_existential(&self) -> bool { - match self.kind { - CanonicalVarKind::Ty(_) => true, - CanonicalVarKind::PlaceholderTy(_) => false, - CanonicalVarKind::Region(_) => true, - CanonicalVarKind::PlaceholderRegion(..) => false, - CanonicalVarKind::Const(..) => true, - CanonicalVarKind::PlaceholderConst(_, _) => false, - CanonicalVarKind::Effect => true, - } - } - - pub fn is_region(&self) -> bool { - match self.kind { - CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true, - CanonicalVarKind::Ty(_) - | CanonicalVarKind::PlaceholderTy(_) - | CanonicalVarKind::Const(_, _) - | CanonicalVarKind::PlaceholderConst(_, _) - | CanonicalVarKind::Effect => false, - } - } - - pub fn expect_placeholder_index(self) -> usize { - match self.kind { - CanonicalVarKind::Ty(_) - | CanonicalVarKind::Region(_) - | CanonicalVarKind::Const(_, _) - | CanonicalVarKind::Effect => bug!("expected placeholder: {self:?}"), - - CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(), - CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(), - CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(), - } - } -} - -/// Describes the "kind" of the canonical variable. This is a "kind" -/// in the type-theory sense of the term -- i.e., a "meta" type system -/// that analyzes type-like values. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] -pub enum CanonicalVarKind<'tcx> { - /// Some kind of type inference variable. - Ty(CanonicalTyVarKind), - - /// A "placeholder" that represents "any type". - PlaceholderTy(ty::PlaceholderType), - - /// Region variable `'?R`. - Region(ty::UniverseIndex), - - /// A "placeholder" that represents "any region". Created when you - /// are solving a goal like `for<'a> T: Foo<'a>` to represent the - /// bound region `'a`. - PlaceholderRegion(ty::PlaceholderRegion), - - /// Some kind of const inference variable. - Const(ty::UniverseIndex, Ty<'tcx>), - - /// Effect variable `'?E`. - Effect, - - /// A "placeholder" that represents "any const". - PlaceholderConst(ty::PlaceholderConst<'tcx>, Ty<'tcx>), -} - -impl<'tcx> CanonicalVarKind<'tcx> { - pub fn universe(self) -> ty::UniverseIndex { - match self { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui, - CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => { - ty::UniverseIndex::ROOT - } - CanonicalVarKind::Effect => ty::UniverseIndex::ROOT, - CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe, - CanonicalVarKind::Region(ui) => ui, - CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe, - CanonicalVarKind::Const(ui, _) => ui, - CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe, - } - } - - /// Replaces the universe of this canonical variable with `ui`. - /// - /// In case this is a float or int variable, this causes an ICE if - /// the updated universe is not the root. - pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> { - match self { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) - } - CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) - | CanonicalVarKind::Effect => { - assert_eq!(ui, ty::UniverseIndex::ROOT); - self - } - CanonicalVarKind::PlaceholderTy(placeholder) => { - CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder }) - } - CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui), - CanonicalVarKind::PlaceholderRegion(placeholder) => { - CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder }) - } - CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty), - CanonicalVarKind::PlaceholderConst(placeholder, ty) => { - CanonicalVarKind::PlaceholderConst( - ty::Placeholder { universe: ui, ..placeholder }, - ty, - ) - } - } - } -} - -/// Rust actually has more than one category of type variables; -/// notably, the type variables we create for literals (e.g., 22 or -/// 22.) can only be instantiated with integral/float types (e.g., -/// usize or f32). In order to faithfully reproduce a type, we need to -/// know what set of types a given type variable can be unified with. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)] -pub enum CanonicalTyVarKind { - /// General type variable `?T` that can be unified with arbitrary types. - General(ty::UniverseIndex), - - /// Integral type variable `?I` (that can only be unified with integral types). - Int, - - /// Floating-point type variable `?F` (that can only be unified with float types). - Float, -} - /// After we execute a query with a canonicalized key, we get back a /// `Canonical>`. You can use /// `instantiate_query_result` to access the data in this result. @@ -366,7 +218,6 @@ pub type QueryOutlivesConstraint<'tcx> = TrivialTypeTraversalImpls! { crate::infer::canonical::Certainty, - crate::infer::canonical::CanonicalTyVarKind, } impl<'tcx> CanonicalVarValues<'tcx> { @@ -389,7 +240,7 @@ impl<'tcx> CanonicalVarValues<'tcx> { var: ty::BoundVar::from_usize(i), kind: ty::BrAnon, }; - ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into() + ty::Region::new_bound(tcx, ty::INNERMOST, br).into() } CanonicalVarKind::Effect => ty::Const::new_bound( tcx, diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 041a63776d113..6e50e89404648 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -58,18 +58,17 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { fn unify_values(value1: &Self, value2: &Self) -> Result { // We pick the value of the least universe because it is compatible with more variables. - // This is *not* necessary for soundness, but it allows more region variables to be - // resolved to the said value. + // This is *not* necessary for completeness. #[cold] fn min_universe<'tcx>(r1: Region<'tcx>, r2: Region<'tcx>) -> Region<'tcx> { cmp::min_by_key(r1, r2, |r| match r.kind() { ty::ReStatic | ty::ReErased - | ty::ReFree(..) - | ty::ReEarlyBound(..) + | ty::ReLateParam(..) + | ty::ReEarlyParam(..) | ty::ReError(_) => ty::UniverseIndex::ROOT, ty::RePlaceholder(placeholder) => placeholder.universe, - ty::ReVar(..) | ty::ReLateBound(..) => bug!("not a universal region"), + ty::ReVar(..) | ty::ReBound(..) => bug!("not a universal region"), }) } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 448a3029ae97a..e048268fad120 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -23,8 +23,8 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(allocator_api)] #![feature(array_windows)] #![feature(assert_matches)] @@ -32,8 +32,7 @@ #![feature(core_intrinsics)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] -#![cfg_attr(bootstrap, feature(generators))] -#![cfg_attr(not(bootstrap), feature(coroutines))] +#![feature(coroutines)] #![feature(get_mut_unchecked)] #![feature(if_let_guard)] #![feature(inline_const)] @@ -50,7 +49,7 @@ #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(control_flow_enum)] -#![feature(trait_upcasting)] +#![cfg_attr(bootstrap, feature(trait_upcasting))] #![feature(trusted_step)] #![feature(try_blocks)] #![feature(try_reserve_kind)] @@ -59,7 +58,6 @@ #![feature(extract_if)] #![feature(intra_doc_pointers)] #![feature(yeet_expr)] -#![feature(result_option_inspect)] #![feature(const_option)] #![feature(trait_alias)] #![feature(ptr_alignment_type)] @@ -79,9 +77,6 @@ extern crate tracing; #[macro_use] extern crate smallvec; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - #[cfg(test)] mod tests; @@ -112,4 +107,4 @@ pub mod dep_graph; // Allows macros to refer to this crate as `::rustc_middle` extern crate self as rustc_middle; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index c1884bb8068d7..8c1e58fefc589 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -4,9 +4,10 @@ /// /// If you have a span available, you should use [`span_bug`] instead. /// -/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful. +/// If the bug should only be emitted when compilation didn't fail, [`Session::span_delayed_bug`] +/// may be useful. /// -/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug +/// [`Session::span_delayed_bug`]: rustc_session::Session::span_delayed_bug /// [`span_bug`]: crate::span_bug #[macro_export] macro_rules! bug { @@ -23,9 +24,10 @@ macro_rules! bug { /// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger /// ICEs. /// -/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful. +/// If the bug should only be emitted when compilation didn't fail, [`Session::span_delayed_bug`] +/// may be useful. /// -/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug +/// [`Session::span_delayed_bug`]: rustc_session::Session::span_delayed_bug #[macro_export] macro_rules! span_bug { ($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) }); diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index e30b6b203d73c..59ce0a14b2a5f 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -35,7 +35,12 @@ pub enum SymbolExportKind { pub struct SymbolExportInfo { pub level: SymbolExportLevel, pub kind: SymbolExportKind, + /// Used to mark these symbols not to be internalized by LTO. These symbols + /// are also added to `symbols.o` to avoid circular dependencies when linking. pub used: bool, + /// Also used to mark these symbols not to be internalized by LTO. But will + /// not be added to `symbols.o`. Currently there are only builtin functions. + pub used_compiler: bool, } #[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)] diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 85c5af9ca13cb..8c1b1ff12e98c 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -7,22 +7,23 @@ pub mod lib_features { use rustc_data_structures::fx::FxHashMap; use rustc_span::{symbol::Symbol, Span}; - #[derive(HashStable, Debug)] + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + #[derive(HashStable, TyEncodable, TyDecodable)] + pub enum FeatureStability { + AcceptedSince(Symbol), + Unstable, + } + + #[derive(HashStable, Debug, Default)] pub struct LibFeatures { - /// A map from feature to stabilisation version. - pub stable: FxHashMap, - pub unstable: FxHashMap, + pub stability: FxHashMap, } impl LibFeatures { - pub fn to_vec(&self) -> Vec<(Symbol, Option)> { - let mut all_features: Vec<_> = self - .stable - .iter() - .map(|(f, (s, _))| (*f, Some(*s))) - .chain(self.unstable.keys().map(|f| (*f, None))) - .collect(); - all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap()); + pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> { + let mut all_features: Vec<_> = + self.stability.iter().map(|(&sym, &(stab, _))| (sym, stab)).collect(); + all_features.sort_unstable_by(|(a, _), (b, _)| a.as_str().cmp(b.as_str())); all_features } } diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 56fed05c63f74..b8f04ed03dcaa 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -77,7 +77,7 @@ use std::ops::Deref; /// picture, but rather the ending point. // // FIXME(pnkfelix): this currently derives `PartialOrd` and `Ord` to -// placate the same deriving in `ty::FreeRegion`, but we may want to +// placate the same deriving in `ty::LateParamRegion`, but we may want to // actually attach a more meaningful ordering to scopes than the one // generated via deriving here. #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, TyEncodable, TyDecodable)] @@ -148,6 +148,8 @@ rustc_index::newtype_index! { /// * The subscope with `first_statement_index == 1` is scope of `c`, /// and thus does not include EXPR_2, but covers the `...`. #[derive(HashStable)] + #[encodable] + #[orderable] pub struct FirstStatementIndex {} } @@ -178,7 +180,7 @@ impl Scope { }; let span = tcx.hir().span(hir_id); if let ScopeData::Remainder(first_statement_index) = self.data { - if let Node::Block(ref blk) = tcx.hir().get(hir_id) { + if let Node::Block(blk) = tcx.hir().get(hir_id) { // Want span for scope starting after the // indexed statement and ending at end of // `blk`; reuse span of `blk` and shift `lo` diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index f7a55fa95b697..27d82f5fefc44 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -566,7 +566,7 @@ impl<'tcx> TyCtxt<'tcx> { |span, def_id| { // The API could be uncallable for other reasons, for example when a private module // was referenced. - self.sess.delay_span_bug(span, format!("encountered unmarked API: {def_id:?}")); + self.sess.span_delayed_bug(span, format!("encountered unmarked API: {def_id:?}")); }, ) } diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index a9d09709e8427..26138157b74e9 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -1,17 +1,16 @@ use std::fmt::{self, Debug, Display, Formatter}; use rustc_hir; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir}; +use rustc_hir::def_id::DefId; use rustc_session::RemapFileNameExt; use rustc_span::Span; use rustc_target::abi::{HasDataLayout, Size}; use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar}; use crate::mir::{pretty_print_const_value, Promoted}; +use crate::ty::GenericArgsRef; use crate::ty::ScalarInt; -use crate::ty::{self, print::pretty_print_const, List, Ty, TyCtxt}; -use crate::ty::{GenericArgs, GenericArgsRef}; +use crate::ty::{self, print::pretty_print_const, Ty, TyCtxt}; /////////////////////////////////////////////////////////////////////////// /// Evaluated Constants @@ -76,7 +75,7 @@ static_assert_size!(ConstValue<'_>, 24); impl<'tcx> ConstValue<'tcx> { #[inline] - pub fn try_to_scalar(&self) -> Option> { + pub fn try_to_scalar(&self) -> Option { match *self { ConstValue::Indirect { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None, ConstValue::Scalar(val) => Some(val), @@ -162,8 +161,8 @@ impl<'tcx> ConstValue<'tcx> { return Some(&[]); } // Non-empty slice, must have memory. We know this is a relative pointer. - let (inner_alloc_id, offset) = ptr.into_parts(); - let data = tcx.global_alloc(inner_alloc_id?).unwrap_memory(); + let (inner_prov, offset) = ptr.into_parts(); + let data = tcx.global_alloc(inner_prov?.alloc_id()).unwrap_memory(); (data, offset.bytes(), offset.bytes() + len) } }; @@ -220,6 +219,17 @@ pub enum Const<'tcx> { } impl<'tcx> Const<'tcx> { + pub fn identity_unevaluated(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::EarlyBinder> { + ty::EarlyBinder::bind(Const::Unevaluated( + UnevaluatedConst { + def: def_id, + args: ty::GenericArgs::identity_for_item(tcx, def_id), + promoted: None, + }, + tcx.type_of(def_id).skip_binder(), + )) + } + #[inline(always)] pub fn ty(&self) -> Ty<'tcx> { match self { @@ -399,101 +409,6 @@ impl<'tcx> Const<'tcx> { Self::Val(val, ty) } - /// Literals are converted to `Const::Val`, const generic parameters are eagerly - /// converted to a constant, everything else becomes `Unevaluated`. - #[instrument(skip(tcx), level = "debug", ret)] - pub fn from_anon_const( - tcx: TyCtxt<'tcx>, - def: LocalDefId, - param_env: ty::ParamEnv<'tcx>, - ) -> Self { - let body_id = match tcx.hir().get_by_def_id(def) { - hir::Node::AnonConst(ac) => ac.body, - _ => { - span_bug!(tcx.def_span(def), "from_anon_const can only process anonymous constants") - } - }; - - let expr = &tcx.hir().body(body_id).value; - debug!(?expr); - - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = match &expr.kind { - hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { - block.expr.as_ref().unwrap() - } - _ => expr, - }; - debug!("expr.kind: {:?}", expr.kind); - - let ty = tcx.type_of(def).instantiate_identity(); - debug!(?ty); - - // FIXME(const_generics): We currently have to special case parameters because `min_const_generics` - // does not provide the parents generics to anonymous constants. We still allow generic const - // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to - // ever try to substitute the generic parameters in their bodies. - // - // While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does - // cause issues if we were to remove that special-case and try to evaluate the constant instead. - use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; - match expr.kind { - ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { - // Find the name and index of the const parameter by indexing the generics of - // the parent item and construct a `ParamConst`. - let item_def_id = tcx.parent(def_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.item_name(def_id); - let ty_const = ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty); - debug!(?ty_const); - - return Self::Ty(ty_const); - } - _ => {} - } - - let hir_id = tcx.hir().local_def_id_to_hir_id(def); - let parent_args = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) - && let Some(parent_did) = parent_hir_id.as_owner() - { - GenericArgs::identity_for_item(tcx, parent_did) - } else { - List::empty() - }; - debug!(?parent_args); - - let did = def.to_def_id(); - let child_args = GenericArgs::identity_for_item(tcx, did); - let args = tcx.mk_args_from_iter(parent_args.into_iter().chain(child_args.into_iter())); - debug!(?args); - - let span = tcx.def_span(def); - let uneval = UnevaluatedConst::new(did, args); - debug!(?span, ?param_env); - - match tcx.const_eval_resolve(param_env, uneval, Some(span)) { - Ok(val) => { - debug!("evaluated const value"); - Self::Val(val, ty) - } - Err(_) => { - debug!("error encountered during evaluation"); - // Error was handled in `const_eval_resolve`. Here we just create a - // new unevaluated const and error hard later in codegen - Self::Unevaluated( - UnevaluatedConst { - def: did, - args: GenericArgs::identity_for_item(tcx, did), - promoted: None, - }, - ty, - ) - } - } - } - pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self { match c.kind() { ty::ConstKind::Value(valtree) => { @@ -592,7 +507,7 @@ impl<'tcx> TyCtxt<'tcx> { let caller = self.sess.source_map().lookup_char_pos(topmost.lo()); self.const_caller_location( rustc_span::symbol::Symbol::intern( - &caller.file.name.for_codegen(&self.sess).to_string_lossy(), + &caller.file.name.for_codegen(self.sess).to_string_lossy(), ), caller.line as u32, caller.col_display as u32 + 1, diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 08d377a8695f9..f15ee0082cede 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -17,6 +17,8 @@ rustc_index::newtype_index! { /// Note that LLVM handles counter IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. #[derive(HashStable)] + #[encodable] + #[orderable] #[max = 0xFFFF_FFFF] #[debug_format = "CounterId({})"] pub struct CounterId {} @@ -37,6 +39,8 @@ rustc_index::newtype_index! { /// Note that LLVM handles expression IDs as `uint32_t`, so there is no need /// to use a larger representation on the Rust side. #[derive(HashStable)] + #[encodable] + #[orderable] #[max = 0xFFFF_FFFF] #[debug_format = "ExpressionId({})"] pub struct ExpressionId {} diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index aded3e495d922..2a9e0847f439f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -18,9 +18,9 @@ use rustc_span::DUMMY_SP; use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ - read_target_uint, write_target_uint, AllocId, BadBytesAccess, InterpError, InterpResult, - Pointer, PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch, - UndefinedBehaviorInfo, UnsupportedOpInfo, + read_target_uint, write_target_uint, AllocId, BadBytesAccess, CtfeProvenance, InterpError, + InterpResult, Pointer, PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, + ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, }; use crate::ty; use init_mask::*; @@ -63,7 +63,7 @@ impl AllocBytes for Box<[u8]> { // hashed. (see the `Hash` impl below for more details), so the impl is not derived. #[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)] #[derive(HashStable)] -pub struct Allocation> { +pub struct Allocation> { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. bytes: Bytes, @@ -315,7 +315,7 @@ impl Allocation { pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> { Self::uninit_inner(size, align, || { ty::tls::with(|tcx| { - tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation") + tcx.sess.span_delayed_bug(DUMMY_SP, "exhausted memory during interpretation") }); InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted).into() }) @@ -336,14 +336,14 @@ impl Allocation { } } -impl Allocation { - /// Adjust allocation from the ones in tcx to a custom Machine instance - /// with a different Provenance and Extra type. +impl Allocation { + /// Adjust allocation from the ones in `tcx` to a custom Machine instance + /// with a different `Provenance` and `Extra` type. pub fn adjust_from_tcx( self, cx: &impl HasDataLayout, extra: Extra, - mut adjust_ptr: impl FnMut(Pointer) -> Result, Err>, + mut adjust_ptr: impl FnMut(Pointer) -> Result, Err>, ) -> Result, Err> { let mut bytes = self.bytes; // Adjust provenance of pointers stored in this allocation. 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 d504af6b7ead1..9459af490e326 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -6,14 +6,14 @@ use std::cmp; use rustc_data_structures::sorted_map::SortedMap; use rustc_target::abi::{HasDataLayout, Size}; -use super::{alloc_range, AllocError, AllocId, AllocRange, AllocResult, Provenance}; +use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; /// Stores the provenance information of pointers stored in memory. #[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(HashStable)] -pub struct ProvenanceMap { - /// Provenance in this map applies from the given offset for an entire pointer-size worth of +pub struct ProvenanceMap { + /// `Provenance` in this map applies from the given offset for an entire pointer-size worth of /// bytes. Two entries in this map are always at least a pointer size apart. ptrs: SortedMap, /// Provenance in this map only applies to the given single byte. @@ -22,18 +22,19 @@ pub struct ProvenanceMap { bytes: Option>>, } +// These impls are generic over `Prov` since `CtfeProvenance` is only decodable/encodable +// for some particular `D`/`S`. impl> Decodable for ProvenanceMap { fn decode(d: &mut D) -> Self { - assert!(!Prov::OFFSET_IS_ADDR); // only `AllocId` is ever serialized + assert!(!Prov::OFFSET_IS_ADDR); // only `CtfeProvenance` is ever serialized Self { ptrs: Decodable::decode(d), bytes: None } } } - impl> Encodable for ProvenanceMap { fn encode(&self, s: &mut S) { let Self { ptrs, bytes } = self; - assert!(!Prov::OFFSET_IS_ADDR); // only `AllocId` is ever serialized - debug_assert!(bytes.is_none()); + assert!(!Prov::OFFSET_IS_ADDR); // only `CtfeProvenance` is ever serialized + debug_assert!(bytes.is_none()); // without `OFFSET_IS_ADDR`, this is always empty ptrs.encode(s) } } @@ -54,10 +55,10 @@ impl ProvenanceMap { /// Give access to the ptr-sized provenances (which can also be thought of as relocations, and /// indeed that is how codegen treats them). /// - /// Only exposed with `AllocId` provenance, since it panics if there is bytewise provenance. + /// Only exposed with `CtfeProvenance` provenance, since it panics if there is bytewise provenance. #[inline] - pub fn ptrs(&self) -> &SortedMap { - debug_assert!(self.bytes.is_none()); // `AllocId::OFFSET_IS_ADDR` is false so this cannot fail + pub fn ptrs(&self) -> &SortedMap { + debug_assert!(self.bytes.is_none()); // `CtfeProvenance::OFFSET_IS_ADDR` is false so this cannot fail &self.ptrs } } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 44b22e2d38386..41386793987f5 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -290,7 +290,7 @@ macro_rules! impl_into_diagnostic_arg_through_debug { // These types have nice `Debug` output so we can just use them in diagnostics. impl_into_diagnostic_arg_through_debug! { AllocId, - Pointer, + Pointer, AllocRange, } @@ -323,7 +323,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Invalid metadata in a wide pointer InvalidMeta(InvalidMetaKind), /// Reading a C string that does not end within its allocation. - UnterminatedCString(Pointer), + UnterminatedCString(Pointer), /// Using a pointer after it got freed. PointerUseAfterFree(AllocId, CheckInAllocMsg), /// Used a pointer outside the bounds it is valid for. @@ -350,11 +350,11 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Using a non-character `u32` as character. InvalidChar(u32), /// The tag of an enum does not encode an actual discriminant. - InvalidTag(Scalar), + InvalidTag(Scalar), /// Using a pointer-not-to-a-function as function pointer. - InvalidFunctionPointer(Pointer), + InvalidFunctionPointer(Pointer), /// Using a pointer-not-to-a-vtable as vtable pointer. - InvalidVTablePointer(Pointer), + InvalidVTablePointer(Pointer), /// Using a string that is not valid UTF-8, InvalidStr(std::str::Utf8Error), /// Using uninitialized data where it is not allowed. diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index e360fb3eaaf3c..2db5600855343 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -157,7 +157,7 @@ pub use self::allocation::{ InitChunk, InitChunkIter, }; -pub use self::pointer::{Pointer, PointerArithmetic, Provenance}; +pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; /// Uniquely identifies one of the following: /// - A constant @@ -199,7 +199,7 @@ pub struct LitToConstInput<'tcx> { #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable)] pub enum LitToConstError { /// The literal's inferred type did not match the expected `ty` in the input. - /// This is used for graceful error handling (`delay_span_bug`) in + /// This is used for graceful error handling (`span_delayed_bug`) in /// type checking (`Const::from_anon_const`). TypeError, Reported(ErrorGuaranteed), diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 1c9ce1cb1308c..6893387736a5a 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -3,7 +3,7 @@ use super::{AllocId, InterpResult}; use rustc_macros::HashStable; use rustc_target::abi::{HasDataLayout, Size}; -use std::fmt; +use std::{fmt, num::NonZeroU64}; //////////////////////////////////////////////////////////////////////////////// // Pointer arithmetic @@ -114,22 +114,7 @@ pub trait Provenance: Copy + fmt::Debug + 'static { const OFFSET_IS_ADDR: bool; /// Determines how a pointer should be printed. - /// - /// Default impl is only good for when `OFFSET_IS_ADDR == true`. - fn fmt(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result - where - Self: Sized, - { - assert!(Self::OFFSET_IS_ADDR); - let (prov, addr) = ptr.into_parts(); // address is absolute - write!(f, "{:#x}", addr.bytes())?; - if f.alternate() { - write!(f, "{prov:#?}")?; - } else { - write!(f, "{prov:?}")?; - } - Ok(()) - } + fn fmt(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result; /// If `OFFSET_IS_ADDR == false`, provenance must always be able to /// identify the allocation this ptr points to (i.e., this must return `Some`). @@ -141,6 +126,80 @@ pub trait Provenance: Copy + fmt::Debug + 'static { fn join(left: Option, right: Option) -> Option; } +/// The type of provenance in the compile-time interpreter. +/// This is a packed representation of an `AllocId` and an `immutable: bool`. +#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct CtfeProvenance(NonZeroU64); + +impl From for CtfeProvenance { + fn from(value: AllocId) -> Self { + let prov = CtfeProvenance(value.0); + assert!(!prov.immutable(), "`AllocId` with the highest bit set cannot be used in CTFE"); + prov + } +} + +impl fmt::Debug for CtfeProvenance { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.alloc_id(), f)?; // propagates `alternate` flag + if self.immutable() { + write!(f, "")?; + } + Ok(()) + } +} + +const IMMUTABLE_MASK: u64 = 1 << 63; // the highest bit + +impl CtfeProvenance { + /// Returns the `AllocId` of this provenance. + #[inline(always)] + pub fn alloc_id(self) -> AllocId { + AllocId(NonZeroU64::new(self.0.get() & !IMMUTABLE_MASK).unwrap()) + } + + /// Returns whether this provenance is immutable. + #[inline] + pub fn immutable(self) -> bool { + self.0.get() & IMMUTABLE_MASK != 0 + } + + /// Returns an immutable version of this provenance. + #[inline] + pub fn as_immutable(self) -> Self { + CtfeProvenance(self.0 | IMMUTABLE_MASK) + } +} + +impl Provenance for CtfeProvenance { + // With the `AllocId` as provenance, the `offset` is interpreted *relative to the allocation*, + // so ptr-to-int casts are not possible (since we do not know the global physical offset). + const OFFSET_IS_ADDR: bool = false; + + fn fmt(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Print AllocId. + fmt::Debug::fmt(&ptr.provenance.alloc_id(), f)?; // propagates `alternate` flag + // Print offset only if it is non-zero. + if ptr.offset.bytes() > 0 { + write!(f, "+{:#x}", ptr.offset.bytes())?; + } + // Print immutable status. + if ptr.provenance.immutable() { + write!(f, "")?; + } + Ok(()) + } + + fn get_alloc_id(self) -> Option { + Some(self.alloc_id()) + } + + fn join(_left: Option, _right: Option) -> Option { + panic!("merging provenance is not supported when `OFFSET_IS_ADDR` is false") + } +} + +// We also need this impl so that one can debug-print `Pointer` impl Provenance for AllocId { // With the `AllocId` as provenance, the `offset` is interpreted *relative to the allocation*, // so ptr-to-int casts are not possible (since we do not know the global physical offset). @@ -174,7 +233,7 @@ impl Provenance for AllocId { /// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to. #[derive(Copy, Clone, Eq, PartialEq, TyEncodable, TyDecodable, Hash)] #[derive(HashStable)] -pub struct Pointer { +pub struct Pointer { pub(super) offset: Size, // kept private to avoid accidental misinterpretation (meaning depends on `Prov` type) pub provenance: Prov, } @@ -182,7 +241,7 @@ pub struct Pointer { static_assert_size!(Pointer, 16); // `Option` pointers are also passed around quite a bit // (but not stored in permanent machine state). -static_assert_size!(Pointer>, 16); +static_assert_size!(Pointer>, 16); // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. @@ -215,7 +274,7 @@ impl fmt::Display for Pointer> { impl From for Pointer { #[inline(always)] fn from(alloc_id: AllocId) -> Self { - Pointer::new(alloc_id, Size::ZERO) + Pointer::new(alloc_id.into(), Size::ZERO) } } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index fbf6403eabe39..34068a9da37e8 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -110,7 +110,7 @@ impl<'tcx> TyCtxt<'tcx> { let Some(local_def_id) = ct.def.as_local() else { return }; self.struct_span_lint_hir( lint::builtin::CONST_EVALUATABLE_UNCHECKED, - self.hir().local_def_id_to_hir_id(local_def_id), + self.local_def_id_to_hir_id(local_def_id), self.def_span(ct.def), "cannot use constants which depend on generic parameters in types", |err| err, diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 0d548f8863610..5ecff04f3ae35 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -11,7 +11,10 @@ use rustc_target::abi::{HasDataLayout, Size}; use crate::ty::ScalarInt; -use super::{AllocId, InterpResult, Pointer, PointerArithmetic, Provenance, ScalarSizeMismatch}; +use super::{ + AllocId, CtfeProvenance, InterpResult, Pointer, PointerArithmetic, Provenance, + ScalarSizeMismatch, +}; /// A `Scalar` represents an immediate, primitive value existing outside of a /// `memory::Allocation`. It is in many ways like a small chunk of an `Allocation`, up to 16 bytes in @@ -22,7 +25,7 @@ use super::{AllocId, InterpResult, Pointer, PointerArithmetic, Provenance, Scala /// Do *not* match on a `Scalar`! Use the various `to_*` methods instead. #[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, Hash)] #[derive(HashStable)] -pub enum Scalar { +pub enum Scalar { /// The raw bytes of a simple value. Int(ScalarInt), @@ -267,6 +270,9 @@ impl<'tcx, Prov: Provenance> Scalar { /// Will perform ptr-to-int casts if needed and possible. /// If that fails, we know the offset is relative, so we return an "erased" Scalar /// (which is useful for error messages but not much else). + /// + /// The error type is `AllocId`, not `CtfeProvenance`, since `AllocId` is the "minimal" + /// component all provenance types must have. #[inline] pub fn try_to_int(self) -> Result> { match self { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7054cede2d87c..1e5a7401c6f94 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -736,6 +736,8 @@ impl SourceInfo { rustc_index::newtype_index! { #[derive(HashStable)] + #[encodable] + #[orderable] #[debug_format = "_{}"] pub struct Local { const RETURN_PLACE = 0; @@ -973,7 +975,7 @@ pub enum LocalInfo<'tcx> { impl<'tcx> LocalDecl<'tcx> { pub fn local_info(&self) -> &LocalInfo<'tcx> { - &self.local_info.as_ref().assert_crate_local() + self.local_info.as_ref().assert_crate_local() } /// Returns `true` only if local is a binding that can itself be @@ -1171,6 +1173,8 @@ rustc_index::newtype_index! { /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/ #[derive(HashStable)] + #[encodable] + #[orderable] #[debug_format = "bb{}"] pub struct BasicBlock { const START_BLOCK = 0; @@ -1305,6 +1309,7 @@ impl<'tcx> BasicBlockData<'tcx> { rustc_index::newtype_index! { #[derive(HashStable)] + #[encodable] #[debug_format = "scope[{}]"] pub struct SourceScope { const OUTERMOST_SOURCE_SCOPE = 0; @@ -1533,6 +1538,8 @@ impl UserTypeProjection { rustc_index::newtype_index! { #[derive(HashStable)] + #[encodable] + #[orderable] #[debug_format = "promoted[{}]"] pub struct Promoted {} } @@ -1611,14 +1618,29 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum DefLocation { Argument, - Body(Location), + Assignment(Location), + CallReturn { call: BasicBlock, target: Option }, } impl DefLocation { pub fn dominates(self, location: Location, dominators: &Dominators) -> bool { match self { DefLocation::Argument => true, - DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators), + DefLocation::Assignment(def) => { + def.successor_within_block().dominates(location, dominators) + } + DefLocation::CallReturn { target: None, .. } => false, + DefLocation::CallReturn { call, target: Some(target) } => { + // The definition occurs on the call -> target edge. The definition dominates a use + // if and only if the edge is on all paths from the entry to the use. + // + // Note that a call terminator has only one edge that can reach the target, so when + // the call strongly dominates the target, all paths from the entry to the target + // go through the call -> target edge. + call != target + && dominators.dominates(call, target) + && dominators.dominates(target, location.block) + } } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index debd85dad2e02..bfaa0d88fc09b 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -942,7 +942,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { Ref(region, borrow_kind, ref place) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", - BorrowKind::Shallow => "shallow ", + BorrowKind::Fake => "fake ", BorrowKind::Mut { .. } => "mut ", }; @@ -1337,13 +1337,13 @@ pub fn write_allocations<'tcx>( fn alloc_ids_from_alloc( alloc: ConstAllocation<'_>, ) -> impl DoubleEndedIterator + '_ { - alloc.inner().provenance().ptrs().values().map(|id| *id) + alloc.inner().provenance().ptrs().values().map(|p| p.alloc_id()) } fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator + '_ { match val { ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => { - Either::Left(std::iter::once(ptr.provenance)) + Either::Left(std::iter::once(ptr.provenance.alloc_id())) } ConstValue::Scalar(interpret::Scalar::Int { .. }) => Either::Right(std::iter::empty()), ConstValue::ZeroSized => Either::Right(std::iter::empty()), diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 0540eb0efd6c9..98642adc19090 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -27,7 +27,7 @@ pub enum UnsafetyViolationKind { UnsafeFn, } -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub enum UnsafetyViolationDetails { CallToUnsafeFunction, UseOfInlineAssembly, @@ -39,68 +39,17 @@ pub enum UnsafetyViolationDetails { AccessToUnionField, MutationOfLayoutConstrainedField, BorrowOfLayoutConstrainedField, - CallToFunctionWith, + CallToFunctionWith { + /// Target features enabled in callee's `#[target_feature]` but missing in + /// caller's `#[target_feature]`. + missing: Vec, + /// Target features in `missing` that are enabled at compile time + /// (e.g., with `-C target-feature`). + build_enabled: Vec, + }, } -impl UnsafetyViolationDetails { - pub fn description_and_note(&self) -> (&'static str, &'static str) { - use UnsafetyViolationDetails::*; - match self { - CallToUnsafeFunction => ( - "call to unsafe function", - "consult the function's documentation for information on how to avoid undefined \ - behavior", - ), - UseOfInlineAssembly => ( - "use of inline assembly", - "inline assembly is entirely unchecked and can cause undefined behavior", - ), - InitializingTypeWith => ( - "initializing type with `rustc_layout_scalar_valid_range` attr", - "initializing a layout restricted type's field with a value outside the valid \ - range is undefined behavior", - ), - CastOfPointerToInt => { - ("cast of pointer to int", "casting pointers to integers in constants") - } - UseOfMutableStatic => ( - "use of mutable static", - "mutable statics can be mutated by multiple threads: aliasing violations or data \ - races will cause undefined behavior", - ), - UseOfExternStatic => ( - "use of extern static", - "extern statics are not controlled by the Rust type system: invalid data, \ - aliasing violations or data races will cause undefined behavior", - ), - DerefOfRawPointer => ( - "dereference of raw pointer", - "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \ - and cause data races: all of these are undefined behavior", - ), - AccessToUnionField => ( - "access to union field", - "the field may not be properly initialized: using uninitialized data will cause \ - undefined behavior", - ), - MutationOfLayoutConstrainedField => ( - "mutation of layout constrained field", - "mutating layout constrained fields cannot statically be checked for valid values", - ), - BorrowOfLayoutConstrainedField => ( - "borrow of layout constrained field with interior mutability", - "references to fields of layout constrained fields lose the constraints. Coupled \ - with interior mutability, the field can be changed to invalid values", - ), - CallToFunctionWith => ( - "call to function with `#[target_feature]`", - "can only be called if the required target features are available", - ), - } - } -} - -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub struct UnsafetyViolation { pub source_info: SourceInfo, pub lint_root: hir::HirId, @@ -132,6 +81,7 @@ pub struct UnsafetyCheckResult { rustc_index::newtype_index! { #[derive(HashStable)] + #[encodable] #[debug_format = "_{}"] pub struct CoroutineSavedLocal {} } @@ -341,7 +291,11 @@ pub enum ConstraintCategory<'tcx> { UseAsConst, UseAsStatic, TypeAnnotation, - Cast, + Cast { + /// Whether this is an unsizing cast and if yes, this contains the target type. + /// Region variables are erased to ReErased. + unsize_to: Option>, + }, /// A constraint that came from checking the body of a closure. /// @@ -416,7 +370,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { let inner = tcx.fold_regions(ty, |r, depth| match r.kind() { ty::ReVar(vid) => { let br = ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon }; - ty::Region::new_late_bound(tcx, depth, br) + ty::Region::new_bound(tcx, depth, br) } _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"), }); @@ -430,7 +384,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, ) -> Ty<'tcx> { tcx.fold_regions(self.inner, |r, depth| match r.kind() { - ty::ReLateBound(debruijn, br) => { + ty::ReBound(debruijn, br) => { debug_assert_eq!(debruijn, depth); map(ty::RegionVid::new(br.var.index())) } diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index a5358687c14c5..46e5c74c73c94 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -369,7 +369,7 @@ where debug_indent, span, viewable.span ); from_pos = span.hi(); - make_html_snippet(tcx, span, Some(&viewable)) + make_html_snippet(tcx, span, Some(viewable)) } else { None }; @@ -439,7 +439,7 @@ where tcx, from_pos, to_pos, - &remaining_viewables, + remaining_viewables, subalt, layer + 1, w, @@ -472,7 +472,7 @@ where "{}After overlaps, writing (end span?) {:?} of viewable.span {:?}", debug_indent, span, viewable.span ); - if let Some(ref html_snippet) = make_html_snippet(tcx, span, Some(&viewable)) { + if let Some(ref html_snippet) = make_html_snippet(tcx, span, Some(viewable)) { from_pos = span.hi(); write_span(html_snippet, &viewable.tooltip, alt, layer, w)?; } @@ -507,11 +507,7 @@ fn write_span( where W: Write, { - let maybe_alt_class = if layer > 0 { - if alt { " odd" } else { " even" } - } else { - "" - }; + let maybe_alt_class = if layer > 0 { if alt { " odd" } else { " even" } } else { "" }; let maybe_title_attr = if !tooltip.is_empty() { format!(" title=\"{}\"", escape_attr(tooltip)) } else { diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 5864acaed7b23..f929a5cec2533 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -159,7 +159,7 @@ impl<'tcx> Place<'tcx> { #[inline] pub fn as_ref(&self) -> PlaceRef<'tcx> { - PlaceRef { local: self.local, projection: &self.projection } + PlaceRef { local: self.local, projection: self.projection } } /// Iterate over the projections in evaluation order, i.e., the first element is the base with @@ -381,7 +381,7 @@ impl<'tcx> Operand<'tcx> { impl<'tcx> ConstOperand<'tcx> { pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { match self.const_.try_to_scalar() { - Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { + Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance.alloc_id()) { GlobalAlloc::Static(def_id) => { assert!(!tcx.is_thread_local_static(def_id)); Some(def_id) @@ -446,7 +446,7 @@ impl<'tcx> Rvalue<'tcx> { impl BorrowKind { pub fn mutability(&self) -> Mutability { match *self { - BorrowKind::Shared | BorrowKind::Shallow => Mutability::Not, + BorrowKind::Shared | BorrowKind::Fake => Mutability::Not, BorrowKind::Mut { .. } => Mutability::Mut, } } @@ -454,7 +454,7 @@ impl BorrowKind { pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared - | BorrowKind::Shallow + | BorrowKind::Fake | BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::ClosureCapture } => { false } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index b6543affc6dbe..8cf9e55f0b603 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -123,7 +123,7 @@ pub enum AnalysisPhase { /// * [`TerminatorKind::FalseEdge`] /// * [`StatementKind::FakeRead`] /// * [`StatementKind::AscribeUserType`] - /// * [`Rvalue::Ref`] with `BorrowKind::Shallow` + /// * [`Rvalue::Ref`] with `BorrowKind::Fake` /// /// Furthermore, `Deref` projections must be the first projection within any place (if they /// appear at all) @@ -182,7 +182,7 @@ pub enum BorrowKind { /// should not prevent `if let None = x { ... }`, for example, because the /// mutating `(*x as Some).0` can't affect the discriminant of `x`. /// We can also report errors with this kind of borrow differently. - Shallow, + Fake, /// Data is mutable and not aliasable. Mut { kind: MutBorrowKind }, @@ -1404,18 +1404,18 @@ pub enum BinOp { BitOr, /// The `<<` operator (shift left) /// - /// The offset is truncated to the size of the first operand before shifting. + /// The offset is truncated to the size of the first operand and made unsigned before shifting. Shl, - /// Like `Shl`, but is UB if the RHS >= LHS::BITS + /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0 ShlUnchecked, /// The `>>` operator (shift right) /// - /// The offset is truncated to the size of the first operand before shifting. + /// The offset is truncated to the size of the first operand and made unsigned before shifting. /// /// This is an arithmetic shift if the LHS is signed /// and a logical shift if the LHS is unsigned. Shr, - /// Like `Shl`, but is UB if the RHS >= LHS::BITS + /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0 ShrUnchecked, /// The `==` operator (equality) Eq, diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 931ee7fd05ef7..0fc12586948d8 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -40,7 +40,7 @@ impl<'tcx> PlaceTy<'tcx> { None => adt_def.non_enum_variant(), Some(variant_index) => { assert!(adt_def.is_enum()); - &adt_def.variant(variant_index) + adt_def.variant(variant_index) } }; let field_def = &variant_def.fields[f]; @@ -95,9 +95,7 @@ impl<'tcx> PlaceTy<'tcx> { ProjectionElem::Subslice { from, to, from_end } => { PlaceTy::from_ty(match self.ty.kind() { ty::Slice(..) => self.ty, - ty::Array(inner, _) if !from_end => { - Ty::new_array(tcx, *inner, (to - from) as u64) - } + ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from), ty::Array(inner, size) if from_end => { let size = size.eval_target_usize(tcx, param_env); let len = size - from - to; @@ -143,7 +141,7 @@ impl<'tcx> Place<'tcx> { where D: HasLocalDecls<'tcx>, { - Place::ty_from(self.local, &self.projection, local_decls, tcx) + Place::ty_from(self.local, self.projection, local_decls, tcx) } } @@ -152,7 +150,7 @@ impl<'tcx> PlaceRef<'tcx> { where D: HasLocalDecls<'tcx>, { - Place::ty_from(self.local, &self.projection, local_decls, tcx) + Place::ty_from(self.local, self.projection, local_decls, tcx) } } @@ -278,7 +276,7 @@ impl BorrowKind { // We have no type corresponding to a shallow borrow, so use // `&` as an approximation. - BorrowKind::Shallow => hir::Mutability::Not, + BorrowKind::Fake => hir::Mutability::Not, } } } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 9dfbe1733cc51..9a6ac6ff57a4e 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -28,7 +28,9 @@ impl SwitchTargets { /// Inverse of `SwitchTargets::static_if`. pub fn as_static_if(&self) -> Option<(u128, BasicBlock, BasicBlock)> { - if let &[value] = &self.values[..] && let &[then, else_] = &self.targets[..] { + if let &[value] = &self.values[..] + && let &[then, else_] = &self.targets[..] + { Some((value, then, else_)) } else { None diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0f0ca3a1420e9..d47cfd5712f8b 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -649,8 +649,8 @@ macro_rules! make_mir_visitor { BorrowKind::Shared => PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow ), - BorrowKind::Shallow => PlaceContext::NonMutatingUse( - NonMutatingUseContext::ShallowBorrow + BorrowKind::Fake => PlaceContext::NonMutatingUse( + NonMutatingUseContext::FakeBorrow ), BorrowKind::Mut { .. } => PlaceContext::MutatingUse(MutatingUseContext::Borrow), @@ -1261,8 +1261,8 @@ pub enum NonMutatingUseContext { Move, /// Shared borrow. SharedBorrow, - /// Shallow borrow. - ShallowBorrow, + /// A fake borrow. + FakeBorrow, /// AddressOf for *const pointer. AddressOf, /// PlaceMention statement. @@ -1341,7 +1341,7 @@ impl PlaceContext { matches!( self, PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::ShallowBorrow + NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow ) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) ) } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index e20e9d9312c1b..b9200f1abf161 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -2,7 +2,8 @@ use crate::mir; use crate::query::CyclePlaceholder; use crate::traits; use crate::ty::{self, Ty}; -use std::mem::{size_of, transmute_copy, MaybeUninit}; +use std::intrinsics::transmute_unchecked; +use std::mem::{size_of, MaybeUninit}; #[derive(Copy, Clone)] pub struct Erased { @@ -29,8 +30,15 @@ pub fn erase(src: T) -> Erase { }; Erased::<::Result> { + // `transmute_unchecked` is needed here because it does not have `transmute`'s size check + // (and thus allows to transmute between `T` and `MaybeUninit`) (we do the size + // check ourselves in the `const` block above). + // + // `transmute_copy` is also commonly used for this (and it would work here since + // `EraseType: Copy`), but `transmute_unchecked` better explains the intent. + // // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes. - data: unsafe { transmute_copy(&src) }, + data: unsafe { transmute_unchecked::>(src) }, } } @@ -38,22 +46,24 @@ pub fn erase(src: T) -> Erase { #[inline(always)] pub fn restore(value: Erase) -> T { let value: Erased<::Result> = value; + // See comment in `erase` for why we use `transmute_unchecked`. + // // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of // the right size. - unsafe { transmute_copy(&value.data) } + unsafe { transmute_unchecked::, T>(value.data) } } impl EraseType for &'_ T { - type Result = [u8; size_of::<*const ()>()]; + type Result = [u8; size_of::<&'static ()>()]; } impl EraseType for &'_ [T] { - type Result = [u8; size_of::<*const [()]>()]; + type Result = [u8; size_of::<&'static [()]>()]; } impl EraseType for &'_ ty::List { - type Result = [u8; size_of::<*const ()>()]; + type Result = [u8; size_of::<&'static ty::List<()>>()]; } impl EraseType for &'_ rustc_index::IndexSlice { @@ -254,6 +264,7 @@ trivial! { rustc_middle::middle::stability::DeprecationEntry, rustc_middle::mir::ConstQualifs, rustc_middle::mir::interpret::AllocId, + rustc_middle::mir::interpret::CtfeProvenance, rustc_middle::mir::interpret::ErrorHandled, rustc_middle::mir::interpret::LitToConstError, rustc_middle::thir::ExprId, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index f9ec368361c59..03f3ceb8d1733 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -61,7 +61,6 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::sync::WorkerLocal; use rustc_data_structures::unord::UnordSet; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -109,10 +108,12 @@ pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue // Queries marked with `fatal_cycle` do not need the latter implementation, // as they will raise an fatal error on query cycles instead. rustc_queries! { - query trigger_delay_span_bug(key: DefId) -> () { - desc { "triggering a delay span bug" } + /// This exists purely for testing the interactions between span_delayed_bug and incremental. + query trigger_span_delayed_bug(key: DefId) -> () { + desc { "triggering a span delayed bug for testing incremental" } } + /// Collects the list of all tools registered using `#![register_tool]`. query registered_tools(_: ()) -> &'tcx ty::RegisteredTools { arena_cache desc { "compute registered tools for crate" } @@ -286,6 +287,7 @@ rustc_queries! { } } + /// The root query triggering all analysis passes like typeck or borrowck. query analysis(key: ()) -> Result<(), ErrorGuaranteed> { eval_always desc { "running analysis passes on this crate" } @@ -564,7 +566,7 @@ rustc_queries! { separate_provide_extern } - query check_coroutine_obligations(key: LocalDefId) { + query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) } } @@ -1149,7 +1151,7 @@ rustc_queries! { cache_on_disk_if { true } } - query opt_def_kind(def_id: DefId) -> Option { + query def_kind(def_id: DefId) -> DefKind { desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) } cache_on_disk_if { def_id.is_local() } separate_provide_extern @@ -1732,13 +1734,10 @@ rustc_queries! { desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) } } - query lib_features(_: ()) -> &'tcx LibFeatures { - arena_cache - desc { "calculating the lib features map" } - } - query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option)] { + query lib_features(_: CrateNum) -> &'tcx LibFeatures { desc { "calculating the lib features defined in a crate" } separate_provide_extern + arena_cache } query stability_implications(_: CrateNum) -> &'tcx FxHashMap { arena_cache @@ -1781,10 +1780,17 @@ rustc_queries! { desc { "calculating the missing lang items in a crate" } separate_provide_extern } + + /// The visible parent map is a map from every item to a visible parent. + /// It prefers the shortest visible path to an item. + /// Used for diagnostics, for example path trimming. + /// The parents are modules, enums or traits. query visible_parent_map(_: ()) -> &'tcx DefIdMap { arena_cache desc { "calculating the visible parent map" } } + /// Collects the "trimmed", shortest accessible paths to all items for diagnostics. + /// See the [provider docs](`rustc_middle::ty::print::trimmed_def_paths`) for more info. query trimmed_def_paths(_: ()) -> &'tcx FxHashMap { arena_cache desc { "calculating trimmed def paths" } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 280f5d0a84caa..f37cfe8b0a111 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -25,7 +25,6 @@ use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span}; use rustc_span::{CachingSourceMapView, Symbol}; use std::collections::hash_map::Entry; -use std::io; use std::mem; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; @@ -246,7 +245,7 @@ impl<'sess> OnDiskCache<'sess> { let index = SourceFileIndex(index as u32); let file_ptr: *const SourceFile = &**file as *const _; file_to_file_index.insert(file_ptr, index); - let source_file_id = EncodedSourceFileId::new(tcx, &file); + let source_file_id = EncodedSourceFileId::new(tcx, file); file_index_to_stable_id.insert(index, source_file_id); } @@ -482,13 +481,8 @@ pub struct CacheDecoder<'a, 'tcx> { impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { #[inline] fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc { - let CacheDecoder { - tcx, - ref file_index_to_file, - ref file_index_to_stable_id, - ref source_map, - .. - } = *self; + let CacheDecoder { tcx, file_index_to_file, file_index_to_stable_id, source_map, .. } = + *self; file_index_to_file .borrow_mut() @@ -867,7 +861,7 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> { } #[inline] - fn finish(self) -> Result { + fn finish(mut self) -> FileEncodeResult { self.encoder.finish() } } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index f4a8ada8f685e..0d1f3c1f8b522 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -11,7 +11,7 @@ use field_offset::FieldOffset; use measureme::StringId; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::AtomicU64; -use rustc_hir::def::DefKind; +use rustc_data_structures::sync::WorkerLocal; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::OwnerId; use rustc_query_system::dep_graph::DepNodeIndex; @@ -71,7 +71,7 @@ pub struct QuerySystemFns<'tcx> { pub struct QuerySystem<'tcx> { pub states: QueryStates<'tcx>, - pub arenas: QueryArenas<'tcx>, + pub arenas: WorkerLocal>, pub caches: QueryCaches<'tcx>, pub dynamic_queries: DynamicQueries<'tcx>, @@ -370,7 +370,7 @@ macro_rules! define_callbacks { pub struct QueryArenas<'tcx> { $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*] - (WorkerLocal::Target>>) + (TypedArena<<$V as Deref>::Target>) () ),)* } @@ -379,7 +379,7 @@ macro_rules! define_callbacks { fn default() -> Self { Self { $($name: query_if_arena!([$($modifiers)*] - (WorkerLocal::new(|_| Default::default())) + (Default::default()) () ),)* } @@ -551,7 +551,7 @@ macro_rules! define_feedable { // We have an inconsistency. This can happen if one of the two // results is tainted by errors. In this case, delay a bug to // ensure compilation is doomed, and keep the `old` value. - tcx.sess.delay_span_bug(DUMMY_SP, format!( + tcx.sess.span_delayed_bug(DUMMY_SP, format!( "Trying to feed an already recorded value for query {} key={key:?}:\n\ old value: {old:?}\nnew value: {value:?}", stringify!($name), @@ -667,21 +667,5 @@ mod sealed { pub use sealed::IntoQueryParam; -impl<'tcx> TyCtxt<'tcx> { - pub fn def_kind(self, def_id: impl IntoQueryParam) -> DefKind { - let def_id = def_id.into_query_param(); - self.opt_def_kind(def_id) - .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id)) - } -} - -impl<'tcx> TyCtxtAt<'tcx> { - pub fn def_kind(self, def_id: impl IntoQueryParam) -> DefKind { - let def_id = def_id.into_query_param(); - self.opt_def_kind(def_id) - .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id)) - } -} - #[derive(Copy, Clone, Debug, HashStable)] pub struct CyclePlaceholder(pub ErrorGuaranteed); diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 3086082fe8d57..c48428c713c44 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -635,7 +635,12 @@ impl<'tcx> Pat<'tcx> { use PatKind::*; match &self.kind { - Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } | Error(_) => {} + Wild + | Never + | Range(..) + | Binding { subpattern: None, .. } + | Constant { .. } + | Error(_) => {} AscribeUserType { subpattern, .. } | Binding { subpattern: Some(subpattern), .. } | Deref { subpattern } @@ -655,7 +660,9 @@ impl<'tcx> Pat<'tcx> { pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> { let mut error = None; self.walk(|pat| { - if let PatKind::Error(e) = pat.kind && error.is_none() { + if let PatKind::Error(e) = pat.kind + && error.is_none() + { error = Some(e); } error.is_none() @@ -807,6 +814,9 @@ pub enum PatKind<'tcx> { pats: Box<[Box>]>, }, + /// A never pattern `!`. + Never, + /// An error has been encountered during lowering. We probably shouldn't report more lints /// related to this pattern. Error(ErrorGuaranteed), @@ -1067,6 +1077,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { match self.kind { PatKind::Wild => write!(f, "_"), + PatKind::Never => write!(f, "!"), PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"), PatKind::Binding { mutability, name, mode, ref subpattern, .. } => { let is_mut = match mode { diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index d03d92c3a4b83..4943c11848b8a 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -66,8 +66,9 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp Use { source } => visitor.visit_expr(&visitor.thir()[source]), NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), - Let { expr, .. } => { + Let { expr, ref pat } => { visitor.visit_expr(&visitor.thir()[expr]); + visitor.visit_pat(pat); } Loop { body } => visitor.visit_expr(&visitor.thir()[body]), Match { scrutinee, ref arms, .. } => { @@ -225,8 +226,8 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' ty: _, is_primary: _, name: _, - } => visitor.visit_pat(&subpattern), - Binding { .. } | Wild | Error(_) => {} + } => visitor.visit_pat(subpattern), + Binding { .. } | Wild | Never | Error(_) => {} Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => { for subpattern in subpatterns { visitor.visit_pat(&subpattern.pattern); @@ -248,7 +249,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' } Or { pats } => { for pat in pats.iter() { - visitor.visit_pat(&pat); + visitor.visit_pat(pat); } } }; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 9e2ff3820af64..5d0187a859833 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -250,9 +250,6 @@ pub enum ObligationCauseCode<'tcx> { /// A tuple is WF only if its middle elements are `Sized`. TupleElem, - /// This is the trait reference from the given projection. - ProjectionWf(ty::AliasTy<'tcx>), - /// Must satisfy all of the where-clause predicates of the /// given item. ItemObligation(DefId), @@ -305,9 +302,14 @@ pub enum ObligationCauseCode<'tcx> { SizedCoroutineInterior(LocalDefId), /// `[expr; N]` requires `type_of(expr): Copy`. RepeatElementCopy { - /// If element is a `const fn` we display a help message suggesting to move the - /// function call to a new `const` item while saying that `T` doesn't implement `Copy`. - is_const_fn: bool, + /// If element is a `const fn` or const ctor we display a help message suggesting + /// to move it to a new `const` item while saying that `T` doesn't implement `Copy`. + is_constable: IsConstable, + elt_type: Ty<'tcx>, + elt_span: Span, + /// Span of the statement/item in which the repeat expression occurs. We can use this to + /// place a `const` declaration before it + elt_stmt_span: Span, }, /// Types of fields (other than the last, except for packed structs) in a struct must be sized. @@ -338,7 +340,8 @@ pub enum ObligationCauseCode<'tcx> { parent_code: InternedObligationCauseCode<'tcx>, }, - /// Error derived when matching traits/impls; see ObligationCause for more details + /// Error derived when checking an impl item is compatible with + /// its corresponding trait item's definition CompareImplItemObligation { impl_item_def_id: LocalDefId, trait_item_def_id: DefId, @@ -367,9 +370,6 @@ pub enum ObligationCauseCode<'tcx> { origin_expr: bool, }, - /// Constants in patterns must have `Structural` type. - ConstPatternStructural, - /// Computing common supertype in an if expression IfExpression(Box>), @@ -402,9 +402,6 @@ pub enum ObligationCauseCode<'tcx> { /// `return` with an expression ReturnValue(hir::HirId), - /// Return type of this function - ReturnType, - /// Opaque return type of this function OpaqueReturnType(Option<(Ty<'tcx>, Span)>), @@ -414,10 +411,7 @@ pub enum ObligationCauseCode<'tcx> { /// #[feature(trivial_bounds)] is not enabled TrivialBound, - /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` - OpaqueType, - - AwaitableExpr(Option), + AwaitableExpr(hir::HirId), ForLoopIterator, @@ -455,6 +449,21 @@ pub enum ObligationCauseCode<'tcx> { TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId), } +/// Whether a value can be extracted into a const. +/// Used for diagnostics around array repeat expressions. +#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum IsConstable { + No, + /// Call to a const fn + Fn, + /// Use of a const ctor + Ctor, +} + +crate::TrivialTypeTraversalAndLiftImpls! { + IsConstable, +} + /// The 'location' at which we try to perform HIR-based wf checking. /// This information is used to obtain an `hir::Ty`, which /// we can walk in order to obtain precise spans for any @@ -666,7 +675,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(n) | ImplSource::Builtin(_, n) => &n, + ImplSource::Param(n) | ImplSource::Builtin(_, n) => n, } } @@ -823,50 +832,31 @@ impl ObjectSafetyViolation { } } - pub fn solution(&self, err: &mut Diagnostic) { + pub fn solution(&self) -> ObjectSafetyViolationSolution { match self { ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) - | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {} + | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => { + ObjectSafetyViolationSolution::None + } ObjectSafetyViolation::Method( name, MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))), _, - ) => { - err.span_suggestion( - add_self_sugg.1, - format!( - "consider turning `{name}` into a method by giving it a `&self` argument" - ), - add_self_sugg.0.to_string(), - Applicability::MaybeIncorrect, - ); - err.span_suggestion( - make_sized_sugg.1, - format!( - "alternatively, consider constraining `{name}` so it does not apply to \ - trait objects" - ), - make_sized_sugg.0.to_string(), - Applicability::MaybeIncorrect, - ); - } + ) => ObjectSafetyViolationSolution::AddSelfOrMakeSized { + name: *name, + add_self_sugg: add_self_sugg.clone(), + make_sized_sugg: make_sized_sugg.clone(), + }, ObjectSafetyViolation::Method( name, MethodViolationCode::UndispatchableReceiver(Some(span)), _, - ) => { - err.span_suggestion( - *span, - format!("consider changing method `{name}`'s `self` parameter to be `&self`"), - "&Self", - Applicability::MachineApplicable, - ); - } + ) => ObjectSafetyViolationSolution::ChangeToRefSelf(*name, *span), ObjectSafetyViolation::AssocConst(name, _) | ObjectSafetyViolation::GAT(name, _) | ObjectSafetyViolation::Method(name, ..) => { - err.help(format!("consider moving `{name}` to another trait")); + ObjectSafetyViolationSolution::MoveToAnotherTrait(*name) } } } @@ -890,6 +880,60 @@ impl ObjectSafetyViolation { } } +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum ObjectSafetyViolationSolution { + None, + AddSelfOrMakeSized { + name: Symbol, + add_self_sugg: (String, Span), + make_sized_sugg: (String, Span), + }, + ChangeToRefSelf(Symbol, Span), + MoveToAnotherTrait(Symbol), +} + +impl ObjectSafetyViolationSolution { + pub fn add_to(self, err: &mut Diagnostic) { + match self { + ObjectSafetyViolationSolution::None => {} + ObjectSafetyViolationSolution::AddSelfOrMakeSized { + name, + add_self_sugg, + make_sized_sugg, + } => { + err.span_suggestion( + add_self_sugg.1, + format!( + "consider turning `{name}` into a method by giving it a `&self` argument" + ), + add_self_sugg.0, + Applicability::MaybeIncorrect, + ); + err.span_suggestion( + make_sized_sugg.1, + format!( + "alternatively, consider constraining `{name}` so it does not apply to \ + trait objects" + ), + make_sized_sugg.0, + Applicability::MaybeIncorrect, + ); + } + ObjectSafetyViolationSolution::ChangeToRefSelf(name, span) => { + err.span_suggestion( + span, + format!("consider changing method `{name}`'s `self` parameter to be `&self`"), + "&Self", + Applicability::MachineApplicable, + ); + } + ObjectSafetyViolationSolution::MoveToAnotherTrait(name) => { + err.help(format!("consider moving `{name}` to another trait")); + } + } + } +} + /// Reasons a method might not be object-safe. #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum MethodViolationCode { @@ -936,13 +980,26 @@ pub enum CodegenObligationError { FulfillmentError, } +/// Defines the treatment of opaque types in a given inference context. +/// +/// This affects both what opaques are allowed to be defined, but also whether +/// opaques are replaced with inference vars eagerly in the old solver (e.g. +/// in projection, and in the signature during function type-checking). #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum DefiningAnchor { - /// `DefId` of the item. + /// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly + /// replace opaque types in `replace_opaque_types_with_inference_vars`. Bind(LocalDefId), - /// When opaque types are not resolved, we `Bubble` up, meaning - /// return the opaque/hidden type pair from query, for caller of query to handle it. + /// In contexts where we don't currently know what opaques are allowed to be + /// defined, such as (old solver) canonical queries, we will simply allow + /// opaques to be defined, but "bubble" them up in the canonical response or + /// otherwise treat them to be handled later. + /// + /// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`, + /// which may affect what predicates pass and fail in the old trait solver. Bubble, - /// Used to catch type mismatch errors when handling opaque types. + /// Do not allow any opaques to be defined. This is used to catch type mismatch + /// errors when handling opaque types, and also should be used when we would + /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode). Error, } diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 3cceb8b2c595f..34c56eb0d7b1e 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -108,17 +108,6 @@ impl<'tcx> DropckOutlivesResult<'tcx> { tcx.sess.emit_err(DropCheckOverflow { span, ty, overflow_ty: *overflow_ty }); } } - - pub fn into_kinds_reporting_overflows( - self, - tcx: TyCtxt<'tcx>, - span: Span, - ty: Ty<'tcx>, - ) -> Vec> { - self.report_overflows(tcx, span, ty); - let DropckOutlivesResult { kinds, overflows: _ } = self; - kinds - } } /// A set of constraints that need to be satisfied in order for diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index f33421bbaa6c1..96ed1a4d0be1f 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -180,8 +180,8 @@ pub enum SelectionCandidate<'tcx> { /// /// The evaluation results are ordered: /// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions` -/// implies `EvaluatedToAmbig` implies `EvaluatedToUnknown` -/// - `EvaluatedToErr` implies `EvaluatedToRecur` +/// implies `EvaluatedToAmbig` implies `EvaluatedToAmbigStackDependent` +/// - `EvaluatedToErr` implies `EvaluatedToErrStackDependent` /// - the "union" of evaluation results is equal to their maximum - /// all the "potential success" candidates can potentially succeed, /// so they are noops when unioned with a definite error, and within @@ -199,7 +199,7 @@ pub enum EvaluationResult { /// Evaluation is known to be ambiguous -- it *might* hold for some /// assignment of inference variables, but it might not. /// - /// While this has the same meaning as `EvaluatedToUnknown` -- we can't + /// While this has the same meaning as `EvaluatedToAmbigStackDependent` -- we can't /// know whether this obligation holds or not -- it is the result we /// would get with an empty stack, and therefore is cacheable. EvaluatedToAmbig, @@ -207,8 +207,8 @@ pub enum EvaluationResult { /// variables. We are somewhat imprecise there, so we don't actually /// know the real result. /// - /// This can't be trivially cached for the same reason as `EvaluatedToRecur`. - EvaluatedToUnknown, + /// This can't be trivially cached for the same reason as `EvaluatedToErrStackDependent`. + EvaluatedToAmbigStackDependent, /// Evaluation failed because we encountered an obligation we are already /// trying to prove on this branch. /// @@ -247,12 +247,12 @@ pub enum EvaluationResult { /// does not hold, because of the bound (which can indeed be satisfied /// by `SomeUnsizedType` from another crate). // - // FIXME: when an `EvaluatedToRecur` goes past its parent root, we + // FIXME: when an `EvaluatedToErrStackDependent` goes past its parent root, we // ought to convert it to an `EvaluatedToErr`, because we know // there definitely isn't a proof tree for that obligation. Not // doing so is still sound -- there isn't any proof tree, so the // branch still can't be a part of a minimal one -- but does not re-enable caching. - EvaluatedToRecur, + EvaluatedToErrStackDependent, /// Evaluation failed. EvaluatedToErr, } @@ -276,15 +276,15 @@ impl EvaluationResult { | EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig - | EvaluatedToUnknown => true, + | EvaluatedToAmbigStackDependent => true, - EvaluatedToErr | EvaluatedToRecur => false, + EvaluatedToErr | EvaluatedToErrStackDependent => false, } } pub fn is_stack_dependent(self) -> bool { match self { - EvaluatedToUnknown | EvaluatedToRecur => true, + EvaluatedToAmbigStackDependent | EvaluatedToErrStackDependent => true, EvaluatedToOkModuloOpaqueTypes | EvaluatedToOk diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index a5916c4ab8552..7883cd338befd 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -122,6 +122,8 @@ pub enum ProbeStep<'tcx> { /// used whenever there are multiple candidates to prove the /// current goalby . NestedProbe(Probe<'tcx>), + CommitIfOkStart, + CommitIfOkSuccess, } /// What kind of probe we're in. In case the probe represents a candidate, or @@ -142,6 +144,9 @@ pub enum ProbeKind<'tcx> { /// Used in the probe that wraps normalizing the non-self type for the unsize /// trait, which is also structurally matched on. UnsizeAssembly, + /// A call to `EvalCtxt::commit_if_ok` which failed, causing the work + /// to be discarded. + CommitIfOk, /// During upcasting from some source object to target object type, used to /// do a probe to find out what projection type(s) may be used to prove that /// the source type upholds all of the target type's object bounds. diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index 4b73d8e41a150..ab9e0283918d9 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -109,6 +109,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { ProbeKind::UpcastProjectionCompatibility => { writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") } + ProbeKind::CommitIfOk => { + writeln!(self.f, "COMMIT_IF_OK:") + } ProbeKind::MiscCandidate { name, result } => { writeln!(self.f, "CANDIDATE {name}: {result:?}") } @@ -123,6 +126,8 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { ProbeStep::AddGoal(goal) => writeln!(this.f, "ADDED GOAL: {goal:?}")?, ProbeStep::EvaluateGoals(eval) => this.format_added_goals_evaluation(eval)?, ProbeStep::NestedProbe(probe) => this.format_probe(probe)?, + ProbeStep::CommitIfOkStart => writeln!(this.f, "COMMIT_IF_OK START")?, + ProbeStep::CommitIfOkSuccess => writeln!(this.f, "COMMIT_IF_OK SUCCESS")?, } } Ok(()) diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index e48b46d12c48a..6db427064d16c 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -72,7 +72,7 @@ impl OverlapMode { .as_local() .into_iter() .flat_map(|local_def_id| { - tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(local_def_id)) + tcx.hir().attrs(tcx.local_def_id_to_hir_id(local_def_id)) }) .find(|attr| attr.has_name(sym::rustc_strict_coherence)) .map(|attr| attr.span); diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index f50969dd967f8..1d9a25628b047 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -99,7 +99,7 @@ pub struct AdtDefData { impl PartialOrd for AdtDefData { fn partial_cmp(&self, other: &AdtDefData) -> Option { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } @@ -375,7 +375,7 @@ impl<'tcx> AdtDef<'tcx> { /// Asserts this is a struct or union and returns its unique variant. pub fn non_enum_variant(self) -> &'tcx VariantDef { assert!(self.is_struct() || self.is_union()); - &self.variant(FIRST_VARIANT) + self.variant(FIRST_VARIANT) } #[inline] @@ -481,7 +481,7 @@ impl<'tcx> AdtDef<'tcx> { ErrorHandled::Reported(..) => "enum discriminant evaluation failed", ErrorHandled::TooGeneric(..) => "enum discriminant depends on generics", }; - tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg); + tcx.sess.span_delayed_bug(tcx.def_span(expr_did), msg); None } } diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 74bdd07a1c946..eaf5da130dd9c 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -247,6 +247,13 @@ impl<'tcx> CapturedPlace<'tcx> { .span } } + + pub fn is_by_ref(&self) -> bool { + match self.info.capture_kind { + ty::UpvarCapture::ByValue => false, + ty::UpvarCapture::ByRef(..) => true, + } + } } #[derive(Copy, Clone, Debug, HashStable)] @@ -262,7 +269,7 @@ fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo let user_provided_sig = typeck_results.user_provided_sigs[&def]; let captures = typeck_results.closure_min_captures_flattened(def); let captures = tcx.arena.alloc_from_iter(captures); - let hir_id = tcx.hir().local_def_id_to_hir_id(def); + let hir_id = tcx.local_def_id_to_hir_id(def); let kind_origin = typeck_results.closure_kind_origins().get(hir_id); ClosureTypeInfo { user_provided_sig, captures, kind_origin } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 8b67e39667b8d..69ae05ca820a3 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -8,6 +8,7 @@ use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; +use crate::mir::interpret::CtfeProvenance; use crate::mir::{ self, interpret::{AllocId, ConstAllocation}, @@ -164,6 +165,13 @@ impl<'tcx, E: TyEncoder>> Encodable for AllocId { } } +impl<'tcx, E: TyEncoder>> Encodable for CtfeProvenance { + fn encode(&self, e: &mut E) { + self.alloc_id().encode(e); + self.immutable().encode(e); + } +} + impl<'tcx, E: TyEncoder>> Encodable for ty::ParamEnv<'tcx> { fn encode(&self, e: &mut E) { self.caller_bounds().encode(e); @@ -295,9 +303,18 @@ impl<'tcx, D: TyDecoder>> Decodable for AllocId { } } +impl<'tcx, D: TyDecoder>> Decodable for CtfeProvenance { + fn decode(decoder: &mut D) -> Self { + let alloc_id: AllocId = Decodable::decode(decoder); + let prov = CtfeProvenance::from(alloc_id); + let immutable: bool = Decodable::decode(decoder); + if immutable { prov.as_immutable() } else { prov } + } +} + impl<'tcx, D: TyDecoder>> Decodable for ty::SymbolName<'tcx> { fn decode(decoder: &mut D) -> Self { - ty::SymbolName::new(decoder.interner(), &decoder.read_str()) + ty::SymbolName::new(decoder.interner(), decoder.read_str()) } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index cfacccd26799e..e48840fac2059 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,5 +1,5 @@ use crate::middle::resolve_bound_vars as rbv; -use crate::mir::interpret::{AllocId, ErrorHandled, LitToConstInput, Scalar}; +use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar}; use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; @@ -7,6 +7,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; +use rustc_type_ir::{TypeFlags, WithCachedTypeInfo}; mod int; mod kind; @@ -23,7 +24,7 @@ use super::sty::ConstKind; /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>); +pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo>>); /// Typed constant value. #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)] @@ -46,6 +47,16 @@ impl<'tcx> Const<'tcx> { self.0.kind.clone() } + #[inline] + pub fn flags(self) -> TypeFlags { + self.0.flags + } + + #[inline] + pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex { + self.0.outer_exclusive_binder + } + #[inline] pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { tcx.mk_ct_from_kind(kind, ty) @@ -84,7 +95,7 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn new_placeholder( tcx: TyCtxt<'tcx>, - placeholder: ty::PlaceholderConst<'tcx>, + placeholder: ty::PlaceholderConst, ty: Ty<'tcx>, ) -> Const<'tcx> { Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty) @@ -133,7 +144,7 @@ impl<'tcx> Const<'tcx> { span: S, msg: &'static str, ) -> Const<'tcx> { - let reported = tcx.sess.delay_span_bug(span, msg); + let reported = tcx.sess.span_delayed_bug(span, msg); Const::new_error(tcx, reported, ty) } @@ -183,11 +194,9 @@ impl<'tcx> Const<'tcx> { }; let lit_input = match expr.kind { - hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), - hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind { - hir::ExprKind::Lit(ref lit) => { - Some(LitToConstInput { lit: &lit.node, ty, neg: true }) - } + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }), _ => None, }, _ => None, @@ -199,7 +208,7 @@ impl<'tcx> Const<'tcx> { match tcx.at(expr.span).lit_to_const(lit_input) { Ok(c) => return Some(c), Err(e) => { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( expr.span, format!("Const::from_anon_const: couldn't lit_to_const {e:?}"), ); @@ -207,6 +216,10 @@ impl<'tcx> Const<'tcx> { } } + // FIXME(const_generics): We currently have to special case parameters because `min_const_generics` + // does not provide the parents generics to anonymous constants. We still allow generic const + // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to + // ever try to substitute the generic parameters in their bodies. match expr.kind { hir::ExprKind::Path(hir::QPath::Resolved( _, @@ -291,8 +304,16 @@ impl<'tcx> Const<'tcx> { let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - let c = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?; - Ok(c.expect("`ty::Const::eval` called on a non-valtree-compatible type")) + let Some(c) = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)? + else { + // This can happen when we run on ill-typed code. + let e = tcx.sess.span_delayed_bug( + span.unwrap_or(DUMMY_SP), + "`ty::Const::eval` called on a non-valtree-compatible type", + ); + return Err(e.into()); + }; + Ok(c) } ConstKind::Value(val) => Ok(val), ConstKind::Error(g) => Err(g.into()), @@ -392,7 +413,7 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn try_to_scalar(self) -> Option> { + pub fn try_to_scalar(self) -> Option { self.try_to_valtree()?.try_to_scalar() } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 4af841fcf9a5f..16e7b16a0bf8c 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -3,7 +3,6 @@ use crate::mir; use crate::ty::abstract_const::CastKind; use crate::ty::GenericArgsRef; use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; @@ -77,28 +76,3 @@ static_assert_size!(Expr<'_>, 24); #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(super::ConstKind<'_>, 32); - -/// An inference variable for a const, for use in const generics. -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] -pub enum InferConst { - /// Infer the value of the const. - Var(ty::ConstVid), - /// Infer the value of the effect. - /// - /// For why this is separate from the `Var` variant above, see the - /// documentation on `EffectVid`. - EffectVar(ty::EffectVid), - /// A fresh const variable. See `infer::freshen` for more details. - Fresh(u32), -} - -impl HashStable for InferConst { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - match self { - InferConst::Var(_) | InferConst::EffectVar(_) => { - panic!("const variables should not be hashed: {self:?}") - } - InferConst::Fresh(i) => i.hash_stable(hcx, hasher), - } - } -} diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index fb7bf78bafe31..ffa0e89c47328 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -1,5 +1,5 @@ use super::ScalarInt; -use crate::mir::interpret::{AllocId, Scalar}; +use crate::mir::interpret::Scalar; use crate::ty::{self, Ty, TyCtxt}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; @@ -67,7 +67,7 @@ impl<'tcx> ValTree<'tcx> { Self::Leaf(i) } - pub fn try_to_scalar(self) -> Option> { + pub fn try_to_scalar(self) -> Option { self.try_to_scalar_int().map(Scalar::Int) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 68812bba42fdd..3012434ad3fb8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -26,9 +26,9 @@ use crate::traits::solve::{ }; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind, - ImplPolarity, InferTy, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, - Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, - TyVid, TypeAndMut, Visibility, + ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, + PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, + TypeAndMut, Visibility, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use rustc_ast::{self as ast, attr}; @@ -39,7 +39,7 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{FreezeReadGuard, Lock, WorkerLocal}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{ DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan, @@ -69,7 +69,6 @@ use rustc_type_ir::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; -use std::any::Any; use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; @@ -96,7 +95,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ParamTy = ParamTy; type BoundTy = ty::BoundTy; type PlaceholderTy = ty::PlaceholderType; - type InferTy = InferTy; type ErrorGuaranteed = ErrorGuaranteed; type BoundExistentialPredicates = &'tcx List>; @@ -104,18 +102,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type AllocId = crate::mir::interpret::AllocId; type Const = ty::Const<'tcx>; - type InferConst = ty::InferConst; type AliasConst = ty::UnevaluatedConst<'tcx>; - type PlaceholderConst = ty::PlaceholderConst<'tcx>; + type PlaceholderConst = ty::PlaceholderConst; type ParamConst = ty::ParamConst; type BoundConst = ty::BoundVar; type ValueConst = ty::ValTree<'tcx>; type ExprConst = ty::Expr<'tcx>; type Region = Region<'tcx>; - type EarlyBoundRegion = ty::EarlyBoundRegion; + type EarlyParamRegion = ty::EarlyParamRegion; type BoundRegion = ty::BoundRegion; - type FreeRegion = ty::FreeRegion; + type LateParamRegion = ty::LateParamRegion; type InferRegion = ty::RegionVid; type PlaceholderRegion = ty::PlaceholderRegion; @@ -124,6 +121,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>; type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>; type ProjectionPredicate = ty::ProjectionPredicate<'tcx>; + type NormalizesTo = ty::NormalizesTo<'tcx>; type SubtypePredicate = ty::SubtypePredicate<'tcx>; type CoercePredicate = ty::CoercePredicate<'tcx>; type ClosureKind = ty::ClosureKind; @@ -154,7 +152,7 @@ pub struct CtxtInterners<'tcx> { clauses: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, - const_: InternedSet<'tcx, ConstData<'tcx>>, + const_: InternedSet<'tcx, WithCachedTypeInfo>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, LayoutS>, @@ -215,6 +213,32 @@ impl<'tcx> CtxtInterners<'tcx> { )) } + /// Interns a const. (Use `mk_*` functions instead, where possible.) + #[allow(rustc::usage_of_ty_tykind)] + #[inline(never)] + fn intern_const( + &self, + data: ty::ConstData<'tcx>, + sess: &Session, + untracked: &Untracked, + ) -> Const<'tcx> { + Const(Interned::new_unchecked( + self.const_ + .intern(data, |data: ConstData<'_>| { + let flags = super::flags::FlagComputation::for_const(&data.kind, data.ty); + let stable_hash = self.stable_hash(&flags, sess, untracked, &data); + + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: data, + stable_hash, + flags: flags.flags, + outer_exclusive_binder: flags.outer_exclusive_binder, + })) + }) + .0, + )) + } + fn stable_hash<'a, T: HashStable>>( &self, flags: &ty::flags::FlagComputation, @@ -327,7 +351,7 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec>, /// Pre-interned values of the form: - /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` + /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` /// for small values of `i` and `v`. pub re_late_bounds: Vec>>, } @@ -402,7 +426,7 @@ impl<'tcx> CommonLifetimes<'tcx> { .map(|i| { (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V) .map(|v| { - mk(ty::ReLateBound( + mk(ty::ReBound( ty::DebruijnIndex::from(i), ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon }, )) @@ -421,11 +445,17 @@ impl<'tcx> CommonLifetimes<'tcx> { } impl<'tcx> CommonConsts<'tcx> { - fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> { + fn new( + interners: &CtxtInterners<'tcx>, + types: &CommonTypes<'tcx>, + sess: &Session, + untracked: &Untracked, + ) -> CommonConsts<'tcx> { let mk_const = |c| { - Const(Interned::new_unchecked( - interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0, - )) + interners.intern_const( + c, sess, // This is only used to create a stable hashing context. + untracked, + ) }; CommonConsts { @@ -445,14 +475,14 @@ impl<'tcx> CommonConsts<'tcx> { } } -/// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime -/// conflict. +/// This struct contains information regarding a free parameter region, +/// either a `ReEarlyParam` or `ReLateParam`. #[derive(Debug)] pub struct FreeRegionInfo { - /// `LocalDefId` corresponding to FreeRegion + /// `LocalDefId` of the free region. pub def_id: LocalDefId, - /// the bound region corresponding to FreeRegion - pub boundregion: ty::BoundRegionKind, + /// the bound region corresponding to free region. + pub bound_region: ty::BoundRegionKind, /// checks if bound region is in Impl Item pub is_impl_item: bool, } @@ -472,6 +502,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> { TyCtxtFeed { tcx: self, key: LOCAL_CRATE } } + pub fn feed_local_def_id(self, key: LocalDefId) -> TyCtxtFeed<'tcx, LocalDefId> { + TyCtxtFeed { tcx: self, key } + } /// In order to break cycles involving `AnonConst`, we need to set the expected type by side /// effect. However, we do not want this as a general capability, so this interface restricts @@ -544,12 +577,6 @@ pub struct GlobalCtxt<'tcx> { /// `rustc_symbol_mangling` crate for more information. stable_crate_id: StableCrateId, - /// This only ever stores a `LintStore` but we don't want a dependency on that type here. - /// - /// FIXME(Centril): consider `dyn LintStoreMarker` once - /// we can upcast to `Any` for some additional type safety. - pub lint_store: Lrc, - pub dep_graph: DepGraph, pub prof: SelfProfilerRef, @@ -606,6 +633,10 @@ impl<'tcx> GlobalCtxt<'tcx> { let icx = tls::ImplicitCtxt::new(self); tls::enter_context(&icx, || f(icx.tcx)) } + + pub fn finish(&self) -> FileEncodeResult { + self.dep_graph.finish_encoding(&self.sess.prof) + } } impl<'tcx> TyCtxt<'tcx> { @@ -684,8 +715,10 @@ impl<'tcx> TyCtxt<'tcx> { { Bound::Included(a) } else { - self.sess - .delay_span_bug(attr.span, "invalid rustc_layout_scalar_valid_range attribute"); + self.sess.span_delayed_bug( + attr.span, + "invalid rustc_layout_scalar_valid_range attribute", + ); Bound::Unbounded } }; @@ -709,7 +742,6 @@ impl<'tcx> TyCtxt<'tcx> { s: &'tcx Session, crate_types: Vec, stable_crate_id: StableCrateId, - lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, untracked: Untracked, @@ -724,13 +756,12 @@ impl<'tcx> TyCtxt<'tcx> { let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new(&interners, s, &untracked); let common_lifetimes = CommonLifetimes::new(&interners); - let common_consts = CommonConsts::new(&interners, &common_types); + let common_consts = CommonConsts::new(&interners, &common_types, s, &untracked); GlobalCtxt { sess: s, crate_types, stable_crate_id, - lint_store, arena, hir_arena, interners, @@ -779,6 +810,10 @@ impl<'tcx> TyCtxt<'tcx> { self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did) } + pub fn is_coroutine(self, def_id: DefId) -> bool { + self.coroutine_kind(def_id).is_some() + } + /// Returns `true` if the node pointed to by `def_id` is a coroutine for an async construct. pub fn coroutine_is_async(self, def_id: DefId) -> bool { matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Async(_))) @@ -943,7 +978,8 @@ impl<'tcx> TyCtxtAt<'tcx> { pub fn create_def( self, parent: LocalDefId, - data: hir::definitions::DefPathData, + name: Symbol, + def_kind: DefKind, ) -> TyCtxtFeed<'tcx, LocalDefId> { // This function modifies `self.definitions` using a side-effect. // We need to ensure that these side effects are re-run by the incr. comp. engine. @@ -965,9 +1001,11 @@ impl<'tcx> TyCtxtAt<'tcx> { // This is fine because: // - those queries are `eval_always` so we won't miss their result changing; // - this write will have happened before these queries are called. + let data = def_kind.def_path_data(name); let key = self.untracked.definitions.write().create_def(parent, data); let feed = TyCtxtFeed { tcx: self.tcx, key }; + feed.def_kind(def_kind); feed.def_span(self.span); feed } @@ -1080,8 +1118,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option { let (suitable_region_binding_scope, bound_region) = loop { let def_id = match region.kind() { - ty::ReFree(fr) => fr.bound_region.get_id()?.as_local()?, - ty::ReEarlyBound(ebr) => ebr.def_id.expect_local(), + ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?, + ty::ReEarlyParam(ebr) => ebr.def_id.expect_local(), _ => return None, // not a free region }; let scope = self.local_parent(def_id); @@ -1102,11 +1140,7 @@ impl<'tcx> TyCtxt<'tcx> { _ => false, }; - Some(FreeRegionInfo { - def_id: suitable_region_binding_scope, - boundregion: bound_region, - is_impl_item, - }) + Some(FreeRegionInfo { def_id: suitable_region_binding_scope, bound_region, is_impl_item }) } /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type. @@ -1114,7 +1148,7 @@ impl<'tcx> TyCtxt<'tcx> { self, scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>> { - let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); + let hir_id = self.local_def_id_to_hir_id(scope_def_id); let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else { @@ -1133,7 +1167,7 @@ impl<'tcx> TyCtxt<'tcx> { self, scope_def_id: LocalDefId, ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option)> { - let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); + let hir_id = self.local_def_id_to_hir_id(scope_def_id); let mut v = TraitObjectVisitor(vec![], self.hir()); // when the return type is a type alias if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) @@ -1548,7 +1582,6 @@ macro_rules! direct_interners { // crate only, and have a corresponding `mk_` function. direct_interners! { region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>, - const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>, const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>, adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>, @@ -1725,7 +1758,12 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - self.intern_const(ty::ConstData { kind, ty }) + self.interners.intern_const( + ty::ConstData { kind, ty }, + self.sess, + // This is only used to create a stable hashing context. + &self.untracked, + ) } // Avoid this in favour of more specific `Ty::new_*` methods, where possible. @@ -1743,7 +1781,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { match param.kind { GenericParamDefKind::Lifetime => { - ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into() + ty::Region::new_early_param(self, param.to_early_bound_region_data()).into() } GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(), GenericParamDefKind::Const { .. } => ty::Const::new_param( @@ -2040,7 +2078,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Given the def-id of an early-bound lifetime on an RPIT corresponding to /// a duplicated captured lifetime, map it back to the early- or late-bound /// lifetime of the function from which it originally as captured. If it is - /// a late-bound lifetime, this will represent the liberated (`ReFree`) lifetime + /// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime /// of the signature. // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just // re-use the generics of the opaque, this function will need to be tweaked slightly. @@ -2079,9 +2117,9 @@ impl<'tcx> TyCtxt<'tcx> { } let generics = self.generics_of(new_parent); - return ty::Region::new_early_bound( + return ty::Region::new_early_param( self, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: ebv, index: generics .param_def_id_to_index(self, ebv) @@ -2092,7 +2130,7 @@ impl<'tcx> TyCtxt<'tcx> { } Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => { let new_parent = self.parent(lbv); - return ty::Region::new_free( + return ty::Region::new_late_param( self, new_parent, ty::BoundRegionKind::BrNamed( @@ -2149,7 +2187,7 @@ impl<'tcx> TyCtxt<'tcx> { hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { generics, .. }), .. - }) if generics.params.iter().any(|p| self.has_attr(p.def_id, sym::rustc_host)) + }) if generics.params.iter().any(|p| matches!(p.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })) ) } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 77a50fa9276db..0094825fc70d4 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -274,7 +274,7 @@ pub fn suggest_constraining_type_params<'a>( span, if span_to_replace.is_some() { constraint.clone() - } else if constraint.starts_with("<") { + } else if constraint.starts_with('<') { constraint.to_string() } else if bound_list_non_empty { format!(" + {constraint}") diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 7895993ccffad..cfd36fd8c7c35 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - // If there's nothing to erase avoid performing the query at all - if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { + // If there's nothing to erase or anonymize, avoid performing the query at all + if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { return value; } debug!("erase_regions({:?})", value); @@ -53,16 +53,11 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - // because late-bound regions affect subtyping, we can't - // erase the bound/free distinction, but we can replace - // all free regions with 'erased. - // - // Note that we *CAN* replace early-bound regions -- the - // type system never "sees" those, they get substituted - // away. In codegen, they will always be erased to 'erased - // whenever a substitution occurs. + // We must not erase bound regions. `for<'a> fn(&'a ())` and + // `fn(&'free ())` are different types: they may implement different + // traits and have a different `TypeId`. match *r { - ty::ReLateBound(..) => r, + ty::ReBound(..) => r, _ => self.tcx.lifetimes.re_erased, } } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 738bb5e8b1959..469593fe66347 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -7,8 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::Symbol; use rustc_target::spec::abi; use std::borrow::Cow; -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; +use std::hash::{DefaultHasher, Hash, Hasher}; use std::path::PathBuf; #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] @@ -236,7 +235,7 @@ impl<'tcx> Ty<'tcx> { _ => "fn item".into(), }, ty::FnPtr(_) => "fn pointer".into(), - ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => { + ty::Dynamic(inner, ..) if let Some(principal) = inner.principal() => { format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into() } ty::Dynamic(..) => "trait object".into(), @@ -282,7 +281,7 @@ impl<'tcx> Ty<'tcx> { | ty::Float(_) | ty::Str | ty::Never => "type".into(), - ty::Tuple(ref tys) if tys.is_empty() => "unit type".into(), + ty::Tuple(tys) if tys.is_empty() => "unit type".into(), ty::Adt(def, _) => def.descr().into(), ty::Foreign(_) => "extern type".into(), ty::Array(..) => "array".into(), diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 75ea53195a3ac..f95ceeff1507a 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -189,14 +189,14 @@ pub struct DeepRejectCtxt { } impl DeepRejectCtxt { - pub fn args_refs_may_unify<'tcx>( + pub fn args_may_unify<'tcx>( self, obligation_args: GenericArgsRef<'tcx>, impl_args: GenericArgsRef<'tcx>, ) -> bool { iter::zip(obligation_args, impl_args).all(|(obl, imp)| { match (obl.unpack(), imp.unpack()) { - // We don't fast reject based on regions for now. + // We don't fast reject based on regions. (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true, (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => { self.types_may_unify(obl, imp) @@ -231,7 +231,7 @@ impl DeepRejectCtxt { | ty::Never | ty::Tuple(..) | ty::FnPtr(..) - | ty::Foreign(..) => {} + | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()), ty::FnDef(..) | ty::Closure(..) | ty::Coroutine(..) @@ -260,7 +260,7 @@ impl DeepRejectCtxt { }, ty::Adt(obl_def, obl_args) => match k { &ty::Adt(impl_def, impl_args) => { - obl_def == impl_def && self.args_refs_may_unify(obl_args, impl_args) + obl_def == impl_def && self.args_may_unify(obl_args, impl_args) } _ => false, }, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index a348e9f608aab..f9a2385b10005 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -28,30 +28,11 @@ impl FlagComputation { result } - pub fn for_const(c: ty::Const<'_>) -> TypeFlags { + pub fn for_const(c: &ty::ConstKind<'_>, t: Ty<'_>) -> FlagComputation { let mut result = FlagComputation::new(); - result.add_const(c); - result.flags - } - - pub fn bound_var_flags(vars: &ty::List) -> FlagComputation { - let mut computation = FlagComputation::new(); - - for bv in vars { - match bv { - ty::BoundVariableKind::Ty(_) => { - computation.flags |= TypeFlags::HAS_TY_LATE_BOUND; - } - ty::BoundVariableKind::Region(_) => { - computation.flags |= TypeFlags::HAS_RE_LATE_BOUND; - } - ty::BoundVariableKind::Const => { - computation.flags |= TypeFlags::HAS_CT_LATE_BOUND; - } - } - } - - computation + result.add_const_kind(c); + result.add_ty(t); + result } fn add_flags(&mut self, flags: TypeFlags) { @@ -77,7 +58,11 @@ impl FlagComputation { where F: FnOnce(&mut Self, T), { - let mut computation = FlagComputation::bound_var_flags(value.bound_vars()); + let mut computation = FlagComputation::new(); + + if !value.bound_vars().is_empty() { + computation.add_flags(TypeFlags::HAS_BINDER_VARS); + } f(&mut computation, value.skip_binder()); @@ -153,7 +138,7 @@ impl FlagComputation { &ty::Bound(debruijn, _) => { self.add_bound_var(debruijn); - self.add_flags(TypeFlags::HAS_TY_LATE_BOUND); + self.add_flags(TypeFlags::HAS_TY_BOUND); } &ty::Placeholder(..) => { @@ -279,9 +264,6 @@ impl FlagComputation { self.add_args(slice::from_ref(&arg)); } ty::PredicateKind::ObjectSafe(_def_id) => {} - ty::PredicateKind::ClosureKind(_def_id, args, _kind) => { - self.add_args(args); - } ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => { self.add_const(uv); } @@ -290,6 +272,10 @@ impl FlagComputation { self.add_const(found); } ty::PredicateKind::Ambiguous => {} + ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => { + self.add_alias_ty(alias); + self.add_term(term); + } ty::PredicateKind::AliasRelate(t1, t2, _) => { self.add_term(t1); self.add_term(t2); @@ -310,14 +296,18 @@ impl FlagComputation { fn add_region(&mut self, r: ty::Region<'_>) { self.add_flags(r.type_flags()); - if let ty::ReLateBound(debruijn, _) = *r { + if let ty::ReBound(debruijn, _) = *r { self.add_bound_var(debruijn); } } fn add_const(&mut self, c: ty::Const<'_>) { - self.add_ty(c.ty()); - match c.kind() { + self.add_flags(c.flags()); + self.add_exclusive_binder(c.outer_exclusive_binder()); + } + + fn add_const_kind(&mut self, c: &ty::ConstKind<'_>) { + match *c { ty::ConstKind::Unevaluated(uv) => { self.add_args(uv.args); self.add_flags(TypeFlags::HAS_CT_PROJECTION); @@ -333,7 +323,7 @@ impl FlagComputation { } ty::ConstKind::Bound(debruijn, _) => { self.add_bound_var(debruijn); - self.add_flags(TypeFlags::HAS_CT_LATE_BOUND); + self.add_flags(TypeFlags::HAS_CT_BOUND); } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 00529a1e066cc..3e64f9a2a9095 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -68,12 +68,10 @@ impl<'tcx> TyCtxt<'tcx> { /// Folds over the substructure of a type, visiting its component /// types and all regions that occur *free* within it. /// -/// That is, `Ty` can contain function or method types that bind -/// regions at the call site (`ReLateBound`), and occurrences of -/// regions (aka "lifetimes") that are bound within a type are not -/// visited by this folder; only regions that occur free will be +/// That is, function pointer types and trait object can introduce +/// new bound regions which are not visited by this visitors as +/// they are not free; only regions that occur free will be /// visited by `fld_r`. - pub struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -117,7 +115,7 @@ impl<'a, 'tcx> TypeFolder> for RegionFolder<'a, 'tcx> { #[instrument(skip(self), level = "debug", ret)] fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { + ty::ReBound(debruijn, _) if debruijn < self.current_index => { debug!(?self.current_index, "skipped bound region"); r } @@ -205,15 +203,15 @@ where fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { + ty::ReBound(debruijn, br) if debruijn == self.current_index => { let region = self.delegate.replace_region(br); - if let ty::ReLateBound(debruijn1, br) = *region { - // If the callback returns a late-bound region, + if let ty::ReBound(debruijn1, br) = *region { + // If the callback returns a bound region, // that region should always use the INNERMOST // debruijn index. Then we adjust it to the // correct depth. assert_eq!(debruijn1, ty::INNERMOST); - ty::Region::new_late_bound(self.tcx, debruijn, br) + ty::Region::new_bound(self.tcx, debruijn, br) } else { region } @@ -252,7 +250,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// This method only replaces late bound regions. Any types or /// constants bound by `value` will cause an ICE. - pub fn replace_late_bound_regions( + pub fn instantiate_bound_regions( self, value: Binder<'tcx, T>, mut fld_r: F, @@ -263,11 +261,11 @@ impl<'tcx> TyCtxt<'tcx> { { let mut region_map = BTreeMap::new(); let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br)); - let value = self.replace_late_bound_regions_uncached(value, real_fld_r); + let value = self.instantiate_bound_regions_uncached(value, real_fld_r); (value, region_map) } - pub fn replace_late_bound_regions_uncached( + pub fn instantiate_bound_regions_uncached( self, value: Binder<'tcx, T>, mut replace_regions: F, @@ -327,8 +325,8 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - self.replace_late_bound_regions_uncached(value, |br| { - ty::Region::new_free(self, all_outlive_scope, br.kind) + self.instantiate_bound_regions_uncached(value, |br| { + ty::Region::new_late_param(self, all_outlive_scope, br.kind) }) } @@ -341,7 +339,7 @@ impl<'tcx> TyCtxt<'tcx> { value, FnMutDelegate { regions: &mut |r: ty::BoundRegion| { - ty::Region::new_late_bound( + ty::Region::new_bound( self, ty::INNERMOST, ty::BoundRegion { var: shift_bv(r.var), kind: r.kind }, @@ -363,11 +361,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also /// method lookup and a few other places where precise region relationships are not required. - pub fn erase_late_bound_regions(self, value: Binder<'tcx, T>) -> T + pub fn instantiate_bound_regions_with_erased(self, value: Binder<'tcx, T>) -> T where T: TypeFoldable>, { - self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0 + self.instantiate_bound_regions(value, |_| self.lifetimes.re_erased).0 } /// Anonymize all bound variables in `value`, this is mostly used to improve caching. @@ -388,7 +386,7 @@ impl<'tcx> TyCtxt<'tcx> { .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon)) .expect_region(); let br = ty::BoundRegion { var, kind }; - ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br) + ty::Region::new_bound(self.tcx, ty::INNERMOST, br) } fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { let entry = self.map.entry(bt.var); @@ -454,9 +452,9 @@ impl<'tcx> TypeFolder> for Shifter<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { + ty::ReBound(debruijn, br) if debruijn >= self.current_index => { let debruijn = debruijn.shifted_in(self.amount); - ty::Region::new_late_bound(self.tcx, debruijn, br) + ty::Region::new_bound(self.tcx, debruijn, br) } _ => r, } @@ -496,8 +494,8 @@ pub fn shift_region<'tcx>( amount: u32, ) -> ty::Region<'tcx> { match *region { - ty::ReLateBound(debruijn, br) if amount > 0 => { - ty::Region::new_late_bound(tcx, debruijn.shifted_in(amount), br) + ty::ReBound(debruijn, br) if amount > 0 => { + ty::Region::new_bound(tcx, debruijn.shifted_in(amount), br) } _ => region, } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 41a1bf04e5f3f..fa68923b2c126 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -70,7 +70,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) + (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo> as usize) } }; @@ -86,7 +86,7 @@ impl<'tcx> Ord for GenericArg<'tcx> { impl<'tcx> PartialOrd for GenericArg<'tcx> { fn partial_cmp(&self, other: &GenericArg<'tcx>) -> Option { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } @@ -136,7 +136,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), _ => intrinsics::unreachable(), } @@ -604,13 +604,6 @@ impl EarlyBinder> { } } -impl EarlyBinder<(T, U)> { - pub fn transpose_tuple2(self) -> (EarlyBinder, EarlyBinder) { - let EarlyBinder { value: (lhs, rhs) } = self; - (EarlyBinder { value: lhs }, EarlyBinder { value: rhs }) - } -} - impl<'tcx, 's, I: IntoIterator> EarlyBinder where I::Item: TypeFoldable>, @@ -809,7 +802,7 @@ impl<'a, 'tcx> TypeFolder> for ArgFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { #[cold] #[inline(never)] - fn region_param_out_of_range(data: ty::EarlyBoundRegion, args: &[GenericArg<'_>]) -> ! { + fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! { bug!( "Region parameter out of range when substituting in region {} (index={}, args = {:?})", data.name, @@ -820,7 +813,7 @@ impl<'a, 'tcx> TypeFolder> for ArgFolder<'a, 'tcx> { #[cold] #[inline(never)] - fn region_param_invalid(data: ty::EarlyBoundRegion, other: GenericArgKind<'_>) -> ! { + fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! { bug!( "Unexpected parameter {:?} when substituting in region {} (index={})", other, @@ -835,7 +828,7 @@ impl<'a, 'tcx> TypeFolder> for ArgFolder<'a, 'tcx> { // regions that appear in a function signature is done using // the specialized routine `ty::replace_late_regions()`. match *r { - ty::ReEarlyBound(data) => { + ty::ReEarlyParam(data) => { let rk = self.args.get(data.index as usize).map(|k| k.unpack()); match rk { Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), @@ -843,8 +836,8 @@ impl<'a, 'tcx> TypeFolder> for ArgFolder<'a, 'tcx> { None => region_param_out_of_range(data, self.args), } } - ty::ReLateBound(..) - | ty::ReFree(_) + ty::ReBound(..) + | ty::ReLateParam(_) | ty::ReStatic | ty::RePlaceholder(_) | ty::ReErased diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 888ee1d237ae7..8316f9c30587f 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; +use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { @@ -62,9 +62,9 @@ pub struct GenericParamDef { } impl GenericParamDef { - pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion { + pub fn to_early_bound_region_data(&self) -> ty::EarlyParamRegion { if let GenericParamDefKind::Lifetime = self.kind { - ty::EarlyBoundRegion { def_id: self.def_id, index: self.index, name: self.name } + ty::EarlyParamRegion { def_id: self.def_id, index: self.index, name: self.name } } else { bug!("cannot convert a non-lifetime parameter def to an early bound region") } @@ -260,10 +260,10 @@ impl<'tcx> Generics { } } - /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`. + /// Returns the `GenericParamDef` associated with this `EarlyParamRegion`. pub fn region_param( &'tcx self, - param: &EarlyBoundRegion, + param: &ty::EarlyParamRegion, tcx: TyCtxt<'tcx>, ) -> &'tcx GenericParamDef { let param = self.param_at(param.index as usize, tcx); @@ -354,7 +354,7 @@ impl<'tcx> Generics { args: &'tcx [ty::GenericArg<'tcx>], ) -> &'tcx [ty::GenericArg<'tcx>] { let own = &args[self.parent_count..][..self.params.len()]; - if self.has_self && self.parent.is_none() { &own[1..] } else { &own } + if self.has_self && self.parent.is_none() { &own[1..] } else { own } } } diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index b03874a90e8d5..129d947697e89 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -29,7 +29,7 @@ where } let mut hasher = StableHasher::new(); - (&self[..]).hash_stable(hcx, &mut hasher); + self[..].hash_stable(hcx, &mut hasher); let hash: Fingerprint = hasher.finish(); cache.borrow_mut().insert(key, hash); @@ -84,6 +84,14 @@ impl<'a> HashStable> for mir::interpret::AllocId { } } +// CtfeProvenance is an AllocId and a bool. +impl<'a> HashStable> for mir::interpret::CtfeProvenance { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.alloc_id().hash_stable(hcx, hasher); + self.immutable().hash_stable(hcx, hasher); + } +} + impl<'a> ToStableHashKey> for region::Scope { type KeyType = region::Scope; diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index cebefbccc11d1..1c7a7545e2b0e 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -215,7 +215,7 @@ impl<'tcx> InstanceDef<'tcx> { }; matches!( tcx.def_key(def_id).disambiguated_data.data, - DefPathData::Ctor | DefPathData::ClosureExpr + DefPathData::Ctor | DefPathData::Closure ) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4223e503f5e22..e1d1f361091b5 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -215,7 +215,7 @@ pub enum LayoutError<'tcx> { SizeOverflow(Ty<'tcx>), NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), ReferencesError(ErrorGuaranteed), - Cycle, + Cycle(ErrorGuaranteed), } impl<'tcx> LayoutError<'tcx> { @@ -226,7 +226,7 @@ impl<'tcx> LayoutError<'tcx> { Unknown(_) => middle_unknown_layout, SizeOverflow(_) => middle_values_too_big, NormalizationFailure(_, _) => middle_cannot_be_normalized, - Cycle => middle_cycle, + Cycle(_) => middle_cycle, ReferencesError(_) => middle_layout_references_error, } } @@ -240,7 +240,7 @@ impl<'tcx> LayoutError<'tcx> { NormalizationFailure(ty, e) => { E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() } } - Cycle => E::Cycle, + Cycle(_) => E::Cycle, ReferencesError(_) => E::ReferencesError, } } @@ -261,7 +261,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { t, e.get_type_for_failure() ), - LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"), + LayoutError::Cycle(_) => write!(f, "a cycle occurred during layout computation"), LayoutError::ReferencesError(_) => write!(f, "the type has an unknown layout"), } } @@ -282,8 +282,8 @@ pub struct LayoutCx<'tcx, C> { impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> { type TargetDataLayoutRef = &'tcx TargetDataLayout; - fn delay_bug(&self, txt: String) { - self.tcx.sess.delay_span_bug(DUMMY_SP, txt); + fn delayed_bug(&self, txt: String) { + self.tcx.sess.span_delayed_bug(DUMMY_SP, txt); } fn current_data_layout(&self) -> Self::TargetDataLayoutRef { @@ -333,7 +333,7 @@ impl<'tcx> SizeSkeleton<'tcx> { Err(err @ LayoutError::Unknown(_)) => err, // We can't extract SizeSkeleton info from other layout errors Err( - e @ LayoutError::Cycle + e @ LayoutError::Cycle(_) | e @ LayoutError::SizeOverflow(_) | e @ LayoutError::NormalizationFailure(..) | e @ LayoutError::ReferencesError(_), @@ -899,13 +899,13 @@ where ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8), // Tuples, coroutines and closures. - ty::Closure(_, ref args) => field_ty_or_layout( + ty::Closure(_, args) => field_ty_or_layout( TyAndLayout { ty: args.as_closure().tupled_upvars_ty(), ..this }, cx, i, ), - ty::Coroutine(def_id, ref args, _) => match this.variants { + ty::Coroutine(def_id, args, _) => match this.variants { Variants::Single { index } => TyMaybeWithLayout::Ty( args.as_coroutine() .state_tys(def_id, tcx) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 739d4fa886ec3..203c9eb65df86 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -42,7 +42,6 @@ use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; -use rustc_hir::Node; use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; @@ -84,9 +83,7 @@ pub use self::closure::{ CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL, }; -pub use self::consts::{ - Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, -}; +pub use self::consts::{Const, ConstData, ConstInt, Expr, ScalarInt, UnevaluatedConst, ValTree}; pub use self::context::{ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, }; @@ -96,13 +93,13 @@ pub use self::parameterized::ParameterizedOverTcx; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ - AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, + AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind, - ConstVid, CoroutineArgs, CoroutineArgsParts, EarlyBoundRegion, EffectVid, ExistentialPredicate, - ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, InlineConstArgs, - InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, - PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, PredicateKind, Region, - RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, + CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, ExistentialPredicate, + ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs, + InlineConstArgsParts, LateParamRegion, ParamConst, ParamTy, PolyExistentialPredicate, + PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyTraitRef, PredicateKind, + Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -204,9 +201,6 @@ pub struct ResolverAstLowering { pub def_id_to_node_id: IndexVec, pub trait_map: NodeMap>, - /// A small map keeping true kinds of built-in macros that appear to be fn-like on - /// the surface (`macro` items in libcore), but are actually attributes or derives. - pub builtin_macro_kinds: FxHashMap, /// List functions and methods for which lifetime elision was successful. pub lifetime_elision_allowed: FxHashSet, @@ -301,6 +295,23 @@ pub enum Visibility { Restricted(Id), } +impl Visibility { + pub fn to_string(self, def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { + match self { + ty::Visibility::Restricted(restricted_id) => { + if restricted_id.is_top_level_module() { + "pub(crate)".to_string() + } else if restricted_id == tcx.parent_module_from_def_id(def_id).to_local_def_id() { + "pub(self)".to_string() + } else { + format!("pub({})", tcx.item_name(restricted_id.to_def_id())) + } + } + ty::Visibility::Public => "pub".to_string(), + } + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] pub enum BoundConstness { /// `T: Trait` @@ -463,7 +474,7 @@ pub struct CReaderCacheKey { #[rustc_pass_by_value] pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); -impl ty::EarlyBoundRegion { +impl EarlyParamRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn has_name(&self) -> bool { @@ -542,6 +553,10 @@ impl<'tcx> Predicate<'tcx> { pub fn allow_normalization(self) -> bool { match self.kind().skip_binder() { PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, + // `NormalizesTo` is only used in the new solver, so this shouldn't + // matter. Normalizing `term` would be 'wrong' however, as it changes whether + // `normalizes-to(::Assoc, ::Assoc)` holds. + PredicateKind::NormalizesTo(..) => false, PredicateKind::Clause(ClauseKind::Trait(_)) | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) @@ -549,7 +564,6 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) | PredicateKind::AliasRelate(..) | PredicateKind::ObjectSafe(_) - | PredicateKind::ClosureKind(_, _, _) | PredicateKind::Subtype(_) | PredicateKind::Coerce(_) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) @@ -902,7 +916,7 @@ impl<'tcx> Term<'tcx> { &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), _ => core::intrinsics::unreachable(), } @@ -969,7 +983,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) + (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo> as usize) } }; @@ -1083,6 +1097,33 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { } } +/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be +/// proven by actually normalizing `alias`. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct NormalizesTo<'tcx> { + pub alias: AliasTy<'tcx>, + pub term: Term<'tcx>, +} + +impl<'tcx> NormalizesTo<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.alias.self_ty() + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> { + Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + self.alias.trait_def_id(tcx) + } + + pub fn def_id(self) -> DefId { + self.alias.def_id + } +} + pub trait ToPolyTraitRef<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; } @@ -1264,6 +1305,12 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { } } +impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + PredicateKind::NormalizesTo(self).to_predicate(tcx) + } +} + impl<'tcx> Predicate<'tcx> { pub fn to_opt_poly_trait_pred(self) -> Option> { let predicate = self.kind(); @@ -1271,13 +1318,13 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), PredicateKind::Clause(ClauseKind::Projection(..)) | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::NormalizesTo(..) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) @@ -1291,13 +1338,13 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), PredicateKind::Clause(ClauseKind::Trait(..)) | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::NormalizesTo(..) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) @@ -1305,26 +1352,6 @@ impl<'tcx> Predicate<'tcx> { } } - pub fn to_opt_type_outlives(self) -> Option> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(ClauseKind::TypeOutlives(data)) => Some(predicate.rebind(data)), - PredicateKind::Clause(ClauseKind::Trait(..)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::Clause(ClauseKind::Projection(..)) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) - | PredicateKind::Clause(ClauseKind::WellFormed(..)) - | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous => None, - } - } - /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`. pub fn as_clause(self) -> Option> { match self.kind().skip_binder() { @@ -1377,7 +1404,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { - (&self).into_iter() + self.into_iter() } } @@ -1518,8 +1545,36 @@ pub struct Placeholder { pub type PlaceholderRegion = Placeholder; +impl rustc_type_ir::Placeholder for PlaceholderRegion { + fn universe(&self) -> UniverseIndex { + self.universe + } + + fn var(&self) -> BoundVar { + self.bound.var + } + + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } + } +} + pub type PlaceholderType = Placeholder; +impl rustc_type_ir::Placeholder for PlaceholderType { + fn universe(&self) -> UniverseIndex { + self.universe + } + + fn var(&self) -> BoundVar { + self.bound.var + } + + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)] pub struct BoundConst<'tcx> { @@ -1527,7 +1582,21 @@ pub struct BoundConst<'tcx> { pub ty: Ty<'tcx>, } -pub type PlaceholderConst<'tcx> = Placeholder; +pub type PlaceholderConst = Placeholder; + +impl rustc_type_ir::Placeholder for PlaceholderConst { + fn universe(&self) -> UniverseIndex { + self.universe + } + + fn var(&self) -> BoundVar { + self.bound + } + + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } + } +} /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this @@ -2011,7 +2080,7 @@ impl<'tcx> TyCtxt<'tcx> { // Generate a deterministically-derived seed from the item's path hash // to allow for cross-crate compilation to actually work - let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash(); + let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash().as_u64(); // If the user defined a custom seed for layout randomization, xor the item's // path hash with the user defined seed, this will allowing determinism while @@ -2021,7 +2090,7 @@ impl<'tcx> TyCtxt<'tcx> { } for attr in self.get_attrs(did, sym::repr) { - for r in attr::parse_repr_attr(&self.sess, attr) { + for r in attr::parse_repr_attr(self.sess, attr) { flags.insert(match r { attr::ReprRust => ReprFlags::empty(), attr::ReprC => ReprFlags::IS_C, @@ -2256,7 +2325,7 @@ impl<'tcx> TyCtxt<'tcx> { // FIXME(@lcnr): Remove this function. pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [ast::Attribute] { if let Some(did) = did.as_local() { - self.hir().attrs(self.hir().local_def_id_to_hir_id(did)) + self.hir().attrs(self.local_def_id_to_hir_id(did)) } else { self.item_attrs(did) } @@ -2271,7 +2340,7 @@ impl<'tcx> TyCtxt<'tcx> { let did: DefId = did.into(); let filter_fn = move |a: &&ast::Attribute| a.has_name(attr); if let Some(did) = did.as_local() { - self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn) + self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn) } else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(attr) { bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr); } else { @@ -2287,9 +2356,9 @@ impl<'tcx> TyCtxt<'tcx> { where 'tcx: 'attr, { - let filter_fn = move |a: &&ast::Attribute| a.path_matches(&attr); + let filter_fn = move |a: &&ast::Attribute| a.path_matches(attr); if let Some(did) = did.as_local() { - self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn) + self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn) } else { self.item_attrs(did).iter().filter(filter_fn) } @@ -2495,22 +2564,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. -pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - let def_id = def_id.as_local()?; - if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) { - if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { - return match opaque_ty.origin { - hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { - Some(parent) - } - hir::OpaqueTyOrigin::TyAlias { .. } => None, - }; - } - } - None -} - pub fn int_ty(ity: ast::IntTy) -> IntTy { match ity { ast::IntTy::Isize => IntTy::Isize, @@ -2599,9 +2652,7 @@ pub struct SymbolName<'tcx> { impl<'tcx> SymbolName<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> { - SymbolName { - name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) }, - } + SymbolName { name: tcx.arena.alloc_str(name) } } } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index fd125af2074e4..27c436c82f53e 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -97,6 +97,10 @@ impl<'tcx> TyCtxt<'tcx> { /// N.B., currently, higher-ranked type bounds inhibit /// normalization. Therefore, each time we erase them in /// codegen, we need to normalize the contents. + // FIXME(@lcnr): This method should not be necessary, we now normalize + // inside of binders. We should be able to only use + // `tcx.instantiate_bound_regions_with_erased`. Same for the `try_X` + // variant. #[tracing::instrument(level = "debug", skip(self, param_env))] pub fn normalize_erasing_late_bound_regions( self, @@ -106,7 +110,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - let value = self.erase_late_bound_regions(value); + let value = self.instantiate_bound_regions_with_erased(value); self.normalize_erasing_regions(param_env, value) } @@ -126,7 +130,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - let value = self.erase_late_bound_regions(value); + let value = self.instantiate_bound_regions_with_erased(value); self.try_normalize_erasing_regions(param_env, value) } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 8d895732dff20..1305f63bdbc2f 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -102,8 +102,9 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { // Ignore bound regions and `'static` regions that appear in the // type, we only need to remap regions that reference lifetimes // from the function declaration. - // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | ty::ReStatic => return r, + // + // E.g. We ignore `'r` in a type like `for<'r> fn(&'r u32)`. + ty::ReBound(..) | ty::ReStatic => return r, // If regions have been erased (by writeback), don't try to unerase // them. @@ -112,7 +113,7 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { ty::ReError(_) => return r, // The regions that we expect from borrow checking. - ty::ReEarlyBound(_) | ty::ReFree(_) => {} + ty::ReEarlyParam(_) | ty::ReLateParam(_) => {} ty::RePlaceholder(_) | ty::ReVar(_) => { // All of the regions in the type should either have been diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 9afa50cf584c3..a63a4eff5e122 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! { crate::middle::codegen_fn_attrs::CodegenFnAttrs, crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, + crate::middle::lib_features::FeatureStability, crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, ty::AssocItemContainer, diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 6bbc8f70f5155..5e09154789a79 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -131,7 +131,7 @@ pub trait Printer<'tcx>: Sized { match key.disambiguated_data.data { // Closures' own generics are only captures, don't print them. - DefPathData::ClosureExpr => {} + DefPathData::Closure => {} // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`. // Anon consts doesn't have their own generics, and inline consts' own // generics are their inferred types, so don't print them. @@ -250,7 +250,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited), - ty::Tuple(ref tys) => tys.iter().find_map(|ty| { + ty::Tuple(tys) => tys.iter().find_map(|ty| { if visited.insert(ty) { return characteristic_def_id_of_type_cached(ty, visited); } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index baf160bcc99da..bd9f0fd3ea9c5 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -8,6 +8,7 @@ use crate::ty::{ }; use crate::ty::{GenericArg, GenericArgKind}; use rustc_apfloat::ieee::{Double, Single}; +use rustc_apfloat::Float; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; @@ -282,7 +283,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// from at least one local module, and returns `true`. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result { - if NO_VISIBLE_PATH.with(|flag| flag.get()) { + if with_no_visible_paths() { return Ok(false); } @@ -322,7 +323,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id) { // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`. - self.write_str(get_local_name(&self, *symbol, def_id, key).as_str())?; + self.write_str(get_local_name(self, *symbol, def_id, key).as_str())?; return Ok(true); } if let Some(symbol) = key.get_opt_name() { @@ -332,7 +333,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { && let Some(symbol) = parent_key.get_opt_name() { // Trait - self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; + self.write_str(get_local_name(self, symbol, parent, parent_key).as_str())?; self.write_str("::")?; } else if let DefKind::Variant = kind && let Some(parent) = self.tcx().opt_parent(def_id) @@ -343,7 +344,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // For associated items and variants, we want the "full" path, namely, include // the parent type in the path. For example, `Iterator::Item`. - self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; + self.write_str(get_local_name(self, symbol, parent, parent_key).as_str())?; self.write_str("::")?; } else if let DefKind::Struct | DefKind::Union @@ -358,7 +359,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // If not covered above, like for example items out of `impl` blocks, fallback. return Ok(false); } - self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?; + self.write_str(get_local_name(self, symbol, def_id, key).as_str())?; return Ok(true); } Ok(false) @@ -366,7 +367,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Try to see if this path can be trimmed to a unique symbol name. fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result { - if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + if with_forced_trimmed_paths() { let trimmed = self.force_print_trimmed_def_path(def_id)?; if trimmed { return Ok(true); @@ -374,8 +375,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never) - || NO_TRIMMED_PATH.with(|flag| flag.get()) - || SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) + || with_no_trimmed_paths() + || with_crate_prefix() { return Ok(false); } @@ -660,7 +661,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!(print(ty::TypeAndMut { ty, mutbl })) } ty::Never => p!("!"), - ty::Tuple(ref tys) => { + ty::Tuple(tys) => { p!("(", comma_sep(tys.iter())); if tys.len() == 1 { p!(","); @@ -860,7 +861,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!("@", print_def_path(did.to_def_id(), args)); } else { let span = self.tcx().def_span(did); - let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + let preference = if with_forced_trimmed_paths() { FileNameDisplayPreference::Short } else { FileNameDisplayPreference::Remapped @@ -1101,7 +1102,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { write!(self, "Sized")?; } - if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + if !with_forced_trimmed_paths() { for re in lifetimes { write!(self, " + ")?; self.print_region(re)?; @@ -1409,14 +1410,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ) -> Result<(), PrintError> { define_scoped_cx!(self); - let (alloc_id, offset) = ptr.into_parts(); + let (prov, offset) = ptr.into_parts(); match ty.kind() { // Byte strings (&[u8; N]) ty::Ref(_, inner, _) => { if let ty::Array(elem, len) = inner.kind() { if let ty::Uint(ty::UintTy::U8) = elem.kind() { if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() { - match self.tcx().try_get_global_alloc(alloc_id) { + match self.tcx().try_get_global_alloc(prov.alloc_id()) { Some(GlobalAlloc::Memory(alloc)) => { let len = int.assert_bits(self.tcx().data_layout.pointer_size); let range = @@ -1446,7 +1447,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // FIXME: We should probably have a helper method to share code with the "Byte strings" // printing above (which also has to handle pointers to all sorts of things). if let Some(GlobalAlloc::Function(instance)) = - self.tcx().try_get_global_alloc(alloc_id) + self.tcx().try_get_global_alloc(prov.alloc_id()) { self.typed_value( |this| this.print_value_path(instance.def_id(), instance.args), @@ -1477,10 +1478,12 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::Bool if int == ScalarInt::TRUE => p!("true"), // Float ty::Float(ty::FloatTy::F32) => { - p!(write("{}f32", Single::try_from(int).unwrap())) + let val = Single::try_from(int).unwrap(); + p!(write("{}{}f32", val, if val.is_finite() { "" } else { "_" })) } ty::Float(ty::FloatTy::F64) => { - p!(write("{}f64", Double::try_from(int).unwrap())) + let val = Double::try_from(int).unwrap(); + p!(write("{}{}f64", val, if val.is_finite() { "" } else { "_" })) } // Int ty::Uint(_) | ty::Int(_) => { @@ -1801,13 +1804,13 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { // (but also some things just print a `DefId` generally so maybe we need this?) fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace { match tcx.def_key(def_id).disambiguated_data.data { - DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => { + DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => { Namespace::TypeNS } DefPathData::ValueNs(..) | DefPathData::AnonConst - | DefPathData::ClosureExpr + | DefPathData::Closure | DefPathData::Ctor => Namespace::ValueNS, DefPathData::MacroNs(..) => Namespace::MacroNS, @@ -1883,7 +1886,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { // available, and filename/line-number is mostly uninteresting. let use_types = !def_id.is_local() || { // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + let force_no_types = with_forced_impl_filename_line(); !force_no_types }; @@ -1948,7 +1951,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { if cnum == LOCAL_CRATE { if self.tcx.sess.at_least_rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. - if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { + if with_crate_prefix() { write!(self, "{}", kw::Crate)?; self.empty_path = false; } @@ -2151,17 +2154,17 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { return true; } - if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + if with_forced_trimmed_paths() { return false; } let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions; match *region { - ty::ReEarlyBound(ref data) => data.has_name(), + ty::ReEarlyParam(ref data) => data.has_name(), - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) - | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) + | ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. }) => { @@ -2228,14 +2231,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // to fit that into a short string. Hence the recommendation to use // `explain_region()` or `note_and_explain_region()`. match *region { - ty::ReEarlyBound(ref data) => { + ty::ReEarlyParam(ref data) => { if data.name != kw::Empty { p!(write("{}", data.name)); return Ok(()); } } - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) - | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) + | ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. }) => { @@ -2315,7 +2318,7 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let name = &mut self.name; let region = match *r { - ty::ReLateBound(db, br) if db >= self.current_index => { + ty::ReBound(db, br) if db >= self.current_index => { *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br)) } ty::RePlaceholder(ty::PlaceholderRegion { @@ -2338,9 +2341,9 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { } _ => return r, }; - if let ty::ReLateBound(debruijn1, br) = *region { + if let ty::ReBound(debruijn1, br) = *region { assert_eq!(debruijn1, ty::INNERMOST); - ty::Region::new_late_bound(self.tcx, self.current_index, br) + ty::Region::new_bound(self.tcx, self.current_index, br) } else { region } @@ -2399,7 +2402,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { let possible_names = ('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}"))); let mut available_names = possible_names - .filter(|name| !self.used_region_names.contains(&name)) + .filter(|name| !self.used_region_names.contains(name)) .collect::>(); debug!(?available_names); let num_available = available_names.len(); @@ -2434,7 +2437,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } else { let tcx = self.tcx; - let trim_path = FORCE_TRIMMED_PATH.with(|flag| flag.get()); + let trim_path = with_forced_trimmed_paths(); // Closure used in `RegionFolder` to create names for anonymous late-bound // regions. We use two `DebruijnIndex`es (one for the currently folded // late-bound region and the other for the binder level) to determine @@ -2445,12 +2448,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { br: ty::BoundRegion| { let (name, kind) = match br.kind { ty::BrAnon | ty::BrEnv => { - let name = next_name(&self); + let name = next_name(self); if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name); - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2461,12 +2464,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)) } ty::BrNamed(def_id, kw::UnderscoreLifetime | kw::Empty) => { - let name = next_name(&self); + let name = next_name(self); if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = ty::BrNamed(def_id, name); - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2480,7 +2483,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = br.kind; - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2496,11 +2499,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { start_or_continue(self, "for<", ", "); do_continue(self, name); } - ty::Region::new_late_bound( - tcx, - ty::INNERMOST, - ty::BoundRegion { var: br.var, kind }, - ) + ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }) }; let mut folder = RegionFolder { tcx, @@ -2641,6 +2640,23 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { } } +/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only +/// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds. +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>); + +impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintSugared<'tcx> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + +impl<'tcx> fmt::Debug for TraitRefPrintSugared<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait name. That is, it will print `Trait` instead of /// `>`. @@ -2658,6 +2674,10 @@ impl<'tcx> ty::TraitRef<'tcx> { TraitRefPrintOnlyTraitPath(self) } + pub fn print_trait_sugared(self) -> TraitRefPrintSugared<'tcx> { + TraitRefPrintSugared(self) + } + pub fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> { TraitRefPrintOnlyTraitName(self) } @@ -2667,6 +2687,10 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> { pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> { self.map_bound(|tr| tr.print_only_trait_path()) } + + pub fn print_trait_sugared(self) -> ty::Binder<'tcx, TraitRefPrintSugared<'tcx>> { + self.map_bound(|tr| tr.print_trait_sugared()) + } } #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] @@ -2746,6 +2770,7 @@ forward_display_to_print! { ty::PolyExistentialTraitRef<'tcx>, ty::Binder<'tcx, ty::TraitRef<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + ty::Binder<'tcx, TraitRefPrintSugared<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>, @@ -2785,15 +2810,11 @@ define_print! { ty::PredicateKind::ObjectSafe(trait_def_id) => { p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe") } - ty::PredicateKind::ClosureKind(closure_def_id, _closure_args, kind) => p!( - "the closure `", - print_value_path(closure_def_id, &[]), - write("` implements the trait `{}`", kind) - ), ty::PredicateKind::ConstEquate(c1, c2) => { p!("the constant `", print(c1), "` equals `", print(c2), "`") } ty::PredicateKind::Ambiguous => p!("ambiguous"), + ty::PredicateKind::NormalizesTo(data) => p!(print(data)), ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } } @@ -2850,6 +2871,24 @@ define_print_and_forward_display! { p!(print_def_path(self.0.def_id, self.0.args)); } + TraitRefPrintSugared<'tcx> { + if !with_no_queries() + && let Some(kind) = cx.tcx().fn_trait_kind_from_def_id(self.0.def_id) + && let ty::Tuple(args) = self.0.args.type_at(1).kind() + { + p!(write("{}", kind.as_str()), "("); + for (i, arg) in args.iter().enumerate() { + if i > 0 { + p!(", "); + } + p!(print(arg)); + } + p!(")"); + } else { + p!(print_def_path(self.0.def_id, self.0.args)); + } + } + TraitRefPrintOnlyTraitName<'tcx> { p!(print_def_path(self.0.def_id, &[])); } @@ -2898,7 +2937,7 @@ define_print_and_forward_display! { if let ty::ImplPolarity::Negative = self.polarity { p!("!"); } - p!(print(self.trait_ref.print_only_trait_path())) + p!(print(self.trait_ref.print_trait_sugared())) } ty::ProjectionPredicate<'tcx> { @@ -2907,6 +2946,12 @@ define_print_and_forward_display! { p!(print(self.term)) } + ty::NormalizesTo<'tcx> { + p!(print(self.alias), " normalizes-to "); + cx.reset_type_limit(); + p!(print(self.term)) + } + ty::Term<'tcx> { match self.unpack() { ty::TermKind::Ty(ty) => p!(print(ty)), @@ -3022,7 +3067,8 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// The implementation uses similar import discovery logic to that of 'use' suggestions. /// /// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`]. -fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { +// this is pub to be able to intra-doc-link it +pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { let mut map: FxHashMap = FxHashMap::default(); if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { @@ -3030,7 +3076,7 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { // // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` // wrapper can be used to suppress this query, in exchange for full paths being formatted. - tcx.sess.delay_good_path_bug( + tcx.sess.good_path_delayed_bug( "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging", ); } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 27e9be37fbfff..d7d9afc30e7ea 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -482,7 +482,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( // the (anonymous) type of the same closure expression. So // all of their regions should be equated. let args = relate_args_invariantly(relation, a_args, b_args)?; - Ok(Ty::new_closure(tcx, a_id, &args)) + Ok(Ty::new_closure(tcx, a_id, args)) } (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 6af68bc5dbabb..0cff6b77eb606 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -79,9 +79,9 @@ impl fmt::Debug for ty::BoundRegionKind { } } -impl fmt::Debug for ty::FreeRegion { +impl fmt::Debug for ty::LateParamRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region) + write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region) } } @@ -173,6 +173,12 @@ impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> { } } +impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term) + } +} + impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.kind()) @@ -202,34 +208,6 @@ impl<'tcx> DebugWithInfcx> for AliasTy<'tcx> { } } -impl fmt::Debug for ty::InferConst { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - InferConst::Var(var) => write!(f, "{var:?}"), - InferConst::EffectVar(var) => write!(f, "{var:?}"), - InferConst::Fresh(var) => write!(f, "Fresh({var:?})"), - } - } -} -impl<'tcx> DebugWithInfcx> for ty::InferConst { - fn fmt>>( - this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - use ty::InferConst::*; - match this.infcx.universe_of_ct(*this.data) { - None => write!(f, "{:?}", this.data), - Some(universe) => match *this.data { - Var(vid) => write!(f, "?{}_{}c", vid.index(), universe.index()), - EffectVar(vid) => write!(f, "?{}_{}e", vid.index(), universe.index()), - Fresh(_) => { - unreachable!() - } - }, - } - } -} - impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { WithInfcx::with_no_infcx(self).fmt(f) @@ -444,7 +422,7 @@ TrivialTypeTraversalImpls! { crate::ty::Placeholder, crate::ty::Placeholder, crate::ty::Placeholder, - crate::ty::FreeRegion, + crate::ty::LateParamRegion, crate::ty::InferTy, crate::ty::IntVarValue, crate::ty::adjustment::PointerCoercion, @@ -468,8 +446,9 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::ClosureKind, crate::ty::ParamConst, crate::ty::ParamTy, - interpret::Scalar, interpret::AllocId, + interpret::CtfeProvenance, + interpret::Scalar, rustc_target::abi::Size, } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 44592b10d5574..e221b4e8bec01 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -32,6 +32,7 @@ use std::fmt; use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; +use rustc_type_ir::BoundVar; use rustc_type_ir::ClauseKind as IrClauseKind; use rustc_type_ir::CollectAndApply; use rustc_type_ir::ConstKind as IrConstKind; @@ -61,9 +62,9 @@ pub struct TypeAndMut<'tcx> { #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] #[derive(HashStable)] -/// A "free" region `fr` can be interpreted as "some region +/// The parameter representation of late-bound function parameters, "some region /// at least as big as the scope `fr.scope`". -pub struct FreeRegion { +pub struct LateParamRegion { pub scope: DefId, pub bound_region: BoundRegionKind, } @@ -467,16 +468,6 @@ impl<'tcx> CoroutineArgs<'tcx> { self.split().return_ty.expect_ty() } - /// Returns the "coroutine signature", which consists of its yield - /// and return types. - /// - /// N.B., some bits of the code prefers to see this wrapped in a - /// binder, but it never contains bound regions. Probably this - /// function should be removed. - pub fn poly_sig(self) -> PolyGenSig<'tcx> { - ty::Binder::dummy(self.sig()) - } - /// Returns the "coroutine signature", which consists of its resume, yield /// and return types. pub fn sig(self) -> GenSig<'tcx> { @@ -1036,7 +1027,7 @@ impl<'tcx, T> Binder<'tcx, T> { /// risky thing to do because it's easy to get confused about /// De Bruijn indices and the like. It is usually better to /// discharge the binder using `no_bound_vars` or - /// `replace_late_bound_regions` or something like + /// `instantiate_bound_regions` or something like /// that. `skip_binder` is only valid when you are either /// extracting data that has nothing to do with bound vars, you /// are doing some sort of test that does not involve bound @@ -1245,6 +1236,28 @@ impl<'tcx> AliasTy<'tcx> { } } + /// Whether this alias type is an opaque. + pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool { + matches!(self.opt_kind(tcx), Some(ty::AliasKind::Opaque)) + } + + /// FIXME: rename `AliasTy` to `AliasTerm` and always handle + /// constants. This function can then be removed. + pub fn opt_kind(self, tcx: TyCtxt<'tcx>) -> Option { + match tcx.def_kind(self.def_id) { + DefKind::AssocTy + if let DefKind::Impl { of_trait: false } = + tcx.def_kind(tcx.parent(self.def_id)) => + { + Some(ty::Inherent) + } + DefKind::AssocTy => Some(ty::Projection), + DefKind::OpaqueTy => Some(ty::Opaque), + DefKind::TyAlias => Some(ty::Weak), + _ => None, + } + } + pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { Ty::new_alias(tcx, self.kind(tcx), self) } @@ -1329,8 +1342,6 @@ pub struct GenSig<'tcx> { pub return_ty: Ty<'tcx>, } -pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>; - /// Signature of a function type, which we have arbitrarily /// decided to use to refer to the input/output types. /// @@ -1468,15 +1479,15 @@ pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>); impl<'tcx> Region<'tcx> { #[inline] - pub fn new_early_bound( + pub fn new_early_param( tcx: TyCtxt<'tcx>, - early_bound_region: ty::EarlyBoundRegion, + early_bound_region: ty::EarlyParamRegion, ) -> Region<'tcx> { - tcx.intern_region(ty::ReEarlyBound(early_bound_region)) + tcx.intern_region(ty::ReEarlyParam(early_bound_region)) } #[inline] - pub fn new_late_bound( + pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, bound_region: ty::BoundRegion, @@ -1488,17 +1499,17 @@ impl<'tcx> Region<'tcx> { { re } else { - tcx.intern_region(ty::ReLateBound(debruijn, bound_region)) + tcx.intern_region(ty::ReBound(debruijn, bound_region)) } } #[inline] - pub fn new_free( + pub fn new_late_param( tcx: TyCtxt<'tcx>, scope: DefId, bound_region: ty::BoundRegionKind, ) -> Region<'tcx> { - tcx.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region })) + tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region })) } #[inline] @@ -1522,7 +1533,7 @@ impl<'tcx> Region<'tcx> { tcx.intern_region(ty::ReError(reported)) } - /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` to ensure it + /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` to ensure it /// gets used. #[track_caller] pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { @@ -1533,7 +1544,7 @@ impl<'tcx> Region<'tcx> { ) } - /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` with the given + /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` with the given /// `msg` to ensure it gets used. #[track_caller] pub fn new_error_with_message>( @@ -1541,7 +1552,7 @@ impl<'tcx> Region<'tcx> { span: S, msg: &'static str, ) -> Region<'tcx> { - let reported = tcx.sess.delay_span_bug(span, msg); + let reported = tcx.sess.span_delayed_bug(span, msg); Region::new_error(tcx, reported) } @@ -1549,10 +1560,10 @@ impl<'tcx> Region<'tcx> { /// to avoid the cost of the `match`. pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { match kind { - ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region), - ty::ReLateBound(debruijn, region) => Region::new_late_bound(tcx, debruijn, region), - ty::ReFree(ty::FreeRegion { scope, bound_region }) => { - Region::new_free(tcx, scope, bound_region) + ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), + ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), + ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => { + Region::new_late_param(tcx, scope, bound_region) } ty::ReStatic => tcx.lifetimes.re_static, ty::ReVar(vid) => Region::new_var(tcx, vid), @@ -1568,45 +1579,29 @@ impl<'tcx> Deref for Region<'tcx> { #[inline] fn deref(&self) -> &RegionKind<'tcx> { - &self.0.0 + self.0.0 } } #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] #[derive(HashStable)] -pub struct EarlyBoundRegion { +pub struct EarlyParamRegion { pub def_id: DefId, pub index: u32, pub name: Symbol, } -impl fmt::Debug for EarlyBoundRegion { +impl fmt::Debug for EarlyParamRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) } } -rustc_index::newtype_index! { - /// A **`const`** **v**ariable **ID**. - #[debug_format = "?{}c"] - pub struct ConstVid {} -} - -rustc_index::newtype_index! { - /// An **effect** **v**ariable **ID**. - /// - /// Handling effect infer variables happens separately from const infer variables - /// because we do not want to reuse any of the const infer machinery. If we try to - /// relate an effect variable with a normal one, we would ICE, which can catch bugs - /// where we are not correctly using the effect var for an effect param. Fallback - /// is also implemented on top of having separate effect and normal const variables. - #[debug_format = "?{}e"] - pub struct EffectVid {} -} - rustc_index::newtype_index! { /// A **region** (lifetime) **v**ariable **ID**. #[derive(HashStable)] + #[encodable] + #[orderable] #[debug_format = "'?{}"] pub struct RegionVid {} } @@ -1617,12 +1612,6 @@ impl Atom for RegionVid { } } -rustc_index::newtype_index! { - #[derive(HashStable)] - #[debug_format = "{}"] - pub struct BoundVar {} -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct BoundTy { @@ -1722,9 +1711,9 @@ impl<'tcx> Region<'tcx> { pub fn get_name(self) -> Option { if self.has_name() { match *self { - ty::ReEarlyBound(ebr) => Some(ebr.name), - ty::ReLateBound(_, br) => br.kind.get_name(), - ty::ReFree(fr) => fr.bound_region.get_name(), + ty::ReEarlyParam(ebr) => Some(ebr.name), + ty::ReBound(_, br) => br.kind.get_name(), + ty::ReLateParam(fr) => fr.bound_region.get_name(), ty::ReStatic => Some(kw::StaticLifetime), ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), _ => None, @@ -1744,9 +1733,9 @@ impl<'tcx> Region<'tcx> { /// Is this region named by the user? pub fn has_name(self) -> bool { match *self { - ty::ReEarlyBound(ebr) => ebr.has_name(), - ty::ReLateBound(_, br) => br.kind.is_named(), - ty::ReFree(fr) => fr.bound_region.is_named(), + ty::ReEarlyParam(ebr) => ebr.has_name(), + ty::ReBound(_, br) => br.kind.is_named(), + ty::ReLateParam(fr) => fr.bound_region.is_named(), ty::ReStatic => true, ty::ReVar(..) => false, ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), @@ -1771,8 +1760,8 @@ impl<'tcx> Region<'tcx> { } #[inline] - pub fn is_late_bound(self) -> bool { - matches!(*self, ty::ReLateBound(..)) + pub fn is_bound(self) -> bool { + matches!(*self, ty::ReBound(..)) } #[inline] @@ -1783,7 +1772,7 @@ impl<'tcx> Region<'tcx> { #[inline] pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { match *self { - ty::ReLateBound(debruijn, _) => debruijn >= index, + ty::ReBound(debruijn, _) => debruijn >= index, _ => false, } } @@ -1802,20 +1791,20 @@ impl<'tcx> Region<'tcx> { flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; } - ty::ReEarlyBound(..) => { + ty::ReEarlyParam(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PARAM; } - ty::ReFree { .. } => { + ty::ReLateParam { .. } => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; } ty::ReStatic => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } - ty::ReLateBound(..) => { - flags = flags | TypeFlags::HAS_RE_LATE_BOUND; + ty::ReBound(..) => { + flags = flags | TypeFlags::HAS_RE_BOUND; } ty::ReErased => { flags = flags | TypeFlags::HAS_RE_ERASED; @@ -1851,22 +1840,28 @@ impl<'tcx> Region<'tcx> { /// function might return the `DefId` of a closure. pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { match *self { - ty::ReEarlyBound(br) => tcx.parent(br.def_id), - ty::ReFree(fr) => fr.scope, + ty::ReEarlyParam(br) => tcx.parent(br.def_id), + ty::ReLateParam(fr) => fr.scope, _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), } } /// True for free regions other than `'static`. - pub fn is_free(self) -> bool { - matches!(*self, ty::ReEarlyBound(_) | ty::ReFree(_)) + pub fn is_param(self) -> bool { + matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_)) } - /// True if `self` is a free region or static. - pub fn is_free_or_static(self) -> bool { + /// True for free region in the current context. + /// + /// This is the case for `'static` and param regions. + pub fn is_free(self) -> bool { match *self { - ty::ReStatic => true, - _ => self.is_free(), + ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true, + ty::ReVar(..) + | ty::RePlaceholder(..) + | ty::ReBound(..) + | ty::ReErased + | ty::ReError(..) => false, } } @@ -1990,13 +1985,13 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Error(reported)) } - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. + /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` to ensure it gets used. #[track_caller] pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported") } - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to + /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg` to /// ensure it gets used. #[track_caller] pub fn new_error_with_message>( @@ -2004,7 +1999,7 @@ impl<'tcx> Ty<'tcx> { span: S, msg: impl Into, ) -> Ty<'tcx> { - let reported = tcx.sess.delay_span_bug(span, msg); + let reported = tcx.sess.span_delayed_bug(span, msg); Ty::new(tcx, Error(reported)) } @@ -2104,7 +2099,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(&ts))) } + if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(ts))) } } pub fn new_tup_from_iter(tcx: TyCtxt<'tcx>, iter: I) -> T::Output @@ -2260,7 +2255,7 @@ impl<'tcx> Ty<'tcx> { impl<'tcx> Ty<'tcx> { #[inline(always)] pub fn kind(self) -> &'tcx TyKind<'tcx> { - &self.0.0 + self.0.0 } #[inline(always)] @@ -2271,7 +2266,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_unit(self) -> bool { match self.kind() { - Tuple(ref tys) => tys.is_empty(), + Tuple(tys) => tys.is_empty(), _ => false, } } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index e9240d1b268e6..d372c1cd60496 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -126,7 +126,7 @@ pub struct TypeckResults<'tcx> { /// fn(&'a u32) -> u32 /// ``` /// - /// Note that `'a` is not bound (it would be an `ReFree`) and + /// Note that `'a` is not bound (it would be an `ReLateParam`) and /// that the `Foo` opaque type is replaced by its hidden type. liberated_fn_sigs: ItemLocalMap>, @@ -241,7 +241,7 @@ impl<'tcx> TypeckResults<'tcx> { /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node. pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { match *qpath { - hir::QPath::Resolved(_, ref path) => path.res, + hir::QPath::Resolved(_, path) => path.res, hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self .type_dependent_def(id) .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), @@ -391,7 +391,7 @@ impl<'tcx> TypeckResults<'tcx> { pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option { self.pat_binding_modes().get(id).copied().or_else(|| { - s.delay_span_bug(sp, "missing binding mode"); + s.span_delayed_bug(sp, "missing binding mode"); None }) } @@ -578,6 +578,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> { rustc_index::newtype_index! { #[derive(HashStable)] + #[encodable] #[debug_format = "UserType({})"] pub struct UserTypeAnnotationIndex { const START_INDEX = 0; @@ -638,7 +639,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { }, GenericArgKind::Lifetime(r) => match *r { - ty::ReLateBound(debruijn, br) => { + ty::ReBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); cvar == br.var diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a251518d14575..52c3529d2b4aa 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -35,12 +35,14 @@ pub struct Discr<'tcx> { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum CheckRegions { No, - /// Only permit early bound regions. This is useful for Adts which - /// can never have late bound regions. - OnlyEarlyBound, - /// Permit both late bound and early bound regions. Use this for functions, - /// which frequently have late bound regions. - Bound, + /// Only permit parameter regions. This should be used + /// for everything apart from functions, which may use + /// `ReBound` to represent late-bound regions. + OnlyParam, + /// Check region parameters from a function definition. + /// Allows `ReEarlyParam` and `ReBound` to handle early + /// and late-bound region parameters. + FromFunction, } #[derive(Copy, Clone, Debug)] @@ -359,7 +361,7 @@ impl<'tcx> TyCtxt<'tcx> { let Some(item_id) = self.associated_item_def_ids(impl_did).first() else { self.sess - .delay_span_bug(self.def_span(impl_did), "Drop impl without drop function"); + .span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function"); return; }; @@ -431,7 +433,7 @@ impl<'tcx> TyCtxt<'tcx> { .filter(|&(_, k)| { match k.unpack() { GenericArgKind::Lifetime(region) => match region.kind() { - ty::ReEarlyBound(ref ebr) => { + ty::ReEarlyParam(ref ebr) => { !impl_generics.region_param(ebr, self).pure_wrt_drop } // Error: not a region param @@ -468,17 +470,17 @@ impl<'tcx> TyCtxt<'tcx> { for arg in args { match arg.unpack() { GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) { - (CheckRegions::Bound, ty::ReLateBound(di, reg)) => { + (CheckRegions::FromFunction, ty::ReBound(di, reg)) => { if !seen_late.insert((di, reg)) { return Err(NotUniqueParam::DuplicateParam(lt.into())); } } - (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, ty::ReEarlyBound(p)) => { + (CheckRegions::OnlyParam | CheckRegions::FromFunction, ty::ReEarlyParam(p)) => { if !seen.insert(p.index) { return Err(NotUniqueParam::DuplicateParam(lt.into())); } } - (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, _) => { + (CheckRegions::OnlyParam | CheckRegions::FromFunction, _) => { return Err(NotUniqueParam::NotParam(lt.into())); } (CheckRegions::No, _) => {} @@ -548,16 +550,13 @@ impl<'tcx> TyCtxt<'tcx> { /// those are not yet phased out). The parent of the closure's /// `DefId` will also be the context where it appears. pub fn is_closure(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Coroutine) + matches!(self.def_kind(def_id), DefKind::Closure) } /// Returns `true` if `def_id` refers to a definition that does not have its own /// type-checking context, i.e. closure, coroutine or inline const. pub fn is_typeck_child(self, def_id: DefId) -> bool { - matches!( - self.def_kind(def_id), - DefKind::Closure | DefKind::Coroutine | DefKind::InlineConst - ) + matches!(self.def_kind(def_id), DefKind::Closure | DefKind::InlineConst) } /// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`). @@ -699,22 +698,6 @@ impl<'tcx> TyCtxt<'tcx> { .map(|decl| ty::EarlyBinder::bind(decl.ty)) } - /// Normalizes all opaque types in the given value, replacing them - /// with their underlying types. - pub fn expand_opaque_types(self, val: Ty<'tcx>) -> Ty<'tcx> { - let mut visitor = OpaqueTypeExpander { - seen_opaque_tys: FxHashSet::default(), - expanded_cache: FxHashMap::default(), - primary_def_id: None, - found_recursion: false, - found_any_recursion: false, - check_recursion: false, - expand_coroutines: false, - tcx: self, - }; - val.fold_with(&mut visitor) - } - /// Expands the given impl trait type, stopping if the type is recursive. #[instrument(skip(self), level = "debug", ret)] pub fn try_expand_impl_trait_type( @@ -746,11 +729,13 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str { match def_kind { DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method", - DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() { - rustc_hir::CoroutineKind::Async(..) => "async closure", - rustc_hir::CoroutineKind::Coroutine => "coroutine", - rustc_hir::CoroutineKind::Gen(..) => "gen closure", - }, + DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { + match coroutine_kind { + rustc_hir::CoroutineKind::Async(..) => "async closure", + rustc_hir::CoroutineKind::Coroutine => "coroutine", + rustc_hir::CoroutineKind::Gen(..) => "gen closure", + } + } _ => def_kind.descr(def_id), } } @@ -764,11 +749,13 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str { match def_kind { DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a", - DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() { - rustc_hir::CoroutineKind::Async(..) => "an", - rustc_hir::CoroutineKind::Coroutine => "a", - rustc_hir::CoroutineKind::Gen(..) => "a", - }, + DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { + match coroutine_kind { + rustc_hir::CoroutineKind::Async(..) => "an", + rustc_hir::CoroutineKind::Coroutine => "a", + rustc_hir::CoroutineKind::Gen(..) => "a", + } + } _ => def_kind.article(), } } @@ -790,7 +777,58 @@ impl<'tcx> TyCtxt<'tcx> { // If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator). // Treat that kind of crate as "indirect", since it's an implementation detail of // the language. - || self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct()) + || self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct()) + } + + pub fn expected_const_effect_param_for_body(self, def_id: LocalDefId) -> ty::Const<'tcx> { + // FIXME(effects): This is suspicious and should probably not be done, + // especially now that we enforce host effects and then properly handle + // effect vars during fallback. + let mut host_always_on = + !self.features().effects || self.sess.opts.unstable_opts.unleash_the_miri_inside_of_you; + + // Compute the constness required by the context. + let const_context = self.hir().body_const_context(def_id); + + let kind = self.def_kind(def_id); + debug_assert_ne!(kind, DefKind::ConstParam); + + if self.has_attr(def_id, sym::rustc_do_not_const_check) { + trace!("do not const check this context"); + host_always_on = true; + } + + match const_context { + _ if host_always_on => self.consts.true_, + Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => { + self.consts.false_ + } + Some(hir::ConstContext::ConstFn) => { + let host_idx = self + .generics_of(def_id) + .host_effect_index + .expect("ConstContext::Maybe must have host effect param"); + ty::GenericArgs::identity_for_item(self, def_id).const_at(host_idx) + } + None => self.consts.true_, + } + } + + /// Constructs generic args for an item, optionally appending a const effect param type + pub fn with_opt_const_effect_param( + self, + caller_def_id: LocalDefId, + callee_def_id: DefId, + args: impl IntoIterator>>, + ) -> ty::GenericArgsRef<'tcx> { + let generics = self.generics_of(callee_def_id); + assert_eq!(generics.parent, None); + + let opt_const_param = generics.host_effect_index.is_some().then(|| { + ty::GenericArg::from(self.expected_const_effect_param_for_body(caller_def_id)) + }); + + self.mk_args_from_iter(args.into_iter().map(|arg| arg.into()).chain(opt_const_param)) } } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index ab0999b3f197f..e1ce941256c95 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -1,4 +1,4 @@ -use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; +use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags}; use rustc_errors::ErrorGuaranteed; use rustc_data_structures::fx::FxHashSet; @@ -111,16 +111,16 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> { } /// True if there are any late-bound regions - fn has_late_bound_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) + fn has_bound_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_BOUND) } /// True if there are any late-bound non-region variables - fn has_non_region_late_bound(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) + fn has_non_region_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND) } - /// True if there are any late-bound variables - fn has_late_bound_vars(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND) + /// True if there are any bound variables + fn has_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS) } /// Indicates whether this value still has parameters/placeholders/inference variables @@ -204,7 +204,7 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { + ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::Continue(()) } _ => { @@ -337,7 +337,7 @@ impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { - ty::ReLateBound(index, br) if index == self.binder_index => { + ty::ReBound(index, br) if index == self.binder_index => { if self.bound_vars.len() <= br.var.as_usize() { bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars); } @@ -440,16 +440,15 @@ impl<'tcx> TypeVisitor> for HasEscapingVarsVisitor { } fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { - // we don't have a `visit_infer_const` callback, so we have to - // hook in here to catch this case (annoying...), but - // otherwise we do want to remember to visit the rest of the - // const, as it has types/regions embedded in a lot of other - // places. - match ct.kind() { - ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => { - ControlFlow::Break(FoundEscapingVars) - } - _ => ct.super_visit_with(self), + // If the outer-exclusive-binder is *strictly greater* than + // `outer_index`, that means that `ct` contains some content + // bound at `outer_index` or above (because + // `outer_exclusive_binder` is always 1 higher than the + // content in `t`). Therefore, `t` has some escaping vars. + if ct.outer_exclusive_binder() > self.outer_index { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::Continue(()) } } @@ -494,15 +493,11 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow { - // If we're looking for any of the HAS_*_LATE_BOUND flags, we need to - // additionally consider the bound vars on the binder itself, even if - // the contents of a the binder (e.g. a `TraitRef`) doesn't reference - // the bound vars. - if self.flags.intersects(TypeFlags::HAS_LATE_BOUND) { - let bound_var_flags = FlagComputation::bound_var_flags(t.bound_vars()); - if bound_var_flags.flags.intersects(self.flags) { - return ControlFlow::Break(FoundFlags); - } + // If we're looking for the HAS_BINDER_VARS flag, check if the + // binder has vars. This won't be present in the binder's bound + // value, so we need to check here too. + if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() { + return ControlFlow::Break(FoundFlags); } t.super_visit_with(self) @@ -533,9 +528,7 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { #[inline] fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { // Note: no `super_visit_with` call. - let flags = FlagComputation::for_const(c); - trace!(r.flags=?flags); - if flags.intersects(self.flags) { + if c.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { ControlFlow::Continue(()) @@ -617,7 +610,7 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - if let ty::ReLateBound(debruijn, br) = *r { + if let ty::ReBound(debruijn, br) = *r { if debruijn == self.current_index { self.regions.insert(br.kind); } diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs index 634ed5ec54ba4..21c1a93fde818 100644 --- a/compiler/rustc_middle/src/util/bug.rs +++ b/compiler/rustc_middle/src/util/bug.rs @@ -38,16 +38,16 @@ fn opt_span_bug_fmt>( }) } -/// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a -/// `delay_span_bug`, so what is the point of this? It exists to help us test `delay_span_bug`'s +/// A query to trigger a `span_delayed_bug`. Clearly, if one has a `tcx` one can already trigger a +/// `span_delayed_bug`, so what is the point of this? It exists to help us test `span_delayed_bug`'s /// interactions with the query system and incremental. -pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) { - tcx.sess.delay_span_bug( +pub fn trigger_span_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) { + tcx.sess.span_delayed_bug( tcx.def_span(key), - "delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)]", + "delayed span bug triggered by #[rustc_error(span_delayed_bug_from_inside_query)]", ); } pub fn provide(providers: &mut crate::query::Providers) { - *providers = crate::query::Providers { trigger_delay_span_bug, ..*providers }; + *providers = crate::query::Providers { trigger_span_delayed_bug, ..*providers }; } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index f30993c9a694d..8ccd3c1aba0cc 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -114,12 +114,11 @@ impl<'tcx> Value> for ty::EarlyBinder> } impl<'tcx, T> Value> for Result> { - fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { + fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self { // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really, // tcx.arena.alloc is pretty much equal to leaking). - // FIXME: `Cycle` should carry the ErrorGuaranteed - Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle))) + Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle(guar)))) } } @@ -155,7 +154,7 @@ pub fn recursive_type_error( let (_, field_id) = item_and_field_ids[i]; let (next_item_id, _) = item_and_field_ids[(i + 1) % cycle_len]; // Find the span(s) that contain the next item in the cycle - let hir_id = tcx.hir().local_def_id_to_hir_id(field_id); + let hir_id = tcx.local_def_id_to_hir_id(field_id); let hir::Node::Field(field) = tcx.hir().get(hir_id) else { bug!("expected field") }; let mut found = Vec::new(); find_item_ty_spans(tcx, field.ty, next_item_id, &mut found, representable_ids); diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 6dceacd75a543..db54223405230 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -17,7 +17,6 @@ rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 563851f712c66..c8d6c2114e9eb 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -30,12 +30,32 @@ mir_build_borrow_of_moved_value = borrow of moved value mir_build_call_to_fn_with_requires_unsafe = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block - .note = can only be called if the required target features are available + .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features} + .note = the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]` .label = call to function with `#[target_feature]` mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block - .note = can only be called if the required target features are available + .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features} + .note = the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]` .label = call to function with `#[target_feature]` mir_build_call_to_unsafe_fn_requires_unsafe = @@ -247,7 +267,7 @@ mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpo mir_build_pattern_not_covered = refutable pattern in {$origin} .pattern_ty = the matched value is of type `{$pattern_ty}` -mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future @@ -320,6 +340,7 @@ mir_build_unreachable_pattern = unreachable pattern .label = unreachable pattern .catchall_label = matches any value +mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe = @@ -329,7 +350,17 @@ mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_uns mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) - .note = can only be called if the required target features are available + .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features} + .note = the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]` .label = call to function with `#[target_feature]` mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe = @@ -386,3 +417,5 @@ mir_build_unused_unsafe = unnecessary `unsafe` block mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block mir_build_variant_defined_here = not covered + +mir_build_wrap_suggestion = consider wrapping the function body in an unsafe block diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index ab4cd24881f6a..58295b3975568 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -31,7 +31,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, block, span, - &stmts, + stmts, expr, safety_mode, region_scope, @@ -42,7 +42,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, block, span, - &stmts, + stmts, expr, safety_mode, region_scope, @@ -312,7 +312,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, Some((None, initializer_span)), ); - this.expr_into_pattern(block, &pattern, init) + this.expr_into_pattern(block, pattern, init) // irrefutable pattern }) }, diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 3de2f45ad9a83..8c68a58d4062d 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -88,7 +88,7 @@ pub(super) fn build_custom_mir<'tcx>( }; let res: PResult<_> = try { - pctxt.parse_args(¶ms)?; + pctxt.parse_args(params)?; pctxt.parse_body(expr)?; }; if let Err(err) = res { @@ -162,6 +162,19 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { expected: expected.to_string(), } } + + fn stmt_error(&self, stmt: StmtId, expected: &'static str) -> ParseError { + let stmt = &self.thir[stmt]; + let span = match stmt.kind { + StmtKind::Expr { expr, .. } => self.thir[expr].span, + StmtKind::Let { span, .. } => span, + }; + ParseError { + span, + item_description: format!("{:?}", stmt.kind), + expected: expected.to_string(), + } + } } type PResult = Result; diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index e2ab2cb90c72f..a6f9caada2d19 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -27,10 +27,13 @@ macro_rules! parse_by_kind { $expr_name:pat, $expected:literal, $( - @call($name:literal, $args:ident) => $call_expr:expr, + @call($name:ident, $args:ident) => $call_expr:expr, )* $( - $pat:pat => $expr:expr, + @variant($adt:ident, $variant:ident) => $variant_expr:expr, + )* + $( + $pat:pat $(if $guard:expr)? => $expr:expr, )* ) => {{ let expr_id = $self.preparse($expr_id); @@ -42,14 +45,20 @@ macro_rules! parse_by_kind { ExprKind::Call { ty, fun: _, args: $args, .. } if { match ty.kind() { ty::FnDef(did, _) => { - $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did) + $self.tcx.is_diagnostic_item(rustc_span::sym::$name, *did) } _ => false, } } => $call_expr, )* $( - $pat => $expr, + ExprKind::Adt(box AdtExpr { adt_def, variant_index, .. }) if { + $self.tcx.is_diagnostic_item(rustc_span::sym::$adt, adt_def.did()) && + adt_def.variants()[*variant_index].name == rustc_span::sym::$variant + } => $variant_expr, + )* + $( + $pat $(if $guard)? => $expr, )* #[allow(unreachable_patterns)] _ => return Err($self.expr_error(expr_id, $expected)) @@ -172,7 +181,8 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ExprKind::Block { block } => &self.thir[*block].stmts, ); for (i, block_def) in block_defs.iter().enumerate() { - let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?; + let is_cleanup = self.body.basic_blocks_mut()[BasicBlock::from_usize(i)].is_cleanup; + let block = self.parse_block_def(self.statement_as_expr(*block_def)?, is_cleanup)?; self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block; } @@ -181,15 +191,28 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_block_decls(&mut self, stmts: impl Iterator) -> PResult<()> { for stmt in stmts { - let (var, _, _) = self.parse_let_statement(stmt)?; - let data = BasicBlockData::new(None); - let block = self.body.basic_blocks_mut().push(data); - self.block_map.insert(var, block); + self.parse_basic_block_decl(stmt)?; } - Ok(()) } + fn parse_basic_block_decl(&mut self, stmt: StmtId) -> PResult<()> { + match &self.thir[stmt].kind { + StmtKind::Let { pattern, initializer: Some(initializer), .. } => { + let (var, ..) = self.parse_var(pattern)?; + let mut data = BasicBlockData::new(None); + data.is_cleanup = parse_by_kind!(self, *initializer, _, "basic block declaration", + @variant(mir_basic_block, Normal) => false, + @variant(mir_basic_block, Cleanup) => true, + ); + let block = self.body.basic_blocks_mut().push(data); + self.block_map.insert(var, block); + Ok(()) + } + _ => Err(self.stmt_error(stmt, "let statement with an initializer")), + } + } + fn parse_local_decls(&mut self, mut stmts: impl Iterator) -> PResult<()> { let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?; self.local_map.insert(ret_var, Local::from_u32(0)); @@ -219,7 +242,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }; let span = self.thir[expr].span; let (name, operand) = parse_by_kind!(self, expr, _, "debuginfo", - @call("mir_debuginfo", args) => { + @call(mir_debuginfo, args) => { (args[0], args[1]) }, ); @@ -281,12 +304,13 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } } - fn parse_block_def(&self, expr_id: ExprId) -> PResult> { + fn parse_block_def(&self, expr_id: ExprId, is_cleanup: bool) -> PResult> { let block = parse_by_kind!(self, expr_id, _, "basic block", ExprKind::Block { block } => &self.thir[*block], ); let mut data = BasicBlockData::new(None); + data.is_cleanup = is_cleanup; for stmt_id in &*block.stmts { let stmt = self.statement_as_expr(*stmt_id)?; let span = self.thir[stmt].span; diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index fd2c57a0a6f12..4ce7f831c8711 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -13,19 +13,19 @@ use super::{parse_by_kind, PResult, ParseCtxt}; impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_statement(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, _, "statement", - @call("mir_storage_live", args) => { + @call(mir_storage_live, args) => { Ok(StatementKind::StorageLive(self.parse_local(args[0])?)) }, - @call("mir_storage_dead", args) => { + @call(mir_storage_dead, args) => { Ok(StatementKind::StorageDead(self.parse_local(args[0])?)) }, - @call("mir_deinit", args) => { + @call(mir_deinit, args) => { Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?))) }, - @call("mir_retag", args) => { + @call(mir_retag, args) => { Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?))) }, - @call("mir_set_discriminant", args) => { + @call(mir_set_discriminant, args) => { let place = self.parse_place(args[0])?; let var = self.parse_integer_literal(args[1])? as u32; Ok(StatementKind::SetDiscriminant { @@ -43,24 +43,30 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_terminator(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "terminator", - @call("mir_return", _args) => { + @call(mir_return, _args) => { Ok(TerminatorKind::Return) }, - @call("mir_goto", args) => { + @call(mir_goto, args) => { Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } ) }, - @call("mir_unreachable", _args) => { + @call(mir_unreachable, _args) => { Ok(TerminatorKind::Unreachable) }, - @call("mir_drop", args) => { + @call(mir_unwind_resume, _args) => { + Ok(TerminatorKind::UnwindResume) + }, + @call(mir_unwind_terminate, args) => { + Ok(TerminatorKind::UnwindTerminate(self.parse_unwind_terminate_reason(args[0])?)) + }, + @call(mir_drop, args) => { Ok(TerminatorKind::Drop { place: self.parse_place(args[0])?, target: self.parse_block(args[1])?, - unwind: UnwindAction::Continue, + unwind: self.parse_unwind_action(args[2])?, replace: false, }) }, - @call("mir_call", args) => { + @call(mir_call, args) => { self.parse_call(args) }, ExprKind::Match { scrutinee, arms, .. } => { @@ -70,6 +76,34 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) } + fn parse_unwind_terminate_reason(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, _, "unwind terminate reason", + @variant(mir_unwind_terminate_reason, Abi) => { + Ok(UnwindTerminateReason::Abi) + }, + @variant(mir_unwind_terminate_reason, InCleanup) => { + Ok(UnwindTerminateReason::InCleanup) + }, + ) + } + + fn parse_unwind_action(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, _, "unwind action", + @call(mir_unwind_continue, _args) => { + Ok(UnwindAction::Continue) + }, + @call(mir_unwind_unreachable, _args) => { + Ok(UnwindAction::Unreachable) + }, + @call(mir_unwind_terminate, args) => { + Ok(UnwindAction::Terminate(self.parse_unwind_terminate_reason(args[0])?)) + }, + @call(mir_unwind_cleanup, args) => { + Ok(UnwindAction::Cleanup(self.parse_block(args[0])?)) + }, + ) + } + fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult { let Some((otherwise, rest)) = arms.split_last() else { return Err(ParseError { @@ -113,6 +147,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ); let destination = self.parse_place(destination)?; let target = self.parse_block(args[1])?; + let unwind = self.parse_unwind_action(args[2])?; parse_by_kind!(self, call, _, "function call", ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => { @@ -126,7 +161,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { args, destination, target: Some(target), - unwind: UnwindAction::Continue, + unwind, call_source: if *from_hir_call { CallSource::Normal } else { CallSource::OverloadedOperator }, @@ -138,25 +173,25 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_rvalue(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "rvalue", - @call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant), - @call("mir_cast_transmute", args) => { + @call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant), + @call(mir_cast_transmute, args) => { let source = self.parse_operand(args[0])?; Ok(Rvalue::Cast(CastKind::Transmute, source, expr.ty)) }, - @call("mir_checked", args) => { + @call(mir_checked, args) => { parse_by_kind!(self, args[0], _, "binary op", ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp( *op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)) )), ) }, - @call("mir_offset", args) => { + @call(mir_offset, args) => { let ptr = self.parse_operand(args[0])?; let offset = self.parse_operand(args[1])?; Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset)))) }, - @call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)), - @call("mir_copy_for_deref", args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)), + @call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)), + @call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)), ExprKind::Borrow { borrow_kind, arg } => Ok( Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) ), @@ -206,9 +241,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_operand(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "operand", - @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move), - @call("mir_static", args) => self.parse_static(args[0]), - @call("mir_static_mut", args) => self.parse_static(args[0]), + @call(mir_move, args) => self.parse_place(args[0]).map(Operand::Move), + @call(mir_static, args) => self.parse_static(args[0]), + @call(mir_static_mut, args) => self.parse_static(args[0]), ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } @@ -229,7 +264,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> { let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place", - @call("mir_field", args) => { + @call(mir_field, args) => { let (parent, ty) = self.parse_place_inner(args[0])?; let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32); let field_ty = ty.field_ty(self.tcx, field); @@ -237,7 +272,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { let place = parent.project_deeper(&[proj], self.tcx); return Ok((place, PlaceTy::from_ty(field_ty))); }, - @call("mir_variant", args) => { + @call(mir_variant, args) => { (args[0], PlaceElem::Downcast( None, VariantIdx::from_u32(self.parse_integer_literal(args[1])? as u32) @@ -245,7 +280,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }, ExprKind::Deref { arg } => { parse_by_kind!(self, *arg, _, "does not matter", - @call("mir_make_place", args) => return self.parse_place_inner(args[0]), + @call(mir_make_place, args) => return self.parse_place_inner(args[0]), _ => (*arg, PlaceElem::Deref), ) }, diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 4ed49e787383d..3bfffa7354db0 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -114,7 +114,7 @@ fn lit_to_mir_constant<'tcx>( let width = tcx .layout_of(param_ty) .map_err(|_| { - LitToConstError::Reported(tcx.sess.delay_span_bug( + LitToConstError::Reported(tcx.sess.span_delayed_bug( DUMMY_SP, format!("couldn't compute width of literal: {:?}", lit_input.lit), )) @@ -158,7 +158,7 @@ fn lit_to_mir_constant<'tcx>( } (ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float_into_constval(*n, *fty, neg) .ok_or_else(|| { - LitToConstError::Reported(tcx.sess.delay_span_bug( + LitToConstError::Reported(tcx.sess.span_delayed_bug( DUMMY_SP, format!("couldn't parse float literal: {:?}", lit_input.lit), )) @@ -167,7 +167,7 @@ fn lit_to_mir_constant<'tcx>( (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)), (ast::LitKind::Err, _) => { return Err(LitToConstError::Reported( - tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"), + tcx.sess.span_delayed_bug(DUMMY_SP, "encountered LitKind::Err during mir build"), )); } _ => return Err(LitToConstError::TypeError), diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index c6a09f6568a5e..43e8348903ef2 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -175,7 +175,7 @@ fn to_upvars_resolved_place_builder<'tcx>( projection: &[PlaceElem<'tcx>], ) -> Option> { let Some((capture_index, capture)) = - find_capture_matching_projections(&cx.upvars, var_hir_id, &projection) + find_capture_matching_projections(&cx.upvars, var_hir_id, projection) else { let closure_span = cx.tcx.def_span(closure_def_id); if !enable_precise_capture(closure_span) { @@ -683,14 +683,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fake_borrow_deref_ty); let fake_borrow_temp = self.local_decls.push(LocalDecl::new(fake_borrow_ty, expr_span)); - let projection = tcx.mk_place_elems(&base_place.projection); + let projection = tcx.mk_place_elems(base_place.projection); self.cfg.push_assign( block, source_info, fake_borrow_temp.into(), Rvalue::Ref( tcx.lifetimes.re_erased, - BorrowKind::Shallow, + BorrowKind::Fake, Place { local: base_place.local, projection }, ), ); diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index eece8684e3601..2130dbdc033ed 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -600,10 +600,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => { // For an unsigned RHS, the shift is in-range for `rhs < bits`. // For a signed RHS, `IntToInt` cast to the equivalent unsigned - // type and do that same comparison. Because the type is the - // same size, there's no negative shift amount that ends up - // overlapping with valid ones, thus it catches negatives too. + // type and do that same comparison. + // A negative value will be *at least* 128 after the cast (that's i8::MIN), + // and 128 is an overflowing shift amount for all our currently existing types, + // so this cast can never make us miss an overflow. let (lhs_size, _) = ty.int_size_and_signed(self.tcx); + assert!(lhs_size.bits() <= 128); let rhs_ty = rhs.ty(&self.local_decls, self.tcx); let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx); @@ -625,7 +627,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This can't overflow because the largest shiftable types are 128-bit, // which fits in `u8`, the smallest possible `unsigned_ty`. - // (And `from_uint` will `bug!` if that's ever no longer true.) let lhs_bits = Operand::const_from_scalar( self.tcx, unsigned_ty, diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index a43aae6f44942..90f950d59d551 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -212,7 +212,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let scrutinee_place = unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,)); - let mut arm_candidates = self.create_match_candidates(&scrutinee_place, &arms); + let mut arm_candidates = self.create_match_candidates(&scrutinee_place, arms); let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard); let mut candidates = @@ -424,7 +424,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.source_scope = source_scope; } - this.expr_into_dest(destination, arm_block, &&this.thir[arm.body]) + this.expr_into_dest(destination, arm_block, &this.thir[arm.body]) }) }) .collect(); @@ -505,7 +505,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let binding_end = self.bind_and_guard_matched_candidate( leaf_candidate, parent_bindings, - &fake_borrow_temps, + fake_borrow_temps, scrutinee_span, arm_match_scope, schedule_drops, @@ -613,7 +613,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => { let place_builder = unpack!(block = self.lower_scrutinee(block, initializer, initializer.span)); - self.place_into_pattern(block, &irrefutable_pat, place_builder, true) + self.place_into_pattern(block, irrefutable_pat, place_builder, true) } } } @@ -625,7 +625,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { initializer: PlaceBuilder<'tcx>, set_match_place: bool, ) -> BlockAnd<()> { - let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false, self); + let mut candidate = Candidate::new(initializer.clone(), irrefutable_pat, false, self); let fake_borrow_temps = self.lower_match_tree( block, irrefutable_pat.span, @@ -700,7 +700,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { opt_match_place: Option<(Option<&Place<'tcx>>, Span)>, ) -> Option { self.visit_primary_bindings( - &pattern, + pattern, UserTypeProjections::none(), &mut |this, mutability, name, mode, var, span, ty, user_ty| { if visibility_scope.is_none() { @@ -827,6 +827,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Constant { .. } | PatKind::Range { .. } | PatKind::Wild + | PatKind::Never | PatKind::Error(_) => {} PatKind::Deref { ref subpattern } => { @@ -1843,7 +1844,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_span = expr.span; let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span)); let wildcard = Pat::wildcard_from_ty(pat.ty); - let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false, self); + let mut guard_candidate = Candidate::new(expr_place_builder.clone(), pat, false, self); let mut otherwise_candidate = Candidate::new(expr_place_builder.clone(), &wildcard, false, self); let fake_borrow_temps = self.lower_match_tree( @@ -2021,7 +2022,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let re_erased = tcx.lifetimes.re_erased; let scrutinee_source_info = self.source_info(scrutinee_span); for &(place, temp) in fake_borrows { - let borrow = Rvalue::Ref(re_erased, BorrowKind::Shallow, place); + let borrow = Rvalue::Ref(re_erased, BorrowKind::Fake, place); self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow); } diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 6a40c8d840bd5..a7f6f4873e383 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { { existing_bindings.extend_from_slice(&new_bindings); mem::swap(&mut candidate.bindings, &mut existing_bindings); - candidate.subcandidates = self.create_or_subcandidates(candidate, &place, pats); + candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats); return true; } @@ -194,6 +194,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Ok(()) } + PatKind::Never => { + // A never pattern acts like a load from the place. + // FIXME(never_patterns): load from the place + Ok(()) + } + PatKind::Constant { .. } => { // FIXME normalize patterns when possible Err(match_pair) diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index bdd4f2011ebe6..642ac9b49c8cf 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -75,6 +75,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | PatKind::Array { .. } | PatKind::Wild | PatKind::Binding { .. } + | PatKind::Never | PatKind::Leaf { .. } | PatKind::Deref { .. } | PatKind::Error(_) => self.error_simplifiable(match_pair), @@ -107,6 +108,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Slice { .. } | PatKind::Array { .. } | PatKind::Wild + | PatKind::Never | PatKind::Or { .. } | PatKind::Binding { .. } | PatKind::AscribeUserType { .. } @@ -494,7 +496,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span)); - let method = trait_method(self.tcx, eq_def_id, sym::eq, [ty, ty]); + let method = trait_method( + self.tcx, + eq_def_id, + sym::eq, + self.tcx.with_opt_const_effect_param(self.def_id, eq_def_id, [ty, ty]), + ); let bool_ty = self.tcx.types.bool; let eq_result = self.temp(bool_ty, source_info.span); @@ -736,7 +743,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // These are all binary tests. // // FIXME(#29623) we can be more clever here - let pattern_test = self.test(&match_pair); + let pattern_test = self.test(match_pair); if pattern_test.kind == test.kind { self.candidate_without_match_pair(match_pair_index, candidate); Some(0) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 58d6be50b905f..19b6496b102ef 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -451,7 +451,7 @@ fn construct_fn<'tcx>( fn_sig: ty::FnSig<'tcx>, ) -> Body<'tcx> { let span = tcx.def_span(fn_def); - let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def); + let fn_id = tcx.local_def_id_to_hir_id(fn_def); let coroutine_kind = tcx.coroutine_kind(fn_def); // The representation of thir for `-Zunpretty=thir-tree` relies on @@ -569,7 +569,7 @@ fn construct_const<'a, 'tcx>( expr: ExprId, const_ty: Ty<'tcx>, ) -> Body<'tcx> { - let hir_id = tcx.hir().local_def_id_to_hir_id(def); + let hir_id = tcx.local_def_id_to_hir_id(def); // Figure out what primary body this item has. let (span, const_ty_span) = match tcx.hir().get(hir_id) { @@ -620,29 +620,53 @@ fn construct_const<'a, 'tcx>( /// /// This is required because we may still want to run MIR passes on an item /// with type errors, but normal MIR construction can't handle that in general. -fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> { - let span = tcx.def_span(def); - let hir_id = tcx.hir().local_def_id_to_hir_id(def); - let coroutine_kind = tcx.coroutine_kind(def); - let body_owner_kind = tcx.hir().body_owner_kind(def); - - let ty = Ty::new_error(tcx, err); - let num_params = match body_owner_kind { - hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(), - hir::BodyOwnerKind::Closure => { - let ty = tcx.type_of(def).instantiate_identity(); - match ty.kind() { - ty::Closure(_, args) => 1 + args.as_closure().sig().inputs().skip_binder().len(), - ty::Coroutine(..) => 2, - _ => bug!("expected closure or coroutine, found {ty:?}"), - } +fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -> Body<'_> { + let span = tcx.def_span(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); + let coroutine_kind = tcx.coroutine_kind(def_id); + + let (inputs, output, yield_ty) = match tcx.def_kind(def_id) { + DefKind::Const + | DefKind::AssocConst + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None), + DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => { + let sig = tcx.liberate_late_bound_regions( + def_id.to_def_id(), + tcx.fn_sig(def_id).instantiate_identity(), + ); + (sig.inputs().to_vec(), sig.output(), None) + } + DefKind::Closure if coroutine_kind.is_some() => { + let coroutine_ty = tcx.type_of(def_id).instantiate_identity(); + let ty::Coroutine(_, args, _) = coroutine_ty.kind() else { bug!() }; + let args = args.as_coroutine(); + let yield_ty = args.yield_ty(); + let return_ty = args.return_ty(); + (vec![coroutine_ty, args.resume_ty()], return_ty, Some(yield_ty)) } - hir::BodyOwnerKind::Const { .. } => 0, - hir::BodyOwnerKind::Static(_) => 0, + DefKind::Closure => { + let closure_ty = tcx.type_of(def_id).instantiate_identity(); + let ty::Closure(_, args) = closure_ty.kind() else { bug!() }; + let args = args.as_closure(); + let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), args.sig()); + let self_ty = match args.kind() { + ty::ClosureKind::Fn => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty), + ty::ClosureKind::FnMut => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty), + ty::ClosureKind::FnOnce => closure_ty, + }; + ([self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), sig.output(), None) + } + dk => bug!("{:?} is not a body: {:?}", def_id, dk), }; + + let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; + let local_decls = IndexVec::from_iter( + [output].iter().chain(&inputs).map(|ty| LocalDecl::with_source_info(*ty, source_info)), + ); let mut cfg = CFG { basic_blocks: IndexVec::new() }; let mut source_scopes = IndexVec::new(); - let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1); cfg.start_new_block(); source_scopes.push(SourceScopeData { @@ -655,28 +679,24 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo safety: Safety::Safe, }), }); - let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; - // Some MIR passes will expect the number of parameters to match the - // function declaration. - for _ in 0..num_params { - local_decls.push(LocalDecl::with_source_info(ty, source_info)); - } cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); let mut body = Body::new( - MirSource::item(def.to_def_id()), + MirSource::item(def_id.to_def_id()), cfg.basic_blocks, source_scopes, local_decls, IndexVec::new(), - num_params, + inputs.len(), vec![], span, coroutine_kind, - Some(err), + Some(guar), ); - body.coroutine.as_mut().map(|gen| gen.yield_ty = Some(ty)); + + body.coroutine.as_mut().map(|gen| gen.yield_ty = yield_ty); + body } @@ -918,12 +938,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scope = self.declare_bindings( scope, expr.span, - &pat, + pat, None, Some((Some(&place), span)), ); let place_builder = PlaceBuilder::from(local); - unpack!(block = self.place_into_pattern(block, &pat, place_builder, false)); + unpack!(block = self.place_into_pattern(block, pat, place_builder, false)); } } self.source_scope = original_source_scope; @@ -934,7 +954,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.source_scope = source_scope; } - self.expr_into_dest(Place::return_place(), block, &expr) + self.expr_into_dest(Place::return_place(), block, expr) } fn set_correct_source_scope_for_arg( diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index b3d3863b5db77..993fee95895ce 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -186,6 +186,7 @@ pub(crate) enum BreakableTarget { } rustc_index::newtype_index! { + #[orderable] struct DropIdx {} } @@ -995,7 +996,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } if scope.region_scope == region_scope { - let region_scope_span = region_scope.span(self.tcx, &self.region_scope_tree); + let region_scope_span = region_scope.span(self.tcx, self.region_scope_tree); // Attribute scope exit drops to scope's closing brace. let scope_end = self.tcx.sess.source_map().end_point(region_scope_span); diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 45be501537130..1f7c6d7875b28 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,7 +1,10 @@ +use std::borrow::Cow; + use crate::build::ExprCategory; use crate::errors::*; use rustc_middle::thir::visit::{self, Visitor}; +use rustc_errors::DiagnosticArgValue; use rustc_hir as hir; use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; @@ -35,6 +38,10 @@ struct UnsafetyVisitor<'a, 'tcx> { param_env: ParamEnv<'tcx>, inside_adt: bool, warnings: &'a mut Vec, + + /// Flag to ensure that we only suggest wrapping the entire function body in + /// an unsafe block once. + suggest_unsafe_block: bool, } impl<'tcx> UnsafetyVisitor<'_, 'tcx> { @@ -95,7 +102,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { // unsafe_op_in_unsafe_fn is disallowed - kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span); + kind.emit_unsafe_op_in_unsafe_fn_lint( + self.tcx, + self.hir_context, + span, + self.suggest_unsafe_block, + ); + self.suggest_unsafe_block = false; } SafetyContext::Safe => { kind.emit_requires_unsafe_err( @@ -128,7 +141,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { // Runs all other queries that depend on THIR. self.tcx.ensure_with_value().mir_built(def); let inner_thir = &inner_thir.steal(); - let hir_context = self.tcx.hir().local_def_id_to_hir_id(def); + let hir_context = self.tcx.local_def_id_to_hir_id(def); let safety_context = mem::replace(&mut self.safety_context, SafetyContext::Safe); let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, @@ -190,7 +203,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for LayoutConstrainedPlaceVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { fn thir(&self) -> &'a Thir<'tcx> { - &self.thir + self.thir } fn visit_block(&mut self, block: &Block) { @@ -237,8 +250,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { self.requires_unsafe(pat.span, AccessToUnionField); return; // we can return here since this already requires unsafe } - // wildcard doesn't take anything + // wildcard/never don't take anything PatKind::Wild | + PatKind::Never | // these just wrap other patterns PatKind::Or { .. } | PatKind::InlineConstant { .. } | @@ -278,7 +292,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { ); }; match borrow_kind { - BorrowKind::Shallow | BorrowKind::Shared => { + BorrowKind::Fake | BorrowKind::Shared => { if !ty.is_freeze(self.tcx, self.param_env) { self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); } @@ -297,6 +311,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } PatKind::InlineConstant { def, .. } => { self.visit_inner_body(*def); + visit::walk_pat(self, pat); } _ => { visit::walk_pat(self, pat); @@ -381,20 +396,36 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { // the call requires `unsafe`. Don't check this on wasm // targets, though. For more information on wasm see the // is_like_wasm check in hir_analysis/src/collect.rs + let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; if !self.tcx.sess.target.options.is_like_wasm - && !self - .tcx - .codegen_fn_attrs(func_did) - .target_features + && !callee_features .iter() .all(|feature| self.body_target_features.contains(feature)) { - self.requires_unsafe(expr.span, CallToFunctionWith(func_did)); + let missing: Vec<_> = callee_features + .iter() + .copied() + .filter(|feature| !self.body_target_features.contains(feature)) + .collect(); + let build_enabled = self + .tcx + .sess + .target_features + .iter() + .copied() + .filter(|feature| missing.contains(feature)) + .collect(); + self.requires_unsafe( + expr.span, + CallToFunctionWith { function: func_did, missing, build_enabled }, + ); } } } ExprKind::Deref { arg } => { - if let ExprKind::StaticRef { def_id, .. } = self.thir[arg].kind { + if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) = + self.thir[arg].kind + { if self.tcx.is_mutable_static(def_id) { self.requires_unsafe(expr.span, UseOfMutableStatic); } else if self.tcx.is_foreign_item(def_id) { @@ -439,7 +470,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { if let Some((assigned_ty, assignment_span)) = self.assignment_info { if assigned_ty.needs_drop(self.tcx, self.param_env) { // This would be unsafe, but should be outright impossible since we reject such unions. - self.tcx.sess.delay_span_bug(assignment_span, format!("union fields that need dropping should be impossible: {assigned_ty}")); + self.tcx.sess.span_delayed_bug(assignment_span, format!("union fields that need dropping should be impossible: {assigned_ty}")); } } else { self.requires_unsafe(expr.span, AccessToUnionField); @@ -470,7 +501,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { visit::walk_expr(&mut visitor, expr); if visitor.found { match borrow_kind { - BorrowKind::Shallow | BorrowKind::Shared + BorrowKind::Fake | BorrowKind::Shared if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) => { self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) @@ -478,18 +509,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { BorrowKind::Mut { .. } => { self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField) } - BorrowKind::Shallow | BorrowKind::Shared => {} + BorrowKind::Fake | BorrowKind::Shared => {} } } } - ExprKind::Let { expr: expr_id, .. } => { - let let_expr = &self.thir[expr_id]; - if let ty::Adt(adt_def, _) = let_expr.ty.kind() - && adt_def.is_union() - { - self.requires_unsafe(expr.span, AccessToUnionField); - } - } _ => {} } visit::walk_expr(self, expr); @@ -521,7 +544,7 @@ struct UnusedUnsafeWarning { enclosing_unsafe: Option, } -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, PartialEq)] enum UnsafeOpKind { CallToUnsafeFunction(Option), UseOfInlineAssembly, @@ -532,7 +555,15 @@ enum UnsafeOpKind { AccessToUnionField, MutationOfLayoutConstrainedField, BorrowOfLayoutConstrainedField, - CallToFunctionWith(DefId), + CallToFunctionWith { + function: DefId, + /// Target features enabled in callee's `#[target_feature]` but missing in + /// caller's `#[target_feature]`. + missing: Vec, + /// Target features in `missing` that are enabled at compile time + /// (e.g., with `-C target-feature`). + build_enabled: Vec, + }, } use UnsafeOpKind::*; @@ -543,7 +574,22 @@ impl UnsafeOpKind { tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, + suggest_unsafe_block: bool, ) { + let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_owner = tcx.hir().owner(parent_id); + let should_suggest = parent_owner.fn_sig().is_some_and(|sig| sig.header.is_unsafe()); + let unsafe_not_inherited_note = if should_suggest { + suggest_unsafe_block.then(|| { + let body_span = tcx.hir().body(parent_owner.body_id().unwrap()).value.span; + UnsafeNotInheritedLintNote { + signature_span: tcx.def_span(parent_id.def_id), + body_span, + } + }) + } else { + None + }; // FIXME: ideally we would want to trim the def paths, but this is not // feasible with the current lint emission API (see issue #106126). match self { @@ -554,69 +600,107 @@ impl UnsafeOpKind { UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { span, function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + unsafe_not_inherited_note, }, ), CallToUnsafeFunction(None) => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span }, + UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { + span, + unsafe_not_inherited_note, + }, ), UseOfInlineAssembly => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), InitializingTypeWith => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span }, + UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), UseOfMutableStatic => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), UseOfExternStatic => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), DerefOfRawPointer => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span }, + UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), AccessToUnionField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), MutationOfLayoutConstrainedField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), - CallToFunctionWith(did) => tcx.emit_spanned_lint( + CallToFunctionWith { function, missing, build_enabled } => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { span, - function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + function: &with_no_trimmed_paths!(tcx.def_path_str(*function)), + missing_target_features: DiagnosticArgValue::StrListSepByAnd( + missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + missing_target_features_count: missing.len(), + note: if build_enabled.is_empty() { None } else { Some(()) }, + build_target_features: DiagnosticArgValue::StrListSepByAnd( + build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + build_target_features_count: build_enabled.len(), + unsafe_not_inherited_note, }, ), } @@ -772,18 +856,38 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }); } - CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => { + CallToFunctionWith { function, missing, build_enabled } + if unsafe_op_in_unsafe_fn_allowed => + { tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, + missing_target_features: DiagnosticArgValue::StrListSepByAnd( + missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + missing_target_features_count: missing.len(), + note: if build_enabled.is_empty() { None } else { Some(()) }, + build_target_features: DiagnosticArgValue::StrListSepByAnd( + build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, - function: &tcx.def_path_str(*did), + function: &tcx.def_path_str(*function), }); } - CallToFunctionWith(did) => { + CallToFunctionWith { function, missing, build_enabled } => { tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe { span, + missing_target_features: DiagnosticArgValue::StrListSepByAnd( + missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + missing_target_features_count: missing.len(), + note: if build_enabled.is_empty() { None } else { Some(()) }, + build_target_features: DiagnosticArgValue::StrListSepByAnd( + build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, - function: &tcx.def_path_str(*did), + function: &tcx.def_path_str(*function), }); } } @@ -810,7 +914,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { return; } - let hir_id = tcx.hir().local_def_id_to_hir_id(def); + let hir_id = tcx.local_def_id_to_hir_id(def); let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| { if fn_sig.header.unsafety == hir::Unsafety::Unsafe { SafetyContext::UnsafeFn @@ -831,6 +935,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { param_env: tcx.param_env(def), inside_adt: false, warnings: &mut warnings, + suggest_unsafe_block: true, }; visitor.visit_expr(&thir[expr]); diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c4eed5532ee63..8d2a559e73ce4 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,6 +2,7 @@ use crate::{ fluent_generated as fluent, thir::pattern::{deconstruct_pat::WitnessPat, MatchCheckCtxt}, }; +use rustc_errors::DiagnosticArgValue; use rustc_errors::{ error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, SubdiagnosticMessage, @@ -29,6 +30,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -37,6 +40,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -45,6 +50,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -53,6 +60,8 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -61,6 +70,8 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -69,6 +80,8 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -77,6 +90,8 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -85,6 +100,8 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -93,6 +110,8 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -100,15 +119,25 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)] -#[note] +#[help] pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features_count: usize, + #[note] + pub note: Option<()>, + pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features_count: usize, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -347,24 +376,36 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed #[derive(Diagnostic)] #[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")] -#[note] +#[help] pub struct CallToFunctionWithRequiresUnsafe<'a> { #[primary_span] #[label] pub span: Span, pub function: &'a str, + pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features_count: usize, + #[note] + pub note: Option<()>, + pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features_count: usize, #[subdiagnostic] pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] -#[note] +#[help] pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[primary_span] #[label] pub span: Span, pub function: &'a str, + pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features_count: usize, + #[note] + pub note: Option<()>, + pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features_count: usize, #[subdiagnostic] pub unsafe_not_inherited_note: Option, } @@ -376,6 +417,27 @@ pub struct UnsafeNotInheritedNote { pub span: Span, } +pub struct UnsafeNotInheritedLintNote { + pub signature_span: Span, + pub body_span: Span, +} + +impl AddToDiagnostic for UnsafeNotInheritedLintNote { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { + diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); + let body_start = self.body_span.shrink_to_lo(); + let body_end = self.body_span.shrink_to_hi(); + diag.tool_only_multipart_suggestion( + fluent::mir_build_wrap_suggestion, + vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())], + Applicability::MaybeIncorrect, + ); + } +} + #[derive(LintDiagnostic)] #[diag(mir_build_unused_unsafe)] pub struct UnusedUnsafe { diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 745c3046d22c2..8c4f0257da3ed 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -24,10 +24,7 @@ mod thir; use rustc_middle::query::Providers; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { providers.check_match = thir::pattern::check_match; diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index acf4d6bc2a071..167b65328d11a 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -52,7 +52,7 @@ fn check_recursion<'tcx>( vis.reachable_recursive_calls.sort(); let sp = tcx.def_span(def_id); - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.emit_spanned_lint( UNCONDITIONAL_RECURSION, hir_id, diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index fbb74650faaeb..240aa10ac918f 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -16,7 +16,7 @@ pub(crate) fn lit_to_const<'tcx>( let width = tcx .layout_of(param_ty) .map_err(|_| { - LitToConstError::Reported(tcx.sess.delay_span_bug( + LitToConstError::Reported(tcx.sess.span_delayed_bug( DUMMY_SP, format!("couldn't compute width of literal: {:?}", lit_input.lit), )) @@ -62,7 +62,7 @@ pub(crate) fn lit_to_const<'tcx>( (ast::LitKind::Float(n, _), ty::Float(fty)) => { let bits = parse_float_into_scalar(*n, *fty, neg) .ok_or_else(|| { - LitToConstError::Reported(tcx.sess.delay_span_bug( + LitToConstError::Reported(tcx.sess.span_delayed_bug( DUMMY_SP, format!("couldn't parse float literal: {:?}", lit_input.lit), )) @@ -73,7 +73,7 @@ pub(crate) fn lit_to_const<'tcx>( (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()), (ast::LitKind::Err, _) => { return Err(LitToConstError::Reported( - tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"), + tcx.sess.span_delayed_bug(DUMMY_SP, "encountered LitKind::Err during mir build"), )); } _ => return Err(LitToConstError::TypeError), diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index a46ad6423a037..527eadb277e10 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -51,7 +51,7 @@ impl<'tcx> Cx<'tcx> { let hir_id = stmt.hir_id; let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id); match stmt.kind { - hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { + hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr) => { let stmt = Stmt { kind: StmtKind::Expr { scope: region::Scope { @@ -68,7 +68,7 @@ impl<'tcx> Cx<'tcx> { // ignore for purposes of the MIR None } - hir::StmtKind::Local(ref local) => { + hir::StmtKind::Local(local) => { let remainder_scope = region::Scope { id: block_id, data: region::ScopeData::Remainder(region::FirstStatementIndex::new( diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index dfd39b512e241..9759c72bf580d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -192,10 +192,10 @@ impl<'tcx> Cx<'tcx> { cast: PointerCoercion::ArrayToPointer, } } else if let hir::ExprKind::Path(ref qpath) = source.kind - && let res = self.typeck_results().qpath_res(qpath, source.hir_id) - && let ty = self.typeck_results().node_type(source.hir_id) - && let ty::Adt(adt_def, args) = ty.kind() - && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res + && let res = self.typeck_results().qpath_res(qpath, source.hir_id) + && let ty = self.typeck_results().node_type(source.hir_id) + && let ty::Adt(adt_def, args) = ty.kind() + && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res { // Check whether this is casting an enum variant discriminant. // To prevent cycles, we refer to the discriminant initializer, @@ -261,7 +261,7 @@ impl<'tcx> Cx<'tcx> { let kind = match expr.kind { // Here comes the interesting stuff: - hir::ExprKind::MethodCall(segment, receiver, ref args, fn_span) => { + hir::ExprKind::MethodCall(segment, receiver, args, fn_span) => { // Rewrite a.b(c) into UFCS form like Trait::b(a, c) let expr = self.method_callee(expr, segment.ident.span, None); info!("Using method span: {:?}", expr.span); @@ -278,7 +278,7 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::Call(ref fun, ref args) => { + hir::ExprKind::Call(fun, ref args) => { if self.typeck_results().is_method_call(expr) { // The callee is something implementing Fn, FnMut, or FnOnce. // Find the actual method implementation being called and @@ -346,7 +346,7 @@ impl<'tcx> Cx<'tcx> { && let Some(adt_def) = expr_ty.ty_adt_def() { match qpath { - hir::QPath::Resolved(_, ref path) => match path.res { + hir::QPath::Resolved(_, path) => match path.res { Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => { Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))) } @@ -407,21 +407,21 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => { + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, arg) => { ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) } } - hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { + hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, arg) => { ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) } } - hir::ExprKind::Block(ref blk, _) => ExprKind::Block { block: self.mirror_block(blk) }, + hir::ExprKind::Block(blk, _) => ExprKind::Block { block: self.mirror_block(blk) }, - hir::ExprKind::Assign(ref lhs, ref rhs, _) => { + hir::ExprKind::Assign(lhs, rhs, _) => { ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) } } - hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { + hir::ExprKind::AssignOp(op, lhs, rhs) => { if self.typeck_results().is_method_call(expr) { let lhs = self.mirror_expr(lhs); let rhs = self.mirror_expr(rhs); @@ -435,9 +435,9 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::Lit(ref lit) => ExprKind::Literal { lit, neg: false }, + hir::ExprKind::Lit(lit) => ExprKind::Literal { lit, neg: false }, - hir::ExprKind::Binary(op, ref lhs, ref rhs) => { + hir::ExprKind::Binary(op, lhs, rhs) => { if self.typeck_results().is_method_call(expr) { let lhs = self.mirror_expr(lhs); let rhs = self.mirror_expr(rhs); @@ -466,7 +466,7 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::Index(ref lhs, ref index, brackets_span) => { + hir::ExprKind::Index(lhs, index, brackets_span) => { if self.typeck_results().is_method_call(expr) { let lhs = self.mirror_expr(lhs); let index = self.mirror_expr(index); @@ -482,7 +482,7 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => { + hir::ExprKind::Unary(hir::UnOp::Deref, arg) => { if self.typeck_results().is_method_call(expr) { let arg = self.mirror_expr(arg); self.overloaded_place(expr, expr_ty, None, Box::new([arg]), expr.span) @@ -491,7 +491,7 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => { + hir::ExprKind::Unary(hir::UnOp::Not, arg) => { if self.typeck_results().is_method_call(expr) { let arg = self.mirror_expr(arg); self.overloaded_operator(expr, Box::new([arg])) @@ -500,18 +500,18 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => { + hir::ExprKind::Unary(hir::UnOp::Neg, arg) => { if self.typeck_results().is_method_call(expr) { let arg = self.mirror_expr(arg); self.overloaded_operator(expr, Box::new([arg])) - } else if let hir::ExprKind::Lit(ref lit) = arg.kind { + } else if let hir::ExprKind::Lit(lit) = arg.kind { ExprKind::Literal { lit, neg: true } } else { ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr(arg) } } } - hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() { + hir::ExprKind::Struct(qpath, fields, ref base) => match expr_ty.kind() { ty::Adt(adt, args) => match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { let user_provided_types = self.typeck_results().user_provided_types(); @@ -614,13 +614,13 @@ impl<'tcx> Cx<'tcx> { self.convert_path_expr(expr, res) } - hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr { + hir::ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr { template: asm.template, operands: asm .operands .iter() .map(|(op, _op_sp)| match *op { - hir::InlineAsmOperand::In { reg, ref expr } => { + hir::InlineAsmOperand::In { reg, expr } => { InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) } } hir::InlineAsmOperand::Out { reg, late, ref expr } => { @@ -630,30 +630,35 @@ impl<'tcx> Cx<'tcx> { expr: expr.map(|expr| self.mirror_expr(expr)), } } - hir::InlineAsmOperand::InOut { reg, late, ref expr } => { + hir::InlineAsmOperand::InOut { reg, late, expr } => { InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) } } - hir::InlineAsmOperand::SplitInOut { - reg, - late, - ref in_expr, - ref out_expr, - } => InlineAsmOperand::SplitInOut { - reg, - late, - in_expr: self.mirror_expr(in_expr), - out_expr: out_expr.map(|expr| self.mirror_expr(expr)), - }, + hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, ref out_expr } => { + InlineAsmOperand::SplitInOut { + reg, + late, + in_expr: self.mirror_expr(in_expr), + out_expr: out_expr.map(|expr| self.mirror_expr(expr)), + } + } hir::InlineAsmOperand::Const { ref anon_const } => { - let value = - mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env); + let value = mir::Const::identity_unevaluated( + tcx, + anon_const.def_id.to_def_id(), + ) + .instantiate_identity() + .normalize(tcx, self.param_env); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::Const { value, span } } hir::InlineAsmOperand::SymFn { ref anon_const } => { - let value = - mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env); + let value = mir::Const::identity_unevaluated( + tcx, + anon_const.def_id.to_def_id(), + ) + .instantiate_identity() + .normalize(tcx, self.param_env); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::SymFn { value, span } @@ -686,7 +691,7 @@ impl<'tcx> Cx<'tcx> { ExprKind::ConstBlock { did, args } } // Now comes the rote stuff: - hir::ExprKind::Repeat(ref v, _) => { + hir::ExprKind::Repeat(v, _) => { let ty = self.typeck_results().expr_ty(expr); let ty::Array(_, count) = ty.kind() else { span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty); @@ -722,12 +727,12 @@ impl<'tcx> Cx<'tcx> { then: self.mirror_expr(then), else_opt: else_opt.map(|el| self.mirror_expr(el)), }, - hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { + hir::ExprKind::Match(discr, arms, _) => ExprKind::Match { scrutinee: self.mirror_expr(discr), scrutinee_hir_id: discr.hir_id, arms: arms.iter().map(|a| self.convert_arm(a)).collect(), }, - hir::ExprKind::Loop(ref body, ..) => { + hir::ExprKind::Loop(body, ..) => { let block_ty = self.typeck_results().node_type(body.hir_id); let temp_lifetime = self .rvalue_scopes @@ -741,12 +746,12 @@ impl<'tcx> Cx<'tcx> { }); ExprKind::Loop { body } } - hir::ExprKind::Field(ref source, ..) => ExprKind::Field { + hir::ExprKind::Field(source, ..) => ExprKind::Field { lhs: self.mirror_expr(source), variant_index: FIRST_VARIANT, name: self.typeck_results.field_index(expr.hir_id), }, - hir::ExprKind::Cast(ref source, ref cast_ty) => { + hir::ExprKind::Cast(source, cast_ty) => { // Check for a user-given type annotation on this `cast` let user_provided_types = self.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(cast_ty.hir_id); @@ -756,7 +761,7 @@ impl<'tcx> Cx<'tcx> { expr, cast_ty.hir_id, user_ty, ); - let cast = self.mirror_expr_cast(*source, temp_lifetime, expr.span); + let cast = self.mirror_expr_cast(source, temp_lifetime, expr.span); if let Some(user_ty) = user_ty { // NOTE: Creating a new Expr and wrapping a Cast inside of it may be @@ -777,7 +782,7 @@ impl<'tcx> Cx<'tcx> { cast } } - hir::ExprKind::Type(ref source, ref ty) => { + hir::ExprKind::Type(source, ty) => { let user_provided_types = self.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(ty.hir_id).copied().map(Box::new); debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty); @@ -788,15 +793,11 @@ impl<'tcx> Cx<'tcx> { ExprKind::ValueTypeAscription { source: mirrored, user_ty } } } - hir::ExprKind::DropTemps(ref source) => { - ExprKind::Use { source: self.mirror_expr(source) } - } - hir::ExprKind::Array(ref fields) => { - ExprKind::Array { fields: self.mirror_exprs(fields) } - } - hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) }, + hir::ExprKind::DropTemps(source) => ExprKind::Use { source: self.mirror_expr(source) }, + hir::ExprKind::Array(fields) => ExprKind::Array { fields: self.mirror_exprs(fields) }, + hir::ExprKind::Tup(fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) }, - hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) }, + hir::ExprKind::Yield(v, _) => ExprKind::Yield { value: self.mirror_expr(v) }, hir::ExprKind::Err(_) => unreachable!(), }; @@ -870,10 +871,10 @@ impl<'tcx> Cx<'tcx> { fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId { let arm = Arm { - pattern: self.pattern_from_hir(&arm.pat), + pattern: self.pattern_from_hir(arm.pat), guard: arm.guard.as_ref().map(|g| match g { - hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)), - hir::Guard::IfLet(ref l) => { + hir::Guard::If(e) => Guard::If(self.mirror_expr(e)), + hir::Guard::IfLet(l) => { Guard::IfLet(self.pattern_from_hir(l.pat), self.mirror_expr(l.init)) } }), @@ -898,7 +899,7 @@ impl<'tcx> Cx<'tcx> { } Res::Def(DefKind::ConstParam, def_id) => { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = self.tcx.local_def_id_to_hir_id(def_id.expect_local()); let generics = self.tcx.generics_of(hir_id.owner); let index = generics.param_def_id_to_index[&def_id]; let name = self.tcx.hir().name(hir_id); diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index b6adb383fa6b2..4eba7103c0cda 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -27,17 +27,17 @@ pub(crate) fn thir_body( if let Some(reported) = cx.typeck_results.tainted_by_errors { return Err(reported); } - let expr = cx.mirror_expr(&body.value); + let expr = cx.mirror_expr(body.value); - let owner_id = hir.local_def_id_to_hir_id(owner_def); - if let Some(ref fn_decl) = hir.fn_decl_by_hir_id(owner_id) { + let owner_id = tcx.local_def_id_to_hir_id(owner_def); + if let Some(fn_decl) = hir.fn_decl_by_hir_id(owner_id) { let closure_env_param = cx.closure_env_param(owner_def, owner_id); let explicit_params = cx.explicit_params(owner_id, fn_decl, body); cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect(); // The resume argument may be missing, in that case we need to provide it here. // It will always be `()` in this case. - if tcx.def_kind(owner_def) == DefKind::Coroutine && body.params.is_empty() { + if tcx.is_coroutine(owner_def.to_def_id()) && body.params.is_empty() { cx.thir.params.push(Param { ty: Ty::new_unit(tcx), pat: None, @@ -72,7 +72,7 @@ impl<'tcx> Cx<'tcx> { fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Cx<'tcx> { let typeck_results = tcx.typeck(def); let hir = tcx.hir(); - let hir_id = hir.local_def_id_to_hir_id(def); + let hir_id = tcx.local_def_id_to_hir_id(def); let body_type = if hir.body_owner_kind(def).is_fn_or_closure() { // fetch the fully liberated fn signature (that is, all bound @@ -119,6 +119,17 @@ impl<'tcx> Cx<'tcx> { fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option> { match self.tcx.def_kind(owner_def) { + DefKind::Closure if self.tcx.is_coroutine(owner_def.to_def_id()) => { + let coroutine_ty = self.typeck_results.node_type(owner_id); + let coroutine_param = Param { + ty: coroutine_ty, + pat: None, + ty_span: None, + self_kind: None, + hir_id: None, + }; + Some(coroutine_param) + } DefKind::Closure => { let closure_ty = self.typeck_results.node_type(owner_id); @@ -132,10 +143,10 @@ impl<'tcx> Cx<'tcx> { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv, }; - let env_region = ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br); + let env_region = ty::Region::new_bound(self.tcx, ty::INNERMOST, br); let closure_env_ty = self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap(); - let liberated_closure_env_ty = self.tcx.erase_late_bound_regions( + let liberated_closure_env_ty = self.tcx.instantiate_bound_regions_with_erased( ty::Binder::bind_with_vars(closure_env_ty, bound_vars), ); let env_param = Param { @@ -148,17 +159,6 @@ impl<'tcx> Cx<'tcx> { Some(env_param) } - DefKind::Coroutine => { - let coroutine_ty = self.typeck_results.node_type(owner_id); - let coroutine_param = Param { - ty: coroutine_ty, - pat: None, - ty_span: None, - self_kind: None, - hir_id: None, - }; - Some(coroutine_param) - } _ => None, } } 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 8c3d09c19a15a..b72b9da21b7d1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -33,7 +33,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err tcx, thir: &*thir, param_env: tcx.param_env(def_id), - lint_level: tcx.hir().local_def_id_to_hir_id(def_id), + lint_level: tcx.local_def_id_to_hir_id(def_id), let_source: LetSource::None, pattern_arena: &pattern_arena, error: Ok(()), @@ -279,8 +279,10 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { } else { // Check the pattern for some things unrelated to exhaustiveness. let refutable = if cx.refutable { Refutable } else { Irrefutable }; - pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat)); - pat.walk_always(|pat| check_for_bindings_named_same_as_variants(self, pat, refutable)); + pat.walk_always(|pat| { + check_borrow_conflicts_in_at_patterns(self, pat); + check_for_bindings_named_same_as_variants(self, pat, refutable); + }); Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pat))) } } @@ -289,6 +291,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { &self, refutability: RefutableFlag, match_span: Option, + scrut_span: Span, ) -> MatchCheckCtxt<'p, 'tcx> { let refutable = match refutability { Irrefutable => false, @@ -298,8 +301,10 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { tcx: self.tcx, param_env: self.param_env, module: self.tcx.parent_module(self.lint_level).to_def_id(), - pattern_arena: &self.pattern_arena, + pattern_arena: self.pattern_arena, + match_lint_level: self.lint_level, match_span, + scrut_span, refutable, } } @@ -330,7 +335,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { source: hir::MatchSource, expr_span: Span, ) { - let cx = self.new_cx(Refutable, Some(expr_span)); + let scrut = &self.thir[scrut]; + let cx = self.new_cx(Refutable, Some(expr_span), scrut.span); let mut tarms = Vec::with_capacity(arms.len()); for &arm in arms { @@ -346,9 +352,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { } } - let scrut = &self.thir[scrut]; let scrut_ty = scrut.ty; - let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span); + let report = compute_match_usefulness(&cx, &tarms, scrut_ty); match source { // Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }` @@ -453,10 +458,10 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { pat: &Pat<'tcx>, refutability: RefutableFlag, ) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> { - let cx = self.new_cx(refutability, None); + let cx = self.new_cx(refutability, None, pat.span); let pat = self.lower_pattern(&cx, pat)?; let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }]; - let report = compute_match_usefulness(&cx, &arms, self.lint_level, pat.ty(), pat.span()); + let report = compute_match_usefulness(&cx, &arms, pat.ty()); Ok((cx, report)) } @@ -862,12 +867,6 @@ fn report_non_exhaustive_match<'p, 'tcx>( exhaustively", )); } - if cx.tcx.sess.is_nightly_build() { - err.help(format!( - "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \ - enable precise `{ty}` matching", - )); - } } else if ty == cx.tcx.types.str_ { err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary"); } else if cx.is_foreign_non_exhaustive_enum(ty) { 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 fc03f7891a86f..4e2c932d6c6a3 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 @@ -123,6 +123,8 @@ impl<'tcx> ConstToPat<'tcx> { }); debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation); + let have_valtree = + matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_))); let inlined_const_as_pat = match cv { mir::Const::Ty(c) => match c.kind() { ty::ConstKind::Param(_) @@ -198,7 +200,9 @@ impl<'tcx> ConstToPat<'tcx> { // We errored. Signal that in the pattern, so that follow up errors can be silenced. let kind = PatKind::Error(e); return Box::new(Pat { span: self.span, ty: cv.ty(), kind }); - } else if let ty::Adt(..) = cv.ty().kind() && matches!(cv, mir::Const::Val(..)) { + } else if let ty::Adt(..) = cv.ty().kind() + && matches!(cv, mir::Const::Val(..)) + { // This branch is only entered when the current `cv` is `mir::Const::Val`. // This is because `mir::Const::ty` has already been handled by `Self::recur` // and the invalid types may be ignored. @@ -209,16 +213,6 @@ impl<'tcx> ConstToPat<'tcx> { } else if !self.saw_const_match_lint.get() { if let Some(mir_structural_match_violation) = mir_structural_match_violation { match non_sm_ty.kind() { - ty::RawPtr(pointee) - if pointee.ty.is_sized(self.tcx(), self.param_env) => {} - ty::FnPtr(..) | ty::RawPtr(..) => { - self.tcx().emit_spanned_lint( - lint::builtin::POINTER_STRUCTURAL_MATCH, - self.id, - self.span, - PointerPattern, - ); - } ty::Adt(..) if mir_structural_match_violation => { self.tcx().emit_spanned_lint( lint::builtin::INDIRECT_STRUCTURAL_MATCH, @@ -236,19 +230,15 @@ impl<'tcx> ConstToPat<'tcx> { } } } - } else if !self.saw_const_match_lint.get() { - match cv.ty().kind() { - ty::RawPtr(pointee) if pointee.ty.is_sized(self.tcx(), self.param_env) => {} - ty::FnPtr(..) | ty::RawPtr(..) => { - self.tcx().emit_spanned_lint( - lint::builtin::POINTER_STRUCTURAL_MATCH, - self.id, - self.span, - PointerPattern, - ); - } - _ => {} - } + } else if !have_valtree && !self.saw_const_match_lint.get() { + // The only way valtree construction can fail without the structural match + // checker finding a violation is if there is a pointer somewhere. + self.tcx().emit_spanned_lint( + lint::builtin::POINTER_STRUCTURAL_MATCH, + self.id, + self.span, + PointerPattern, + ); } // Always check for `PartialEq`, even if we emitted other lints. (But not if there were @@ -268,18 +258,26 @@ impl<'tcx> ConstToPat<'tcx> { #[instrument(level = "trace", skip(self), ret)] fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { + let tcx = self.tcx(); // double-check there even *is* a semantic `PartialEq` to dispatch to. // // (If there isn't, then we can safely issue a hard // error, because that's never worked, due to compiler // using `PartialEq::eq` in this scenario in the past.) - let partial_eq_trait_id = - self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span)); + let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span)); let partial_eq_obligation = Obligation::new( - self.tcx(), + tcx, ObligationCause::dummy(), self.param_env, - ty::TraitRef::new(self.tcx(), partial_eq_trait_id, [ty, ty]), + ty::TraitRef::new( + tcx, + partial_eq_trait_id, + tcx.with_opt_const_effect_param( + tcx.hir().enclosing_body_owner(self.id), + partial_eq_trait_id, + [ty, ty], + ), + ), ); // This *could* accept a type that isn't actually `PartialEq`, because region bounds get @@ -389,11 +387,19 @@ impl<'tcx> ConstToPat<'tcx> { subpatterns: self .field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter()))?, }, - ty::Adt(def, args) => PatKind::Leaf { - subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip( - def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), args)), - ))?, - }, + ty::Adt(def, args) => { + assert!(!def.is_union()); // Valtree construction would never succeed for unions. + PatKind::Leaf { + subpatterns: self.field_pats( + cv.unwrap_branch().iter().copied().zip( + def.non_enum_variant() + .fields + .iter() + .map(|field| field.ty(self.tcx(), args)), + ), + )?, + } + } ty::Slice(elem_ty) => PatKind::Slice { prefix: cv .unwrap_branch() @@ -480,10 +486,15 @@ impl<'tcx> ConstToPat<'tcx> { } } }, - ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => { + // The raw pointers we see here have been "vetted" by valtree construction to be + // just integers, so we simply allow them. PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) } } - ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(), + ty::FnPtr(..) => { + // Valtree construction would never succeed for these, so this is unreachable. + unreachable!() + } _ => { let err = InvalidPattern { span, non_sm_ty: ty }; let e = tcx.sess.emit_err(err); diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 0c7c2c6f9b4b7..ddcceeb7ef6b1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -1,46 +1,88 @@ -//! [`super::usefulness`] explains most of what is happening in this file. As explained there, -//! values and patterns are made from constructors applied to fields. This file defines a -//! `Constructor` enum, a `Fields` struct, and various operations to manipulate them and convert -//! them from/to patterns. +//! As explained in [`super::usefulness`], values and patterns are made from constructors applied to +//! fields. This file defines a `Constructor` enum, a `Fields` struct, and various operations to +//! manipulate them and convert them from/to patterns. //! -//! There's one idea that is not detailed in [`super::usefulness`] because the details are not -//! needed there: _constructor splitting_. +//! There are two important bits of core logic in this file: constructor inclusion and constructor +//! splitting. Constructor inclusion, i.e. whether a constructor is included in/covered by another, +//! is straightforward and defined in [`Constructor::is_covered_by`]. //! -//! # Constructor splitting +//! Constructor splitting is mentioned in [`super::usefulness`] but not detailed. We describe it +//! precisely here. //! -//! The idea is as follows: given a constructor `c` and a matrix, we want to specialize in turn -//! with all the value constructors that are covered by `c`, and compute usefulness for each. -//! Instead of listing all those constructors (which is intractable), we group those value -//! constructors together as much as possible. Example: //! +//! # Constructor grouping and splitting +//! +//! As explained in the corresponding section in [`super::usefulness`], to make usefulness tractable +//! we need to group together constructors that have the same effect when they are used to +//! specialize the matrix. +//! +//! Example: //! ```compile_fail,E0004 //! match (0, false) { -//! (0 ..=100, true) => {} // `p_1` -//! (50..=150, false) => {} // `p_2` -//! (0 ..=200, _) => {} // `q` +//! (0 ..=100, true) => {} +//! (50..=150, false) => {} +//! (0 ..=200, _) => {} //! } //! ``` //! -//! The naive approach would try all numbers in the range `0..=200`. But we can be a lot more -//! clever: `0` and `1` for example will match the exact same rows, and return equivalent -//! witnesses. In fact all of `0..50` would. We can thus restrict our exploration to 4 -//! constructors: `0..50`, `50..=100`, `101..=150` and `151..=200`. That is enough and infinitely -//! more tractable. +//! In this example we can restrict specialization to 5 cases: `0..50`, `50..=100`, `101..=150`, +//! `151..=200` and `200..`. +//! +//! In [`super::usefulness`], we had said that `specialize` only takes value-only constructors. We +//! now relax this restriction: we allow `specialize` to take constructors like `0..50` as long as +//! we're careful to only do that with constructors that make sense. For example, `specialize(0..50, +//! (0..=100, true))` is sensible, but `specialize(50..=200, (0..=100, true))` is not. +//! +//! Constructor splitting looks at the constructors in the first column of the matrix and constructs +//! such a sensible set of constructors. Formally, we want to find a smallest disjoint set of +//! constructors: +//! - Whose union covers the whole type, and +//! - That have no non-trivial intersection with any of the constructors in the column (i.e. they're +//! each either disjoint with or covered by any given column constructor). +//! +//! We compute this in two steps: first [`ConstructorSet::for_ty`] determines the set of all +//! possible constructors for the type. Then [`ConstructorSet::split`] looks at the column of +//! constructors and splits the set into groups accordingly. The precise invariants of +//! [`ConstructorSet::split`] is described in [`SplitConstructorSet`]. +//! +//! Constructor splitting has two interesting special cases: integer range splitting (see +//! [`IntRange::split`]) and slice splitting (see [`Slice::split`]). +//! +//! +//! # The `Missing` constructor +//! +//! We detail a special case of constructor splitting that is a bit subtle. Take the following: +//! +//! ``` +//! enum Direction { North, South, East, West } +//! # let wind = (Direction::North, 0u8); +//! match wind { +//! (Direction::North, 50..) => {} +//! (_, _) => {} +//! } +//! ``` +//! +//! Here we expect constructor splitting to output two cases: `North`, and "everything else". This +//! "everything else" is represented by [`Constructor::Missing`]. Unlike other constructors, it's a +//! bit contextual: to know the exact list of constructors it represents we have to look at the +//! column. In practice however we don't need to, because by construction it only matches rows that +//! have wildcards. This is how this constructor is special: the only constructor that covers it is +//! `Wildcard`. +//! +//! The only place where we care about which constructors `Missing` represents is in diagnostics +//! (see `super::usefulness::WitnessMatrix::apply_constructor`). //! -//! We capture this idea in a function `split(p_1 ... p_n, c)` which returns a list of constructors -//! `c'` covered by `c`. Given such a `c'`, we require that all value ctors `c''` covered by `c'` -//! return an equivalent set of witnesses after specializing and computing usefulness. -//! In the example above, witnesses for specializing by `c''` covered by `0..50` will only differ -//! in their first element. +//! We choose whether to specialize with `Missing` in +//! `super::usefulness::compute_exhaustiveness_and_reachability`. //! -//! We usually also ask that the `c'` together cover all of the original `c`. However we allow -//! skipping some constructors as long as it doesn't change whether the resulting list of witnesses -//! is empty of not. We use this in the wildcard `_` case. //! -//! Splitting is implemented in the [`Constructor::split`] function. We don't do splitting for -//! or-patterns; instead we just try the alternatives one-by-one. For details on splitting -//! wildcards, see [`Constructor::split`]; for integer ranges, see -//! [`IntRange::split`]; for slices, see [`Slice::split`]. +//! +//! ## Opaque patterns +//! +//! Some patterns, such as constants that are not allowed to be matched structurally, cannot be +//! inspected, which we handle with `Constructor::Opaque`. Since we know nothing of these patterns, +//! we assume they never cover each other. In order to respect the invariants of +//! [`SplitConstructorSet`], we give each `Opaque` constructor a unique id so we can recognize it. use std::cell::Cell; use std::cmp::{self, max, min, Ordering}; @@ -74,7 +116,7 @@ fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) { if let PatKind::Or { pats } = &pat.kind { for pat in pats.iter() { - expand(&pat, vec); + expand(pat, vec); } } else { vec.push(pat) @@ -284,8 +326,7 @@ impl IntRange { /// `NegInfinity..PosInfinity`. In other words, as far as `IntRange` is concerned, there are /// values before `isize::MIN` and after `usize::MAX`/`isize::MAX`. /// This is to avoid e.g. `0..(u32::MAX as usize)` from being exhaustive on one architecture and - /// not others. See discussions around the `precise_pointer_size_matching` feature for more - /// details. + /// not others. This was decided in . /// /// These infinities affect splitting subtly: it is possible to get `NegInfinity..0` and /// `usize::MAX+1..PosInfinity` in the output. Diagnostics must be careful to handle these @@ -338,7 +379,7 @@ impl IntRange { /// Whether the range denotes the fictitious values before `isize::MIN` or after /// `usize::MAX`/`isize::MAX` (see doc of [`IntRange::split`] for why these exist). pub(crate) fn is_beyond_boundaries<'tcx>(&self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool { - ty.is_ptr_sized_integral() && !tcx.features().precise_pointer_size_matching && { + ty.is_ptr_sized_integral() && { // The two invalid ranges are `NegInfinity..isize::MIN` (represented as // `NegInfinity..0`), and `{u,i}size::MAX+1..PosInfinity`. `to_diagnostic_pat_range_bdy` // converts `MAX+1` to `PosInfinity`, and we couldn't have `PosInfinity` in `self.lo` @@ -617,6 +658,18 @@ impl Slice { } } +/// A globally unique id to distinguish `Opaque` patterns. +#[derive(Clone, Debug, PartialEq, Eq)] +pub(super) struct OpaqueId(u32); + +impl OpaqueId { + fn new() -> Self { + use std::sync::atomic::{AtomicU32, Ordering}; + static OPAQUE_ID: AtomicU32 = AtomicU32::new(0); + OpaqueId(OPAQUE_ID.fetch_add(1, Ordering::SeqCst)) + } +} + /// A value can be decomposed into a constructor applied to some fields. This struct represents /// the constructor. See also `Fields`. /// @@ -626,8 +679,8 @@ impl Slice { /// `Fields`. #[derive(Clone, Debug, PartialEq)] pub(super) enum Constructor<'tcx> { - /// The constructor for patterns that have a single constructor, like tuples, struct patterns - /// and fixed-length arrays. + /// The constructor for patterns that have a single constructor, like tuples, struct patterns, + /// and references. Fixed-length arrays are treated separately with `Slice`. Single, /// Enum variants. Variant(VariantIdx), @@ -642,10 +695,12 @@ pub(super) enum Constructor<'tcx> { Str(mir::Const<'tcx>), /// Array and slice patterns. Slice(Slice), - /// Constants that must not be matched structurally. They are treated as black - /// boxes for the purposes of exhaustiveness: we must not inspect them, and they - /// don't count towards making a match exhaustive. - Opaque, + /// Constants that must not be matched structurally. They are treated as black boxes for the + /// purposes of exhaustiveness: we must not inspect them, and they don't count towards making a + /// match exhaustive. + /// Carries an id that must be unique within a match. We need this to ensure the invariants of + /// [`SplitConstructorSet`]. + Opaque(OpaqueId), /// Or-pattern. Or, /// Wildcard pattern. @@ -657,12 +712,15 @@ pub(super) enum Constructor<'tcx> { /// We use this for variants behind an unstable gate as well as /// `#[doc(hidden)]` ones. Hidden, - /// Fake extra constructor for constructors that are not seen in the matrix, as explained in the - /// code for [`Constructor::split`]. + /// Fake extra constructor for constructors that are not seen in the matrix, as explained at the + /// top of the file. Missing, } impl<'tcx> Constructor<'tcx> { + pub(super) fn is_wildcard(&self) -> bool { + matches!(self, Wildcard) + } pub(super) fn is_non_exhaustive(&self) -> bool { matches!(self, NonExhaustive) } @@ -728,7 +786,7 @@ impl<'tcx> Constructor<'tcx> { | F32Range(..) | F64Range(..) | Str(..) - | Opaque + | Opaque(..) | NonExhaustive | Hidden | Missing { .. } @@ -737,109 +795,23 @@ impl<'tcx> Constructor<'tcx> { } } - /// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of - /// actual constructors (like variants, integers or fixed-sized slices). When specializing for - /// these constructors, we want to be specialising for the actual underlying constructors. - /// Naively, we would simply return the list of constructors they correspond to. We instead are - /// more clever: if there are constructors that we know will behave the same w.r.t. the current - /// matrix, we keep them grouped. For example, all slices of a sufficiently large length will - /// either be all useful or all non-useful with a given matrix. - /// - /// See the branches for details on how the splitting is done. - /// - /// This function may discard some irrelevant constructors if this preserves behavior. Eg. for - /// the `_` case, we ignore the constructors already present in the column, unless all of them - /// are. - pub(super) fn split<'a>( - &self, - pcx: &PatCtxt<'_, '_, 'tcx>, - ctors: impl Iterator> + Clone, - ) -> SmallVec<[Self; 1]> - where - 'tcx: 'a, - { - match self { - Wildcard => { - let split_set = ConstructorSet::for_ty(pcx.cx, pcx.ty).split(pcx, ctors); - if !split_set.missing.is_empty() { - // We are splitting a wildcard in order to compute its usefulness. Some constructors are - // not present in the column. The first thing we note is that specializing with any of - // the missing constructors would select exactly the rows with wildcards. Moreover, they - // would all return equivalent results. We can therefore group them all into a - // fictitious `Missing` constructor. - // - // As an important optimization, this function will skip all the present constructors. - // This is correct because specializing with any of the present constructors would - // select a strict superset of the wildcard rows, and thus would only find witnesses - // already found with the `Missing` constructor. - // This does mean that diagnostics are incomplete: in - // ``` - // match x { - // Some(true) => {} - // } - // ``` - // we report `None` as missing but not `Some(false)`. - // - // When all the constructors are missing we can equivalently return the `Wildcard` - // constructor on its own. The difference between `Wildcard` and `Missing` will then - // only be in diagnostics. - - // If some constructors are missing, we typically want to report those constructors, - // e.g.: - // ``` - // enum Direction { N, S, E, W } - // let Direction::N = ...; - // ``` - // we can report 3 witnesses: `S`, `E`, and `W`. - // - // However, if the user didn't actually specify a constructor - // in this arm, e.g., in - // ``` - // let x: (Direction, Direction, bool) = ...; - // let (_, _, false) = x; - // ``` - // we don't want to show all 16 possible witnesses `(, , - // true)` - we are satisfied with `(_, _, true)`. So if all constructors are missing we - // prefer to report just a wildcard `_`. - // - // The exception is: if we are at the top-level, for example in an empty match, we - // usually prefer to report the full list of constructors. - let all_missing = split_set.present.is_empty(); - let report_when_all_missing = - pcx.is_top_level && !IntRange::is_integral(pcx.ty); - let ctor = - if all_missing && !report_when_all_missing { Wildcard } else { Missing }; - smallvec![ctor] - } else { - split_set.present - } - } - // Fast-track if the range is trivial. - IntRange(this_range) if !this_range.is_singleton() => { - let column_ranges = ctors.filter_map(|ctor| ctor.as_int_range()).cloned(); - this_range.split(column_ranges).map(|(_, range)| IntRange(range)).collect() - } - Slice(this_slice @ Slice { kind: VarLen(..), .. }) => { - let column_slices = ctors.filter_map(|c| c.as_slice()); - this_slice.split(column_slices).map(|(_, slice)| Slice(slice)).collect() - } - // Any other constructor can be used unchanged. - _ => smallvec![self.clone()], - } - } - /// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`. /// For the simple cases, this is simply checking for equality. For the "grouped" constructors, /// this checks for inclusion. // We inline because this has a single call site in `Matrix::specialize_constructor`. #[inline] pub(super) fn is_covered_by<'p>(&self, pcx: &PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool { - // This must be kept in sync with `is_covered_by_any`. match (self, other) { + (Wildcard, _) => { + span_bug!( + pcx.cx.scrut_span, + "Constructor splitting should not have returned `Wildcard`" + ) + } // Wildcards cover anything (_, Wildcard) => true, // Only a wildcard pattern can match these special constructors. - (Wildcard | Missing { .. } | NonExhaustive | Hidden, _) => false, + (Missing { .. } | NonExhaustive | Hidden, _) => false, (Single, Single) => true, (Variant(self_id), Variant(other_id)) => self_id == other_id, @@ -869,11 +841,13 @@ impl<'tcx> Constructor<'tcx> { } (Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice), - // We are trying to inspect an opaque constant. Thus we skip the row. - (Opaque, _) | (_, Opaque) => false, + // Opaque constructors don't interact with anything unless they come from the + // syntactically identical pattern. + (Opaque(self_id), Opaque(other_id)) => self_id == other_id, + (Opaque(..), _) | (_, Opaque(..)) => false, _ => span_bug!( - pcx.span, + pcx.cx.scrut_span, "trying to compare incompatible constructors {:?} and {:?}", self, other @@ -917,16 +891,20 @@ pub(super) enum ConstructorSet { /// `present` is morally the set of constructors present in the column, and `missing` is the set of /// constructors that exist in the type but are not present in the column. /// -/// More formally, they respect the following constraints: -/// - the union of `present` and `missing` covers the whole type -/// - `present` and `missing` are disjoint -/// - neither contains wildcards -/// - each constructor in `present` is covered by some non-wildcard constructor in the column -/// - together, the constructors in `present` cover all the non-wildcard constructor in the column -/// - non-wildcards in the column do no cover anything in `missing` -/// - constructors in `present` and `missing` are split for the column; in other words, they are -/// either fully included in or disjoint from each constructor in the column. This avoids -/// non-trivial intersections like between `0..10` and `5..15`. +/// More formally, if we discard wildcards from the column, this respects the following constraints: +/// 1. the union of `present` and `missing` covers the whole type +/// 2. each constructor in `present` is covered by something in the column +/// 3. no constructor in `missing` is covered by anything in the column +/// 4. each constructor in the column is equal to the union of one or more constructors in `present` +/// 5. `missing` does not contain empty constructors (see discussion about emptiness at the top of +/// the file); +/// 6. constructors in `present` and `missing` are split for the column; in other words, they are +/// either fully included in or fully disjoint from each constructor in the column. In other +/// words, there are no non-trivial intersections like between `0..10` and `5..15`. +/// +/// We must be particularly careful with weird constructors like `Opaque`: they're not formally part +/// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be +/// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4. #[derive(Debug)] pub(super) struct SplitConstructorSet<'tcx> { pub(super) present: SmallVec<[Constructor<'tcx>; 1]>, @@ -934,6 +912,7 @@ pub(super) struct SplitConstructorSet<'tcx> { } impl ConstructorSet { + /// Creates a set that represents all the constructors of `ty`. #[instrument(level = "debug", skip(cx), ret)] pub(super) fn for_ty<'p, 'tcx>(cx: &MatchCheckCtxt<'p, 'tcx>, ty: Ty<'tcx>) -> Self { let make_range = |start, end| { @@ -961,11 +940,8 @@ impl ConstructorSet { } } &ty::Int(ity) => { - let range = if ty.is_ptr_sized_integral() - && !cx.tcx.features().precise_pointer_size_matching - { - // The min/max values of `isize` are not allowed to be observed unless the - // `precise_pointer_size_matching` feature is enabled. + let range = if ty.is_ptr_sized_integral() { + // The min/max values of `isize` are not allowed to be observed. IntRange { lo: NegInfinity, hi: PosInfinity } } else { let bits = Integer::from_int_ty(&cx.tcx, ity).size().bits() as u128; @@ -976,11 +952,8 @@ impl ConstructorSet { Self::Integers { range_1: range, range_2: None } } &ty::Uint(uty) => { - let range = if ty.is_ptr_sized_integral() - && !cx.tcx.features().precise_pointer_size_matching - { - // The max value of `usize` is not allowed to be observed unless the - // `precise_pointer_size_matching` feature is enabled. + let range = if ty.is_ptr_sized_integral() { + // The max value of `usize` is not allowed to be observed. let lo = MaybeInfiniteInt::new_finite(cx.tcx, ty, 0); IntRange { lo, hi: PosInfinity } } else { @@ -1069,9 +1042,10 @@ impl ConstructorSet { } } - /// This is the core logical operation of exhaustiveness checking. This analyzes a column a - /// constructors to 1/ determine which constructors of the type (if any) are missing; 2/ split - /// constructors to handle non-trivial intersections e.g. on ranges or slices. + /// This analyzes a column of constructors to 1/ determine which constructors of the type (if + /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges + /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation + /// and its invariants. #[instrument(level = "debug", skip(self, pcx, ctors), ret)] pub(super) fn split<'a, 'tcx>( &self, @@ -1083,23 +1057,31 @@ impl ConstructorSet { { let mut present: SmallVec<[_; 1]> = SmallVec::new(); let mut missing = Vec::new(); - // Constructors in `ctors`, except wildcards. - let mut seen = ctors.filter(|c| !(matches!(c, Opaque | Wildcard))); + // Constructors in `ctors`, except wildcards and opaques. + let mut seen = Vec::new(); + for ctor in ctors.cloned() { + if let Constructor::Opaque(..) = ctor { + present.push(ctor); + } else if !ctor.is_wildcard() { + seen.push(ctor); + } + } + match self { ConstructorSet::Single => { - if seen.next().is_none() { + if seen.is_empty() { missing.push(Single); } else { present.push(Single); } } ConstructorSet::Variants { visible_variants, hidden_variants, non_exhaustive } => { - let seen_set: FxHashSet<_> = seen.map(|c| c.as_variant().unwrap()).collect(); + let seen_set: FxHashSet<_> = seen.iter().map(|c| c.as_variant().unwrap()).collect(); let mut skipped_a_hidden_variant = false; for variant in visible_variants { let ctor = Variant(*variant); - if seen_set.contains(&variant) { + if seen_set.contains(variant) { present.push(ctor); } else { missing.push(ctor); @@ -1108,7 +1090,7 @@ impl ConstructorSet { for variant in hidden_variants { let ctor = Variant(*variant); - if seen_set.contains(&variant) { + if seen_set.contains(variant) { present.push(ctor); } else { skipped_a_hidden_variant = true; @@ -1125,7 +1107,7 @@ impl ConstructorSet { ConstructorSet::Bool => { let mut seen_false = false; let mut seen_true = false; - for b in seen.map(|ctor| ctor.as_bool().unwrap()) { + for b in seen.iter().map(|ctor| ctor.as_bool().unwrap()) { if b { seen_true = true; } else { @@ -1145,7 +1127,7 @@ impl ConstructorSet { } ConstructorSet::Integers { range_1, range_2 } => { let seen_ranges: Vec<_> = - seen.map(|ctor| ctor.as_int_range().unwrap().clone()).collect(); + seen.iter().map(|ctor| ctor.as_int_range().unwrap().clone()).collect(); for (seen, splitted_range) in range_1.split(seen_ranges.iter().cloned()) { match seen { Presence::Unseen => missing.push(IntRange(splitted_range)), @@ -1162,7 +1144,7 @@ impl ConstructorSet { } } &ConstructorSet::Slice(array_len) => { - let seen_slices = seen.map(|c| c.as_slice().unwrap()); + let seen_slices = seen.iter().map(|c| c.as_slice().unwrap()); let base_slice = Slice::new(array_len, VarLen(0, 0)); for (seen, splitted_slice) in base_slice.split(seen_slices) { let ctor = Slice(splitted_slice); @@ -1178,7 +1160,7 @@ impl ConstructorSet { // unreachable if length != 0. // We still gather the seen constructors in `present`, but the only slice that can // go in `missing` is `[]`. - let seen_slices = seen.map(|c| c.as_slice().unwrap()); + let seen_slices = seen.iter().map(|c| c.as_slice().unwrap()); let base_slice = Slice::new(None, VarLen(0, 0)); for (seen, splitted_slice) in base_slice.split(seen_slices) { let ctor = Slice(splitted_slice); @@ -1194,7 +1176,7 @@ impl ConstructorSet { ConstructorSet::Unlistable => { // Since we can't list constructors, we take the ones in the column. This might list // some constructors several times but there's not much we can do. - present.extend(seen.cloned()); + present.extend(seen); missing.push(NonExhaustive); } // If `exhaustive_patterns` is disabled and our scrutinee is an empty type, we cannot @@ -1210,19 +1192,6 @@ impl ConstructorSet { SplitConstructorSet { present, missing } } - - /// Compute the set of constructors missing from this column. - /// This is only used for reporting to the user. - pub(super) fn compute_missing<'a, 'tcx>( - &self, - pcx: &PatCtxt<'_, '_, 'tcx>, - ctors: impl Iterator> + Clone, - ) -> Vec> - where - 'tcx: 'a, - { - self.split(pcx, ctors).missing - } } /// A value can be decomposed into a constructor applied to some fields. This struct represents @@ -1273,9 +1242,8 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { fn wildcards_from_tys( cx: &MatchCheckCtxt<'p, 'tcx>, tys: impl IntoIterator>, - span: Span, ) -> Self { - Fields::from_iter(cx, tys.into_iter().map(|ty| DeconstructedPat::wildcard(ty, span))) + Fields::from_iter(cx, tys.into_iter().map(|ty| DeconstructedPat::wildcard(ty, DUMMY_SP))) } // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide @@ -1311,18 +1279,18 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { pub(super) fn wildcards(pcx: &PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self { let ret = match constructor { Single | Variant(_) => match pcx.ty.kind() { - ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter(), pcx.span), - ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty), pcx.span), + ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter()), + ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty)), ty::Adt(adt, args) => { if adt.is_box() { // The only legal patterns of type `Box` (outside `std`) are `_` and box // patterns. If we're here we can assume this is a box pattern. - Fields::wildcards_from_tys(pcx.cx, once(args.type_at(0)), pcx.span) + Fields::wildcards_from_tys(pcx.cx, once(args.type_at(0))) } else { let variant = &adt.variant(constructor.variant_index_for_adt(*adt)); let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant) .map(|(_, ty)| ty); - Fields::wildcards_from_tys(pcx.cx, tys, pcx.span) + Fields::wildcards_from_tys(pcx.cx, tys) } } _ => bug!("Unexpected type for `Single` constructor: {:?}", pcx), @@ -1330,7 +1298,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { Slice(slice) => match *pcx.ty.kind() { ty::Slice(ty) | ty::Array(ty, _) => { let arity = slice.arity(); - Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty), pcx.span) + Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty)) } _ => bug!("bad slice pattern {:?} {:?}", constructor, pcx), }, @@ -1339,7 +1307,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { | F32Range(..) | F64Range(..) | Str(..) - | Opaque + | Opaque(..) | NonExhaustive | Hidden | Missing { .. } @@ -1388,6 +1356,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { DeconstructedPat { ctor, fields, ty, span, reachable: Cell::new(false) } } + /// Note: the input patterns must have been lowered through + /// `super::check_match::MatchVisitor::lower_pattern`. pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self { let mkpat = |pat| DeconstructedPat::from_pat(cx, pat); let ctor; @@ -1470,14 +1440,14 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { ty::Bool => { ctor = match value.try_eval_bool(cx.tcx, cx.param_env) { Some(b) => Bool(b), - None => Opaque, + None => Opaque(OpaqueId::new()), }; fields = Fields::empty(); } ty::Char | ty::Int(_) | ty::Uint(_) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)), - None => Opaque, + None => Opaque(OpaqueId::new()), }; fields = Fields::empty(); } @@ -1488,7 +1458,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { let value = rustc_apfloat::ieee::Single::from_bits(bits); F32Range(value, value, RangeEnd::Included) } - None => Opaque, + None => Opaque(OpaqueId::new()), }; fields = Fields::empty(); } @@ -1499,7 +1469,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { let value = rustc_apfloat::ieee::Double::from_bits(bits); F64Range(value, value, RangeEnd::Included) } - None => Opaque, + None => Opaque(OpaqueId::new()), }; fields = Fields::empty(); } @@ -1520,7 +1490,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are // opaque. _ => { - ctor = Opaque; + ctor = Opaque(OpaqueId::new()); fields = Fields::empty(); } } @@ -1580,8 +1550,14 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { let pats = expand_or_pat(pat); fields = Fields::from_iter(cx, pats.into_iter().map(mkpat)); } + PatKind::Never => { + // FIXME(never_patterns): handle `!` in exhaustiveness. This is a sane default + // in the meantime. + ctor = Wildcard; + fields = Fields::empty(); + } PatKind::Error(_) => { - ctor = Opaque; + ctor = Opaque(OpaqueId::new()); fields = Fields::empty(); } } @@ -1591,6 +1567,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { pub(super) fn is_or_pat(&self) -> bool { matches!(self.ctor, Or) } + /// Expand this (possibly-nested) or-pattern into its alternatives. pub(super) fn flatten_or_pat(&'p self) -> SmallVec<[&'p Self; 1]> { if self.is_or_pat() { self.iter_fields().flat_map(|p| p.flatten_or_pat()).collect() @@ -1646,7 +1623,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { let wildcard: &_ = pcx .cx .pattern_arena - .alloc(DeconstructedPat::wildcard(inner_ty, pcx.span)); + .alloc(DeconstructedPat::wildcard(inner_ty, DUMMY_SP)); let extra_wildcards = other_slice.arity() - self_slice.arity(); let extra_wildcards = (0..extra_wildcards).map(|_| wildcard); prefix.iter().chain(extra_wildcards).chain(suffix).collect() @@ -1663,7 +1640,17 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { self.reachable.set(true) } pub(super) fn is_reachable(&self) -> bool { - self.reachable.get() + if self.reachable.get() { + true + } else if self.is_or_pat() && self.iter_fields().any(|f| f.is_reachable()) { + // We always expand or patterns in the matrix, so we will never see the actual + // or-pattern (the one with constructor `Or`) in the column. As such, it will not be + // marked as reachable itself, only its children will. We recover this information here. + self.set_reachable(); + true + } else { + false + } } /// Report the spans of subpatterns that were not reachable, if any. @@ -1672,7 +1659,6 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { self.collect_unreachable_spans(&mut spans); spans } - fn collect_unreachable_spans(&self, spans: &mut Vec) { // We don't look at subpatterns if we already reported the whole pattern as unreachable. if !self.is_reachable() { @@ -1768,7 +1754,7 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> { F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"), F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"), Str(value) => write!(f, "{value}"), - Opaque => write!(f, ""), + Opaque(..) => write!(f, ""), Or => { for pat in self.iter_fields() { write!(f, "{}{:?}", start_or_continue(" | "), pat)?; @@ -1898,7 +1884,7 @@ impl<'tcx> WitnessPat<'tcx> { "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug, `Missing` should have been processed in `apply_constructors`" ), - F32Range(..) | F64Range(..) | Opaque | Or => { + F32Range(..) | F64Range(..) | Opaque(..) | Or => { bug!("can't convert to pattern: {:?}", self) } }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 0811ab6a0a6bd..eb548ad29ebcd 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -18,17 +18,14 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::RangeEnd; use rustc_index::Idx; use rustc_middle::mir::interpret::{ErrorHandled, GlobalId, LitToConstError, LitToConstInput}; -use rustc_middle::mir::{self, BorrowKind, Const, Mutability, UserTypeProjection}; +use rustc_middle::mir::{self, BorrowKind, Const, Mutability}; use rustc_middle::thir::{ Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{ - self, AdtDef, CanonicalUserTypeAnnotation, GenericArg, GenericArgsRef, Region, Ty, TyCtxt, - TypeVisitableExt, UserType, -}; +use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::LocalDefId; -use rustc_span::{ErrorGuaranteed, Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_target::abi::{FieldIdx, Integer}; use std::cmp::Ordering; @@ -111,7 +108,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let msg = format!( "found bad range pattern endpoint `{expr:?}` outside of error recovery" ); - return Err(self.tcx.sess.delay_span_bug(expr.span, msg)); + return Err(self.tcx.sess.span_delayed_bug(expr.span, msg)); }; Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) } @@ -181,7 +178,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ) -> Result, ErrorGuaranteed> { if lo_expr.is_none() && hi_expr.is_none() { let msg = format!("found twice-open range pattern (`..`) outside of error recovery"); - return Err(self.tcx.sess.delay_span_bug(span, msg)); + return Err(self.tcx.sess.span_delayed_bug(span, msg)); } let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?; @@ -254,6 +251,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let kind = match pat.kind { hir::PatKind::Wild => PatKind::Wild, + hir::PatKind::Never => PatKind::Never, + hir::PatKind::Lit(value) => self.lower_lit(value), hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => { @@ -266,16 +265,16 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { return self.lower_path(qpath, pat.hir_id, pat.span); } - hir::PatKind::Ref(ref subpattern, _) | hir::PatKind::Box(ref subpattern) => { + hir::PatKind::Ref(subpattern, _) | hir::PatKind::Box(subpattern) => { PatKind::Deref { subpattern: self.lower_pattern(subpattern) } } - hir::PatKind::Slice(ref prefix, ref slice, ref suffix) => { + hir::PatKind::Slice(prefix, ref slice, suffix) => { self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix) } - hir::PatKind::Tuple(ref pats, ddpos) => { - let ty::Tuple(ref tys) = ty.kind() else { + hir::PatKind::Tuple(pats, ddpos) => { + let ty::Tuple(tys) = ty.kind() else { span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty); }; let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos); @@ -325,7 +324,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } } - hir::PatKind::TupleStruct(ref qpath, ref pats, ddpos) => { + hir::PatKind::TupleStruct(ref qpath, pats, ddpos) => { let res = self.typeck_results.qpath_res(qpath, pat.hir_id); let ty::Adt(adt_def, _) = ty.kind() else { span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty); @@ -335,20 +334,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns) } - hir::PatKind::Struct(ref qpath, ref fields, _) => { + hir::PatKind::Struct(ref qpath, fields, _) => { let res = self.typeck_results.qpath_res(qpath, pat.hir_id); let subpatterns = fields .iter() .map(|field| FieldPat { field: self.typeck_results.field_index(field.hir_id), - pattern: self.lower_pattern(&field.pat), + pattern: self.lower_pattern(field.pat), }) .collect(); self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns) } - hir::PatKind::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) }, + hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) }, }; Box::new(Pat { span, ty, kind }) @@ -701,146 +700,3 @@ impl<'tcx> UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> { self.typeck_results } } - -trait PatternFoldable<'tcx>: Sized { - fn fold_with>(&self, folder: &mut F) -> Self { - self.super_fold_with(folder) - } - - fn super_fold_with>(&self, folder: &mut F) -> Self; -} - -trait PatternFolder<'tcx>: Sized { - fn fold_pattern(&mut self, pattern: &Pat<'tcx>) -> Pat<'tcx> { - pattern.super_fold_with(self) - } - - fn fold_pattern_kind(&mut self, kind: &PatKind<'tcx>) -> PatKind<'tcx> { - kind.super_fold_with(self) - } -} - -impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box { - fn super_fold_with>(&self, folder: &mut F) -> Self { - let content: T = (**self).fold_with(folder); - Box::new(content) - } -} - -impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Vec { - fn super_fold_with>(&self, folder: &mut F) -> Self { - self.iter().map(|t| t.fold_with(folder)).collect() - } -} - -impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<[T]> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - self.iter().map(|t| t.fold_with(folder)).collect() - } -} - -impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option { - fn super_fold_with>(&self, folder: &mut F) -> Self { - self.as_ref().map(|t| t.fold_with(folder)) - } -} - -macro_rules! ClonePatternFoldableImpls { - (<$lt_tcx:tt> $($ty:ty),+) => { - $( - impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty { - fn super_fold_with>(&self, _: &mut F) -> Self { - Clone::clone(self) - } - } - )+ - } -} - -ClonePatternFoldableImpls! { <'tcx> - Span, FieldIdx, Mutability, Symbol, LocalVarId, usize, - Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>, - GenericArgsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>, - UserTypeProjection, CanonicalUserTypeAnnotation<'tcx> -} - -impl<'tcx> PatternFoldable<'tcx> for FieldPat<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - FieldPat { field: self.field.fold_with(folder), pattern: self.pattern.fold_with(folder) } - } -} - -impl<'tcx> PatternFoldable<'tcx> for Pat<'tcx> { - fn fold_with>(&self, folder: &mut F) -> Self { - folder.fold_pattern(self) - } - - fn super_fold_with>(&self, folder: &mut F) -> Self { - Pat { - ty: self.ty.fold_with(folder), - span: self.span.fold_with(folder), - kind: self.kind.fold_with(folder), - } - } -} - -impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { - fn fold_with>(&self, folder: &mut F) -> Self { - folder.fold_pattern_kind(self) - } - - fn super_fold_with>(&self, folder: &mut F) -> Self { - match *self { - PatKind::Wild => PatKind::Wild, - PatKind::Error(e) => PatKind::Error(e), - PatKind::AscribeUserType { - ref subpattern, - ascription: Ascription { ref annotation, variance }, - } => PatKind::AscribeUserType { - subpattern: subpattern.fold_with(folder), - ascription: Ascription { annotation: annotation.fold_with(folder), variance }, - }, - PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, is_primary } => { - PatKind::Binding { - mutability: mutability.fold_with(folder), - name: name.fold_with(folder), - mode: mode.fold_with(folder), - var: var.fold_with(folder), - ty: ty.fold_with(folder), - subpattern: subpattern.fold_with(folder), - is_primary, - } - } - PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => { - PatKind::Variant { - adt_def: adt_def.fold_with(folder), - args: args.fold_with(folder), - variant_index, - subpatterns: subpatterns.fold_with(folder), - } - } - PatKind::Leaf { ref subpatterns } => { - PatKind::Leaf { subpatterns: subpatterns.fold_with(folder) } - } - PatKind::Deref { ref subpattern } => { - PatKind::Deref { subpattern: subpattern.fold_with(folder) } - } - PatKind::Constant { value } => PatKind::Constant { value }, - PatKind::InlineConstant { def, subpattern: ref pattern } => { - PatKind::InlineConstant { def, subpattern: pattern.fold_with(folder) } - } - PatKind::Range(ref range) => PatKind::Range(range.clone()), - PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice { - prefix: prefix.fold_with(folder), - slice: slice.fold_with(folder), - suffix: suffix.fold_with(folder), - }, - PatKind::Array { ref prefix, ref slice, ref suffix } => PatKind::Array { - prefix: prefix.fold_with(folder), - slice: slice.fold_with(folder), - suffix: suffix.fold_with(folder), - }, - PatKind::Or { ref pats } => PatKind::Or { pats: pats.fold_with(folder) }, - } - } -} diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index da7b6587a7220..a2f829f93e3a9 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -1,46 +1,55 @@ -//! Note: tests specific to this file can be found in: +//! # Match exhaustiveness and reachability algorithm //! -//! - `ui/pattern/usefulness` -//! - `ui/or-patterns` -//! - `ui/consts/const_in_pattern` -//! - `ui/rfc-2008-non-exhaustive` -//! - `ui/half-open-range-patterns` -//! - probably many others +//! This file contains the logic for exhaustiveness and reachability checking for pattern-matching. +//! Specifically, given a list of patterns in a match, we can tell whether: +//! (a) a given pattern is reachable (reachability) +//! (b) the patterns cover every possible value for the type (exhaustiveness) //! -//! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific -//! reason not to, for example if they depend on a particular feature like `or_patterns`. +//! The algorithm implemented here is inspired from the one described in [this +//! paper](http://moscova.inria.fr/~maranget/papers/warn/index.html). We have however changed it in +//! various ways to accommodate the variety of patterns that Rust supports. We thus explain our +//! version here, without being as precise. //! -//! ----- +//! Fun fact: computing exhaustiveness is NP-complete, because we can encode a SAT problem as an +//! exhaustiveness problem. See [here](https://niedzejkob.p4.team/rust-np) for the fun details. //! -//! This file includes the logic for exhaustiveness and reachability checking for pattern-matching. -//! Specifically, given a list of patterns for a type, we can tell whether: -//! (a) each pattern is reachable (reachability) -//! (b) the patterns cover every possible value for the type (exhaustiveness) //! -//! The algorithm implemented here is a modified version of the one described in [this -//! paper](http://moscova.inria.fr/~maranget/papers/warn/index.html). We have however generalized -//! it to accommodate the variety of patterns that Rust supports. We thus explain our version here, -//! without being as rigorous. +//! # Summary //! +//! The algorithm is given as input a list of patterns, one for each arm of a match, and computes +//! the following: +//! - a set of values that match none of the patterns (if any), +//! - for each subpattern (taking into account or-patterns), whether it would catch any value that +//! isn't caught by a pattern before it, i.e. whether it is reachable. //! -//! # Summary +//! To a first approximation, the algorithm works by exploring all possible values for the type +//! being matched on, and determining which arm(s) catch which value. To make this tractable we +//! cleverly group together values, as we'll see below. //! -//! The core of the algorithm is the notion of "usefulness". A pattern `q` is said to be *useful* -//! relative to another pattern `p` of the same type if there is a value that is matched by `q` and -//! not matched by `p`. This generalizes to many `p`s: `q` is useful w.r.t. a list of patterns -//! `p_1 .. p_n` if there is a value that is matched by `q` and by none of the `p_i`. We write -//! `usefulness(p_1 .. p_n, q)` for a function that returns a list of such values. The aim of this -//! file is to compute it efficiently. -//! -//! This is enough to compute reachability: a pattern in a `match` expression is reachable iff it -//! is useful w.r.t. the patterns above it: -//! ```rust -//! # fn foo(x: Option) { -//! match x { -//! Some(_) => {}, -//! None => {}, // reachable: `None` is matched by this but not the branch above -//! Some(0) => {}, // unreachable: all the values this matches are already matched by -//! // `Some(_)` above +//! The entrypoint of this file is the [`compute_match_usefulness`] function, which computes +//! reachability for each subpattern and exhaustiveness for the whole match. +//! +//! In this page we explain the necessary concepts to understand how the algorithm works. +//! +//! +//! # Usefulness +//! +//! The central concept of this file is the notion of "usefulness". Given some patterns `p_1 .. +//! p_n`, a pattern `q` is said to be *useful* if there is a value that is matched by `q` and by +//! none of the `p_i`. We write `usefulness(p_1 .. p_n, q)` for a function that returns a list of +//! such values. The aim of this file is to compute it efficiently. +//! +//! This is enough to compute reachability: a pattern in a `match` expression is reachable iff it is +//! useful w.r.t. the patterns above it: +//! ```compile_fail,E0004 +//! # #![feature(exclusive_range_pattern)] +//! # fn foo() { +//! match Some(0u32) { +//! Some(0..100) => {}, +//! Some(90..190) => {}, // reachable: `Some(150)` is matched by this but not the branch above +//! Some(50..150) => {}, // unreachable: all the values this matches are already matched by +//! // the branches above +//! None => {}, // reachable: `None` is matched by this but not the branches above //! } //! # } //! ``` @@ -49,48 +58,35 @@ //! pattern is _not_ useful w.r.t. the patterns in the match. The values returned by `usefulness` //! are used to tell the user which values are missing. //! ```compile_fail,E0004 -//! # fn foo(x: Option) { +//! # fn foo(x: Option) { //! match x { -//! Some(0) => {}, //! None => {}, +//! Some(0) => {}, //! // not exhaustive: `_` is useful because it matches `Some(1)` //! } //! # } //! ``` //! -//! The entrypoint of this file is the [`compute_match_usefulness`] function, which computes -//! reachability for each match branch and exhaustiveness for the whole match. -//! //! //! # Constructors and fields //! -//! Note: we will often abbreviate "constructor" as "ctor". -//! -//! The idea that powers everything that is done in this file is the following: a (matchable) -//! value is made from a constructor applied to a number of subvalues. 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`). This is natural when we think of -//! pattern-matching, and this is the basis for what follows. -//! -//! Some of the ctors listed above might feel weird: `None` and `2` don't take any arguments. -//! That's ok: those are ctors that take a list of 0 arguments; they are the simplest case of -//! ctors. We treat `2` as a ctor because `u64` and other number types behave exactly like a huge -//! `enum`, with one variant for each number. This allows us to see any matchable value as made up -//! from a tree of ctors, each having a set number of children. For example: `Foo { bar: None, -//! baz: Ok(0) }` is made from 4 different ctors, namely `Foo{..}`, `None`, `Ok` and `0`. -//! -//! This idea can be extended to patterns: they are also made from constructors applied to fields. -//! A pattern for a given type is allowed to use all the ctors for values of that type (which we -//! call "value constructors"), but there are also pattern-only ctors. The most important one is -//! the wildcard (`_`), and the others are integer ranges (`0..=10`), variable-length slices (`[x, -//! ..]`), and or-patterns (`Ok(0) | Err(_)`). Examples of valid patterns are `42`, `Some(_)`, `Foo -//! { bar: Some(0) | None, baz: _ }`. Note that a binder in a pattern (e.g. `Some(x)`) matches the -//! same values as a wildcard (e.g. `Some(_)`), so we treat both as wildcards. -//! -//! From this deconstruction we can compute whether a given value matches a given pattern; we -//! simply look at ctors one at a time. Given a pattern `p` and a value `v`, we want to compute -//! `matches!(v, p)`. It's mostly straightforward: we compare the head ctors and when they match -//! we compare their fields recursively. A few representative examples: +//! 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 +//! constructors are: `Some`, `None`, `(,)` (the 2-tuple constructor), `Foo {..}` (the constructor +//! for a struct `Foo`), and `2` (the constructor for the number `2`). +//! +//! Each constructor takes a fixed number of fields; this is called its arity. `Pair` and `(,)` have +//! arity 2, `Some` has arity 1, `None` and `42` have arity 0. Each type has a known set of +//! constructors. Some types have many constructors (like `u64`) or even an infinitely many (like +//! `&str` and `&[T]`). +//! +//! Patterns are similar: `Pair(Some(_), _)` has constructor `Pair` and two fields. The difference +//! is that we get some extra pattern-only constructors, namely: the wildcard `_`, variable +//! bindings, integer ranges like `0..=10`, and variable-length slices like `[_, .., _]`. We treat +//! or-patterns separately, see the dedicated section below. +//! +//! Now to check if a value `v` matches a pattern `p`, we check if `v`'s constructor matches `p`'s +//! constructor, then recursively compare their fields if necessary. A few representative examples: //! //! - `matches!(v, _) := true` //! - `matches!((v0, v1), (p0, p1)) := matches!(v0, p0) && matches!(v1, p1)` @@ -100,213 +96,398 @@ //! - `matches!(v, 1..=100) := matches!(v, 1) || ... || matches!(v, 100)` //! - `matches!([v0], [p0, .., p1]) := false` (incompatible lengths) //! - `matches!([v0, v1, v2], [p0, .., p1]) := matches!(v0, p0) && matches!(v2, p1)` -//! - `matches!(v, p0 | p1) := matches!(v, p0) || matches!(v, p1)` //! -//! Constructors, fields and relevant operations are defined in the [`super::deconstruct_pat`] module. +//! Constructors, fields and relevant operations are defined in the [`super::deconstruct_pat`] +//! module. The question of whether a constructor is matched by another one is answered by +//! [`Constructor::is_covered_by`]. //! -//! Note: this constructors/fields distinction may not straightforwardly apply to every Rust type. -//! For example a value of type `Rc` can't be deconstructed that way, and `&str` has an -//! infinitude of constructors. There are also subtleties with visibility of fields and -//! uninhabitedness and various other things. The constructors idea can be extended to handle most -//! of these subtleties though; caveats are documented where relevant throughout the code. +//! 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` can't be +//! deconstructed that way. //! -//! Whether constructors cover each other is computed by [`Constructor::is_covered_by`]. //! //! //! # Specialization //! -//! Recall that we wish to compute `usefulness(p_1 .. p_n, q)`: given a list of patterns `p_1 .. -//! p_n` and a pattern `q`, all of the same type, we want to find a list of values (called -//! "witnesses") that are matched by `q` and by none of the `p_i`. We obviously don't just -//! enumerate all possible values. From the discussion above we see that we can proceed -//! ctor-by-ctor: for each value ctor of the given type, we ask "is there a value that starts with -//! this constructor and matches `q` and none of the `p_i`?". As we saw above, there's a lot we can -//! say from knowing only the first constructor of our candidate value. +//! The examples in the previous section motivate the operation at the heart of the algorithm: +//! "specialization". It captures this idea of "removing one layer of constructor". +//! +//! `specialize(c, p)` takes a value-only constructor `c` and a pattern `p`, and returns a +//! pattern-tuple or nothing. It works as follows: +//! +//! - Specializing for the wrong constructor returns nothing +//! +//! - `specialize(None, Some(p0)) := ` +//! - `specialize([,,,], [p0]) := ` +//! +//! - Specializing for the correct constructor returns a tuple of the fields +//! +//! - `specialize(Variant1, Variant1(p0, p1, p2)) := (p0, p1, p2)` +//! - `specialize(Foo{ bar, baz, quz }, Foo { bar: p0, baz: p1, .. }) := (p0, p1, _)` +//! - `specialize([,,,], [p0, .., p1]) := (p0, _, _, p1)` +//! +//! We get the following property: for any values `v_1, .., v_n` of appropriate types, we have: +//! ```text +//! matches!(c(v_1, .., v_n), p) +//! <=> specialize(c, p) returns something +//! && matches!((v_1, .., v_n), specialize(c, p)) +//! ``` +//! +//! We also extend specialization to pattern-tuples by applying it to the first pattern: +//! `specialize(c, (p_0, .., p_n)) := specialize(c, p_0) ++ (p_1, .., p_m)` +//! where `++` is concatenation of tuples. +//! +//! +//! The previous property extends to pattern-tuples: +//! ```text +//! matches!((c(v_1, .., v_n), w_1, .., w_m), (p_0, p_1, .., p_m)) +//! <=> specialize(c, p_0) does not error +//! && matches!((v_1, .., v_n, w_1, .., w_m), specialize(c, (p_0, p_1, .., p_m))) +//! ``` +//! +//! Whether specialization returns something or not is given by [`Constructor::is_covered_by`]. +//! Specialization of a pattern is computed in [`DeconstructedPat::specialize`]. Specialization for +//! a pattern-tuple is computed in [`PatStack::pop_head_constructor`]. Finally, specialization for a +//! set of pattern-tuples is computed in [`Matrix::specialize_constructor`]. +//! +//! +//! +//! # Undoing specialization +//! +//! To construct witnesses we will need an inverse of specialization. If `c` is a constructor of +//! arity `n`, we define `unspecialize` as: +//! `unspecialize(c, (p_1, .., p_n, q_1, .., q_m)) := (c(p_1, .., p_n), q_1, .., q_m)`. +//! +//! This is done for a single witness-tuple in [`WitnessStack::apply_constructor`], and for a set of +//! witness-tuples in [`WitnessMatrix::apply_constructor`]. +//! +//! +//! +//! # Computing usefulness +//! +//! We now present a naive version of the algorithm for computing usefulness. From now on we operate +//! on pattern-tuples. +//! +//! Let `pt_1, .., pt_n` and `qt` be length-m tuples of patterns for the same type `(T_1, .., T_m)`. +//! We compute `usefulness(tp_1, .., tp_n, tq)` as follows: +//! +//! - Base case: `m == 0`. +//! The pattern-tuples are all empty, i.e. they're all `()`. Thus `tq` is useful iff there are +//! no rows above it, i.e. if `n == 0`. In that case we return `()` as a witness-tuple of +//! usefulness of `tq`. +//! +//! - Inductive case: `m > 0`. +//! In this naive version, we list all the possible constructors for values of type `T1` (we +//! will be more clever in the next section). +//! +//! - For each such constructor `c` for which `specialize(c, tq)` is not nothing: +//! - We recursively compute `usefulness(specialize(c, tp_1) ... specialize(c, tp_n), specialize(c, tq))`, +//! where we discard any `specialize(c, p_i)` that returns nothing. +//! - For each witness-tuple `w` found, we apply `unspecialize(c, w)` to it. +//! +//! - We return the all the witnesses found, if any. +//! //! //! Let's take the following example: //! ```compile_fail,E0004 //! # enum Enum { Variant1(()), Variant2(Option, u32)} +//! # use Enum::*; //! # fn foo(x: Enum) { //! match x { -//! Enum::Variant1(_) => {} // `p1` -//! Enum::Variant2(None, 0) => {} // `p2` -//! Enum::Variant2(Some(_), 0) => {} // `q` +//! Variant1(_) => {} // `p1` +//! Variant2(None, 0) => {} // `p2` +//! Variant2(Some(_), 0) => {} // `q` //! } //! # } //! ``` //! -//! We can easily see that if our candidate value `v` starts with `Variant1` it will not match `q`. -//! If `v = Variant2(v0, v1)` however, whether or not it matches `p2` and `q` will depend on `v0` -//! and `v1`. In fact, such a `v` will be a witness of usefulness of `q` exactly when the tuple -//! `(v0, v1)` is a witness of usefulness of `q'` in the following reduced match: -//! -//! ```compile_fail,E0004 -//! # fn foo(x: (Option, u32)) { -//! match x { -//! (None, 0) => {} // `p2'` -//! (Some(_), 0) => {} // `q'` -//! } -//! # } +//! To compute the usefulness of `q`, we would proceed as follows: +//! ```text +//! Start: +//! `tp1 = [Variant1(_)]` +//! `tp2 = [Variant2(None, 0)]` +//! `tq = [Variant2(Some(true), 0)]` +//! +//! Constructors are `Variant1` and `Variant2`. Only `Variant2` can specialize `tq`. +//! Specialize with `Variant2`: +//! `tp2 = [None, 0]` +//! `tq = [Some(true), 0]` +//! +//! Constructors are `None` and `Some`. Only `Some` can specialize `tq`. +//! Specialize with `Some`: +//! `tq = [true, 0]` +//! +//! Constructors are `false` and `true`. Only `true` can specialize `tq`. +//! Specialize with `true`: +//! `tq = [0]` +//! +//! Constructors are `0`, `1`, .. up to infinity. Only `0` can specialize `tq`. +//! Specialize with `0`: +//! `tq = []` +//! +//! m == 0 and n == 0, so `tq` is useful with witness `[]`. +//! `witness = []` +//! +//! Unspecialize with `0`: +//! `witness = [0]` +//! Unspecialize with `true`: +//! `witness = [true, 0]` +//! Unspecialize with `Some`: +//! `witness = [Some(true), 0]` +//! Unspecialize with `Variant2`: +//! `witness = [Variant2(Some(true), 0)]` //! ``` //! -//! This motivates a new step in computing usefulness, that we call _specialization_. -//! Specialization consist of filtering a list of patterns for those that match a constructor, and -//! then looking into the constructor's fields. This enables usefulness to be computed recursively. -//! -//! Instead of acting on a single pattern in each row, we will consider a list of patterns for each -//! row, and we call such a list a _pattern-stack_. The idea is that we will specialize the -//! leftmost pattern, which amounts to popping the constructor and pushing its fields, which feels -//! like a stack. We note a pattern-stack simply with `[p_1 ... p_n]`. -//! Here's a sequence of specializations of a list of pattern-stacks, to illustrate what's -//! happening: -//! ```ignore (illustrative) -//! [Enum::Variant1(_)] -//! [Enum::Variant2(None, 0)] -//! [Enum::Variant2(Some(_), 0)] -//! //==>> specialize with `Variant2` -//! [None, 0] -//! [Some(_), 0] -//! //==>> specialize with `Some` -//! [_, 0] -//! //==>> specialize with `true` (say the type was `bool`) -//! [0] -//! //==>> specialize with `0` -//! [] -//! ``` +//! Therefore `usefulness(tp_1, tp_2, tq)` returns the single witness-tuple `[Variant2(Some(true), 0)]`. //! -//! The function `specialize(c, p)` takes a value constructor `c` and a pattern `p`, and returns 0 -//! or more pattern-stacks. If `c` does not match the head constructor of `p`, it returns nothing; -//! otherwise if returns the fields of the constructor. This only returns more than one -//! pattern-stack if `p` has a pattern-only constructor. //! -//! - Specializing for the wrong constructor returns nothing +//! Computing the set of constructors for a type is done in [`ConstructorSet::for_ty`]. See the +//! following sections for more accurate versions of the algorithm and corresponding links. //! -//! `specialize(None, Some(p0)) := []` //! -//! - Specializing for the correct constructor returns a single row with the fields //! -//! `specialize(Variant1, Variant1(p0, p1, p2)) := [[p0, p1, p2]]` +//! # Computing reachability and exhaustiveness in one go //! -//! `specialize(Foo{..}, Foo { bar: p0, baz: p1 }) := [[p0, p1]]` +//! The algorithm we have described so far computes usefulness of each pattern in turn to check if +//! it is reachable, and ends by checking if `_` is useful to determine exhaustiveness of the whole +//! match. In practice, instead of doing "for each pattern { for each constructor { ... } }", we do +//! "for each constructor { for each pattern { ... } }". This allows us to compute everything in one +//! go. //! -//! - For or-patterns, we specialize each branch and concatenate the results +//! [`Matrix`] stores the set of pattern-tuples under consideration. We track reachability of each +//! row mutably in the matrix as we go along. We ignore witnesses of usefulness of the match rows. +//! We gather witnesses of the usefulness of `_` in [`WitnessMatrix`]. The algorithm that computes +//! all this is in [`compute_exhaustiveness_and_reachability`]. //! -//! `specialize(c, p0 | p1) := specialize(c, p0) ++ specialize(c, p1)` +//! See the full example at the bottom of this documentation. //! -//! - We treat the other pattern constructors as if they were a large or-pattern of all the -//! possibilities: //! -//! `specialize(c, _) := specialize(c, Variant1(_) | Variant2(_, _) | ...)` //! -//! `specialize(c, 1..=100) := specialize(c, 1 | ... | 100)` +//! # Making usefulness tractable: constructor splitting //! -//! `specialize(c, [p0, .., p1]) := specialize(c, [p0, p1] | [p0, _, p1] | [p0, _, _, p1] | ...)` +//! We're missing one last detail: which constructors do we list? Naively listing all value +//! constructors cannot work for types like `u64` or `&str`, so we need to be more clever. The final +//! clever idea for this algorithm is that we can group together constructors that behave the same. //! -//! - If `c` is a pattern-only constructor, `specialize` is defined on a case-by-case basis. See -//! the discussion about constructor splitting in [`super::deconstruct_pat`]. +//! Examples: +//! ```compile_fail,E0004 +//! match (0, false) { +//! (0 ..=100, true) => {} +//! (50..=150, false) => {} +//! (0 ..=200, _) => {} +//! } +//! ``` //! +//! In this example, trying any of `0`, `1`, .., `49` will give the same specialized matrix, and +//! thus the same reachability/exhaustiveness results. We can thus accelerate the algorithm by +//! trying them all at once. Here in fact, the only cases we need to consider are: `0..50`, +//! `50..=100`, `101..=150`,`151..=200` and `201..`. //! -//! We then extend this function to work with pattern-stacks as input, by acting on the first -//! column and keeping the other columns untouched. +//! ``` +//! enum Direction { North, South, East, West } +//! # let wind = (Direction::North, 0u8); +//! match wind { +//! (Direction::North, 50..) => {} +//! (_, _) => {} +//! } +//! ``` //! -//! Specialization for the whole matrix is done in [`Matrix::specialize_constructor`]. Note that -//! or-patterns in the first column are expanded before being stored in the matrix. Specialization -//! for a single patstack is done from a combination of [`Constructor::is_covered_by`] and -//! [`PatStack::pop_head_constructor`]. The internals of how it's done mostly live in the -//! [`super::deconstruct_pat::Fields`] struct. +//! In this example, trying any of `South`, `East`, `West` will give the same specialized matrix. By +//! the same reasoning, we only need to try two cases: `North`, and "everything else". //! +//! We call _constructor splitting_ the operation that computes such a minimal set of cases to try. +//! This is done in [`ConstructorSet::split`] and explained in [`super::deconstruct_pat`]. //! -//! # Computing usefulness //! -//! We now have all we need to compute usefulness. The inputs to usefulness are a list of -//! pattern-stacks `p_1 ... p_n` (one per row), and a new pattern_stack `q`. The paper and this -//! file calls the list of patstacks a _matrix_. They must all have the same number of columns and -//! the patterns in a given column must all have the same type. `usefulness` returns a (possibly -//! empty) list of witnesses of usefulness. These witnesses will also be pattern-stacks. -//! -//! - base case: `n_columns == 0`. -//! Since a pattern-stack functions like a tuple of patterns, an empty one functions like the -//! unit type. Thus `q` is useful iff there are no rows above it, i.e. if `n == 0`. -//! -//! - inductive case: `n_columns > 0`. -//! We need a way to list the constructors we want to try. We will be more clever in the next -//! section but for now assume we list all value constructors for the type of the first column. -//! -//! - for each such ctor `c`: -//! -//! - for each `q'` returned by `specialize(c, q)`: -//! -//! - we compute `usefulness(specialize(c, p_1) ... specialize(c, p_n), q')` -//! -//! - for each witness found, we revert specialization by pushing the constructor `c` on top. -//! -//! - We return the concatenation of all the witnesses found, if any. -//! -//! Example: -//! ```ignore (illustrative) -//! [Some(true)] // p_1 -//! [None] // p_2 -//! [Some(_)] // q -//! //==>> try `None`: `specialize(None, q)` returns nothing -//! //==>> try `Some`: `specialize(Some, q)` returns a single row -//! [true] // p_1' -//! [_] // q' -//! //==>> try `true`: `specialize(true, q')` returns a single row -//! [] // p_1'' -//! [] // q'' -//! //==>> base case; `n != 0` so `q''` is not useful. -//! //==>> go back up a step -//! [true] // p_1' -//! [_] // q' -//! //==>> try `false`: `specialize(false, q')` returns a single row -//! [] // q'' -//! //==>> base case; `n == 0` so `q''` is useful. We return the single witness `[]` -//! witnesses: -//! [] -//! //==>> undo the specialization with `false` -//! witnesses: -//! [false] -//! //==>> undo the specialization with `Some` -//! witnesses: -//! [Some(false)] -//! //==>> we have tried all the constructors. The output is the single witness `[Some(false)]`. -//! ``` +//! # Or-patterns //! -//! This computation is done in [`is_useful`]. In practice we don't care about the list of -//! witnesses when computing reachability; we only need to know whether any exist. We do keep the -//! witnesses when computing exhaustiveness to report them to the user. +//! What we have described so far works well if there are no or-patterns. To handle them, if the +//! first pattern of a row in the matrix is an or-pattern, we expand it by duplicating the rest of +//! the row as necessary. This is handled automatically in [`Matrix`]. //! +//! This makes reachability tracking subtle, because we also want to compute whether an alternative +//! of an or-pattern is unreachable, e.g. in `Some(_) | Some(0)`. We track reachability of each +//! subpattern by interior mutability in [`DeconstructedPat`] with `set_reachable`/`is_reachable`. //! -//! # Making usefulness tractable: constructor splitting +//! It's unfortunate that we have to use interior mutability, but believe me (Nadrieril), I have +//! tried [other](https://github.com/rust-lang/rust/pull/80104) +//! [solutions](https://github.com/rust-lang/rust/pull/80632) and nothing is remotely as simple. //! -//! We're missing one last detail: which constructors do we list? Naively listing all value -//! constructors cannot work for types like `u64` or `&str`, so we need to be more clever. The -//! first obvious insight is that we only want to list constructors that are covered by the head -//! constructor of `q`. If it's a value constructor, we only try that one. If it's a pattern-only -//! constructor, we use the final clever idea for this algorithm: _constructor splitting_, where we -//! group together constructors that behave the same. //! -//! The details are not necessary to understand this file, so we explain them in -//! [`super::deconstruct_pat`]. Splitting is done by the [`Constructor::split`] function. //! -//! # Constants in patterns +//! # Constants and opaques //! //! There are two kinds of constants in patterns: //! //! * literals (`1`, `true`, `"foo"`) //! * named or inline consts (`FOO`, `const { 5 + 6 }`) //! -//! The latter are converted into other patterns with literals at the leaves. For example +//! The latter are converted into the corresponding patterns by a previous phase. For example //! `const_to_pat(const { [1, 2, 3] })` becomes an `Array(vec![Const(1), Const(2), Const(3)])` //! pattern. This gets problematic when comparing the constant via `==` would behave differently -//! from matching on the constant converted to a pattern. Situations like that can occur, when -//! the user implements `PartialEq` manually, and thus could make `==` behave arbitrarily different. -//! In order to honor the `==` implementation, constants of types that implement `PartialEq` manually -//! stay as a full constant and become an `Opaque` pattern. These `Opaque` patterns do not participate -//! in exhaustiveness, specialization or overlap checking. - -use self::ArmType::*; -use self::Usefulness::*; +//! from matching on the constant converted to a pattern. The situation around this is currently +//! unclear and the lang team is working on clarifying what we want to do there. In any case, there +//! are constants we will not turn into patterns. We capture these with `Constructor::Opaque`. These +//! `Opaque` patterns do not participate in exhaustiveness, specialization or overlap checking. +//! +//! +//! +//! # Full example +//! +//! We illustrate a full run of the algorithm on the following match. +//! +//! ```compile_fail,E0004 +//! # struct Pair(Option, bool); +//! # fn foo(x: Pair) -> u32 { +//! match x { +//! Pair(Some(0), _) => 1, +//! Pair(_, false) => 2, +//! Pair(Some(0), false) => 3, +//! } +//! # } +//! ``` +//! +//! We keep track of the original row for illustration purposes, this is not what the algorithm +//! actually does (it tracks reachability as a boolean on each row). +//! +//! ```text +//! ┐ Patterns: +//! │ 1. `[Pair(Some(0), _)]` +//! │ 2. `[Pair(_, false)]` +//! │ 3. `[Pair(Some(0), false)]` +//! │ +//! │ Specialize with `Pair`: +//! ├─┐ Patterns: +//! │ │ 1. `[Some(0), _]` +//! │ │ 2. `[_, false]` +//! │ │ 3. `[Some(0), false]` +//! │ │ +//! │ │ Specialize with `Some`: +//! │ ├─┐ Patterns: +//! │ │ │ 1. `[0, _]` +//! │ │ │ 2. `[_, false]` +//! │ │ │ 3. `[0, false]` +//! │ │ │ +//! │ │ │ Specialize with `0`: +//! │ │ ├─┐ Patterns: +//! │ │ │ │ 1. `[_]` +//! │ │ │ │ 3. `[false]` +//! │ │ │ │ +//! │ │ │ │ Specialize with `true`: +//! │ │ │ ├─┐ Patterns: +//! │ │ │ │ │ 1. `[]` +//! │ │ │ │ │ +//! │ │ │ │ │ We note arm 1 is reachable (by `Pair(Some(0), true)`). +//! │ │ │ ├─┘ +//! │ │ │ │ +//! │ │ │ │ Specialize with `false`: +//! │ │ │ ├─┐ Patterns: +//! │ │ │ │ │ 1. `[]` +//! │ │ │ │ │ 3. `[]` +//! │ │ │ │ │ +//! │ │ │ │ │ We note arm 1 is reachable (by `Pair(Some(0), false)`). +//! │ │ │ ├─┘ +//! │ │ ├─┘ +//! │ │ │ +//! │ │ │ Specialize with `1..`: +//! │ │ ├─┐ Patterns: +//! │ │ │ │ 2. `[false]` +//! │ │ │ │ +//! │ │ │ │ Specialize with `true`: +//! │ │ │ ├─┐ Patterns: +//! │ │ │ │ │ // no rows left +//! │ │ │ │ │ +//! │ │ │ │ │ We have found an unmatched value (`Pair(Some(1..), true)`)! This gives us a witness. +//! │ │ │ │ │ New witnesses: +//! │ │ │ │ │ `[]` +//! │ │ │ ├─┘ +//! │ │ │ │ Unspecialize new witnesses with `true`: +//! │ │ │ │ `[true]` +//! │ │ │ │ +//! │ │ │ │ Specialize with `false`: +//! │ │ │ ├─┐ Patterns: +//! │ │ │ │ │ 2. `[]` +//! │ │ │ │ │ +//! │ │ │ │ │ We note arm 2 is reachable (by `Pair(Some(1..), false)`). +//! │ │ │ ├─┘ +//! │ │ │ │ +//! │ │ │ │ Total witnesses for `1..`: +//! │ │ │ │ `[true]` +//! │ │ ├─┘ +//! │ │ │ Unspecialize new witnesses with `1..`: +//! │ │ │ `[1.., true]` +//! │ │ │ +//! │ │ │ Total witnesses for `Some`: +//! │ │ │ `[1.., true]` +//! │ ├─┘ +//! │ │ Unspecialize new witnesses with `Some`: +//! │ │ `[Some(1..), true]` +//! │ │ +//! │ │ Specialize with `None`: +//! │ ├─┐ Patterns: +//! │ │ │ 2. `[false]` +//! │ │ │ +//! │ │ │ Specialize with `true`: +//! │ │ ├─┐ Patterns: +//! │ │ │ │ // no rows left +//! │ │ │ │ +//! │ │ │ │ We have found an unmatched value (`Pair(None, true)`)! This gives us a witness. +//! │ │ │ │ New witnesses: +//! │ │ │ │ `[]` +//! │ │ ├─┘ +//! │ │ │ Unspecialize new witnesses with `true`: +//! │ │ │ `[true]` +//! │ │ │ +//! │ │ │ Specialize with `false`: +//! │ │ ├─┐ Patterns: +//! │ │ │ │ 2. `[]` +//! │ │ │ │ +//! │ │ │ │ We note arm 2 is reachable (by `Pair(None, false)`). +//! │ │ ├─┘ +//! │ │ │ +//! │ │ │ Total witnesses for `None`: +//! │ │ │ `[true]` +//! │ ├─┘ +//! │ │ Unspecialize new witnesses with `None`: +//! │ │ `[None, true]` +//! │ │ +//! │ │ Total witnesses for `Pair`: +//! │ │ `[Some(1..), true]` +//! │ │ `[None, true]` +//! ├─┘ +//! │ Unspecialize new witnesses with `Pair`: +//! │ `[Pair(Some(1..), true)]` +//! │ `[Pair(None, true)]` +//! │ +//! │ Final witnesses: +//! │ `[Pair(Some(1..), true)]` +//! │ `[Pair(None, true)]` +//! ┘ +//! ``` +//! +//! We conclude: +//! - Arm 3 is unreachable (it was never marked as reachable); +//! - The match is not exhaustive; +//! - Adding arms with `Pair(Some(1..), true)` and `Pair(None, true)` would make the match exhaustive. +//! +//! Note that when we're deep in the algorithm, we don't know what specialization steps got us here. +//! We can only figure out what our witnesses correspond to by unspecializing back up the stack. +//! +//! +//! # Tests +//! +//! Note: tests specific to this file can be found in: +//! +//! - `ui/pattern/usefulness` +//! - `ui/or-patterns` +//! - `ui/consts/const_in_pattern` +//! - `ui/rfc-2008-non-exhaustive` +//! - `ui/half-open-range-patterns` +//! - probably many others +//! +//! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific +//! reason not to, for example if they crucially depend on a particular feature like `or_patterns`. + use super::deconstruct_pat::{ Constructor, ConstructorSet, DeconstructedPat, IntRange, MaybeInfiniteInt, SplitConstructorSet, WitnessPat, @@ -340,8 +521,12 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> { pub(crate) module: DefId, pub(crate) param_env: ty::ParamEnv<'tcx>, pub(crate) pattern_arena: &'p TypedArena>, + /// Lint level at the match. + pub(crate) match_lint_level: HirId, /// The span of the whole match, if applicable. pub(crate) match_span: Option, + /// Span of the scrutinee. + pub(crate) scrut_span: Span, /// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns. pub(crate) refutable: bool, } @@ -371,8 +556,6 @@ pub(super) struct PatCtxt<'a, 'p, 'tcx> { pub(super) cx: &'a MatchCheckCtxt<'p, 'tcx>, /// Type of the current column under investigation. pub(super) ty: Ty<'tcx>, - /// Span of the current pattern under investigation. - pub(super) span: Span, /// Whether the current pattern is the whole pattern as found in a match arm, or if it's a /// subpattern. pub(super) is_top_level: bool, @@ -384,20 +567,16 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> { } } -/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]` -/// works well. +/// Represents a pattern-tuple under investigation. #[derive(Clone)] -pub(crate) struct PatStack<'p, 'tcx> { - pub(crate) pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>, +struct PatStack<'p, 'tcx> { + // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well. + pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>, } impl<'p, 'tcx> PatStack<'p, 'tcx> { fn from_pattern(pat: &'p DeconstructedPat<'p, 'tcx>) -> Self { - Self::from_vec(smallvec![pat]) - } - - fn from_vec(vec: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>) -> Self { - PatStack { pats: vec } + PatStack { pats: smallvec![pat] } } fn is_empty(&self) -> bool { @@ -416,37 +595,18 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> { self.pats.iter().copied() } - // Recursively expand the first pattern into its subpatterns. Only useful if the pattern is an - // or-pattern. Panics if `self` is empty. + // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is + // an or-pattern. Panics if `self` is empty. fn expand_or_pat<'a>(&'a self) -> impl Iterator> + Captures<'a> { - self.head().iter_fields().map(move |pat| { - let mut new_patstack = PatStack::from_pattern(pat); - new_patstack.pats.extend_from_slice(&self.pats[1..]); - new_patstack + self.head().flatten_or_pat().into_iter().map(move |pat| { + let mut new = self.clone(); + new.pats[0] = pat; + new }) } - // Recursively expand all patterns into their subpatterns and push each `PatStack` to matrix. - fn expand_and_extend<'a>(&'a self, matrix: &mut Matrix<'p, 'tcx>) { - if !self.is_empty() && self.head().is_or_pat() { - for pat in self.head().iter_fields() { - let mut new_patstack = PatStack::from_pattern(pat); - new_patstack.pats.extend_from_slice(&self.pats[1..]); - if !new_patstack.is_empty() && new_patstack.head().is_or_pat() { - new_patstack.expand_and_extend(matrix); - } else if !new_patstack.is_empty() { - matrix.push(new_patstack); - } - } - } - } - - /// This computes `S(self.head().ctor(), self)`. See top of the file for explanations. - /// - /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing - /// fields filled with wild patterns. - /// - /// This is roughly the inverse of `Constructor::apply`. + /// This computes `specialize(ctor, self)`. See top of the file for explanations. + /// Only call if `ctor.is_covered_by(self.head().ctor())` is true. fn pop_head_constructor( &self, pcx: &PatCtxt<'_, 'p, 'tcx>, @@ -454,15 +614,15 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> { ) -> PatStack<'p, 'tcx> { // We pop the head pattern and push the new fields extracted from the arguments of // `self.head()`. - let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(pcx, ctor); - new_fields.extend_from_slice(&self.pats[1..]); - PatStack::from_vec(new_fields) + let mut new_pats = self.head().specialize(pcx, ctor); + new_pats.extend_from_slice(&self.pats[1..]); + PatStack { pats: new_pats } } } -/// Pretty-printing for matrix row. impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // We pretty-print similarly to the `Debug` impl of `Matrix`. write!(f, "+")?; for pat in self.iter() { write!(f, " {pat:?} +")?; @@ -471,45 +631,179 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> { } } -/// A 2D matrix. +/// A row of the matrix. #[derive(Clone)] -pub(super) struct Matrix<'p, 'tcx> { - pub patterns: Vec>, +struct MatrixRow<'p, 'tcx> { + // The patterns in the row. + pats: PatStack<'p, 'tcx>, + /// Whether the original arm had a guard. This is inherited when specializing. + is_under_guard: bool, + /// When we specialize, we remember which row of the original matrix produced a given row of the + /// specialized matrix. When we unspecialize, we use this to propagate reachability back up the + /// callstack. + parent_row: usize, + /// False when the matrix is just built. This is set to `true` by + /// [`compute_exhaustiveness_and_reachability`] if the arm is found to be reachable. + /// This is reset to `false` when specializing. + reachable: bool, } -impl<'p, 'tcx> Matrix<'p, 'tcx> { - fn empty() -> Self { - Matrix { patterns: vec![] } +impl<'p, 'tcx> MatrixRow<'p, 'tcx> { + fn is_empty(&self) -> bool { + self.pats.is_empty() } + fn len(&self) -> usize { + self.pats.len() + } + + fn head(&self) -> &'p DeconstructedPat<'p, 'tcx> { + self.pats.head() + } + + fn iter(&self) -> impl Iterator> { + self.pats.iter() + } + + // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is + // an or-pattern. Panics if `self` is empty. + fn expand_or_pat<'a>(&'a self) -> impl Iterator> + Captures<'a> { + self.pats.expand_or_pat().map(|patstack| MatrixRow { + pats: patstack, + parent_row: self.parent_row, + is_under_guard: self.is_under_guard, + reachable: false, + }) + } + + /// This computes `specialize(ctor, self)`. See top of the file for explanations. + /// Only call if `ctor.is_covered_by(self.head().ctor())` is true. + fn pop_head_constructor( + &self, + pcx: &PatCtxt<'_, 'p, 'tcx>, + ctor: &Constructor<'tcx>, + parent_row: usize, + ) -> MatrixRow<'p, 'tcx> { + MatrixRow { + pats: self.pats.pop_head_constructor(pcx, ctor), + parent_row, + is_under_guard: self.is_under_guard, + reachable: false, + } + } +} + +impl<'p, 'tcx> fmt::Debug for MatrixRow<'p, 'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.pats.fmt(f) + } +} + +/// A 2D matrix. Represents a list of pattern-tuples under investigation. +/// +/// Invariant: each row must have the same length, and each column must have the same type. +/// +/// Invariant: the first column must not contain or-patterns. This is handled by +/// [`Matrix::expand_and_push`]. +/// +/// In fact each column corresponds to a place inside the scrutinee of the match. E.g. after +/// specializing `(,)` and `Some` on a pattern of type `(Option, bool)`, the first column of +/// the matrix will correspond to `scrutinee.0.Some.0` and the second column to `scrutinee.1`. +#[derive(Clone)] +struct Matrix<'p, 'tcx> { + rows: Vec>, + /// Stores an extra fictitious row full of wildcards. Mostly used to keep track of the type of + /// each column. This must obey the same invariants as the real rows. + wildcard_row: PatStack<'p, 'tcx>, +} + +impl<'p, 'tcx> Matrix<'p, 'tcx> { /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively - /// expands it. - fn push(&mut self, row: PatStack<'p, 'tcx>) { + /// expands it. Internal method, prefer [`Matrix::new`]. + fn expand_and_push(&mut self, row: MatrixRow<'p, 'tcx>) { if !row.is_empty() && row.head().is_or_pat() { - row.expand_and_extend(self); + // Expand nested or-patterns. + for new_row in row.expand_or_pat() { + self.rows.push(new_row); + } } else { - self.patterns.push(row); + self.rows.push(row); + } + } + + /// Build a new matrix from an iterator of `MatchArm`s. + fn new(cx: &MatchCheckCtxt<'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>) -> Self { + let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty, DUMMY_SP)); + let wildcard_row = PatStack::from_pattern(wild_pattern); + let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), wildcard_row }; + for (row_id, arm) in arms.iter().enumerate() { + let v = MatrixRow { + pats: PatStack::from_pattern(arm.pat), + parent_row: row_id, // dummy, we won't read it + is_under_guard: arm.has_guard, + reachable: false, + }; + matrix.expand_and_push(v); + } + matrix + } + + fn head_ty(&self) -> Option> { + if self.column_count() == 0 { + return None; + } + + let mut ty = self.wildcard_row.head().ty(); + // If the type is opaque and it is revealed anywhere in the column, we take the revealed + // version. Otherwise we could encounter constructors for the revealed type and crash. + let is_opaque = |ty: Ty<'tcx>| matches!(ty.kind(), ty::Alias(ty::Opaque, ..)); + if is_opaque(ty) { + for pat in self.heads() { + let pat_ty = pat.ty(); + if !is_opaque(pat_ty) { + ty = pat_ty; + break; + } + } } + Some(ty) + } + fn column_count(&self) -> usize { + self.wildcard_row.len() } - /// Iterate over the first component of each row + fn rows<'a>( + &'a self, + ) -> impl Iterator> + Clone + DoubleEndedIterator + ExactSizeIterator + { + self.rows.iter() + } + fn rows_mut<'a>( + &'a mut self, + ) -> impl Iterator> + DoubleEndedIterator + ExactSizeIterator + { + self.rows.iter_mut() + } + + /// Iterate over the first pattern of each row. fn heads<'a>( &'a self, ) -> impl Iterator> + Clone + Captures<'a> { - self.patterns.iter().map(|r| r.head()) + self.rows().map(|r| r.head()) } - /// This computes `S(constructor, self)`. See top of the file for explanations. + /// This computes `specialize(ctor, self)`. See top of the file for explanations. fn specialize_constructor( &self, pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>, ) -> Matrix<'p, 'tcx> { - let mut matrix = Matrix::empty(); - for row in &self.patterns { + let wildcard_row = self.wildcard_row.pop_head_constructor(pcx, ctor); + let mut matrix = Matrix { rows: Vec::new(), wildcard_row }; + for (i, row) in self.rows().enumerate() { if ctor.is_covered_by(pcx, row.head().ctor()) { - let new_row = row.pop_head_constructor(pcx, ctor); - matrix.push(new_row); + let new_row = row.pop_head_constructor(pcx, ctor, i); + matrix.expand_and_push(new_row); } } matrix @@ -529,12 +823,12 @@ impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "\n")?; - let Matrix { patterns: m, .. } = self; + let Matrix { rows, .. } = self; let pretty_printed_matrix: Vec> = - m.iter().map(|row| row.iter().map(|pat| format!("{pat:?}")).collect()).collect(); + rows.iter().map(|row| row.iter().map(|pat| format!("{pat:?}")).collect()).collect(); - let column_count = m.iter().map(|row| row.len()).next().unwrap_or(0); - assert!(m.iter().all(|row| row.len() == column_count)); + let column_count = rows.iter().map(|row| row.len()).next().unwrap_or(0); + assert!(rows.iter().all(|row| row.len() == column_count)); let column_widths: Vec = (0..column_count) .map(|col| pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)) .collect(); @@ -552,129 +846,17 @@ impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> { } } -/// This carries the results of computing usefulness, as described at the top of the file. When -/// checking usefulness of a match branch, we use the `NoWitnesses` variant, which also keeps track -/// of potential unreachable sub-patterns (in the presence of or-patterns). When checking -/// exhaustiveness of a whole match, we use the `WithWitnesses` variant, which carries a list of -/// witnesses of non-exhaustiveness when there are any. -/// Which variant to use is dictated by `ArmType`. -#[derive(Debug, Clone)] -enum Usefulness<'tcx> { - /// If we don't care about witnesses, simply remember if the pattern was useful. - NoWitnesses { useful: bool }, - /// Carries a list of witnesses of non-exhaustiveness. If empty, indicates that the whole - /// pattern is unreachable. - WithWitnesses(Vec>), -} - -impl<'tcx> Usefulness<'tcx> { - fn new_useful(preference: ArmType) -> Self { - match preference { - // A single (empty) witness of reachability. - FakeExtraWildcard => WithWitnesses(vec![WitnessStack(vec![])]), - RealArm => NoWitnesses { useful: true }, - } - } - - fn new_not_useful(preference: ArmType) -> Self { - match preference { - FakeExtraWildcard => WithWitnesses(vec![]), - RealArm => NoWitnesses { useful: false }, - } - } - - fn is_useful(&self) -> bool { - match self { - Usefulness::NoWitnesses { useful } => *useful, - Usefulness::WithWitnesses(witnesses) => !witnesses.is_empty(), - } - } - - /// Combine usefulnesses from two branches. This is an associative operation. - fn extend(&mut self, other: Self) { - match (&mut *self, other) { - (WithWitnesses(_), WithWitnesses(o)) if o.is_empty() => {} - (WithWitnesses(s), WithWitnesses(o)) if s.is_empty() => *self = WithWitnesses(o), - (WithWitnesses(s), WithWitnesses(o)) => s.extend(o), - (NoWitnesses { useful: s_useful }, NoWitnesses { useful: o_useful }) => { - *s_useful = *s_useful || o_useful - } - _ => unreachable!(), - } - } - - /// After calculating usefulness after a specialization, call this to reconstruct a usefulness - /// that makes sense for the matrix pre-specialization. This new usefulness can then be merged - /// with the results of specializing with the other constructors. - fn apply_constructor( - self, - pcx: &PatCtxt<'_, '_, 'tcx>, - matrix: &Matrix<'_, 'tcx>, // used to compute missing ctors - ctor: &Constructor<'tcx>, - ) -> Self { - match self { - NoWitnesses { .. } => self, - WithWitnesses(ref witnesses) if witnesses.is_empty() => self, - WithWitnesses(witnesses) => { - let new_witnesses = if let Constructor::Missing { .. } = ctor { - let mut missing = ConstructorSet::for_ty(pcx.cx, pcx.ty) - .compute_missing(pcx, matrix.heads().map(DeconstructedPat::ctor)); - if missing.iter().any(|c| c.is_non_exhaustive()) { - // We only report `_` here; listing other constructors would be redundant. - missing = vec![Constructor::NonExhaustive]; - } - - // We got the special `Missing` constructor, so each of the missing constructors - // gives a new pattern that is not caught by the match. - // We construct for each missing constructor a version of this constructor with - // wildcards for fields, i.e. that matches everything that can be built with it. - // For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get - // the pattern `Some(_)`. - let new_patterns: Vec> = missing - .into_iter() - .map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor.clone())) - .collect(); - - witnesses - .into_iter() - .flat_map(|witness| { - new_patterns.iter().map(move |pat| { - let mut stack = witness.clone(); - stack.0.push(pat.clone()); - stack - }) - }) - .collect() - } else { - witnesses - .into_iter() - .map(|witness| witness.apply_constructor(pcx, &ctor)) - .collect() - }; - WithWitnesses(new_witnesses) - } - } - } -} - -#[derive(Copy, Clone, Debug)] -enum ArmType { - FakeExtraWildcard, - RealArm, -} - /// A witness-tuple of non-exhaustiveness for error reporting, represented as a list of patterns (in -/// reverse order of construction) with wildcards inside to represent elements that can take any -/// inhabitant of the type as a value. +/// reverse order of construction). /// /// This mirrors `PatStack`: they function similarly, except `PatStack` contains user patterns we /// are inspecting, and `WitnessStack` contains witnesses we are constructing. -/// FIXME(Nadrieril): use the same order of patterns for both +/// FIXME(Nadrieril): use the same order of patterns for both. /// -/// A `WitnessStack` should have the same types and length as the `PatStacks` we are inspecting -/// (except we store the patterns in reverse order). Because Rust `match` is always against a single -/// pattern, at the end the stack will have length 1. In the middle of the algorithm, it can contain -/// multiple patterns. +/// A `WitnessStack` should have the same types and length as the `PatStack`s we are inspecting +/// (except we store the patterns in reverse order). The same way `PatStack` starts with length 1, +/// at the end of the algorithm this will have length 1. In the middle of the algorithm, it can +/// contain multiple patterns. /// /// For example, if we are constructing a witness for the match against /// @@ -689,6 +871,7 @@ enum ArmType { /// ``` /// /// We'll perform the following steps (among others): +/// ```text /// - Start with a matrix representing the match /// `PatStack(vec![Pair(None, _)])` /// `PatStack(vec![Pair(_, false)])` @@ -711,8 +894,11 @@ enum ArmType { /// `WitnessStack(vec![true, Some(_)])` /// - Apply `Pair` /// `WitnessStack(vec![Pair(Some(_), true)])` +/// ``` /// /// The final `Pair(Some(_), true)` is then the resulting witness. +/// +/// See the top of the file for more detailed explanations and examples. #[derive(Debug, Clone)] pub(crate) struct WitnessStack<'tcx>(Vec>); @@ -723,158 +909,235 @@ impl<'tcx> WitnessStack<'tcx> { self.0.into_iter().next().unwrap() } - /// Constructs a partial witness for a pattern given a list of - /// patterns expanded by the specialization step. - /// - /// When a pattern P is discovered to be useful, this function is used bottom-up - /// to reconstruct a complete witness, e.g., a pattern P' that covers a subset - /// of values, V, where each value in that set is not covered by any previously - /// used patterns and is covered by the pattern P'. Examples: + /// Reverses specialization by the `Missing` constructor by pushing a whole new pattern. + fn push_pattern(&mut self, pat: WitnessPat<'tcx>) { + self.0.push(pat); + } + + /// Reverses specialization. Given a witness obtained after specialization, this constructs a + /// new witness valid for before specialization. See the section on `unspecialize` at the top of + /// the file. /// - /// left_ty: tuple of 3 elements - /// pats: [10, 20, _] => (10, 20, _) + /// Examples: + /// ```text + /// ctor: tuple of 2 elements + /// pats: [false, "foo", _, true] + /// result: [(false, "foo"), _, true] /// - /// left_ty: struct X { a: (bool, &'static str), b: usize} - /// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 } - fn apply_constructor(mut self, pcx: &PatCtxt<'_, '_, 'tcx>, ctor: &Constructor<'tcx>) -> Self { - let pat = { - let len = self.0.len(); - let arity = ctor.arity(pcx); - let fields = self.0.drain((len - arity)..).rev().collect(); - WitnessPat::new(ctor.clone(), fields, pcx.ty) - }; - + /// ctor: Enum::Variant { a: (bool, &'static str), b: usize} + /// pats: [(false, "foo"), _, true] + /// result: [Enum::Variant { a: (false, "foo"), b: _ }, true] + /// ``` + fn apply_constructor(&mut self, pcx: &PatCtxt<'_, '_, 'tcx>, ctor: &Constructor<'tcx>) { + let len = self.0.len(); + let arity = ctor.arity(pcx); + let fields = self.0.drain((len - arity)..).rev().collect(); + let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty); self.0.push(pat); - - self } } -/// Algorithm from . -/// The algorithm from the paper has been modified to correctly handle empty -/// types. The changes are: -/// (0) We don't exit early if the pattern matrix has zero rows. We just -/// continue to recurse over columns. -/// (1) all_constructors will only return constructors that are statically -/// possible. E.g., it will only return `Ok` for `Result`. +/// Represents a set of pattern-tuples that are witnesses of non-exhaustiveness for error +/// reporting. This has similar invariants as `Matrix` does. +/// +/// The `WitnessMatrix` returned by [`compute_exhaustiveness_and_reachability`] obeys the invariant +/// that the union of the input `Matrix` and the output `WitnessMatrix` together matches the type +/// exhaustively. /// -/// This finds whether a (row) vector `v` of patterns is 'useful' in relation -/// to a set of such vectors `m` - this is defined as there being a set of -/// inputs that will match `v` but not any of the sets in `m`. +/// Just as the `Matrix` starts with a single column, by the end of the algorithm, this has a single +/// column, which contains the patterns that are missing for the match to be exhaustive. +#[derive(Debug, Clone)] +pub struct WitnessMatrix<'tcx>(Vec>); + +impl<'tcx> WitnessMatrix<'tcx> { + /// New matrix with no witnesses. + fn empty() -> Self { + WitnessMatrix(vec![]) + } + /// New matrix with one `()` witness, i.e. with no columns. + fn unit_witness() -> Self { + WitnessMatrix(vec![WitnessStack(vec![])]) + } + + /// Whether this has any witnesses. + fn is_empty(&self) -> bool { + self.0.is_empty() + } + /// Asserts that there is a single column and returns the patterns in it. + fn single_column(self) -> Vec> { + self.0.into_iter().map(|w| w.single_pattern()).collect() + } + + /// Reverses specialization by the `Missing` constructor by pushing a whole new pattern. + fn push_pattern(&mut self, pat: WitnessPat<'tcx>) { + for witness in self.0.iter_mut() { + witness.push_pattern(pat.clone()) + } + } + + /// Reverses specialization by `ctor`. See the section on `unspecialize` at the top of the file. + fn apply_constructor( + &mut self, + pcx: &PatCtxt<'_, '_, 'tcx>, + missing_ctors: &[Constructor<'tcx>], + ctor: &Constructor<'tcx>, + report_individual_missing_ctors: bool, + ) { + if self.is_empty() { + return; + } + if matches!(ctor, Constructor::Missing) { + // We got the special `Missing` constructor that stands for the constructors not present + // in the match. + if !report_individual_missing_ctors { + // Report `_` as missing. + let pat = WitnessPat::wild_from_ctor(pcx, Constructor::Wildcard); + self.push_pattern(pat); + } else if missing_ctors.iter().any(|c| c.is_non_exhaustive()) { + // We need to report a `_` anyway, so listing other constructors would be redundant. + // `NonExhaustive` is displayed as `_` just like `Wildcard`, but it will be picked + // up by diagnostics to add a note about why `_` is required here. + let pat = WitnessPat::wild_from_ctor(pcx, Constructor::NonExhaustive); + self.push_pattern(pat); + } else { + // For each missing constructor `c`, we add a `c(_, _, _)` witness appropriately + // filled with wildcards. + let mut ret = Self::empty(); + for ctor in missing_ctors { + let pat = WitnessPat::wild_from_ctor(pcx, ctor.clone()); + // Clone `self` and add `c(_, _, _)` to each of its witnesses. + let mut wit_matrix = self.clone(); + wit_matrix.push_pattern(pat); + ret.extend(wit_matrix); + } + *self = ret; + } + } else { + // Any other constructor we unspecialize as expected. + for witness in self.0.iter_mut() { + witness.apply_constructor(pcx, ctor) + } + } + } + + /// Merges the witnesses of two matrices. Their column types must match. + fn extend(&mut self, other: Self) { + self.0.extend(other.0) + } +} + +/// The core of the algorithm. /// -/// All the patterns at each column of the `matrix ++ v` matrix must have the same type. +/// This recursively computes witnesses of the non-exhaustiveness of `matrix` (if any). Also tracks +/// usefulness of each row in the matrix (in `row.reachable`). We track reachability of each +/// subpattern using interior mutability in `DeconstructedPat`. /// -/// This is used both for reachability checking (if a pattern isn't useful in -/// relation to preceding patterns, it is not reachable) and exhaustiveness -/// checking (if a wildcard pattern is useful in relation to a matrix, the -/// matrix isn't exhaustive). +/// The input `Matrix` and the output `WitnessMatrix` together match the type exhaustively. /// -/// `is_under_guard` is used to inform if the pattern has a guard. If it -/// has one it must not be inserted into the matrix. This shouldn't be -/// relied on for soundness. -#[instrument(level = "debug", skip(cx, matrix, lint_root), ret)] -fn is_useful<'p, 'tcx>( +/// The key steps are: +/// - specialization, where we dig into the rows that have a specific constructor and call ourselves +/// recursively; +/// - unspecialization, where we lift the results from the previous step into results for this step +/// (using `apply_constructor` and by updating `row.reachable` for each parent row). +/// This is all explained at the top of the file. +#[instrument(level = "debug", skip(cx, is_top_level), ret)] +fn compute_exhaustiveness_and_reachability<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, - matrix: &Matrix<'p, 'tcx>, - v: &PatStack<'p, 'tcx>, - witness_preference: ArmType, - lint_root: HirId, - is_under_guard: bool, + matrix: &mut Matrix<'p, 'tcx>, is_top_level: bool, -) -> Usefulness<'tcx> { - debug!(?matrix, ?v); - let Matrix { patterns: rows, .. } = matrix; - - // The base case. We are pattern-matching on () and the return value is - // based on whether our matrix has a row or not. - // NOTE: This could potentially be optimized by checking rows.is_empty() - // first and then, if v is non-empty, the return value is based on whether - // the type of the tuple we're checking is inhabited or not. - if v.is_empty() { - let ret = if rows.is_empty() { - Usefulness::new_useful(witness_preference) - } else { - Usefulness::new_not_useful(witness_preference) - }; - debug!(?ret); - return ret; - } - - debug_assert!(rows.iter().all(|r| r.len() == v.len())); - - // If the first pattern is an or-pattern, expand it. - let mut ret = Usefulness::new_not_useful(witness_preference); - if v.head().is_or_pat() { - debug!("expanding or-pattern"); - // We try each or-pattern branch in turn. - let mut matrix = matrix.clone(); - for v in v.expand_or_pat() { - debug!(?v); - let usefulness = ensure_sufficient_stack(|| { - is_useful(cx, &matrix, &v, witness_preference, lint_root, is_under_guard, false) - }); - debug!(?usefulness); - ret.extend(usefulness); - // If pattern has a guard don't add it to the matrix. - if !is_under_guard { - // We push the already-seen patterns into the matrix in order to detect redundant - // branches like `Some(_) | Some(0)`. - matrix.push(v); +) -> WitnessMatrix<'tcx> { + debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); + + let Some(ty) = matrix.head_ty() else { + // The base case: there are no columns in the matrix. We are morally pattern-matching on (). + // A row is reachable iff it has no (unguarded) rows above it. + for row in matrix.rows_mut() { + // All rows are reachable until we find one without a guard. + row.reachable = true; + if !row.is_under_guard { + // There's an unguarded row, so the match is exhaustive, and any subsequent row is + // unreachable. + return WitnessMatrix::empty(); } } - } else { - let mut ty = v.head().ty(); + // No (unguarded) rows, so the match is not exhaustive. We return a new witness. + return WitnessMatrix::unit_witness(); + }; - // Opaque types can't get destructured/split, but the patterns can - // actually hint at hidden types, so we use the patterns' types instead. - if let ty::Alias(ty::Opaque, ..) = ty.kind() { - if let Some(row) = rows.first() { - ty = row.head().ty(); - } + debug!("ty: {ty:?}"); + let pcx = &PatCtxt { cx, ty, is_top_level }; + + // Analyze the constructors present in this column. + let ctors = matrix.heads().map(|p| p.ctor()); + let split_set = ConstructorSet::for_ty(pcx.cx, pcx.ty).split(pcx, ctors); + + let all_missing = split_set.present.is_empty(); + let always_report_all = is_top_level && !IntRange::is_integral(pcx.ty); + // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". + let report_individual_missing_ctors = always_report_all || !all_missing; + + let mut split_ctors = split_set.present; + let mut only_report_missing = false; + if !split_set.missing.is_empty() { + // We need to iterate over a full set of constructors, so we add `Missing` to represent the + // missing ones. This is explained under "Constructor Splitting" at the top of this file. + split_ctors.push(Constructor::Missing); + // For diagnostic purposes we choose to only report the constructors that are missing. Since + // `Missing` matches only the wildcard rows, it matches fewer rows than any normal + // constructor and is therefore guaranteed to result in more witnesses. So skipping the + // other constructors does not jeopardize correctness. + only_report_missing = true; + } + + let mut ret = WitnessMatrix::empty(); + for ctor in split_ctors { + debug!("specialize({:?})", ctor); + // Dig into rows that match `ctor`. + let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor); + let mut witnesses = ensure_sufficient_stack(|| { + compute_exhaustiveness_and_reachability(cx, &mut spec_matrix, false) + }); + + if !only_report_missing || matches!(ctor, Constructor::Missing) { + // Transform witnesses for `spec_matrix` into witnesses for `matrix`. + witnesses.apply_constructor( + pcx, + &split_set.missing, + &ctor, + report_individual_missing_ctors, + ); + // Accumulate the found witnesses. + ret.extend(witnesses); } - debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span()); - let pcx = &PatCtxt { cx, ty, span: v.head().span(), is_top_level }; - - let v_ctor = v.head().ctor(); - debug!(?v_ctor); - // We split the head constructor of `v`. - let split_ctors = v_ctor.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); - // For each constructor, we compute whether there's a value that starts with it that would - // witness the usefulness of `v`. - let start_matrix = &matrix; - for ctor in split_ctors { - debug!("specialize({:?})", ctor); - // We cache the result of `Fields::wildcards` because it is used a lot. - let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor); - let v = v.pop_head_constructor(pcx, &ctor); - let usefulness = ensure_sufficient_stack(|| { - is_useful( - cx, - &spec_matrix, - &v, - witness_preference, - lint_root, - is_under_guard, - false, - ) - }); - let usefulness = usefulness.apply_constructor(pcx, start_matrix, &ctor); - ret.extend(usefulness); + + // A parent row is useful if any of its children is. + for child_row in spec_matrix.rows() { + let parent_row = &mut matrix.rows[child_row.parent_row]; + parent_row.reachable = parent_row.reachable || child_row.reachable; } } - if ret.is_useful() { - v.head().set_reachable(); + // Record that the subpattern is reachable. + for row in matrix.rows() { + if row.reachable { + row.head().set_reachable(); + } } ret } /// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that -/// inspect the same subvalue". +/// inspect the same subvalue/place". /// This is used to traverse patterns column-by-column for lints. Despite similarities with -/// `is_useful`, this is a different traversal. Notably this is linear in the depth of patterns, -/// whereas `is_useful` is worst-case exponential (exhaustiveness is NP-complete). +/// [`compute_exhaustiveness_and_reachability`], this does a different traversal. Notably this is +/// linear in the depth of patterns, whereas `compute_exhaustiveness_and_reachability` is worst-case +/// exponential (exhaustiveness is NP-complete). The core difference is that we treat sub-columns +/// separately. +/// +/// This must not contain an or-pattern. `specialize` takes care to expand them. +/// +/// This is not used in the main algorithm; only in lints. #[derive(Debug)] struct PatternColumn<'p, 'tcx> { patterns: Vec<&'p DeconstructedPat<'p, 'tcx>>, @@ -907,17 +1170,19 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { Some(first_ty) } + /// Do constructor splitting on the constructors of the column. fn analyze_ctors(&self, pcx: &PatCtxt<'_, 'p, 'tcx>) -> SplitConstructorSet<'tcx> { let column_ctors = self.patterns.iter().map(|p| p.ctor()); ConstructorSet::for_ty(pcx.cx, pcx.ty).split(pcx, column_ctors) } + fn iter<'a>(&'a self) -> impl Iterator> + Captures<'a> { self.patterns.iter().copied() } /// Does specialization: given a constructor, this takes the patterns from the column that match /// the constructor, and outputs their fields. - /// This returns one column per field of the constructor. The normally all have the same length + /// This returns one column per field of the constructor. They usually all have the same length /// (the number of patterns in `self` that matched `ctor`), except that we expand or-patterns /// which may change the lengths. fn specialize(&self, pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Vec { @@ -934,7 +1199,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { let relevant_patterns = self.patterns.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor())); for pat in relevant_patterns { - let specialized = pat.specialize(pcx, &ctor); + let specialized = pat.specialize(pcx, ctor); for (subpat, column) in specialized.iter().zip(&mut specialized_columns) { if subpat.is_or_pat() { column.patterns.extend(subpat.flatten_or_pat()) @@ -963,7 +1228,7 @@ fn collect_nonexhaustive_missing_variants<'p, 'tcx>( let Some(ty) = column.head_ty() else { return Vec::new(); }; - let pcx = &PatCtxt { cx, ty, span: DUMMY_SP, is_top_level: false }; + let pcx = &PatCtxt { cx, ty, is_top_level: false }; let set = column.analyze_ctors(pcx); if set.present.is_empty() { @@ -1004,16 +1269,15 @@ fn collect_nonexhaustive_missing_variants<'p, 'tcx>( } /// Traverse the patterns to warn the user about ranges that overlap on their endpoints. -#[instrument(level = "debug", skip(cx, lint_root))] +#[instrument(level = "debug", skip(cx))] fn lint_overlapping_range_endpoints<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, column: &PatternColumn<'p, 'tcx>, - lint_root: HirId, ) { let Some(ty) = column.head_ty() else { return; }; - let pcx = &PatCtxt { cx, ty, span: DUMMY_SP, is_top_level: false }; + let pcx = &PatCtxt { cx, ty, is_top_level: false }; let set = column.analyze_ctors(pcx); @@ -1027,7 +1291,7 @@ fn lint_overlapping_range_endpoints<'p, 'tcx>( .collect(); cx.tcx.emit_spanned_lint( lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, - lint_root, + cx.match_lint_level, this_span, OverlappingRangeEndpoints { overlap: overlaps, range: this_span }, ); @@ -1072,7 +1336,7 @@ fn lint_overlapping_range_endpoints<'p, 'tcx>( // Recurse into the fields. for ctor in set.present { for col in column.specialize(pcx, &ctor) { - lint_overlapping_range_endpoints(cx, &col, lint_root); + lint_overlapping_range_endpoints(cx, &col); } } } @@ -1107,30 +1371,24 @@ pub(crate) struct UsefulnessReport<'p, 'tcx> { pub(crate) non_exhaustiveness_witnesses: Vec>, } -/// The entrypoint for the usefulness algorithm. Computes whether a match is exhaustive and which -/// of its arms are reachable. -/// -/// Note: the input patterns must have been lowered through -/// `check_match::MatchVisitor::lower_pattern`. +/// The entrypoint for this file. Computes whether a match is exhaustive and which of its arms are +/// reachable. #[instrument(skip(cx, arms), level = "debug")] pub(crate) fn compute_match_usefulness<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], - lint_root: HirId, scrut_ty: Ty<'tcx>, - scrut_span: Span, ) -> UsefulnessReport<'p, 'tcx> { - let mut matrix = Matrix::empty(); + let mut matrix = Matrix::new(cx, arms, scrut_ty); + let non_exhaustiveness_witnesses = + compute_exhaustiveness_and_reachability(cx, &mut matrix, true); + + let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column(); let arm_usefulness: Vec<_> = arms .iter() .copied() .map(|arm| { debug!(?arm); - let v = PatStack::from_pattern(arm.pat); - is_useful(cx, &matrix, &v, RealArm, arm.hir_id, arm.has_guard, true); - if !arm.has_guard { - matrix.push(v); - } let reachability = if arm.pat.is_reachable() { Reachability::Reachable(arm.pat.unreachable_spans()) } else { @@ -1139,28 +1397,20 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( (arm, reachability) }) .collect(); + let report = UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }; - let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty, DUMMY_SP)); - let v = PatStack::from_pattern(wild_pattern); - let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, lint_root, false, true); - let non_exhaustiveness_witnesses: Vec<_> = match usefulness { - WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(), - NoWitnesses { .. } => bug!(), - }; - - let pat_column = arms.iter().flat_map(|arm| arm.pat.flatten_or_pat()).collect::>(); - let pat_column = PatternColumn::new(pat_column); - lint_overlapping_range_endpoints(cx, &pat_column, lint_root); + let pat_column = PatternColumn::new(matrix.heads().collect()); + // Lint on ranges that overlap on their endpoints, which is likely a mistake. + lint_overlapping_range_endpoints(cx, &pat_column); // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. - if cx.refutable && non_exhaustiveness_witnesses.is_empty() { + if cx.refutable && report.non_exhaustiveness_witnesses.is_empty() { if !matches!( - cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).0, + cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, cx.match_lint_level).0, rustc_session::lint::Level::Allow ) { let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column); - if !witnesses.is_empty() { // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` // is not exhaustive enough. @@ -1168,11 +1418,11 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`. cx.tcx.emit_spanned_lint( NON_EXHAUSTIVE_OMITTED_PATTERNS, - lint_root, - scrut_span, + cx.match_lint_level, + cx.scrut_span, NonExhaustiveOmittedPattern { scrut_ty, - uncovered: Uncovered::new(scrut_span, cx, witnesses), + uncovered: Uncovered::new(cx.scrut_span, cx, witnesses), }, ); } @@ -1201,5 +1451,5 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( } } - UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses } + report } diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index c3b2309b7cdae..547da7e700794 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -31,8 +31,8 @@ const INDENT: &str = " "; macro_rules! print_indented { ($writer:ident, $s:expr, $indent_lvl:expr) => { - let indent = (0..$indent_lvl).map(|_| INDENT).collect::>().concat(); - writeln!($writer, "{}{}", indent, $s).expect("unable to write to ThirPrinter"); + $writer.indent($indent_lvl); + writeln!($writer, "{}", $s).expect("unable to write to ThirPrinter"); }; } @@ -48,6 +48,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { Self { thir, fmt: String::new() } } + fn indent(&mut self, level: usize) { + for _ in 0..level { + self.fmt.push_str(INDENT); + } + } + fn print(&mut self) { print_indented!(self, "params: [", 0); for param in self.thir.params.iter() { @@ -636,6 +642,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { PatKind::Wild => { print_indented!(self, "Wild", depth_lvl + 1); } + PatKind::Never => { + print_indented!(self, "Never", depth_lvl + 1); + } PatKind::AscribeUserType { ascription, subpattern } => { print_indented!(self, "AscribeUserType: {", depth_lvl + 1); print_indented!(self, format!("ascription: {:?}", ascription), depth_lvl + 2); diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 61664eb2a6fb0..7199db677c464 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -16,7 +16,6 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs index 163d74cc9cfb0..de1ca8d823b3e 100644 --- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs +++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs @@ -1,10 +1,8 @@ use crate::elaborate_drops::DropFlagState; use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind}; -use rustc_middle::ty::TyCtxt; use rustc_target::abi::VariantIdx; -use super::indexes::MovePathIndex; -use super::move_paths::{InitKind, LookupResult, MoveData}; +use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex}; use super::MoveDataParamEnv; pub fn move_path_children_matching<'tcx, F>( @@ -30,8 +28,6 @@ where } pub fn on_lookup_result_bits<'tcx, F>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, move_data: &MoveData<'tcx>, lookup_result: LookupResult, each_child: F, @@ -42,13 +38,11 @@ pub fn on_lookup_result_bits<'tcx, F>( LookupResult::Parent(..) => { // access to untracked value - do not touch children } - LookupResult::Exact(e) => on_all_children_bits(tcx, body, move_data, e, each_child), + LookupResult::Exact(e) => on_all_children_bits(move_data, e, each_child), } } pub fn on_all_children_bits<'tcx, F>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, move_data: &MoveData<'tcx>, move_path_index: MovePathIndex, mut each_child: F, @@ -56,8 +50,6 @@ pub fn on_all_children_bits<'tcx, F>( F: FnMut(MovePathIndex), { fn on_all_children_bits<'tcx, F>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, move_data: &MoveData<'tcx>, move_path_index: MovePathIndex, each_child: &mut F, @@ -68,15 +60,14 @@ pub fn on_all_children_bits<'tcx, F>( let mut next_child_index = move_data.move_paths[move_path_index].first_child; while let Some(child_index) = next_child_index { - on_all_children_bits(tcx, body, move_data, child_index, each_child); + on_all_children_bits(move_data, child_index, each_child); next_child_index = move_data.move_paths[child_index].next_sibling; } } - on_all_children_bits(tcx, body, move_data, move_path_index, &mut each_child); + on_all_children_bits(move_data, move_path_index, &mut each_child); } pub fn drop_flag_effects_for_function_entry<'tcx, F>( - tcx: TyCtxt<'tcx>, body: &Body<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, mut callback: F, @@ -87,14 +78,13 @@ pub fn drop_flag_effects_for_function_entry<'tcx, F>( for arg in body.args_iter() { let place = mir::Place::from(arg); let lookup_result = move_data.rev_lookup.find(place.as_ref()); - on_lookup_result_bits(tcx, body, move_data, lookup_result, |mpi| { + on_lookup_result_bits(move_data, lookup_result, |mpi| { callback(mpi, DropFlagState::Present) }); } } pub fn drop_flag_effects_for_location<'tcx, F>( - tcx: TyCtxt<'tcx>, body: &Body<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, loc: Location, @@ -110,7 +100,7 @@ pub fn drop_flag_effects_for_location<'tcx, F>( let path = mi.move_path_index(move_data); debug!("moving out of path {:?}", move_data.move_paths[path]); - on_all_children_bits(tcx, body, move_data, path, |mpi| callback(mpi, DropFlagState::Absent)) + on_all_children_bits(move_data, path, |mpi| callback(mpi, DropFlagState::Absent)) } // Drop does not count as a move but we should still consider the variable uninitialized. @@ -118,24 +108,17 @@ pub fn drop_flag_effects_for_location<'tcx, F>( body.stmt_at(loc).right() { if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) { - on_all_children_bits(tcx, body, move_data, mpi, |mpi| { - callback(mpi, DropFlagState::Absent) - }) + on_all_children_bits(move_data, mpi, |mpi| callback(mpi, DropFlagState::Absent)) } } debug!("drop_flag_effects: assignment for location({:?})", loc); - for_location_inits(tcx, body, move_data, loc, |mpi| callback(mpi, DropFlagState::Present)); + for_location_inits(move_data, loc, |mpi| callback(mpi, DropFlagState::Present)); } -pub fn for_location_inits<'tcx, F>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - move_data: &MoveData<'tcx>, - loc: Location, - mut callback: F, -) where +fn for_location_inits<'tcx, F>(move_data: &MoveData<'tcx>, loc: Location, mut callback: F) +where F: FnMut(MovePathIndex), { for ii in &move_data.init_loc_map[loc] { @@ -144,7 +127,7 @@ pub fn for_location_inits<'tcx, F>( InitKind::Deep => { let path = init.path; - on_all_children_bits(tcx, body, move_data, path, &mut callback) + on_all_children_bits(move_data, path, &mut callback) } InitKind::Shallow => { let mpi = init.path; @@ -161,8 +144,6 @@ pub fn for_location_inits<'tcx, F>( /// NOTE: If there are no move paths corresponding to an inactive variant, /// `handle_inactive_variant` will not be called for that variant. pub(crate) fn on_all_inactive_variants<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mir::Body<'tcx>, move_data: &MoveData<'tcx>, enum_place: mir::Place<'tcx>, active_variant: VariantIdx, @@ -185,9 +166,7 @@ pub(crate) fn on_all_inactive_variants<'tcx>( }; if variant_idx != active_variant { - on_all_children_bits(tcx, body, move_data, variant_mpi, |mpi| { - handle_inactive_variant(mpi) - }); + on_all_children_bits(move_data, variant_mpi, |mpi| handle_inactive_variant(mpi)); } } } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 25ba67a63ecee..958fa0d17cd39 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -481,12 +481,8 @@ where ) -> (BasicBlock, Unwind) { let (succ, unwind) = self.drop_ladder_bottom(); if !adt.is_enum() { - let fields = self.move_paths_for_fields( - self.place, - self.path, - &adt.variant(FIRST_VARIANT), - args, - ); + let fields = + self.move_paths_for_fields(self.place, self.path, adt.variant(FIRST_VARIANT), args); self.drop_ladder(fields, succ, unwind) } else { self.open_drop_for_multivariant(adt, args, succ, unwind) @@ -518,7 +514,7 @@ where self.place, ProjectionElem::Downcast(Some(variant.name), variant_index), ); - let fields = self.move_paths_for_fields(base_place, variant_path, &variant, args); + let fields = self.move_paths_for_fields(base_place, variant_path, variant, args); values.push(discr.val); if let Unwind::To(unwind) = unwind { // We can't use the half-ladder from the original @@ -859,14 +855,14 @@ where fn open_drop(&mut self) -> BasicBlock { let ty = self.place_ty(self.place); match ty.kind() { - ty::Closure(_, args) => self.open_drop_for_tuple(&args.as_closure().upvar_tys()), + ty::Closure(_, args) => self.open_drop_for_tuple(args.as_closure().upvar_tys()), // Note that `elaborate_drops` only drops the upvars of a coroutine, // and this is ok because `open_drop` here can only be reached // within that own coroutine's resume function. // This should only happen for the self argument on the resume function. // It effectively only contains upvars until the coroutine transformation runs. // See librustc_body/transform/coroutine.rs for more details. - ty::Coroutine(_, args, _) => self.open_drop_for_tuple(&args.as_coroutine().upvar_tys()), + ty::Coroutine(_, args, _) => self.open_drop_for_tuple(args.as_coroutine().upvar_tys()), ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index c978bddfef540..815f204594257 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -1,60 +1,14 @@ //! Random access inspection of the results of a dataflow analysis. -use crate::{framework::BitSetExt, CloneAnalysis}; +use crate::framework::BitSetExt; -use std::borrow::{Borrow, BorrowMut}; use std::cmp::Ordering; #[cfg(debug_assertions)] use rustc_index::bit_set::BitSet; use rustc_middle::mir::{self, BasicBlock, Location}; -use super::{Analysis, Direction, Effect, EffectIndex, EntrySets, Results, ResultsCloned}; - -// `AnalysisResults` is needed as an impl such as the following has an unconstrained type -// parameter: -// ``` -// impl<'tcx, A, E, R> ResultsCursor<'_, 'tcx, A, R> -// where -// A: Analysis<'tcx>, -// E: Borrow>, -// R: Results<'tcx, A, E>, -// {} -// ``` - -/// A type representing the analysis results consumed by a `ResultsCursor`. -pub trait AnalysisResults<'tcx, A>: BorrowMut> -where - A: Analysis<'tcx>, -{ - /// The type containing the entry sets for this `Results` type. - /// - /// Should be either `EntrySets<'tcx, A>` or `&EntrySets<'tcx, A>`. - type EntrySets: Borrow>; -} -impl<'tcx, A, E> AnalysisResults<'tcx, A> for Results<'tcx, A, E> -where - A: Analysis<'tcx>, - E: Borrow>, -{ - type EntrySets = E; -} -impl<'a, 'tcx, A, E> AnalysisResults<'tcx, A> for &'a mut Results<'tcx, A, E> -where - A: Analysis<'tcx>, - E: Borrow>, -{ - type EntrySets = E; -} - -/// A `ResultsCursor` that borrows the underlying `Results`. -pub type ResultsRefCursor<'res, 'mir, 'tcx, A> = - ResultsCursor<'mir, 'tcx, A, &'res mut Results<'tcx, A>>; - -/// A `ResultsCursor` which uses a cloned `Analysis` while borrowing the underlying `Results`. This -/// allows multiple cursors over the same `Results`. -pub type ResultsClonedCursor<'res, 'mir, 'tcx, A> = - ResultsCursor<'mir, 'tcx, A, ResultsCloned<'res, 'tcx, A>>; +use super::{Analysis, Direction, Effect, EffectIndex, Results}; /// Allows random access inspection of the results of a dataflow analysis. /// @@ -62,15 +16,12 @@ pub type ResultsClonedCursor<'res, 'mir, 'tcx, A> = /// the same order as the `DIRECTION` of the analysis. In the worst case—when statements are /// visited in *reverse* order—performance will be quadratic in the number of statements in the /// block. The order in which basic blocks are inspected has no impact on performance. -/// -/// A `ResultsCursor` can either own (the default) or borrow the dataflow results it inspects. The -/// type of ownership is determined by `R` (see `ResultsRefCursor` above). -pub struct ResultsCursor<'mir, 'tcx, A, R = Results<'tcx, A>> +pub struct ResultsCursor<'mir, 'tcx, A> where A: Analysis<'tcx>, { body: &'mir mir::Body<'tcx>, - results: R, + results: Results<'tcx, A>, state: A::Domain, pos: CursorPosition, @@ -84,7 +35,7 @@ where reachable_blocks: BitSet, } -impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R> +impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A> where A: Analysis<'tcx>, { @@ -99,30 +50,13 @@ where } /// Unwraps this cursor, returning the underlying `Results`. - pub fn into_results(self) -> R { + pub fn into_results(self) -> Results<'tcx, A> { self.results } -} -impl<'res, 'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A, ResultsCloned<'res, 'tcx, A>> -where - A: Analysis<'tcx> + CloneAnalysis, -{ - /// Creates a new cursor over the same `Results`. Note that the cursor's position is *not* - /// copied. - pub fn new_cursor(&self) -> Self { - Self::new(self.body, self.results.reclone_analysis()) - } -} - -impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R> -where - A: Analysis<'tcx>, - R: AnalysisResults<'tcx, A>, -{ /// Returns a new cursor that can inspect `results`. - pub fn new(body: &'mir mir::Body<'tcx>, results: R) -> Self { - let bottom_value = results.borrow().analysis.bottom_value(body); + pub fn new(body: &'mir mir::Body<'tcx>, results: Results<'tcx, A>) -> Self { + let bottom_value = results.analysis.bottom_value(body); ResultsCursor { body, results, @@ -147,28 +81,23 @@ where } /// Returns the underlying `Results`. - pub fn results(&mut self) -> &Results<'tcx, A, R::EntrySets> { - self.results.borrow() + pub fn results(&self) -> &Results<'tcx, A> { + &self.results } /// Returns the underlying `Results`. - pub fn mut_results(&mut self) -> &mut Results<'tcx, A, R::EntrySets> { - self.results.borrow_mut() + pub fn mut_results(&mut self) -> &mut Results<'tcx, A> { + &mut self.results } /// Returns the `Analysis` used to generate the underlying `Results`. pub fn analysis(&self) -> &A { - &self.results.borrow().analysis + &self.results.analysis } /// Returns the `Analysis` used to generate the underlying `Results`. pub fn mut_analysis(&mut self) -> &mut A { - &mut self.results.borrow_mut().analysis - } - - /// Returns both the dataflow state at the current location and the `Analysis`. - pub fn get_with_analysis(&mut self) -> (&A::Domain, &mut A) { - (&self.state, &mut self.results.borrow_mut().analysis) + &mut self.results.analysis } /// Resets the cursor to hold the entry set for the given basic block. @@ -180,7 +109,7 @@ where #[cfg(debug_assertions)] assert!(self.reachable_blocks.contains(block)); - self.state.clone_from(self.results.borrow().entry_set_for_block(block)); + self.state.clone_from(self.results.entry_set_for_block(block)); self.pos = CursorPosition::block_entry(block); self.state_needs_reset = false; } @@ -269,11 +198,10 @@ where ) }; - let analysis = &mut self.results.borrow_mut().analysis; let target_effect_index = effect.at_index(target.statement_index); A::Direction::apply_effects_in_range( - analysis, + &mut self.results.analysis, &mut self.state, target.block, block_data, @@ -289,12 +217,12 @@ where /// This can be used, e.g., to apply the call return effect directly to the cursor without /// creating an extra copy of the dataflow state. pub fn apply_custom_effect(&mut self, f: impl FnOnce(&mut A, &mut A::Domain)) { - f(&mut self.results.borrow_mut().analysis, &mut self.state); + f(&mut self.results.analysis, &mut self.state); self.state_needs_reset = true; } } -impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R> +impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A> where A: crate::GenKillAnalysis<'tcx>, A::Domain: BitSetExt, diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 70451edd50046..08b7b1a26193b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -196,7 +196,7 @@ impl Direction for Backward { { results.reset_to_block_entry(state, block); - vis.visit_block_end(results, &state, block_data, block); + vis.visit_block_end(results, state, block_data, block); // Terminator let loc = Location { block, statement_index: block_data.statements.len() }; @@ -287,12 +287,12 @@ impl Direction for Backward { } } -struct BackwardSwitchIntEdgeEffectsApplier<'a, 'tcx, D, F> { - body: &'a mir::Body<'tcx>, +struct BackwardSwitchIntEdgeEffectsApplier<'mir, 'tcx, D, F> { + body: &'mir mir::Body<'tcx>, pred: BasicBlock, - exit_state: &'a mut D, + exit_state: &'mir mut D, bb: BasicBlock, - propagate: &'a mut F, + propagate: &'mir mut F, effects_applied: bool, } @@ -523,9 +523,9 @@ impl Direction for Forward { } } -struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> { - exit_state: &'a mut D, - targets: &'a SwitchTargets, +struct ForwardSwitchIntEdgeEffectsApplier<'mir, D, F> { + exit_state: &'mir mut D, + targets: &'mir SwitchTargets, propagate: F, effects_applied: bool, diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index a29962d7717a9..784872c7ed7d8 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -5,9 +5,7 @@ use crate::errors::{ }; use crate::framework::BitSetExt; -use std::borrow::Borrow; use std::ffi::OsString; -use std::marker::PhantomData; use std::path::PathBuf; use rustc_ast as ast; @@ -24,42 +22,37 @@ use rustc_span::symbol::{sym, Symbol}; use super::fmt::DebugWithContext; use super::graphviz; use super::{ - visit_results, Analysis, AnalysisDomain, CloneAnalysis, Direction, GenKill, GenKillAnalysis, - GenKillSet, JoinSemiLattice, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, - ResultsVisitor, + visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis, GenKillSet, + JoinSemiLattice, ResultsCursor, ResultsVisitor, }; pub type EntrySets<'tcx, A> = IndexVec>::Domain>; /// A dataflow analysis that has converged to fixpoint. -pub struct Results<'tcx, A, E = EntrySets<'tcx, A>> +#[derive(Clone)] +pub struct Results<'tcx, A> where A: Analysis<'tcx>, { pub analysis: A, - pub(super) entry_sets: E, - pub(super) _marker: PhantomData<&'tcx ()>, + pub(super) entry_sets: EntrySets<'tcx, A>, } -/// `Results` type with a cloned `Analysis` and borrowed entry sets. -pub type ResultsCloned<'res, 'tcx, A> = Results<'tcx, A, &'res EntrySets<'tcx, A>>; - -impl<'tcx, A, E> Results<'tcx, A, E> +impl<'tcx, A> Results<'tcx, A> where A: Analysis<'tcx>, - E: Borrow>, { /// Creates a `ResultsCursor` that can inspect these `Results`. pub fn into_results_cursor<'mir>( self, body: &'mir mir::Body<'tcx>, - ) -> ResultsCursor<'mir, 'tcx, A, Self> { + ) -> ResultsCursor<'mir, 'tcx, A> { ResultsCursor::new(body, self) } /// Gets the dataflow state for the given block. pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain { - &self.entry_sets.borrow()[block] + &self.entry_sets[block] } pub fn visit_with<'mir>( @@ -80,60 +73,14 @@ where visit_results(body, blocks.map(|(bb, _)| bb), self, vis) } } -impl<'tcx, A> Results<'tcx, A> -where - A: Analysis<'tcx>, -{ - /// Creates a `ResultsCursor` that can inspect these `Results`. - pub fn as_results_cursor<'a, 'mir>( - &'a mut self, - body: &'mir mir::Body<'tcx>, - ) -> ResultsRefCursor<'a, 'mir, 'tcx, A> { - ResultsCursor::new(body, self) - } -} -impl<'tcx, A> Results<'tcx, A> -where - A: Analysis<'tcx> + CloneAnalysis, -{ - /// Creates a new `Results` type with a cloned `Analysis` and borrowed entry sets. - pub fn clone_analysis(&self) -> ResultsCloned<'_, 'tcx, A> { - Results { - analysis: self.analysis.clone_analysis(), - entry_sets: &self.entry_sets, - _marker: PhantomData, - } - } - - /// Creates a `ResultsCursor` that can inspect these `Results`. - pub fn cloned_results_cursor<'mir>( - &self, - body: &'mir mir::Body<'tcx>, - ) -> ResultsClonedCursor<'_, 'mir, 'tcx, A> { - self.clone_analysis().into_results_cursor(body) - } -} -impl<'res, 'tcx, A> Results<'tcx, A, &'res EntrySets<'tcx, A>> -where - A: Analysis<'tcx> + CloneAnalysis, -{ - /// Creates a new `Results` type with a cloned `Analysis` and borrowed entry sets. - pub fn reclone_analysis(&self) -> Self { - Results { - analysis: self.analysis.clone_analysis(), - entry_sets: self.entry_sets, - _marker: PhantomData, - } - } -} /// A solver for dataflow problems. -pub struct Engine<'a, 'tcx, A> +pub struct Engine<'mir, 'tcx, A> where A: Analysis<'tcx>, { tcx: TyCtxt<'tcx>, - body: &'a mir::Body<'tcx>, + body: &'mir mir::Body<'tcx>, entry_sets: IndexVec, pass_name: Option<&'static str>, analysis: A, @@ -147,14 +94,14 @@ where apply_statement_trans_for_block: Option>, } -impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A> +impl<'mir, 'tcx, A, D, T> Engine<'mir, 'tcx, A> where A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, D: Clone + JoinSemiLattice + GenKill + BitSetExt, T: Idx, { /// Creates a new `Engine` to solve a gen-kill dataflow problem. - pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, mut analysis: A) -> Self { + pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, mut analysis: A) -> Self { // If there are no back-edges in the control-flow graph, we only ever need to apply the // transfer function for each block exactly once (assuming that we process blocks in RPO). // @@ -186,7 +133,7 @@ where } } -impl<'a, 'tcx, A, D> Engine<'a, 'tcx, A> +impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A> where A: Analysis<'tcx, Domain = D>, D: Clone + JoinSemiLattice, @@ -196,13 +143,13 @@ where /// /// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for /// better performance. - pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, analysis: A) -> Self { + pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self { Self::new(tcx, body, analysis, None) } fn new( tcx: TyCtxt<'tcx>, - body: &'a mir::Body<'tcx>, + body: &'mir mir::Body<'tcx>, analysis: A, apply_statement_trans_for_block: Option>, ) -> Self { @@ -239,7 +186,6 @@ where tcx, apply_statement_trans_for_block, pass_name, - .. } = self; let mut dirty_queue: WorkQueue = WorkQueue::with_none(body.basic_blocks.len()); @@ -292,29 +238,31 @@ where ); } - let mut results = Results { analysis, entry_sets, _marker: PhantomData }; + let results = Results { analysis, entry_sets }; if tcx.sess.opts.unstable_opts.dump_mir_dataflow { - let res = write_graphviz_results(tcx, &body, &mut results, pass_name); + let (res, results) = write_graphviz_results(tcx, body, results, pass_name); if let Err(e) = res { error!("Failed to write graphviz dataflow results: {}", e); } + results + } else { + results } - - results } } // Graphviz /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via -/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. +/// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are +/// the same. fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, - results: &mut Results<'tcx, A>, + results: Results<'tcx, A>, pass_name: Option<&'static str>, -) -> std::io::Result<()> +) -> (std::io::Result<()>, Results<'tcx, A>) where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -325,23 +273,30 @@ where let def_id = body.source.def_id(); let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else { // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse` - return Ok(()); + return (Ok(()), results); }; - let mut file = match attrs.output_path(A::NAME) { - Some(path) => { - debug!("printing dataflow results for {:?} to {}", def_id, path.display()); - if let Some(parent) = path.parent() { - fs::create_dir_all(parent)?; + let file = try { + match attrs.output_path(A::NAME) { + Some(path) => { + debug!("printing dataflow results for {:?} to {}", def_id, path.display()); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + let f = fs::File::create(&path)?; + io::BufWriter::new(f) } - io::BufWriter::new(fs::File::create(&path)?) - } - None if dump_enabled(tcx, A::NAME, def_id) => { - create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? - } + None if dump_enabled(tcx, A::NAME, def_id) => { + create_dump_file(tcx, ".dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? + } - _ => return Ok(()), + _ => return (Ok(()), results), + } + }; + let mut file = match file { + Ok(f) => f, + Err(e) => return (Err(e), results), }; let style = match attrs.formatter { @@ -357,11 +312,14 @@ where if tcx.sess.opts.unstable_opts.graphviz_dark_mode { render_opts.push(dot::RenderOption::DarkTheme); } - with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)?); + let r = with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)); - file.write_all(&buf)?; + let lhs = try { + r?; + file.write_all(&buf)?; + }; - Ok(()) + (lhs, graphviz.into_results()) } #[derive(Default)] diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index c12ccba1e5c6d..fa16cac31686b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -12,10 +12,10 @@ use rustc_middle::mir::graphviz_safe_def_name; use rustc_middle::mir::{self, BasicBlock, Body, Location}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; -use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor}; +use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum OutputStyle { +pub(crate) enum OutputStyle { AfterOnly, BeforeAndAfter, } @@ -29,33 +29,37 @@ impl OutputStyle { } } -pub struct Formatter<'res, 'mir, 'tcx, A> +pub(crate) struct Formatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { body: &'mir Body<'tcx>, - results: RefCell<&'res mut Results<'tcx, A>>, + results: RefCell>>, style: OutputStyle, reachable: BitSet, } -impl<'res, 'mir, 'tcx, A> Formatter<'res, 'mir, 'tcx, A> +impl<'mir, 'tcx, A> Formatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { - pub fn new( + pub(crate) fn new( body: &'mir Body<'tcx>, - results: &'res mut Results<'tcx, A>, + results: Results<'tcx, A>, style: OutputStyle, ) -> Self { let reachable = mir::traversal::reachable_as_bitset(body); - Formatter { body, results: results.into(), style, reachable } + Formatter { body, results: Some(results).into(), style, reachable } + } + + pub(crate) fn into_results(self) -> Results<'tcx, A> { + self.results.into_inner().unwrap() } } /// A pair of a basic block and an index into that basic blocks `successors`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct CfgEdge { +pub(crate) struct CfgEdge { source: BasicBlock, index: usize, } @@ -69,7 +73,7 @@ fn dataflow_successors(body: &Body<'_>, bb: BasicBlock) -> Vec { .collect() } -impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, '_, 'tcx, A> +impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -88,14 +92,19 @@ where fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> { let mut label = Vec::new(); - let mut results = self.results.borrow_mut(); - let mut fmt = BlockFormatter { - results: results.as_results_cursor(self.body), - style: self.style, - bg: Background::Light, - }; + self.results.replace_with(|results| { + // `Formatter::result` is a `RefCell>` so we can replace + // the value with `None`, move it into the results cursor, move it + // back out, and return it to the refcell wrapped in `Some`. + let mut fmt = BlockFormatter { + results: results.take().unwrap().into_results_cursor(self.body), + style: self.style, + bg: Background::Light, + }; - fmt.write_node_label(&mut label, *block).unwrap(); + fmt.write_node_label(&mut label, *block).unwrap(); + Some(fmt.results.into_results()) + }); dot::LabelText::html(String::from_utf8(label).unwrap()) } @@ -109,7 +118,7 @@ where } } -impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'_, 'mir, 'tcx, A> +impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { @@ -143,16 +152,16 @@ where } } -struct BlockFormatter<'res, 'mir, 'tcx, A> +struct BlockFormatter<'mir, 'tcx, A> where A: Analysis<'tcx>, { - results: ResultsRefCursor<'res, 'mir, 'tcx, A>, + results: ResultsCursor<'mir, 'tcx, A>, bg: Background, style: OutputStyle, } -impl<'res, 'mir, 'tcx, A> BlockFormatter<'res, 'mir, 'tcx, A> +impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index 3b89598d28993..1c2b475a43c96 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -342,7 +342,7 @@ impl Clone for MaybeReachable { fn clone_from(&mut self, source: &Self) { match (&mut *self, source) { (MaybeReachable::Reachable(x), MaybeReachable::Reachable(y)) => { - x.clone_from(&y); + x.clone_from(y); } _ => *self = source.clone(), } diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 5020a1cf0b27c..b7dfbe0710da7 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -45,9 +45,9 @@ pub mod graphviz; pub mod lattice; mod visitor; -pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor}; +pub use self::cursor::ResultsCursor; pub use self::direction::{Backward, Direction, Forward}; -pub use self::engine::{Engine, EntrySets, Results, ResultsCloned}; +pub use self::engine::{Engine, Results}; pub use self::lattice::{JoinSemiLattice, MaybeReachable}; pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor}; @@ -246,21 +246,6 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { } } -/// Defines an `Analysis` which can be cloned for use in multiple `ResultsCursor`s or -/// `ResultsVisitor`s. Note this need not be a full clone, only enough of one to be used with a new -/// `ResultsCursor` or `ResultsVisitor` -pub trait CloneAnalysis { - fn clone_analysis(&self) -> Self; -} -impl<'tcx, A> CloneAnalysis for A -where - A: Analysis<'tcx> + Copy, -{ - fn clone_analysis(&self) -> Self { - *self - } -} - /// A gen/kill dataflow problem. /// /// Each method in this trait has a corresponding one in `Analysis`. However, these methods only diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 9cce5b26cd305..1da5057ff40f7 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -267,8 +267,7 @@ fn test_cursor(analysis: MockAnalysis<'_, D>) { let body = analysis.body; let mut cursor = - Results { entry_sets: analysis.mock_entry_sets(), analysis, _marker: PhantomData } - .into_results_cursor(body); + Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body); cursor.allow_unreachable(); diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index 3cfa7cc1c02fd..e3648bb40768f 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -1,8 +1,6 @@ -use std::borrow::Borrow; - use rustc_middle::mir::{self, BasicBlock, Location}; -use super::{Analysis, Direction, EntrySets, Results}; +use super::{Analysis, Direction, Results}; /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the /// dataflow state at that location. @@ -143,10 +141,9 @@ pub trait ResultsVisitable<'tcx> { ); } -impl<'tcx, A, E> ResultsVisitable<'tcx> for Results<'tcx, A, E> +impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A> where A: Analysis<'tcx>, - E: Borrow>, { type FlowState = A::Domain; diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 1e8e09ac333b1..01acc380fa39c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -5,7 +5,8 @@ use rustc_middle::mir::*; use crate::{AnalysisDomain, GenKill, GenKillAnalysis}; /// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points -/// to a given local. +/// to a given local. This analysis ignores fake borrows, so it should not be used by +/// borrowck. /// /// At present, this is used as a very limited form of alias analysis. For example, /// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for @@ -91,13 +92,17 @@ where self.super_rvalue(rvalue, location); match rvalue { - Rvalue::AddressOf(_, borrowed_place) | Rvalue::Ref(_, _, borrowed_place) => { + // We ignore fake borrows as these get removed after analysis and shouldn't effect + // the layout of generators. + Rvalue::AddressOf(_, borrowed_place) + | Rvalue::Ref(_, BorrowKind::Mut { .. } | BorrowKind::Shared, borrowed_place) => { if !borrowed_place.is_indirect() { self.trans.gen(borrowed_place.local); } } Rvalue::Cast(..) + | Rvalue::Ref(_, BorrowKind::Fake, _) | Rvalue::ShallowInitBox(..) | Rvalue::Use(..) | Rvalue::ThreadLocalRef(..) diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index c968e7aea8fde..b050e963d8ece 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -72,7 +72,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { ) -> bool { if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) { let mut maybe_live = false; - on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| { + on_all_children_bits(self.move_data(), path, |child| { maybe_live |= state.contains(child); }); !maybe_live @@ -203,14 +203,13 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> { /// this data and `MaybeInitializedPlaces` yields the set of places /// that would require a dynamic drop-flag at that statement. pub struct DefinitelyInitializedPlaces<'a, 'tcx> { - tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>, } impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - DefinitelyInitializedPlaces { tcx, body, mdpe } + pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { + DefinitelyInitializedPlaces { body, mdpe } } } @@ -250,15 +249,13 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { /// } /// ``` pub struct EverInitializedPlaces<'a, 'tcx> { - #[allow(dead_code)] - tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>, } impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - EverInitializedPlaces { tcx, body, mdpe } + pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { + EverInitializedPlaces { body, mdpe } } } @@ -319,7 +316,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { *state = MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len())); - drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); state.gen(path); }); @@ -339,7 +336,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); @@ -351,7 +348,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { | mir::Rvalue::AddressOf(_, place) = rvalue && let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) { - on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| { + on_all_children_bits(self.move_data(), mpi, |child| { trans.gen(child); }) } @@ -371,7 +368,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { { edges = TerminatorEdges::Single(target); } - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(state, path, s) }); edges @@ -387,8 +384,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { // when a call returns successfully, that means we need to set // the bits for that dest_place to 1 (initialized). on_lookup_result_bits( - self.tcx, - self.body, self.move_data(), self.move_data().rev_lookup.find(place.as_ref()), |mpi| { @@ -409,7 +404,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { } let enum_ = discr.place().and_then(|discr| { - switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr) + switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr) }); let Some((enum_place, enum_def)) = enum_ else { @@ -432,8 +427,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { // Kill all move paths that correspond to variants we know to be inactive along this // particular outgoing edge of a `SwitchInt`. drop_flag_effects::on_all_inactive_variants( - self.tcx, - self.body, self.move_data(), enum_place, variant, @@ -458,7 +451,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // set all bits to 1 (uninit) before gathering counter-evidence state.insert_all(); - drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); state.remove(path); }); @@ -478,7 +471,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { _statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); @@ -492,7 +485,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); if self.skip_unreachable_unwind.contains(location.block) { @@ -514,8 +507,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // when a call returns successfully, that means we need to set // the bits for that dest_place to 0 (initialized). on_lookup_result_bits( - self.tcx, - self.body, self.move_data(), self.move_data().rev_lookup.find(place.as_ref()), |mpi| { @@ -540,7 +531,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { } let enum_ = discr.place().and_then(|discr| { - switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr) + switch_on_enum_discriminant(self.tcx, self.body, &self.body[block], discr) }); let Some((enum_place, enum_def)) = enum_ else { @@ -563,8 +554,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // Mark all move paths that correspond to variants other than this one as maybe // uninitialized (in reality, they are *definitely* uninitialized). drop_flag_effects::on_all_inactive_variants( - self.tcx, - self.body, self.move_data(), enum_place, variant, @@ -589,7 +578,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { state.0.clear(); - drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); state.0.insert(path); }); @@ -609,7 +598,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { _statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }) } @@ -620,7 +609,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { Self::update_bits(trans, path, s) }); terminator.edges() @@ -636,8 +625,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { // when a call returns successfully, that means we need to set // the bits for that dest_place to 1 (initialized). on_lookup_result_bits( - self.tcx, - self.body, self.move_data(), self.move_data().rev_lookup.find(place.as_ref()), |mpi| { diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index c1152e88cd0f2..c3fdca1641ab5 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -23,7 +23,6 @@ use crate::{Analysis, AnalysisDomain, Backward, GenKill, GenKillAnalysis}; /// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals /// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis -#[derive(Clone, Copy)] pub struct MaybeLiveLocals; impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { @@ -201,7 +200,7 @@ impl DefUse { | NonMutatingUseContext::Inspect | NonMutatingUseContext::Move | NonMutatingUseContext::PlaceMention - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::SharedBorrow, ) => Some(DefUse::Use), diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 5a58e3af8be1a..26fc903973f80 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::*; use std::borrow::Cow; use super::MaybeBorrowedLocals; -use crate::{GenKill, ResultsClonedCursor}; +use crate::{GenKill, ResultsCursor}; #[derive(Clone)] pub struct MaybeStorageLive<'a> { @@ -18,12 +18,6 @@ impl<'a> MaybeStorageLive<'a> { } } -impl crate::CloneAnalysis for MaybeStorageLive<'_> { - fn clone_analysis(&self) -> Self { - self.clone() - } -} - impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> { type Domain = BitSet; @@ -158,28 +152,21 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead { } } -type BorrowedLocalsResults<'res, 'mir, 'tcx> = - ResultsClonedCursor<'res, 'mir, 'tcx, MaybeBorrowedLocals>; +type BorrowedLocalsResults<'mir, 'tcx> = ResultsCursor<'mir, 'tcx, MaybeBorrowedLocals>; /// Dataflow analysis that determines whether each local requires storage at a /// given location; i.e. whether its storage can go away without being observed. -pub struct MaybeRequiresStorage<'res, 'mir, 'tcx> { - borrowed_locals: BorrowedLocalsResults<'res, 'mir, 'tcx>, +pub struct MaybeRequiresStorage<'mir, 'tcx> { + borrowed_locals: BorrowedLocalsResults<'mir, 'tcx>, } -impl<'res, 'mir, 'tcx> MaybeRequiresStorage<'res, 'mir, 'tcx> { - pub fn new(borrowed_locals: BorrowedLocalsResults<'res, 'mir, 'tcx>) -> Self { +impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { + pub fn new(borrowed_locals: BorrowedLocalsResults<'mir, 'tcx>) -> Self { MaybeRequiresStorage { borrowed_locals } } } -impl crate::CloneAnalysis for MaybeRequiresStorage<'_, '_, '_> { - fn clone_analysis(&self) -> Self { - Self { borrowed_locals: self.borrowed_locals.new_cursor() } - } -} - -impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { +impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, 'tcx> { type Domain = BitSet; const NAME: &'static str = "requires_storage"; @@ -198,7 +185,7 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { } } -impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { +impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { type Idx = Local; fn domain_size(&self, body: &Body<'tcx>) -> usize { @@ -355,7 +342,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { } } -impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> { +impl<'tcx> MaybeRequiresStorage<'_, 'tcx> { /// Kill locals that are fully moved and have not been borrowed. fn check_for_move(&mut self, trans: &mut impl GenKill, loc: Location) { let body = self.borrowed_locals.body(); @@ -364,12 +351,12 @@ impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> { } } -struct MoveVisitor<'a, 'res, 'mir, 'tcx, T> { - borrowed_locals: &'a mut BorrowedLocalsResults<'res, 'mir, 'tcx>, +struct MoveVisitor<'a, 'mir, 'tcx, T> { + borrowed_locals: &'a mut BorrowedLocalsResults<'mir, 'tcx>, trans: &'a mut T, } -impl<'tcx, T> Visitor<'tcx> for MoveVisitor<'_, '_, '_, 'tcx, T> +impl<'tcx, T> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx, T> where T: GenKill, { diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index eea0e030e7d3a..f0b21fd418472 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -4,7 +4,7 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] -#![feature(trusted_step)] +#![feature(try_blocks)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -14,24 +14,17 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; -use rustc_ast::MetaItem; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; -use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::symbol::{sym, Symbol}; +use rustc_middle::ty; pub use self::drop_flag_effects::{ drop_flag_effects_for_function_entry, drop_flag_effects_for_location, move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward, - CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, - MaybeReachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, - ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, + fmt, lattice, visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis, + JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor, }; - +use self::framework::{Backward, SwitchIntEdgeEffects}; use self::move_paths::MoveData; pub mod debuginfo; @@ -46,26 +39,9 @@ pub mod storage; pub mod un_derefer; pub mod value_analysis; -fluent_messages! { "../messages.ftl" } - -pub(crate) mod indexes { - pub(crate) use super::move_paths::MovePathIndex; -} +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub struct MoveDataParamEnv<'tcx> { pub move_data: MoveData<'tcx>, pub param_env: ty::ParamEnv<'tcx>, } - -pub fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option { - for attr in tcx.get_attrs(def_id, sym::rustc_mir) { - let items = attr.meta_item_list(); - for item in items.iter().flat_map(|l| l.iter()) { - match item.meta_item() { - Some(mi) if mi.has_name(name) => return Some(mi.clone()), - _ => continue, - } - } - } - None -} diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 7ab1a9ed069ff..22cf3999239c1 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -14,6 +14,7 @@ use self::abs_domain::{AbstractElem, Lift}; mod abs_domain; rustc_index::newtype_index! { + #[orderable] #[debug_format = "mp{}"] pub struct MovePathIndex {} } @@ -25,6 +26,7 @@ impl polonius_engine::Atom for MovePathIndex { } rustc_index::newtype_index! { + #[orderable] #[debug_format = "mo{}"] pub struct MoveOutIndex {} } diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index d3dce641ba1fd..448128b6993fc 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,11 +1,3 @@ -use rustc_span::symbol::sym; -use rustc_span::Span; - -use rustc_index::bit_set::ChunkedBitSet; -use rustc_middle::mir::MirPass; -use rustc_middle::mir::{self, Body, Local, Location}; -use rustc_middle::ty::{self, Ty, TyCtxt}; - use crate::errors::{ PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary, PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation, @@ -18,13 +10,33 @@ use crate::move_paths::{HasMoveData, MoveData}; use crate::move_paths::{LookupResult, MovePathIndex}; use crate::MoveDataParamEnv; use crate::{Analysis, JoinSemiLattice, ResultsCursor}; +use rustc_ast::MetaItem; +use rustc_hir::def_id::DefId; +use rustc_index::bit_set::ChunkedBitSet; +use rustc_middle::mir::MirPass; +use rustc_middle::mir::{self, Body, Local, Location}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::Span; pub struct SanityCheck; +fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option { + for attr in tcx.get_attrs(def_id, sym::rustc_mir) { + let items = attr.meta_item_list(); + for item in items.iter().flat_map(|l| l.iter()) { + match item.meta_item() { + Some(mi) if mi.has_name(name) => return Some(mi.clone()), + _ => continue, + } + } + } + None +} + // FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first. impl<'tcx> MirPass<'tcx> for SanityCheck { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - use crate::has_rustc_mir_with; let def_id = body.source.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); @@ -34,7 +46,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { } let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(&body, tcx, param_env, |_| true); + let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); let mdpe = MoveDataParamEnv { move_data, param_env }; if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { @@ -54,7 +66,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { - let flow_def_inits = DefinitelyInitializedPlaces::new(tcx, body, &mdpe) + let flow_def_inits = DefinitelyInitializedPlaces::new(body, &mdpe) .into_engine(tcx, body) .iterate_to_fixpoint(); @@ -89,10 +101,8 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { /// (If there are any calls to `rustc_peek` that do not match the /// expression form above, then that emits an error as well, but those /// errors are not intended to be used for unit tests.) -pub fn sanity_check_via_rustc_peek<'tcx, A>( - tcx: TyCtxt<'tcx>, - mut cursor: ResultsCursor<'_, 'tcx, A>, -) where +fn sanity_check_via_rustc_peek<'tcx, A>(tcx: TyCtxt<'tcx>, mut cursor: ResultsCursor<'_, 'tcx, A>) +where A: RustcPeekAt<'tcx>, { let def_id = cursor.body().source.def_id(); @@ -129,7 +139,8 @@ pub fn sanity_check_via_rustc_peek<'tcx, A>( ) => { let loc = Location { block: bb, statement_index }; cursor.seek_before_primary_effect(loc); - let (state, analysis) = cursor.get_with_analysis(); + let state = cursor.get(); + let analysis = cursor.analysis(); analysis.peek_at(tcx, *place, state, call); } @@ -173,7 +184,7 @@ impl PeekCallKind { } #[derive(Clone, Copy, Debug)] -pub struct PeekCall { +struct PeekCall { arg: Local, kind: PeekCallKind, span: Span, @@ -221,7 +232,7 @@ impl PeekCall { } } -pub trait RustcPeekAt<'tcx>: Analysis<'tcx> { +trait RustcPeekAt<'tcx>: Analysis<'tcx> { fn peek_at( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_dataflow/src/un_derefer.rs b/compiler/rustc_mir_dataflow/src/un_derefer.rs index 874d50ffd0e21..b803ecc575ee0 100644 --- a/compiler/rustc_mir_dataflow/src/un_derefer.rs +++ b/compiler/rustc_mir_dataflow/src/un_derefer.rs @@ -3,13 +3,13 @@ use rustc_middle::mir::*; /// Used for reverting changes made by `DerefSeparator` #[derive(Default, Debug)] -pub struct UnDerefer<'tcx> { +pub(crate) struct UnDerefer<'tcx> { deref_chains: FxHashMap>>, } impl<'tcx> UnDerefer<'tcx> { #[inline] - pub fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) { + pub(crate) fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) { let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default(); chain.push(reffed); self.deref_chains.insert(local, chain); @@ -17,7 +17,7 @@ impl<'tcx> UnDerefer<'tcx> { /// Returns the chain of places behind `DerefTemp` locals #[inline] - pub fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] { + pub(crate) fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] { self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default() } @@ -25,7 +25,7 @@ impl<'tcx> UnDerefer<'tcx> { /// /// See [`PlaceRef::iter_projections`] #[inline] - pub fn iter_projections( + pub(crate) fn iter_projections( &self, place: PlaceRef<'tcx>, ) -> impl Iterator, PlaceElem<'tcx>)> + '_ { diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 025d2ddfd4ff7..071024a0fa35d 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -332,8 +332,6 @@ pub struct ValueAnalysisWrapper(pub T); impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper { type Domain = State; - type Direction = crate::Forward; - const NAME: &'static str = T::NAME; fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain { @@ -476,26 +474,10 @@ impl State { } } - pub fn is_reachable(&self) -> bool { + fn is_reachable(&self) -> bool { matches!(&self.0, StateData::Reachable(_)) } - pub fn mark_unreachable(&mut self) { - self.0 = StateData::Unreachable; - } - - pub fn flood_all(&mut self) - where - V: HasTop, - { - self.flood_all_with(V::TOP) - } - - pub fn flood_all_with(&mut self, value: V) { - let StateData::Reachable(values) = &mut self.0 else { return }; - values.raw.fill(value); - } - /// Assign `value` to all places that are contained in `place` or may alias one. pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { self.flood_with_tail_elem(place, None, map, value) @@ -510,7 +492,7 @@ impl State { } /// Assign `value` to the discriminant of `place` and all places that may alias it. - pub fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { + fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) { self.flood_with_tail_elem(place, Some(TrackElem::Discriminant), map, value) } @@ -546,7 +528,7 @@ impl State { /// This does nothing if the place is not tracked. /// /// The target place must have been flooded before calling this method. - pub fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace, map: &Map) { + fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace, map: &Map) { match result { ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map), ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map), @@ -841,7 +823,7 @@ impl Map { ) { // Allocate a value slot if it doesn't have one, and the user requested one. assert!(self.places[place].value_index.is_none()); - if tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.abi.is_scalar()) { + if tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.abi.is_scalar()) { self.places[place].value_index = Some(self.value_count.into()); self.value_count += 1; } @@ -910,18 +892,13 @@ impl Map { self.inner_values[root] = start..end; } - /// Returns the number of tracked places, i.e., those for which a value can be stored. - pub fn tracked_places(&self) -> usize { - self.value_count - } - /// Applies a single projection element, yielding the corresponding child. pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option { self.projections.get(&(place, elem)).copied() } /// Locates the given place, if it exists in the tree. - pub fn find_extra( + fn find_extra( &self, place: PlaceRef<'_>, extra: impl IntoIterator, @@ -954,7 +931,7 @@ impl Map { } /// Iterate over all direct children. - pub fn children(&self, parent: PlaceIndex) -> impl Iterator + '_ { + fn children(&self, parent: PlaceIndex) -> impl Iterator + '_ { Children::new(self, parent) } diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 0448e9d276d4e..9cc083edb44e3 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1" -itertools = "0.10.1" +itertools = "0.11" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } @@ -20,7 +20,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_mir_build = { path = "../rustc_mir_build" } rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } -rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } @@ -28,8 +27,3 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end - -[dev-dependencies] -# tidy-alphabetical-start -coverage_test_macros = { path = "src/coverage/test_macros" } -# tidy-alphabetical-end diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index 5a99afc45b020..b8dbdf18db3ea 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -42,8 +42,19 @@ mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in } .not_inherited = items do not inherit unsafety from separate enclosing items +mir_transform_target_feature_call_help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features} + mir_transform_target_feature_call_label = call to function with `#[target_feature]` -mir_transform_target_feature_call_note = can only be called if the required target features are available +mir_transform_target_feature_call_note = the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]` mir_transform_unaligned_packed_ref = reference to packed field is unaligned .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 61bf530f11c18..3195cd3622dc9 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -13,7 +13,7 @@ pub struct CheckConstItemMutation; impl<'tcx> MirLint<'tcx> for CheckConstItemMutation { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = ConstMutationChecker { body, tcx, target_local: None }; - checker.visit_body(&body); + checker.visit_body(body); } } @@ -98,7 +98,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> { if !lhs.projection.is_empty() { if let Some(def_id) = self.is_const_item_without_destructor(lhs.local) && let Some((lint_root, span, item)) = - self.should_lint_const_item_usage(&lhs, def_id, loc) + self.should_lint_const_item_usage(lhs, def_id, loc) { self.tcx.emit_spanned_lint( CONST_ITEM_MUTATION, @@ -132,12 +132,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> { // the `self` parameter of a method call (as the terminator of our current // BasicBlock). If so, we emit a more specific lint. let method_did = self.target_local.and_then(|target_local| { - rustc_middle::util::find_self_call( - self.tcx, - &self.body, - target_local, - loc.block, - ) + rustc_middle::util::find_self_call(self.tcx, self.body, target_local, loc.block) }); let lint_loc = if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc }; diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index 9ee0a70407165..77bcba50a3cd4 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -12,7 +12,7 @@ impl<'tcx> MirLint<'tcx> for CheckPackedRef { let param_env = tcx.param_env(body.source.def_id()); let source_info = SourceInfo::outermost(body.span); let mut checker = PackedRefChecker { body, tcx, param_env, source_info }; - checker.visit_body(&body); + checker.visit_body(body); } } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 8872f9a97d746..f246de55ca894 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -242,7 +242,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty; if assigned_ty.needs_drop(self.tcx, self.param_env) { // This would be unsafe, but should be outright impossible since we reject such unions. - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( self.source_info.span, format!("union fields that need dropping should be impossible: {assigned_ty}") ); @@ -287,19 +287,20 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { .safety; match safety { // `unsafe` blocks are required in safe code - Safety::Safe => violations.into_iter().for_each(|&violation| { + Safety::Safe => violations.into_iter().for_each(|violation| { match violation.kind { UnsafetyViolationKind::General => {} UnsafetyViolationKind::UnsafeFn => { bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") } } - if !self.violations.contains(&violation) { - self.violations.push(violation) + if !self.violations.contains(violation) { + self.violations.push(violation.clone()) } }), // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s - Safety::FnUnsafe => violations.into_iter().for_each(|&(mut violation)| { + Safety::FnUnsafe => violations.into_iter().for_each(|violation| { + let mut violation = violation.clone(); violation.kind = UnsafetyViolationKind::UnsafeFn; if !self.violations.contains(&violation) { self.violations.push(violation) @@ -367,9 +368,22 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { // Is `callee_features` a subset of `calling_features`? if !callee_features.iter().all(|feature| self_features.contains(feature)) { + let missing: Vec<_> = callee_features + .iter() + .copied() + .filter(|feature| !self_features.contains(feature)) + .collect(); + let build_enabled = self + .tcx + .sess + .target_features + .iter() + .copied() + .filter(|feature| missing.contains(feature)) + .collect(); self.require_unsafe( UnsafetyViolationKind::General, - UnsafetyViolationDetails::CallToFunctionWith, + UnsafetyViolationDetails::CallToFunctionWith { missing, build_enabled }, ) } } @@ -385,7 +399,7 @@ pub(crate) fn provide(providers: &mut Providers) { enum Context { Safe, /// in an `unsafe fn` - UnsafeFn(HirId), + UnsafeFn, /// in a *used* `unsafe` block /// (i.e. a block without unused-unsafe warning) UnsafeBlock(HirId), @@ -407,7 +421,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { }; let unused_unsafe = match (self.context, used) { (_, false) => UnusedUnsafe::Unused, - (Context::Safe, true) | (Context::UnsafeFn(_), true) => { + (Context::Safe, true) | (Context::UnsafeFn, true) => { let previous_context = self.context; self.context = Context::UnsafeBlock(block.hir_id); intravisit::walk_block(self, block); @@ -452,9 +466,9 @@ fn check_unused_unsafe( }; let body = tcx.hir().body(body_id); - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let context = match tcx.hir().fn_sig_by_hir_id(hir_id) { - Some(sig) if sig.header.unsafety == hir::Unsafety::Unsafe => Context::UnsafeFn(hir_id), + Some(sig) if sig.header.unsafety == hir::Unsafety::Unsafe => Context::UnsafeFn, _ => Context::Safe, }; @@ -494,7 +508,7 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def: LocalDefId) -> &UnsafetyCheckResu let param_env = tcx.param_env(def); let mut checker = UnsafetyChecker::new(body, def, tcx, param_env); - checker.visit_body(&body); + checker.visit_body(body); let unused_unsafes = (!tcx.is_typeck_child(def.to_def_id())) .then(|| check_unused_unsafe(tcx, def, &checker.used_unsafe_blocks)); @@ -528,8 +542,9 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { // Only suggest wrapping the entire function body in an unsafe block once let mut suggest_unsafe_block = true; - for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() { - let details = errors::RequiresUnsafeDetail { violation: details, span: source_info.span }; + for &UnsafetyViolation { source_info, lint_root, kind, ref details } in violations.iter() { + let details = + errors::RequiresUnsafeDetail { violation: details.clone(), span: source_info.span }; match kind { UnsafetyViolationKind::General => { @@ -568,7 +583,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { errors::UnsafeOpInUnsafeFn { details, suggest_unsafe_block: suggest_unsafe_block.then(|| { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let fn_sig = tcx .hir() .fn_sig_by_hir_id(hir_id) diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index d435d3ee69b76..5b4bc4fa13424 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -4,13 +4,13 @@ //! //! - [`AscribeUserType`] //! - [`FakeRead`] -//! - [`Assign`] statements with a [`Shallow`] borrow +//! - [`Assign`] statements with a [`Fake`] borrow //! //! [`AscribeUserType`]: rustc_middle::mir::StatementKind::AscribeUserType //! [`Assign`]: rustc_middle::mir::StatementKind::Assign //! [`FakeRead`]: rustc_middle::mir::StatementKind::FakeRead //! [`Nop`]: rustc_middle::mir::StatementKind::Nop -//! [`Shallow`]: rustc_middle::mir::BorrowKind::Shallow +//! [`Fake`]: rustc_middle::mir::BorrowKind::Fake use crate::MirPass; use rustc_middle::mir::{Body, BorrowKind, Rvalue, StatementKind, TerminatorKind}; @@ -24,7 +24,7 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck { for statement in basic_block.statements.iter_mut() { match statement.kind { StatementKind::AscribeUserType(..) - | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Shallow, _))) + | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake, _))) | StatementKind::FakeRead(..) => statement.make_nop(), _ => (), } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 53c0d0dea2924..d88b33cc9734c 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -11,6 +11,7 @@ use rustc_middle::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc_middle::mir::*; +use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::{self, GenericArgs, Instance, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::{def_id::DefId, Span}; @@ -84,8 +85,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { // FIXME(welseywiser) const prop doesn't work on coroutines because of query cycles // computing their layout. - let is_coroutine = def_kind == DefKind::Coroutine; - if is_coroutine { + if tcx.is_coroutine(def_id.to_def_id()) { trace!("ConstProp skipped for coroutine {:?}", def_id); return; } @@ -221,7 +221,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> } fn before_access_global( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, _machine: &Self, _alloc_id: AllocId, alloc: ConstAllocation<'tcx>, @@ -241,10 +241,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> } #[inline(always)] - fn expose_ptr( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _ptr: Pointer, - ) -> InterpResult<'tcx> { + fn expose_ptr(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> { throw_machine_stop_str!("exposing pointers isn't supported in ConstProp") } @@ -440,6 +437,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // FIXME we need to revisit this for #67176 if rvalue.has_param() { + trace!("skipping, has param"); return None; } if !rvalue @@ -606,7 +604,7 @@ impl CanConstProp { for arg in body.args_iter() { cpv.found_assignment.insert(arg); } - cpv.visit_body(&body); + cpv.visit_body(body); cpv.can_const_prop } } @@ -668,7 +666,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // These can't ever be propagated under any scheme, as we can't reason about indirect // mutation. | NonMutatingUse(NonMutatingUseContext::SharedBorrow) - | NonMutatingUse(NonMutatingUseContext::ShallowBorrow) + | NonMutatingUse(NonMutatingUseContext::FakeBorrow) | NonMutatingUse(NonMutatingUseContext::AddressOf) | MutatingUse(MutatingUseContext::Borrow) | MutatingUse(MutatingUseContext::AddressOf) => { @@ -708,7 +706,11 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { self.super_assign(place, rvalue, location); - let Some(()) = self.check_rvalue(rvalue) else { return }; + let Some(()) = self.check_rvalue(rvalue) else { + trace!("rvalue check failed, removing const"); + Self::remove_const(&mut self.ecx, place.local); + return; + }; match self.ecx.machine.can_const_prop[place.local] { // Do nothing if the place is indirect. diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index a23ba9c4aa9fd..99eecb567f277 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -61,7 +61,7 @@ impl<'tcx> MirLint<'tcx> for ConstPropLint { // FIXME(welseywiser) const prop doesn't work on coroutines because of query cycles // computing their layout. - if let DefKind::Coroutine = def_kind { + if tcx.is_coroutine(def_id.to_def_id()) { trace!("ConstPropLint skipped for coroutine {:?}", def_id); return; } @@ -453,7 +453,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { cond: &Operand<'tcx>, location: Location, ) -> Option { - let value = &self.eval_operand(&cond, location)?; + let value = &self.eval_operand(cond, location)?; trace!("assertion on {:?} should be {:?}", value, expected); let expected = Scalar::from_bool(expected); @@ -626,7 +626,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { self.check_assertion(*expected, msg, cond, location); } TerminatorKind::SwitchInt { ref discr, ref targets } => { - if let Some(ref value) = self.eval_operand(&discr, location) + if let Some(ref value) = self.eval_operand(discr, location) && let Some(value_const) = self.use_ecx(location, |this| this.ecx.read_scalar(value)) && let Ok(constant) = value_const.try_to_int() diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index be4af3b76f1e9..74009496e75d4 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -50,7 +50,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { Replacer { tcx, - copy_classes: &ssa.copy_classes(), + copy_classes: ssa.copy_classes(), fully_moved, borrowed_locals, storage_to_remove, @@ -124,14 +124,14 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) { - if let Some(new_projection) = self.process_projection(&place.projection, loc) { + if let Some(new_projection) = self.process_projection(place.projection, loc) { place.projection = self.tcx().mk_place_elems(&new_projection); } let observes_address = match ctxt { PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::AddressOf, ) => true, // For debuginfo, merging locals is ok. diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index fc30a718cbb57..79a1509531d66 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -617,6 +617,22 @@ fn replace_resume_ty_local<'tcx>( } } +/// Transforms the `body` of the coroutine applying the following transform: +/// +/// - Remove the `resume` argument. +/// +/// Ideally the async lowering would not add the `resume` argument. +/// +/// The async lowering step and the type / lifetime inference / checking are +/// still using the `resume` argument for the time being. After this transform, +/// the coroutine body doesn't have the `resume` argument. +fn transform_gen_context<'tcx>(_tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // This leaves the local representing the `resume` argument in place, + // but turns it into a regular local variable. This is cheaper than + // adjusting all local references in the body after removing it. + body.arg_count = 1; +} + struct LivenessInfo { /// Which locals are live across any suspension point. saved_locals: CoroutineSavedLocals, @@ -637,42 +653,48 @@ struct LivenessInfo { storage_liveness: IndexVec>>, } +/// Computes which locals have to be stored in the state-machine for the +/// given coroutine. +/// +/// The basic idea is as follows: +/// - a local is live until we encounter a `StorageDead` statement. In +/// case none exist, the local is considered to be always live. +/// - a local has to be stored if it is either directly used after the +/// the suspend point, or if it is live and has been previously borrowed. fn locals_live_across_suspend_points<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, always_live_locals: &BitSet, movable: bool, ) -> LivenessInfo { - let body_ref: &Body<'_> = &body; - // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals)) - .into_engine(tcx, body_ref) + .into_engine(tcx, body) .iterate_to_fixpoint() - .into_results_cursor(body_ref); + .into_results_cursor(body); // Calculate the MIR locals which have been previously // borrowed (even if they are still active). let borrowed_locals_results = - MaybeBorrowedLocals.into_engine(tcx, body_ref).pass_name("coroutine").iterate_to_fixpoint(); + MaybeBorrowedLocals.into_engine(tcx, body).pass_name("coroutine").iterate_to_fixpoint(); - let mut borrowed_locals_cursor = borrowed_locals_results.cloned_results_cursor(body_ref); + let mut borrowed_locals_cursor = borrowed_locals_results.clone().into_results_cursor(body); // Calculate the MIR locals that we actually need to keep storage around // for. - let mut requires_storage_results = - MaybeRequiresStorage::new(borrowed_locals_results.cloned_results_cursor(body)) - .into_engine(tcx, body_ref) - .iterate_to_fixpoint(); - let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body_ref); + let mut requires_storage_cursor = + MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body)) + .into_engine(tcx, body) + .iterate_to_fixpoint() + .into_results_cursor(body); // Calculate the liveness of MIR locals ignoring borrows. let mut liveness = MaybeLiveLocals - .into_engine(tcx, body_ref) + .into_engine(tcx, body) .pass_name("coroutine") .iterate_to_fixpoint() - .into_results_cursor(body_ref); + .into_results_cursor(body); let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks); let mut live_locals_at_suspension_points = Vec::new(); @@ -734,14 +756,14 @@ fn locals_live_across_suspend_points<'tcx>( // saving. let live_locals_at_suspension_points = live_locals_at_suspension_points .iter() - .map(|live_here| saved_locals.renumber_bitset(&live_here)) + .map(|live_here| saved_locals.renumber_bitset(live_here)) .collect(); let storage_conflicts = compute_storage_conflicts( - body_ref, + body, &saved_locals, always_live_locals.clone(), - requires_storage_results, + requires_storage_cursor.into_results(), ); LivenessInfo { @@ -770,7 +792,7 @@ impl CoroutineSavedLocals { /// Transforms a `BitSet` that contains only locals saved across yield points to the /// equivalent `BitSet`. fn renumber_bitset(&self, input: &BitSet) -> BitSet { - assert!(self.superset(&input), "{:?} not a superset of {:?}", self.0, input); + assert!(self.superset(input), "{:?} not a superset of {:?}", self.0, input); let mut out = BitSet::new_empty(self.count()); for (saved_local, local) in self.iter_enumerated() { if input.contains(local) { @@ -806,7 +828,7 @@ fn compute_storage_conflicts<'mir, 'tcx>( body: &'mir Body<'tcx>, saved_locals: &CoroutineSavedLocals, always_live_locals: BitSet, - mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'_, 'mir, 'tcx>>, + mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), saved_locals.domain_size()); @@ -821,7 +843,7 @@ fn compute_storage_conflicts<'mir, 'tcx>( // Compute the storage conflicts for all eligible locals. let mut visitor = StorageConflictVisitor { body, - saved_locals: &saved_locals, + saved_locals: saved_locals, local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()), }; @@ -1120,7 +1142,7 @@ fn create_coroutine_drop_shim<'tcx>( // The returned state and the poisoned state fall through to the default // case which is just to return - insert_switch(&mut body, cases, &transform, TerminatorKind::Return); + insert_switch(&mut body, cases, transform, TerminatorKind::Return); for block in body.basic_blocks_mut() { let kind = &mut block.terminator_mut().kind; @@ -1145,18 +1167,9 @@ fn create_coroutine_drop_shim<'tcx>( simplify::remove_dead_blocks(&mut body); // Update the body's def to become the drop glue. - // This needs to be updated before the AbortUnwindingCalls pass. let coroutine_instance = body.source.instance; let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None); let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(coroutine_ty)); - body.source.instance = drop_instance; - - pm::run_passes_no_validate( - tcx, - &mut body, - &[&abort_unwinding_calls::AbortUnwindingCalls], - None, - ); // Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible // filename. @@ -1329,7 +1342,15 @@ fn create_coroutine_resume_function<'tcx>( insert_switch(body, cases, &transform, TerminatorKind::Unreachable); make_coroutine_state_argument_indirect(tcx, body); - make_coroutine_state_argument_pinned(tcx, body); + + match coroutine_kind { + // Iterator::next doesn't accept a pinned argument, + // unlike for all other coroutine kinds. + CoroutineKind::Gen(_) => {} + _ => { + make_coroutine_state_argument_pinned(tcx, body); + } + } // Make sure we remove dead blocks to remove // unrelated code from the drop part of the function @@ -1449,16 +1470,15 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>( // The first argument is the coroutine type passed by value let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - // Get the interior types and args which typeck computed let movable = match *coroutine_ty.kind() { ty::Coroutine(_, _, movability) => movability == hir::Movability::Movable, ty::Error(_) => return None, _ => span_bug!(body.span, "unexpected coroutine type {}", coroutine_ty), }; - // When first entering the coroutine, move the resume argument into its new local. - let always_live_locals = always_storage_live_locals(&body); + // The witness simply contains all locals live across suspend points. + let always_live_locals = always_storage_live_locals(body); let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable); // Extract locals which are live across suspension point into `layout` @@ -1466,7 +1486,7 @@ pub(crate) fn mir_coroutine_witnesses<'tcx>( // `storage_liveness` tells us which locals have live storage at suspension points let (_, coroutine_layout, _) = compute_layout(liveness_info, body); - check_suspend_tys(tcx, &coroutine_layout, &body); + check_suspend_tys(tcx, &coroutine_layout, body); Some(coroutine_layout) } @@ -1490,13 +1510,16 @@ impl<'tcx> MirPass<'tcx> for StateTransform { (args.discr_ty(tcx), movability == hir::Movability::Movable) } _ => { - tcx.sess - .delay_span_bug(body.span, format!("unexpected coroutine type {coroutine_ty}")); + tcx.sess.span_delayed_bug( + body.span, + format!("unexpected coroutine type {coroutine_ty}"), + ); return; } }; let is_async_kind = matches!(body.coroutine_kind(), Some(CoroutineKind::Async(_))); + let is_gen_kind = matches!(body.coroutine_kind(), Some(CoroutineKind::Gen(_))); let (state_adt_ref, state_args) = match body.coroutine_kind().unwrap() { CoroutineKind::Async(_) => { // Compute Poll @@ -1557,7 +1580,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { }, ); - let always_live_locals = always_storage_live_locals(&body); + let always_live_locals = always_storage_live_locals(body); let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable); @@ -1602,6 +1625,11 @@ impl<'tcx> MirPass<'tcx> for StateTransform { body.arg_count = 2; // self, resume arg body.spread_arg = None; + // Remove the context argument within generator bodies. + if is_gen_kind { + transform_gen_context(tcx, body); + } + // The original arguments to the function are no longer arguments, mark them as such. // Otherwise they'll conflict with our new arguments, which although they don't have // argument_index set, will get emitted as unnamed arguments. diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 9bb26693cb244..79bed960b950f 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -69,7 +69,9 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { } TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => { let fn_ty = self.instantiate_ty(f.const_.ty()); - self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) { + self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() + && tcx.is_intrinsic(def_id) + { // Don't give intrinsics the extra penalty for calls INSTR_COST } else { diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index b34ec95b4e8d3..604589e5b96ba 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -1,18 +1,16 @@ -use super::graph; - -use graph::{BasicCoverageBlock, BcbBranch, CoverageGraph, TraverseCoverageGraphWithLoops}; - use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::WithNumNodes; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; use rustc_middle::mir::coverage::*; +use super::graph::{BasicCoverageBlock, CoverageGraph, TraverseCoverageGraphWithLoops}; + use std::fmt::{self, Debug}; /// The coverage counter or counter expression associated with a particular /// BCB node or BCB edge. -#[derive(Clone)] +#[derive(Clone, Copy)] pub(super) enum BcbCounter { Counter { id: CounterId }, Expression { id: ExpressionId }, @@ -88,11 +86,20 @@ impl CoverageCounters { BcbCounter::Counter { id } } - fn make_expression(&mut self, lhs: CovTerm, op: Op, rhs: CovTerm) -> BcbCounter { - let id = self.expressions.push(Expression { lhs, op, rhs }); + fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter { + let expression = Expression { lhs: lhs.as_term(), op, rhs: rhs.as_term() }; + let id = self.expressions.push(expression); BcbCounter::Expression { id } } + /// Variant of `make_expression` that makes `lhs` optional and assumes [`Op::Add`]. + /// + /// This is useful when using [`Iterator::fold`] to build an arbitrary-length sum. + fn make_sum_expression(&mut self, lhs: Option, rhs: BcbCounter) -> BcbCounter { + let Some(lhs) = lhs else { return rhs }; + self.make_expression(lhs, Op::Add, rhs) + } + /// Counter IDs start from one and go up. fn next_counter(&mut self) -> CounterId { let next = self.next_counter_id; @@ -109,7 +116,7 @@ impl CoverageCounters { self.expressions.len() } - fn set_bcb_counter(&mut self, bcb: BasicCoverageBlock, counter_kind: BcbCounter) -> CovTerm { + fn set_bcb_counter(&mut self, bcb: BasicCoverageBlock, counter_kind: BcbCounter) -> BcbCounter { assert!( // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also // have an expression (to be injected into an existing `BasicBlock` represented by this @@ -118,14 +125,13 @@ impl CoverageCounters { "attempt to add a `Counter` to a BCB target with existing incoming edge counters" ); - let term = counter_kind.as_term(); if let Some(replaced) = self.bcb_counters[bcb].replace(counter_kind) { bug!( "attempt to set a BasicCoverageBlock coverage counter more than once; \ {bcb:?} already had counter {replaced:?}", ); } else { - term + counter_kind } } @@ -134,11 +140,13 @@ impl CoverageCounters { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, counter_kind: BcbCounter, - ) -> CovTerm { + ) -> BcbCounter { // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also // have an expression (to be injected into an existing `BasicBlock` represented by this // `BasicCoverageBlock`). - if let Some(node_counter) = self.bcb_counter(to_bcb) && !node_counter.is_expression() { + if let Some(node_counter) = self.bcb_counter(to_bcb) + && !node_counter.is_expression() + { bug!( "attempt to add an incoming edge counter from {from_bcb:?} \ when the target BCB already has {node_counter:?}" @@ -146,19 +154,18 @@ impl CoverageCounters { } self.bcb_has_incoming_edge_counters.insert(to_bcb); - let term = counter_kind.as_term(); if let Some(replaced) = self.bcb_edge_counters.insert((from_bcb, to_bcb), counter_kind) { bug!( "attempt to set an edge counter more than once; from_bcb: \ {from_bcb:?} already had counter {replaced:?}", ); } else { - term + counter_kind } } - pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&BcbCounter> { - self.bcb_counters[bcb].as_ref() + pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option { + self.bcb_counters[bcb] } pub(super) fn bcb_node_counters( @@ -220,15 +227,11 @@ impl<'a> MakeBcbCounters<'a> { // all `BasicCoverageBlock` nodes in the loop are visited before visiting any node outside // the loop. The `traversal` state includes a `context_stack`, providing a way to know if // the current BCB is in one or more nested loops or not. - let mut traversal = TraverseCoverageGraphWithLoops::new(&self.basic_coverage_blocks); + let mut traversal = TraverseCoverageGraphWithLoops::new(self.basic_coverage_blocks); while let Some(bcb) = traversal.next() { if bcb_has_coverage_spans(bcb) { debug!("{:?} has at least one coverage span. Get or make its counter", bcb); - let branching_counter_operand = self.get_or_make_counter_operand(bcb); - - if self.bcb_needs_branch_counters(bcb) { - self.make_branch_counters(&traversal, bcb, branching_counter_operand); - } + self.make_node_and_branch_counters(&traversal, bcb); } else { debug!( "{:?} does not have any coverage spans. A counter will only be added if \ @@ -245,100 +248,93 @@ impl<'a> MakeBcbCounters<'a> { ); } - fn make_branch_counters( + fn make_node_and_branch_counters( &mut self, traversal: &TraverseCoverageGraphWithLoops<'_>, - branching_bcb: BasicCoverageBlock, - branching_counter_operand: CovTerm, + from_bcb: BasicCoverageBlock, ) { - let branches = self.bcb_branches(branching_bcb); + // First, ensure that this node has a counter of some kind. + // We might also use its term later to compute one of the branch counters. + let from_bcb_operand = self.get_or_make_counter_operand(from_bcb); + + let branch_target_bcbs = self.basic_coverage_blocks.successors[from_bcb].as_slice(); + + // If this node doesn't have multiple out-edges, or all of its out-edges + // already have counters, then we don't need to create edge counters. + let needs_branch_counters = branch_target_bcbs.len() > 1 + && branch_target_bcbs + .iter() + .any(|&to_bcb| self.branch_has_no_counter(from_bcb, to_bcb)); + if !needs_branch_counters { + return; + } + debug!( - "{:?} has some branch(es) without counters:\n {}", - branching_bcb, - branches + "{from_bcb:?} has some branch(es) without counters:\n {}", + branch_target_bcbs .iter() - .map(|branch| { format!("{:?}: {:?}", branch, self.branch_counter(branch)) }) + .map(|&to_bcb| { + format!("{from_bcb:?}->{to_bcb:?}: {:?}", self.branch_counter(from_bcb, to_bcb)) + }) .collect::>() .join("\n "), ); - // Use the `traversal` state to decide if a subset of the branches exit a loop, making it - // likely that branch is executed less than branches that do not exit the same loop. In this - // case, any branch that does not exit the loop (and has not already been assigned a - // counter) should be counted by expression, if possible. (If a preferred expression branch - // is not selected based on the loop context, select any branch without an existing - // counter.) - let expression_branch = self.choose_preferred_expression_branch(traversal, &branches); - - // Assign a Counter or Expression to each branch, plus additional `Expression`s, as needed, - // to sum up intermediate results. - let mut some_sumup_counter_operand = None; - for branch in branches { - // Skip the selected `expression_branch`, if any. It's expression will be assigned after - // all others. - if branch != expression_branch { - let branch_counter_operand = if branch.is_only_path_to_target() { - debug!( - " {:?} has only one incoming edge (from {:?}), so adding a \ - counter", - branch, branching_bcb - ); - self.get_or_make_counter_operand(branch.target_bcb) - } else { - debug!(" {:?} has multiple incoming edges, so adding an edge counter", branch); - self.get_or_make_edge_counter_operand(branching_bcb, branch.target_bcb) - }; - if let Some(sumup_counter_operand) = - some_sumup_counter_operand.replace(branch_counter_operand) - { - let intermediate_expression = self.coverage_counters.make_expression( - branch_counter_operand, - Op::Add, - sumup_counter_operand, - ); - debug!(" [new intermediate expression: {:?}]", intermediate_expression); - let intermediate_expression_operand = intermediate_expression.as_term(); - some_sumup_counter_operand.replace(intermediate_expression_operand); - } - } - } + // Of the branch edges that don't have counters yet, one can be given an expression + // (computed from the other edges) instead of a dedicated counter. + let expression_to_bcb = self.choose_preferred_expression_branch(traversal, from_bcb); - // Assign the final expression to the `expression_branch` by subtracting the total of all - // other branches from the counter of the branching BCB. - let sumup_counter_operand = - some_sumup_counter_operand.expect("sumup_counter_operand should have a value"); + // For each branch arm other than the one that was chosen to get an expression, + // ensure that it has a counter (existing counter/expression or a new counter), + // and accumulate the corresponding terms into a single sum term. + let sum_of_all_other_branches: BcbCounter = { + let _span = debug_span!("sum_of_all_other_branches", ?expression_to_bcb).entered(); + branch_target_bcbs + .iter() + .copied() + // Skip the chosen branch, since we'll calculate it from the other branches. + .filter(|&to_bcb| to_bcb != expression_to_bcb) + .fold(None, |accum, to_bcb| { + let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered(); + let branch_counter = self.get_or_make_edge_counter_operand(from_bcb, to_bcb); + Some(self.coverage_counters.make_sum_expression(accum, branch_counter)) + }) + .expect("there must be at least one other branch") + }; + + // For the branch that was chosen to get an expression, create that expression + // by taking the count of the node we're branching from, and subtracting the + // sum of all the other branches. debug!( - "Making an expression for the selected expression_branch: {:?} \ - (expression_branch predecessors: {:?})", - expression_branch, - self.bcb_predecessors(expression_branch.target_bcb), + "Making an expression for the selected expression_branch: \ + {expression_to_bcb:?} (expression_branch predecessors: {:?})", + self.bcb_predecessors(expression_to_bcb), ); let expression = self.coverage_counters.make_expression( - branching_counter_operand, + from_bcb_operand, Op::Subtract, - sumup_counter_operand, + sum_of_all_other_branches, ); - debug!("{:?} gets an expression: {:?}", expression_branch, expression); - let bcb = expression_branch.target_bcb; - if expression_branch.is_only_path_to_target() { - self.coverage_counters.set_bcb_counter(bcb, expression); + debug!("{expression_to_bcb:?} gets an expression: {expression:?}"); + if self.basic_coverage_blocks.bcb_has_multiple_in_edges(expression_to_bcb) { + self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression); } else { - self.coverage_counters.set_bcb_edge_counter(branching_bcb, bcb, expression); + self.coverage_counters.set_bcb_counter(expression_to_bcb, expression); } } #[instrument(level = "debug", skip(self))] - fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> CovTerm { + fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> BcbCounter { // If the BCB already has a counter, return it. - if let Some(counter_kind) = &self.coverage_counters.bcb_counters[bcb] { + if let Some(counter_kind) = self.coverage_counters.bcb_counters[bcb] { debug!("{bcb:?} already has a counter: {counter_kind:?}"); - return counter_kind.as_term(); + return counter_kind; } // A BCB with only one incoming edge gets a simple `Counter` (via `make_counter()`). // Also, a BCB that loops back to itself gets a simple `Counter`. This may indicate the // program results in a tight infinite loop, but it should still compile. - let one_path_to_target = self.bcb_has_one_path_to_target(bcb); + let one_path_to_target = !self.basic_coverage_blocks.bcb_has_multiple_in_edges(bcb); if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) { let counter_kind = self.coverage_counters.make_counter(); if one_path_to_target { @@ -353,40 +349,25 @@ impl<'a> MakeBcbCounters<'a> { return self.coverage_counters.set_bcb_counter(bcb, counter_kind); } - // A BCB with multiple incoming edges can compute its count by `Expression`, summing up the - // counters and/or expressions of its incoming edges. This will recursively get or create - // counters for those incoming edges first, then call `make_expression()` to sum them up, - // with additional intermediate expressions as needed. - let _sumup_debug_span = debug_span!("(preparing sum-up expression)").entered(); - - let mut predecessors = self.bcb_predecessors(bcb).to_owned().into_iter(); - let first_edge_counter_operand = - self.get_or_make_edge_counter_operand(predecessors.next().unwrap(), bcb); - let mut some_sumup_edge_counter_operand = None; - for predecessor in predecessors { - let edge_counter_operand = self.get_or_make_edge_counter_operand(predecessor, bcb); - if let Some(sumup_edge_counter_operand) = - some_sumup_edge_counter_operand.replace(edge_counter_operand) - { - let intermediate_expression = self.coverage_counters.make_expression( - sumup_edge_counter_operand, - Op::Add, - edge_counter_operand, - ); - debug!("new intermediate expression: {intermediate_expression:?}"); - let intermediate_expression_operand = intermediate_expression.as_term(); - some_sumup_edge_counter_operand.replace(intermediate_expression_operand); - } - } - let counter_kind = self.coverage_counters.make_expression( - first_edge_counter_operand, - Op::Add, - some_sumup_edge_counter_operand.unwrap(), - ); - drop(_sumup_debug_span); - - debug!("{bcb:?} gets a new counter (sum of predecessor counters): {counter_kind:?}"); - self.coverage_counters.set_bcb_counter(bcb, counter_kind) + // A BCB with multiple incoming edges can compute its count by ensuring that counters + // exist for each of those edges, and then adding them up to get a total count. + let sum_of_in_edges: BcbCounter = { + let _span = debug_span!("sum_of_in_edges", ?bcb).entered(); + // We avoid calling `self.bcb_predecessors` here so that we can + // call methods on `&mut self` inside the fold. + self.basic_coverage_blocks.predecessors[bcb] + .iter() + .copied() + .fold(None, |accum, from_bcb| { + let _span = debug_span!("from_bcb", ?accum, ?from_bcb).entered(); + let edge_counter = self.get_or_make_edge_counter_operand(from_bcb, bcb); + Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) + }) + .expect("there must be at least one in-edge") + }; + + debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}"); + self.coverage_counters.set_bcb_counter(bcb, sum_of_in_edges) } #[instrument(level = "debug", skip(self))] @@ -394,20 +375,26 @@ impl<'a> MakeBcbCounters<'a> { &mut self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, - ) -> CovTerm { + ) -> BcbCounter { + // If the target BCB has only one in-edge (i.e. this one), then create + // a node counter instead, since it will have the same value. + if !self.basic_coverage_blocks.bcb_has_multiple_in_edges(to_bcb) { + assert_eq!([from_bcb].as_slice(), self.basic_coverage_blocks.predecessors[to_bcb]); + return self.get_or_make_counter_operand(to_bcb); + } + // If the source BCB has only one successor (assumed to be the given target), an edge // counter is unnecessary. Just get or make a counter for the source BCB. - let successors = self.bcb_successors(from_bcb).iter(); - if successors.len() == 1 { + if self.bcb_successors(from_bcb).len() == 1 { return self.get_or_make_counter_operand(from_bcb); } // If the edge already has a counter, return it. - if let Some(counter_kind) = + if let Some(&counter_kind) = self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb)) { debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}"); - return counter_kind.as_term(); + return counter_kind; } // Make a new counter to count this edge. @@ -421,16 +408,19 @@ impl<'a> MakeBcbCounters<'a> { fn choose_preferred_expression_branch( &self, traversal: &TraverseCoverageGraphWithLoops<'_>, - branches: &[BcbBranch], - ) -> BcbBranch { - let good_reloop_branch = self.find_good_reloop_branch(traversal, &branches); - if let Some(reloop_branch) = good_reloop_branch { - assert!(self.branch_has_no_counter(&reloop_branch)); - debug!("Selecting reloop branch {reloop_branch:?} to get an expression"); - reloop_branch + from_bcb: BasicCoverageBlock, + ) -> BasicCoverageBlock { + let good_reloop_branch = self.find_good_reloop_branch(traversal, from_bcb); + if let Some(reloop_target) = good_reloop_branch { + assert!(self.branch_has_no_counter(from_bcb, reloop_target)); + debug!("Selecting reloop target {reloop_target:?} to get an expression"); + reloop_target } else { - let &branch_without_counter = - branches.iter().find(|&branch| self.branch_has_no_counter(branch)).expect( + let &branch_without_counter = self + .bcb_successors(from_bcb) + .iter() + .find(|&&to_bcb| self.branch_has_no_counter(from_bcb, to_bcb)) + .expect( "needs_branch_counters was `true` so there should be at least one \ branch", ); @@ -451,26 +441,28 @@ impl<'a> MakeBcbCounters<'a> { fn find_good_reloop_branch( &self, traversal: &TraverseCoverageGraphWithLoops<'_>, - branches: &[BcbBranch], - ) -> Option { + from_bcb: BasicCoverageBlock, + ) -> Option { + let branch_target_bcbs = self.bcb_successors(from_bcb); + // Consider each loop on the current traversal context stack, top-down. for reloop_bcbs in traversal.reloop_bcbs_per_loop() { let mut all_branches_exit_this_loop = true; // Try to find a branch that doesn't exit this loop and doesn't // already have a counter. - for &branch in branches { + for &branch_target_bcb in branch_target_bcbs { // A branch is a reloop branch if it dominates any BCB that has // an edge back to the loop header. (Other branches are exits.) let is_reloop_branch = reloop_bcbs.iter().any(|&reloop_bcb| { - self.basic_coverage_blocks.dominates(branch.target_bcb, reloop_bcb) + self.basic_coverage_blocks.dominates(branch_target_bcb, reloop_bcb) }); if is_reloop_branch { all_branches_exit_this_loop = false; - if self.branch_has_no_counter(&branch) { + if self.branch_has_no_counter(from_bcb, branch_target_bcb) { // We found a good branch to be given an expression. - return Some(branch); + return Some(branch_target_bcb); } // Keep looking for another reloop branch without a counter. } else { @@ -503,36 +495,23 @@ impl<'a> MakeBcbCounters<'a> { } #[inline] - fn bcb_branches(&self, from_bcb: BasicCoverageBlock) -> Vec { - self.bcb_successors(from_bcb) - .iter() - .map(|&to_bcb| BcbBranch::from_to(from_bcb, to_bcb, &self.basic_coverage_blocks)) - .collect::>() - } - - fn bcb_needs_branch_counters(&self, bcb: BasicCoverageBlock) -> bool { - let branch_needs_a_counter = |branch: &BcbBranch| self.branch_has_no_counter(branch); - let branches = self.bcb_branches(bcb); - branches.len() > 1 && branches.iter().any(branch_needs_a_counter) - } - - fn branch_has_no_counter(&self, branch: &BcbBranch) -> bool { - self.branch_counter(branch).is_none() + fn branch_has_no_counter( + &self, + from_bcb: BasicCoverageBlock, + to_bcb: BasicCoverageBlock, + ) -> bool { + self.branch_counter(from_bcb, to_bcb).is_none() } - fn branch_counter(&self, branch: &BcbBranch) -> Option<&BcbCounter> { - let to_bcb = branch.target_bcb; - if let Some(from_bcb) = branch.edge_from_bcb { + fn branch_counter( + &self, + from_bcb: BasicCoverageBlock, + to_bcb: BasicCoverageBlock, + ) -> Option<&BcbCounter> { + if self.basic_coverage_blocks.bcb_has_multiple_in_edges(to_bcb) { self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb)) } else { self.coverage_counters.bcb_counters[to_bcb].as_ref() } } - - /// Returns true if the BasicCoverageBlock has zero or one incoming edge. (If zero, it should be - /// the entry point for the function.) - #[inline] - fn bcb_has_one_path_to_target(&self, bcb: BasicCoverageBlock) -> bool { - self.bcb_predecessors(bcb).len() <= 1 - } } diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 6bab62aa85409..263bfdaaabab7 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -38,7 +38,7 @@ impl CoverageGraph { } let bcb_data = &bcbs[bcb]; let mut bcb_successors = Vec::new(); - for successor in bcb_filtered_successors(&mir_body, bcb_data.last_bb()) + for successor in bcb_filtered_successors(mir_body, bcb_data.last_bb()) .filter_map(|successor_bb| bb_to_bcb[successor_bb]) { if !seen[successor] { @@ -62,6 +62,14 @@ impl CoverageGraph { Self { bcbs, bb_to_bcb, successors, predecessors, dominators: None }; let dominators = dominators::dominators(&basic_coverage_blocks); basic_coverage_blocks.dominators = Some(dominators); + + // The coverage graph's entry-point node (bcb0) always starts with bb0, + // which never has predecessors. Any other blocks merged into bcb0 can't + // have multiple (coverage-relevant) predecessors, so bcb0 always has + // zero in-edges. + assert!(basic_coverage_blocks[START_BCB].leader_bb() == mir::START_BLOCK); + assert!(basic_coverage_blocks.predecessors[START_BCB].is_empty()); + basic_coverage_blocks } @@ -199,6 +207,25 @@ impl CoverageGraph { pub fn cmp_in_dominator_order(&self, a: BasicCoverageBlock, b: BasicCoverageBlock) -> Ordering { self.dominators.as_ref().unwrap().cmp_in_dominator_order(a, b) } + + /// Returns true if the given node has 2 or more in-edges, i.e. 2 or more + /// predecessors. + /// + /// This property is interesting to code that assigns counters to nodes and + /// edges, because if a node _doesn't_ have multiple in-edges, then there's + /// no benefit in having a separate counter for its in-edge, because it + /// would have the same value as the node's own counter. + /// + /// FIXME: That assumption might not be true for [`TerminatorKind::Yield`]? + #[inline(always)] + pub(super) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool { + // Even though bcb0 conceptually has an extra virtual in-edge due to + // being the entry point, we've already asserted that it has no _other_ + // in-edges, so there's no possibility of it having _multiple_ in-edges. + // (And since its virtual in-edge doesn't exist in the graph, that edge + // can't have a separate counter anyway.) + self.predecessors[bcb].len() > 1 + } } impl Index for CoverageGraph { @@ -264,6 +291,7 @@ impl graph::WithPredecessors for CoverageGraph { rustc_index::newtype_index! { /// A node in the control-flow graph of CoverageGraph. + #[orderable] #[debug_format = "bcb{}"] pub(super) struct BasicCoverageBlock { const START_BCB = 0; @@ -318,45 +346,6 @@ impl BasicCoverageBlockData { } } -/// Represents a successor from a branching BasicCoverageBlock (such as the arms of a `SwitchInt`) -/// as either the successor BCB itself, if it has only one incoming edge, or the successor _plus_ -/// the specific branching BCB, representing the edge between the two. The latter case -/// distinguishes this incoming edge from other incoming edges to the same `target_bcb`. -#[derive(Clone, Copy, PartialEq, Eq)] -pub(super) struct BcbBranch { - pub edge_from_bcb: Option, - pub target_bcb: BasicCoverageBlock, -} - -impl BcbBranch { - pub fn from_to( - from_bcb: BasicCoverageBlock, - to_bcb: BasicCoverageBlock, - basic_coverage_blocks: &CoverageGraph, - ) -> Self { - let edge_from_bcb = if basic_coverage_blocks.predecessors[to_bcb].len() > 1 { - Some(from_bcb) - } else { - None - }; - Self { edge_from_bcb, target_bcb: to_bcb } - } - - pub fn is_only_path_to_target(&self) -> bool { - self.edge_from_bcb.is_none() - } -} - -impl std::fmt::Debug for BcbBranch { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(from_bcb) = self.edge_from_bcb { - write!(fmt, "{:?}->{:?}", from_bcb, self.target_bcb) - } else { - write!(fmt, "{:?}", self.target_bcb) - } - } -} - // Returns the subset of a block's successors that are relevant to the coverage // graph, i.e. those that do not represent unwinds or unreachable branches. // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 97e4468a0e8bd..796150f931581 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -142,7 +142,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { //////////////////////////////////////////////////// // Compute coverage spans from the `CoverageGraph`. let coverage_spans = CoverageSpans::generate_coverage_spans( - &self.mir_body, + self.mir_body, fn_sig_span, body_span, &self.basic_coverage_blocks, @@ -240,7 +240,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { ); // Inject a counter into the newly-created BB. - inject_statement(self.mir_body, self.make_mir_coverage_kind(&counter_kind), new_bb); + inject_statement(self.mir_body, self.make_mir_coverage_kind(counter_kind), new_bb); } mappings diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 704eea413e118..c415a8329942a 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -89,10 +89,10 @@ impl CoverageSpan { } } - pub fn merge_from(&mut self, mut other: CoverageSpan) { - debug_assert!(self.is_mergeable(&other)); + pub fn merge_from(&mut self, other: &Self) { + debug_assert!(self.is_mergeable(other)); self.span = self.span.to(other.span); - self.merged_spans.append(&mut other.merged_spans); + self.merged_spans.extend_from_slice(&other.merged_spans); } pub fn cutoff_statements_at(&mut self, cutoff_pos: BytePos) { @@ -129,16 +129,14 @@ impl CoverageSpan { /// If the span is part of a macro, and the macro is visible (expands directly to the given /// body_span), returns the macro name symbol. pub fn visible_macro(&self, body_span: Span) -> Option { - if let Some(current_macro) = self.current_macro() - && self - .expn_span - .parent_callsite() - .unwrap_or_else(|| bug!("macro must have a parent")) - .eq_ctxt(body_span) - { - return Some(current_macro); - } - None + let current_macro = self.current_macro()?; + let parent_callsite = self.expn_span.parent_callsite()?; + + // In addition to matching the context of the body span, the parent callsite + // must also be the source callsite, i.e. the parent must have no parent. + let is_visible_macro = + parent_callsite.parent_callsite().is_none() && parent_callsite.eq_ctxt(body_span); + is_visible_macro.then_some(current_macro) } pub fn is_macro_expansion(&self) -> bool { @@ -269,7 +267,7 @@ impl<'a> CoverageSpansGenerator<'a> { if curr.is_mergeable(prev) { debug!(" same bcb (and neither is a closure), merge with prev={prev:?}"); let prev = self.take_prev(); - self.curr_mut().merge_from(prev); + self.curr_mut().merge_from(&prev); self.maybe_push_macro_name_span(); // Note that curr.span may now differ from curr_original_span } else if prev.span.hi() <= curr.span.lo() { @@ -277,7 +275,7 @@ impl<'a> CoverageSpansGenerator<'a> { " different bcbs and disjoint spans, so keep curr for next iter, and add prev={prev:?}", ); let prev = self.take_prev(); - self.push_refined_span(prev); + self.refined_spans.push(prev); self.maybe_push_macro_name_span(); } else if prev.is_closure { // drop any equal or overlapping span (`curr`) and keep `prev` to test again in the @@ -324,11 +322,10 @@ impl<'a> CoverageSpansGenerator<'a> { let prev = self.take_prev(); debug!(" AT END, adding last prev={prev:?}"); - // Take `pending_dups` so that we can drain it while calling self methods. - // It is never used as a field after this point. - for dup in std::mem::take(&mut self.pending_dups) { + // Drain any remaining dups into the output. + for dup in self.pending_dups.drain(..) { debug!(" ...adding at least one pending dup={:?}", dup); - self.push_refined_span(dup); + self.refined_spans.push(dup); } // Async functions wrap a closure that implements the body to be executed. The enclosing @@ -345,9 +342,20 @@ impl<'a> CoverageSpansGenerator<'a> { }; if !body_ends_with_closure { - self.push_refined_span(prev); + self.refined_spans.push(prev); } + // Do one last merge pass, to simplify the output. + self.refined_spans.dedup_by(|b, a| { + if a.is_mergeable(b) { + debug!(?a, ?b, "merging list-adjacent refined spans"); + a.merge_from(b); + true + } else { + false + } + }); + // Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage // regions for the current function leave room for the closure's own coverage regions // (injected separately, from the closure's own MIR). @@ -355,18 +363,6 @@ impl<'a> CoverageSpansGenerator<'a> { self.refined_spans } - fn push_refined_span(&mut self, covspan: CoverageSpan) { - if let Some(last) = self.refined_spans.last_mut() - && last.is_mergeable(&covspan) - { - // Instead of pushing the new span, merge it with the last refined span. - debug!(?last, ?covspan, "merging new refined span with last refined span"); - last.merge_from(covspan); - } else { - self.refined_spans.push(covspan); - } - } - /// If `curr` is part of a new macro expansion, carve out and push a separate /// span that ends just after the macro name and its subsequent `!`. fn maybe_push_macro_name_span(&mut self) { @@ -379,17 +375,27 @@ impl<'a> CoverageSpansGenerator<'a> { return; } - let merged_prefix_len = self.curr_original_span.lo() - curr.span.lo(); - let after_macro_bang = merged_prefix_len + BytePos(visible_macro.as_str().len() as u32 + 1); + // The split point is relative to `curr_original_span`, + // because `curr.span` may have been merged with preceding spans. + let split_point_after_macro_bang = self.curr_original_span.lo() + + BytePos(visible_macro.as_str().len() as u32) + + BytePos(1); // add 1 for the `!` + debug_assert!(split_point_after_macro_bang <= curr.span.hi()); + if split_point_after_macro_bang > curr.span.hi() { + // Something is wrong with the macro name span; + // return now to avoid emitting malformed mappings (e.g. #117788). + return; + } + let mut macro_name_cov = curr.clone(); - self.curr_mut().span = curr.span.with_lo(curr.span.lo() + after_macro_bang); - macro_name_cov.span = - macro_name_cov.span.with_hi(macro_name_cov.span.lo() + after_macro_bang); + macro_name_cov.span = macro_name_cov.span.with_hi(split_point_after_macro_bang); + self.curr_mut().span = curr.span.with_lo(split_point_after_macro_bang); + debug!( " and curr starts a new macro expansion, so add a new span just for \ the macro `{visible_macro}!`, new span={macro_name_cov:?}", ); - self.push_refined_span(macro_name_cov); + self.refined_spans.push(macro_name_cov); } fn curr(&self) -> &CoverageSpan { @@ -446,19 +452,14 @@ impl<'a> CoverageSpansGenerator<'a> { previous iteration, or prev started a new disjoint span" ); if last_dup.span.hi() <= self.curr().span.lo() { - // Temporarily steal `pending_dups` into a local, so that we can - // drain it while calling other self methods. - let mut pending_dups = std::mem::take(&mut self.pending_dups); - for dup in pending_dups.drain(..) { + for dup in self.pending_dups.drain(..) { debug!(" ...adding at least one pending={:?}", dup); - self.push_refined_span(dup); + self.refined_spans.push(dup); } - // The list of dups is now empty, but we can recycle its capacity. - assert!(pending_dups.is_empty() && self.pending_dups.is_empty()); - self.pending_dups = pending_dups; } else { self.pending_dups.clear(); } + assert!(self.pending_dups.is_empty()); } /// Advance `prev` to `curr` (if any), and `curr` to the next `CoverageSpan` in sorted order. @@ -469,7 +470,9 @@ impl<'a> CoverageSpansGenerator<'a> { } while let Some(curr) = self.sorted_spans_iter.next() { debug!("FOR curr={:?}", curr); - if let Some(prev) = &self.some_prev && prev.span.lo() > curr.span.lo() { + if let Some(prev) = &self.some_prev + && prev.span.lo() > curr.span.lo() + { // Skip curr because prev has already advanced beyond the end of curr. // This can only happen if a prior iteration updated `prev` to skip past // a region of code, such as skipping past a closure. @@ -503,22 +506,18 @@ impl<'a> CoverageSpansGenerator<'a> { let has_pre_closure_span = prev.span.lo() < right_cutoff; let has_post_closure_span = prev.span.hi() > right_cutoff; - // Temporarily steal `pending_dups` into a local, so that we can - // mutate and/or drain it while calling other self methods. - let mut pending_dups = std::mem::take(&mut self.pending_dups); - if has_pre_closure_span { let mut pre_closure = self.prev().clone(); pre_closure.span = pre_closure.span.with_hi(left_cutoff); debug!(" prev overlaps a closure. Adding span for pre_closure={:?}", pre_closure); - if !pending_dups.is_empty() { - for mut dup in pending_dups.iter().cloned() { - dup.span = dup.span.with_hi(left_cutoff); - debug!(" ...and at least one pre_closure dup={:?}", dup); - self.push_refined_span(dup); - } + + for mut dup in self.pending_dups.iter().cloned() { + dup.span = dup.span.with_hi(left_cutoff); + debug!(" ...and at least one pre_closure dup={:?}", dup); + self.refined_spans.push(dup); } - self.push_refined_span(pre_closure); + + self.refined_spans.push(pre_closure); } if has_post_closure_span { @@ -527,19 +526,17 @@ impl<'a> CoverageSpansGenerator<'a> { // about how the `CoverageSpan`s are ordered.) self.prev_mut().span = self.prev().span.with_lo(right_cutoff); debug!(" Mutated prev.span to start after the closure. prev={:?}", self.prev()); - for dup in pending_dups.iter_mut() { + + for dup in &mut self.pending_dups { debug!(" ...and at least one overlapping dup={:?}", dup); dup.span = dup.span.with_lo(right_cutoff); } + let closure_covspan = self.take_curr(); // Prevent this curr from becoming prev. - self.push_refined_span(closure_covspan); // since self.prev() was already updated + self.refined_spans.push(closure_covspan); // since self.prev() was already updated } else { - pending_dups.clear(); + self.pending_dups.clear(); } - - // Restore the modified post-closure spans, or the empty vector's capacity. - assert!(self.pending_dups.is_empty()); - self.pending_dups = pending_dups; } /// Called if `curr.span` equals `prev_original_span` (and potentially equal to all @@ -635,7 +632,7 @@ impl<'a> CoverageSpansGenerator<'a> { } else { debug!(" ... adding modified prev={:?}", self.prev()); let prev = self.take_prev(); - self.push_refined_span(prev); + self.refined_spans.push(prev); } } else { // with `pending_dups`, `prev` cannot have any statements that don't overlap diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 6189e5379ea05..e1531f2c239bf 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -63,14 +63,14 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( let statement_spans = data.statements.iter().filter_map(move |statement| { let expn_span = filtered_statement_span(statement)?; - let span = function_source_span(expn_span, body_span); + let span = unexpand_into_body_span(expn_span, body_span)?; Some(CoverageSpan::new(span, expn_span, bcb, is_closure(statement))) }); let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| { let expn_span = filtered_terminator_span(terminator)?; - let span = function_source_span(expn_span, body_span); + let span = unexpand_into_body_span(expn_span, body_span)?; Some(CoverageSpan::new(span, expn_span, bcb, false)) }); @@ -180,14 +180,16 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { /// Returns an extrapolated span (pre-expansion[^1]) corresponding to a range /// within the function's body source. This span is guaranteed to be contained /// within, or equal to, the `body_span`. If the extrapolated span is not -/// contained within the `body_span`, the `body_span` is returned. +/// contained within the `body_span`, `None` is returned. /// /// [^1]Expansions result from Rust syntax including macros, syntactic sugar, /// etc.). #[inline] -fn function_source_span(span: Span, body_span: Span) -> Span { +fn unexpand_into_body_span(span: Span, body_span: Span) -> Option { use rustc_span::source_map::original_sp; + // FIXME(#118525): Consider switching from `original_sp` to `Span::find_ancestor_inside`, + // which is similar but gives slightly different results in some edge cases. let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt()); - if body_span.contains(original_span) { original_span } else { body_span } + body_span.contains(original_span).then_some(original_span) } diff --git a/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml deleted file mode 100644 index f753caa91248e..0000000000000 --- a/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "coverage_test_macros" -version = "0.0.0" -edition = "2021" - -[lib] -proc-macro = true diff --git a/compiler/rustc_mir_transform/src/coverage/test_macros/src/lib.rs b/compiler/rustc_mir_transform/src/coverage/test_macros/src/lib.rs deleted file mode 100644 index f41adf667ec55..0000000000000 --- a/compiler/rustc_mir_transform/src/coverage/test_macros/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -use proc_macro::TokenStream; - -#[proc_macro] -pub fn let_bcb(item: TokenStream) -> TokenStream { - format!("let bcb{item} = graph::BasicCoverageBlock::from_usize({item});").parse().unwrap() -} diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 702fe5f563e56..302cbf05d78b1 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -27,8 +27,6 @@ use super::counters; use super::graph::{self, BasicCoverageBlock}; -use coverage_test_macros::let_bcb; - use itertools::Itertools; use rustc_data_structures::graph::WithNumNodes; use rustc_data_structures::graph::WithSuccessors; @@ -37,6 +35,10 @@ use rustc_middle::mir::*; use rustc_middle::ty; use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP}; +fn bcb(index: u32) -> BasicCoverageBlock { + BasicCoverageBlock::from_u32(index) +} + // All `TEMP_BLOCK` targets should be replaced before calling `to_body() -> mir::Body`. const TEMP_BLOCK: BasicBlock = BasicBlock::MAX; @@ -300,12 +302,15 @@ fn goto_switchint<'a>() -> Body<'a> { mir_body } -macro_rules! assert_successors { - ($basic_coverage_blocks:ident, $i:ident, [$($successor:ident),*]) => { - let mut successors = $basic_coverage_blocks.successors[$i].clone(); - successors.sort_unstable(); - assert_eq!(successors, vec![$($successor),*]); - } +#[track_caller] +fn assert_successors( + basic_coverage_blocks: &graph::CoverageGraph, + bcb: BasicCoverageBlock, + expected_successors: &[BasicCoverageBlock], +) { + let mut successors = basic_coverage_blocks.successors[bcb].clone(); + successors.sort_unstable(); + assert_eq!(successors, expected_successors); } #[test] @@ -334,13 +339,9 @@ fn test_covgraph_goto_switchint() { basic_coverage_blocks.iter_enumerated().collect::>() ); - let_bcb!(0); - let_bcb!(1); - let_bcb!(2); - - assert_successors!(basic_coverage_blocks, bcb0, [bcb1, bcb2]); - assert_successors!(basic_coverage_blocks, bcb1, []); - assert_successors!(basic_coverage_blocks, bcb2, []); + assert_successors(&basic_coverage_blocks, bcb(0), &[bcb(1), bcb(2)]); + assert_successors(&basic_coverage_blocks, bcb(1), &[]); + assert_successors(&basic_coverage_blocks, bcb(2), &[]); } /// Create a mock `Body` with a loop. @@ -418,15 +419,10 @@ fn test_covgraph_switchint_then_loop_else_return() { basic_coverage_blocks.iter_enumerated().collect::>() ); - let_bcb!(0); - let_bcb!(1); - let_bcb!(2); - let_bcb!(3); - - assert_successors!(basic_coverage_blocks, bcb0, [bcb1]); - assert_successors!(basic_coverage_blocks, bcb1, [bcb2, bcb3]); - assert_successors!(basic_coverage_blocks, bcb2, []); - assert_successors!(basic_coverage_blocks, bcb3, [bcb1]); + assert_successors(&basic_coverage_blocks, bcb(0), &[bcb(1)]); + assert_successors(&basic_coverage_blocks, bcb(1), &[bcb(2), bcb(3)]); + assert_successors(&basic_coverage_blocks, bcb(2), &[]); + assert_successors(&basic_coverage_blocks, bcb(3), &[bcb(1)]); } /// Create a mock `Body` with nested loops. @@ -546,21 +542,13 @@ fn test_covgraph_switchint_loop_then_inner_loop_else_break() { basic_coverage_blocks.iter_enumerated().collect::>() ); - let_bcb!(0); - let_bcb!(1); - let_bcb!(2); - let_bcb!(3); - let_bcb!(4); - let_bcb!(5); - let_bcb!(6); - - assert_successors!(basic_coverage_blocks, bcb0, [bcb1]); - assert_successors!(basic_coverage_blocks, bcb1, [bcb2, bcb3]); - assert_successors!(basic_coverage_blocks, bcb2, []); - assert_successors!(basic_coverage_blocks, bcb3, [bcb4]); - assert_successors!(basic_coverage_blocks, bcb4, [bcb5, bcb6]); - assert_successors!(basic_coverage_blocks, bcb5, [bcb1]); - assert_successors!(basic_coverage_blocks, bcb6, [bcb4]); + assert_successors(&basic_coverage_blocks, bcb(0), &[bcb(1)]); + assert_successors(&basic_coverage_blocks, bcb(1), &[bcb(2), bcb(3)]); + assert_successors(&basic_coverage_blocks, bcb(2), &[]); + assert_successors(&basic_coverage_blocks, bcb(3), &[bcb(4)]); + assert_successors(&basic_coverage_blocks, bcb(4), &[bcb(5), bcb(6)]); + assert_successors(&basic_coverage_blocks, bcb(5), &[bcb(1)]); + assert_successors(&basic_coverage_blocks, bcb(6), &[bcb(4)]); } #[test] @@ -595,10 +583,7 @@ fn test_find_loop_backedges_one() { backedges ); - let_bcb!(1); - let_bcb!(3); - - assert_eq!(backedges[bcb1], vec![bcb3]); + assert_eq!(backedges[bcb(1)], &[bcb(3)]); } #[test] @@ -613,13 +598,8 @@ fn test_find_loop_backedges_two() { backedges ); - let_bcb!(1); - let_bcb!(4); - let_bcb!(5); - let_bcb!(6); - - assert_eq!(backedges[bcb1], vec![bcb5]); - assert_eq!(backedges[bcb4], vec![bcb6]); + assert_eq!(backedges[bcb(1)], &[bcb(5)]); + assert_eq!(backedges[bcb(4)], &[bcb(6)]); } #[test] @@ -632,13 +612,11 @@ fn test_traverse_coverage_with_loops() { traversed_in_order.push(bcb); } - let_bcb!(6); - // bcb0 is visited first. Then bcb1 starts the first loop, and all remaining nodes, *except* // bcb6 are inside the first loop. assert_eq!( *traversed_in_order.last().expect("should have elements"), - bcb6, + bcb(6), "bcb6 should not be visited until all nodes inside the first loop have been visited" ); } @@ -656,20 +634,18 @@ fn test_make_bcb_counters() { coverage_counters.make_bcb_counters(&basic_coverage_blocks, bcb_has_coverage_spans); assert_eq!(coverage_counters.num_expressions(), 0); - let_bcb!(1); assert_eq!( 0, // bcb1 has a `Counter` with id = 0 - match coverage_counters.bcb_counter(bcb1).expect("should have a counter") { + match coverage_counters.bcb_counter(bcb(1)).expect("should have a counter") { counters::BcbCounter::Counter { id, .. } => id, _ => panic!("expected a Counter"), } .as_u32() ); - let_bcb!(2); assert_eq!( 1, // bcb2 has a `Counter` with id = 1 - match coverage_counters.bcb_counter(bcb2).expect("should have a counter") { + match coverage_counters.bcb_counter(bcb(2)).expect("should have a counter") { counters::BcbCounter::Counter { id, .. } => id, _ => panic!("expected a Counter"), } diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 4d0e261ed1fd7..261d9dd448d47 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -7,6 +7,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; +use rustc_session::config::InliningThreshold; use rustc_session::config::OptLevel; pub fn provide(providers: &mut Providers) { @@ -54,6 +55,12 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return false; } + let threshold = match tcx.sess.opts.unstable_opts.cross_crate_inline_threshold { + InliningThreshold::Always => return true, + InliningThreshold::Sometimes(threshold) => threshold, + InliningThreshold::Never => return false, + }; + let mir = tcx.optimized_mir(def_id); let mut checker = CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 }; @@ -61,8 +68,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { checker.calls == 0 && checker.resumes == 0 && checker.landing_pads == 0 - && checker.statements - <= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100) + && checker.statements <= threshold } struct CostChecker<'b, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index bf5722b3d00b2..dcc960e1e0206 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -20,7 +20,7 @@ impl<'tcx> MirPass<'tcx> for CtfeLimit { .filter_map(|(node, node_data)| { if matches!(node_data.terminator().kind, TerminatorKind::Call { .. }) // Back edges in a CFG indicate loops - || has_back_edge(&doms, node, &node_data) + || has_back_edge(doms, node, node_data) { Some(node) } else { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 81d2bba989a7f..e9949ebbc873c 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -8,6 +8,7 @@ use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult, Scalar}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{ @@ -362,7 +363,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { && let Ok(rhs_layout) = self.tcx.layout_of(self.param_env.and(rhs_ty)) { let op = ImmTy::from_scalar(pointer, rhs_layout).into(); - self.assign_constant(state, place, op, &rhs.projection); + self.assign_constant(state, place, op, rhs.projection); } } Operand::Constant(box constant) => { @@ -597,7 +598,9 @@ fn propagatable_scalar( state: &State>, map: &Map, ) -> Option { - if let FlatSet::Elem(value) = state.get_idx(place, map) && value.try_to_int().is_ok() { + if let FlatSet::Elem(value) = state.get_idx(place, map) + && value.try_to_int().is_ok() + { // Do not attempt to propagate pointers, as we may fail to preserve their identity. Some(value) } else { @@ -836,7 +839,8 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { location: Location, ) { if let PlaceElem::Index(local) = elem - && let Some(value) = self.visitor.try_make_constant(self.ecx, local.into(), self.state, self.map) + && let Some(value) = + self.visitor.try_make_constant(self.ecx, local.into(), self.state, self.map) { self.visitor.patch.before_effect.insert((location, local.into()), value); } @@ -873,7 +877,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm } fn before_access_global( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, _machine: &Self, _alloc_id: AllocId, alloc: ConstAllocation<'tcx>, diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 59156b2427cce..f7188ea83fc5c 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -57,7 +57,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { // For types that do not need dropping, the behaviour is trivial. So we only need to track // init/uninit for types that do need dropping. let move_data = - MoveData::gather_moves(&body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env)); + MoveData::gather_moves(body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env)); let elaborate_patch = { let env = MoveDataParamEnv { move_data, param_env }; @@ -67,7 +67,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { .pass_name("elaborate_drops") .iterate_to_fixpoint() .into_results_cursor(body); - let dead_unwinds = compute_dead_unwinds(&body, &mut inits); + let dead_unwinds = compute_dead_unwinds(body, &mut inits); let uninits = MaybeUninitializedPlaces::new(tcx, body, &env) .mark_inactive_variants_as_uninit() @@ -172,19 +172,13 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { let mut some_live = false; let mut some_dead = false; let mut children_count = 0; - on_all_children_bits( - self.tcx(), - self.body(), - self.ctxt.move_data(), - path, - |child| { - let (live, dead) = self.ctxt.init_data.maybe_live_dead(child); - debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead)); - some_live |= live; - some_dead |= dead; - children_count += 1; - }, - ); + on_all_children_bits(self.ctxt.move_data(), path, |child| { + let (live, dead) = self.ctxt.init_data.maybe_live_dead(child); + debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead)); + some_live |= live; + some_dead |= dead; + children_count += 1; + }); ((some_live, some_dead), children_count != 1) } }; @@ -202,13 +196,9 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent); } DropFlagMode::Deep => { - on_all_children_bits( - self.tcx(), - self.body(), - self.ctxt.move_data(), - path, - |child| self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent), - ); + on_all_children_bits(self.ctxt.move_data(), path, |child| { + self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent) + }); } } } @@ -268,10 +258,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) { - let tcx = self.tcx; let patch = &mut self.patch; debug!("create_drop_flag({:?})", self.body.span); - self.drop_flags[index].get_or_insert_with(|| patch.new_temp(tcx.types.bool, span)); + self.drop_flags[index].get_or_insert_with(|| patch.new_temp(self.tcx.types.bool, span)); } fn drop_flag(&mut self, index: MovePathIndex) -> Option> { @@ -304,7 +293,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { match path { LookupResult::Exact(path) => { self.init_data.seek_before(self.body.terminator_loc(bb)); - on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| { + on_all_children_bits(self.move_data(), path, |child| { let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child); debug!( "collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}", @@ -327,7 +316,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { self.init_data.seek_before(self.body.terminator_loc(bb)); let (_maybe_live, maybe_dead) = self.init_data.maybe_live_dead(parent); if maybe_dead { - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( terminator.source_info.span, format!( "drop of untracked, uninitialized value {bb:?}, place {place:?} ({path:?})" @@ -392,7 +381,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { LookupResult::Parent(None) => {} LookupResult::Parent(Some(_)) => { if !replace { - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( terminator.source_info.span, format!("drop of untracked value {bb:?}"), ); @@ -444,7 +433,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let loc = Location { block: tgt, statement_index: 0 }; let path = self.move_data().rev_lookup.find(destination.as_ref()); - on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| { + on_lookup_result_bits(self.move_data(), path, |child| { self.set_drop_flag(loc, child, DropFlagState::Present) }); } @@ -453,14 +442,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn drop_flags_for_args(&mut self) { let loc = Location::START; - rustc_mir_dataflow::drop_flag_effects_for_function_entry( - self.tcx, - self.body, - self.env, - |path, ds| { - self.set_drop_flag(loc, path, ds); - }, - ) + rustc_mir_dataflow::drop_flag_effects_for_function_entry(self.body, self.env, |path, ds| { + self.set_drop_flag(loc, path, ds); + }) } fn drop_flags_for_locs(&mut self) { @@ -492,7 +476,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } let loc = Location { block: bb, statement_index: i }; rustc_mir_dataflow::drop_flag_effects_for_location( - self.tcx, self.body, self.env, loc, @@ -515,7 +498,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let loc = Location { block: bb, statement_index: data.statements.len() }; let path = self.move_data().rev_lookup.find(destination.as_ref()); - on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| { + on_lookup_result_bits(self.move_data(), path, |child| { self.set_drop_flag(loc, child, DropFlagState::Present) }); } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 5879a803946d6..2358661738a55 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,6 +1,8 @@ +use std::borrow::Cow; + use rustc_errors::{ - Applicability, DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler, - IntoDiagnostic, + Applicability, DecorateLint, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, + EmissionGuarantee, ErrorGuaranteed, Handler, IntoDiagnostic, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; @@ -9,6 +11,8 @@ use rustc_session::lint::{self, Lint}; use rustc_span::def_id::DefId; use rustc_span::Span; +use crate::fluent_generated as fluent; + #[derive(LintDiagnostic)] pub(crate) enum ConstMutate { #[diag(mir_transform_const_modify)] @@ -58,75 +62,108 @@ pub(crate) struct RequiresUnsafe { // so we need to eagerly translate the label here, which isn't supported by the derive API // We could also exhaustively list out the primary messages for all unsafe violations, // but this would result in a lot of duplication. -impl<'sess, G: EmissionGuarantee> IntoDiagnostic<'sess, G> for RequiresUnsafe { +impl<'sess> IntoDiagnostic<'sess> for RequiresUnsafe { #[track_caller] - fn into_diagnostic(self, handler: &'sess Handler) -> DiagnosticBuilder<'sess, G> { - let mut diag = - handler.struct_diagnostic(crate::fluent_generated::mir_transform_requires_unsafe); + fn into_diagnostic(self, handler: &'sess Handler) -> DiagnosticBuilder<'sess, ErrorGuaranteed> { + let mut diag = handler.struct_diagnostic(fluent::mir_transform_requires_unsafe); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.set_span(self.span); diag.span_label(self.span, self.details.label()); - diag.note(self.details.note()); let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); diag.set_arg("details", desc); diag.set_arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); + self.details.add_subdiagnostics(&mut diag); if let Some(sp) = self.enclosing { - diag.span_label(sp, crate::fluent_generated::mir_transform_not_inherited); + diag.span_label(sp, fluent::mir_transform_not_inherited); } diag } } -#[derive(Copy, Clone)] +#[derive(Clone)] pub(crate) struct RequiresUnsafeDetail { pub span: Span, pub violation: UnsafetyViolationDetails, } impl RequiresUnsafeDetail { - fn note(self) -> DiagnosticMessage { + fn add_subdiagnostics(&self, diag: &mut DiagnosticBuilder<'_, G>) { use UnsafetyViolationDetails::*; match self.violation { - CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_note, - UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_note, + CallToUnsafeFunction => { + diag.note(fluent::mir_transform_call_to_unsafe_note); + } + UseOfInlineAssembly => { + diag.note(fluent::mir_transform_use_of_asm_note); + } InitializingTypeWith => { - crate::fluent_generated::mir_transform_initializing_valid_range_note + diag.note(fluent::mir_transform_initializing_valid_range_note); + } + CastOfPointerToInt => { + diag.note(fluent::mir_transform_const_ptr2int_note); + } + UseOfMutableStatic => { + diag.note(fluent::mir_transform_use_of_static_mut_note); + } + UseOfExternStatic => { + diag.note(fluent::mir_transform_use_of_extern_static_note); + } + DerefOfRawPointer => { + diag.note(fluent::mir_transform_deref_ptr_note); + } + AccessToUnionField => { + diag.note(fluent::mir_transform_union_access_note); } - CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_note, - UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_note, - UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_note, - DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_note, - AccessToUnionField => crate::fluent_generated::mir_transform_union_access_note, MutationOfLayoutConstrainedField => { - crate::fluent_generated::mir_transform_mutation_layout_constrained_note + diag.note(fluent::mir_transform_mutation_layout_constrained_note); } BorrowOfLayoutConstrainedField => { - crate::fluent_generated::mir_transform_mutation_layout_constrained_borrow_note + diag.note(fluent::mir_transform_mutation_layout_constrained_borrow_note); + } + CallToFunctionWith { ref missing, ref build_enabled } => { + diag.help(fluent::mir_transform_target_feature_call_help); + diag.set_arg( + "missing_target_features", + DiagnosticArgValue::StrListSepByAnd( + missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + ); + diag.set_arg("missing_target_features_count", missing.len()); + if !build_enabled.is_empty() { + diag.note(fluent::mir_transform_target_feature_call_note); + diag.set_arg( + "build_target_features", + DiagnosticArgValue::StrListSepByAnd( + build_enabled + .iter() + .map(|feature| Cow::from(feature.as_str())) + .collect(), + ), + ); + diag.set_arg("build_target_features_count", build_enabled.len()); + } } - CallToFunctionWith => crate::fluent_generated::mir_transform_target_feature_call_note, } } - fn label(self) -> DiagnosticMessage { + fn label(&self) -> DiagnosticMessage { use UnsafetyViolationDetails::*; match self.violation { - CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_label, - UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_label, - InitializingTypeWith => { - crate::fluent_generated::mir_transform_initializing_valid_range_label - } - CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_label, - UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_label, - UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_label, - DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_label, - AccessToUnionField => crate::fluent_generated::mir_transform_union_access_label, + CallToUnsafeFunction => fluent::mir_transform_call_to_unsafe_label, + UseOfInlineAssembly => fluent::mir_transform_use_of_asm_label, + InitializingTypeWith => fluent::mir_transform_initializing_valid_range_label, + CastOfPointerToInt => fluent::mir_transform_const_ptr2int_label, + UseOfMutableStatic => fluent::mir_transform_use_of_static_mut_label, + UseOfExternStatic => fluent::mir_transform_use_of_extern_static_label, + DerefOfRawPointer => fluent::mir_transform_deref_ptr_label, + AccessToUnionField => fluent::mir_transform_union_access_label, MutationOfLayoutConstrainedField => { - crate::fluent_generated::mir_transform_mutation_layout_constrained_label + fluent::mir_transform_mutation_layout_constrained_label } BorrowOfLayoutConstrainedField => { - crate::fluent_generated::mir_transform_mutation_layout_constrained_borrow_label + fluent::mir_transform_mutation_layout_constrained_borrow_label } - CallToFunctionWith => crate::fluent_generated::mir_transform_target_feature_call_label, + CallToFunctionWith { .. } => fluent::mir_transform_target_feature_call_label, } } } @@ -151,12 +188,12 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); diag.set_arg("details", desc); diag.span_label(self.details.span, self.details.label()); - diag.note(self.details.note()); + self.details.add_subdiagnostics(diag); if let Some((start, end, fn_sig)) = self.suggest_unsafe_block { - diag.span_note(fn_sig, crate::fluent_generated::mir_transform_note); + diag.span_note(fn_sig, fluent::mir_transform_note); diag.tool_only_multipart_suggestion( - crate::fluent_generated::mir_transform_suggestion, + fluent::mir_transform_suggestion, vec![(start, " unsafe {".into()), (end, "}".into())], Applicability::MaybeIncorrect, ); @@ -166,7 +203,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { } fn msg(&self) -> DiagnosticMessage { - crate::fluent_generated::mir_transform_unsafe_op_in_unsafe_fn + fluent::mir_transform_unsafe_op_in_unsafe_fn } } @@ -193,12 +230,8 @@ impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint

{ fn msg(&self) -> DiagnosticMessage { match self { - AssertLint::ArithmeticOverflow(..) => { - crate::fluent_generated::mir_transform_arithmetic_overflow - } - AssertLint::UnconditionalPanic(..) => { - crate::fluent_generated::mir_transform_operation_will_panic - } + AssertLint::ArithmeticOverflow(..) => fluent::mir_transform_arithmetic_overflow, + AssertLint::UnconditionalPanic(..) => fluent::mir_transform_operation_will_panic, } } } @@ -255,11 +288,11 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - diag.span_label(self.yield_sp, crate::fluent_generated::_subdiag::label); + diag.span_label(self.yield_sp, fluent::_subdiag::label); if let Some(reason) = self.reason { diag.subdiagnostic(reason); } - diag.span_help(self.src_sp, crate::fluent_generated::_subdiag::help); + diag.span_help(self.src_sp, fluent::_subdiag::help); diag.set_arg("pre", self.pre); diag.set_arg("def_path", self.tcx.def_path_str(self.def_id)); diag.set_arg("post", self.post); @@ -267,7 +300,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { } fn msg(&self) -> rustc_errors::DiagnosticMessage { - crate::fluent_generated::mir_transform_must_not_suspend + fluent::mir_transform_must_not_suspend } } diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index a42eacbf22b42..340bb1948ebf9 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -14,7 +14,7 @@ pub struct FunctionItemReferences; impl<'tcx> MirLint<'tcx> for FunctionItemReferences { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = FunctionItemRefChecker { tcx, body }; - checker.visit_body(&body); + checker.visit_body(body); } } @@ -47,12 +47,12 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> { for inner_ty in arg_ty.walk().filter_map(|arg| arg.as_type()) { if let Some((fn_id, fn_args)) = FunctionItemRefChecker::is_fn_ref(inner_ty) { - let span = self.nth_arg_span(&args, 0); + let span = self.nth_arg_span(args, 0); self.emit_lint(fn_id, fn_args, source_info, span); } } } else { - self.check_bound_args(def_id, args_ref, &args, source_info); + self.check_bound_args(def_id, args_ref, args, source_info); } } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index dce298e92e166..1a5979ef714bd 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -88,8 +88,8 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; +use rustc_index::newtype_index; use rustc_index::IndexVec; -use rustc_macros::newtype_index; use rustc_middle::mir::interpret::GlobalAlloc; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; @@ -388,7 +388,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.ecx.copy_op(op, &field_dest, /*allow_transmute*/ false).ok()?; } self.ecx.write_discriminant(variant.unwrap_or(FIRST_VARIANT), &dest).ok()?; - self.ecx.alloc_mark_immutable(dest.ptr().provenance.unwrap()).ok()?; + self.ecx + .alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()) + .ok()?; dest.into() } else { return None; @@ -461,7 +463,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } NullaryOp(null_op, ty) => { let layout = self.ecx.layout_of(ty).ok()?; - if let NullOp::SizeOf | NullOp::AlignOf = null_op && layout.is_unsized() { + if let NullOp::SizeOf | NullOp::AlignOf = null_op + && layout.is_unsized() + { return None; } let val = match null_op { @@ -865,7 +869,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { .collect(); let fields = fields?; - if let AggregateTy::Array = ty && fields.len() > 4 { + if let AggregateTy::Array = ty + && fields.len() > 4 + { let first = fields[0]; if fields.iter().all(|&v| v == first) { let len = ty::Const::from_target_usize(self.tcx, fields.len().try_into().unwrap()); @@ -924,7 +930,8 @@ fn op_to_prop_const<'tcx>( } let pointer = mplace.ptr().into_pointer_or_addr().ok()?; - let (alloc_id, offset) = pointer.into_parts(); + let (prov, offset) = pointer.into_parts(); + let alloc_id = prov.alloc_id(); intern_const_alloc_for_constprop(ecx, alloc_id).ok()?; if matches!(ecx.tcx.global_alloc(alloc_id), GlobalAlloc::Memory(_)) { // `alloc_id` may point to a static. Codegen will choke on an `Indirect` with anything @@ -1008,8 +1015,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { // Do not try to simplify a constant, it's already in canonical shape. && !matches!(rvalue, Rvalue::Use(Operand::Constant(_))) { - if let Some(value) = self.simplify_rvalue(rvalue, location) - { + if let Some(value) = self.simplify_rvalue(rvalue, location) { if let Some(const_) = self.try_as_constant(value) { *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); } else if let Some(local) = self.try_as_local(value, location) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 793dcf0d994c3..8fa2671318430 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -32,7 +32,6 @@ struct CallSite<'tcx> { callee: Instance<'tcx>, fn_sig: ty::PolyFnSig<'tcx>, block: BasicBlock, - target: Option, source_info: SourceInfo, } @@ -281,7 +280,7 @@ impl<'tcx> Inliner<'tcx> { } let old_blocks = caller_body.basic_blocks.next_index(); - self.inline_call(caller_body, &callsite, callee_body); + self.inline_call(caller_body, callsite, callee_body); let new_blocks = old_blocks..caller_body.basic_blocks.next_index(); Ok(new_blocks) @@ -367,7 +366,7 @@ impl<'tcx> Inliner<'tcx> { ) -> Option> { // Only consider direct calls to functions let terminator = bb_data.terminator(); - if let TerminatorKind::Call { ref func, target, fn_span, .. } = terminator.kind { + if let TerminatorKind::Call { ref func, fn_span, .. } = terminator.kind { let func_ty = func.ty(caller_body, self.tcx); if let ty::FnDef(def_id, args) = *func_ty.kind() { // To resolve an instance its args have to be fully normalized. @@ -386,7 +385,7 @@ impl<'tcx> Inliner<'tcx> { let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args); let source_info = SourceInfo { span: fn_span, ..terminator.source_info }; - return Some(CallSite { callee, fn_sig, block: bb, target, source_info }); + return Some(CallSite { callee, fn_sig, block: bb, source_info }); } } @@ -541,142 +540,158 @@ impl<'tcx> Inliner<'tcx> { mut callee_body: Body<'tcx>, ) { let terminator = caller_body[callsite.block].terminator.take().unwrap(); - match terminator.kind { - TerminatorKind::Call { args, destination, unwind, .. } => { - // If the call is something like `a[*i] = f(i)`, where - // `i : &mut usize`, then just duplicating the `a[*i]` - // Place could result in two different locations if `f` - // writes to `i`. To prevent this we need to create a temporary - // borrow of the place and pass the destination as `*temp` instead. - fn dest_needs_borrow(place: Place<'_>) -> bool { - for elem in place.projection.iter() { - match elem { - ProjectionElem::Deref | ProjectionElem::Index(_) => return true, - _ => {} - } - } + let TerminatorKind::Call { args, destination, unwind, target, .. } = terminator.kind else { + bug!("unexpected terminator kind {:?}", terminator.kind); + }; + + let return_block = if let Some(block) = target { + // Prepare a new block for code that should execute when call returns. We don't use + // target block directly since it might have other predecessors. + let mut data = BasicBlockData::new(Some(Terminator { + source_info: terminator.source_info, + kind: TerminatorKind::Goto { target: block }, + })); + data.is_cleanup = caller_body[block].is_cleanup; + Some(caller_body.basic_blocks_mut().push(data)) + } else { + None + }; - false + // If the call is something like `a[*i] = f(i)`, where + // `i : &mut usize`, then just duplicating the `a[*i]` + // Place could result in two different locations if `f` + // writes to `i`. To prevent this we need to create a temporary + // borrow of the place and pass the destination as `*temp` instead. + fn dest_needs_borrow(place: Place<'_>) -> bool { + for elem in place.projection.iter() { + match elem { + ProjectionElem::Deref | ProjectionElem::Index(_) => return true, + _ => {} } + } - let dest = if dest_needs_borrow(destination) { - trace!("creating temp for return destination"); - let dest = Rvalue::Ref( - self.tcx.lifetimes.re_erased, - BorrowKind::Mut { kind: MutBorrowKind::Default }, - destination, - ); - let dest_ty = dest.ty(caller_body, self.tcx); - let temp = Place::from(self.new_call_temp(caller_body, &callsite, dest_ty)); - caller_body[callsite.block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::Assign(Box::new((temp, dest))), - }); - self.tcx.mk_place_deref(temp) - } else { - destination - }; + false + } - // Always create a local to hold the destination, as `RETURN_PLACE` may appear - // where a full `Place` is not allowed. - let (remap_destination, destination_local) = if let Some(d) = dest.as_local() { - (false, d) - } else { - ( - true, - self.new_call_temp( - caller_body, - &callsite, - destination.ty(caller_body, self.tcx).ty, - ), - ) - }; + let dest = if dest_needs_borrow(destination) { + trace!("creating temp for return destination"); + let dest = Rvalue::Ref( + self.tcx.lifetimes.re_erased, + BorrowKind::Mut { kind: MutBorrowKind::Default }, + destination, + ); + let dest_ty = dest.ty(caller_body, self.tcx); + let temp = + Place::from(self.new_call_temp(caller_body, &callsite, dest_ty, return_block)); + caller_body[callsite.block].statements.push(Statement { + source_info: callsite.source_info, + kind: StatementKind::Assign(Box::new((temp, dest))), + }); + self.tcx.mk_place_deref(temp) + } else { + destination + }; - // Copy the arguments if needed. - let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body); - - let mut integrator = Integrator { - args: &args, - new_locals: Local::new(caller_body.local_decls.len()).., - new_scopes: SourceScope::new(caller_body.source_scopes.len()).., - new_blocks: BasicBlock::new(caller_body.basic_blocks.len()).., - destination: destination_local, - callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(), - callsite, - cleanup_block: unwind, - in_cleanup_block: false, - tcx: self.tcx, - always_live_locals: BitSet::new_filled(callee_body.local_decls.len()), - }; + // Always create a local to hold the destination, as `RETURN_PLACE` may appear + // where a full `Place` is not allowed. + let (remap_destination, destination_local) = if let Some(d) = dest.as_local() { + (false, d) + } else { + ( + true, + self.new_call_temp( + caller_body, + &callsite, + destination.ty(caller_body, self.tcx).ty, + return_block, + ), + ) + }; - // Map all `Local`s, `SourceScope`s and `BasicBlock`s to new ones - // (or existing ones, in a few special cases) in the caller. - integrator.visit_body(&mut callee_body); - - // If there are any locals without storage markers, give them storage only for the - // duration of the call. - for local in callee_body.vars_and_temps_iter() { - if integrator.always_live_locals.contains(local) { - let new_local = integrator.map_local(local); - caller_body[callsite.block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::StorageLive(new_local), - }); - } - } - if let Some(block) = callsite.target { - // To avoid repeated O(n) insert, push any new statements to the end and rotate - // the slice once. - let mut n = 0; - if remap_destination { - caller_body[block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::Assign(Box::new(( - dest, - Rvalue::Use(Operand::Move(destination_local.into())), - ))), - }); - n += 1; - } - for local in callee_body.vars_and_temps_iter().rev() { - if integrator.always_live_locals.contains(local) { - let new_local = integrator.map_local(local); - caller_body[block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::StorageDead(new_local), - }); - n += 1; - } - } - caller_body[block].statements.rotate_right(n); - } + // Copy the arguments if needed. + let args: Vec<_> = + self.make_call_args(args, &callsite, caller_body, &callee_body, return_block); + + let mut integrator = Integrator { + args: &args, + new_locals: Local::new(caller_body.local_decls.len()).., + new_scopes: SourceScope::new(caller_body.source_scopes.len()).., + new_blocks: BasicBlock::new(caller_body.basic_blocks.len()).., + destination: destination_local, + callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(), + callsite, + cleanup_block: unwind, + in_cleanup_block: false, + return_block, + tcx: self.tcx, + always_live_locals: BitSet::new_filled(callee_body.local_decls.len()), + }; - // Insert all of the (mapped) parts of the callee body into the caller. - caller_body.local_decls.extend(callee_body.drain_vars_and_temps()); - caller_body.source_scopes.extend(&mut callee_body.source_scopes.drain(..)); - caller_body.var_debug_info.append(&mut callee_body.var_debug_info); - caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..)); + // Map all `Local`s, `SourceScope`s and `BasicBlock`s to new ones + // (or existing ones, in a few special cases) in the caller. + integrator.visit_body(&mut callee_body); - caller_body[callsite.block].terminator = Some(Terminator { + // If there are any locals without storage markers, give them storage only for the + // duration of the call. + for local in callee_body.vars_and_temps_iter() { + if integrator.always_live_locals.contains(local) { + let new_local = integrator.map_local(local); + caller_body[callsite.block].statements.push(Statement { source_info: callsite.source_info, - kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) }, + kind: StatementKind::StorageLive(new_local), }); - - // Copy only unevaluated constants from the callee_body into the caller_body. - // Although we are only pushing `ConstKind::Unevaluated` consts to - // `required_consts`, here we may not only have `ConstKind::Unevaluated` - // because we are calling `instantiate_and_normalize_erasing_regions`. - caller_body.required_consts.extend( - callee_body.required_consts.iter().copied().filter(|&ct| match ct.const_ { - Const::Ty(_) => { - bug!("should never encounter ty::UnevaluatedConst in `required_consts`") - } - Const::Val(..) | Const::Unevaluated(..) => true, - }), - ); } - kind => bug!("unexpected terminator kind {:?}", kind), } + if let Some(block) = return_block { + // To avoid repeated O(n) insert, push any new statements to the end and rotate + // the slice once. + let mut n = 0; + if remap_destination { + caller_body[block].statements.push(Statement { + source_info: callsite.source_info, + kind: StatementKind::Assign(Box::new(( + dest, + Rvalue::Use(Operand::Move(destination_local.into())), + ))), + }); + n += 1; + } + for local in callee_body.vars_and_temps_iter().rev() { + if integrator.always_live_locals.contains(local) { + let new_local = integrator.map_local(local); + caller_body[block].statements.push(Statement { + source_info: callsite.source_info, + kind: StatementKind::StorageDead(new_local), + }); + n += 1; + } + } + caller_body[block].statements.rotate_right(n); + } + + // Insert all of the (mapped) parts of the callee body into the caller. + caller_body.local_decls.extend(callee_body.drain_vars_and_temps()); + caller_body.source_scopes.extend(&mut callee_body.source_scopes.drain(..)); + caller_body.var_debug_info.append(&mut callee_body.var_debug_info); + caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..)); + + caller_body[callsite.block].terminator = Some(Terminator { + source_info: callsite.source_info, + kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) }, + }); + + // Copy only unevaluated constants from the callee_body into the caller_body. + // Although we are only pushing `ConstKind::Unevaluated` consts to + // `required_consts`, here we may not only have `ConstKind::Unevaluated` + // because we are calling `instantiate_and_normalize_erasing_regions`. + caller_body.required_consts.extend(callee_body.required_consts.iter().copied().filter( + |&ct| match ct.const_ { + Const::Ty(_) => { + bug!("should never encounter ty::UnevaluatedConst in `required_consts`") + } + Const::Val(..) | Const::Unevaluated(..) => true, + }, + )); } fn make_call_args( @@ -685,6 +700,7 @@ impl<'tcx> Inliner<'tcx> { callsite: &CallSite<'tcx>, caller_body: &mut Body<'tcx>, callee_body: &Body<'tcx>, + return_block: Option, ) -> Vec { let tcx = self.tcx; @@ -713,8 +729,18 @@ impl<'tcx> Inliner<'tcx> { // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`. if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() { let mut args = args.into_iter(); - let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body); - let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body); + let self_ = self.create_temp_if_necessary( + args.next().unwrap(), + callsite, + caller_body, + return_block, + ); + let tuple = self.create_temp_if_necessary( + args.next().unwrap(), + callsite, + caller_body, + return_block, + ); assert!(args.next().is_none()); let tuple = Place::from(tuple); @@ -731,13 +757,13 @@ impl<'tcx> Inliner<'tcx> { let tuple_field = Operand::Move(tcx.mk_place_field(tuple, FieldIdx::new(i), ty)); // Spill to a local to make e.g., `tmp0`. - self.create_temp_if_necessary(tuple_field, callsite, caller_body) + self.create_temp_if_necessary(tuple_field, callsite, caller_body, return_block) }); closure_ref_arg.chain(tuple_tmp_args).collect() } else { args.into_iter() - .map(|a| self.create_temp_if_necessary(a, callsite, caller_body)) + .map(|a| self.create_temp_if_necessary(a, callsite, caller_body, return_block)) .collect() } } @@ -749,6 +775,7 @@ impl<'tcx> Inliner<'tcx> { arg: Operand<'tcx>, callsite: &CallSite<'tcx>, caller_body: &mut Body<'tcx>, + return_block: Option, ) -> Local { // Reuse the operand if it is a moved temporary. if let Operand::Move(place) = &arg @@ -761,7 +788,7 @@ impl<'tcx> Inliner<'tcx> { // Otherwise, create a temporary for the argument. trace!("creating temp for argument {:?}", arg); let arg_ty = arg.ty(caller_body, self.tcx); - let local = self.new_call_temp(caller_body, callsite, arg_ty); + let local = self.new_call_temp(caller_body, callsite, arg_ty, return_block); caller_body[callsite.block].statements.push(Statement { source_info: callsite.source_info, kind: StatementKind::Assign(Box::new((Place::from(local), Rvalue::Use(arg)))), @@ -775,6 +802,7 @@ impl<'tcx> Inliner<'tcx> { caller_body: &mut Body<'tcx>, callsite: &CallSite<'tcx>, ty: Ty<'tcx>, + return_block: Option, ) -> Local { let local = caller_body.local_decls.push(LocalDecl::new(ty, callsite.source_info.span)); @@ -783,7 +811,7 @@ impl<'tcx> Inliner<'tcx> { kind: StatementKind::StorageLive(local), }); - if let Some(block) = callsite.target { + if let Some(block) = return_block { caller_body[block].statements.insert( 0, Statement { @@ -814,6 +842,7 @@ struct Integrator<'a, 'tcx> { callsite: &'a CallSite<'tcx>, cleanup_block: UnwindAction, in_cleanup_block: bool, + return_block: Option, tcx: TyCtxt<'tcx>, always_live_locals: BitSet, } @@ -957,7 +986,7 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { *unwind = self.map_unwind(*unwind); } TerminatorKind::Return => { - terminator.kind = if let Some(tgt) = self.callsite.target { + terminator.kind = if let Some(tgt) = self.return_block { TerminatorKind::Goto { target: tgt } } else { TerminatorKind::Unreachable diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index fbcd6e75ad4f1..7a844b01707d1 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -35,12 +35,9 @@ impl<'tcx> MirPass<'tcx> for InstSimplify { } } - ctx.simplify_primitive_clone( - &mut block.terminator.as_mut().unwrap(), - &mut block.statements, - ); + ctx.simplify_primitive_clone(block.terminator.as_mut().unwrap(), &mut block.statements); ctx.simplify_intrinsic_assert( - &mut block.terminator.as_mut().unwrap(), + block.terminator.as_mut().unwrap(), &mut block.statements, ); simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 7b918be447413..5754dd08164e6 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -95,7 +95,7 @@ impl<'tcx> MirPass<'tcx> for JumpThreading { let cost = CostChecker::new(tcx, param_env, None, body); - let mut state = State::new(ConditionSet::default(), &finder.map); + let mut state = State::new(ConditionSet::default(), finder.map); let conds = if let Some((value, then, else_)) = targets.as_static_if() { let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { @@ -112,7 +112,7 @@ impl<'tcx> MirPass<'tcx> for JumpThreading { })) }; let conds = ConditionSet(conds); - state.insert_value_idx(discr, conds, &finder.map); + state.insert_value_idx(discr, conds, finder.map); finder.find_opportunity(bb, state, cost, 0); } @@ -247,7 +247,9 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { let last_non_rec = self.opportunities.len(); let predecessors = &self.body.basic_blocks.predecessors()[bb]; - if let &[pred] = &predecessors[..] && bb != START_BLOCK { + if let &[pred] = &predecessors[..] + && bb != START_BLOCK + { let term = self.body.basic_blocks[pred].terminator(); match term.kind { TerminatorKind::SwitchInt { ref discr, ref targets } => { @@ -419,8 +421,10 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // Do not support unions. AggregateKind::Adt(.., Some(_)) => return None, AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { - if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant) - && let Some(discr_value) = discriminant_for_variant(agg_ty, *variant_index) + if let Some(discr_target) = + self.map.apply(lhs, TrackElem::Discriminant) + && let Some(discr_value) = + discriminant_for_variant(agg_ty, *variant_index) { self.process_operand(bb, discr_target, &discr_value, state); } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index bf5f0ca7cbd23..89e897191e852 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -118,10 +118,7 @@ use rustc_const_eval::transform::promote_consts; use rustc_const_eval::transform::validate; use rustc_mir_dataflow::rustc_peek; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { check_unsafety::provide(providers); @@ -269,7 +266,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { let body = &tcx.mir_const(def).borrow(); if body.return_ty().references_error() { - tcx.sess.delay_span_bug(body.span, "mir_const_qualif: MIR had errors"); + tcx.sess.span_delayed_bug(body.span, "mir_const_qualif: MIR had errors"); return Default::default(); } @@ -398,7 +395,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { /// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't /// end up missing the source MIR due to stealing happening. fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { - if let DefKind::Coroutine = tcx.def_kind(def) { + if tcx.is_coroutine(def.to_def_id()) { tcx.ensure_with_value().mir_coroutine_witnesses(def); } let mir_borrowck = tcx.mir_borrowck(def); @@ -481,14 +478,14 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' assert!(body.phase == MirPhase::Analysis(AnalysisPhase::PostCleanup)); // Do a little drop elaboration before const-checking if `const_precise_live_drops` is enabled. - if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, &body)) { + if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, body)) { pm::run_passes( tcx, body, &[&remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::RemoveFalseEdges], None, ); - check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint + check_consts::post_drop_elaboration::check_live_drops(tcx, body); // FIXME: make this a MIR lint } debug!("runtime_mir_lowering({:?})", did); diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 5f3d8dfc6c42b..249e0fc633e88 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -4,7 +4,6 @@ use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::sym; -use rustc_target::abi::{FieldIdx, VariantIdx}; pub struct LowerIntrinsics; @@ -251,37 +250,6 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { }); terminator.kind = TerminatorKind::Goto { target }; } - sym::option_payload_ptr => { - if let (Some(target), Some(arg)) = (*target, args[0].place()) { - let ty::RawPtr(ty::TypeAndMut { ty: dest_ty, .. }) = - destination.ty(local_decls, tcx).ty.kind() - else { - bug!(); - }; - - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::AddressOf( - Mutability::Not, - arg.project_deeper( - &[ - PlaceElem::Deref, - PlaceElem::Downcast( - Some(sym::Some), - VariantIdx::from_u32(1), - ), - PlaceElem::Field(FieldIdx::from_u32(0), *dest_ty), - ], - tcx, - ), - ), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } - } sym::transmute | sym::transmute_unchecked => { let dst_ty = destination.ty(local_decls, tcx).ty; let Ok([arg]) = <[_; 1]>::try_from(std::mem::take(args)) else { diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index a8aba29adcd13..c4eca18ff277a 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -99,7 +99,7 @@ where ); *polarity }); - overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) + overridden.unwrap_or_else(|| pass.is_enabled(tcx.sess)) } fn run_passes_inner<'tcx>( @@ -126,7 +126,7 @@ fn run_passes_inner<'tcx>( let dump_enabled = pass.is_mir_dump_enabled(); if dump_enabled { - dump_mir_for_pass(tcx, body, &name, false); + dump_mir_for_pass(tcx, body, name, false); } if validate { validate_body(tcx, body, format!("before pass {name}")); @@ -142,7 +142,7 @@ fn run_passes_inner<'tcx>( } if dump_enabled { - dump_mir_for_pass(tcx, body, &name, true); + dump_mir_for_pass(tcx, body, name, true); } if validate { validate_body(tcx, body, format!("after pass {name}")); diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 87fee2410eca6..548879e2e39bf 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -25,7 +25,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let move_data = - MoveData::gather_moves(&body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env)); + MoveData::gather_moves(body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env)); let mdpe = MoveDataParamEnv { move_data, param_env }; let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 5aa3c3cfe4dde..9f59f9d124520 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -17,6 +17,11 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts { if tcx.type_of(body.source.def_id()).instantiate_identity().is_coroutine() { return; } + + if !tcx.consider_optimizing(|| format!("RemoveZsts - {:?}", body.source.def_id())) { + return; + } + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let local_decls = &body.local_decls; let mut replacer = Replacer { tcx, param_env, local_decls }; @@ -125,12 +130,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { if let Some(place_for_ty) = place_for_ty && let ty = place_for_ty.ty(self.local_decls, self.tcx).ty && self.known_to_be_zst(ty) - && self.tcx.consider_optimizing(|| { - format!( - "RemoveZsts - Place: {:?} SourceInfo: {:?}", - place_for_ty, statement.source_info - ) - }) { statement.make_nop(); } else { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 4ae5ea4c8d68f..fba73d5195b76 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -74,11 +74,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); debug!("make_shim({:?}) = {:?}", instance, body); - // Run empty passes to mark phase change and perform validation. pm::run_passes( tcx, &mut body, - &[], + &[ + &abort_unwinding_calls::AbortUnwindingCalls, + &add_call_guards::CriticalCallEdges, + ], Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); @@ -111,8 +113,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' &deref_separator::Derefer, &remove_noop_landing_pads::RemoveNoopLandingPads, &simplify::SimplifyCfg::MakeShim, - &add_call_guards::CriticalCallEdges, &abort_unwinding_calls::AbortUnwindingCalls, + &add_call_guards::CriticalCallEdges, ], Some(MirPhase::Runtime(RuntimePhase::Optimized)), ); @@ -179,7 +181,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) GenericArgs::identity_for_item(tcx, def_id) }; let sig = tcx.fn_sig(def_id).instantiate(tcx, args); - let sig = tcx.erase_late_bound_regions(sig); + let sig = tcx.instantiate_bound_regions_with_erased(sig); let span = tcx.def_span(def_id); let source_info = SourceInfo::outermost(span); @@ -416,7 +418,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { // otherwise going to be TySelf and we can't index // or access fields of a Place of type TySelf. let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]); - let sig = tcx.erase_late_bound_regions(sig); + let sig = tcx.instantiate_bound_regions_with_erased(sig); let span = tcx.def_span(def_id); CloneShimBuilder { @@ -654,7 +656,7 @@ fn build_call_shim<'tcx>( // to substitute into the signature of the shim. It is not necessary for users of this // MIR body to perform further substitutions (see `InstanceDef::has_polymorphic_mir_body`). let (sig_args, untuple_args) = if let ty::InstanceDef::FnPtrShim(_, ty) = instance { - let sig = tcx.erase_late_bound_regions(ty.fn_sig(tcx)); + let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx)); let untuple_args = sig.inputs(); @@ -668,7 +670,7 @@ fn build_call_shim<'tcx>( let def_id = instance.def_id(); let sig = tcx.fn_sig(def_id); - let sig = sig.map_bound(|sig| tcx.erase_late_bound_regions(sig)); + let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig)); assert_eq!(sig_args.is_some(), !instance.has_polymorphic_mir_body()); let mut sig = if let Some(sig_args) = sig_args { diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 0a1c011147ae0..97d398fe5c910 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -74,7 +74,7 @@ pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { impl<'tcx> MirPass<'tcx> for SimplifyCfg { fn name(&self) -> &'static str { - &self.name() + self.name() } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 427cc1e192413..a4ca2b91e829b 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; -use rustc_target::abi::{FieldIdx, ReprFlags, FIRST_VARIANT}; +use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; pub struct ScalarReplacementOfAggregates; @@ -66,7 +66,7 @@ fn escaping_locals<'tcx>( return true; } if let ty::Adt(def, _args) = ty.kind() { - if def.repr().flags.contains(ReprFlags::IS_SIMD) { + if def.repr().simd() { // Exclude #[repr(simd)] types so that they are not de-optimized into an array return true; } @@ -167,7 +167,7 @@ impl<'tcx> ReplacementMap<'tcx> { }; let fields = self.fragments[place.local].as_ref()?; let (_, new_local) = fields[f]?; - Some(Place { local: new_local, projection: tcx.mk_place_elems(&rest) }) + Some(Place { local: new_local, projection: tcx.mk_place_elems(rest) }) } fn place_fragments( diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 8dc7b60c4e53d..3a6e1ef348831 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -40,7 +40,8 @@ impl SsaLocals { let dominators = body.basic_blocks.dominators(); let direct_uses = IndexVec::from_elem(0, &body.local_decls); - let mut visitor = SsaVisitor { assignments, assignment_order, dominators, direct_uses }; + let mut visitor = + SsaVisitor { body, assignments, assignment_order, dominators, direct_uses }; for local in body.args_iter() { visitor.assignments[local] = Set1::One(DefLocation::Argument); @@ -110,7 +111,7 @@ impl SsaLocals { body: &'a Body<'tcx>, ) -> impl Iterator, Location)> + 'a { self.assignment_order.iter().filter_map(|&local| { - if let Set1::One(DefLocation::Body(loc)) = self.assignments[local] { + if let Set1::One(DefLocation::Assignment(loc)) = self.assignments[local] { let stmt = body.stmt_at(loc).left()?; // `loc` must point to a direct assignment to `local`. let Some((target, rvalue)) = stmt.kind.as_assign() else { bug!() }; @@ -134,21 +135,21 @@ impl SsaLocals { AssignedValue::Arg, Location { block: START_BLOCK, statement_index: 0 }, ), - Set1::One(DefLocation::Body(loc)) => { + Set1::One(DefLocation::Assignment(loc)) => { let bb = &mut basic_blocks[loc.block]; - let value = if loc.statement_index < bb.statements.len() { - // `loc` must point to a direct assignment to `local`. - let stmt = &mut bb.statements[loc.statement_index]; - let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { - bug!() - }; - assert_eq!(target.as_local(), Some(local)); - AssignedValue::Rvalue(rvalue) - } else { - let term = bb.terminator_mut(); - AssignedValue::Terminator(&mut term.kind) + // `loc` must point to a direct assignment to `local`. + let stmt = &mut bb.statements[loc.statement_index]; + let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { + bug!() }; - f(local, value, loc) + assert_eq!(target.as_local(), Some(local)); + f(local, AssignedValue::Rvalue(rvalue), loc) + } + Set1::One(DefLocation::CallReturn { call, .. }) => { + let bb = &mut basic_blocks[call]; + let loc = Location { block: call, statement_index: bb.statements.len() }; + let term = bb.terminator_mut(); + f(local, AssignedValue::Terminator(&mut term.kind), loc) } _ => {} } @@ -201,14 +202,15 @@ impl SsaLocals { } } -struct SsaVisitor<'a> { +struct SsaVisitor<'tcx, 'a> { + body: &'a Body<'tcx>, dominators: &'a Dominators, assignments: IndexVec>, assignment_order: Vec, direct_uses: IndexVec, } -impl SsaVisitor<'_> { +impl SsaVisitor<'_, '_> { fn check_dominates(&mut self, local: Local, loc: Location) { let set = &mut self.assignments[local]; let assign_dominates = match *set { @@ -224,7 +226,7 @@ impl SsaVisitor<'_> { } } -impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { +impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> { fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) { match ctxt { PlaceContext::MutatingUse(MutatingUseContext::Projection) @@ -234,7 +236,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { // so we have to remove them too. PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::AddressOf, ) | PlaceContext::MutatingUse(_) => { @@ -250,9 +252,18 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, loc: Location) { let location = match ctxt { - PlaceContext::MutatingUse( - MutatingUseContext::Store | MutatingUseContext::Call | MutatingUseContext::Yield, - ) => Some(DefLocation::Body(loc)), + PlaceContext::MutatingUse(MutatingUseContext::Store) => { + Some(DefLocation::Assignment(loc)) + } + PlaceContext::MutatingUse(MutatingUseContext::Call) => { + let call = loc.block; + let TerminatorKind::Call { target, .. } = + self.body.basic_blocks[call].terminator().kind + else { + bug!() + }; + Some(DefLocation::CallReturn { call, target }) + } _ => None, }; if let Some(location) = location @@ -359,7 +370,7 @@ impl StorageLiveLocals { for (statement_index, statement) in bbdata.statements.iter().enumerate() { if let StatementKind::StorageLive(local) = statement.kind { storage_live[local] - .insert(DefLocation::Body(Location { block, statement_index })); + .insert(DefLocation::Assignment(Location { block, statement_index })); } } } diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index 98f67e18a8d0e..e68d37f4c701e 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -86,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { continue; } - let Some(discriminant_ty) = get_switched_on_type(&bb_data, tcx, body) else { continue }; + let Some(discriminant_ty) = get_switched_on_type(bb_data, tcx, body) else { continue }; let layout = tcx.layout_of( tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty), diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 65bdcf1076225..71b3754fac870 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -385,8 +385,8 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; if let Ok(alloc) = tcx.eval_static_initializer(def_id) { - for &id in alloc.inner().provenance().ptrs().values() { - collect_alloc(tcx, id, &mut used_items); + for &prov in alloc.inner().provenance().ptrs().values() { + collect_alloc(tcx, prov.alloc_id(), &mut used_items); } } @@ -740,7 +740,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { ) => { let fn_ty = operand.ty(self.body, self.tcx); let fn_ty = self.monomorphize(fn_ty); - visit_fn_use(self.tcx, fn_ty, false, span, &mut self.output); + visit_fn_use(self.tcx, fn_ty, false, span, self.output); } mir::Rvalue::Cast( mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)), @@ -816,7 +816,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let callee_ty = func.ty(self.body, tcx); let callee_ty = self.monomorphize(callee_ty); self.check_fn_args_move_size(callee_ty, args, location); - visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output) + visit_fn_use(self.tcx, callee_ty, true, source, self.output) } mir::TerminatorKind::Drop { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; @@ -828,7 +828,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { match *op { mir::InlineAsmOperand::SymFn { ref value } => { let fn_ty = self.monomorphize(value.const_.ty()); - visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output); + visit_fn_use(self.tcx, fn_ty, false, source, self.output); } mir::InlineAsmOperand::SymStatic { def_id } => { let instance = Instance::mono(self.tcx, def_id); @@ -844,6 +844,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { mir::TerminatorKind::Assert { ref msg, .. } => { let lang_item = match &**msg { mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck, + mir::AssertKind::MisalignedPointerDereference { .. } => { + LangItem::PanicMisalignedPointerDereference + } _ => LangItem::Panic, }; push_mono_lang_item(self, lang_item); @@ -1118,7 +1121,7 @@ fn create_mono_items_for_vtable_methods<'tcx>( ) { assert!(!trait_ty.has_escaping_bound_vars() && !impl_ty.has_escaping_bound_vars()); - if let ty::Dynamic(ref trait_ty, ..) = trait_ty.kind() { + if let ty::Dynamic(trait_ty, ..) = trait_ty.kind() { if let Some(principal) = trait_ty.principal() { let poly_trait_ref = principal.with_self_ty(tcx, impl_ty); assert!(!poly_trait_ref.has_escaping_bound_vars()); @@ -1191,7 +1194,7 @@ impl<'v> RootCollector<'_, 'v> { // but even just declaring them must collect the items they refer to if let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id()) { - collect_const_value(self.tcx, val, &mut self.output); + collect_const_value(self.tcx, val, self.output); } } DefKind::Impl { .. } => { @@ -1363,9 +1366,9 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt } GlobalAlloc::Memory(alloc) => { trace!("collecting {:?} with {:#?}", alloc_id, alloc); - for &inner in alloc.inner().provenance().ptrs().values() { + for &prov in alloc.inner().provenance().ptrs().values() { rustc_data_structures::stack::ensure_sufficient_stack(|| { - collect_alloc(tcx, inner, output); + collect_alloc(tcx, prov.alloc_id(), output); }); } } @@ -1422,14 +1425,14 @@ fn collect_used_items<'tcx>( // and abort compilation if any of them errors. MirUsedCollector { tcx, - body: &body, + body: body, output, instance, move_size_spans: vec![], visiting_call_terminator: false, skip_move_check_fns: None, } - .visit_body(&body); + .visit_body(body); } #[instrument(skip(tcx, output), level = "debug")] @@ -1440,12 +1443,12 @@ fn collect_const_value<'tcx>( ) { match value { mir::ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => { - collect_alloc(tcx, ptr.provenance, output) + collect_alloc(tcx, ptr.provenance.alloc_id(), output) } mir::ConstValue::Indirect { alloc_id, .. } => collect_alloc(tcx, alloc_id, output), mir::ConstValue::Slice { data, meta: _ } => { - for &id in data.inner().provenance().ptrs().values() { - collect_alloc(tcx, id, output); + for &prov in data.inner().provenance().ptrs().values() { + collect_alloc(tcx, prov.alloc_id(), output); } } _ => {} diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 5f05020acae91..2f5f2d15cd456 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -10,8 +10,6 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_hir::lang_items::LangItem; use rustc_middle::query::{Providers, TyCtxtAt}; use rustc_middle::traits; @@ -24,7 +22,7 @@ mod partitioning; mod polymorphize; mod util; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxtAt<'tcx>, diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 4009e28924068..c2b307910e42b 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -436,12 +436,12 @@ fn merge_codegen_units<'tcx>( for cgu in codegen_units.iter_mut() { if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) { if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names { - cgu.set_name(Symbol::intern(&new_cgu_name)); + cgu.set_name(Symbol::intern(new_cgu_name)); } else { // If we don't require CGU names to be human-readable, // we use a fixed length hash of the composite CGU name // instead. - let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name); + let new_cgu_name = CodegenUnit::mangle_name(new_cgu_name); cgu.set_name(Symbol::intern(&new_cgu_name)); } } @@ -1140,7 +1140,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co // Output monomorphization stats per def_id if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats { if let Err(err) = - dump_mono_items_stats(tcx, &codegen_units, path, tcx.crate_name(LOCAL_CRATE)) + dump_mono_items_stats(tcx, codegen_units, path, tcx.crate_name(LOCAL_CRATE)) { tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() }); } diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index a3b35eab46581..91abbb216d662 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -131,7 +131,7 @@ fn mark_used_by_default_parameters<'tcx>( unused_parameters: &mut UnusedGenericParams, ) { match tcx.def_kind(def_id) { - DefKind::Closure | DefKind::Coroutine => { + DefKind::Closure => { for param in &generics.params { debug!(?param, "(closure/gen)"); unused_parameters.mark_used(param.index); @@ -248,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { if local == Local::from_usize(1) { let def_kind = self.tcx.def_kind(self.def_id); - if matches!(def_kind, DefKind::Closure | DefKind::Coroutine) { + if matches!(def_kind, DefKind::Closure) { // Skip visiting the closure/coroutine that is currently being processed. This only // happens because the first argument to the closure is a reference to itself and // that will call `visit_args`, resulting in each generic parameter captured being diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index e51b672205c2b..083e26651c13a 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -23,6 +23,8 @@ parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or late parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015 .label = to use `async fn`, switch to Rust 2018 or later +parse_async_gen_fn = `async gen` functions are not supported + parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 2018 or later parse_async_move_order_incorrect = the order of `move` and `async` is incorrect @@ -270,6 +272,9 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet *[false] a } `for` parameter list +parse_fn_trait_missing_paren = `Fn` bounds require arguments in parentheses + .add_paren = add the missing parentheses + parse_forgot_paren = perhaps you forgot parentheses? parse_found_expr_would_be_stmt = expected expression, found `{$token}` @@ -453,8 +458,6 @@ parse_macro_expands_to_adt_field = macros cannot expand to {$adt_ty} fields parse_macro_expands_to_enum_variant = macros cannot expand to enum variants -parse_macro_expands_to_match_arm = macros cannot expand to match arms - parse_macro_invocation_visibility = can't qualify macro invocation with `pub` .suggestion = remove the visibility .help = try adjusting the macro to put `{$vis}` inside the invocation @@ -489,9 +492,13 @@ parse_match_arm_body_without_braces = `match` arm body without braces } with a body .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression +parse_maybe_comparison = you might have meant to compare for equality + parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn` .suggestion = replace `fn` with `impl` here +parse_maybe_missing_let = you might have meant to continue the let-chain + parse_maybe_recover_from_bad_qpath_stage_2 = missing angle brackets in associated item path .suggestion = types that don't start with an identifier need to be surrounded with angle brackets in qualified paths @@ -718,6 +725,9 @@ parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses parse_switch_mut_let_order = switch the order of `mut` and `let` +parse_switch_ref_box_order = switch the order of `ref` and `box` + .suggestion = swap them + parse_ternary_operator = Rust has no ternary operator .help = use an `if-else` expression instead @@ -736,6 +746,9 @@ parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto` parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe` +parse_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before + .suggestion = move `{$kw}` before the `for<...>` + parse_type_ascription_removed = if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 @@ -764,6 +777,9 @@ parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in patter parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head .suggestion = remove parentheses in `for` loop +parse_unexpected_parentheses_in_match_arm_pattern = unexpected parentheses surrounding `match` arm pattern + .suggestion = remove parentheses surrounding the pattern + parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters .note = you cannot use `Self` as a generic parameter because it is reserved for associated items diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 20b4292701e39..45f950db5c309 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; -use rustc_errors::{AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic}; +use rustc_errors::{AddToDiagnostic, Applicability, ErrorGuaranteed, IntoDiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; @@ -137,6 +137,14 @@ pub(crate) enum InvalidVariableDeclarationSub { UseLetNotVar(#[primary_span] Span), } +#[derive(Diagnostic)] +#[diag(parse_switch_ref_box_order)] +pub(crate) struct SwitchRefBoxOrder { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "box ref")] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_invalid_comparison_operator)] pub(crate) struct InvalidComparisonOperator { @@ -407,6 +415,32 @@ pub(crate) struct ExpectedExpressionFoundLet { pub span: Span, #[subdiagnostic] pub reason: ForbiddenLetReason, + #[subdiagnostic] + pub missing_let: Option, + #[subdiagnostic] + pub comparison: Option, +} + +#[derive(Subdiagnostic, Clone, Copy)] +#[multipart_suggestion( + parse_maybe_missing_let, + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct MaybeMissingLet { + #[suggestion_part(code = "let ")] + pub span: Span, +} + +#[derive(Subdiagnostic, Clone, Copy)] +#[multipart_suggestion( + parse_maybe_comparison, + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct MaybeComparison { + #[suggestion_part(code = "=")] + pub span: Span, } #[derive(Diagnostic)] @@ -528,6 +562,13 @@ pub(crate) struct GenFn { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parse_async_gen_fn)] +pub(crate) struct AsyncGenFn { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_comma_after_base_struct)] #[note] @@ -1004,12 +1045,12 @@ pub(crate) struct ExpectedIdentifier { pub help_cannot_start_number: Option, } -impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier { +impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier { #[track_caller] fn into_diagnostic( self, handler: &'a rustc_errors::Handler, - ) -> rustc_errors::DiagnosticBuilder<'a, G> { + ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { let token_descr = TokenDescription::from_token(&self.token); let mut diag = handler.struct_diagnostic(match token_descr { @@ -1061,12 +1102,12 @@ pub(crate) struct ExpectedSemi { pub sugg: ExpectedSemiSugg, } -impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi { +impl<'a> IntoDiagnostic<'a> for ExpectedSemi { #[track_caller] fn into_diagnostic( self, handler: &'a rustc_errors::Handler, - ) -> rustc_errors::DiagnosticBuilder<'a, G> { + ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { let token_descr = TokenDescription::from_token(&self.token); let mut diag = handler.struct_diagnostic(match token_descr { @@ -1241,12 +1282,28 @@ pub(crate) struct ParenthesesInForHead { #[derive(Subdiagnostic)] #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] pub(crate) struct ParenthesesInForHeadSugg { - #[suggestion_part(code = "{left_snippet}")] + #[suggestion_part(code = " ")] pub left: Span, - pub left_snippet: String, - #[suggestion_part(code = "{right_snippet}")] + #[suggestion_part(code = " ")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_unexpected_parentheses_in_match_arm_pattern)] +pub(crate) struct ParenthesesInMatchPat { + #[primary_span] + pub span: Vec, + #[subdiagnostic] + pub sugg: ParenthesesInMatchPatSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct ParenthesesInMatchPatSugg { + #[suggestion_part(code = "")] + pub left: Span, + #[suggestion_part(code = "")] pub right: Span, - pub right_snippet: String, } #[derive(Diagnostic)] @@ -1378,6 +1435,34 @@ pub(crate) struct FnPtrWithGenericsSugg { pub for_param_list_exists: bool, } +pub(crate) struct FnTraitMissingParen { + pub span: Span, + pub machine_applicable: bool, +} + +impl AddToDiagnostic for FnTraitMissingParen { + fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + where + F: Fn( + &mut rustc_errors::Diagnostic, + rustc_errors::SubdiagnosticMessage, + ) -> rustc_errors::SubdiagnosticMessage, + { + diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); + let applicability = if self.machine_applicable { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + diag.span_suggestion_short( + self.span.shrink_to_hi(), + crate::fluent_generated::parse_add_paren, + "()", + applicability, + ); + } +} + #[derive(Diagnostic)] #[diag(parse_unexpected_if_with_if)] pub(crate) struct UnexpectedIfWithIf( @@ -1648,7 +1733,7 @@ pub(crate) struct ExternItemCannotBeConst { #[primary_span] pub ident_span: Span, #[suggestion(code = "static ", applicability = "machine-applicable")] - pub const_span: Span, + pub const_span: Option, } #[derive(Diagnostic)] @@ -2250,9 +2335,8 @@ pub(crate) enum InvalidMutInPattern { #[note(parse_note_mut_pattern_usage)] NonIdent { #[primary_span] - #[suggestion(code = "{pat}", applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable")] span: Span, - pat: String, }, } @@ -2800,3 +2884,23 @@ pub(crate) struct GenericArgsInPatRequireTurbofishSyntax { )] pub suggest_turbofish: Span, } + +#[derive(Diagnostic)] +#[diag(parse_transpose_dyn_or_impl)] +pub(crate) struct TransposeDynOrImpl<'a> { + #[primary_span] + pub span: Span, + pub kw: &'a str, + #[subdiagnostic] + pub sugg: TransposeDynOrImplSugg<'a>, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct TransposeDynOrImplSugg<'a> { + #[suggestion_part(code = "")] + pub removal_span: Span, + #[suggestion_part(code = "{kw} ")] + pub insertion_span: Span, + pub kw: &'a str, +} diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index f2eed5c9be510..92df2da8710da 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -75,7 +75,7 @@ pub(crate) fn parse_token_trees<'a>( let mut buffer = Vec::with_capacity(1); for unmatched in unmatched_delims { - if let Some(err) = make_unclosed_delims_error(unmatched, &sess) { + if let Some(err) = make_unclosed_delims_error(unmatched, sess) { err.buffer(&mut buffer); } } @@ -223,9 +223,6 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::Literal { kind, suffix_start } => { let suffix_start = start + BytePos(suffix_start); let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); - if let token::LitKind::CStr | token::LitKind::CStrRaw(_) = kind { - self.sess.gated_spans.gate(sym::c_str_literals, self.mk_sp(start, self.pos)); - } let suffix = if suffix_start < self.pos { let string = self.str_from(suffix_start); if string == "_" { @@ -362,7 +359,7 @@ impl<'a> StringReader<'a> { if contains_text_flow_control_chars(content) { let span = self.mk_sp(start, self.pos); self.sess.buffer_lint_with_diagnostic( - &TEXT_DIRECTION_CODEPOINT_IN_COMMENT, + TEXT_DIRECTION_CODEPOINT_IN_COMMENT, span, ast::CRATE_NODE_ID, "unicode codepoint changing visible direction of text present in comment", @@ -683,7 +680,7 @@ impl<'a> StringReader<'a> { } else { // Before Rust 2021, only emit a lint for migration. self.sess.buffer_lint_with_diagnostic( - &RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, + RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, prefix_span, ast::CRATE_NODE_ID, format!("prefix `{prefix}` is unknown"), diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 31d91fe80bd61..e646f5dfd8514 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -5,7 +5,8 @@ use super::{StringReader, UnmatchedDelim}; use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast_pretty::pprust::token_to_string; -use rustc_errors::PErr; +use rustc_errors::{Applicability, PErr}; +use rustc_span::symbol::kw; pub(super) struct TokenTreesReader<'a> { string_reader: StringReader<'a>, @@ -96,7 +97,7 @@ impl<'a> TokenTreesReader<'a> { report_suspicious_mismatch_block( &mut err, &self.diag_info, - &self.string_reader.sess.source_map(), + self.string_reader.sess.source_map(), *delim, ) } @@ -116,24 +117,8 @@ impl<'a> TokenTreesReader<'a> { // We stop at any delimiter so we can try to recover if the user // uses an incorrect delimiter. let (tts, res) = self.parse_token_trees(/* is_delimited */ true); - if let Err(mut errs) = res { - // If there are unclosed delims, see if there are diff markers and if so, point them - // out instead of complaining about the unclosed delims. - let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); - let mut diff_errs = vec![]; - while parser.token != token::Eof { - if let Err(diff_err) = parser.err_diff_marker() { - diff_errs.push(diff_err); - } - parser.bump(); - } - if !diff_errs.is_empty() { - errs.iter_mut().for_each(|err| { - err.delay_as_bug(); - }); - return Err(diff_errs); - } - return Err(errs); + if let Err(errs) = res { + return Err(self.unclosed_delim_err(tts, errs)); } // Expand to cover the entire delimited token tree @@ -179,7 +164,7 @@ impl<'a> TokenTreesReader<'a> { unclosed_delimiter = Some(sp); }; for (brace, brace_span) in &self.diag_info.open_braces { - if same_indentation_level(&sm, self.token.span, *brace_span) + if same_indentation_level(sm, self.token.span, *brace_span) && brace == &close_delim { // high likelihood of these two corresponding @@ -220,6 +205,62 @@ impl<'a> TokenTreesReader<'a> { Ok(TokenTree::Delimited(delim_span, open_delim, tts)) } + fn unclosed_delim_err(&mut self, tts: TokenStream, mut errs: Vec>) -> Vec> { + // If there are unclosed delims, see if there are diff markers and if so, point them + // out instead of complaining about the unclosed delims. + let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); + let mut diff_errs = vec![]; + // Suggest removing a `{` we think appears in an `if`/`while` condition + // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but + // we have no way of tracking this in the lexer itself, so we piggyback on the parser + let mut in_cond = false; + while parser.token != token::Eof { + if let Err(diff_err) = parser.err_diff_marker() { + diff_errs.push(diff_err); + } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) { + in_cond = true; + } else if matches!( + parser.token.kind, + token::CloseDelim(Delimiter::Brace) | token::FatArrow + ) { + // end of the `if`/`while` body, or the end of a `match` guard + in_cond = false; + } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) { + // Store the `&&` and `let` to use their spans later when creating the diagnostic + let maybe_andand = parser.look_ahead(1, |t| t.clone()); + let maybe_let = parser.look_ahead(2, |t| t.clone()); + if maybe_andand == token::OpenDelim(Delimiter::Brace) { + // This might be the beginning of the `if`/`while` body (i.e., the end of the condition) + in_cond = false; + } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) { + let mut err = parser.struct_span_err( + parser.token.span, + "found a `{` in the middle of a let-chain", + ); + err.span_suggestion( + parser.token.span, + "consider removing this brace to parse the `let` as part of the same chain", + "", + Applicability::MachineApplicable, + ); + err.span_label( + maybe_andand.span.to(maybe_let.span), + "you might have meant to continue the let-chain here", + ); + errs.push(err); + } + } + parser.bump(); + } + if !diff_errs.is_empty() { + errs.iter_mut().for_each(|err| { + err.delay_as_bug(); + }); + return diff_errs; + } + return errs; + } + fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). @@ -230,7 +271,7 @@ impl<'a> TokenTreesReader<'a> { report_suspicious_mismatch_block( &mut err, &self.diag_info, - &self.string_reader.sess.source_map(), + self.string_reader.sess.source_map(), delim, ); err.span_label(self.token.span, "unexpected closing delimiter"); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index c012a86633299..95352dbdc134f 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -20,8 +20,6 @@ use rustc_ast::{AttrItem, Attribute, MetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diagnostic, FatalError, Level, PResult}; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; @@ -37,7 +35,7 @@ pub mod validate_attr; mod errors; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 104de47b97dd1..422bb79308d29 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -56,7 +56,7 @@ impl<'a> Parser<'a> { } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { if attr_style != ast::AttrStyle::Outer { let span = self.token.span; - let mut err = self.sess.span_diagnostic.struct_span_err_with_code( + let mut err = self.diagnostic().struct_span_err_with_code( span, fluent::parse_inner_doc_comment_not_permitted, error_code!(E0753), @@ -249,7 +249,7 @@ impl<'a> Parser<'a> { /// The delimiters or `=` are still put into the resulting token stream. pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::AttrItem> { let item = match &self.token.kind { - token::Interpolated(nt) => match &**nt { + token::Interpolated(nt) => match &nt.0 { Nonterminal::NtMeta(item) => Some(item.clone().into_inner()), _ => None, }, @@ -369,7 +369,7 @@ impl<'a> Parser<'a> { /// ``` pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { let nt_meta = match &self.token.kind { - token::Interpolated(nt) => match &**nt { + token::Interpolated(nt) => match &nt.0 { token::NtMeta(e) => Some(e.clone()), _ => None, }, @@ -418,7 +418,7 @@ impl<'a> Parser<'a> { } Err(InvalidMetaItem { span: self.token.span, token: self.token.clone() } - .into_diagnostic(&self.sess.span_diagnostic)) + .into_diagnostic(self.diagnostic())) } } diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index c4e8d9006e6d8..c66a7176aab32 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -41,7 +41,7 @@ impl AttrWrapper { } pub(crate) fn take_for_recovery(self, sess: &ParseSess) -> AttrVec { - sess.span_diagnostic.delay_span_bug( + sess.span_diagnostic.span_delayed_bug( self.attrs.get(0).map(|attr| attr.span).unwrap_or(DUMMY_SP), "AttrVec is taken for recovery but no error is produced", ); @@ -266,9 +266,8 @@ impl<'a> Parser<'a> { if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&inner_attr.id) { inner_attr_replace_ranges.push(attr_range); } else { - self.sess - .span_diagnostic - .delay_span_bug(inner_attr.span, "Missing token range for attribute"); + self.diagnostic() + .span_delayed_bug(inner_attr.span, "Missing token range for attribute"); } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 2a8eb6edd23fd..5295172b25e77 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -11,24 +11,25 @@ use crate::errors::{ DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, InInTypo, IncorrectAwait, IncorrectSemicolon, - IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg, - PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, - StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, - StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, - TernaryOperator, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, - UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, + IncorrectUseOfAwait, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, + SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, + StructLiteralNeedingParens, StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, + SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, UnexpectedConstInGenericParam, + UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, + UseEqInstead, WrapType, }; - use crate::fluent_generated as fluent; use crate::parser; +use crate::parser::attr::InnerAttrPolicy; use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind}; +use rustc_ast::tokenstream::AttrTokenTree; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingAnnotation, Block, - BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind, - Path, PathSegment, QSelf, Ty, TyKind, + BlockCheckMode, Expr, ExprKind, GenericArg, Generics, HasTokens, Item, ItemKind, Param, Pat, + PatKind, Path, PathSegment, QSelf, Ty, TyKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -245,11 +246,11 @@ impl<'a> Parser<'a> { sp: S, m: impl Into, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - self.sess.span_diagnostic.struct_span_err(sp, m) + self.diagnostic().struct_span_err(sp, m) } pub fn span_bug>(&self, sp: S, m: impl Into) -> ! { - self.sess.span_diagnostic.span_bug(sp, m) + self.diagnostic().span_bug(sp, m) } pub(super) fn diagnostic(&self) -> &'a Handler { @@ -283,7 +284,7 @@ impl<'a> Parser<'a> { span: self.prev_token.span, missing_comma: None, } - .into_diagnostic(&self.sess.span_diagnostic)); + .into_diagnostic(self.diagnostic())); } let valid_follow = &[ @@ -346,7 +347,7 @@ impl<'a> Parser<'a> { suggest_remove_comma, help_cannot_start_number, }; - let mut err = err.into_diagnostic(&self.sess.span_diagnostic); + let mut err = err.into_diagnostic(self.diagnostic()); // if the token we have is a `<` // it *might* be a misplaced generic @@ -506,7 +507,9 @@ impl<'a> Parser<'a> { if expected.contains(&TokenType::Token(token::Semi)) { // If the user is trying to write a ternary expression, recover it and // return an Err to prevent a cascade of irrelevant diagnostics - if self.prev_token == token::Question && let Err(e) = self.maybe_recover_from_ternary_operator() { + if self.prev_token == token::Question + && let Err(e) = self.maybe_recover_from_ternary_operator() + { return Err(e); } @@ -670,15 +673,6 @@ impl<'a> Parser<'a> { ); } - // Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens - // there are unclosed angle brackets - if self.unmatched_angle_bracket_count > 0 - && self.token.kind == TokenKind::Eq - && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Gt))) - { - err.span_label(self.prev_token.span, "maybe try to close unmatched angle bracket"); - } - let sp = if self.token == token::Eof { // This is EOF; don't want to point at the following char, but rather the last token. self.prev_token.span @@ -720,6 +714,95 @@ impl<'a> Parser<'a> { Err(err) } + pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) { + // Missing semicolon typo error. + let span = self.prev_token.span.shrink_to_hi(); + let mut err = self.sess.create_err(ExpectedSemi { + span, + token: self.token.clone(), + unexpected_token_label: Some(self.token.span), + sugg: ExpectedSemiSugg::AddSemi(span), + }); + let attr_span = match &expr.attrs[..] { + [] => unreachable!(), + [only] => only.span, + [first, rest @ ..] => { + for attr in rest { + err.span_label(attr.span, ""); + } + first.span + } + }; + err.span_label( + attr_span, + format!( + "only `;` terminated statements or tail expressions are allowed after {}", + if expr.attrs.len() == 1 { "this attribute" } else { "these attributes" }, + ), + ); + if self.token == token::Pound + && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Bracket)) + { + // We have + // #[attr] + // expr + // #[not_attr] + // other_expr + err.span_label(span, "expected `;` here"); + err.multipart_suggestion( + "alternatively, consider surrounding the expression with a block", + vec![ + (expr.span.shrink_to_lo(), "{ ".to_string()), + (expr.span.shrink_to_hi(), " }".to_string()), + ], + Applicability::MachineApplicable, + ); + let mut snapshot = self.create_snapshot_for_diagnostic(); + if let [attr] = &expr.attrs[..] + && let ast::AttrKind::Normal(attr_kind) = &attr.kind + && let [segment] = &attr_kind.item.path.segments[..] + && segment.ident.name == sym::cfg + && let Some(args_span) = attr_kind.item.args.span() + && let Ok(next_attr) = snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None)) + && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind + && let Some(next_attr_args_span) = next_attr_kind.item.args.span() + && let [next_segment] = &next_attr_kind.item.path.segments[..] + && segment.ident.name == sym::cfg + && let Ok(next_expr) = snapshot.parse_expr() + { + // We have for sure + // #[cfg(..)] + // expr + // #[cfg(..)] + // other_expr + // So we suggest using `if cfg!(..) { expr } else if cfg!(..) { other_expr }`. + let margin = self.sess.source_map().span_to_margin(next_expr.span).unwrap_or(0); + let sugg = vec![ + (attr.span.with_hi(segment.span().hi()), "if cfg!".to_string()), + (args_span.shrink_to_hi().with_hi(attr.span.hi()), " {".to_string()), + (expr.span.shrink_to_lo(), " ".to_string()), + ( + next_attr.span.with_hi(next_segment.span().hi()), + "} else if cfg!".to_string(), + ), + ( + next_attr_args_span.shrink_to_hi().with_hi(next_attr.span.hi()), + " {".to_string(), + ), + (next_expr.span.shrink_to_lo(), " ".to_string()), + (next_expr.span.shrink_to_hi(), format!("\n{}}}", " ".repeat(margin))), + ]; + err.multipart_suggestion( + "it seems like you are trying to provide different expressions depending on \ + `cfg`, consider using `if cfg!(..)`", + sugg, + Applicability::MachineApplicable, + ); + } + } + err.emit(); + } + fn check_too_many_raw_str_terminators(&mut self, err: &mut Diagnostic) -> bool { let sm = self.sess.source_map(); match (&self.prev_token.kind, &self.token.kind) { @@ -1182,11 +1265,11 @@ impl<'a> Parser<'a> { (BinOpKind::Ge, AssocOp::GreaterEqual | AssocOp::Greater) => { let expr_to_str = |e: &Expr| { self.span_to_snippet(e.span) - .unwrap_or_else(|_| pprust::expr_to_string(&e)) + .unwrap_or_else(|_| pprust::expr_to_string(e)) }; err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::SplitComparison { span: inner_op.span.shrink_to_hi(), - middle_term: expr_to_str(&r1), + middle_term: expr_to_str(r1), }); false // Keep the current parse behavior, where the AST is `(x < y) < z`. } @@ -1327,7 +1410,7 @@ impl<'a> Parser<'a> { // Not entirely sure now, but we bubble the error up with the // suggestion. self.restore_snapshot(snapshot); - Err(err.into_diagnostic(&self.sess.span_diagnostic)) + Err(err.into_diagnostic(self.diagnostic())) } } } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind { @@ -1342,7 +1425,7 @@ impl<'a> Parser<'a> { } // Consume the fn call arguments. match self.consume_fn_args() { - Err(()) => Err(err.into_diagnostic(&self.sess.span_diagnostic)), + Err(()) => Err(err.into_diagnostic(self.diagnostic())), Ok(()) => { self.sess.emit_err(err); // FIXME: actually check that the two expressions in the binop are @@ -1368,7 +1451,7 @@ impl<'a> Parser<'a> { mk_err_expr(self, inner_op.span.to(self.prev_token.span)) } else { // These cases cause too many knock-down errors, bail out (#61329). - Err(err.into_diagnostic(&self.sess.span_diagnostic)) + Err(err.into_diagnostic(self.diagnostic())) } }; } @@ -1407,7 +1490,7 @@ impl<'a> Parser<'a> { pub(super) fn maybe_report_ambiguous_plus(&mut self, impl_dyn_multi: bool, ty: &Ty) { if impl_dyn_multi { - self.sess.emit_err(AmbiguousPlus { sum_ty: pprust::ty_to_string(&ty), span: ty.span }); + self.sess.emit_err(AmbiguousPlus { sum_ty: pprust::ty_to_string(ty), span: ty.span }); } } @@ -1840,7 +1923,7 @@ impl<'a> Parser<'a> { self.sess.emit_err(IncorrectAwait { span, sugg_span: (span, applicability), - expr: self.span_to_snippet(expr.span).unwrap_or_else(|_| pprust::expr_to_string(&expr)), + expr: self.span_to_snippet(expr.span).unwrap_or_else(|_| pprust::expr_to_string(expr)), question_mark: if is_question { "?" } else { "" }, }); @@ -1895,54 +1978,37 @@ impl<'a> Parser<'a> { } } - /// Recovers a situation like `for ( $pat in $expr )` - /// and suggest writing `for $pat in $expr` instead. - /// - /// This should be called before parsing the `$block`. - pub(super) fn recover_parens_around_for_head( + /// When trying to close a generics list and encountering code like + /// ```text + /// impl> From for Canonical {} + /// // ^ missing > here + /// ``` + /// we provide a structured suggestion on the error from `expect_gt`. + pub(super) fn expect_gt_or_maybe_suggest_closing_generics( &mut self, - pat: P, - begin_paren: Option, - ) -> P { - match (&self.token.kind, begin_paren) { - (token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => { - self.bump(); - - let sm = self.sess.source_map(); - let left = begin_par_sp; - let right = self.prev_token.span; - let left_snippet = if let Ok(snip) = sm.span_to_prev_source(left) - && !snip.ends_with(' ') - { - " ".to_string() - } else { - "".to_string() - }; - - let right_snippet = if let Ok(snip) = sm.span_to_next_source(right) - && !snip.starts_with(' ') - { - " ".to_string() - } else { - "".to_string() - }; - - self.sess.emit_err(ParenthesesInForHead { - span: vec![left, right], - // With e.g. `for (x) in y)` this would replace `(x) in y)` - // with `x) in y)` which is syntactically invalid. - // However, this is prevented before we get here. - sugg: ParenthesesInForHeadSugg { left, right, left_snippet, right_snippet }, - }); - - // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. - pat.and_then(|pat| match pat.kind { - PatKind::Paren(pat) => pat, - _ => P(pat), + params: &[ast::GenericParam], + ) -> PResult<'a, ()> { + let Err(mut err) = self.expect_gt() else { + return Ok(()); + }; + // Attempt to find places where a missing `>` might belong. + if let [.., ast::GenericParam { bounds, .. }] = params + && let Some(poly) = bounds + .iter() + .filter_map(|bound| match bound { + ast::GenericBound::Trait(poly, _) => Some(poly), + _ => None, }) - } - _ => pat, + .last() + { + err.span_suggestion_verbose( + poly.span.shrink_to_hi(), + "you might have meant to end the type parameters here", + ">", + Applicability::MaybeIncorrect, + ); } + Err(err) } pub(super) fn recover_seq_parse_error( @@ -2250,6 +2316,59 @@ impl<'a> Parser<'a> { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } err.span_label(span, "expected expression"); + + // Walk the chain of macro expansions for the current token to point at how the original + // code was interpreted. This helps the user realize when a macro argument of one type is + // later reinterpreted as a different type, like `$x:expr` being reinterpreted as `$x:pat` + // in a subsequent macro invocation (#71039). + let mut tok = self.token.clone(); + let mut labels = vec![]; + while let TokenKind::Interpolated(node) = &tok.kind { + let tokens = node.0.tokens(); + labels.push(node.clone()); + if let Some(tokens) = tokens + && let tokens = tokens.to_attr_token_stream() + && let tokens = tokens.0.deref() + && let [AttrTokenTree::Token(token, _)] = &tokens[..] + { + tok = token.clone(); + } else { + break; + } + } + let mut iter = labels.into_iter().peekable(); + let mut show_link = false; + while let Some(node) = iter.next() { + let descr = node.0.descr(); + if let Some(next) = iter.peek() { + let next_descr = next.0.descr(); + if next_descr != descr { + err.span_label(next.1, format!("this macro fragment matcher is {next_descr}")); + err.span_label(node.1, format!("this macro fragment matcher is {descr}")); + err.span_label( + next.0.use_span(), + format!("this is expected to be {next_descr}"), + ); + err.span_label( + node.0.use_span(), + format!( + "this is interpreted as {}, but it is expected to be {}", + next_descr, descr, + ), + ); + show_link = true; + } else { + err.span_label(node.1, ""); + } + } + } + if show_link { + err.note( + "when forwarding a matched fragment to another macro-by-example, matchers in the \ + second macro will see an opaque AST of the fragment type, not the underlying \ + tokens", + ); + } err } @@ -2420,8 +2539,7 @@ impl<'a> Parser<'a> { Ok(Some(GenericArg::Const(self.parse_const_arg()?))) } else { let after_kw_const = self.token.span; - self.recover_const_arg(after_kw_const, err.into_diagnostic(&self.sess.span_diagnostic)) - .map(Some) + self.recover_const_arg(after_kw_const, err.into_diagnostic(self.diagnostic())).map(Some) } } @@ -2721,7 +2839,6 @@ impl<'a> Parser<'a> { pub(crate) fn maybe_recover_unexpected_comma( &mut self, lo: Span, - is_mac_invoc: bool, rt: CommaRecoveryMode, ) -> PResult<'a, ()> { if self.token != token::Comma { @@ -2742,28 +2859,24 @@ impl<'a> Parser<'a> { let seq_span = lo.to(self.prev_token.span); let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { - if is_mac_invoc { - err.note(fluent::parse_macro_expands_to_match_arm); - } else { - err.multipart_suggestion( - format!( - "try adding parentheses to match on a tuple{}", - if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." }, - ), - vec![ - (seq_span.shrink_to_lo(), "(".to_string()), - (seq_span.shrink_to_hi(), ")".to_string()), - ], + err.multipart_suggestion( + format!( + "try adding parentheses to match on a tuple{}", + if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." }, + ), + vec![ + (seq_span.shrink_to_lo(), "(".to_string()), + (seq_span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MachineApplicable, + ); + if let CommaRecoveryMode::EitherTupleOrPipe = rt { + err.span_suggestion( + seq_span, + "...or a vertical bar to match on multiple alternatives", + seq_snippet.replace(',', " |"), Applicability::MachineApplicable, ); - if let CommaRecoveryMode::EitherTupleOrPipe = rt { - err.span_suggestion( - seq_span, - "...or a vertical bar to match on multiple alternatives", - seq_snippet.replace(',', " |"), - Applicability::MachineApplicable, - ); - } } } Err(err) @@ -2784,7 +2897,7 @@ impl<'a> Parser<'a> { span: path.span.shrink_to_hi(), between: between_span, } - .into_diagnostic(&self.sess.span_diagnostic)); + .into_diagnostic(self.diagnostic())); } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 36125e138b2d3..42257054f49d3 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength use super::diagnostics::SnapshotParser; use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; @@ -9,7 +10,7 @@ use super::{ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::mut_visit::{noop_visit_expr, MutVisitor}; -use ast::{GenBlockKind, Path, PathSegment}; +use ast::{CoroutineKind, GenBlockKind, Pat, Path, PathSegment}; use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -20,7 +21,7 @@ use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity}; use rustc_ast::visit::Visitor; use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID}; use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind}; -use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; +use rustc_ast::{Arm, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -46,7 +47,7 @@ use thin_vec::{thin_vec, ThinVec}; macro_rules! maybe_whole_expr { ($p:expr) => { if let token::Interpolated(nt) = &$p.token.kind { - match &**nt { + match &nt.0 { token::NtExpr(e) | token::NtLiteral(e) => { let e = e.clone(); $p.bump(); @@ -1060,7 +1061,7 @@ impl<'a> Parser<'a> { match &*components { // 1e2 [IdentLike(i)] => { - DestructuredFloat::Single(Symbol::intern(&i), span) + DestructuredFloat::Single(Symbol::intern(i), span) } // 1. [IdentLike(i), Punct('.')] => { @@ -1072,7 +1073,7 @@ impl<'a> Parser<'a> { } else { (span, span) }; - let symbol = Symbol::intern(&i); + let symbol = Symbol::intern(i); DestructuredFloat::TrailingDot(symbol, ident_span, dot_span) } // 1.2 | 1.2e3 @@ -1088,8 +1089,8 @@ impl<'a> Parser<'a> { } else { (span, span, span) }; - let symbol1 = Symbol::intern(&i1); - let symbol2 = Symbol::intern(&i2); + let symbol1 = Symbol::intern(i1); + let symbol2 = Symbol::intern(i2); DestructuredFloat::MiddleDot(symbol1, ident1_span, dot_span, symbol2, ident2_span) } // 1e+ | 1e- (recovered) @@ -1268,7 +1269,7 @@ impl<'a> Parser<'a> { .collect(), }, } - .into_diagnostic(&self.sess.span_diagnostic); + .into_diagnostic(self.diagnostic()); replacement_err.emit(); let old_err = mem::replace(err, replacement_err); @@ -1690,7 +1691,7 @@ impl<'a> Parser<'a> { err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>, ) -> L { if let Some(mut diag) = - self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) + self.diagnostic().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) { diag.span_suggestion_verbose( lifetime.span.shrink_to_hi(), @@ -1881,7 +1882,7 @@ impl<'a> Parser<'a> { let Some((ident, false)) = self.token.ident() else { let err = errors::ExpectedBuiltinIdent { span: self.token.span } - .into_diagnostic(&self.sess.span_diagnostic); + .into_diagnostic(self.diagnostic()); return Err(err); }; self.sess.gated_spans.gate(sym::builtin_syntax, ident.span); @@ -1892,7 +1893,7 @@ impl<'a> Parser<'a> { Ok(res) } else { let err = errors::UnknownBuiltinConstruct { span: lo.to(ident.span), name: ident.name } - .into_diagnostic(&self.sess.span_diagnostic); + .into_diagnostic(self.diagnostic()); return Err(err); }; self.expect(&TokenKind::CloseDelim(Delimiter::Parenthesis))?; @@ -1952,11 +1953,11 @@ impl<'a> Parser<'a> { mk_lit_char: impl FnOnce(Symbol, Span) -> L, ) -> PResult<'a, L> { if let token::Interpolated(nt) = &self.token.kind - && let token::NtExpr(e) | token::NtLiteral(e) = &**nt + && let token::NtExpr(e) | token::NtLiteral(e) = &nt.0 && matches!(e.kind, ExprKind::Err) { let mut err = errors::InvalidInterpolatedExpression { span: self.token.span } - .into_diagnostic(&self.sess.span_diagnostic); + .into_diagnostic(self.diagnostic()); err.downgrade_to_delayed_bug(); return Err(err); } @@ -2052,7 +2053,7 @@ impl<'a> Parser<'a> { Err(err) => { let span = token.uninterpolated_span(); self.bump(); - report_lit_error(&self.sess, err, lit, span); + report_lit_error(self.sess, err, lit, span); // Pack possible quotes and prefixes from the original literal into // the error literal's symbol so they can be pretty-printed faithfully. let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); @@ -2168,7 +2169,7 @@ impl<'a> Parser<'a> { return Err(errors::MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), - }.into_diagnostic(&self.sess.span_diagnostic)); + }.into_diagnostic(self.diagnostic())); } Ok(_) => (), Err(err) => err.cancel(), @@ -2236,7 +2237,7 @@ impl<'a> Parser<'a> { let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() { self.parse_asyncness(Case::Sensitive) } else { - Async::No + None }; let capture_clause = self.parse_capture_clause()?; @@ -2260,7 +2261,7 @@ impl<'a> Parser<'a> { } }; - if let Async::Yes { span, .. } = asyncness { + if let Some(CoroutineKind::Async { span, .. }) = asyncness { // Feature-gate `async ||` closures. self.sess.gated_spans.gate(sym::async_closure, span); } @@ -2283,7 +2284,7 @@ impl<'a> Parser<'a> { binder, capture_clause, constness, - asyncness, + coro_kind: asyncness, movability, fn_decl, body, @@ -2303,13 +2304,14 @@ impl<'a> Parser<'a> { /// Parses an optional `move` prefix to a closure-like construct. fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> { if self.eat_keyword(kw::Move) { + let move_kw_span = self.prev_token.span; // Check for `move async` and recover if self.check_keyword(kw::Async) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } - .into_diagnostic(&self.sess.span_diagnostic)) + .into_diagnostic(self.diagnostic())) } else { - Ok(CaptureBy::Value) + Ok(CaptureBy::Value { move_kw: move_kw_span }) } } else { Ok(CaptureBy::Ref) @@ -2440,10 +2442,26 @@ impl<'a> Parser<'a> { self.error_on_extra_if(&cond)?; // Parse block, which will always fail, but we can add a nice note to the error self.parse_block().map_err(|mut err| { - err.span_note( - cond_span, - "the `if` expression is missing a block after this condition", - ); + if self.prev_token == token::Semi + && self.token == token::AndAnd + && let maybe_let = self.look_ahead(1, |t| t.clone()) + && maybe_let.is_keyword(kw::Let) + { + err.span_suggestion( + self.prev_token.span, + "consider removing this semicolon to parse the `let` as part of the same chain", + "", + Applicability::MachineApplicable, + ).span_note( + self.token.span.to(maybe_let.span), + "you likely meant to continue parsing the let-chain starting here", + ); + } else { + err.span_note( + cond_span, + "the `if` expression is missing a block after this condition", + ); + } err })? } @@ -2460,7 +2478,7 @@ impl<'a> Parser<'a> { let mut cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?; - CondChecker { parser: self, forbid_let_reason: None }.visit_expr(&mut cond); + CondChecker::new(self).visit_expr(&mut cond); if let ExprKind::Let(_, _, _, None) = cond.kind { // Remove the last feature gating of a `let` expression since it's stable. @@ -2476,10 +2494,12 @@ impl<'a> Parser<'a> { let err = errors::ExpectedExpressionFoundLet { span: self.token.span, reason: ForbiddenLetReason::OtherForbidden, + missing_let: None, + comparison: None, }; if self.prev_token.kind == token::BinOp(token::Or) { // This was part of a closure, the that part of the parser recover. - return Err(err.into_diagnostic(&self.sess.span_diagnostic)); + return Err(err.into_diagnostic(self.diagnostic())); } else { Some(self.sess.emit_err(err)) } @@ -2589,30 +2609,72 @@ impl<'a> Parser<'a> { } } - /// Parses `for in ` (`for` token already eaten). - fn parse_expr_for(&mut self, opt_label: Option <: T iff A <: B -- e.g., function return type Invariant, // T <: T iff B == A -- e.g., type of mutable cell @@ -287,8 +294,11 @@ rustc_index::newtype_index! { /// declared, but a type name in a non-zero universe is a placeholder /// type -- an idealized representative of "types in general" that we /// use for checking generic functions. - #[derive(HashStable_Generic)] + #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] + #[encodable] + #[orderable] #[debug_format = "U{}"] + #[gate_rustc_only] pub struct UniverseIndex {} } @@ -326,3 +336,12 @@ impl UniverseIndex { self.private < other.private } } + +rustc_index::newtype_index! { + #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] + #[encodable] + #[orderable] + #[debug_format = "{}"] + #[gate_rustc_only] + pub struct BoundVar {} +} diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 23117fdd53109..b567fa8e2f621 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,18 +1,15 @@ -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_serialize::Decoder; -use rustc_serialize::{Decodable, Encodable}; use std::fmt; use std::ops::ControlFlow; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; -use crate::{HashStableContext, Interner}; -use crate::{TyDecoder, TyEncoder}; +use crate::Interner; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum ClauseKind { /// Corresponds to `where Foo: Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -69,45 +66,6 @@ impl PartialEq for ClauseKind { impl Eq for ClauseKind {} -fn clause_kind_discriminant(value: &ClauseKind) -> usize { - match value { - ClauseKind::Trait(_) => 0, - ClauseKind::RegionOutlives(_) => 1, - ClauseKind::TypeOutlives(_) => 2, - ClauseKind::Projection(_) => 3, - ClauseKind::ConstArgHasType(_, _) => 4, - ClauseKind::WellFormed(_) => 5, - ClauseKind::ConstEvaluatable(_) => 6, - } -} - -impl HashStable for ClauseKind -where - I::Ty: HashStable, - I::Const: HashStable, - I::GenericArg: HashStable, - I::TraitPredicate: HashStable, - I::ProjectionPredicate: HashStable, - I::TypeOutlivesPredicate: HashStable, - I::RegionOutlivesPredicate: HashStable, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - clause_kind_discriminant(self).hash_stable(hcx, hasher); - match self { - ClauseKind::Trait(p) => p.hash_stable(hcx, hasher), - ClauseKind::RegionOutlives(p) => p.hash_stable(hcx, hasher), - ClauseKind::TypeOutlives(p) => p.hash_stable(hcx, hasher), - ClauseKind::Projection(p) => p.hash_stable(hcx, hasher), - ClauseKind::ConstArgHasType(c, t) => { - c.hash_stable(hcx, hasher); - t.hash_stable(hcx, hasher); - } - ClauseKind::WellFormed(t) => t.hash_stable(hcx, hasher), - ClauseKind::ConstEvaluatable(c) => c.hash_stable(hcx, hasher), - } - } -} - impl TypeFoldable for ClauseKind where I::Ty: TypeFoldable, @@ -161,65 +119,9 @@ where } } -impl> Decodable for ClauseKind -where - I::Ty: Decodable, - I::Const: Decodable, - I::GenericArg: Decodable, - I::TraitPredicate: Decodable, - I::ProjectionPredicate: Decodable, - I::TypeOutlivesPredicate: Decodable, - I::RegionOutlivesPredicate: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => ClauseKind::Trait(Decodable::decode(d)), - 1 => ClauseKind::RegionOutlives(Decodable::decode(d)), - 2 => ClauseKind::TypeOutlives(Decodable::decode(d)), - 3 => ClauseKind::Projection(Decodable::decode(d)), - 4 => ClauseKind::ConstArgHasType(Decodable::decode(d), Decodable::decode(d)), - 5 => ClauseKind::WellFormed(Decodable::decode(d)), - 6 => ClauseKind::ConstEvaluatable(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "ClauseKind", 7, - ) - ), - } - } -} - -impl Encodable for ClauseKind -where - I::Ty: Encodable, - I::Const: Encodable, - I::GenericArg: Encodable, - I::TraitPredicate: Encodable, - I::ProjectionPredicate: Encodable, - I::TypeOutlivesPredicate: Encodable, - I::RegionOutlivesPredicate: Encodable, -{ - fn encode(&self, s: &mut E) { - let discriminant = clause_kind_discriminant(self); - match self { - ClauseKind::Trait(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::RegionOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::TypeOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::Projection(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::ConstArgHasType(c, t) => s.emit_enum_variant(discriminant, |s| { - c.encode(s); - t.encode(s); - }), - ClauseKind::WellFormed(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::ConstEvaluatable(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - } - } -} - #[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Hash(bound = ""))] +#[derivative(Clone(bound = ""), Hash(bound = ""), PartialEq(bound = ""), Eq(bound = ""))] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum PredicateKind { /// Prove a clause Clause(ClauseKind), @@ -227,11 +129,6 @@ pub enum PredicateKind { /// Trait must be object-safe. ObjectSafe(I::DefId), - /// No direct syntax. May be thought of as `where T: FnFoo<...>` - /// for some generic args `...` and `T` being a closure type. - /// Satisfied (or refuted) once we know the closure's kind. - ClosureKind(I::DefId, I::GenericArgs, I::ClosureKind), - /// `T1 <: T2` /// /// This obligation is created most often when we have two @@ -256,6 +153,15 @@ pub enum PredicateKind { /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. Ambiguous, + /// The alias normalizes to `term`. Unlike `Projection`, this always fails if the alias + /// cannot be normalized in the current context. + /// + /// `Projection(::Assoc, ?x)` results in `?x == ::Assoc` while + /// `NormalizesTo(::Assoc, ?x)` results in `NoSolution`. + /// + /// Only used in the new solver. + NormalizesTo(I::NormalizesTo), + /// Separate from `ClauseKind::Projection` which is used for normalization in new solver. /// This predicate requires two terms to be equal to eachother. /// @@ -271,82 +177,11 @@ where I::Term: Copy, I::CoercePredicate: Copy, I::SubtypePredicate: Copy, - I::ClosureKind: Copy, + I::NormalizesTo: Copy, ClauseKind: Copy, { } -impl PartialEq for PredicateKind { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Self::Clause(l0), Self::Clause(r0)) => l0 == r0, - (Self::ObjectSafe(l0), Self::ObjectSafe(r0)) => l0 == r0, - (Self::ClosureKind(l0, l1, l2), Self::ClosureKind(r0, r1, r2)) => { - l0 == r0 && l1 == r1 && l2 == r2 - } - (Self::Subtype(l0), Self::Subtype(r0)) => l0 == r0, - (Self::Coerce(l0), Self::Coerce(r0)) => l0 == r0, - (Self::ConstEquate(l0, l1), Self::ConstEquate(r0, r1)) => l0 == r0 && l1 == r1, - (Self::AliasRelate(l0, l1, l2), Self::AliasRelate(r0, r1, r2)) => { - l0 == r0 && l1 == r1 && l2 == r2 - } - _ => core::mem::discriminant(self) == core::mem::discriminant(other), - } - } -} - -impl Eq for PredicateKind {} - -fn predicate_kind_discriminant(value: &PredicateKind) -> usize { - match value { - PredicateKind::Clause(_) => 0, - PredicateKind::ObjectSafe(_) => 1, - PredicateKind::ClosureKind(_, _, _) => 2, - PredicateKind::Subtype(_) => 3, - PredicateKind::Coerce(_) => 4, - PredicateKind::ConstEquate(_, _) => 5, - PredicateKind::Ambiguous => 6, - PredicateKind::AliasRelate(_, _, _) => 7, - } -} - -impl HashStable for PredicateKind -where - I::DefId: HashStable, - I::Const: HashStable, - I::GenericArgs: HashStable, - I::Term: HashStable, - I::CoercePredicate: HashStable, - I::SubtypePredicate: HashStable, - I::ClosureKind: HashStable, - ClauseKind: HashStable, -{ - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - predicate_kind_discriminant(self).hash_stable(hcx, hasher); - match self { - PredicateKind::Clause(p) => p.hash_stable(hcx, hasher), - PredicateKind::ObjectSafe(d) => d.hash_stable(hcx, hasher), - PredicateKind::ClosureKind(d, g, k) => { - d.hash_stable(hcx, hasher); - g.hash_stable(hcx, hasher); - k.hash_stable(hcx, hasher); - } - PredicateKind::Subtype(p) => p.hash_stable(hcx, hasher), - PredicateKind::Coerce(p) => p.hash_stable(hcx, hasher), - PredicateKind::ConstEquate(c1, c2) => { - c1.hash_stable(hcx, hasher); - c2.hash_stable(hcx, hasher); - } - PredicateKind::Ambiguous => {} - PredicateKind::AliasRelate(t1, t2, r) => { - t1.hash_stable(hcx, hasher); - t2.hash_stable(hcx, hasher); - r.hash_stable(hcx, hasher); - } - } - } -} - impl TypeFoldable for PredicateKind where I::DefId: TypeFoldable, @@ -355,24 +190,20 @@ where I::Term: TypeFoldable, I::CoercePredicate: TypeFoldable, I::SubtypePredicate: TypeFoldable, - I::ClosureKind: TypeFoldable, + I::NormalizesTo: TypeFoldable, ClauseKind: TypeFoldable, { fn try_fold_with>(self, folder: &mut F) -> Result { Ok(match self { PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?), PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?), - PredicateKind::ClosureKind(d, g, k) => PredicateKind::ClosureKind( - d.try_fold_with(folder)?, - g.try_fold_with(folder)?, - k.try_fold_with(folder)?, - ), PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?), PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?), PredicateKind::ConstEquate(a, b) => { PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?) } PredicateKind::Ambiguous => PredicateKind::Ambiguous, + PredicateKind::NormalizesTo(p) => PredicateKind::NormalizesTo(p.try_fold_with(folder)?), PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate( a.try_fold_with(folder)?, b.try_fold_with(folder)?, @@ -390,18 +221,13 @@ where I::Term: TypeVisitable, I::CoercePredicate: TypeVisitable, I::SubtypePredicate: TypeVisitable, - I::ClosureKind: TypeVisitable, + I::NormalizesTo: TypeVisitable, ClauseKind: TypeVisitable, { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { match self { PredicateKind::Clause(p) => p.visit_with(visitor), PredicateKind::ObjectSafe(d) => d.visit_with(visitor), - PredicateKind::ClosureKind(d, g, k) => { - d.visit_with(visitor)?; - g.visit_with(visitor)?; - k.visit_with(visitor) - } PredicateKind::Subtype(s) => s.visit_with(visitor), PredicateKind::Coerce(s) => s.visit_with(visitor), PredicateKind::ConstEquate(a, b) => { @@ -409,6 +235,7 @@ where b.visit_with(visitor) } PredicateKind::Ambiguous => ControlFlow::Continue(()), + PredicateKind::NormalizesTo(p) => p.visit_with(visitor), PredicateKind::AliasRelate(a, b, d) => { a.visit_with(visitor)?; b.visit_with(visitor)?; @@ -418,85 +245,8 @@ where } } -impl> Decodable for PredicateKind -where - I::DefId: Decodable, - I::Const: Decodable, - I::GenericArgs: Decodable, - I::Term: Decodable, - I::CoercePredicate: Decodable, - I::SubtypePredicate: Decodable, - I::ClosureKind: Decodable, - ClauseKind: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => PredicateKind::Clause(Decodable::decode(d)), - 1 => PredicateKind::ObjectSafe(Decodable::decode(d)), - 2 => PredicateKind::ClosureKind( - Decodable::decode(d), - Decodable::decode(d), - Decodable::decode(d), - ), - 3 => PredicateKind::Subtype(Decodable::decode(d)), - 4 => PredicateKind::Coerce(Decodable::decode(d)), - 5 => PredicateKind::ConstEquate(Decodable::decode(d), Decodable::decode(d)), - 6 => PredicateKind::Ambiguous, - 7 => PredicateKind::AliasRelate( - Decodable::decode(d), - Decodable::decode(d), - Decodable::decode(d), - ), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "PredicateKind", 8, - ) - ), - } - } -} - -impl Encodable for PredicateKind -where - I::DefId: Encodable, - I::Const: Encodable, - I::GenericArgs: Encodable, - I::Term: Encodable, - I::CoercePredicate: Encodable, - I::SubtypePredicate: Encodable, - I::ClosureKind: Encodable, - ClauseKind: Encodable, -{ - fn encode(&self, s: &mut E) { - let discriminant = predicate_kind_discriminant(self); - match self { - PredicateKind::Clause(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::ObjectSafe(d) => s.emit_enum_variant(discriminant, |s| d.encode(s)), - PredicateKind::ClosureKind(d, g, k) => s.emit_enum_variant(discriminant, |s| { - d.encode(s); - g.encode(s); - k.encode(s); - }), - PredicateKind::Subtype(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::Coerce(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::ConstEquate(a, b) => s.emit_enum_variant(discriminant, |s| { - a.encode(s); - b.encode(s); - }), - PredicateKind::Ambiguous => s.emit_enum_variant(discriminant, |_s| {}), - PredicateKind::AliasRelate(a, b, d) => s.emit_enum_variant(discriminant, |s| { - a.encode(s); - b.encode(s); - d.encode(s); - }), - } - } -} - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, Encodable, Decodable))] pub enum AliasRelationDirection { Equate, Subtype, @@ -538,11 +288,9 @@ impl fmt::Debug for PredicateKind { PredicateKind::ObjectSafe(trait_def_id) => { write!(f, "ObjectSafe({trait_def_id:?})") } - PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => { - write!(f, "ClosureKind({closure_def_id:?}, {closure_args:?}, {kind:?})") - } PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"), PredicateKind::Ambiguous => write!(f, "Ambiguous"), + PredicateKind::NormalizesTo(p) => p.fmt(f), PredicateKind::AliasRelate(t1, t2, dir) => { write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})") } diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 72f86fc069299..4157d49287c20 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -1,12 +1,8 @@ -use rustc_data_structures::stable_hasher::HashStable; -use rustc_data_structures::stable_hasher::StableHasher; -use rustc_serialize::{Decodable, Decoder, Encodable}; +#[cfg(feature = "nightly")] +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use std::fmt; -use crate::{ - DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder, - TyEncoder, WithInfcx, -}; +use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx}; use self::RegionKind::*; @@ -26,8 +22,8 @@ use self::RegionKind::*; /// ```text /// static ----------+-----...------+ (greatest) /// | | | -/// early-bound and | | -/// free regions | | +/// param regions | | +/// | | | /// | | | /// | | | /// empty(root) placeholder(U1) | @@ -92,8 +88,8 @@ use self::RegionKind::*; /// To do this, we replace the bound regions with placeholder markers, /// which don't satisfy any relation not explicitly provided. /// -/// There are two kinds of placeholder regions in rustc: `ReFree` and -/// `RePlaceholder`. When checking an item's body, `ReFree` is supposed +/// There are two kinds of placeholder regions in rustc: `ReLateParam` and +/// `RePlaceholder`. When checking an item's body, `ReLateParam` is supposed /// to be used. These also support explicit bounds: both the internally-stored /// *scope*, which the region is assumed to outlive, as well as other /// relations stored in the `FreeRegionMap`. Note that these relations @@ -125,20 +121,37 @@ use self::RegionKind::*; Ord = "feature_allow_slow_enum", Hash(bound = "") )] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] pub enum RegionKind { - /// Region bound in a type or fn declaration which will be - /// substituted 'early' -- that is, at the same time when type - /// parameters are substituted. - ReEarlyBound(I::EarlyBoundRegion), + /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`. + /// + /// There are some important differences between region and type parameters. + /// Not all region parameters in the source are represented via `ReEarlyParam`: + /// late-bound function parameters are instead lowered to a `ReBound`. Late-bound + /// regions get eagerly replaced with `ReLateParam` which behaves in the same way as + /// `ReEarlyParam`. Region parameters are also sometimes implicit, + /// e.g. in `impl Trait for &()`. + ReEarlyParam(I::EarlyParamRegion), - /// Region bound in a function scope, which will be substituted when the - /// function is called. - ReLateBound(DebruijnIndex, I::BoundRegion), + /// A higher-ranked region. These represent either late-bound function parameters + /// or bound variables from a `for<'a>`-binder. + /// + /// While inside of a function, e.g. during typeck, the late-bound function parameters + /// can be converted to `ReLateParam` by calling `tcx.liberate_late_bound_regions`. + /// + /// Bound regions inside of types **must not** be erased, as they impact trait + /// selection and the `TypeId` of that type. `for<'a> fn(&'a ())` and + /// `fn(&'static ())` are different types and have to be treated as such. + ReBound(DebruijnIndex, I::BoundRegion), - /// When checking a function body, the types of all arguments and so forth - /// that refer to bound region parameters are modified to refer to free - /// region parameters. - ReFree(I::FreeRegion), + /// Late-bound function parameters are represented using a `ReBound`. When + /// inside of a function, we convert these bound variables to placeholder + /// parameters via `tcx.liberate_late_bound_regions`. They are then treated + /// the same way as `ReEarlyParam` while inside of the function. + /// + /// See for + /// more info about early and late bound lifetime parameters. + ReLateParam(I::LateParamRegion), /// Static data that has an "infinite" lifetime. Top in the region lattice. ReStatic, @@ -146,8 +159,11 @@ pub enum RegionKind { /// A region variable. Should not exist outside of type inference. ReVar(I::InferRegion), - /// A placeholder region -- basically, the higher-ranked version of `ReFree`. + /// A placeholder region -- the higher-ranked version of `ReLateParam`. /// Should not exist outside of type inference. + /// + /// Used when instantiating a `forall` binder via + /// `infcx.instantiate_binder_with_placeholders`. RePlaceholder(I::PlaceholderRegion), /// Erased region, used by trait selection, in MIR and during codegen. @@ -162,9 +178,9 @@ pub enum RegionKind { #[inline] const fn regionkind_discriminant(value: &RegionKind) -> usize { match value { - ReEarlyBound(_) => 0, - ReLateBound(_, _) => 1, - ReFree(_) => 2, + ReEarlyParam(_) => 0, + ReBound(_, _) => 1, + ReLateParam(_) => 2, ReStatic => 3, ReVar(_) => 4, RePlaceholder(_) => 5, @@ -176,9 +192,9 @@ const fn regionkind_discriminant(value: &RegionKind) -> usize { // This is manually implemented because a derive would require `I: Copy` impl Copy for RegionKind where - I::EarlyBoundRegion: Copy, + I::EarlyParamRegion: Copy, I::BoundRegion: Copy, - I::FreeRegion: Copy, + I::LateParamRegion: Copy, I::InferRegion: Copy, I::PlaceholderRegion: Copy, I::ErrorGuaranteed: Copy, @@ -191,9 +207,9 @@ impl PartialEq for RegionKind { fn eq(&self, other: &RegionKind) -> bool { regionkind_discriminant(self) == regionkind_discriminant(other) && match (self, other) { - (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r, - (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r, - (ReFree(a_r), ReFree(b_r)) => a_r == b_r, + (ReEarlyParam(a_r), ReEarlyParam(b_r)) => a_r == b_r, + (ReBound(a_d, a_r), ReBound(b_d, b_r)) => a_d == b_d && a_r == b_r, + (ReLateParam(a_r), ReLateParam(b_r)) => a_r == b_r, (ReStatic, ReStatic) => true, (ReVar(a_r), ReVar(b_r)) => a_r == b_r, (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r, @@ -219,13 +235,13 @@ impl DebugWithInfcx for RegionKind { f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { match this.data { - ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"), + ReEarlyParam(data) => write!(f, "ReEarlyParam({data:?})"), - ReLateBound(binder_id, bound_region) => { - write!(f, "ReLateBound({binder_id:?}, {bound_region:?})") + ReBound(binder_id, bound_region) => { + write!(f, "ReBound({binder_id:?}, {bound_region:?})") } - ReFree(fr) => write!(f, "{fr:?}"), + ReLateParam(fr) => write!(f, "{fr:?}"), ReStatic => f.write_str("ReStatic"), @@ -245,78 +261,13 @@ impl fmt::Debug for RegionKind { } } -// This is manually implemented because a derive would require `I: Encodable` -impl> Encodable for RegionKind -where - I::EarlyBoundRegion: Encodable, - I::BoundRegion: Encodable, - I::FreeRegion: Encodable, - I::InferRegion: Encodable, - I::PlaceholderRegion: Encodable, -{ - fn encode(&self, e: &mut E) { - let disc = regionkind_discriminant(self); - match self { - ReEarlyBound(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReLateBound(a, b) => e.emit_enum_variant(disc, |e| { - a.encode(e); - b.encode(e); - }), - ReFree(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReStatic => e.emit_enum_variant(disc, |_| {}), - ReVar(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - RePlaceholder(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReErased => e.emit_enum_variant(disc, |_| {}), - ReError(_) => e.emit_enum_variant(disc, |_| {}), - } - } -} - -// This is manually implemented because a derive would require `I: Decodable` -impl> Decodable for RegionKind -where - I::EarlyBoundRegion: Decodable, - I::BoundRegion: Decodable, - I::FreeRegion: Decodable, - I::InferRegion: Decodable, - I::PlaceholderRegion: Decodable, - I::ErrorGuaranteed: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => ReEarlyBound(Decodable::decode(d)), - 1 => ReLateBound(Decodable::decode(d), Decodable::decode(d)), - 2 => ReFree(Decodable::decode(d)), - 3 => ReStatic, - 4 => ReVar(Decodable::decode(d)), - 5 => RePlaceholder(Decodable::decode(d)), - 6 => ReErased, - 7 => ReError(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "RegionKind", 8, - ) - ), - } - } -} - +#[cfg(feature = "nightly")] // This is not a derived impl because a derive would require `I: HashStable` -impl HashStable for RegionKind +impl HashStable for RegionKind where - I::EarlyBoundRegion: HashStable, + I::EarlyParamRegion: HashStable, I::BoundRegion: HashStable, - I::FreeRegion: HashStable, + I::LateParamRegion: HashStable, I::InferRegion: HashStable, I::PlaceholderRegion: HashStable, { @@ -327,14 +278,14 @@ where ReErased | ReStatic | ReError(_) => { // No variant fields to hash for these ... } - ReLateBound(d, r) => { + ReBound(d, r) => { d.hash_stable(hcx, hasher); r.hash_stable(hcx, hasher); } - ReEarlyBound(r) => { + ReEarlyParam(r) => { r.hash_stable(hcx, hasher); } - ReFree(r) => { + ReLateParam(r) => { r.hash_stable(hcx, hasher); } RePlaceholder(r) => { diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs index d986e310c3297..0e4930552c211 100644 --- a/compiler/rustc_type_ir/src/ty_info.rs +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -1,4 +1,6 @@ +#[cfg(feature = "nightly")] use rustc_data_structures::fingerprint::Fingerprint; +#[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; @@ -16,6 +18,8 @@ use crate::{DebruijnIndex, TypeFlags}; #[derive(Copy, Clone)] pub struct WithCachedTypeInfo { pub internee: T, + + #[cfg(feature = "nightly")] pub stable_hash: Fingerprint, /// This field provides fast access to information that is also contained @@ -81,14 +85,16 @@ impl Deref for WithCachedTypeInfo { impl Hash for WithCachedTypeInfo { #[inline] fn hash(&self, s: &mut H) { + #[cfg(feature = "nightly")] if self.stable_hash != Fingerprint::ZERO { - self.stable_hash.hash(s) - } else { - self.internee.hash(s) + return self.stable_hash.hash(s); } + + self.internee.hash(s) } } +#[cfg(feature = "nightly")] impl, CTX> HashStable for WithCachedTypeInfo { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 2138c27334134..3d4e7f77a4f2c 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,23 +1,20 @@ #![allow(rustc::usage_of_ty_tykind)] +#[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +#[cfg(feature = "nightly")] use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; -use rustc_serialize::{Decodable, Decoder, Encodable}; use std::fmt; -use std::mem::discriminant; -use crate::HashStableContext; use crate::Interner; -use crate::TyDecoder; -use crate::TyEncoder; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx}; use self::TyKind::*; /// The movability of a coroutine / closure literal: /// whether a coroutine contains self-references, causing it to be `!Unpin`. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)] -#[derive(HashStable_Generic)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum Movability { /// May contain self-references, `!Unpin`. Static, @@ -26,7 +23,7 @@ pub enum Movability { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum Mutability { // N.B. Order is deliberate, so that Not < Mut Not, @@ -78,7 +75,7 @@ impl Mutability { /// Specifies how a trait object is represented. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum DynKind { /// An unsized `dyn Trait` object Dyn, @@ -92,7 +89,7 @@ pub enum DynKind { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum AliasKind { /// A projection `::AssocType`. /// Can get normalized away if monomorphic enough. @@ -112,7 +109,7 @@ pub enum AliasKind { /// /// Types written by the user start out as `hir::TyKind` and get /// converted to this representation using `AstConv::ast_ty_to_ty`. -#[rustc_diagnostic_item = "IrTyKind"] +#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")] #[derive(derivative::Derivative)] #[derivative( Clone(bound = ""), @@ -122,6 +119,7 @@ pub enum AliasKind { Ord = "feature_allow_slow_enum", Hash(bound = "") )] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum TyKind { /// The primitive boolean type. Written as `bool`. Bool, @@ -283,7 +281,7 @@ pub enum TyKind { /// correctly deal with higher ranked types. Though unlike placeholders, /// that universe is stored in the `InferCtxt` instead of directly /// inside of the type. - Infer(I::InferTy), + Infer(InferTy), /// A placeholder for a type which could not be computed; this is /// propagated to avoid useless error messages. @@ -409,7 +407,7 @@ impl DebugWithInfcx for TyKind { write!(f, ">") } - Foreign(d) => f.debug_tuple_field1_finish("Foreign", d), + Foreign(d) => f.debug_tuple("Foreign").field(d).finish(), Str => write!(f, "str"), Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), @@ -425,7 +423,7 @@ impl DebugWithInfcx for TyKind { Mutability::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), Mutability::Not => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), }, - FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)), + FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&this.wrap(s)).finish(), FnPtr(s) => write!(f, "{:?}", &this.wrap(s)), Dynamic(p, r, repr) => match repr { DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)), @@ -433,10 +431,12 @@ impl DebugWithInfcx for TyKind { write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r)) } }, - Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)), - Coroutine(d, s, m) => f.debug_tuple_field3_finish("Coroutine", d, &this.wrap(s), m), + Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(), + Coroutine(d, s, m) => { + f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).field(m).finish() + } CoroutineWitness(d, s) => { - f.debug_tuple_field2_finish("CoroutineWitness", d, &this.wrap(s)) + f.debug_tuple("CoroutineWitness").field(d).field(&this.wrap(s)).finish() } Never => write!(f, "!"), Tuple(t) => { @@ -455,7 +455,7 @@ impl DebugWithInfcx for TyKind { } write!(f, ")") } - Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, &this.wrap(a)), + Alias(i, a) => f.debug_tuple("Alias").field(i).field(&this.wrap(a)).finish(), Param(p) => write!(f, "{p:?}"), Bound(d, b) => crate::debug_bound_var(f, *d, b), Placeholder(p) => write!(f, "{p:?}"), @@ -472,292 +472,8 @@ impl fmt::Debug for TyKind { } } -// This is manually implemented because a derive would require `I: Encodable` -impl> Encodable for TyKind -where - I::ErrorGuaranteed: Encodable, - I::AdtDef: Encodable, - I::GenericArgs: Encodable, - I::DefId: Encodable, - I::Ty: Encodable, - I::Const: Encodable, - I::Region: Encodable, - I::TypeAndMut: Encodable, - I::PolyFnSig: Encodable, - I::BoundExistentialPredicates: Encodable, - I::Tys: Encodable, - I::AliasTy: Encodable, - I::ParamTy: Encodable, - I::BoundTy: Encodable, - I::PlaceholderTy: Encodable, - I::InferTy: Encodable, - I::AllocId: Encodable, -{ - fn encode(&self, e: &mut E) { - let disc = tykind_discriminant(self); - match self { - Bool => e.emit_enum_variant(disc, |_| {}), - Char => e.emit_enum_variant(disc, |_| {}), - Int(i) => e.emit_enum_variant(disc, |e| { - i.encode(e); - }), - Uint(u) => e.emit_enum_variant(disc, |e| { - u.encode(e); - }), - Float(f) => e.emit_enum_variant(disc, |e| { - f.encode(e); - }), - Adt(adt, args) => e.emit_enum_variant(disc, |e| { - adt.encode(e); - args.encode(e); - }), - Foreign(def_id) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - }), - Str => e.emit_enum_variant(disc, |_| {}), - Array(t, c) => e.emit_enum_variant(disc, |e| { - t.encode(e); - c.encode(e); - }), - Slice(t) => e.emit_enum_variant(disc, |e| { - t.encode(e); - }), - RawPtr(tam) => e.emit_enum_variant(disc, |e| { - tam.encode(e); - }), - Ref(r, t, m) => e.emit_enum_variant(disc, |e| { - r.encode(e); - t.encode(e); - m.encode(e); - }), - FnDef(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| { - polyfnsig.encode(e); - }), - Dynamic(l, r, repr) => e.emit_enum_variant(disc, |e| { - l.encode(e); - r.encode(e); - repr.encode(e); - }), - Closure(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - Coroutine(def_id, args, m) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - m.encode(e); - }), - CoroutineWitness(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - Never => e.emit_enum_variant(disc, |_| {}), - Tuple(args) => e.emit_enum_variant(disc, |e| { - args.encode(e); - }), - Alias(k, p) => e.emit_enum_variant(disc, |e| { - k.encode(e); - p.encode(e); - }), - Param(p) => e.emit_enum_variant(disc, |e| { - p.encode(e); - }), - Bound(d, b) => e.emit_enum_variant(disc, |e| { - d.encode(e); - b.encode(e); - }), - Placeholder(p) => e.emit_enum_variant(disc, |e| { - p.encode(e); - }), - Infer(i) => e.emit_enum_variant(disc, |e| { - i.encode(e); - }), - Error(d) => e.emit_enum_variant(disc, |e| { - d.encode(e); - }), - } - } -} - -// This is manually implemented because a derive would require `I: Decodable` -impl> Decodable for TyKind -where - I::ErrorGuaranteed: Decodable, - I::AdtDef: Decodable, - I::GenericArgs: Decodable, - I::DefId: Decodable, - I::Ty: Decodable, - I::Const: Decodable, - I::Region: Decodable, - I::TypeAndMut: Decodable, - I::PolyFnSig: Decodable, - I::BoundExistentialPredicates: Decodable, - I::Tys: Decodable, - I::AliasTy: Decodable, - I::ParamTy: Decodable, - I::AliasTy: Decodable, - I::BoundTy: Decodable, - I::PlaceholderTy: Decodable, - I::InferTy: Decodable, - I::AllocId: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => Bool, - 1 => Char, - 2 => Int(Decodable::decode(d)), - 3 => Uint(Decodable::decode(d)), - 4 => Float(Decodable::decode(d)), - 5 => Adt(Decodable::decode(d), Decodable::decode(d)), - 6 => Foreign(Decodable::decode(d)), - 7 => Str, - 8 => Array(Decodable::decode(d), Decodable::decode(d)), - 9 => Slice(Decodable::decode(d)), - 10 => RawPtr(Decodable::decode(d)), - 11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 12 => FnDef(Decodable::decode(d), Decodable::decode(d)), - 13 => FnPtr(Decodable::decode(d)), - 14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 15 => Closure(Decodable::decode(d), Decodable::decode(d)), - 16 => Coroutine(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 17 => CoroutineWitness(Decodable::decode(d), Decodable::decode(d)), - 18 => Never, - 19 => Tuple(Decodable::decode(d)), - 20 => Alias(Decodable::decode(d), Decodable::decode(d)), - 21 => Param(Decodable::decode(d)), - 22 => Bound(Decodable::decode(d), Decodable::decode(d)), - 23 => Placeholder(Decodable::decode(d)), - 24 => Infer(Decodable::decode(d)), - 25 => Error(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "TyKind", 26, - ) - ), - } - } -} - -// This is not a derived impl because a derive would require `I: HashStable` -#[allow(rustc::usage_of_ty_tykind)] -impl HashStable for TyKind -where - I::AdtDef: HashStable, - I::DefId: HashStable, - I::GenericArgs: HashStable, - I::Ty: HashStable, - I::Const: HashStable, - I::TypeAndMut: HashStable, - I::PolyFnSig: HashStable, - I::BoundExistentialPredicates: HashStable, - I::Region: HashStable, - I::Tys: HashStable, - I::AliasTy: HashStable, - I::BoundTy: HashStable, - I::ParamTy: HashStable, - I::PlaceholderTy: HashStable, - I::InferTy: HashStable, - I::ErrorGuaranteed: HashStable, -{ - #[inline] - fn hash_stable(&self, __hcx: &mut CTX, __hasher: &mut StableHasher) { - std::mem::discriminant(self).hash_stable(__hcx, __hasher); - match self { - Bool => {} - Char => {} - Int(i) => { - i.hash_stable(__hcx, __hasher); - } - Uint(u) => { - u.hash_stable(__hcx, __hasher); - } - Float(f) => { - f.hash_stable(__hcx, __hasher); - } - Adt(adt, args) => { - adt.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - } - Foreign(def_id) => { - def_id.hash_stable(__hcx, __hasher); - } - Str => {} - Array(t, c) => { - t.hash_stable(__hcx, __hasher); - c.hash_stable(__hcx, __hasher); - } - Slice(t) => { - t.hash_stable(__hcx, __hasher); - } - RawPtr(tam) => { - tam.hash_stable(__hcx, __hasher); - } - Ref(r, t, m) => { - r.hash_stable(__hcx, __hasher); - t.hash_stable(__hcx, __hasher); - m.hash_stable(__hcx, __hasher); - } - FnDef(def_id, args) => { - def_id.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - } - FnPtr(polyfnsig) => { - polyfnsig.hash_stable(__hcx, __hasher); - } - Dynamic(l, r, repr) => { - l.hash_stable(__hcx, __hasher); - r.hash_stable(__hcx, __hasher); - repr.hash_stable(__hcx, __hasher); - } - Closure(def_id, args) => { - def_id.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - } - Coroutine(def_id, args, m) => { - def_id.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - m.hash_stable(__hcx, __hasher); - } - CoroutineWitness(def_id, args) => { - def_id.hash_stable(__hcx, __hasher); - args.hash_stable(__hcx, __hasher); - } - Never => {} - Tuple(args) => { - args.hash_stable(__hcx, __hasher); - } - Alias(k, p) => { - k.hash_stable(__hcx, __hasher); - p.hash_stable(__hcx, __hasher); - } - Param(p) => { - p.hash_stable(__hcx, __hasher); - } - Bound(d, b) => { - d.hash_stable(__hcx, __hasher); - b.hash_stable(__hcx, __hasher); - } - Placeholder(p) => { - p.hash_stable(__hcx, __hasher); - } - Infer(i) => { - i.hash_stable(__hcx, __hasher); - } - Error(d) => { - d.hash_stable(__hcx, __hasher); - } - } - } -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum IntTy { Isize, I8, @@ -815,7 +531,7 @@ impl IntTy { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum UintTy { Usize, U8, @@ -873,7 +589,7 @@ impl UintTy { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum FloatTy { F32, F64, @@ -906,19 +622,28 @@ pub struct FloatVarValue(pub FloatTy); rustc_index::newtype_index! { /// A **ty**pe **v**ariable **ID**. + #[encodable] + #[orderable] #[debug_format = "?{}t"] + #[gate_rustc_only] pub struct TyVid {} } rustc_index::newtype_index! { /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. + #[encodable] + #[orderable] #[debug_format = "?{}i"] + #[gate_rustc_only] pub struct IntVid {} } rustc_index::newtype_index! { /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. + #[encodable] + #[orderable] #[debug_format = "?{}f"] + #[gate_rustc_only] pub struct FloatVid {} } @@ -927,7 +652,8 @@ rustc_index::newtype_index! { /// E.g., if we have an empty array (`[]`), then we create a fresh /// type variable for the element type since we won't know until it's /// used what the element type is supposed to be. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))] pub enum InferTy { /// A type variable. TyVar(TyVid), @@ -960,6 +686,7 @@ pub enum InferTy { /// Raw `TyVid` are used as the unification key for `sub_relations`; /// they carry no values. +#[cfg(feature = "nightly")] impl UnifyKey for TyVid { type Value = (); #[inline] @@ -975,8 +702,10 @@ impl UnifyKey for TyVid { } } +#[cfg(feature = "nightly")] impl EqUnifyValue for IntVarValue {} +#[cfg(feature = "nightly")] impl UnifyKey for IntVid { type Value = Option; #[inline] // make this function eligible for inlining - it is quite hot. @@ -992,8 +721,10 @@ impl UnifyKey for IntVid { } } +#[cfg(feature = "nightly")] impl EqUnifyValue for FloatVarValue {} +#[cfg(feature = "nightly")] impl UnifyKey for FloatVid { type Value = Option; #[inline] @@ -1009,10 +740,11 @@ impl UnifyKey for FloatVid { } } +#[cfg(feature = "nightly")] impl HashStable for InferTy { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { use InferTy::*; - discriminant(self).hash_stable(ctx, hasher); + std::mem::discriminant(self).hash_stable(ctx, hasher); match self { TyVar(_) | IntVar(_) | FloatVar(_) => { panic!("type variables should not be hashed: {self:?}") @@ -1083,7 +815,7 @@ impl fmt::Debug for InferTy { } } -impl> DebugWithInfcx for InferTy { +impl DebugWithInfcx for InferTy { fn fmt>( this: WithInfcx<'_, Infcx, &Self>, f: &mut fmt::Formatter<'_>, diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 9c7b8156b0437..7aa990046675f 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -41,12 +41,12 @@ //! - u.visit_with(visitor) //! ``` -use rustc_data_structures::sync::Lrc; use rustc_index::{Idx, IndexVec}; use std::fmt; use std::ops::ControlFlow; use crate::Interner; +use crate::Lrc; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -82,8 +82,12 @@ pub trait TypeSuperVisitable: TypeVisitable { /// method defined for every type of interest. Each such method has a default /// that recurses into the type's fields in a non-custom fashion. pub trait TypeVisitor: Sized { + #[cfg(feature = "nightly")] type BreakTy = !; + #[cfg(not(feature = "nightly"))] + type BreakTy; + fn visit_binder>(&mut self, t: &I::Binder) -> ControlFlow where I::Binder: TypeSuperVisitable, diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs new file mode 100644 index 0000000000000..7916d04250d57 --- /dev/null +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -0,0 +1,189 @@ +//! Define the interface with the Rust compiler. +//! +//! StableMIR users should not use any of the items in this module directly. +//! These APIs have no stability guarantee. + +use std::cell::Cell; + +use crate::mir::alloc::{AllocId, GlobalAlloc}; +use crate::mir::mono::{Instance, InstanceDef, StaticDef}; +use crate::mir::Body; +use crate::ty::{ + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs, + GenericPredicates, Generics, ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, + TraitDef, Ty, TyKind, VariantDef, +}; +use crate::{ + mir, Crate, CrateItem, CrateItems, DefId, Error, Filename, ImplTraitDecls, ItemKind, Symbol, + TraitDecls, +}; + +/// This trait defines the interface between stable_mir and the Rust compiler. +/// Do not use this directly. +pub trait Context { + fn entry_fn(&self) -> Option; + /// Retrieve all items of the local crate that have a MIR associated with them. + fn all_local_items(&self) -> CrateItems; + /// Retrieve the body of a function. + /// This function will panic if the body is not available. + fn mir_body(&self, item: DefId) -> mir::Body; + /// Check whether the body of a function is available. + fn has_body(&self, item: DefId) -> bool; + fn all_trait_decls(&self) -> TraitDecls; + fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; + fn all_trait_impls(&self) -> ImplTraitDecls; + fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait; + fn generics_of(&self, def_id: DefId) -> Generics; + fn predicates_of(&self, def_id: DefId) -> GenericPredicates; + fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates; + /// Get information about the local crate. + fn local_crate(&self) -> Crate; + /// Retrieve a list of all external crates. + fn external_crates(&self) -> Vec; + + /// Find a crate with the given name. + fn find_crates(&self, name: &str) -> Vec; + + /// Returns the name of given `DefId` + fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol; + + /// Returns printable, human readable form of `Span` + fn span_to_string(&self, span: Span) -> String; + + /// Return filename from given `Span`, for diagnostic purposes + fn get_filename(&self, span: &Span) -> Filename; + + /// Return lines corresponding to this `Span` + fn get_lines(&self, span: &Span) -> LineInfo; + + /// Returns the `kind` of given `DefId` + fn item_kind(&self, item: CrateItem) -> ItemKind; + + /// Returns whether this is a foreign item. + fn is_foreign_item(&self, item: DefId) -> bool; + + /// Returns the kind of a given algebraic data type + fn adt_kind(&self, def: AdtDef) -> AdtKind; + + /// Returns if the ADT is a box. + fn adt_is_box(&self, def: AdtDef) -> bool; + + /// Retrieve the function signature for the given generic arguments. + fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig; + + /// The number of variants in this ADT. + fn adt_variants_len(&self, def: AdtDef) -> usize; + + /// The name of a variant. + fn variant_name(&self, def: VariantDef) -> Symbol; + fn variant_fields(&self, def: VariantDef) -> Vec; + + /// Evaluate constant as a target usize. + fn eval_target_usize(&self, cnst: &Const) -> Result; + + /// Create a target usize constant for the given value. + fn usize_to_const(&self, val: u64) -> Result; + + /// Create a new type from the given kind. + fn new_rigid_ty(&self, kind: RigidTy) -> Ty; + + /// Create a new box type, `Box`, for the given inner type `T`. + fn new_box_ty(&self, ty: Ty) -> Ty; + + /// Returns the type of given crate item. + fn def_ty(&self, item: DefId) -> Ty; + + /// Returns the type of given definition instantiated with the given arguments. + fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty; + + /// Returns literal value of a const as a string. + fn const_literal(&self, cnst: &Const) -> String; + + /// `Span` of an item + fn span_of_an_item(&self, def_id: DefId) -> Span; + + /// Obtain the representation of a type. + fn ty_kind(&self, ty: Ty) -> TyKind; + + // Get the discriminant Ty for this Ty if there's one. + fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty; + + /// Get the body of an Instance which is already monomorphized. + fn instance_body(&self, instance: InstanceDef) -> Option; + + /// Get the instance type with generic substitutions applied and lifetimes erased. + fn instance_ty(&self, instance: InstanceDef) -> Ty; + + /// Get the instance. + fn instance_def_id(&self, instance: InstanceDef) -> DefId; + + /// Get the instance mangled name. + fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol; + + /// Check if this is an empty DropGlue shim. + fn is_empty_drop_shim(&self, def: InstanceDef) -> bool; + + /// Convert a non-generic crate item into an instance. + /// This function will panic if the item is generic. + fn mono_instance(&self, def_id: DefId) -> Instance; + + /// Item requires monomorphization. + fn requires_monomorphization(&self, def_id: DefId) -> bool; + + /// Resolve an instance from the given function definition and generic arguments. + fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option; + + /// Resolve an instance for drop_in_place for the given type. + fn resolve_drop_in_place(&self, ty: Ty) -> Instance; + + /// Resolve instance for a function pointer. + fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option; + + /// Resolve instance for a closure with the requested type. + fn resolve_closure( + &self, + def: ClosureDef, + args: &GenericArgs, + kind: ClosureKind, + ) -> Option; + + /// Evaluate a static's initializer. + fn eval_static_initializer(&self, def: StaticDef) -> Result; + + /// Retrieve global allocation for the given allocation ID. + fn global_alloc(&self, id: AllocId) -> GlobalAlloc; + + /// Retrieve the id for the virtual table. + fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option; + fn krate(&self, def_id: DefId) -> Crate; + fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol; +} + +// A thread local variable that stores a pointer to the tables mapping between TyCtxt +// datastructures and stable MIR datastructures +scoped_thread_local! (static TLV: Cell<*const ()>); + +pub fn run(context: &dyn Context, f: F) -> Result +where + F: FnOnce() -> T, +{ + if TLV.is_set() { + Err(Error::from("StableMIR already running")) + } else { + let ptr: *const () = &context as *const &_ as _; + TLV.set(&Cell::new(ptr), || Ok(f())) + } +} + +/// Execute the given function with access the compiler [Context]. +/// +/// I.e., This function will load the current context and calls a function with it. +/// Do not nest these, as that will ICE. +pub(crate) fn with(f: impl FnOnce(&dyn Context) -> R) -> R { + assert!(TLV.is_set()); + TLV.with(|tlv| { + let ptr = tlv.get(); + assert!(!ptr.is_null()); + f(unsafe { *(ptr as *const &dyn Context) }) + }) +} diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs new file mode 100644 index 0000000000000..70ca9e6825e1f --- /dev/null +++ b/compiler/stable_mir/src/crate_def.rs @@ -0,0 +1,69 @@ +//! Module that define a common trait for things that represent a crate definition, +//! such as, a function, a trait, an enum, and any other definitions. + +use crate::ty::Span; +use crate::{with, Crate, Symbol}; + +/// A unique identification number for each item accessible for the current compilation unit. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct DefId(pub(crate) usize); + +/// A trait for retrieving information about a particular definition. +/// +/// Implementors must provide the implementation of `def_id` which will be used to retrieve +/// information about a crate's definition. +pub trait CrateDef { + /// Retrieve the unique identifier for the current definition. + fn def_id(&self) -> DefId; + + /// Return the fully qualified name of the current definition. + fn name(&self) -> Symbol { + let def_id = self.def_id(); + with(|cx| cx.def_name(def_id, false)) + } + + /// Return a trimmed name of this definition. + /// + /// This can be used to print more user friendly diagnostic messages. + /// + /// If a symbol name can only be imported from one place for a type, and as + /// long as it was not glob-imported anywhere in the current crate, we trim its + /// path and print only the name. + /// + /// For example, this function may shorten `std::vec::Vec` to just `Vec`, + /// as long as there is no other `Vec` importable anywhere. + fn trimmed_name(&self) -> Symbol { + let def_id = self.def_id(); + with(|cx| cx.def_name(def_id, true)) + } + + /// Return information about the crate where this definition is declared. + /// + /// This will return the crate number and its name. + fn krate(&self) -> Crate { + let def_id = self.def_id(); + with(|cx| cx.krate(def_id)) + } + + /// Return the span of this definition. + fn span(&self) -> Span { + let def_id = self.def_id(); + with(|cx| cx.span_of_an_item(def_id)) + } +} + +macro_rules! crate_def { + ( $(#[$attr:meta])* + $vis:vis $name:ident $(;)? + ) => { + $(#[$attr])* + #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] + $vis struct $name(pub DefId); + + impl CrateDef for $name { + fn def_id(&self) -> DefId { + self.0 + } + } + }; +} diff --git a/compiler/stable_mir/src/error.rs b/compiler/stable_mir/src/error.rs index 1991069145628..bb5e1a34180ba 100644 --- a/compiler/stable_mir/src/error.rs +++ b/compiler/stable_mir/src/error.rs @@ -8,6 +8,11 @@ use std::convert::From; use std::fmt::{Debug, Display, Formatter}; use std::{error, fmt}; +macro_rules! error { + ($fmt: literal $(,)?) => { Error(format!($fmt)) }; + ($fmt: literal, $($arg:tt)*) => { Error(format!($fmt, $($arg:tt)*)) }; + } + /// An error type used to represent an error that has already been reported by the compiler. #[derive(Clone, Copy, PartialEq, Eq)] pub enum CompilerError { @@ -23,11 +28,11 @@ pub enum CompilerError { } /// A generic error to represent an API request that cannot be fulfilled. -#[derive(Debug)] -pub struct Error(String); +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Error(pub(crate) String); impl Error { - pub(crate) fn new(msg: String) -> Self { + pub fn new(msg: String) -> Self { Self(msg) } } diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index f316671b278ea..1e7495009d8de 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -16,45 +16,43 @@ //! //! The goal is to eventually be published on //! [crates.io](https://crates.io). +#![feature(type_alias_impl_trait)] +#[macro_use] +extern crate scoped_tls; -use crate::mir::mono::InstanceDef; -use crate::mir::Body; -use std::cell::Cell; use std::fmt; use std::fmt::Debug; +use std::io; -use self::ty::{ - GenericPredicates, Generics, ImplDef, ImplTrait, IndexedVal, LineInfo, Span, TraitDecl, - TraitDef, Ty, TyKind, -}; +use crate::compiler_interface::with; +pub use crate::crate_def::CrateDef; +pub use crate::crate_def::DefId; +pub use crate::error::*; +use crate::mir::pretty::function_name; +use crate::mir::Body; +use crate::mir::Mutability; +use crate::ty::{ImplDef, ImplTrait, IndexedVal, Span, TraitDecl, TraitDef, Ty}; #[macro_use] -extern crate scoped_tls; - +pub mod crate_def; +pub mod compiler_interface; +#[macro_use] pub mod error; pub mod mir; pub mod ty; pub mod visitor; -pub use error::*; -use mir::mono::Instance; -use ty::{FnDef, GenericArgs}; - /// Use String for now but we should replace it. pub type Symbol = String; /// The number that identifies a crate. pub type CrateNum = usize; -/// A unique identification number for each item accessible for the current compilation unit. -#[derive(Clone, Copy, PartialEq, Eq)] -pub struct DefId(usize); - impl Debug for DefId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("DefId") .field("id", &self.0) - .field("name", &with(|cx| cx.name_of_def_id(*self))) + .field("name", &with(|cx| cx.def_name(*self, false))) .finish() } } @@ -69,19 +67,6 @@ impl IndexedVal for DefId { } } -/// A unique identification number for each provenance -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AllocId(usize); - -impl IndexedVal for AllocId { - fn to_val(index: usize) -> Self { - AllocId(index) - } - fn to_index(&self) -> usize { - self.0 - } -} - /// A list of crate items. pub type CrateItems = Vec; @@ -99,12 +84,19 @@ pub struct Crate { pub is_local: bool, } -pub type DefKind = Opaque; -pub type Filename = Opaque; +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +pub enum ItemKind { + Fn, + Static, + Const, +} + +pub type Filename = String; -/// Holds information about an item in the crate. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct CrateItem(pub DefId); +crate_def! { + /// Holds information about an item in a crate. + pub CrateItem; +} impl CrateItem { pub fn body(&self) -> mir::Body { @@ -115,17 +107,26 @@ impl CrateItem { with(|cx| cx.span_of_an_item(self.0)) } - pub fn name(&self) -> String { - with(|cx| cx.name_of_def_id(self.0)) - } - - pub fn kind(&self) -> DefKind { - with(|cx| cx.def_kind(self.0)) + pub fn kind(&self) -> ItemKind { + with(|cx| cx.item_kind(*self)) } pub fn requires_monomorphization(&self) -> bool { with(|cx| cx.requires_monomorphization(self.0)) } + + pub fn ty(&self) -> Ty { + with(|cx| cx.def_ty(self.0)) + } + + pub fn is_foreign_item(&self) -> bool { + with(|cx| cx.is_foreign_item(self.0)) + } + + pub fn dump(&self, w: &mut W) -> io::Result<()> { + writeln!(w, "{}", function_name(*self))?; + self.body().dump(w) + } } /// Return the function where execution starts if the current @@ -171,96 +172,8 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait { with(|cx| cx.trait_impl(trait_impl)) } -pub trait Context { - fn entry_fn(&self) -> Option; - /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&self) -> CrateItems; - fn mir_body(&self, item: DefId) -> mir::Body; - fn all_trait_decls(&self) -> TraitDecls; - fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; - fn all_trait_impls(&self) -> ImplTraitDecls; - fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait; - fn generics_of(&self, def_id: DefId) -> Generics; - fn predicates_of(&self, def_id: DefId) -> GenericPredicates; - fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates; - /// Get information about the local crate. - fn local_crate(&self) -> Crate; - /// Retrieve a list of all external crates. - fn external_crates(&self) -> Vec; - - /// Find a crate with the given name. - fn find_crates(&self, name: &str) -> Vec; - - /// Returns the name of given `DefId` - fn name_of_def_id(&self, def_id: DefId) -> String; - - /// Returns printable, human readable form of `Span` - fn span_to_string(&self, span: Span) -> String; - - /// Return filename from given `Span`, for diagnostic purposes - fn get_filename(&self, span: &Span) -> Filename; - - /// Return lines corresponding to this `Span` - fn get_lines(&self, span: &Span) -> LineInfo; - - /// Returns the `kind` of given `DefId` - fn def_kind(&self, def_id: DefId) -> DefKind; - - /// `Span` of an item - fn span_of_an_item(&self, def_id: DefId) -> Span; - - /// Obtain the representation of a type. - fn ty_kind(&self, ty: Ty) -> TyKind; - - /// Get the body of an Instance. - /// FIXME: Monomorphize the body. - fn instance_body(&self, instance: InstanceDef) -> Body; - - /// Get the instance type with generic substitutions applied and lifetimes erased. - fn instance_ty(&self, instance: InstanceDef) -> Ty; - - /// Get the instance. - fn instance_def_id(&self, instance: InstanceDef) -> DefId; - - /// Get the instance mangled name. - fn instance_mangled_name(&self, instance: InstanceDef) -> String; - - /// Convert a non-generic crate item into an instance. - /// This function will panic if the item is generic. - fn mono_instance(&self, item: CrateItem) -> Instance; - - /// Item requires monomorphization. - fn requires_monomorphization(&self, def_id: DefId) -> bool; - - /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option; -} - -// A thread local variable that stores a pointer to the tables mapping between TyCtxt -// datastructures and stable MIR datastructures -scoped_thread_local! (static TLV: Cell<*const ()>); - -pub fn run(context: &dyn Context, f: impl FnOnce()) { - assert!(!TLV.is_set()); - let ptr: *const () = &context as *const &_ as _; - TLV.set(&Cell::new(ptr), || { - f(); - }); -} - -/// Loads the current context and calls a function with it. -/// Do not nest these, as that will ICE. -pub fn with(f: impl FnOnce(&dyn Context) -> R) -> R { - assert!(TLV.is_set()); - TLV.with(|tlv| { - let ptr = tlv.get(); - assert!(!ptr.is_null()); - f(unsafe { *(ptr as *const &dyn Context) }) - }) -} - /// A type that provides internal information but that can still be used for debug purpose. -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, PartialEq, Eq, Hash)] pub struct Opaque(String); impl std::fmt::Display for Opaque { @@ -271,7 +184,7 @@ impl std::fmt::Display for Opaque { impl std::fmt::Debug for Opaque { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.0) + write!(f, "{}", self.0) } } diff --git a/compiler/stable_mir/src/mir.rs b/compiler/stable_mir/src/mir.rs index 2e1714b49c184..82555461d644e 100644 --- a/compiler/stable_mir/src/mir.rs +++ b/compiler/stable_mir/src/mir.rs @@ -1,5 +1,7 @@ +pub mod alloc; mod body; pub mod mono; +pub mod pretty; pub mod visit; pub use body::*; diff --git a/compiler/stable_mir/src/mir/alloc.rs b/compiler/stable_mir/src/mir/alloc.rs new file mode 100644 index 0000000000000..af951bcef8c1e --- /dev/null +++ b/compiler/stable_mir/src/mir/alloc.rs @@ -0,0 +1,51 @@ +//! This module provides methods to retrieve allocation information, such as static variables. +use crate::mir::mono::{Instance, StaticDef}; +use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty}; +use crate::with; + +/// An allocation in the SMIR global memory can be either a function pointer, +/// a static, or a "real" allocation with some data in it. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum GlobalAlloc { + /// The alloc ID is used as a function pointer. + Function(Instance), + /// This alloc ID points to a symbolic (not-reified) vtable. + /// The `None` trait ref is used to represent auto traits. + VTable(Ty, Option>), + /// The alloc ID points to a "lazy" static variable that did not get computed (yet). + /// This is also used to break the cycle in recursive statics. + Static(StaticDef), + /// The alloc ID points to memory. + Memory(Allocation), +} + +impl From for GlobalAlloc { + fn from(value: AllocId) -> Self { + with(|cx| cx.global_alloc(value)) + } +} + +impl GlobalAlloc { + /// Retrieve the allocation id for a global allocation if it exists. + /// + /// For `[GlobalAlloc::VTable]`, this will return the allocation for the VTable of the given + /// type for the optional trait if the type implements the trait. + /// + /// This method will always return `None` for allocations other than `[GlobalAlloc::VTable]`. + pub fn vtable_allocation(&self) -> Option { + with(|cx| cx.vtable_allocation(self)) + } +} + +/// A unique identification number for each provenance +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct AllocId(usize); + +impl IndexedVal for AllocId { + fn to_val(index: usize) -> Self { + AllocId(index) + } + fn to_index(&self) -> usize { + self.0 + } +} diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 4818bceadeffc..90bd7aa7d1872 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1,36 +1,49 @@ -use crate::ty::{AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, Ty}; -use crate::Opaque; -use crate::Span; - +use crate::mir::pretty::{function_body, pretty_statement, pretty_terminator}; +use crate::ty::{ + AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind, + VariantIdx, +}; +use crate::{Error, Opaque, Span, Symbol}; +use std::io; /// The SMIR representation of a single function. #[derive(Clone, Debug)] pub struct Body { pub blocks: Vec, - // Declarations of locals within the function. - // - // The first local is the return value pointer, followed by `arg_count` - // locals for the function arguments, followed by any user-declared - // variables and temporaries. + /// Declarations of locals within the function. + /// + /// The first local is the return value pointer, followed by `arg_count` + /// locals for the function arguments, followed by any user-declared + /// variables and temporaries. pub(super) locals: LocalDecls, - // The number of arguments this function takes. + /// The number of arguments this function takes. pub(super) arg_count: usize, + + /// Debug information pertaining to user variables, including captures. + pub(super) var_debug_info: Vec, } +pub type BasicBlockIdx = usize; + impl Body { /// Constructs a `Body`. /// /// A constructor is required to build a `Body` from outside the crate /// because the `arg_count` and `locals` fields are private. - pub fn new(blocks: Vec, locals: LocalDecls, arg_count: usize) -> Self { + pub fn new( + blocks: Vec, + locals: LocalDecls, + arg_count: usize, + var_debug_info: Vec, + ) -> Self { // If locals doesn't contain enough entries, it can lead to panics in // `ret_local`, `arg_locals`, and `inner_locals`. assert!( locals.len() > arg_count, "A Body must contain at least a local for the return value and each of the function's arguments" ); - Self { blocks, locals, arg_count } + Self { blocks, locals, arg_count, var_debug_info } } /// Return local that holds this function's return value. @@ -56,6 +69,35 @@ impl Body { pub fn locals(&self) -> &[LocalDecl] { &self.locals } + + /// Get the local declaration for this local. + pub fn local_decl(&self, local: Local) -> Option<&LocalDecl> { + self.locals.get(local) + } + + pub fn dump(&self, w: &mut W) -> io::Result<()> { + writeln!(w, "{}", function_body(self))?; + self.blocks + .iter() + .enumerate() + .map(|(index, block)| -> io::Result<()> { + writeln!(w, " bb{}: {{", index)?; + let _ = block + .statements + .iter() + .map(|statement| -> io::Result<()> { + writeln!(w, "{}", pretty_statement(&statement.kind))?; + Ok(()) + }) + .collect::>(); + pretty_terminator(&block.terminator.kind, w)?; + writeln!(w, "").unwrap(); + writeln!(w, " }}").unwrap(); + Ok(()) + }) + .collect::, _>>()?; + Ok(()) + } } type LocalDecls = Vec; @@ -64,9 +106,10 @@ type LocalDecls = Vec; pub struct LocalDecl { pub ty: Ty, pub span: Span, + pub mutability: Mutability, } -#[derive(Clone, Debug)] +#[derive(Clone, PartialEq, Eq, Debug)] pub struct BasicBlock { pub statements: Vec, pub terminator: Terminator, @@ -78,15 +121,22 @@ pub struct Terminator { pub span: Span, } +impl Terminator { + pub fn successors(&self) -> Successors { + self.kind.successors() + } +} + +pub type Successors = Vec; + #[derive(Clone, Debug, Eq, PartialEq)] pub enum TerminatorKind { Goto { - target: usize, + target: BasicBlockIdx, }, SwitchInt { discr: Operand, - targets: Vec, - otherwise: usize, + targets: SwitchTargets, }, Resume, Abort, @@ -94,34 +144,81 @@ pub enum TerminatorKind { Unreachable, Drop { place: Place, - target: usize, + target: BasicBlockIdx, unwind: UnwindAction, }, Call { func: Operand, args: Vec, destination: Place, - target: Option, + target: Option, unwind: UnwindAction, }, Assert { cond: Operand, expected: bool, msg: AssertMessage, - target: usize, + target: BasicBlockIdx, unwind: UnwindAction, }, - CoroutineDrop, InlineAsm { template: String, operands: Vec, options: String, line_spans: String, - destination: Option, + destination: Option, unwind: UnwindAction, }, } +impl TerminatorKind { + pub fn successors(&self) -> Successors { + use self::TerminatorKind::*; + match *self { + Call { target: Some(t), unwind: UnwindAction::Cleanup(u), .. } + | Drop { target: t, unwind: UnwindAction::Cleanup(u), .. } + | Assert { target: t, unwind: UnwindAction::Cleanup(u), .. } + | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(u), .. } => { + vec![t, u] + } + Goto { target: t } + | Call { target: None, unwind: UnwindAction::Cleanup(t), .. } + | Call { target: Some(t), unwind: _, .. } + | Drop { target: t, unwind: _, .. } + | Assert { target: t, unwind: _, .. } + | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. } + | InlineAsm { destination: Some(t), unwind: _, .. } => { + vec![t] + } + + Return + | Resume + | Abort + | Unreachable + | Call { target: None, unwind: _, .. } + | InlineAsm { destination: None, unwind: _, .. } => { + vec![] + } + SwitchInt { ref targets, .. } => targets.all_targets(), + } + } + + pub fn unwind(&self) -> Option<&UnwindAction> { + match *self { + TerminatorKind::Goto { .. } + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::SwitchInt { .. } => None, + TerminatorKind::Call { ref unwind, .. } + | TerminatorKind::Assert { ref unwind, .. } + | TerminatorKind::Drop { ref unwind, .. } + | TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind), + } + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct InlineAsmOperand { pub in_value: Option, @@ -136,7 +233,7 @@ pub enum UnwindAction { Continue, Unreachable, Terminate, - Cleanup(usize), + Cleanup(BasicBlockIdx), } #[derive(Clone, Debug, Eq, PartialEq)] @@ -177,6 +274,38 @@ pub enum BinOp { Offset, } +impl BinOp { + /// Return the type of this operation for the given input Ty. + /// This function does not perform type checking, and it currently doesn't handle SIMD. + pub fn ty(&self, lhs_ty: Ty, rhs_ty: Ty) -> Ty { + assert!(lhs_ty.kind().is_primitive()); + assert!(rhs_ty.kind().is_primitive()); + match self { + BinOp::Add + | BinOp::AddUnchecked + | BinOp::Sub + | BinOp::SubUnchecked + | BinOp::Mul + | BinOp::MulUnchecked + | BinOp::Div + | BinOp::Rem + | BinOp::BitXor + | BinOp::BitAnd + | BinOp::BitOr => { + assert_eq!(lhs_ty, rhs_ty); + lhs_ty + } + BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked | BinOp::Offset => { + lhs_ty + } + BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { + assert_eq!(lhs_ty, rhs_ty); + Ty::bool_ty() + } + } + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub enum UnOp { Not, @@ -378,6 +507,63 @@ pub enum Rvalue { Use(Operand), } +impl Rvalue { + pub fn ty(&self, locals: &[LocalDecl]) -> Result { + match self { + Rvalue::Use(operand) => operand.ty(locals), + Rvalue::Repeat(operand, count) => { + Ok(Ty::new_array_with_const_len(operand.ty(locals)?, count.clone())) + } + Rvalue::ThreadLocalRef(did) => Ok(did.ty()), + Rvalue::Ref(reg, bk, place) => { + let place_ty = place.ty(locals)?; + Ok(Ty::new_ref(reg.clone(), place_ty, bk.to_mutable_lossy())) + } + Rvalue::AddressOf(mutability, place) => { + let place_ty = place.ty(locals)?; + Ok(Ty::new_ptr(place_ty, *mutability)) + } + Rvalue::Len(..) => Ok(Ty::usize_ty()), + Rvalue::Cast(.., ty) => Ok(*ty), + Rvalue::BinaryOp(op, lhs, rhs) => { + let lhs_ty = lhs.ty(locals)?; + let rhs_ty = rhs.ty(locals)?; + Ok(op.ty(lhs_ty, rhs_ty)) + } + Rvalue::CheckedBinaryOp(op, lhs, rhs) => { + let lhs_ty = lhs.ty(locals)?; + let rhs_ty = rhs.ty(locals)?; + let ty = op.ty(lhs_ty, rhs_ty); + Ok(Ty::new_tuple(&[ty, Ty::bool_ty()])) + } + Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, operand) => operand.ty(locals), + Rvalue::Discriminant(place) => { + let place_ty = place.ty(locals)?; + place_ty + .kind() + .discriminant_ty() + .ok_or_else(|| error!("Expected a `RigidTy` but found: {place_ty:?}")) + } + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { + Ok(Ty::usize_ty()) + } + Rvalue::Aggregate(ak, ops) => match *ak { + AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64), + AggregateKind::Tuple => Ok(Ty::new_tuple( + &ops.iter().map(|op| op.ty(locals)).collect::, _>>()?, + )), + AggregateKind::Adt(def, _, ref args, _, _) => Ok(def.ty_with_args(args)), + AggregateKind::Closure(def, ref args) => Ok(Ty::new_closure(def, args.clone())), + AggregateKind::Coroutine(def, ref args, mov) => { + Ok(Ty::new_coroutine(def, args.clone(), mov)) + } + }, + Rvalue::ShallowInitBox(_, ty) => Ok(Ty::new_box(*ty)), + Rvalue::CopyForDeref(place) => place.ty(locals), + } + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub enum AggregateKind { Array(Ty), @@ -398,23 +584,170 @@ pub enum Operand { pub struct Place { pub local: Local, /// projection out of a place (access a field, deref a pointer, etc) - pub projection: String, + pub projection: Vec, +} + +impl From for Place { + fn from(local: Local) -> Self { + Place { local, projection: vec![] } + } +} + +/// Debug information pertaining to a user variable. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct VarDebugInfo { + /// The variable name. + pub name: Symbol, + + /// Source info of the user variable, including the scope + /// within which the variable is visible (to debuginfo). + pub source_info: SourceInfo, + + /// The user variable's data is split across several fragments, + /// each described by a `VarDebugInfoFragment`. + pub composite: Option, + + /// Where the data for this user variable is to be found. + pub value: VarDebugInfoContents, + + /// When present, indicates what argument number this variable is in the function that it + /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the + /// argument number in the original function before it was inlined. + pub argument_index: Option, +} + +pub type SourceScope = u32; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct SourceInfo { + pub span: Span, + pub scope: SourceScope, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct VarDebugInfoFragment { + pub ty: Ty, + pub projection: Vec, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum VarDebugInfoContents { + Place(Place), + Const(ConstOperand), +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ConstOperand { + pub span: Span, + pub user_ty: Option, + pub const_: Const, +} + +// In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This +// is so it can be used for both Places (for which the projection elements are of type +// ProjectionElem) and user-provided type annotations (for which the projection elements +// are of type ProjectionElem<(), ()>). In SMIR we don't need this generality, so we just use +// ProjectionElem for Places. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ProjectionElem { + /// Dereference projections (e.g. `*_1`) project to the address referenced by the base place. + Deref, + + /// A field projection (e.g., `f` in `_1.f`) project to a field in the base place. The field is + /// referenced by source-order index rather than the name of the field. The fields type is also + /// given. + Field(FieldIdx, Ty), + + /// Index into a slice/array. The value of the index is computed at runtime using the `V` + /// argument. + /// + /// Note that this does not also dereference, and so it does not exactly correspond to slice + /// indexing in Rust. In other words, in the below Rust code: + /// + /// ```rust + /// let x = &[1, 2, 3, 4]; + /// let i = 2; + /// x[i]; + /// ``` + /// + /// The `x[i]` is turned into a `Deref` followed by an `Index`, not just an `Index`. The same + /// thing is true of the `ConstantIndex` and `Subslice` projections below. + Index(Local), + + /// Index into a slice/array given by offsets. + /// + /// These indices are generated by slice patterns. Easiest to explain by example: + /// + /// ```ignore (illustrative) + /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false }, + /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false }, + /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true }, + /// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true }, + /// ``` + ConstantIndex { + /// index or -index (in Python terms), depending on from_end + offset: u64, + /// The thing being indexed must be at least this long. For arrays this + /// is always the exact length. + min_length: u64, + /// Counting backwards from end? This is always false when indexing an + /// array. + from_end: bool, + }, + + /// Projects a slice from the base place. + /// + /// These indices are generated by slice patterns. If `from_end` is true, this represents + /// `slice[from..slice.len() - to]`. Otherwise it represents `array[from..to]`. + Subslice { + from: u64, + to: u64, + /// Whether `to` counts from the start or end of the array/slice. + from_end: bool, + }, + + /// "Downcast" to a variant of an enum or a coroutine. + Downcast(VariantIdx), + + /// Like an explicit cast from an opaque type to a concrete type, but without + /// requiring an intermediate variable. + OpaqueCast(Ty), + + /// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where + /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping + /// explicit during optimizations and codegen. + /// + /// This projection doesn't impact the runtime behavior of the program except for potentially changing + /// some type metadata of the interpreter or codegen backend. + Subtype(Ty), } #[derive(Clone, Debug, Eq, PartialEq)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, - pub projection: String, + + pub projection: Opaque, } pub type Local = usize; pub const RETURN_LOCAL: Local = 0; -type FieldIdx = usize; - -/// The source-order index of a variant in a type. -pub type VariantIdx = usize; +/// The source-order index of a field in a variant. +/// +/// For example, in the following types, +/// ```ignore(illustrative) +/// enum Demo1 { +/// Variant0 { a: bool, b: i32 }, +/// Variant1 { c: u8, d: u64 }, +/// } +/// struct Demo2 { e: u8, f: u16, g: u8 } +/// ``` +/// `a`'s `FieldIdx` is `0`, +/// `b`'s `FieldIdx` is `1`, +/// `c`'s `FieldIdx` is `0`, and +/// `g`'s `FieldIdx` is `2`. +pub type FieldIdx = usize; type UserTypeAnnotationIndex = usize; @@ -425,21 +758,54 @@ pub struct Constant { pub literal: Const, } +/// The possible branch sites of a [TerminatorKind::SwitchInt]. #[derive(Clone, Debug, Eq, PartialEq)] -pub struct SwitchTarget { - pub value: u128, - pub target: usize, +pub struct SwitchTargets { + /// The conditional branches where the first element represents the value that guards this + /// branch, and the second element is the branch target. + branches: Vec<(u128, BasicBlockIdx)>, + /// The `otherwise` branch which will be taken in case none of the conditional branches are + /// satisfied. + otherwise: BasicBlockIdx, +} + +impl SwitchTargets { + /// All possible targets including the `otherwise` target. + pub fn all_targets(&self) -> Successors { + self.branches.iter().map(|(_, target)| *target).chain(Some(self.otherwise)).collect() + } + + /// The `otherwise` branch target. + pub fn otherwise(&self) -> BasicBlockIdx { + self.otherwise + } + + /// The conditional targets which are only taken if the pattern matches the given value. + pub fn branches(&self) -> impl Iterator + '_ { + self.branches.iter().copied() + } + + /// The number of targets including `otherwise`. + pub fn len(&self) -> usize { + self.branches.len() + 1 + } + + /// Create a new SwitchTargets from the given branches and `otherwise` target. + pub fn new(branches: Vec<(u128, BasicBlockIdx)>, otherwise: BasicBlockIdx) -> SwitchTargets { + SwitchTargets { branches, otherwise } + } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum BorrowKind { /// Data must be immutable and is aliasable. Shared, /// The immediately borrowed place must be immutable, but projections from - /// it don't need to be. For example, a shallow borrow of `a.b` doesn't + /// it don't need to be. This is used to prevent match guards from replacing + /// the scrutinee. For example, a fake borrow of `a.b` doesn't /// conflict with a mutable borrow of `a.b.c`. - Shallow, + Fake, /// Data is mutable and not aliasable. Mut { @@ -448,14 +814,25 @@ pub enum BorrowKind { }, } -#[derive(Clone, Debug, Eq, PartialEq)] +impl BorrowKind { + pub fn to_mutable_lossy(self) -> Mutability { + match self { + BorrowKind::Mut { .. } => Mutability::Mut, + BorrowKind::Shared => Mutability::Not, + // FIXME: There's no type corresponding to a shallow borrow, so use `&` as an approximation. + BorrowKind::Fake => Mutability::Not, + } + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum MutBorrowKind { Default, TwoPhaseBorrow, ClosureCapture, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Mutability { Not, Mut, @@ -520,10 +897,16 @@ pub enum NullOp { } impl Operand { - pub fn ty(&self, locals: &[LocalDecl]) -> Ty { + /// Get the type of an operand relative to the local declaration. + /// + /// In order to retrieve the correct type, the `locals` argument must match the list of all + /// locals from the function body where this operand originates from. + /// + /// Errors indicate a malformed operand or incompatible locals list. + pub fn ty(&self, locals: &[LocalDecl]) -> Result { match self { Operand::Copy(place) | Operand::Move(place) => place.ty(locals), - Operand::Constant(c) => c.ty(), + Operand::Constant(c) => Ok(c.ty()), } } } @@ -535,8 +918,57 @@ impl Constant { } impl Place { - pub fn ty(&self, locals: &[LocalDecl]) -> Ty { - let _start_ty = locals[self.local].ty; - todo!("Implement projection") + /// Resolve down the chain of projections to get the type referenced at the end of it. + /// E.g.: + /// Calling `ty()` on `var.field` should return the type of `field`. + /// + /// In order to retrieve the correct type, the `locals` argument must match the list of all + /// locals from the function body where this place originates from. + pub fn ty(&self, locals: &[LocalDecl]) -> Result { + let start_ty = locals[self.local].ty; + self.projection.iter().fold(Ok(start_ty), |place_ty, elem| { + let ty = place_ty?; + match elem { + ProjectionElem::Deref => Self::deref_ty(ty), + ProjectionElem::Field(_idx, fty) => Ok(*fty), + ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => { + Self::index_ty(ty) + } + ProjectionElem::Subslice { from, to, from_end } => { + Self::subslice_ty(ty, from, to, from_end) + } + ProjectionElem::Downcast(_) => Ok(ty), + ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty), + } + }) + } + + fn index_ty(ty: Ty) -> Result { + ty.kind().builtin_index().ok_or_else(|| error!("Cannot index non-array type: {ty:?}")) + } + + fn subslice_ty(ty: Ty, from: &u64, to: &u64, from_end: &bool) -> Result { + let ty_kind = ty.kind(); + match ty_kind { + TyKind::RigidTy(RigidTy::Slice(..)) => Ok(ty), + TyKind::RigidTy(RigidTy::Array(inner, _)) if !from_end => Ty::try_new_array( + inner, + to.checked_sub(*from).ok_or_else(|| error!("Subslice overflow: {from}..{to}"))?, + ), + TyKind::RigidTy(RigidTy::Array(inner, size)) => { + let size = size.eval_target_usize()?; + let len = size - from - to; + Ty::try_new_array(inner, len) + } + _ => Err(Error(format!("Cannot subslice non-array type: `{ty_kind:?}`"))), + } + } + + fn deref_ty(ty: Ty) -> Result { + let deref_ty = ty + .kind() + .builtin_deref(true) + .ok_or_else(|| error!("Cannot dereference type: {ty:?}"))?; + Ok(deref_ty.ty) } } diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 8f533349848e2..5c27f9281de65 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -1,16 +1,17 @@ +use crate::crate_def::CrateDef; use crate::mir::Body; -use crate::ty::{FnDef, GenericArgs, IndexedVal, Ty}; -use crate::{with, CrateItem, DefId, Error, Opaque}; -use std::fmt::Debug; +use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, FnSig, GenericArgs, IndexedVal, Ty}; +use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque, Symbol}; +use std::fmt::{Debug, Formatter}; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum MonoItem { Fn(Instance), Static(StaticDef), GlobalAsm(Opaque), } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Instance { /// The type of instance. pub kind: InstanceKind, @@ -19,33 +20,65 @@ pub struct Instance { pub def: InstanceDef, } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum InstanceKind { /// A user defined item. Item, /// A compiler intrinsic function. Intrinsic, /// A virtual function definition stored in a VTable. - Virtual, + /// The `idx` field indicates the position in the VTable for this instance. + Virtual { idx: usize }, /// A compiler generated shim. Shim, } impl Instance { /// Get the body of an Instance. The body will be eagerly monomorphized. - pub fn body(&self) -> Body { + pub fn body(&self) -> Option { with(|context| context.instance_body(self.def)) } + /// Check whether this instance has a body available. + /// + /// This call is much cheaper than `instance.body().is_some()`, since it doesn't try to build + /// the StableMIR body. + pub fn has_body(&self) -> bool { + with(|cx| cx.has_body(self.def.def_id())) + } + + pub fn is_foreign_item(&self) -> bool { + with(|cx| cx.is_foreign_item(self.def.def_id())) + } + /// Get the instance type with generic substitutions applied and lifetimes erased. pub fn ty(&self) -> Ty { with(|context| context.instance_ty(self.def)) } - pub fn mangled_name(&self) -> String { + /// Retrieve the instance's mangled name used for calling the given instance. + /// + /// This will also look up the correct name of instances from upstream crates. + pub fn mangled_name(&self) -> Symbol { with(|context| context.instance_mangled_name(self.def)) } + /// Retrieve the instance name for diagnostic messages. + /// + /// This will return the specialized name, e.g., `std::vec::Vec::new`. + pub fn name(&self) -> Symbol { + with(|context| context.instance_name(self.def, false)) + } + + /// Return a trimmed name of the given instance including its args. + /// + /// If a symbol name can only be imported from one place for a type, and as + /// long as it was not glob-imported anywhere in the current crate, we trim its + /// path and print only the name. + pub fn trimmed_name(&self) -> Symbol { + with(|context| context.instance_name(self.def, true)) + } + /// Resolve an instance starting from a function definition and generic arguments. pub fn resolve(def: FnDef, args: &GenericArgs) -> Result { with(|context| { @@ -54,6 +87,60 @@ impl Instance { }) }) } + + /// Resolve the drop in place for a given type. + pub fn resolve_drop_in_place(ty: Ty) -> Instance { + with(|cx| cx.resolve_drop_in_place(ty)) + } + + /// Resolve an instance for a given function pointer. + pub fn resolve_for_fn_ptr(def: FnDef, args: &GenericArgs) -> Result { + with(|context| { + context.resolve_for_fn_ptr(def, args).ok_or_else(|| { + crate::Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`")) + }) + }) + } + + /// Resolve a closure with the expected kind. + pub fn resolve_closure( + def: ClosureDef, + args: &GenericArgs, + kind: ClosureKind, + ) -> Result { + with(|context| { + context.resolve_closure(def, args, kind).ok_or_else(|| { + crate::Error::new(format!("Failed to resolve `{def:?}` with `{args:?}`")) + }) + }) + } + + /// Get this function signature with all types already instantiated. + pub fn fn_sig(&self) -> FnSig { + self.ty().kind().fn_sig().unwrap().skip_binder() + } + + /// Check whether this instance is an empty shim. + /// + /// Allow users to check if this shim can be ignored when called directly. + /// + /// We have decided not to export different types of Shims to StableMIR users, however, this + /// is a query that can be very helpful for users when processing DropGlue. + /// + /// When generating code for a Drop terminator, users can ignore an empty drop glue. + /// These shims are only needed to generate a valid Drop call done via VTable. + pub fn is_empty_shim(&self) -> bool { + self.kind == InstanceKind::Shim && with(|cx| cx.is_empty_drop_shim(self.def)) + } +} + +impl Debug for Instance { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Instance") + .field("kind", &self.kind) + .field("def", &self.mangled_name()) + .finish() + } } /// Try to convert a crate item into an instance. @@ -63,8 +150,9 @@ impl TryFrom for Instance { fn try_from(item: CrateItem) -> Result { with(|context| { - if !context.requires_monomorphization(item.0) { - Ok(context.mono_instance(item)) + let def_id = item.def_id(); + if !context.requires_monomorphization(def_id) { + Ok(context.mono_instance(def_id)) } else { Err(Error::new("Item requires monomorphization".to_string())) } @@ -78,19 +166,86 @@ impl TryFrom for CrateItem { type Error = crate::Error; fn try_from(value: Instance) -> Result { - if value.kind == InstanceKind::Item { - Ok(CrateItem(with(|context| context.instance_def_id(value.def)))) + with(|context| { + if value.kind == InstanceKind::Item && context.has_body(value.def.def_id()) { + Ok(CrateItem(context.instance_def_id(value.def))) + } else { + Err(Error::new(format!("Item kind `{:?}` cannot be converted", value.kind))) + } + }) + } +} + +impl From for MonoItem { + fn from(value: Instance) -> Self { + MonoItem::Fn(value) + } +} + +impl From for MonoItem { + fn from(value: StaticDef) -> Self { + MonoItem::Static(value) + } +} + +impl From for CrateItem { + fn from(value: StaticDef) -> Self { + CrateItem(value.0) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct InstanceDef(usize); + +impl CrateDef for InstanceDef { + fn def_id(&self) -> DefId { + with(|context| context.instance_def_id(*self)) + } +} + +crate_def! { + /// Holds information about a static variable definition. + pub StaticDef; +} + +impl TryFrom for StaticDef { + type Error = crate::Error; + + fn try_from(value: CrateItem) -> Result { + if matches!(value.kind(), ItemKind::Static | ItemKind::Const) { + Ok(StaticDef(value.0)) } else { - Err(Error::new(format!("Item kind `{:?}` cannot be converted", value.kind))) + Err(Error::new(format!("Expected a static item, but found: {value:?}"))) } } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct InstanceDef(usize); +impl TryFrom for StaticDef { + type Error = crate::Error; + + fn try_from(value: Instance) -> Result { + StaticDef::try_from(CrateItem::try_from(value)?) + } +} -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct StaticDef(pub DefId); +impl From for Instance { + fn from(value: StaticDef) -> Self { + // A static definition should always be convertible to an instance. + with(|cx| cx.mono_instance(value.def_id())) + } +} + +impl StaticDef { + /// Return the type of this static definition. + pub fn ty(&self) -> Ty { + with(|cx| cx.def_ty(self.0)) + } + + /// Evaluate a static's initializer, returning the allocation of the initializer's memory. + pub fn eval_initializer(&self) -> Result { + with(|cx| cx.eval_static_initializer(*self)) + } +} impl IndexedVal for InstanceDef { fn to_val(index: usize) -> Self { diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs new file mode 100644 index 0000000000000..3a0eed521dc6e --- /dev/null +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -0,0 +1,467 @@ +use crate::crate_def::CrateDef; +use crate::mir::{Operand, Rvalue, StatementKind, UnwindAction}; +use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy}; +use crate::{with, Body, CrateItem, Mutability}; +use std::io::Write; +use std::{io, iter}; + +use super::{AssertMessage, BinOp, TerminatorKind}; + +pub fn function_name(item: CrateItem) -> String { + let mut pretty_name = String::new(); + let body = item.body(); + pretty_name.push_str("fn "); + pretty_name.push_str(item.name().as_str()); + if body.arg_locals().is_empty() { + pretty_name.push_str("()"); + } else { + pretty_name.push_str("("); + } + body.arg_locals().iter().enumerate().for_each(|(index, local)| { + pretty_name.push_str(format!("_{}: ", index).as_str()); + pretty_name.push_str(&pretty_ty(local.ty.kind())); + }); + if !body.arg_locals().is_empty() { + pretty_name.push_str(")"); + } + let return_local = body.ret_local(); + pretty_name.push_str(" -> "); + pretty_name.push_str(&pretty_ty(return_local.ty.kind())); + pretty_name.push_str(" {"); + pretty_name +} + +pub fn function_body(body: &Body) -> String { + let mut pretty_body = String::new(); + body.inner_locals().iter().enumerate().for_each(|(index, local)| { + pretty_body.push_str(" "); + pretty_body.push_str(format!("let {}", ret_mutability(&local.mutability)).as_str()); + pretty_body.push_str(format!("_{}: ", index).as_str()); + pretty_body.push_str(format!("{}", pretty_ty(local.ty.kind())).as_str()); + pretty_body.push_str(";\n"); + }); + pretty_body.push_str("}"); + pretty_body +} + +pub fn ret_mutability(mutability: &Mutability) -> String { + match mutability { + Mutability::Not => "".to_string(), + Mutability::Mut => "mut ".to_string(), + } +} + +pub fn pretty_statement(statement: &StatementKind) -> String { + let mut pretty = String::new(); + match statement { + StatementKind::Assign(place, rval) => { + pretty.push_str(format!(" _{} = ", place.local).as_str()); + pretty.push_str(format!("{}", &pretty_rvalue(rval)).as_str()); + } + StatementKind::FakeRead(_, _) => todo!(), + StatementKind::SetDiscriminant { .. } => todo!(), + StatementKind::Deinit(_) => todo!(), + StatementKind::StorageLive(_) => todo!(), + StatementKind::StorageDead(_) => todo!(), + StatementKind::Retag(_, _) => todo!(), + StatementKind::PlaceMention(_) => todo!(), + StatementKind::AscribeUserType { .. } => todo!(), + StatementKind::Coverage(_) => todo!(), + StatementKind::Intrinsic(_) => todo!(), + StatementKind::ConstEvalCounter => (), + StatementKind::Nop => (), + } + pretty +} + +pub fn pretty_terminator(terminator: &TerminatorKind, w: &mut W) -> io::Result<()> { + write!(w, "{}", pretty_terminator_head(terminator))?; + let successors = terminator.successors(); + let successor_count = successors.len(); + let labels = pretty_successor_labels(terminator); + + let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_))); + let fmt_unwind = |fmt: &mut dyn Write| -> io::Result<()> { + write!(fmt, "unwind ")?; + match terminator.unwind() { + None | Some(UnwindAction::Cleanup(_)) => unreachable!(), + Some(UnwindAction::Continue) => write!(fmt, "continue"), + Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"), + Some(UnwindAction::Terminate) => write!(fmt, "terminate"), + } + }; + + match (successor_count, show_unwind) { + (0, false) => Ok(()), + (0, true) => { + write!(w, " -> ")?; + fmt_unwind(w)?; + Ok(()) + } + (1, false) => { + write!(w, " -> {:?}", successors[0])?; + Ok(()) + } + _ => { + write!(w, " -> [")?; + for (i, target) in successors.iter().enumerate() { + if i > 0 { + write!(w, ", ")?; + } + write!(w, "{}: bb{:?}", labels[i], target)?; + } + if show_unwind { + write!(w, ", ")?; + fmt_unwind(w)?; + } + write!(w, "]") + } + }?; + + Ok(()) +} + +pub fn pretty_terminator_head(terminator: &TerminatorKind) -> String { + use self::TerminatorKind::*; + let mut pretty = String::new(); + match terminator { + Goto { .. } => format!(" goto"), + SwitchInt { discr, .. } => { + format!(" switchInt(_{})", pretty_operand(discr)) + } + Resume => format!(" resume"), + Abort => format!(" abort"), + Return => format!(" return"), + Unreachable => format!(" unreachable"), + Drop { place, .. } => format!(" drop(_{:?})", place.local), + Call { func, args, destination, .. } => { + pretty.push_str(" "); + pretty.push_str(format!("_{} = ", destination.local).as_str()); + pretty.push_str(&pretty_operand(func)); + pretty.push_str("("); + args.iter().enumerate().for_each(|(i, arg)| { + if i > 0 { + pretty.push_str(", "); + } + pretty.push_str(&pretty_operand(arg)); + }); + pretty.push_str(")"); + pretty + } + Assert { cond, expected, msg, target: _, unwind: _ } => { + pretty.push_str(" assert("); + if !expected { + pretty.push_str("!"); + } + pretty.push_str(format!("{} bool),", &pretty_operand(cond)).as_str()); + pretty.push_str(&pretty_assert_message(msg)); + pretty.push_str(")"); + pretty + } + InlineAsm { .. } => todo!(), + } +} + +pub fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec { + use self::TerminatorKind::*; + match terminator { + Resume | Abort | Return | Unreachable => vec![], + Goto { .. } => vec!["".to_string()], + SwitchInt { targets, .. } => targets + .branches() + .map(|(val, _target)| format!("{val}")) + .chain(iter::once("otherwise".into())) + .collect(), + Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()], + Drop { unwind: _, .. } => vec!["return".into()], + Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { + vec!["return".into(), "unwind".into()] + } + Call { target: Some(_), unwind: _, .. } => vec!["return".into()], + Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()], + Call { target: None, unwind: _, .. } => vec![], + Assert { unwind: UnwindAction::Cleanup(_), .. } => { + vec!["success".into(), "unwind".into()] + } + Assert { unwind: _, .. } => vec!["success".into()], + InlineAsm { .. } => todo!(), + } +} + +pub fn pretty_assert_message(msg: &AssertMessage) -> String { + let mut pretty = String::new(); + match msg { + AssertMessage::BoundsCheck { len, index } => { + let pretty_len = pretty_operand(len); + let pretty_index = pretty_operand(index); + pretty.push_str(format!("\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Add, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Sub, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Mul, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Div, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Rem, l, r) => { + let pretty_l = pretty_operand(l); + let pretty_r = pretty_operand(r); + pretty.push_str(format!("\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str()); + pretty + } + AssertMessage::Overflow(BinOp::Shr, _, r) => { + let pretty_r = pretty_operand(r); + pretty.push_str( + format!("\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}") + .as_str(), + ); + pretty + } + AssertMessage::Overflow(BinOp::Shl, _, r) => { + let pretty_r = pretty_operand(r); + pretty.push_str( + format!("\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}") + .as_str(), + ); + pretty + } + AssertMessage::OverflowNeg(op) => { + let pretty_op = pretty_operand(op); + pretty.push_str( + format!("\"attempt to negate `{{}}`, which would overflow\", {pretty_op}").as_str(), + ); + pretty + } + AssertMessage::DivisionByZero(op) => { + let pretty_op = pretty_operand(op); + pretty.push_str(format!("\"attempt to divide `{{}}` by zero\", {pretty_op}").as_str()); + pretty + } + AssertMessage::RemainderByZero(op) => { + let pretty_op = pretty_operand(op); + pretty.push_str( + format!("\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}").as_str(), + ); + pretty + } + AssertMessage::ResumedAfterReturn(_) => { + format!("attempt to resume a generator after completion") + } + AssertMessage::ResumedAfterPanic(_) => format!("attempt to resume a panicked generator"), + AssertMessage::MisalignedPointerDereference { required, found } => { + let pretty_required = pretty_operand(required); + let pretty_found = pretty_operand(found); + pretty.push_str(format!("\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}").as_str()); + pretty + } + _ => todo!(), + } +} + +pub fn pretty_operand(operand: &Operand) -> String { + let mut pretty = String::new(); + match operand { + Operand::Copy(copy) => { + pretty.push_str(""); + pretty.push_str(format!("{}", copy.local).as_str()); + } + Operand::Move(mv) => { + pretty.push_str("move "); + pretty.push_str(format!("_{}", mv.local).as_str()); + } + Operand::Constant(cnst) => { + pretty.push_str("const "); + pretty.push_str(with(|cx| cx.const_literal(&cnst.literal)).as_str()); + } + } + pretty +} + +pub fn pretty_rvalue(rval: &Rvalue) -> String { + let mut pretty = String::new(); + match rval { + Rvalue::AddressOf(muta, addr) => { + pretty.push_str("&raw "); + pretty.push_str(&ret_mutability(muta)); + pretty.push_str(format!("(*_{})", addr.local).as_str()); + } + Rvalue::Aggregate(aggregatekind, operands) => { + pretty.push_str(format!("{:#?}", aggregatekind).as_str()); + pretty.push_str("("); + operands.iter().enumerate().for_each(|(i, op)| { + pretty.push_str(&pretty_operand(op)); + if i != operands.len() - 1 { + pretty.push_str(", "); + } + }); + pretty.push_str(")"); + } + Rvalue::BinaryOp(bin, op, op2) => { + pretty.push_str(&pretty_operand(op)); + pretty.push_str(" "); + pretty.push_str(format!("{:#?}", bin).as_str()); + pretty.push_str(" "); + pretty.push_str(&pretty_operand(op2)); + } + Rvalue::Cast(_, op, ty) => { + pretty.push_str(&pretty_operand(op)); + pretty.push_str(" as "); + pretty.push_str(&pretty_ty(ty.kind())); + } + Rvalue::CheckedBinaryOp(bin, op1, op2) => { + pretty.push_str(&pretty_operand(op1)); + pretty.push_str(" "); + pretty.push_str(format!("{:#?}", bin).as_str()); + pretty.push_str(" "); + pretty.push_str(&pretty_operand(op2)); + } + Rvalue::CopyForDeref(deref) => { + pretty.push_str("CopyForDeref"); + pretty.push_str(format!("{}", deref.local).as_str()); + } + Rvalue::Discriminant(place) => { + pretty.push_str("discriminant"); + pretty.push_str(format!("{}", place.local).as_str()); + } + Rvalue::Len(len) => { + pretty.push_str("len"); + pretty.push_str(format!("{}", len.local).as_str()); + } + Rvalue::Ref(_, borrowkind, place) => { + pretty.push_str("ref"); + pretty.push_str(format!("{:#?}", borrowkind).as_str()); + pretty.push_str(format!("{}", place.local).as_str()); + } + Rvalue::Repeat(op, cnst) => { + pretty.push_str(&pretty_operand(op)); + pretty.push_str(" "); + pretty.push_str(&pretty_ty(cnst.ty().kind())); + } + Rvalue::ShallowInitBox(_, _) => todo!(), + Rvalue::ThreadLocalRef(item) => { + pretty.push_str("thread_local_ref"); + pretty.push_str(format!("{:#?}", item).as_str()); + } + Rvalue::NullaryOp(nul, ty) => { + pretty.push_str(format!("{:#?}", nul).as_str()); + pretty.push_str(&pretty_ty(ty.kind())); + pretty.push_str(" "); + } + Rvalue::UnaryOp(un, op) => { + pretty.push_str(&pretty_operand(op)); + pretty.push_str(" "); + pretty.push_str(format!("{:#?}", un).as_str()); + } + Rvalue::Use(op) => pretty.push_str(&pretty_operand(op)), + } + pretty +} + +pub fn pretty_ty(ty: TyKind) -> String { + let mut pretty = String::new(); + match ty { + TyKind::RigidTy(rigid_ty) => match rigid_ty { + RigidTy::Bool => "bool".to_string(), + RigidTy::Char => "char".to_string(), + RigidTy::Int(i) => match i { + IntTy::Isize => "isize".to_string(), + IntTy::I8 => "i8".to_string(), + IntTy::I16 => "i16".to_string(), + IntTy::I32 => "i32".to_string(), + IntTy::I64 => "i64".to_string(), + IntTy::I128 => "i128".to_string(), + }, + RigidTy::Uint(u) => match u { + UintTy::Usize => "usize".to_string(), + UintTy::U8 => "u8".to_string(), + UintTy::U16 => "u16".to_string(), + UintTy::U32 => "u32".to_string(), + UintTy::U64 => "u64".to_string(), + UintTy::U128 => "u128".to_string(), + }, + RigidTy::Float(f) => match f { + FloatTy::F32 => "f32".to_string(), + FloatTy::F64 => "f64".to_string(), + }, + RigidTy::Adt(def, _) => { + format!("{:#?}", with(|cx| cx.def_ty(def.0))) + } + RigidTy::Str => "str".to_string(), + RigidTy::Array(ty, len) => { + format!("[{}; {}]", pretty_ty(ty.kind()), with(|cx| cx.const_literal(&len))) + } + RigidTy::Slice(ty) => { + format!("[{}]", pretty_ty(ty.kind())) + } + RigidTy::RawPtr(ty, mutability) => { + pretty.push_str("*"); + match mutability { + Mutability::Not => pretty.push_str("const "), + Mutability::Mut => pretty.push_str("mut "), + } + pretty.push_str(&pretty_ty(ty.kind())); + pretty + } + RigidTy::Ref(_, ty, mutability) => match mutability { + Mutability::Not => format!("&{}", pretty_ty(ty.kind())), + Mutability::Mut => format!("&mut {}", pretty_ty(ty.kind())), + }, + RigidTy::FnDef(_, _) => format!("{:#?}", rigid_ty), + RigidTy::FnPtr(_) => format!("{:#?}", rigid_ty), + RigidTy::Closure(_, _) => format!("{:#?}", rigid_ty), + RigidTy::Coroutine(_, _, _) => format!("{:#?}", rigid_ty), + RigidTy::Dynamic(data, region, repr) => { + // FIXME: Fix binder printing, it looks ugly now + pretty.push_str("("); + match repr { + DynKind::Dyn => pretty.push_str("dyn "), + DynKind::DynStar => pretty.push_str("dyn* "), + } + pretty.push_str(format!("{:#?}", data).as_str()); + pretty.push_str(format!(" + {:#?} )", region).as_str()); + pretty + } + RigidTy::Never => "!".to_string(), + RigidTy::Tuple(tuple) => { + if tuple.is_empty() { + "()".to_string() + } else { + let mut tuple_str = String::new(); + tuple_str.push_str("("); + tuple.iter().enumerate().for_each(|(i, ty)| { + tuple_str.push_str(&pretty_ty(ty.kind())); + if i != tuple.len() - 1 { + tuple_str.push_str(", "); + } + }); + tuple_str.push_str(")"); + tuple_str + } + } + _ => format!("{:#?}", rigid_ty), + }, + TyKind::Alias(_, _) => format!("{:#?}", ty), + TyKind::Param(param_ty) => { + format!("{:#?}", param_ty.name) + } + TyKind::Bound(_, _) => format!("{:#?}", ty), + } +} diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 806dced71ff3e..d46caad9a016b 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -76,6 +76,15 @@ pub trait MirVisitor { self.super_place(place, ptx, location) } + fn visit_projection_elem( + &mut self, + elem: &ProjectionElem, + ptx: PlaceContext, + location: Location, + ) { + self.super_projection_elem(elem, ptx, location); + } + fn visit_local(&mut self, local: &Local, ptx: PlaceContext, location: Location) { let _ = (local, ptx, location); } @@ -119,8 +128,12 @@ pub trait MirVisitor { self.super_assert_msg(msg, location) } + fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) { + self.super_var_debug_info(var_debug_info); + } + fn super_body(&mut self, body: &Body) { - let Body { blocks, locals: _, arg_count } = body; + let Body { blocks, locals: _, arg_count, var_debug_info } = body; for bb in blocks { self.visit_basic_block(bb); @@ -133,9 +146,13 @@ pub trait MirVisitor { } let local_start = arg_count + 1; - for (idx, arg) in body.arg_locals().iter().enumerate() { + for (idx, arg) in body.inner_locals().iter().enumerate() { self.visit_local_decl(idx + local_start, arg) } + + for info in var_debug_info.iter() { + self.visit_var_debug_info(info); + } } fn super_basic_block(&mut self, bb: &BasicBlock) { @@ -148,7 +165,7 @@ pub trait MirVisitor { fn super_local_decl(&mut self, local: Local, decl: &LocalDecl) { let _ = local; - let LocalDecl { ty, span } = decl; + let LocalDecl { ty, span, .. } = decl; self.visit_ty(ty, Location(*span)); } @@ -215,13 +232,12 @@ pub trait MirVisitor { fn super_terminator(&mut self, term: &Terminator, location: Location) { let Terminator { kind, span } = term; - self.visit_span(&span); + self.visit_span(span); match kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::Abort - | TerminatorKind::Unreachable - | TerminatorKind::CoroutineDrop => {} + | TerminatorKind::Unreachable => {} TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => { self.visit_operand(cond, location); self.visit_assert_msg(msg, location); @@ -251,7 +267,7 @@ pub trait MirVisitor { let local = RETURN_LOCAL; self.visit_local(&local, PlaceContext::NON_MUTATING, location); } - TerminatorKind::SwitchInt { discr, targets: _, otherwise: _ } => { + TerminatorKind::SwitchInt { discr, targets: _ } => { self.visit_operand(discr, location); } } @@ -264,7 +280,29 @@ pub trait MirVisitor { fn super_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) { let _ = location; let _ = ptx; - visit_opaque(&Opaque(place.projection.clone())); + self.visit_local(&place.local, ptx, location); + + for elem in &place.projection { + self.visit_projection_elem(elem, ptx, location); + } + } + + fn super_projection_elem( + &mut self, + elem: &ProjectionElem, + ptx: PlaceContext, + location: Location, + ) { + match elem { + ProjectionElem::Deref => {} + ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location), + ProjectionElem::Index(local) => self.visit_local(local, ptx, location), + ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {} + ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} + ProjectionElem::Downcast(_idx) => {} + ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location), + ProjectionElem::Subtype(ty) => self.visit_ty(ty, location), + } } fn super_rvalue(&mut self, rvalue: &Rvalue, location: Location) { @@ -351,6 +389,24 @@ pub trait MirVisitor { let _ = args; } + fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) { + let VarDebugInfo { source_info, composite, value, name: _, argument_index: _ } = + var_debug_info; + self.visit_span(&source_info.span); + let location = Location(source_info.span); + if let Some(composite) = composite { + self.visit_ty(&composite.ty, location); + } + match value { + VarDebugInfoContents::Place(place) => { + self.visit_place(place, PlaceContext::NON_USE, location); + } + VarDebugInfoContents::Const(constant) => { + self.visit_const(&constant.const_, location); + } + } + } + fn super_assert_msg(&mut self, msg: &AssertMessage, location: Location) { match msg { AssertMessage::BoundsCheck { len, index } => { @@ -386,7 +442,7 @@ pub trait MirVisitor { fn visit_opaque(_: &Opaque) {} /// The location of a statement / terminator in the code and the CFG. -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct Location(Span); impl Location { @@ -396,7 +452,7 @@ impl Location { } /// Information about a place's usage. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct PlaceContext { /// Whether the access is mutable or not. Keep this private so we can increment the type in a /// backward compatible manner. diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 5dfaa0fd89158..c922264f8a365 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -1,10 +1,12 @@ use super::{ mir::Safety, mir::{Body, Mutability}, - with, AllocId, DefId, Symbol, + with, DefId, Error, Symbol, }; +use crate::crate_def::CrateDef; +use crate::mir::alloc::AllocId; use crate::{Filename, Opaque}; -use std::fmt::{self, Debug, Formatter}; +use std::fmt::{self, Debug, Display, Formatter}; #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct Ty(pub usize); @@ -15,6 +17,66 @@ impl Debug for Ty { } } +/// Constructors for `Ty`. +impl Ty { + /// Create a new type from a given kind. + /// + /// Note that not all types may be supported at this point. + fn from_rigid_kind(kind: RigidTy) -> Ty { + with(|cx| cx.new_rigid_ty(kind)) + } + + /// Create a new array type. + pub fn try_new_array(elem_ty: Ty, size: u64) -> Result { + Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, Const::try_from_target_usize(size)?))) + } + + /// Create a new array type from Const length. + pub fn new_array_with_const_len(elem_ty: Ty, len: Const) -> Ty { + Ty::from_rigid_kind(RigidTy::Array(elem_ty, len)) + } + + /// Create a new pointer type. + pub fn new_ptr(pointee_ty: Ty, mutability: Mutability) -> Ty { + Ty::from_rigid_kind(RigidTy::RawPtr(pointee_ty, mutability)) + } + + /// Create a new reference type. + pub fn new_ref(reg: Region, pointee_ty: Ty, mutability: Mutability) -> Ty { + Ty::from_rigid_kind(RigidTy::Ref(reg, pointee_ty, mutability)) + } + + /// Create a new pointer type. + pub fn new_tuple(tys: &[Ty]) -> Ty { + Ty::from_rigid_kind(RigidTy::Tuple(Vec::from(tys))) + } + + /// Create a new closure type. + pub fn new_closure(def: ClosureDef, args: GenericArgs) -> Ty { + Ty::from_rigid_kind(RigidTy::Closure(def, args)) + } + + /// Create a new coroutine type. + pub fn new_coroutine(def: CoroutineDef, args: GenericArgs, mov: Movability) -> Ty { + Ty::from_rigid_kind(RigidTy::Coroutine(def, args, mov)) + } + + /// Create a new box type that represents `Box`, for the given inner type `T`. + pub fn new_box(inner_ty: Ty) -> Ty { + with(|cx| cx.new_box_ty(inner_ty)) + } + + /// Create a type representing `usize`. + pub fn usize_ty() -> Ty { + Ty::from_rigid_kind(RigidTy::Uint(UintTy::Usize)) + } + + /// Create a type representing `bool`. + pub fn bool_ty() -> Ty { + Ty::from_rigid_kind(RigidTy::Bool) + } +} + impl Ty { pub fn kind(&self) -> TyKind { with(|context| context.ty_kind(*self)) @@ -47,6 +109,16 @@ impl Const { pub fn ty(&self) -> Ty { self.ty } + + /// Creates an interned usize constant. + fn try_from_target_usize(val: u64) -> Result { + with(|cx| cx.usize_to_const(val)) + } + + /// Try to evaluate to a target `usize`. + pub fn eval_target_usize(&self) -> Result { + with(|cx| cx.eval_target_usize(self)) + } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -61,8 +133,8 @@ pub struct Region { #[derive(Clone, Debug, Eq, PartialEq)] pub enum RegionKind { - ReEarlyBound(EarlyBoundRegion), - ReLateBound(DebruijnIndex, BoundRegion), + ReEarlyParam(EarlyParamRegion), + ReBound(DebruijnIndex, BoundRegion), ReStatic, RePlaceholder(Placeholder), ReErased, @@ -71,7 +143,7 @@ pub enum RegionKind { pub(crate) type DebruijnIndex = u32; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct EarlyBoundRegion { +pub struct EarlyParamRegion { pub def_id: RegionDef, pub index: u32, pub name: Symbol, @@ -113,7 +185,7 @@ impl Span { /// Return lines that corespond to this `Span` pub fn get_lines(&self) -> LineInfo { - with(|c| c.get_lines(&self)) + with(|c| c.get_lines(self)) } } @@ -135,6 +207,118 @@ pub enum TyKind { Bound(usize, BoundTy), } +impl TyKind { + pub fn rigid(&self) -> Option<&RigidTy> { + if let TyKind::RigidTy(inner) = self { Some(inner) } else { None } + } + + pub fn is_unit(&self) -> bool { + matches!(self, TyKind::RigidTy(RigidTy::Tuple(data)) if data.is_empty()) + } + + pub fn is_bool(&self) -> bool { + matches!(self, TyKind::RigidTy(RigidTy::Bool)) + } + + pub fn is_trait(&self) -> bool { + matches!(self, TyKind::RigidTy(RigidTy::Dynamic(_, _, DynKind::Dyn))) + } + + pub fn is_enum(&self) -> bool { + matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Enum) + } + + pub fn is_struct(&self) -> bool { + matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Struct) + } + + pub fn is_union(&self) -> bool { + matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Union) + } + + pub fn is_fn(&self) -> bool { + matches!(self, TyKind::RigidTy(RigidTy::FnDef(..))) + } + + pub fn is_fn_ptr(&self) -> bool { + matches!(self, TyKind::RigidTy(RigidTy::FnPtr(..))) + } + + pub fn is_primitive(&self) -> bool { + matches!( + self, + TyKind::RigidTy( + RigidTy::Bool + | RigidTy::Char + | RigidTy::Int(_) + | RigidTy::Uint(_) + | RigidTy::Float(_) + ) + ) + } + + pub fn trait_principal(&self) -> Option> { + if let TyKind::RigidTy(RigidTy::Dynamic(predicates, _, _)) = self { + if let Some(Binder { value: ExistentialPredicate::Trait(trait_ref), bound_vars }) = + predicates.first() + { + Some(Binder { value: trait_ref.clone(), bound_vars: bound_vars.clone() }) + } else { + None + } + } else { + None + } + } + + /// Returns the type of `ty[i]` for builtin types. + pub fn builtin_index(&self) -> Option { + match self.rigid()? { + RigidTy::Array(ty, _) | RigidTy::Slice(ty) => Some(*ty), + _ => None, + } + } + + /// Returns the type and mutability of `*ty` for builtin types. + /// + /// The parameter `explicit` indicates if this is an *explicit* dereference. + /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly. + pub fn builtin_deref(&self, explicit: bool) -> Option { + match self.rigid()? { + RigidTy::Adt(def, args) if def.is_box() => { + Some(TypeAndMut { ty: *args.0.first()?.ty()?, mutability: Mutability::Not }) + } + RigidTy::Ref(_, ty, mutability) => { + Some(TypeAndMut { ty: *ty, mutability: *mutability }) + } + RigidTy::RawPtr(ty, mutability) if explicit => { + Some(TypeAndMut { ty: *ty, mutability: *mutability }) + } + _ => None, + } + } + + /// Get the function signature for function like types (Fn, FnPtr, Closure, Coroutine) + /// FIXME(closure) + pub fn fn_sig(&self) -> Option { + match self { + TyKind::RigidTy(RigidTy::FnDef(def, args)) => Some(with(|cx| cx.fn_sig(*def, args))), + TyKind::RigidTy(RigidTy::FnPtr(sig)) => Some(sig.clone()), + _ => None, + } + } + + /// Get the discriminant type for this type. + pub fn discriminant_ty(&self) -> Option { + self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty))) + } +} + +pub struct TypeAndMut { + pub ty: Ty, + pub mutability: Mutability, +} + #[derive(Clone, Debug, Eq, PartialEq)] pub enum RigidTy { Bool, @@ -156,6 +340,20 @@ pub enum RigidTy { Dynamic(Vec>, Region, DynKind), Never, Tuple(Vec), + CoroutineWitness(CoroutineWitnessDef, GenericArgs), +} + +impl RigidTy { + /// Get the discriminant type for this type. + pub fn discriminant_ty(&self) -> Ty { + with(|cx| cx.rigid_ty_discriminant_ty(self)) + } +} + +impl From for TyKind { + fn from(value: RigidTy) -> Self { + TyKind::RigidTy(value) + } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -190,50 +388,199 @@ pub enum Movability { Movable, } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ForeignDef(pub DefId); +crate_def! { + /// Hold information about a ForeignItem in a crate. + pub ForeignDef; +} -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct FnDef(pub DefId); +crate_def! { + /// Hold information about a function definition in a crate. + pub FnDef; +} impl FnDef { - pub fn body(&self) -> Body { - with(|ctx| ctx.mir_body(self.0)) + // Get the function body if available. + pub fn body(&self) -> Option { + with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0))) } } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ClosureDef(pub DefId); +crate_def! { + pub ClosureDef; +} -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct CoroutineDef(pub DefId); +crate_def! { + pub CoroutineDef; +} -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ParamDef(pub DefId); +crate_def! { + pub ParamDef; +} -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct BrNamedDef(pub DefId); +crate_def! { + pub BrNamedDef; +} -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AdtDef(pub DefId); +crate_def! { + pub AdtDef; +} -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AliasDef(pub DefId); +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum AdtKind { + Enum, + Union, + Struct, +} -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct TraitDef(pub DefId); +impl AdtDef { + pub fn kind(&self) -> AdtKind { + with(|cx| cx.adt_kind(*self)) + } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct GenericDef(pub DefId); + /// Retrieve the type of this Adt. + pub fn ty(&self) -> Ty { + with(|cx| cx.def_ty(self.0)) + } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ConstDef(pub DefId); + /// Retrieve the type of this Adt instantiating the type with the given arguments. + /// + /// This will assume the type can be instantiated with these arguments. + pub fn ty_with_args(&self, args: &GenericArgs) -> Ty { + with(|cx| cx.def_ty_with_args(self.0, args)) + } -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct ImplDef(pub DefId); + pub fn is_box(&self) -> bool { + with(|cx| cx.adt_is_box(*self)) + } -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct RegionDef(pub DefId); + /// The number of variants in this ADT. + pub fn num_variants(&self) -> usize { + with(|cx| cx.adt_variants_len(*self)) + } + + /// Retrieve the variants in this ADT. + pub fn variants(&self) -> Vec { + self.variants_iter().collect() + } + + /// Iterate over the variants in this ADT. + pub fn variants_iter(&self) -> impl Iterator + '_ { + (0..self.num_variants()) + .map(|idx| VariantDef { idx: VariantIdx::to_val(idx), adt_def: *self }) + } + + pub fn variant(&self, idx: VariantIdx) -> Option { + (idx.to_index() < self.num_variants()).then_some(VariantDef { idx, adt_def: *self }) + } +} + +/// Definition of a variant, which can be either a struct / union field or an enum variant. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct VariantDef { + /// The variant index. + /// + /// ## Warning + /// Do not access this field directly! + pub idx: VariantIdx, + /// The data type where this variant comes from. + /// For now, we use this to retrieve information about the variant itself so we don't need to + /// cache more information. + /// + /// ## Warning + /// Do not access this field directly! + pub adt_def: AdtDef, +} + +impl VariantDef { + pub fn name(&self) -> Symbol { + with(|cx| cx.variant_name(*self)) + } + + /// Retrieve all the fields in this variant. + // We expect user to cache this and use it directly since today it is expensive to generate all + // fields name. + pub fn fields(&self) -> Vec { + with(|cx| cx.variant_fields(*self)) + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct FieldDef { + /// The field definition. + /// + /// ## Warning + /// Do not access this field directly! This is public for the compiler to have access to it. + pub def: DefId, + + /// The field name. + pub name: Symbol, +} + +impl FieldDef { + /// Retrieve the type of this field instantiating the type with the given arguments. + /// + /// This will assume the type can be instantiated with these arguments. + pub fn ty_with_args(&self, args: &GenericArgs) -> Ty { + with(|cx| cx.def_ty_with_args(self.def, args)) + } + + /// Retrieve the type of this field. + pub fn ty(&self) -> Ty { + with(|cx| cx.def_ty(self.def)) + } +} + +impl Display for AdtKind { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str(match self { + AdtKind::Enum => "enum", + AdtKind::Union => "union", + AdtKind::Struct => "struct", + }) + } +} + +impl AdtKind { + pub fn is_enum(&self) -> bool { + matches!(self, AdtKind::Enum) + } + + pub fn is_struct(&self) -> bool { + matches!(self, AdtKind::Struct) + } + + pub fn is_union(&self) -> bool { + matches!(self, AdtKind::Union) + } +} + +crate_def! { + pub AliasDef; +} + +crate_def! { + pub TraitDef; +} + +crate_def! { + pub GenericDef; +} + +crate_def! { + pub ConstDef; +} + +crate_def! { + pub ImplDef; +} + +crate_def! { + pub RegionDef; +} + +crate_def! { + pub CoroutineWitnessDef; +} /// A list of generic arguments. #[derive(Clone, Debug, Eq, PartialEq)] @@ -282,6 +629,14 @@ impl GenericArgKind { _ => panic!("{self:?}"), } } + + /// Return the generic argument type if applicable, otherwise return `None`. + pub fn ty(&self) -> Option<&Ty> { + match self { + GenericArgKind::Type(ty) => Some(ty), + _ => None, + } + } } #[derive(Clone, Debug, Eq, PartialEq)] @@ -314,6 +669,16 @@ pub struct FnSig { pub abi: Abi, } +impl FnSig { + pub fn output(&self) -> Ty { + self.inputs_and_output[self.inputs_and_output.len() - 1] + } + + pub fn inputs(&self) -> &[Ty] { + &self.inputs_and_output[..self.inputs_and_output.len() - 1] + } +} + #[derive(Clone, PartialEq, Eq, Debug)] pub enum Abi { Rust, @@ -351,6 +716,30 @@ pub struct Binder { pub bound_vars: Vec, } +impl Binder { + pub fn skip_binder(self) -> T { + self.value + } + + pub fn map_bound_ref(&self, f: F) -> Binder + where + F: FnOnce(&T) -> U, + { + let Binder { value, bound_vars } = self; + let new_value = f(value); + Binder { value: new_value, bound_vars: bound_vars.clone() } + } + + pub fn map_bound(self, f: F) -> Binder + where + F: FnOnce(T) -> U, + { + let Binder { value, bound_vars } = self; + let new_value = f(value); + Binder { value: new_value, bound_vars } + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct EarlyBinder { pub value: T, @@ -389,12 +778,27 @@ pub enum ExistentialPredicate { AutoTrait(TraitDef), } +/// An existential reference to a trait where `Self` is not included. +/// +/// The `generic_args` will include any other known argument. #[derive(Clone, Debug, Eq, PartialEq)] pub struct ExistentialTraitRef { pub def_id: TraitDef, pub generic_args: GenericArgs, } +impl Binder { + pub fn with_self_ty(&self, self_ty: Ty) -> Binder { + self.map_bound_ref(|trait_ref| trait_ref.with_self_ty(self_ty)) + } +} + +impl ExistentialTraitRef { + pub fn with_self_ty(&self, self_ty: Ty) -> TraitRef { + TraitRef::new(self.def_id, self_ty, &self.generic_args) + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct ExistentialProjection { pub def_id: TraitDef, @@ -500,10 +904,39 @@ impl TraitDecl { pub type ImplTrait = EarlyBinder; +/// A complete reference to a trait, i.e., one where `Self` is known. #[derive(Clone, Debug, Eq, PartialEq)] pub struct TraitRef { pub def_id: TraitDef, - pub args: GenericArgs, + /// The generic arguments for this definition. + /// The first element must always be type, and it represents `Self`. + args: GenericArgs, +} + +impl TraitRef { + pub fn new(def_id: TraitDef, self_ty: Ty, gen_args: &GenericArgs) -> TraitRef { + let mut args = vec![GenericArgKind::Type(self_ty)]; + args.extend_from_slice(&gen_args.0); + TraitRef { def_id, args: GenericArgs(args) } + } + + pub fn try_new(def_id: TraitDef, args: GenericArgs) -> Result { + match &args.0[..] { + [GenericArgKind::Type(_), ..] => Ok(TraitRef { def_id, args }), + _ => Err(()), + } + } + + pub fn args(&self) -> &GenericArgs { + &self.args + } + + pub fn self_ty(&self) -> Ty { + let GenericArgKind::Type(self_ty) = self.args.0[0] else { + panic!("Self must be a type, but found: {:?}", self.args.0[0]) + }; + self_ty + } } #[derive(Clone, Debug, Eq, PartialEq)] @@ -542,7 +975,6 @@ pub struct GenericPredicates { pub enum PredicateKind { Clause(ClauseKind), ObjectSafe(TraitDef), - ClosureKind(ClosureDef, GenericArgs, ClosureKind), SubType(SubtypePredicate), Coerce(CoercePredicate), ConstEquate(Const, Const), @@ -633,3 +1065,21 @@ macro_rules! index_impl { index_impl!(ConstId); index_impl!(Ty); index_impl!(Span); + +/// The source-order index of a variant in a type. +/// +/// For example, in the following types, +/// ```ignore(illustrative) +/// enum Demo1 { +/// Variant0 { a: bool, b: i32 }, +/// Variant1 { c: u8, d: u64 }, +/// } +/// struct Demo2 { e: u8, f: u16, g: u8 } +/// ``` +/// `a` is in the variant with the `VariantIdx` of `0`, +/// `c` is in the variant with the `VariantIdx` of `1`, and +/// `g` is in the variant with the `VariantIdx` of `0`. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct VariantIdx(usize); + +index_impl!(VariantIdx); diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 05e0b9b4d7860..65e42879d618b 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -149,6 +149,7 @@ impl Visitable for RigidTy { RigidTy::FnPtr(sig) => sig.visit(visitor), RigidTy::Closure(_, args) => args.visit(visitor), RigidTy::Coroutine(_, args, _) => args.visit(visitor), + RigidTy::CoroutineWitness(_, args) => args.visit(visitor), RigidTy::Dynamic(pred, r, _) => { pred.visit(visitor)?; r.visit(visitor) diff --git a/config.example.toml b/config.example.toml index 66fa91d4bad15..c91222169d982 100644 --- a/config.example.toml +++ b/config.example.toml @@ -30,7 +30,7 @@ # # If `change-id` does not match the version that is currently running, # `x.py` will prompt you to update it and check the related PR for more details. -change-id = 116998 +change-id = 117813 # ============================================================================= # Tweaking how LLVM is compiled @@ -42,14 +42,15 @@ change-id = 116998 # Unless you're developing for a target where Rust CI doesn't build a compiler # toolchain or changing LLVM locally, you probably want to leave this enabled. # -# All tier 1 targets are currently supported; set this to `"if-available"` if -# you are not sure whether you're on a tier 1 target. -# -# We also currently only support this when building LLVM for the build triple. +# Set this to `"if-unchanged"` to download only if the llvm-project has not +# been modified. You can also use this if you are unsure whether you're on a +# tier 1 target. All tier 1 targets are currently supported. + +# Currently, we only support this when building LLVM for the build triple. # # Note that many of the LLVM options are not currently supported for # downloading. Currently only the "assertions" option can be toggled. -#download-ci-llvm = if rust.channel == "dev" { "if-available" } else { false } +#download-ci-llvm = if rust.channel == "dev" { "if-unchanged" } else { false } # Indicates whether the LLVM build is a Release or Debug build #optimize = true @@ -553,10 +554,11 @@ change-id = 116998 # Whether to always use incremental compilation when building rustc #incremental = false -# Build a multi-threaded rustc -# FIXME(#75760): Some UI tests fail when this option is enabled. -# NOTE: This option is NOT SUPPORTED. See #48685. -#parallel-compiler = false +# Build a multi-threaded rustc. This allows users to use parallel rustc +# via the unstable option `-Z threads=n`. +# Since stable/beta channels only allow using stable features, +# `parallel-compiler = false` should be set for these channels. +#parallel-compiler = true # The default linker that will be hard-coded into the generated # compiler for targets that don't specify a default linker explicitly @@ -684,6 +686,10 @@ change-id = 116998 # This only applies from stage 1 onwards, and only for Windows targets. #control-flow-guard = false +# Enable Windows EHCont Guard checks in the standard library. +# This only applies from stage 1 onwards, and only for Windows targets. +#ehcont-guard = false + # Enable symbol-mangling-version v0. This can be helpful when profiling rustc, # as generics will be preserved in symbols (rather than erased into opaque T). # When no setting is given, the new scheme will be used when compiling the diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 63aec14f48100..e8afed6b35a83 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -17,11 +17,11 @@ rand = { version = "0.8.5", default-features = false, features = ["alloc"] } rand_xorshift = "0.3.0" [[test]] -name = "collectionstests" +name = "alloctests" path = "tests/lib.rs" [[bench]] -name = "collectionsbenches" +name = "allocbenches" path = "benches/lib.rs" test = true diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index c1d3e1bdfe79d..8ebfe313dc5d5 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -658,13 +658,17 @@ fn random_sorted_fill(mut seed: u32, buf: &mut [u32]) { buf.sort(); } -fn bench_vec_dedup_old(b: &mut Bencher, sz: usize) { +// Measures performance of slice dedup impl. +// This was used to justify separate implementation of dedup for Vec. +// This algorithm was used for Vecs prior to Rust 1.52. +fn bench_dedup_slice_truncate(b: &mut Bencher, sz: usize) { let mut template = vec![0u32; sz]; b.bytes = std::mem::size_of_val(template.as_slice()) as u64; random_sorted_fill(0x43, &mut template); let mut vec = template.clone(); b.iter(|| { + let vec = black_box(&mut vec); let len = { let (dedup, _) = vec.partition_dedup(); dedup.len() @@ -672,59 +676,143 @@ fn bench_vec_dedup_old(b: &mut Bencher, sz: usize) { vec.truncate(len); black_box(vec.first()); + let vec = black_box(vec); vec.clear(); vec.extend_from_slice(&template); }); } -fn bench_vec_dedup_new(b: &mut Bencher, sz: usize) { +// Measures performance of Vec::dedup on random data. +fn bench_vec_dedup_random(b: &mut Bencher, sz: usize) { let mut template = vec![0u32; sz]; b.bytes = std::mem::size_of_val(template.as_slice()) as u64; random_sorted_fill(0x43, &mut template); let mut vec = template.clone(); b.iter(|| { + let vec = black_box(&mut vec); vec.dedup(); black_box(vec.first()); + let vec = black_box(vec); + vec.clear(); + vec.extend_from_slice(&template); + }); +} + +// Measures performance of Vec::dedup when there is no items removed +fn bench_vec_dedup_none(b: &mut Bencher, sz: usize) { + let mut template = vec![0u32; sz]; + b.bytes = std::mem::size_of_val(template.as_slice()) as u64; + template.chunks_exact_mut(2).for_each(|w| { + w[0] = black_box(0); + w[1] = black_box(5); + }); + + let mut vec = template.clone(); + b.iter(|| { + let vec = black_box(&mut vec); + vec.dedup(); + black_box(vec.first()); + // Unlike other benches of `dedup` + // this doesn't reinitialize vec + // because we measure how efficient dedup is + // when no memory written + }); +} + +// Measures performance of Vec::dedup when there is all items removed +fn bench_vec_dedup_all(b: &mut Bencher, sz: usize) { + let mut template = vec![0u32; sz]; + b.bytes = std::mem::size_of_val(template.as_slice()) as u64; + template.iter_mut().for_each(|w| { + *w = black_box(0); + }); + + let mut vec = template.clone(); + b.iter(|| { + let vec = black_box(&mut vec); + vec.dedup(); + black_box(vec.first()); + let vec = black_box(vec); vec.clear(); vec.extend_from_slice(&template); }); } #[bench] -fn bench_dedup_old_100(b: &mut Bencher) { - bench_vec_dedup_old(b, 100); +fn bench_dedup_slice_truncate_100(b: &mut Bencher) { + bench_dedup_slice_truncate(b, 100); } #[bench] -fn bench_dedup_new_100(b: &mut Bencher) { - bench_vec_dedup_new(b, 100); +fn bench_dedup_random_100(b: &mut Bencher) { + bench_vec_dedup_random(b, 100); } #[bench] -fn bench_dedup_old_1000(b: &mut Bencher) { - bench_vec_dedup_old(b, 1000); +fn bench_dedup_none_100(b: &mut Bencher) { + bench_vec_dedup_none(b, 100); } + +#[bench] +fn bench_dedup_all_100(b: &mut Bencher) { + bench_vec_dedup_all(b, 100); +} + +#[bench] +fn bench_dedup_slice_truncate_1000(b: &mut Bencher) { + bench_dedup_slice_truncate(b, 1000); +} +#[bench] +fn bench_dedup_random_1000(b: &mut Bencher) { + bench_vec_dedup_random(b, 1000); +} + +#[bench] +fn bench_dedup_none_1000(b: &mut Bencher) { + bench_vec_dedup_none(b, 1000); +} + #[bench] -fn bench_dedup_new_1000(b: &mut Bencher) { - bench_vec_dedup_new(b, 1000); +fn bench_dedup_all_1000(b: &mut Bencher) { + bench_vec_dedup_all(b, 1000); } #[bench] -fn bench_dedup_old_10000(b: &mut Bencher) { - bench_vec_dedup_old(b, 10000); +fn bench_dedup_slice_truncate_10000(b: &mut Bencher) { + bench_dedup_slice_truncate(b, 10000); } #[bench] -fn bench_dedup_new_10000(b: &mut Bencher) { - bench_vec_dedup_new(b, 10000); +fn bench_dedup_random_10000(b: &mut Bencher) { + bench_vec_dedup_random(b, 10000); } #[bench] -fn bench_dedup_old_100000(b: &mut Bencher) { - bench_vec_dedup_old(b, 100000); +fn bench_dedup_none_10000(b: &mut Bencher) { + bench_vec_dedup_none(b, 10000); } + +#[bench] +fn bench_dedup_all_10000(b: &mut Bencher) { + bench_vec_dedup_all(b, 10000); +} + +#[bench] +fn bench_dedup_slice_truncate_100000(b: &mut Bencher) { + bench_dedup_slice_truncate(b, 100000); +} +#[bench] +fn bench_dedup_random_100000(b: &mut Bencher) { + bench_vec_dedup_random(b, 100000); +} + +#[bench] +fn bench_dedup_none_100000(b: &mut Bencher) { + bench_vec_dedup_none(b, 100000); +} + #[bench] -fn bench_dedup_new_100000(b: &mut Bencher) { - bench_vec_dedup_new(b, 100000); +fn bench_dedup_all_100000(b: &mut Bencher) { + bench_vec_dedup_all(b, 100000); } #[bench] diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 2499f1053d860..1663aa84921c9 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -423,12 +423,14 @@ pub mod __alloc_error_handler { } } +#[cfg(not(no_global_oom_handling))] /// Specialize clones into pre-allocated, uninitialized memory. /// Used by `Box::clone` and `Rc`/`Arc::make_mut`. pub(crate) trait WriteCloneIntoRaw: Sized { unsafe fn write_clone_into_raw(&self, target: *mut Self); } +#[cfg(not(no_global_oom_handling))] impl WriteCloneIntoRaw for T { #[inline] default unsafe fn write_clone_into_raw(&self, target: *mut Self) { @@ -438,6 +440,7 @@ impl WriteCloneIntoRaw for T { } } +#[cfg(not(no_global_oom_handling))] impl WriteCloneIntoRaw for T { #[inline] unsafe fn write_clone_into_raw(&self, target: *mut Self) { diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 25c63b425ce59..fdf5e134f4d4c 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1038,10 +1038,18 @@ impl Box { /// use std::ptr; /// /// let x = Box::new(String::from("Hello")); - /// let p = Box::into_raw(x); + /// let ptr = Box::into_raw(x); + /// unsafe { + /// ptr::drop_in_place(ptr); + /// dealloc(ptr as *mut u8, Layout::new::()); + /// } + /// ``` + /// Note: This is equivalent to the following: + /// ``` + /// let x = Box::new(String::from("Hello")); + /// let ptr = Box::into_raw(x); /// unsafe { - /// ptr::drop_in_place(p); - /// dealloc(p as *mut u8, Layout::new::()); + /// drop(Box::from_raw(ptr)); /// } /// ``` /// diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index f83c8f83cc989..a8005b7067d07 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -171,6 +171,7 @@ struct WithHeader(NonNull, PhantomData); /// An opaque representation of `WithHeader` to avoid the /// projection invariance of `::Metadata`. #[repr(transparent)] +#[allow(unused_tuple_struct_fields)] // Field only used through `WithHeader` type above. struct WithOpaqueHeader(NonNull); impl WithOpaqueHeader { diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 61c5950b02731..00a101541c589 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -145,7 +145,7 @@ use core::alloc::Allocator; use core::fmt; -use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen}; +use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen}; use core::mem::{self, swap, ManuallyDrop}; use core::num::NonZeroUsize; use core::ops::{Deref, DerefMut}; @@ -1542,6 +1542,10 @@ impl ExactSizeIterator for IntoIter { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} +#[doc(hidden)] +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for IntoIter {} + #[stable(feature = "default_iters", since = "1.70.0")] impl Default for IntoIter { /// Creates an empty `binary_heap::IntoIter`. @@ -1571,7 +1575,10 @@ unsafe impl SourceIter for IntoIter { #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] -unsafe impl InPlaceIterable for IntoIter {} +unsafe impl InPlaceIterable for IntoIter { + const EXPAND_BY: Option = NonZeroUsize::new(1); + const MERGE_BY: Option = NonZeroUsize::new(1); +} unsafe impl AsVecIntoIter for IntoIter { type Item = I; diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 3e0b0f735508e..705b81535c279 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -148,6 +148,7 @@ impl Display for TryReserveError { /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] +#[cfg(not(no_global_oom_handling))] trait SpecExtend { /// Extends `self` with the contents of the given iterator. fn spec_extend(&mut self, iter: I); diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 1e2c35bf735f5..5b50ef7bf6c21 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -555,6 +555,8 @@ pub use core::fmt::Alignment; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::Error; +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub use core::fmt::FormatterFn; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{write, Arguments}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 4f0a02da44079..0af3ac38ee534 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -78,8 +78,8 @@ not(no_sync), target_has_atomic = "ptr" ))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![no_std] #![needs_allocator] // Lints: @@ -115,7 +115,6 @@ #![feature(const_eval_select)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_write)] -#![feature(const_maybe_uninit_zeroed)] #![feature(const_pin)] #![feature(const_refs_to_cell)] #![feature(const_size_of_val)] @@ -141,7 +140,6 @@ #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array_transpose)] #![feature(pattern)] -#![feature(ptr_addr_eq)] #![feature(ptr_internals)] #![feature(ptr_metadata)] #![feature(ptr_sub_ptr)] @@ -156,6 +154,7 @@ #![feature(std_internals)] #![feature(str_internals)] #![feature(strict_provenance)] +#![feature(trusted_fused)] #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] @@ -271,7 +270,7 @@ pub(crate) mod test_helpers { /// seed not being the same for every RNG invocation too. pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use std::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = std::hash::RandomState::new().build_hasher(); std::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index bd66ad612196d..817b93720ce28 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -305,10 +305,13 @@ impl RawVec { /// The same as `reserve`, but returns on errors instead of panicking or aborting. pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { if self.needs_to_grow(len, additional) { - self.grow_amortized(len, additional) - } else { - Ok(()) + self.grow_amortized(len, additional)?; + } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + core::intrinsics::assume(!self.needs_to_grow(len, additional)); } + Ok(()) } /// Ensures that the buffer contains at least enough space to hold `len + @@ -339,7 +342,14 @@ impl RawVec { len: usize, additional: usize, ) -> Result<(), TryReserveError> { - if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) } + if self.needs_to_grow(len, additional) { + self.grow_exact(len, additional)?; + } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + core::intrinsics::assume(!self.needs_to_grow(len, additional)); + } + Ok(()) } /// Shrinks the buffer down to the specified capacity. If the given amount diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index dd7876bed7691..98983e670d0f6 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2023,6 +2023,7 @@ impl Rc<[T], A> { } } +#[cfg(not(no_global_oom_handling))] /// Specialization trait used for `From<&[T]>`. trait RcFromSlice { fn from_slice(slice: &[T]) -> Self; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 351e6c1a4b3d2..5a4a94d79d89e 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2843,16 +2843,14 @@ impl Weak { /// (i.e., when this `Weak` was created by `Weak::new`). #[inline] fn inner(&self) -> Option> { - if is_dangling(self.ptr.as_ptr()) { + let ptr = self.ptr.as_ptr(); + if is_dangling(ptr) { None } else { // We are careful to *not* create a reference covering the "data" field, as // the field may be mutated concurrently (for example, if the last `Arc` // is dropped, the data field will be dropped in-place). - Some(unsafe { - let ptr = self.ptr.as_ptr(); - WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } - }) + Some(unsafe { WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } }) } } @@ -3503,6 +3501,7 @@ impl FromIterator for Arc<[T]> { } } +#[cfg(not(no_global_oom_handling))] /// Specialization trait used for collecting into `Arc<[T]>`. trait ToArcSlice: Iterator + Sized { fn to_arc_slice(self) -> Arc<[T]>; diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 5ecd0479971ea..a6cbed092c0ac 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -6,11 +6,11 @@ //! The specialization in this module applies to iterators in the shape of //! `source.adapter().adapter().adapter().collect::>()` //! where `source` is an owning iterator obtained from [`Vec`], [`Box<[T]>`][box] (by conversion to `Vec`) -//! or [`BinaryHeap`], the adapters each consume one or more items per step -//! (represented by [`InPlaceIterable`]), provide transitive access to `source` (via [`SourceIter`]) -//! and thus the underlying allocation. And finally the layouts of `T` and `U` must -//! have the same size and alignment, this is currently ensured via const eval instead of trait bounds -//! in the specialized [`SpecFromIter`] implementation. +//! or [`BinaryHeap`], the adapters guarantee to consume enough items per step to make room +//! for the results (represented by [`InPlaceIterable`]), provide transitive access to `source` +//! (via [`SourceIter`]) and thus the underlying allocation. +//! And finally there are alignment and size constriants to consider, this is currently ensured via +//! const eval instead of trait bounds in the specialized [`SpecFromIter`] implementation. //! //! [`BinaryHeap`]: crate::collections::BinaryHeap //! [box]: crate::boxed::Box @@ -35,11 +35,28 @@ //! the step of reading a value and getting a reference to write to. Instead raw pointers must be //! used on the reader and writer side. //! -//! That writes never clobber a yet-to-be-read item is ensured by the [`InPlaceIterable`] requirements. +//! That writes never clobber a yet-to-be-read items is ensured by the [`InPlaceIterable`] requirements. //! //! # Layout constraints //! -//! [`Allocator`] requires that `allocate()` and `deallocate()` have matching alignment and size. +//! When recycling an allocation between different types we must uphold the [`Allocator`] contract +//! which means that the input and output Layouts have to "fit". +//! +//! To complicate things further `InPlaceIterable` supports splitting or merging items into smaller/ +//! larger ones to enable (de)aggregation of arrays. +//! +//! Ultimately each step of the iterator must free up enough *bytes* in the source to make room +//! for the next output item. +//! If `T` and `U` have the same size no fixup is needed. +//! If `T`'s size is a multiple of `U`'s we can compensate by multiplying the capacity accordingly. +//! Otherwise the input capacity (and thus layout) in bytes may not be representable by the output +//! `Vec`. In that case `alloc.shrink()` is used to update the allocation's layout. +//! +//! Alignments of `T` must be the same or larger than `U`. Since alignments are always a power +//! of two _larger_ implies _is a multiple of_. +//! +//! See `in_place_collectible()` for the current conditions. +//! //! Additionally this specialization doesn't make sense for ZSTs as there is no reallocation to //! avoid and it would make pointer arithmetic more difficult. //! @@ -137,44 +154,94 @@ //! } //! vec.truncate(write_idx); //! ``` +use crate::alloc::{handle_alloc_error, Global}; +use core::alloc::Allocator; +use core::alloc::Layout; use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce}; use core::mem::{self, ManuallyDrop, SizedTypeProperties}; -use core::ptr::{self}; +use core::num::NonZeroUsize; +use core::ptr::{self, NonNull}; use super::{InPlaceDrop, InPlaceDstBufDrop, SpecFromIter, SpecFromIterNested, Vec}; -/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the -/// source allocation, i.e. executing the pipeline in place. -#[rustc_unsafe_specialization_marker] -pub(super) trait InPlaceIterableMarker {} +const fn in_place_collectible( + step_merge: Option, + step_expand: Option, +) -> bool { + if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::() < mem::align_of::() } { + return false; + } + + match (step_merge, step_expand) { + (Some(step_merge), Some(step_expand)) => { + // At least N merged source items -> at most M expanded destination items + // e.g. + // - 1 x [u8; 4] -> 4x u8, via flatten + // - 4 x u8 -> 1x [u8; 4], via array_chunks + mem::size_of::() * step_merge.get() >= mem::size_of::() * step_expand.get() + } + // Fall back to other from_iter impls if an overflow occurred in the step merge/expansion + // tracking. + _ => false, + } +} + +const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { + if const { mem::align_of::() != mem::align_of::() } { + return src_cap > 0; + } + + // If src type size is an integer multiple of the destination type size then + // the caller will have calculated a `dst_cap` that is an integer multiple of + // `src_cap` without remainder. + if const { + let src_sz = mem::size_of::(); + let dest_sz = mem::size_of::(); + dest_sz != 0 && src_sz % dest_sz == 0 + } { + return false; + } -impl InPlaceIterableMarker for T where T: InPlaceIterable {} + // type layouts don't guarantee a fit, so do a runtime check to see if + // the allocations happen to match + return src_cap > 0 && src_cap * mem::size_of::() != dst_cap * mem::size_of::(); +} + +/// This provides a shorthand for the source type since local type aliases aren't a thing. +#[rustc_specialization_trait] +trait InPlaceCollect: SourceIter + InPlaceIterable { + type Src; +} + +impl InPlaceCollect for T +where + T: SourceIter + InPlaceIterable, +{ + type Src = <::Source as AsVecIntoIter>::Item; +} impl SpecFromIter for Vec where - I: Iterator + SourceIter + InPlaceIterableMarker, + I: Iterator + InPlaceCollect, + ::Source: AsVecIntoIter, { default fn from_iter(mut iterator: I) -> Self { // See "Layout constraints" section in the module documentation. We rely on const // optimization here since these conditions currently cannot be expressed as trait bounds - if T::IS_ZST - || mem::size_of::() - != mem::size_of::<<::Source as AsVecIntoIter>::Item>() - || mem::align_of::() - != mem::align_of::<<::Source as AsVecIntoIter>::Item>() - { + if const { !in_place_collectible::(I::MERGE_BY, I::EXPAND_BY) } { // fallback to more generic implementations return SpecFromIterNested::from_iter(iterator); } - let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe { + let (src_buf, src_ptr, src_cap, mut dst_buf, dst_end, dst_cap) = unsafe { let inner = iterator.as_inner().as_into_iter(); ( inner.buf.as_ptr(), inner.ptr, + inner.cap, inner.buf.as_ptr() as *mut T, inner.end as *const T, - inner.cap, + inner.cap * mem::size_of::() / mem::size_of::(), ) }; @@ -196,18 +263,54 @@ where } // The ownership of the allocation and the new `T` values is temporarily moved into `dst_guard`. - // This is safe because `forget_allocation_drop_remaining` immediately forgets the allocation + // This is safe because + // * `forget_allocation_drop_remaining` immediately forgets the allocation // before any panic can occur in order to avoid any double free, and then proceeds to drop // any remaining values at the tail of the source. + // * the shrink either panics without invalidating the allocation, aborts or + // succeeds. In the last case we disarm the guard. // // Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce // contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the // module documentation why this is ok anyway. - let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap }; + let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap: dst_cap }; src.forget_allocation_drop_remaining(); + + // Adjust the allocation if the alignment didn't match or the source had a capacity in bytes + // that wasn't a multiple of the destination type size. + // Since the discrepancy should generally be small this should only result in some + // bookkeeping updates and no memmove. + if needs_realloc::(src_cap, dst_cap) { + let alloc = Global; + debug_assert_ne!(src_cap, 0); + debug_assert_ne!(dst_cap, 0); + unsafe { + // The old allocation exists, therefore it must have a valid layout. + let src_align = mem::align_of::(); + let src_size = mem::size_of::().unchecked_mul(src_cap); + let old_layout = Layout::from_size_align_unchecked(src_size, src_align); + + // The must be equal or smaller for in-place iteration to be possible + // therefore the new layout must be ≤ the old one and therefore valid. + let dst_align = mem::align_of::(); + let dst_size = mem::size_of::().unchecked_mul(dst_cap); + let new_layout = Layout::from_size_align_unchecked(dst_size, dst_align); + + let result = alloc.shrink( + NonNull::new_unchecked(dst_buf as *mut u8), + old_layout, + new_layout, + ); + let Ok(reallocated) = result else { handle_alloc_error(new_layout) }; + dst_buf = reallocated.as_ptr() as *mut T; + } + } else { + debug_assert_eq!(src_cap * mem::size_of::(), dst_cap * mem::size_of::()); + } + mem::forget(dst_guard); - let vec = unsafe { Vec::from_raw_parts(dst_buf, len, cap) }; + let vec = unsafe { Vec::from_raw_parts(dst_buf, len, dst_cap) }; vec } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index b2db2fdfd18f1..b03e04b7c706f 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -7,7 +7,8 @@ use crate::raw_vec::RawVec; use core::array; use core::fmt; use core::iter::{ - FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce, + FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen, + TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; @@ -285,9 +286,7 @@ impl Iterator for IntoIter { // Also note the implementation of `Self: TrustedRandomAccess` requires // that `T: Copy` so reading elements from the buffer doesn't invalidate // them for `Drop`. - unsafe { - if T::IS_ZST { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } - } + unsafe { if T::IS_ZST { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } } } } @@ -339,6 +338,10 @@ impl ExactSizeIterator for IntoIter { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} +#[doc(hidden)] +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for IntoIter {} + #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for IntoIter {} @@ -423,7 +426,10 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { // also refer to the vec::in_place_collect module documentation to get an overview #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] -unsafe impl InPlaceIterable for IntoIter {} +unsafe impl InPlaceIterable for IntoIter { + const EXPAND_BY: Option = NonZeroUsize::new(1); + const MERGE_BY: Option = NonZeroUsize::new(1); +} #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6c78d65f1c943..fca85c6123b3f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -58,6 +58,7 @@ use core::cmp; use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; +#[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; @@ -101,6 +102,7 @@ mod into_iter; #[cfg(not(no_global_oom_handling))] use self::is_zero::IsZero; +#[cfg(not(no_global_oom_handling))] mod is_zero; #[cfg(not(no_global_oom_handling))] @@ -1775,7 +1777,32 @@ impl Vec { return; } - /* INVARIANT: vec.len() > read >= write > write-1 >= 0 */ + // Check if we ever want to remove anything. + // This allows to use copy_non_overlapping in next cycle. + // And avoids any memory writes if we don't need to remove anything. + let mut first_duplicate_idx: usize = 1; + let start = self.as_mut_ptr(); + while first_duplicate_idx != len { + let found_duplicate = unsafe { + // SAFETY: first_duplicate always in range [1..len) + // Note that we start iteration from 1 so we never overflow. + let prev = start.add(first_duplicate_idx.wrapping_sub(1)); + let current = start.add(first_duplicate_idx); + // We explicitly say in docs that references are reversed. + same_bucket(&mut *current, &mut *prev) + }; + if found_duplicate { + break; + } + first_duplicate_idx += 1; + } + // Don't need to remove anything. + // We cannot get bigger than len. + if first_duplicate_idx == len { + return; + } + + /* INVARIANT: vec.len() > read > write > write-1 >= 0 */ struct FillGapOnDrop<'a, T, A: core::alloc::Allocator> { /* Offset of the element we want to check if it is duplicate */ read: usize, @@ -1821,31 +1848,39 @@ impl Vec { } } - let mut gap = FillGapOnDrop { read: 1, write: 1, vec: self }; - let ptr = gap.vec.as_mut_ptr(); - /* Drop items while going through Vec, it should be more efficient than * doing slice partition_dedup + truncate */ + // Construct gap first and then drop item to avoid memory corruption if `T::drop` panics. + let mut gap = + FillGapOnDrop { read: first_duplicate_idx + 1, write: first_duplicate_idx, vec: self }; + unsafe { + // SAFETY: we checked that first_duplicate_idx in bounds before. + // If drop panics, `gap` would remove this item without drop. + ptr::drop_in_place(start.add(first_duplicate_idx)); + } + /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr * are always in-bounds and read_ptr never aliases prev_ptr */ unsafe { while gap.read < len { - let read_ptr = ptr.add(gap.read); - let prev_ptr = ptr.add(gap.write.wrapping_sub(1)); + let read_ptr = start.add(gap.read); + let prev_ptr = start.add(gap.write.wrapping_sub(1)); - if same_bucket(&mut *read_ptr, &mut *prev_ptr) { + // We explicitly say in docs that references are reversed. + let found_duplicate = same_bucket(&mut *read_ptr, &mut *prev_ptr); + if found_duplicate { // Increase `gap.read` now since the drop may panic. gap.read += 1; /* We have found duplicate, drop it in-place */ ptr::drop_in_place(read_ptr); } else { - let write_ptr = ptr.add(gap.write); + let write_ptr = start.add(gap.write); - /* Because `read_ptr` can be equal to `write_ptr`, we either - * have to use `copy` or conditional `copy_nonoverlapping`. - * Looks like the first option is faster. */ - ptr::copy(read_ptr, write_ptr, 1); + /* read_ptr cannot be equal to write_ptr because at this point + * we guaranteed to skip at least one element (before loop starts). + */ + ptr::copy_nonoverlapping(read_ptr, write_ptr, 1); /* We have filled that place, so go further */ gap.write += 1; @@ -2599,6 +2634,7 @@ pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec< ::from_elem(elem, n, alloc) } +#[cfg(not(no_global_oom_handling))] trait ExtendFromWithinSpec { /// # Safety /// @@ -2607,6 +2643,7 @@ trait ExtendFromWithinSpec { unsafe fn spec_extend_from_within(&mut self, src: Range); } +#[cfg(not(no_global_oom_handling))] impl ExtendFromWithinSpec for Vec { default unsafe fn spec_extend_from_within(&mut self, src: Range) { // SAFETY: @@ -2626,6 +2663,7 @@ impl ExtendFromWithinSpec for Vec { } } +#[cfg(not(no_global_oom_handling))] impl ExtendFromWithinSpec for Vec { unsafe fn spec_extend_from_within(&mut self, src: Range) { let count = src.len(); @@ -2706,7 +2744,7 @@ impl Clone for Vec { /// ``` /// use std::hash::BuildHasher; /// -/// let b = std::collections::hash_map::RandomState::new(); +/// let b = std::hash::RandomState::new(); /// let v: Vec = vec![0xa8, 0x3c, 0x09]; /// let s: &[u8] = &[0xa8, 0x3c, 0x09]; /// assert_eq!(b.hash_one(v), b.hash_one(s)); diff --git a/library/alloc/src/vec/spec_from_elem.rs b/library/alloc/src/vec/spec_from_elem.rs index da43d17bf3624..01a6db14474bb 100644 --- a/library/alloc/src/vec/spec_from_elem.rs +++ b/library/alloc/src/vec/spec_from_elem.rs @@ -36,12 +36,12 @@ impl SpecFromElem for i8 { if elem == 0 { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } + let mut v = Vec::with_capacity_in(n, alloc); unsafe { - let mut v = Vec::with_capacity_in(n, alloc); ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); v.set_len(n); - v } + v } } @@ -51,11 +51,26 @@ impl SpecFromElem for u8 { if elem == 0 { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } + let mut v = Vec::with_capacity_in(n, alloc); unsafe { - let mut v = Vec::with_capacity_in(n, alloc); ptr::write_bytes(v.as_mut_ptr(), elem, n); v.set_len(n); - v } + v + } +} + +// A better way would be to implement this for all ZSTs which are `Copy` and have trivial `Clone` +// but the latter cannot be detected currently +impl SpecFromElem for () { + #[inline] + fn from_elem(_elem: (), n: usize, alloc: A) -> Vec<(), A> { + let mut v = Vec::with_capacity_in(n, alloc); + // SAFETY: the capacity has just been set to `n` + // and `()` is a ZST with trivial `Clone` implementation + unsafe { + v.set_len(n); + } + v } } diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index aa7a331b368be..2dcfc6b4abfe9 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -1,5 +1,6 @@ #![feature(allocator_api)] #![feature(alloc_layout_extra)] +#![feature(iter_array_chunks)] #![feature(assert_matches)] #![feature(btree_extract_if)] #![feature(cow_is_borrowed)] @@ -40,11 +41,11 @@ #![feature(thin_box)] #![feature(strict_provenance)] #![feature(drain_keep_rest)] +#![allow(internal_features)] #![deny(fuzzy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; +use std::hash::{DefaultHasher, Hash, Hasher}; mod arc; mod autotraits; diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index cb59a9d4ab2a6..df8a260624a28 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1170,6 +1170,17 @@ fn test_iterator() { assert_eq!(s.chars().count(), v.len()); } +#[test] +fn test_iterator_advance() { + let s = "「赤錆」と呼ばれる鉄錆は、水の存在下での鉄の自然酸化によって生じる、オキシ水酸化鉄(III) 等の(含水)酸化物粒子の疎な凝集膜であるとみなせる。"; + let chars: Vec = s.chars().collect(); + let mut it = s.chars(); + it.advance_by(1).unwrap(); + assert_eq!(it.next(), Some(chars[1])); + it.advance_by(33).unwrap(); + assert_eq!(it.next(), Some(chars[35])); +} + #[test] fn test_rev_iterator() { let s = "ศไทย中华Việt Nam"; diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index d44dcfbf67301..3d3175ba3a9ca 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1,6 +1,7 @@ +use alloc::vec::Vec; use core::alloc::{Allocator, Layout}; -use core::assert_eq; -use core::iter::IntoIterator; +use core::{assert_eq, assert_ne}; +use core::iter::{IntoIterator, Iterator}; use core::num::NonZeroUsize; use core::ptr::NonNull; use std::alloc::System; @@ -1184,6 +1185,54 @@ fn test_from_iter_specialization_with_iterator_adapters() { assert_eq!(srcptr, sinkptr as *const usize); } +#[test] +fn test_in_place_specialization_step_up_down() { + fn assert_in_place_trait(_: &T) {} + let src = vec![[0u8; 4]; 256]; + let srcptr = src.as_ptr(); + let src_cap = src.capacity(); + let iter = src.into_iter().flatten(); + assert_in_place_trait(&iter); + let sink = iter.collect::>(); + let sinkptr = sink.as_ptr(); + assert_eq!(srcptr as *const u8, sinkptr); + assert_eq!(src_cap * 4, sink.capacity()); + + let iter = sink.into_iter().array_chunks::<4>(); + assert_in_place_trait(&iter); + let sink = iter.collect::>(); + let sinkptr = sink.as_ptr(); + assert_eq!(srcptr, sinkptr); + assert_eq!(src_cap, sink.capacity()); + + let mut src: Vec = Vec::with_capacity(17); + let src_bytes = src.capacity(); + src.resize(8, 0u8); + let sink: Vec<[u8; 4]> = src.into_iter().array_chunks::<4>().collect(); + let sink_bytes = sink.capacity() * 4; + assert_ne!(src_bytes, sink_bytes); + assert_eq!(sink.len(), 2); + + let mut src: Vec<[u8; 3]> = Vec::with_capacity(17); + src.resize( 8, [0; 3]); + let iter = src.into_iter().map(|[a, b, _]| [a, b]); + assert_in_place_trait(&iter); + let sink: Vec<[u8; 2]> = iter.collect(); + assert_eq!(sink.len(), 8); + assert!(sink.capacity() <= 25); + + let src = vec![[0u8; 4]; 256]; + let srcptr = src.as_ptr(); + let iter = src + .into_iter() + .flat_map(|a| { + a.into_iter().map(|b| b.wrapping_add(1)) + }); + assert_in_place_trait(&iter); + let sink = iter.collect::>(); + assert_eq!(srcptr as *const u8, sink.as_ptr()); +} + #[test] fn test_from_iter_specialization_head_tail_drop() { let drop_count: Vec<_> = (0..=2).map(|_| Rc::new(())).collect(); diff --git a/library/backtrace b/library/backtrace index e9da96eb452aa..6145fe6bac65c 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit e9da96eb452aa65e79e2342be700544afe509440 +Subproject commit 6145fe6bac65c38375f1216a565a6cc7deb89a2d diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index 74ef0949b8af2..fdefc9a714e57 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -5,6 +5,7 @@ #![feature(trusted_random_access)] #![feature(iter_array_chunks)] #![feature(iter_next_chunk)] +#![feature(iter_advance_by)] extern crate test; diff --git a/library/core/benches/str.rs b/library/core/benches/str.rs index 78865d81fb90c..7d36eff3d6c8b 100644 --- a/library/core/benches/str.rs +++ b/library/core/benches/str.rs @@ -3,6 +3,7 @@ use test::{black_box, Bencher}; mod char_count; mod corpora; +mod iter; #[bench] fn str_validate_emoji(b: &mut Bencher) { diff --git a/library/core/benches/str/iter.rs b/library/core/benches/str/iter.rs new file mode 100644 index 0000000000000..58ae71fc10f12 --- /dev/null +++ b/library/core/benches/str/iter.rs @@ -0,0 +1,17 @@ +use super::corpora; +use test::{black_box, Bencher}; + +#[bench] +fn chars_advance_by_1000(b: &mut Bencher) { + b.iter(|| black_box(corpora::ru::LARGE).chars().advance_by(1000)); +} + +#[bench] +fn chars_advance_by_0010(b: &mut Bencher) { + b.iter(|| black_box(corpora::ru::LARGE).chars().advance_by(10)); +} + +#[bench] +fn chars_advance_by_0001(b: &mut Bencher) { + b.iter(|| black_box(corpora::ru::LARGE).chars().advance_by(1)); +} diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 65946e09ff9ba..9ef0a7d760840 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -450,7 +450,11 @@ impl Layout { return Err(LayoutError); } - let array_size = element_size * n; + // SAFETY: We just checked that we won't overflow `usize` when we multiply. + // This is a useless hint inside this function, but after inlining this helps + // deduplicate checks for whether the overall capacity is zero (e.g., in RawVec's + // allocation path) before/after this multiplication. + let array_size = unsafe { element_size.unchecked_mul(n) }; // SAFETY: We just checked above that the `array_size` will not // exceed `isize::MAX` even when rounded up to the alignment. diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 8f5404d9713dd..22777fb078a26 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -115,6 +115,11 @@ use crate::intrinsics; pub trait Any: 'static { /// Gets the `TypeId` of `self`. /// + /// If called on a `dyn Any` trait object + /// (or a trait object of a subtrait of `Any`), + /// this returns the `TypeId` of the underlying + /// concrete type, not that of `dyn Any` itself. + /// /// # Examples /// /// ``` diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index ebd4a8c05fe30..34213637a32fc 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -206,7 +206,7 @@ where #[inline] fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> { - <&Self>::try_from(slice).map(|r| *r) + <&Self>::try_from(slice).copied() } } @@ -297,7 +297,7 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { /// ``` /// use std::hash::BuildHasher; /// -/// let b = std::collections::hash_map::RandomState::new(); +/// let b = std::hash::RandomState::new(); /// let a: [u8; 3] = [0xa8, 0x3c, 0x09]; /// let s: &[u8] = &[0xa8, 0x3c, 0x09]; /// assert_eq!(b.hash_one(a), b.hash_one(s)); diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 0978b3c92805e..030040ba09abb 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -143,17 +143,17 @@ //! //! ``` //! # #![allow(dead_code)] -//! use std::cell::RefCell; +//! use std::cell::OnceCell; //! //! struct Graph { //! edges: Vec<(i32, i32)>, -//! span_tree_cache: RefCell>> +//! span_tree_cache: OnceCell> //! } //! //! impl Graph { //! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> { -//! self.span_tree_cache.borrow_mut() -//! .get_or_insert_with(|| self.calc_span_tree()) +//! self.span_tree_cache +//! .get_or_init(|| self.calc_span_tree()) //! .clone() //! } //! @@ -409,8 +409,7 @@ impl Cell { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn set(&self, val: T) { - let old = self.replace(val); - drop(old); + self.replace(val); } /// Swaps the values of two `Cell`s. diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs index d76f983d87cce..23319fbe5ddc4 100644 --- a/library/core/src/char/decode.rs +++ b/library/core/src/char/decode.rs @@ -106,7 +106,7 @@ impl> Iterator for DecodeUtf16 { } } -#[stable(feature = "decode_utf16_fused_iterator", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "decode_utf16_fused_iterator", since = "1.75.0")] impl + FusedIterator> FusedIterator for DecodeUtf16 {} impl DecodeUtf16Error { diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 89125b7955e02..8c01b0973d65a 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -138,7 +138,7 @@ pub const fn identity(x: T) -> T { /// /// [dereferenceable types]: core::ops::Deref /// [pointed-to value]: core::ops::Deref::Target -/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion +/// ['`Deref` coercion']: core::ops::Deref#deref-coercion /// /// ``` /// let x = Box::new(5i32); @@ -244,7 +244,7 @@ pub trait AsRef { /// /// [mutably dereferenceable types]: core::ops::DerefMut /// [pointed-to value]: core::ops::Deref::Target -/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion +/// ['`Deref` coercion']: core::ops::DerefMut#mutable-deref-coercion /// /// ``` /// let mut x = Box::new(5i32); diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 1170221c10c43..f1a7ad935480c 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -439,10 +439,10 @@ where /// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise /// prepared to generate a value requested). eg, `backtrace::Backtrace` or /// `std::backtrace::Backtrace` -/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace). In the case -/// of a `dyn Error` trait object (the Producer), there are methods called `request_ref` and -/// `request_value` are available to simplify obtaining an ``Option`` for a given type. * The -/// Producer, when requested, populates the given Request object which is given as a mutable +/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the +/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and +/// `request_value` to simplify obtaining an `Option` for a given type. +/// * The Producer, when requested, populates the given Request object which is given as a mutable /// reference. /// * The Consumer extracts a value or reference to the requested type from the `Request` object /// wrapped in an `Option`; in the case of `dyn Error` the aforementioned `request_ref` and ` diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index 24bb9ad1ad1a2..60b5df752ca85 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -21,12 +21,16 @@ pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Rang b'\\' => backslash(ascii::Char::ReverseSolidus), b'\'' => backslash(ascii::Char::Apostrophe), b'\"' => backslash(ascii::Char::QuotationMark), - _ => if let Some(a) = byte.as_ascii() && !byte.is_ascii_control() { - ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1) - } else { - let hi = HEX_DIGITS[usize::from(byte >> 4)]; - let lo = HEX_DIGITS[usize::from(byte & 0xf)]; - ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4) + _ => { + if let Some(a) = byte.as_ascii() + && !byte.is_ascii_control() + { + ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1) + } else { + let hi = HEX_DIGITS[usize::from(byte >> 4)]; + let lo = HEX_DIGITS[usize::from(byte & 0xf)]; + ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4) + } } }; *output = data; diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 6908c824f44b6..7340ad90da509 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -241,7 +241,6 @@ impl fmt::Debug for c_void { ), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), target_family = "wasm", - target_arch = "asmjs", target_os = "uefi", windows, ))] @@ -270,7 +269,6 @@ pub struct VaListImpl<'f> { ), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), target_family = "wasm", - target_arch = "asmjs", target_os = "uefi", windows, ))] @@ -395,7 +393,6 @@ pub struct VaList<'a, 'f: 'a> { any(target_os = "macos", target_os = "ios", target_os = "tvos") ), target_family = "wasm", - target_arch = "asmjs", target_os = "uefi", windows, ))] @@ -413,7 +410,6 @@ pub struct VaList<'a, 'f: 'a> { not(any(target_os = "macos", target_os = "ios", target_os = "tvos")) ), not(target_family = "wasm"), - not(target_arch = "asmjs"), not(target_os = "uefi"), not(windows), ))] @@ -431,7 +427,6 @@ pub struct VaList<'a, 'f: 'a> { ), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")), target_family = "wasm", - target_arch = "asmjs", target_os = "uefi", windows, ))] @@ -461,7 +456,6 @@ impl<'f> VaListImpl<'f> { not(any(target_os = "macos", target_os = "ios", target_os = "tvos")) ), not(target_family = "wasm"), - not(target_arch = "asmjs"), not(target_os = "uefi"), not(windows), ))] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 47db53ac6f34b..4ccb585862cdf 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -130,6 +130,18 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self { + self.field_with(name, |f| value.fmt(f)) + } + + /// Adds a new field to the generated struct output. + /// + /// This method is equivalent to [`DebugStruct::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -140,14 +152,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); writer.write_str(name)?; writer.write_str(": ")?; - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n") } else { let prefix = if self.has_fields { ", " } else { " { " }; self.fmt.write_str(prefix)?; self.fmt.write_str(name)?; self.fmt.write_str(": ")?; - value.fmt(self.fmt) + value_fmt(self.fmt) } }); @@ -315,6 +327,18 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self { + self.field_with(|f| value.fmt(f)) + } + + /// Adds a new field to the generated tuple struct output. + /// + /// This method is equivalent to [`DebugTuple::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if self.fields == 0 { @@ -323,12 +347,12 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { let mut slot = None; let mut state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n") } else { let prefix = if self.fields == 0 { "(" } else { ", " }; self.fmt.write_str(prefix)?; - value.fmt(self.fmt) + value_fmt(self.fmt) } }); @@ -385,7 +409,10 @@ struct DebugInner<'a, 'b: 'a> { } impl<'a, 'b: 'a> DebugInner<'a, 'b> { - fn entry(&mut self, entry: &dyn fmt::Debug) { + fn entry_with(&mut self, entry_fmt: F) + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -394,13 +421,13 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { let mut slot = None; let mut state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); - entry.fmt(&mut writer)?; + entry_fmt(&mut writer)?; writer.write_str(",\n") } else { if self.has_fields { self.fmt.write_str(", ")? } - entry.fmt(self.fmt) + entry_fmt(self.fmt) } }); @@ -475,7 +502,20 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { - self.inner.entry(entry); + self.inner.entry_with(|f| entry.fmt(f)); + self + } + + /// Adds a new entry to the set output. + /// + /// This method is equivalent to [`DebugSet::entry`], but formats the + /// entry using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.inner.entry_with(entry_fmt); self } @@ -605,7 +645,20 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { - self.inner.entry(entry); + self.inner.entry_with(|f| entry.fmt(f)); + self + } + + /// Adds a new entry to the list output. + /// + /// This method is equivalent to [`DebugList::entry`], but formats the + /// entry using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.inner.entry_with(entry_fmt); self } @@ -775,6 +828,18 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self { + self.key_with(|f| key.fmt(f)) + } + + /// Adds the key part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::key`], but formats the + /// key using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn key_with(&mut self, key_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { assert!( !self.has_key, @@ -789,13 +854,13 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { let mut slot = None; self.state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); - key.fmt(&mut writer)?; + key_fmt(&mut writer)?; writer.write_str(": ")?; } else { if self.has_fields { self.fmt.write_str(", ")? } - key.fmt(self.fmt)?; + key_fmt(self.fmt)?; self.fmt.write_str(": ")?; } @@ -839,16 +904,28 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self { + self.value_with(|f| value.fmt(f)) + } + + /// Adds the value part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::value`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn value_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { assert!(self.has_key, "attempted to format a map value before its key"); if self.is_pretty() { let mut slot = None; let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n")?; } else { - value.fmt(self.fmt)?; + value_fmt(self.fmt)?; } self.has_key = false; @@ -936,3 +1013,44 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self.fmt.alternate() } } + +/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function. +/// +/// # Examples +/// +/// ``` +/// #![feature(debug_closure_helpers)] +/// use std::fmt; +/// +/// let value = 'a'; +/// assert_eq!(format!("{}", value), "a"); +/// assert_eq!(format!("{:?}", value), "'a'"); +/// +/// let wrapped = fmt::FormatterFn(|f| write!(f, "{:?}", &value)); +/// assert_eq!(format!("{}", wrapped), "'a'"); +/// assert_eq!(format!("{:?}", wrapped), "'a'"); +/// ``` +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub struct FormatterFn(pub F) +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result; + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl fmt::Debug for FormatterFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl fmt::Display for FormatterFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index c45ab094a20d6..e1b7b46a1ed2f 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -39,6 +39,9 @@ pub enum Alignment { #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub use self::builders::FormatterFn; + /// The type returned by formatter methods. /// /// # Examples diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 4f42f73ebbaff..778515f8616c4 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -309,7 +309,6 @@ macro_rules! impl_Exp { n /= 10; exponent += 1; } - let (added_precision, subtracted_precision) = match f.precision() { Some(fmt_prec) => { // number of decimal digits minus 1 @@ -331,9 +330,15 @@ macro_rules! impl_Exp { let rem = n % 10; n /= 10; exponent += 1; - // round up last digit - if rem >= 5 { + // round up last digit, round to even on a tie + if rem > 5 || (rem == 5 && (n % 2 != 0 || subtracted_precision > 1 )) { n += 1; + // if the digit is rounded to the next power + // instead adjust the exponent + if n.ilog10() > (n - 1).ilog10() { + n /= 10; + exponent += 1; + } } } (n, exponent, exponent, added_precision) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 35b757dc1ee06..153971a59c5c9 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -12,8 +12,7 @@ //! # Examples //! //! ```rust -//! use std::collections::hash_map::DefaultHasher; -//! use std::hash::{Hash, Hasher}; +//! use std::hash::{DefaultHasher, Hash, Hasher}; //! //! #[derive(Hash)] //! struct Person { @@ -46,8 +45,7 @@ //! the [`Hash`] trait: //! //! ```rust -//! use std::collections::hash_map::DefaultHasher; -//! use std::hash::{Hash, Hasher}; +//! use std::hash::{DefaultHasher, Hash, Hasher}; //! //! struct Person { //! id: u32, @@ -194,8 +192,7 @@ pub trait Hash { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::{Hash, Hasher}; + /// use std::hash::{DefaultHasher, Hash, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// 7920.hash(&mut hasher); @@ -224,8 +221,7 @@ pub trait Hash { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::{Hash, Hasher}; + /// use std::hash::{DefaultHasher, Hash, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// let numbers = [6, 28, 496, 8128]; @@ -300,8 +296,7 @@ pub use macros::Hash; /// # Examples /// /// ``` -/// use std::collections::hash_map::DefaultHasher; -/// use std::hash::Hasher; +/// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// @@ -329,8 +324,7 @@ pub trait Hasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::Hasher; + /// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// hasher.write(b"Cool!"); @@ -347,8 +341,7 @@ pub trait Hasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::Hasher; + /// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; @@ -627,8 +620,7 @@ impl Hasher for &mut H { /// # Examples /// /// ``` -/// use std::collections::hash_map::RandomState; -/// use std::hash::{BuildHasher, Hasher}; +/// use std::hash::{BuildHasher, Hasher, RandomState}; /// /// let s = RandomState::new(); /// let mut hasher_1 = s.build_hasher(); @@ -656,8 +648,7 @@ pub trait BuildHasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::RandomState; - /// use std::hash::BuildHasher; + /// use std::hash::{BuildHasher, RandomState}; /// /// let s = RandomState::new(); /// let new_s = s.build_hasher(); @@ -690,7 +681,7 @@ pub trait BuildHasher { /// } /// /// // Then later, in a `#[test]` for the type... - /// let bh = std::collections::hash_map::RandomState::new(); + /// let bh = std::hash::RandomState::new(); /// assert_eq!( /// bh.hash_one(OrderAmbivalentPair(1, 2)), /// bh.hash_one(OrderAmbivalentPair(2, 1)) diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 6b9f2e84257d1..78a232faaf88c 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -14,7 +14,7 @@ use crate::ptr; /// /// See: #[unstable(feature = "hashmap_internals", issue = "none")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] #[doc(hidden)] pub struct SipHasher13 { @@ -25,7 +25,7 @@ pub struct SipHasher13 { /// /// See: #[unstable(feature = "hashmap_internals", issue = "none")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] struct SipHasher24 { hasher: Hasher, @@ -44,7 +44,7 @@ struct SipHasher24 { /// it is not intended for cryptographic purposes. As such, all /// cryptographic uses of this implementation are _strongly discouraged_. #[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher(SipHasher24); @@ -147,10 +147,7 @@ impl SipHasher { /// Creates a new `SipHasher` with the two initial keys set to 0. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new() -> SipHasher { @@ -160,10 +157,7 @@ impl SipHasher { /// Creates a `SipHasher` that is keyed off the provided keys. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher { @@ -175,10 +169,7 @@ impl SipHasher13 { /// Creates a new `SipHasher13` with the two initial keys set to 0. #[inline] #[unstable(feature = "hashmap_internals", issue = "none")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] pub const fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) @@ -187,10 +178,7 @@ impl SipHasher13 { /// Creates a `SipHasher13` that is keyed off the provided keys. #[inline] #[unstable(feature = "hashmap_internals", issue = "none")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs index 5774107f5207f..bf53b2245ac59 100644 --- a/library/core/src/internal_macros.rs +++ b/library/core/src/internal_macros.rs @@ -31,6 +31,7 @@ macro_rules! forward_ref_binop { type Output = <$t as $imp<$u>>::Output; #[inline] + #[track_caller] fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { $imp::$method(*self, other) } @@ -41,6 +42,7 @@ macro_rules! forward_ref_binop { type Output = <$t as $imp<$u>>::Output; #[inline] + #[track_caller] fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { $imp::$method(self, *other) } @@ -51,6 +53,7 @@ macro_rules! forward_ref_binop { type Output = <$t as $imp<$u>>::Output; #[inline] + #[track_caller] fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output { $imp::$method(*self, *other) } @@ -69,6 +72,7 @@ macro_rules! forward_ref_op_assign { #[$attr] impl $imp<&$u> for $t { #[inline] + #[track_caller] fn $method(&mut self, other: &$u) { $imp::$method(self, *other); } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 964aa3906f1d2..3406112ddb111 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -341,6 +341,9 @@ extern "rust-intrinsic" { /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`]. #[rustc_nounwind] pub fn atomic_load_relaxed(src: *const T) -> T; + /// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model! + /// In terms of the Rust Abstract Machine, this operation is equivalent to `src.read()`, + /// i.e., it performs a non-atomic read. #[rustc_nounwind] pub fn atomic_load_unordered(src: *const T) -> T; @@ -365,6 +368,9 @@ extern "rust-intrinsic" { /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::store`]. #[rustc_nounwind] pub fn atomic_store_relaxed(dst: *mut T, val: T); + /// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model! + /// In terms of the Rust Abstract Machine, this operation is equivalent to `dst.write(val)`, + /// i.e., it performs a non-atomic write. #[rustc_nounwind] pub fn atomic_store_unordered(dst: *mut T, val: T); @@ -1072,7 +1078,7 @@ extern "rust-intrinsic" { /// zero-initialization: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] + #[rustc_const_stable(feature = "const_assert_type2", since = "1.75.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn assert_zero_valid(); @@ -1080,7 +1086,7 @@ extern "rust-intrinsic" { /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] + #[rustc_const_stable(feature = "const_assert_type2", since = "1.75.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn assert_mem_uninitialized_valid(); @@ -1900,6 +1906,7 @@ extern "rust-intrinsic" { /// /// ``` /// #![feature(core_intrinsics)] + /// # #![allow(internal_features)] /// /// use std::intrinsics::ctlz; /// @@ -1912,6 +1919,7 @@ extern "rust-intrinsic" { /// /// ``` /// #![feature(core_intrinsics)] + /// # #![allow(internal_features)] /// /// use std::intrinsics::ctlz; /// @@ -1933,6 +1941,7 @@ extern "rust-intrinsic" { /// /// ``` /// #![feature(core_intrinsics)] + /// # #![allow(internal_features)] /// /// use std::intrinsics::ctlz_nonzero; /// @@ -1959,6 +1968,7 @@ extern "rust-intrinsic" { /// /// ``` /// #![feature(core_intrinsics)] + /// # #![allow(internal_features)] /// /// use std::intrinsics::cttz; /// @@ -1971,6 +1981,7 @@ extern "rust-intrinsic" { /// /// ``` /// #![feature(core_intrinsics)] + /// # #![allow(internal_features)] /// /// use std::intrinsics::cttz; /// @@ -1992,6 +2003,7 @@ extern "rust-intrinsic" { /// /// ``` /// #![feature(core_intrinsics)] + /// # #![allow(internal_features)] /// /// use std::intrinsics::cttz_nonzero; /// @@ -2279,7 +2291,7 @@ extern "rust-intrinsic" { /// any safety invariants. /// /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. - #[rustc_const_stable(feature = "const_discriminant", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_discriminant", since = "1.75.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn discriminant_value(v: &T) -> ::Discriminant; @@ -2312,6 +2324,10 @@ extern "rust-intrinsic" { /// Emits a `!nontemporal` store according to LLVM (see their docs). /// Probably will never become stable. + /// + /// Do NOT use this intrinsic; "nontemporal" operations do not exist in our memory model! + /// It exists to support current stdarch, but the plan is to change stdarch and remove this intrinsic. + /// See for some more discussion. #[rustc_nounwind] pub fn nontemporal_store(ptr: *mut T, val: T); @@ -2453,6 +2469,7 @@ extern "rust-intrinsic" { /// ```no_run /// #![feature(const_eval_select)] /// #![feature(core_intrinsics)] + /// # #![allow(internal_features)] /// use std::hint::unreachable_unchecked; /// use std::intrinsics::const_eval_select; /// @@ -2487,12 +2504,6 @@ extern "rust-intrinsic" { where G: FnOnce, F: FnOnce; - - /// This method creates a pointer to any `Some` value. If the argument is - /// `None`, an invalid within-bounds pointer (that is still acceptable for - /// constructing an empty slice) is returned. - #[rustc_nounwind] - pub fn option_payload_ptr(arg: *const Option) -> *const T; } // Some functions are defined here because they accidentally got made @@ -2855,3 +2866,28 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { write_bytes(dst, val, count) } } + +/// Inform Miri that a given pointer definitely has a certain alignment. +#[cfg(miri)] +pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) { + extern "Rust" { + /// Miri-provided extern function to promise that a given pointer is properly aligned for + /// "symbolic" alignment checks. Will fail if the pointer is not actually aligned or `align` is + /// not a power of two. Has no effect when alignment checks are concrete (which is the default). + fn miri_promise_symbolic_alignment(ptr: *const (), align: usize); + } + + fn runtime(ptr: *const (), align: usize) { + // SAFETY: this call is always safe. + unsafe { + miri_promise_symbolic_alignment(ptr, align); + } + } + + const fn compiletime(_ptr: *const (), _align: usize) {} + + // SAFETY: the extra behavior at runtime is for UB checks only. + unsafe { + const_eval_select((ptr, align), compiletime, runtime); + } +} diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index b26a17ec30e9d..34a61e76fcf66 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -110,15 +110,15 @@ //! let popped; //! //! { -//! Call(_unused = Vec::push(v, value), pop) +//! Call(_unused = Vec::push(v, value), pop, UnwindContinue()) //! } //! //! pop = { -//! Call(popped = Vec::pop(v), drop) +//! Call(popped = Vec::pop(v), drop, UnwindContinue()) //! } //! //! drop = { -//! Drop(popped, ret) +//! Drop(popped, ret, UnwindContinue()) //! } //! //! ret = { @@ -193,7 +193,7 @@ //! 27 | | ) //! | |_____- binding declared here but left uninitialized //! -//! error: aborting due to previous error +//! error: aborting due to 1 previous error //! //! For more information about this error, try `rustc --explain E0381`. //! ``` @@ -238,10 +238,6 @@ //! //! #### Terminators //! -//! Custom MIR does not currently support cleanup blocks or non-trivial unwind paths. As such, there -//! are no resume and abort terminators, and terminators that might unwind do not have any way to -//! indicate the unwind block. -//! //! - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions. //! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block` //! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the @@ -260,7 +256,26 @@ /// Type representing basic blocks. /// /// All terminators will have this type as a return type. It helps achieve some type safety. -pub struct BasicBlock; +#[rustc_diagnostic_item = "mir_basic_block"] +pub enum BasicBlock { + /// A non-cleanup basic block. + Normal, + /// A basic block that lies on an unwind path. + Cleanup, +} + +/// The reason we are terminating the process during unwinding. +#[rustc_diagnostic_item = "mir_unwind_terminate_reason"] +pub enum UnwindTerminateReason { + /// Unwinding is just not possible given the ABI of this function. + Abi, + /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was + /// triggered by the drop glue. + InCleanup, +} + +pub use UnwindTerminateReason::Abi as ReasonAbi; +pub use UnwindTerminateReason::InCleanup as ReasonInCleanup; macro_rules! define { ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => { @@ -271,11 +286,41 @@ macro_rules! define { } } +// Unwind actions +define!( + "mir_unwind_continue", + /// An unwind action that continues unwinding. + fn UnwindContinue() +); +define!( + "mir_unwind_unreachable", + /// An unwind action that triggers undefined behaviour. + fn UnwindUnreachable() -> BasicBlock +); +define!( + "mir_unwind_terminate", + /// An unwind action that terminates the execution. + /// + /// `UnwindTerminate` can also be used as a terminator. + fn UnwindTerminate(reason: UnwindTerminateReason) +); +define!( + "mir_unwind_cleanup", + /// An unwind action that continues execution in a given basic blok. + fn UnwindCleanup(goto: BasicBlock) +); + +// Terminators define!("mir_return", fn Return() -> BasicBlock); define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_unreachable", fn Unreachable() -> BasicBlock); -define!("mir_drop", fn Drop(place: T, goto: BasicBlock)); -define!("mir_call", fn Call(call: (), goto: BasicBlock)); +define!("mir_drop", fn Drop(place: T, goto: BasicBlock, unwind_action: U)); +define!("mir_call", fn Call(call: (), goto: BasicBlock, unwind_action: U)); +define!("mir_unwind_resume", + /// A terminator that resumes the unwinding. + fn UnwindResume() +); + define!("mir_storage_live", fn StorageLive(local: T)); define!("mir_storage_dead", fn StorageDead(local: T)); define!("mir_deinit", fn Deinit(place: T)); @@ -382,16 +427,15 @@ pub macro mir { } $( - $block_name:ident = { + $block_name:ident $(($block_cleanup:ident))? = { $($block:tt)* } )* ) => {{ // First, we declare all basic blocks. - $( - let $block_name: ::core::intrinsics::mir::BasicBlock; - )* - + __internal_declare_basic_blocks!($( + $block_name $(($block_cleanup))? + )*); { // Now all locals #[allow(non_snake_case)] @@ -585,3 +629,17 @@ pub macro __internal_remove_let { } }, } + +/// Helper macro that declares the basic blocks. +#[doc(hidden)] +pub macro __internal_declare_basic_blocks { + () => {}, + ($name:ident (cleanup) $($rest:tt)*) => { + let $name = ::core::intrinsics::mir::BasicBlock::Cleanup; + __internal_declare_basic_blocks!($($rest)*) + }, + ($name:ident $($rest:tt)*) => { + let $name = ::core::intrinsics::mir::BasicBlock::Normal; + __internal_declare_basic_blocks!($($rest)*) + }, +} diff --git a/library/std/src/io/readbuf.rs b/library/core/src/io/borrowed_buf.rs similarity index 97% rename from library/std/src/io/readbuf.rs rename to library/core/src/io/borrowed_buf.rs index 034ddd8df9aed..fe25cac280fe3 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -1,10 +1,6 @@ -#![unstable(feature = "read_buf", issue = "78485")] - -#[cfg(test)] -mod tests; +#![unstable(feature = "core_io_borrowed_buf", issue = "117693")] use crate::fmt::{self, Debug, Formatter}; -use crate::io::{Result, Write}; use crate::mem::{self, MaybeUninit}; use crate::{cmp, ptr}; @@ -303,15 +299,3 @@ impl<'a> BorrowedCursor<'a> { self.buf.filled += buf.len(); } } - -impl<'a> Write for BorrowedCursor<'a> { - fn write(&mut self, buf: &[u8]) -> Result { - self.append(buf); - Ok(buf.len()) - } - - #[inline] - fn flush(&mut self) -> Result<()> { - Ok(()) - } -} diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs new file mode 100644 index 0000000000000..2f20180cdc9a2 --- /dev/null +++ b/library/core/src/io/mod.rs @@ -0,0 +1,6 @@ +//! Traits, helpers, and type definitions for core I/O functionality. + +mod borrowed_buf; + +#[unstable(feature = "core_io_borrowed_buf", issue = "117693")] +pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor}; diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 13719c727e93f..319af4408d76d 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -1,5 +1,9 @@ use crate::array; -use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce}; +use crate::iter::adapters::SourceIter; +use crate::iter::{ + ByRefSized, FusedIterator, InPlaceIterable, Iterator, TrustedFused, TrustedRandomAccessNoCoerce, +}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, NeverShortCircuit, Try}; /// An iterator over `N` elements of the iterator at a time. @@ -159,6 +163,9 @@ where #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] impl FusedIterator for ArrayChunks where I: FusedIterator {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for ArrayChunks where I: TrustedFused + Iterator {} + #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] impl ExactSizeIterator for ArrayChunks where @@ -229,3 +236,28 @@ where accum } } + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for ArrayChunks +where + I: SourceIter + Iterator, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.iter) } + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for ArrayChunks { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = const { + match (I::MERGE_BY, NonZeroUsize::new(N)) { + (Some(m), Some(n)) => m.checked_mul(n), + _ => None, + } + }; +} diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 8f6b2904eae42..7a2c9d839b7e4 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -193,7 +193,7 @@ where T: Copy, { default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter> { - array::iter_next_chunk(&mut self.map(|e| *e)) + array::iter_next_chunk(&mut self.copied()) } } diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 00c1c377bf9c2..92f465ccdb4e8 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -1,7 +1,7 @@ use crate::iter::adapters::{ zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen}; use crate::num::NonZeroUsize; use crate::ops::Try; @@ -243,6 +243,9 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Enumerate where I: FusedIterator {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Enumerate {} + #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Enumerate where I: TrustedLen {} @@ -261,7 +264,10 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Enumerate {} +unsafe impl InPlaceIterable for Enumerate { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; +} #[stable(feature = "default_iters", since = "1.70.0")] impl Default for Enumerate { diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index 723657b9e43e4..882f3e3bc60f5 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -1,5 +1,6 @@ use crate::fmt; -use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; +use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused}; +use crate::num::NonZeroUsize; use crate::ops::Try; use core::array; use core::mem::{ManuallyDrop, MaybeUninit}; @@ -189,6 +190,9 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Filter where P: FnMut(&I::Item) -> bool {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Filter {} + #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for Filter where @@ -204,4 +208,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Filter where P: FnMut(&I::Item) -> bool {} +unsafe impl InPlaceIterable for Filter { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; +} diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index 693479977db51..81ac0eaa67e95 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -1,5 +1,6 @@ -use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; +use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused}; use crate::mem::{ManuallyDrop, MaybeUninit}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; use crate::{array, fmt}; @@ -97,9 +98,11 @@ where // SAFETY: Loop conditions ensure the index is in bounds. unsafe { - let opt_payload_at = core::intrinsics::option_payload_ptr(&val); + let opt_payload_at: *const MaybeUninit = (&val as *const Option) + .byte_add(core::mem::offset_of!(Option, Some.0)) + .cast(); let dst = guard.array.as_mut_ptr().add(idx); - crate::ptr::copy_nonoverlapping(opt_payload_at.cast(), dst, 1); + crate::ptr::copy_nonoverlapping(opt_payload_at, dst, 1); crate::mem::forget(val); }; @@ -188,6 +191,9 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for FilterMap where F: FnMut(I::Item) -> Option {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for FilterMap {} + #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for FilterMap where @@ -203,7 +209,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for FilterMap where - F: FnMut(I::Item) -> Option -{ +unsafe impl InPlaceIterable for FilterMap { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; } diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index eee6e5bccecc7..09428350fd92a 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,7 +1,13 @@ -use crate::fmt; -use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen}; +use crate::iter::adapters::SourceIter; +use crate::iter::{ + Cloned, Copied, DoubleEndedIterator, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable, + Iterator, Map, TrustedFused, TrustedLen, +}; +use crate::iter::{Once, OnceWith}; use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; +use crate::result; +use crate::{array, fmt, option}; /// An iterator that maps each element to an iterator, and yields the elements /// of the produced iterators. @@ -145,6 +151,91 @@ where { } +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for FlatMap +where + I: InPlaceIterable, + U: BoundedSize + IntoIterator, +{ + const EXPAND_BY: Option = const { + match (I::EXPAND_BY, U::UPPER_BOUND) { + (Some(m), Some(n)) => m.checked_mul(n), + _ => None, + } + }; + const MERGE_BY: Option = I::MERGE_BY; +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for FlatMap +where + I: SourceIter + TrustedFused, + U: IntoIterator, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.inner.iter) } + } +} + +/// Marker trait for iterators/iterables which have a statically known upper +/// bound of the number of items they can produce. +/// +/// # Safety +/// +/// Implementations must not yield more elements than indicated by UPPER_BOUND if it is `Some`. +/// Used in specializations. Implementations must not be conditional on lifetimes or +/// user-implementable traits. +#[rustc_specialization_trait] +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe trait BoundedSize { + const UPPER_BOUND: Option = NonZeroUsize::new(1); +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Option {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for option::IntoIter {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Result {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for result::IntoIter {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Once {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for OnceWith {} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for [T; N] { + const UPPER_BOUND: Option = NonZeroUsize::new(N); +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for array::IntoIter { + const UPPER_BOUND: Option = NonZeroUsize::new(N); +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Filter { + const UPPER_BOUND: Option = I::UPPER_BOUND; +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for FilterMap { + const UPPER_BOUND: Option = I::UPPER_BOUND; +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Map { + const UPPER_BOUND: Option = I::UPPER_BOUND; +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Copied { + const UPPER_BOUND: Option = I::UPPER_BOUND; +} +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl BoundedSize for Cloned { + const UPPER_BOUND: Option = I::UPPER_BOUND; +} + /// An iterator that flattens one level of nesting in an iterator of things /// that can be turned into iterators. /// @@ -289,6 +380,36 @@ where { } +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for Flatten +where + I: InPlaceIterable + Iterator, + ::Item: IntoIterator + BoundedSize, +{ + const EXPAND_BY: Option = const { + match (I::EXPAND_BY, I::Item::UPPER_BOUND) { + (Some(m), Some(n)) => m.checked_mul(n), + _ => None, + } + }; + const MERGE_BY: Option = I::MERGE_BY; +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Flatten +where + I: SourceIter + TrustedFused + Iterator, + ::Item: IntoIterator, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements + unsafe { SourceIter::as_inner(&mut self.inner.iter) } + } +} + #[stable(feature = "default_iters", since = "1.70.0")] impl Default for Flatten where diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index b1fa4f92117b1..3234cade50dc5 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -1,8 +1,9 @@ use crate::intrinsics; use crate::iter::adapters::zip::try_get_unchecked; +use crate::iter::adapters::SourceIter; use crate::iter::{ - DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess, - TrustedRandomAccessNoCoerce, + DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedFused, TrustedLen, + TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::ops::Try; @@ -29,6 +30,9 @@ impl Fuse { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Fuse where I: Iterator {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Fuse where I: TrustedFused {} + // Any specialized implementation here is made internal // to avoid exposing default fns outside this trait. #[stable(feature = "rust1", since = "1.0.0")] @@ -418,6 +422,23 @@ where } } +// This is used by Flatten's SourceIter impl +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for Fuse +where + I: SourceIter + TrustedFused, +{ + type Source = I::Source; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut I::Source { + // SAFETY: unsafe function forwarding to unsafe function with the same requirements. + // TrustedFused guarantees that we'll never encounter a case where `self.iter` would + // be set to None. + unsafe { SourceIter::as_inner(self.iter.as_mut().unwrap_unchecked()) } + } +} + #[inline] fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option) -> Option { let x = f(opt.as_mut()?); diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 19839fdfe5bc3..fd2d830b693d1 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -1,5 +1,6 @@ use crate::fmt; -use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; +use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// An iterator that calls a function with a reference to each element before @@ -148,6 +149,9 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Inspect where F: FnMut(&I::Item) {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Inspect {} + #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for Inspect where @@ -163,4 +167,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Inspect where F: FnMut(&I::Item) {} +unsafe impl InPlaceIterable for Inspect { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; +} diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 31d02a4da6ea5..e27fc7257f6cc 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -2,7 +2,8 @@ use crate::fmt; use crate::iter::adapters::{ zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator}; +use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, UncheckedIterator}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// An iterator that maps the values of `iter` with `f`. @@ -179,6 +180,9 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Map where F: FnMut(I::Item) -> B {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Map {} + #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Map where @@ -228,4 +232,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Map where F: FnMut(I::Item) -> B {} +unsafe impl InPlaceIterable for Map { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; +} diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index fbdeca4d4ee4f..bcae73cbe09cf 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -1,5 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, InPlaceIterable}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator that only accepts elements while `predicate` returns `Some(_)`. @@ -82,7 +83,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for MapWhile where - P: FnMut(I::Item) -> Option -{ +unsafe impl InPlaceIterable for MapWhile { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; } diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 6f4fa7010f446..a691039c789c6 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,4 +1,5 @@ use crate::iter::{InPlaceIterable, Iterator}; +use crate::num::NonZeroUsize; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; mod array_chunks; @@ -119,8 +120,9 @@ pub unsafe trait SourceIter { /// /// # Safety /// - /// Implementations of must return the same mutable reference for their lifetime, unless + /// Implementations must return the same mutable reference for their lifetime, unless /// replaced by a caller. + /// /// Callers may only replace the reference when they stopped iteration and drop the /// iterator pipeline after extracting the source. /// @@ -228,7 +230,10 @@ where // in order to return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's // guaranteed that at least one item will be moved out from the underlying source. #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for GenericShunt<'_, I, R> where - I: Iterator> + InPlaceIterable +unsafe impl InPlaceIterable for GenericShunt<'_, I, R> +where + I: InPlaceIterable, { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; } diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 62470512cc747..635bad199ff95 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -1,5 +1,6 @@ use crate::fmt; use crate::iter::{adapters::SourceIter, InPlaceIterable}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator to maintain state while iterating another iterator. @@ -92,7 +93,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Scan where - F: FnMut(&mut St, I::Item) -> Option -{ +unsafe impl InPlaceIterable for Scan { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; } diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index 306338bc7cca0..e6c946e7f880d 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -1,4 +1,5 @@ use crate::intrinsics::unlikely; +use crate::iter::TrustedFused; use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; @@ -214,6 +215,9 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Skip where I: FusedIterator {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Skip {} + #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for Skip where @@ -229,4 +233,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Skip {} +unsafe impl InPlaceIterable for Skip { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; +} diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs index f29661779c056..3a661973e5fe0 100644 --- a/library/core/src/iter/adapters/skip_while.rs +++ b/library/core/src/iter/adapters/skip_while.rs @@ -1,5 +1,6 @@ use crate::fmt; -use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; +use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused}; +use crate::num::NonZeroUsize; use crate::ops::Try; /// An iterator that rejects elements while `predicate` returns `true`. @@ -104,6 +105,9 @@ where { } +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for SkipWhile {} + #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for SkipWhile where @@ -119,7 +123,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for SkipWhile where - F: FnMut(&I::Item) -> bool -{ +unsafe impl InPlaceIterable for SkipWhile { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; } diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs index 7f58f7d17758d..9e83584e3f3db 100644 --- a/library/core/src/iter/adapters/step_by.rs +++ b/library/core/src/iter/adapters/step_by.rs @@ -83,11 +83,7 @@ where // last element. Used in the `DoubleEndedIterator` implementation. fn next_back_index(&self) -> usize { let rem = self.iter.len() % (self.step + 1); - if self.first_take { - if rem == 0 { self.step } else { rem - 1 } - } else { - rem - } + if self.first_take { if rem == 0 { self.step } else { rem - 1 } } else { rem } } } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index c1d8cc4ff57bd..80e06066d28f9 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -1,6 +1,7 @@ use crate::cmp; use crate::iter::{ - adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess, + adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, + TrustedRandomAccess, }; use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; @@ -143,7 +144,10 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Take {} +unsafe impl InPlaceIterable for Take { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; +} #[stable(feature = "double_ended_take_iterator", since = "1.38.0")] impl DoubleEndedIterator for Take @@ -241,6 +245,9 @@ impl ExactSizeIterator for Take where I: ExactSizeIterator {} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Take where I: FusedIterator {} +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Take {} + #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Take {} diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index ec66dc3aec360..e55d55a6d2377 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -1,5 +1,6 @@ use crate::fmt; -use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable}; +use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused}; +use crate::num::NonZeroUsize; use crate::ops::{ControlFlow, Try}; /// An iterator that only accepts elements while `predicate` returns `true`. @@ -105,6 +106,9 @@ where { } +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for TakeWhile {} + #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for TakeWhile where @@ -120,7 +124,7 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for TakeWhile where - F: FnMut(&I::Item) -> bool -{ +unsafe impl InPlaceIterable for TakeWhile { + const EXPAND_BY: Option = I::EXPAND_BY; + const MERGE_BY: Option = I::MERGE_BY; } diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 77ccf5085022b..e3041519be707 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -1,7 +1,8 @@ use crate::cmp; use crate::fmt::{self, Debug}; -use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator}; +use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedFused}; use crate::iter::{InPlaceIterable, SourceIter, TrustedLen, UncheckedIterator}; +use crate::num::NonZeroUsize; /// An iterator that iterates two other iterators simultaneously. /// @@ -446,6 +447,14 @@ where { } +#[unstable(issue = "none", feature = "trusted_fused")] +unsafe impl TrustedFused for Zip +where + A: TrustedFused, + B: TrustedFused, +{ +} + #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Zip where @@ -479,7 +488,10 @@ where // Since SourceIter forwards the left hand side we do the same here #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for Zip {} +unsafe impl InPlaceIterable for Zip { + const EXPAND_BY: Option = A::EXPAND_BY; + const MERGE_BY: Option = A::MERGE_BY; +} #[stable(feature = "rust1", since = "1.0.0")] impl Debug for Zip { diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 937a149acaa50..44fef3e145b78 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -417,6 +417,8 @@ pub use self::sources::{successors, Successors}; pub use self::traits::FusedIterator; #[unstable(issue = "none", feature = "inplace_iteration")] pub use self::traits::InPlaceIterable; +#[unstable(issue = "none", feature = "trusted_fused")] +pub use self::traits::TrustedFused; #[unstable(feature = "trusted_len", issue = "37572")] pub use self::traits::TrustedLen; #[unstable(feature = "trusted_step", issue = "85731")] diff --git a/library/core/src/iter/sources/from_coroutine.rs b/library/core/src/iter/sources/from_coroutine.rs index 16fbca9b65e7d..bf413b24d4177 100644 --- a/library/core/src/iter/sources/from_coroutine.rs +++ b/library/core/src/iter/sources/from_coroutine.rs @@ -11,8 +11,7 @@ use crate::pin::Pin; /// # Examples /// /// ``` -/// #![cfg_attr(bootstrap, feature(generators))] -/// #![cfg_attr(not(bootstrap), feature(coroutines))] +/// #![feature(coroutines)] /// #![feature(iter_from_coroutine)] /// /// let it = std::iter::from_coroutine(|| { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 6adea444214eb..8e2c887a161e0 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -69,7 +69,7 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} message = "`{Self}` is not an iterator" )] #[doc(notable_trait)] -#[cfg_attr(not(bootstrap), lang = "iterator")] +#[lang = "iterator"] #[rustc_diagnostic_item = "Iterator"] #[must_use = "iterators are lazy and do nothing unless consumed"] pub trait Iterator { diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs index c21a2aac1c9a6..e7c1f195aacc6 100644 --- a/library/core/src/iter/traits/marker.rs +++ b/library/core/src/iter/traits/marker.rs @@ -1,4 +1,16 @@ use crate::iter::Step; +use crate::num::NonZeroUsize; + +/// Same as FusedIterator +/// +/// # Safety +/// +/// This is used for specialization. Therefore implementations must not +/// be lifetime-dependent. +#[unstable(issue = "none", feature = "trusted_fused")] +#[doc(hidden)] +#[rustc_specialization_trait] +pub unsafe trait TrustedFused {} /// An iterator that always continues to yield `None` when exhausted. /// @@ -14,6 +26,8 @@ use crate::iter::Step; /// [`Fuse`]: crate::iter::Fuse #[stable(feature = "fused", since = "1.26.0")] #[rustc_unsafe_specialization_marker] +// FIXME: this should be a #[marker] and have another blanket impl for T: TrustedFused +// but that ICEs iter::Fuse specializations. pub trait FusedIterator: Iterator {} #[stable(feature = "fused", since = "1.26.0")] @@ -71,7 +85,19 @@ unsafe impl TrustedLen for &mut I {} /// [`try_fold()`]: Iterator::try_fold #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] -pub unsafe trait InPlaceIterable: Iterator {} +#[rustc_specialization_trait] +pub unsafe trait InPlaceIterable { + /// The product of one-to-many item expansions that happen throughout the iterator pipeline. + /// E.g. [[u8; 4]; 4].iter().flatten().flatten() would have a `EXPAND_BY` of 16. + /// This is an upper bound, i.e. the transformations will produce at most this many items per + /// input. It's meant for layout calculations. + const EXPAND_BY: Option; + /// The product of many-to-one item reductions that happen throughout the iterator pipeline. + /// E.g. [u8].iter().array_chunks::<4>().array_chunks::<4>() would have a `MERGE_BY` of 16. + /// This is a lower bound, i.e. the transformations will consume at least this many items per + /// output. + const MERGE_BY: Option; +} /// A type that upholds all invariants of [`Step`]. /// diff --git a/library/core/src/iter/traits/mod.rs b/library/core/src/iter/traits/mod.rs index 41ea29e6a84d9..d4c9cc4b16037 100644 --- a/library/core/src/iter/traits/mod.rs +++ b/library/core/src/iter/traits/mod.rs @@ -18,6 +18,8 @@ pub use self::{ #[unstable(issue = "none", feature = "inplace_iteration")] pub use self::marker::InPlaceIterable; +#[unstable(issue = "none", feature = "trusted_fused")] +pub use self::marker::TrustedFused; #[unstable(feature = "trusted_step", issue = "85731")] pub use self::marker::TrustedStep; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index de643fb333efe..07720f235989b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -24,10 +24,9 @@ //! which are generated by Rust codegen backends. Additionally, this library can make explicit //! calls to `strlen`. Their signatures are the same as found in C, but there are extra //! assumptions about their semantics: For `memcpy`, `memmove`, `memset`, `memcmp`, and `bcmp`, if -//! the `n` parameter is 0, the function is assumed to not be UB. Furthermore, for `memcpy`, if -//! source and target pointer are equal, the function is assumed to not be UB. -//! (Note that these are standard assumptions among compilers: -//! [clang](https://reviews.llvm.org/D86993) and [GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=32667) do the same.) +//! the `n` parameter is 0, the function is assumed to not be UB, even if the pointers are NULL or +//! dangling. (Note that making extra assumptions about these functions is common among compilers: +//! [clang](https://reviews.llvm.org/D86993) and [GCC](https://gcc.gnu.org/onlinedocs/gcc/Standards.html#C-Language) do the same.) //! These functions are often provided by the system libc, but can also be provided by the //! [compiler-builtins crate](https://crates.io/crates/compiler_builtins). //! Note that the library does not guarantee that it will always make these assumptions, so Rust @@ -69,7 +68,7 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![doc(rust_logo)] #![doc(cfg_hide( not(test), any(not(feature = "miri-test-libstd"), test, doctest), @@ -178,6 +177,9 @@ #![feature(is_ascii_octdigit)] #![feature(isqrt)] #![feature(maybe_uninit_uninit_array)] +#![feature(non_null_convenience)] +#![feature(offset_of)] +#![feature(offset_of_enum)] #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] @@ -219,6 +221,7 @@ #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] +#![feature(effects)] #![feature(exhaustive_patterns)] #![feature(extern_types)] #![feature(fundamental)] @@ -369,6 +372,8 @@ pub mod async_iter; pub mod cell; pub mod char; pub mod ffi; +#[unstable(feature = "core_io_borrowed_buf", issue = "117693")] +pub mod io; pub mod iter; pub mod net; pub mod option; @@ -441,9 +446,10 @@ pub mod arch; #[unstable(feature = "portable_simd", issue = "86656")] mod core_simd; -#[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] #[unstable(feature = "portable_simd", issue = "86656")] pub mod simd { + #![doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] + #[unstable(feature = "portable_simd", issue = "86656")] pub use crate::core_simd::simd::*; } diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 125a6f57bfbaa..7f5908e477cfd 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1044,6 +1044,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] + #[rustc_diagnostic_item = "env_macro"] // useful for external lints macro_rules! env { ($name:expr $(,)?) => {{ /* compiler built-in */ }}; ($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }}; @@ -1074,6 +1075,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] + #[rustc_diagnostic_item = "option_env_macro"] // useful for external lints macro_rules! option_env { ($name:expr $(,)?) => {{ /* compiler built-in */ }}; } @@ -1479,6 +1481,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] + #[rustc_diagnostic_item = "include_macro"] // useful for external lints macro_rules! include { ($file:expr $(,)?) => {{ /* compiler built-in */ }}; } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 13437d8f96120..99762bccd18f2 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -253,6 +253,7 @@ marker_impls! { /// /// const CFN: Wrap = Wrap(higher_order); /// +/// #[allow(pointer_structural_match)] /// fn main() { /// match CFN { /// CFN => {} diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 855bb1675c59d..53e9a32e30554 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -374,6 +374,9 @@ impl MaybeUninit { /// assert_eq!(x, (0, false)); /// ``` /// + /// This can be used in const contexts, such as to indicate the end of static arrays for + /// plugin registration. + /// /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` /// when `0` is not a valid bit-pattern for the type: /// @@ -387,17 +390,19 @@ impl MaybeUninit { /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. /// // This is undefined behavior. ⚠️ /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_zeroed", issue = "91850")] - #[must_use] #[inline] + #[must_use] #[rustc_diagnostic_item = "maybe_uninit_zeroed"] + #[stable(feature = "maybe_uninit", since = "1.36.0")] + // These are OK to allow since we do not leak &mut to user-visible API + #[rustc_allow_const_fn_unstable(const_mut_refs)] + #[rustc_allow_const_fn_unstable(const_ptr_write)] + #[rustc_allow_const_fn_unstable(const_maybe_uninit_as_mut_ptr)] + #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "1.75.0")] pub const fn zeroed() -> MaybeUninit { let mut u = MaybeUninit::::uninit(); // SAFETY: `u.as_mut_ptr()` points to allocated memory. - unsafe { - u.as_mut_ptr().write_bytes(0u8, 1); - } + unsafe { u.as_mut_ptr().write_bytes(0u8, 1) }; u } @@ -686,10 +691,7 @@ impl MaybeUninit { /// // they both get dropped! /// ``` #[stable(feature = "maybe_uninit_extra", since = "1.60.0")] - #[rustc_const_stable( - feature = "const_maybe_uninit_assume_init_read", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_read", since = "1.75.0")] #[inline(always)] #[track_caller] pub const unsafe fn assume_init_read(&self) -> T { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 9159ecb740d9f..bf10ada0176c2 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -647,7 +647,8 @@ pub const fn needs_drop() -> bool { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] #[track_caller] -pub unsafe fn zeroed() -> T { +#[rustc_const_stable(feature = "const_mem_zeroed", since = "1.75.0")] +pub const unsafe fn zeroed() -> T { // SAFETY: the caller must guarantee that an all-zero value is valid for `T`. unsafe { intrinsics::assert_zero_valid::(); @@ -1131,10 +1132,12 @@ impl fmt::Debug for Discriminant { /// /// [Reference]: ../../reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations /// -/// The value of a [`Discriminant`] is independent of any *lifetimes* in `T`. As such, reading -/// or writing a `Discriminant>` as a `Discriminant>` (whether via [`transmute`] or -/// otherwise) is always sound. Note that this is **not** true for other kinds of generic -/// parameters; `Discriminant>` and `Discriminant>` might be incompatible. +/// The value of a [`Discriminant`] is independent of any *free lifetimes* in `T`. As such, +/// reading or writing a `Discriminant>` as a `Discriminant>` (whether via +/// [`transmute`] or otherwise) is always sound. Note that this is **not** true for other kinds +/// of generic parameters and for higher-ranked lifetimes; `Discriminant>` and +/// `Discriminant>` as well as `Discriminant Trait<'a>>>` and +/// `Discriminant>>` may be incompatible. /// /// # Examples /// @@ -1207,7 +1210,7 @@ impl fmt::Debug for Discriminant { /// // assert_eq!(0, unsafe { std::mem::transmute::<_, u8>(std::mem::discriminant(&unit_like)) }); /// ``` #[stable(feature = "discriminant_value", since = "1.21.0")] -#[rustc_const_stable(feature = "const_discriminant", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_discriminant", since = "1.75.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const fn discriminant(v: &T) -> Discriminant { @@ -1357,6 +1360,7 @@ impl SizedTypeProperties for T {} /// /// ``` /// #![feature(offset_of)] +/// # #![feature(offset_of_enum)] /// /// use std::mem; /// #[repr(C)] @@ -1386,12 +1390,9 @@ impl SizedTypeProperties for T {} /// B { one: u8, two: u16 }, /// } /// -/// # #[cfg(not(bootstrap))] /// assert_eq!(mem::offset_of!(Enum, A.0), 1); -/// # #[cfg(not(bootstrap))] /// assert_eq!(mem::offset_of!(Enum, B.two), 2); /// -/// # #[cfg(not(bootstrap))] /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` #[unstable(feature = "offset_of", issue = "106655")] diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index b7eca9b168a12..dafc58d3a7d91 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -425,8 +425,8 @@ impl IpAddr { #[inline] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[stable(feature = "ip_to_canonical", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ip_to_canonical", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_to_canonical", since = "1.75.0")] + #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")] pub const fn to_canonical(&self) -> IpAddr { match self { IpAddr::V4(_) => *self, @@ -468,7 +468,13 @@ impl Ipv4Addr { #[unstable(feature = "ip_bits", issue = "113744")] pub const BITS: u32 = 32; - /// Converts an IPv4 address into host byte order `u32`. + /// Converts an IPv4 address into a `u32` representation using native byte order. + /// + /// Although IPv4 addresses are big-endian, the `u32` value will use the target platform's + /// native byte order. That is, the `u32` value is an integer representation of the IPv4 + /// address and not an integer interpretation of the IPv4 address's big-endian bitstring. This + /// means that the `u32` value masked with `0xffffff00` will set the last octet in the address + /// to 0, regardless of the target platform's endianness. /// /// # Examples /// @@ -479,6 +485,16 @@ impl Ipv4Addr { /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); /// assert_eq!(0x12345678, addr.to_bits()); /// ``` + /// + /// ``` + /// #![feature(ip_bits)] + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); + /// let addr_bits = addr.to_bits() & 0xffffff00; + /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x00), Ipv4Addr::from_bits(addr_bits)); + /// + /// ``` #[rustc_const_unstable(feature = "ip_bits", issue = "113744")] #[unstable(feature = "ip_bits", issue = "113744")] #[must_use] @@ -487,7 +503,9 @@ impl Ipv4Addr { u32::from_be_bytes(self.octets) } - /// Converts a host byte order `u32` into an IPv4 address. + /// Converts a native byte order `u32` into an IPv4 address. + /// + /// See [`Ipv4Addr::to_bits`] for an explanation on endianness. /// /// # Examples /// @@ -1224,7 +1242,13 @@ impl Ipv6Addr { #[unstable(feature = "ip_bits", issue = "113744")] pub const BITS: u32 = 128; - /// Converts an IPv6 address into host byte order `u128`. + /// Converts an IPv6 address into a `u128` representation using native byte order. + /// + /// Although IPv6 addresses are big-endian, the `u128` value will use the target platform's + /// native byte order. That is, the `u128` value is an integer representation of the IPv6 + /// address and not an integer interpretation of the IPv6 address's big-endian bitstring. This + /// means that the `u128` value masked with `0xffffffffffffffffffffffffffff0000_u128` will set + /// the last segment in the address to 0, regardless of the target platform's endianness. /// /// # Examples /// @@ -1238,6 +1262,24 @@ impl Ipv6Addr { /// ); /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr)); /// ``` + /// + /// ``` + /// #![feature(ip_bits)] + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::new( + /// 0x1020, 0x3040, 0x5060, 0x7080, + /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, + /// ); + /// let addr_bits = addr.to_bits() & 0xffffffffffffffffffffffffffff0000_u128; + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x1020, 0x3040, 0x5060, 0x7080, + /// 0x90A0, 0xB0C0, 0xD0E0, 0x0000, + /// ), + /// Ipv6Addr::from_bits(addr_bits)); + /// + /// ``` #[rustc_const_unstable(feature = "ip_bits", issue = "113744")] #[unstable(feature = "ip_bits", issue = "113744")] #[must_use] @@ -1246,7 +1288,9 @@ impl Ipv6Addr { u128::from_be_bytes(self.octets) } - /// Converts a host byte order `u128` into an IPv6 address. + /// Converts a native byte order `u128` into an IPv6 address. + /// + /// See [`Ipv6Addr::to_bits`] for an explanation on endianness. /// /// # Examples /// @@ -1757,7 +1801,7 @@ impl Ipv6Addr { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")] - #[rustc_const_stable(feature = "const_ipv6_to_ipv4_mapped", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ipv6_to_ipv4_mapped", since = "1.75.0")] pub const fn to_ipv4_mapped(&self) -> Option { match self.octets() { [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => { @@ -1825,8 +1869,8 @@ impl Ipv6Addr { #[inline] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[stable(feature = "ip_to_canonical", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ip_to_canonical", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_to_canonical", since = "1.75.0")] + #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")] pub const fn to_canonical(&self) -> IpAddr { if let Some(mapped) = self.to_ipv4_mapped() { return IpAddr::V4(mapped); @@ -2128,7 +2172,7 @@ impl From<[u16; 8]> for IpAddr { } } -#[stable(feature = "ip_bitops", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "ip_bitops", since = "1.75.0")] impl Not for Ipv4Addr { type Output = Ipv4Addr; @@ -2141,7 +2185,7 @@ impl Not for Ipv4Addr { } } -#[stable(feature = "ip_bitops", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "ip_bitops", since = "1.75.0")] impl Not for &'_ Ipv4Addr { type Output = Ipv4Addr; @@ -2151,7 +2195,7 @@ impl Not for &'_ Ipv4Addr { } } -#[stable(feature = "ip_bitops", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "ip_bitops", since = "1.75.0")] impl Not for Ipv6Addr { type Output = Ipv6Addr; @@ -2164,7 +2208,7 @@ impl Not for Ipv6Addr { } } -#[stable(feature = "ip_bitops", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "ip_bitops", since = "1.75.0")] impl Not for &'_ Ipv6Addr { type Output = Ipv6Addr; @@ -2246,13 +2290,13 @@ macro_rules! bitop_impls { } bitop_impls! { - #[stable(feature = "ip_bitops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_bitops", since = "1.75.0")] impl (BitAnd, BitAndAssign) for Ipv4Addr = (bitand, bitand_assign); - #[stable(feature = "ip_bitops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_bitops", since = "1.75.0")] impl (BitOr, BitOrAssign) for Ipv4Addr = (bitor, bitor_assign); - #[stable(feature = "ip_bitops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_bitops", since = "1.75.0")] impl (BitAnd, BitAndAssign) for Ipv6Addr = (bitand, bitand_assign); - #[stable(feature = "ip_bitops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_bitops", since = "1.75.0")] impl (BitOr, BitOrAssign) for Ipv6Addr = (bitor, bitor_assign); } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index f60626b00dc8a..709eba2ffc9ac 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1424,9 +1424,17 @@ impl f32 { /// ]; /// /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight)); - /// # assert!(bois.into_iter().map(|b| b.weight) - /// # .zip([-5.0, 0.1, 10.0, 99.0, f32::INFINITY, f32::NAN].iter()) - /// # .all(|(a, b)| a.to_bits() == b.to_bits())) + /// + /// // `f32::NAN` could be positive or negative, which will affect the sort order. + /// if f32::NAN.is_sign_negative() { + /// assert!(bois.into_iter().map(|b| b.weight) + /// .zip([f32::NAN, -5.0, 0.1, 10.0, 99.0, f32::INFINITY].iter()) + /// .all(|(a, b)| a.to_bits() == b.to_bits())) + /// } else { + /// assert!(bois.into_iter().map(|b| b.weight) + /// .zip([-5.0, 0.1, 10.0, 99.0, f32::INFINITY, f32::NAN].iter()) + /// .all(|(a, b)| a.to_bits() == b.to_bits())) + /// } /// ``` #[stable(feature = "total_cmp", since = "1.62.0")] #[must_use] diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 0a87021d8c183..73fa61574cc42 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1422,9 +1422,17 @@ impl f64 { /// ]; /// /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight)); - /// # assert!(bois.into_iter().map(|b| b.weight) - /// # .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter()) - /// # .all(|(a, b)| a.to_bits() == b.to_bits())) + /// + /// // `f64::NAN` could be positive or negative, which will affect the sort order. + /// if f64::NAN.is_sign_negative() { + /// assert!(bois.into_iter().map(|b| b.weight) + /// .zip([f64::NAN, -5.0, 0.1, 10.0, 99.0, f64::INFINITY].iter()) + /// .all(|(a, b)| a.to_bits() == b.to_bits())) + /// } else { + /// assert!(bois.into_iter().map(|b| b.weight) + /// .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter()) + /// .all(|(a, b)| a.to_bits() == b.to_bits())) + /// } /// ``` #[stable(feature = "total_cmp", since = "1.62.0")] #[must_use] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 2a0b31404f035..695e87aaabf8a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -474,7 +474,7 @@ impl isize { } } -/// If 6th bit is set ascii is lower case. +/// If the 6th bit is set ascii is lower case. const ASCII_CASE_MASK: u8 = 0b0010_0000; impl u8 { @@ -549,7 +549,7 @@ impl u8 { #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] pub const fn to_ascii_uppercase(&self) -> u8 { - // Toggle the fifth bit if this is a lowercase letter + // Toggle the 6th bit if this is a lowercase letter *self ^ ((self.is_ascii_lowercase() as u8) * ASCII_CASE_MASK) } @@ -574,7 +574,7 @@ impl u8 { #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] pub const fn to_ascii_lowercase(&self) -> u8 { - // Set the fifth bit if this is an uppercase letter + // Set the 6th bit if this is an uppercase letter *self | (self.is_ascii_uppercase() as u8 * ASCII_CASE_MASK) } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 7f8d673c179a3..f5ecf501ce990 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -75,12 +75,12 @@ macro_rules! nonzero_integers { #[must_use] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { + crate::panic::debug_assert_nounwind!( + n != 0, + concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") + ); // SAFETY: this is guaranteed to be safe by the caller. unsafe { - core::intrinsics::assert_unsafe_precondition!( - concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument"), - (n: $Int) => n != 0 - ); Self(n) } } @@ -353,8 +353,13 @@ macro_rules! nonzero_unsigned_operations { #[inline] pub const fn checked_add(self, other: $Int) -> Option<$Ty> { if let Some(result) = self.get().checked_add(other) { - // SAFETY: $Int::checked_add returns None on overflow - // so the result cannot be zero. + // SAFETY: + // - `checked_add` returns `None` on overflow + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. Some(unsafe { $Ty::new_unchecked(result) }) } else { None @@ -386,8 +391,13 @@ macro_rules! nonzero_unsigned_operations { without modifying the original"] #[inline] pub const fn saturating_add(self, other: $Int) -> $Ty { - // SAFETY: $Int::saturating_add returns $Int::MAX on overflow - // so the result cannot be zero. + // SAFETY: + // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } } @@ -1000,9 +1010,13 @@ macro_rules! nonzero_unsigned_signed_operations { #[inline] pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { if let Some(result) = self.get().checked_mul(other.get()) { - // SAFETY: checked_mul returns None on overflow - // and `other` is also non-null - // so the result cannot be zero. + // SAFETY: + // - `checked_mul` returns `None` on overflow + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. Some(unsafe { $Ty::new_unchecked(result) }) } else { None @@ -1034,9 +1048,14 @@ macro_rules! nonzero_unsigned_signed_operations { without modifying the original"] #[inline] pub const fn saturating_mul(self, other: $Ty) -> $Ty { - // SAFETY: saturating_mul returns u*::MAX on overflow - // and `other` is also non-null - // so the result cannot be zero. + // SAFETY: + // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } } @@ -1107,8 +1126,13 @@ macro_rules! nonzero_unsigned_signed_operations { #[inline] pub const fn checked_pow(self, other: u32) -> Option<$Ty> { if let Some(result) = self.get().checked_pow(other) { - // SAFETY: checked_pow returns None on overflow - // so the result cannot be zero. + // SAFETY: + // - `checked_pow` returns `None` on overflow/underflow + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. Some(unsafe { $Ty::new_unchecked(result) }) } else { None @@ -1149,8 +1173,14 @@ macro_rules! nonzero_unsigned_signed_operations { without modifying the original"] #[inline] pub const fn saturating_pow(self, other: u32) -> $Ty { - // SAFETY: saturating_pow returns u*::MAX on overflow - // so the result cannot be zero. + // SAFETY: + // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } } } diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 840c8cd2fe8d0..1773fdbf37cc7 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -98,6 +98,7 @@ macro_rules! add_impl { type Output = $t; #[inline] + #[track_caller] #[rustc_inherit_overflow_checks] fn add(self, other: $t) -> $t { self + other } } @@ -206,6 +207,7 @@ macro_rules! sub_impl { type Output = $t; #[inline] + #[track_caller] #[rustc_inherit_overflow_checks] fn sub(self, other: $t) -> $t { self - other } } @@ -335,6 +337,7 @@ macro_rules! mul_impl { type Output = $t; #[inline] + #[track_caller] #[rustc_inherit_overflow_checks] fn mul(self, other: $t) -> $t { self * other } } @@ -474,6 +477,7 @@ macro_rules! div_impl_integer { type Output = $t; #[inline] + #[track_caller] fn div(self, other: $t) -> $t { self / other } } @@ -575,6 +579,7 @@ macro_rules! rem_impl_integer { type Output = $t; #[inline] + #[track_caller] fn rem(self, other: $t) -> $t { self % other } } @@ -749,6 +754,7 @@ macro_rules! add_assign_impl { #[stable(feature = "op_assign_traits", since = "1.8.0")] impl AddAssign for $t { #[inline] + #[track_caller] #[rustc_inherit_overflow_checks] fn add_assign(&mut self, other: $t) { *self += other } } @@ -815,6 +821,7 @@ macro_rules! sub_assign_impl { #[stable(feature = "op_assign_traits", since = "1.8.0")] impl SubAssign for $t { #[inline] + #[track_caller] #[rustc_inherit_overflow_checks] fn sub_assign(&mut self, other: $t) { *self -= other } } @@ -872,6 +879,7 @@ macro_rules! mul_assign_impl { #[stable(feature = "op_assign_traits", since = "1.8.0")] impl MulAssign for $t { #[inline] + #[track_caller] #[rustc_inherit_overflow_checks] fn mul_assign(&mut self, other: $t) { *self *= other } } @@ -929,6 +937,7 @@ macro_rules! div_assign_impl { #[stable(feature = "op_assign_traits", since = "1.8.0")] impl DivAssign for $t { #[inline] + #[track_caller] fn div_assign(&mut self, other: $t) { *self /= other } } @@ -989,6 +998,7 @@ macro_rules! rem_assign_impl { #[stable(feature = "op_assign_traits", since = "1.8.0")] impl RemAssign for $t { #[inline] + #[track_caller] fn rem_assign(&mut self, other: $t) { *self %= other } } diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index cd5ca988f7e03..80e2903992ec3 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -7,8 +7,7 @@ use crate::pin::Pin; /// possible return values of a coroutine. Currently this corresponds to either /// a suspension point (`Yielded`) or a termination point (`Complete`). #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] -#[cfg_attr(bootstrap, lang = "generator_state")] -#[cfg_attr(not(bootstrap), lang = "coroutine_state")] +#[lang = "coroutine_state"] #[unstable(feature = "coroutine_trait", issue = "43122")] pub enum CoroutineState { /// The coroutine suspended with a value. @@ -40,8 +39,7 @@ pub enum CoroutineState { /// closure-like: /// /// ```rust -/// #![cfg_attr(bootstrap, feature(generators))] -/// #![cfg_attr(not(bootstrap), feature(coroutines))] +/// #![feature(coroutines)] /// #![feature(coroutine_trait)] /// /// use std::ops::{Coroutine, CoroutineState}; @@ -68,8 +66,7 @@ pub enum CoroutineState { /// /// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 /// [unstable book]: ../../unstable-book/language-features/coroutines.html -#[cfg_attr(bootstrap, lang = "generator")] -#[cfg_attr(not(bootstrap), lang = "coroutine")] +#[lang = "coroutine"] #[unstable(feature = "coroutine_trait", issue = "43122")] #[fundamental] pub trait Coroutine { diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index d6f2f5ca3662b..99adbb91599ac 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -3,40 +3,107 @@ /// In addition to being used for explicit dereferencing operations with the /// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly /// by the compiler in many circumstances. This mechanism is called -/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used. +/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and +/// mutable deref coercion similarly occurs. /// -/// Implementing `Deref` for smart pointers makes accessing the data behind them -/// convenient, which is why they implement `Deref`. On the other hand, the -/// rules regarding `Deref` and [`DerefMut`] were designed specifically to -/// accommodate smart pointers. Because of this, **`Deref` should only be -/// implemented for smart pointers** to avoid confusion. +/// **Warning:** Deref coercion is a powerful language feature which has +/// far-reaching implications for every type that implements `Deref`. The +/// compiler will silently insert calls to `Deref::deref`. For this reason, one +/// should be careful about implementing `Deref` and only do so when deref +/// coercion is desirable. See [below][implementing] for advice on when this is +/// typically desirable or undesirable. /// -/// For similar reasons, **this trait should never fail**. Failure during -/// dereferencing can be extremely confusing when `Deref` is invoked implicitly. +/// Types that implement `Deref` or `DerefMut` are often called "smart +/// pointers" and the mechanism of deref coercion has been specifically designed +/// to facilitate the pointer-like behaviour that name suggests. Often, the +/// purpose of a "smart pointer" type is to change the ownership semantics +/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the +/// storage semantics of a contained value (for example, [`Box`][box]). /// -/// Violating these requirements is a logic error. The behavior resulting from a logic error is not -/// specified, but users of the trait must ensure that such logic errors do *not* result in -/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this -/// method. +/// # Deref coercion /// -/// # More on `Deref` coercion +/// If `T` implements `Deref`, and `v` is a value of type `T`, then: /// -/// If `T` implements `Deref`, and `x` is a value of type `T`, then: -/// -/// * In immutable contexts, `*x` (where `T` is neither a reference nor a raw pointer) -/// is equivalent to `*Deref::deref(&x)`. +/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw +/// pointer) is equivalent to `*Deref::deref(&v)`. /// * Values of type `&T` are coerced to values of type `&U` -/// * `T` implicitly implements all the (immutable) methods of the type `U`. +/// * `T` implicitly implements all the methods of the type `U` which take the +/// `&self` receiver. /// /// For more details, visit [the chapter in *The Rust Programming Language*][book] /// as well as the reference sections on [the dereference operator][ref-deref-op], -/// [method resolution] and [type coercions]. +/// [method resolution], and [type coercions]. +/// +/// # When to implement `Deref` or `DerefMut` +/// +/// The same advice applies to both deref traits. In general, deref traits +/// **should** be implemented if: +/// +/// 1. a value of the type transparently behaves like a value of the target +/// type; +/// 1. the implementation of the deref function is cheap; and +/// 1. users of the type will not be surprised by any deref coercion behaviour. +/// +/// In general, deref traits **should not** be implemented if: +/// +/// 1. the deref implementations could fail unexpectedly; or +/// 1. the type has methods that are likely to collide with methods on the +/// target type; or +/// 1. committing to deref coercion as part of the public API is not desirable. +/// +/// Note that there's a large difference between implementing deref traits +/// generically over many target types, and doing so only for specific target +/// types. +/// +/// Generic implementations, such as for [`Box`][box] (which is generic over +/// every type and dereferences to `T`) should be careful to provide few or no +/// methods, since the target type is unknown and therefore every method could +/// collide with one on the target type, causing confusion for users. +/// `impl Box` has no methods (though several associated functions), +/// partly for this reason. +/// +/// Specific implementations, such as for [`String`][string] (whose `Deref` +/// implementation has `Target = str`) can have many methods, since avoiding +/// collision is much easier. `String` and `str` both have many methods, and +/// `String` additionally behaves as if it has every method of `str` because of +/// deref coercion. The implementing type may also be generic while the +/// implementation is still specific in this sense; for example, [`Vec`][vec] +/// dereferences to `[T]`, so methods of `T` are not applicable. +/// +/// Consider also that deref coericion means that deref traits are a much larger +/// part of a type's public API than any other trait as it is implicitly called +/// by the compiler. Therefore, it is advisable to consider whether this is +/// something you are comfortable supporting as a public API. +/// +/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar +/// signatures to `Deref`. It may be desirable to implement either or both of +/// these, whether in addition to or rather than deref traits. See their +/// documentation for details. +/// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `Deref::deref` implicitly. Failure +/// during dereferencing can be extremely confusing when `Deref` is invoked +/// implicitly. In the majority of uses it should be infallible, though it may +/// be acceptable to panic if the type is misused through programmer error, for +/// example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. /// /// [book]: ../../book/ch15-02-deref.html -/// [more]: #more-on-deref-coercion +/// [coercion]: #deref-coercion +/// [implementing]: #when-to-implement-deref-or-derefmut /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator /// [method resolution]: ../../reference/expressions/method-call-expr.html /// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [vec]: ../../alloc/vec/struct.Vec.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html /// /// # Examples /// @@ -107,30 +174,29 @@ impl Deref for &mut T { /// In addition to being used for explicit dereferencing operations with the /// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly /// by the compiler in many circumstances. This mechanism is called -/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used. -/// -/// Implementing `DerefMut` for smart pointers makes mutating the data behind -/// them convenient, which is why they implement `DerefMut`. On the other hand, -/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to -/// accommodate smart pointers. Because of this, **`DerefMut` should only be -/// implemented for smart pointers** to avoid confusion. +/// ["mutable deref coercion"][coercion]. In immutable contexts, [`Deref`] is used. /// -/// For similar reasons, **this trait should never fail**. Failure during -/// dereferencing can be extremely confusing when `DerefMut` is invoked -/// implicitly. +/// **Warning:** Deref coercion is a powerful language feature which has +/// far-reaching implications for every type that implements `DerefMut`. The +/// compiler will silently insert calls to `DerefMut::deref_mut`. For this +/// reason, one should be careful about implementing `DerefMut` and only do so +/// when mutable deref coercion is desirable. See [the `Deref` docs][implementing] +/// for advice on when this is typically desirable or undesirable. /// -/// Violating these requirements is a logic error. The behavior resulting from a logic error is not -/// specified, but users of the trait must ensure that such logic errors do *not* result in -/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this -/// method. +/// Types that implement `DerefMut` or `Deref` are often called "smart +/// pointers" and the mechanism of deref coercion has been specifically designed +/// to facilitate the pointer-like behaviour that name suggests. Often, the +/// purpose of a "smart pointer" type is to change the ownership semantics +/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the +/// storage semantics of a contained value (for example, [`Box`][box]). /// -/// # More on `Deref` coercion +/// # Mutable deref coercion /// -/// If `T` implements `DerefMut`, and `x` is a value of type `T`, +/// If `T` implements `DerefMut`, and `v` is a value of type `T`, /// then: /// -/// * In mutable contexts, `*x` (where `T` is neither a reference nor a raw pointer) -/// is equivalent to `*DerefMut::deref_mut(&mut x)`. +/// * In mutable contexts, `*v` (where `T` is neither a reference nor a raw pointer) +/// is equivalent to `*DerefMut::deref_mut(&mut v)`. /// * Values of type `&mut T` are coerced to values of type `&mut U` /// * `T` implicitly implements all the (mutable) methods of the type `U`. /// @@ -138,11 +204,29 @@ impl Deref for &mut T { /// as well as the reference sections on [the dereference operator][ref-deref-op], /// [method resolution] and [type coercions]. /// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `DerefMut::deref_mut` implicitly. +/// Failure during dereferencing can be extremely confusing when `DerefMut` is +/// invoked implicitly. In the majority of uses it should be infallible, though +/// it may be acceptable to panic if the type is misused through programmer +/// error, for example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. +/// /// [book]: ../../book/ch15-02-deref.html -/// [more]: #more-on-deref-coercion +/// [coercion]: #mutable-deref-coercion +/// [implementing]: Deref#when-to-implement-deref-or-derefmut /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator /// [method resolution]: ../../reference/expressions/method-call-expr.html /// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html /// /// # Examples /// diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 51e304dd7c247..3a3d3fcf1da64 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -56,7 +56,7 @@ use crate::marker::Tuple; #[lang = "fn"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] -#[cfg_attr(not(bootstrap), rustc_on_unimplemented( +#[rustc_on_unimplemented( on( Args = "()", note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" @@ -69,7 +69,7 @@ use crate::marker::Tuple; ), message = "expected a `{Trait}` closure, found `{Self}`", label = "expected an `{Trait}` closure, found `{Self}`" -))] +)] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] // FIXME(effects) #[const_trait] @@ -143,7 +143,7 @@ pub trait Fn: FnMut { #[lang = "fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] -#[cfg_attr(not(bootstrap), rustc_on_unimplemented( +#[rustc_on_unimplemented( on( Args = "()", note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" @@ -156,7 +156,7 @@ pub trait Fn: FnMut { ), message = "expected a `{Trait}` closure, found `{Self}`", label = "expected an `{Trait}` closure, found `{Self}`" -))] +)] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] // FIXME(effects) #[const_trait] @@ -222,7 +222,7 @@ pub trait FnMut: FnOnce { #[lang = "fn_once"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] -#[cfg_attr(not(bootstrap), rustc_on_unimplemented( +#[rustc_on_unimplemented( on( Args = "()", note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" @@ -235,7 +235,7 @@ pub trait FnMut: FnOnce { ), message = "expected a `{Trait}` closure, found `{Self}`", label = "expected an `{Trait}` closure, found `{Self}`" -))] +)] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] // FIXME(effects) #[const_trait] diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index 265022a394e88..743799c4b3edf 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -1,4 +1,4 @@ -use crate::intrinsics::{assert_unsafe_precondition, unchecked_add, unchecked_sub}; +use crate::intrinsics::{unchecked_add, unchecked_sub}; use crate::iter::{FusedIterator, TrustedLen}; use crate::num::NonZeroUsize; @@ -19,13 +19,10 @@ impl IndexRange { /// - `start <= end` #[inline] pub const unsafe fn new_unchecked(start: usize, end: usize) -> Self { - // SAFETY: comparisons on usize are pure - unsafe { - assert_unsafe_precondition!( - "IndexRange::new_unchecked requires `start <= end`", - (start: usize, end: usize) => start <= end - ) - }; + crate::panic::debug_assert_nounwind!( + start <= end, + "IndexRange::new_unchecked requires `start <= end`" + ); IndexRange { start, end } } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index acf3dfbdf4cf4..bfd6aee4a2357 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -119,7 +119,7 @@ //! # Representation //! //! Rust guarantees to optimize the following types `T` such that -//! [`Option`] has the same size and alignment as `T`. In some +//! [`Option`] has the same size, alignment, and [function call ABI] as `T`. In some //! of these cases, Rust further guarantees that //! `transmute::<_, Option>([0u8; size_of::()])` is sound and //! produces `Option::::None`. These cases are identified by the @@ -127,7 +127,7 @@ //! //! | `T` | `transmute::<_, Option>([0u8; size_of::()])` sound? | //! |---------------------------------------------------------------------|----------------------------------------------------------------------| -//! | [`Box`] | when `U: Sized` | +//! | [`Box`] (specifically, only `Box`) | when `U: Sized` | //! | `&U` | when `U: Sized` | //! | `&mut U` | when `U: Sized` | //! | `fn`, `extern "C" fn`[^extern_fn] | always | @@ -135,11 +135,12 @@ //! | [`ptr::NonNull`] | when `U: Sized` | //! | `#[repr(transparent)]` struct around one of the types in this list. | when it holds for the inner type | //! -//! [^extern_fn]: this remains true for any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`) +//! [^extern_fn]: this remains true for any argument/return types and any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`) //! //! [`Box`]: ../../std/boxed/struct.Box.html //! [`num::NonZero*`]: crate::num //! [`ptr::NonNull`]: crate::ptr::NonNull +//! [function call ABI]: ../primitive.fn.html#abi-compatibility //! //! This is called the "null pointer optimization" or NPO. //! @@ -765,7 +766,7 @@ impl Option { /// ``` #[inline] #[must_use] - #[stable(feature = "option_as_slice", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "option_as_slice", since = "1.75.0")] pub fn as_slice(&self) -> &[T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to @@ -779,7 +780,7 @@ impl Option { // `None` case it's just padding). unsafe { slice::from_raw_parts( - crate::intrinsics::option_payload_ptr(crate::ptr::from_ref(self)), + (self as *const Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(), usize::from(self.is_some()), ) } @@ -819,7 +820,7 @@ impl Option { /// ``` #[inline] #[must_use] - #[stable(feature = "option_as_slice", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "option_as_slice", since = "1.75.0")] pub fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to @@ -835,8 +836,7 @@ impl Option { // the `None` case it's just padding). unsafe { slice::from_raw_parts_mut( - crate::intrinsics::option_payload_ptr(crate::ptr::from_mut(self).cast_const()) - .cast_mut(), + (self as *mut Self).byte_add(core::mem::offset_of!(Self, Some.0)).cast(), usize::from(self.is_some()), ) } @@ -1079,8 +1079,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// let v = vec![1, 2, 3, 4, 5]; /// /// // prints "got: 4" @@ -1090,11 +1088,8 @@ impl Option { /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {x}")); /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] - pub fn inspect(self, f: F) -> Self - where - F: FnOnce(&T), - { + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] + pub fn inspect(self, f: F) -> Self { if let Some(ref x) = self { f(x); } diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index a00fd322b3ce7..4ca5af1eaea32 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -47,7 +47,7 @@ pub macro panic_2015 { #[allow_internal_unstable(core_panic, const_format_args)] #[rustc_diagnostic_item = "core_panic_2021_macro"] #[rustc_macro_transparency = "semitransparent"] -#[cfg(any(bootstrap, feature = "panic_immediate_abort"))] +#[cfg(feature = "panic_immediate_abort")] pub macro panic_2021 { () => ( $crate::panicking::panic("explicit panic") @@ -75,7 +75,7 @@ pub macro panic_2021 { )] #[rustc_diagnostic_item = "core_panic_2021_macro"] #[rustc_macro_transparency = "semitransparent"] -#[cfg(not(any(bootstrap, feature = "panic_immediate_abort")))] +#[cfg(not(feature = "panic_immediate_abort"))] pub macro panic_2021 { () => ({ // Create a function so that the argument for `track_caller` @@ -139,6 +139,32 @@ pub macro unreachable_2021 { ), } +/// Asserts that a boolean expression is `true`, and perform a non-unwinding panic otherwise. +/// +/// This macro is similar to `debug_assert!`, but is intended to be used in code that should not +/// unwind. For example, checks in `_unchecked` functions that are intended for debugging but should +/// not compromise unwind safety. +#[doc(hidden)] +#[unstable(feature = "core_panic", issue = "none")] +#[allow_internal_unstable(core_panic, const_format_args)] +#[rustc_macro_transparency = "semitransparent"] +pub macro debug_assert_nounwind { + ($cond:expr $(,)?) => { + if $crate::cfg!(debug_assertions) { + if !$cond { + $crate::panicking::panic_nounwind($crate::concat!("assertion failed: ", $crate::stringify!($cond))); + } + } + }, + ($cond:expr, $($arg:tt)+) => { + if $crate::cfg!(debug_assertions) { + if !$cond { + $crate::panicking::panic_nounwind_fmt($crate::const_format_args!($($arg)+), false); + } + } + }, +} + /// An internal trait used by std to pass data from std to `panic_unwind` and /// other panic runtimes. Not intended to be stabilized any time soon, do not /// use. diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 39a5e8d9fe2ec..1b6e77b96b1dd 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -82,28 +82,45 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { // and unwinds anyway, we will hit the "unwinding out of nounwind function" guard, // which causes a "panic in a function that cannot unwind". #[rustc_nounwind] -pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { - if cfg!(feature = "panic_immediate_abort") { - super::intrinsics::abort() - } +#[rustc_const_unstable(feature = "core_panic", issue = "none")] +pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { + #[inline] // this should always be inlined into `panic_nounwind_fmt` + #[track_caller] + fn runtime(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { + if cfg!(feature = "panic_immediate_abort") { + super::intrinsics::abort() + } - // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - // that gets resolved to the `#[panic_handler]` function. - extern "Rust" { - #[lang = "panic_impl"] - fn panic_impl(pi: &PanicInfo<'_>) -> !; + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + extern "Rust" { + #[lang = "panic_impl"] + fn panic_impl(pi: &PanicInfo<'_>) -> !; + } + + // PanicInfo with the `can_unwind` flag set to false forces an abort. + let pi = PanicInfo::internal_constructor( + Some(&fmt), + Location::caller(), + /* can_unwind */ false, + force_no_backtrace, + ); + + // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. + unsafe { panic_impl(&pi) } } - // PanicInfo with the `can_unwind` flag set to false forces an abort. - let pi = PanicInfo::internal_constructor( - Some(&fmt), - Location::caller(), - /* can_unwind */ false, - force_no_backtrace, - ); + #[inline] + #[track_caller] + const fn comptime(fmt: fmt::Arguments<'_>, _force_no_backtrace: bool) -> ! { + // We don't unwind anyway at compile-time so we can call the regular `panic_fmt`. + panic_fmt(fmt); + } - // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. - unsafe { panic_impl(&pi) } + // SAFETY: const panic does not care about unwinding + unsafe { + super::intrinsics::const_eval_select((fmt, force_no_backtrace), comptime, runtime); + } } // Next we define a bunch of higher-level wrappers that all bottom out in the two core functions @@ -127,12 +144,14 @@ pub const fn panic(expr: &'static str) -> ! { panic_fmt(fmt::Arguments::new_const(&[expr])); } -/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize. +/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize on the caller. +/// If you want `#[track_caller]` for nicer errors, call `panic_nounwind_fmt` directly. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics #[rustc_nounwind] -pub fn panic_nounwind(expr: &'static str) -> ! { +#[rustc_const_unstable(feature = "core_panic", issue = "none")] +pub const fn panic_nounwind(expr: &'static str) -> ! { panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false); } @@ -170,9 +189,8 @@ pub fn unreachable_display(x: &T) -> ! { #[inline] #[track_caller] #[rustc_do_not_const_check] // hooked by const-eval -#[cfg_attr(bootstrap, lang = "panic_display")] // enforce a &&str argument in const-check and hook this by const-eval -#[cfg_attr(not(bootstrap), rustc_const_panic_str)] +#[rustc_const_panic_str] #[rustc_const_unstable(feature = "core_panic", issue = "none")] pub const fn panic_display(x: &T) -> ! { panic_fmt(format_args!("{}", *x)); @@ -190,8 +208,8 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { panic!("index out of bounds: the len is {len} but the index is {index}") } -#[cold] -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] #[lang = "panic_misaligned_pointer_dereference"] // needed by codegen for panic on misaligned pointer deref #[rustc_nounwind] // `CheckAlignment` MIR pass requires this function to never unwind diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index bca97d4ee3643..c3e774e1dab15 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1088,8 +1088,7 @@ impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// ### With `Coroutine`s /// /// ```rust -/// #![cfg_attr(bootstrap, feature(generators))] -/// #![cfg_attr(not(bootstrap), feature(coroutines))] +/// #![feature(coroutines)] /// #![feature(coroutine_trait)] /// use core::{ /// ops::{Coroutine, CoroutineState}, diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index f3695d16d7a6b..e5d7e964381c5 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -283,7 +283,7 @@ mod prim_never {} /// `char` type. For technical reasons, there is additional, separate /// documentation in [the `std::char` module](char/index.html) as well. /// -/// # Validity +/// # Validity and Layout /// /// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]' /// other than a [surrogate code point]. This has a fixed numerical definition: @@ -291,7 +291,7 @@ mod prim_never {} /// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF. /// /// No `char` may be constructed, whether as a literal or at runtime, that is not a -/// Unicode scalar value: +/// Unicode scalar value. Violating this rule causes undefined behavior. /// /// ```compile_fail /// // Each of these is a compiler error @@ -308,9 +308,10 @@ mod prim_never {} /// let _ = unsafe { char::from_u32_unchecked(0x110000) }; /// ``` /// -/// USVs are also the exact set of values that may be encoded in UTF-8. Because -/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store -/// any `char` in a `str` or read any character from a `str` as a `char`. +/// Unicode scalar values are also the exact set of values that may be encoded in UTF-8. Because +/// `char` values are Unicode scalar values and functions may assume [incoming `str` values are +/// valid UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read +/// any character from a `str` as a `char`. /// /// The gap in valid `char` values is understood by the compiler, so in the /// below example the two ranges are understood to cover the whole range of @@ -324,11 +325,17 @@ mod prim_never {} /// }; /// ``` /// -/// All USVs are valid `char` values, but not all of them represent a real -/// character. Many USVs are not currently assigned to a character, but may be -/// in the future ("reserved"); some will never be a character -/// ("noncharacters"); and some may be given different meanings by different -/// users ("private use"). +/// All Unicode scalar values are valid `char` values, but not all of them represent a real +/// character. Many Unicode scalar values are not currently assigned to a character, but may be in +/// the future ("reserved"); some will never be a character ("noncharacters"); and some may be given +/// different meanings by different users ("private use"). +/// +/// `char` is guaranteed to have the same size and alignment as `u32` on all +/// platforms. +/// ``` +/// use std::alloc::Layout; +/// assert_eq!(Layout::new::(), Layout::new::()); +/// ``` /// /// [Unicode code point]: https://www.unicode.org/glossary/#code_point /// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value @@ -887,8 +894,6 @@ mod prim_slice {} /// type. It is usually seen in its borrowed form, `&str`. It is also the type /// of string literals, `&'static str`. /// -/// String slices are always valid UTF-8. -/// /// # Basic Usage /// /// String literals are string slices: @@ -942,6 +947,14 @@ mod prim_slice {} /// Note: This example shows the internals of `&str`. `unsafe` should not be /// used to get a string slice under normal circumstances. Use `as_str` /// instead. +/// +/// # Invariant +/// +/// Rust libraries may assume that string slices are always valid UTF-8. +/// +/// Constructing a non-UTF-8 string slice is not immediate undefined behavior, but any function +/// called on a string slice may assume that it is valid UTF-8, which means that a non-UTF-8 string +/// slice can lead to undefined behavior down the road. #[stable(feature = "rust1", since = "1.0.0")] mod prim_str {} @@ -1480,7 +1493,7 @@ mod prim_ref {} /// /// ### Casting to and from integers /// -/// You cast function pointers directly to integers: +/// You can cast function pointers directly to integers: /// /// ```rust /// let fnptr: fn(i32) -> i32 = |x| x+2; @@ -1506,9 +1519,117 @@ mod prim_ref {} /// Note that all of this is not portable to platforms where function pointers and data pointers /// have different sizes. /// +/// ### ABI compatibility +/// +/// Generally, when a function is declared with one signature and called via a function pointer with +/// a different signature, the two signatures must be *ABI-compatible* or else calling the function +/// via that function pointer is Undefined Behavior. ABI compatibility is a lot stricter than merely +/// having the same memory layout; for example, even if `i32` and `f32` have the same size and +/// alignment, they might be passed in different registers and hence not be ABI-compatible. +/// +/// ABI compatibility as a concern only arises in code that alters the type of function pointers, +/// code that imports functions via `extern` blocks, and in code that combines `#[target_feature]` +/// with `extern fn`. Altering the type of function pointers is wildly unsafe (as in, a lot more +/// unsafe than even [`transmute_copy`][mem::transmute_copy]), and should only occur in the most +/// exceptional circumstances. Most Rust code just imports functions via `use`. `#[target_feature]` +/// is also used rarely. So, most likely you do not have to worry about ABI compatibility. +/// +/// But assuming such circumstances, what are the rules? For this section, we are only considering +/// the ABI of direct Rust-to-Rust calls, not linking in general -- once functions are imported via +/// `extern` blocks, there are more things to consider that we do not go into here. +/// +/// For two signatures to be considered *ABI-compatible*, they must use a compatible ABI string, +/// must take the same number of arguments, the individual argument types and the return types must +/// be ABI-compatible, and the target feature requirements must be met (see the subsection below for +/// the last point). The ABI string is declared via `extern "ABI" fn(...) -> ...`; note that +/// `fn name(...) -> ...` implicitly uses the `"Rust"` ABI string and `extern fn name(...) -> ...` +/// implicitly uses the `"C"` ABI string. +/// +/// The ABI strings are guaranteed to be compatible if they are the same, or if the caller ABI +/// string is `$X-unwind` and the callee ABI string is `$X`, where `$X` is one of the following: +/// "C", "aapcs", "fastcall", "stdcall", "system", "sysv64", "thiscall", "vectorcall", "win64". +/// +/// The following types are guaranteed to be ABI-compatible: +/// +/// - `*const T`, `*mut T`, `&T`, `&mut T`, `Box` (specifically, only `Box`), and +/// `NonNull` are all ABI-compatible with each other for all `T`. They are also ABI-compatible +/// with each other for _different_ `T` if they have the same metadata type (`::Metadata`). +/// - `usize` is ABI-compatible with the `uN` integer type of the same size, and likewise `isize` is +/// ABI-compatible with the `iN` integer type of the same size. +/// - Any two `fn` (function pointer) types are ABI-compatible with each other if they have the same +/// ABI string or the ABI string only differs in a trailing `-unwind`, independent of the rest of +/// their signature. (This means you can pass `fn()` to a function expecting `fn(i32)`, and the +/// call will be valid ABI-wise. The callee receives the result of transmuting the function pointer +/// from `fn()` to `fn(i32)`; that transmutation is itself a well-defined operation, it's just +/// almost certainly UB to later call that function pointer.) +/// - Any two types with size 0 and alignment 1 are ABI-compatible. +/// - A `repr(transparent)` type `T` is ABI-compatible with its unique non-trivial field, i.e., the +/// unique field that doesn't have size 0 and alignment 1 (if there is such a field). +/// - `i32` is ABI-compatible with `NonZeroI32`, and similar for all other integer types with their +/// matching `NonZero*` type. +/// - If `T` is guaranteed to be subject to the [null pointer +/// optimization](option/index.html#representation), then `T` and `Option` are ABI-compatible. +/// +/// Furthermore, ABI compatibility satisfies the following general properties: +/// +/// - Every type is ABI-compatible with itself. +/// - If `T1` and `T2` are ABI-compatible, then two `repr(C)` types that only differ because one +/// field type was changed from `T1` to `T2` are ABI-compatible. +/// - If `T1` and `T2` are ABI-compatible and `T2` and `T3` are ABI-compatible, then so are `T1` and +/// `T3` (i.e., ABI-compatibility is transitive). +/// - If `T1` and `T2` are ABI-compatible, then so are `T2` and `T1` (i.e., ABI-compatibility is +/// symmetric). +/// +/// More signatures can be ABI-compatible on specific targets, but that should not be relied upon +/// since it is not portable and not a stable guarantee. +/// +/// Noteworthy cases of types *not* being ABI-compatible in general are: +/// * `bool` vs `u8`, and `i32` vs `u32`: on some targets, the calling conventions for these types +/// differ in terms of what they guarantee for the remaining bits in the register that are not +/// used by the value. +/// * `i32` vs `f32` are not compatible either, as has already been mentioned above. +/// * `struct Foo(u32)` and `u32` are not compatible (without `repr(transparent)`) since structs are +/// aggregate types and often passed in a different way than primitives like `i32`. +/// +/// Note that these rules describe when two completely known types are ABI-compatible. When +/// considering ABI compatibility of a type declared in another crate (including the standard +/// library), consider that any type that has a private field or the `#[non_exhaustive]` attribute +/// may change its layout as a non-breaking update unless documented otherwise -- so for instance, +/// even if such a type is a 1-ZST or `repr(transparent)` right now, this might change with any +/// library version bump. +/// +/// If the declared signature and the signature of the function pointer are ABI-compatible, then the +/// function call behaves as if every argument was [`transmute`d][mem::transmute] from the +/// type in the function pointer to the type at the function declaration, and the return value is +/// [`transmute`d][mem::transmute] from the type in the declaration to the type in the +/// pointer. All the usual caveats and concerns around transmutation apply; for instance, if the +/// function expects a `NonNullI32` and the function pointer uses the ABI-compatible type +/// `Option`, and the value used for the argument is `None`, then this call is Undefined +/// Behavior since transmuting `None::` to `NonNullI32` violates the non-null +/// requirement. +/// +/// #### Requirements concerning target features +/// +/// Under some conditions, the signature used by the caller and the callee can be ABI-incompatible +/// even if the exact same ABI string and types are being used. As an example, the +/// `std::arch::x86_64::__m256` type has a different `extern "C"` ABI when the `avx` feature is +/// enabled vs when it is not enabled. +/// +/// Therefore, to ensure ABI compatibility when code using different target features is combined +/// (such as via `#[target_feature]`), we further require that one of the following conditions is +/// met: +/// +/// - The function uses the `"Rust"` ABI string (which is the default without `extern`). +/// - Caller and callee are using the exact same set of target features. For the callee we consider +/// the features enabled (via `#[target_feature]` and `-C target-feature`/`-C target-cpu`) at the +/// declaration site; for the caller we consider the features enabled at the call site. +/// - Neither any argument nor the return value involves a SIMD type (`#[repr(simd)]`) that is not +/// behind a pointer indirection (i.e., `*mut __m256` is fine, but `(i32, __m256)` is not). +/// /// ### Trait implementations /// -/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic +/// In this documentation the shorthand `fn(T₁, T₂, …, Tₙ)` is used to represent non-variadic /// function pointers of varying length. Note that this is a convenience notation to avoid /// repetitive documentation, not valid Rust syntax. /// diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index bbf7199fffa06..ce176e6fc18f3 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -1,5 +1,4 @@ use crate::convert::{TryFrom, TryInto}; -use crate::intrinsics::assert_unsafe_precondition; use crate::num::NonZeroUsize; use crate::{cmp, fmt, hash, mem, num}; @@ -42,6 +41,7 @@ impl Alignment { /// This provides the same numerical value as [`mem::align_of`], /// but in an `Alignment` instead of a `usize`. #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const fn of() -> Self { // SAFETY: rustc ensures that type alignment is always a power of two. @@ -53,6 +53,7 @@ impl Alignment { /// /// Note that `0` is not a power of two, nor a valid alignment. #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const fn new(align: usize) -> Option { if align.is_power_of_two() { @@ -75,13 +76,10 @@ impl Alignment { #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const unsafe fn new_unchecked(align: usize) -> Self { - // SAFETY: Precondition passed to the caller. - unsafe { - assert_unsafe_precondition!( - "Alignment::new_unchecked requires a power of two", - (align: usize) => align.is_power_of_two() - ) - }; + crate::panic::debug_assert_nounwind!( + align.is_power_of_two(), + "Alignment::new_unchecked requires a power of two" + ); // SAFETY: By precondition, this must be a power of two, and // our variants encompass all possible powers of two. @@ -98,6 +96,7 @@ impl Alignment { /// Returns the alignment as a [`NonZeroUsize`] #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const fn as_nonzero(self) -> NonZeroUsize { // SAFETY: All the discriminants are non-zero. @@ -118,10 +117,42 @@ impl Alignment { /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] - pub fn log2(self) -> u32 { + pub const fn log2(self) -> u32 { self.as_nonzero().trailing_zeros() } + + /// Returns a bit mask that can be used to match this alignment. + /// + /// This is equivalent to `!(self.as_usize() - 1)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_alignment_type)] + /// #![feature(ptr_mask)] + /// use std::ptr::{Alignment, NonNull}; + /// + /// #[repr(align(1))] struct Align1(u8); + /// #[repr(align(2))] struct Align2(u16); + /// #[repr(align(4))] struct Align4(u32); + /// let one = >::dangling().as_ptr(); + /// let two = >::dangling().as_ptr(); + /// let four = >::dangling().as_ptr(); + /// + /// assert_eq!(four.mask(Alignment::of::().mask()), four); + /// assert_eq!(four.mask(Alignment::of::().mask()), four); + /// assert_eq!(four.mask(Alignment::of::().mask()), four); + /// assert_ne!(one.mask(Alignment::of::().mask()), one); + /// ``` + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] + #[inline] + pub const fn mask(self) -> usize { + // SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow. + !(unsafe { self.as_usize().unchecked_sub(1) }) + } } #[unstable(feature = "ptr_alignment_type", issue = "102070")] @@ -193,6 +224,14 @@ impl hash::Hash for Alignment { } } +/// Returns [`Alignment::MIN`], which is valid for any type. +#[unstable(feature = "ptr_alignment_type", issue = "102070")] +impl Default for Alignment { + fn default() -> Alignment { + Alignment::MIN + } +} + #[cfg(target_pointer_width = "16")] type AlignmentEnum = AlignmentEnum16; #[cfg(target_pointer_width = "32")] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 97f936fbd9ea4..2f47ca29ec534 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -186,10 +186,10 @@ impl *const T { /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. /// /// If using those APIs is not possible because there is no way to preserve a pointer with the - /// required provenance, use [`expose_addr`][pointer::expose_addr] and - /// [`from_exposed_addr`][from_exposed_addr] instead. However, note that this makes - /// your code less portable and less amenable to tools that check for compliance with the Rust - /// memory model. + /// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts + /// or [`expose_addr`][pointer::expose_addr] and [`from_exposed_addr`][from_exposed_addr] + /// instead. However, note that this makes your code less portable and less amenable to tools + /// that check for compliance with the Rust memory model. /// /// On most platforms this will produce a value with the same bytes as the original /// pointer, because all the bytes are dedicated to describing the address. @@ -219,7 +219,8 @@ impl *const T { /// later call [`from_exposed_addr`][] to reconstitute the original pointer including its /// provenance. (Reconstructing address space information, if required, is your responsibility.) /// - /// Using this method means that code is *not* following Strict Provenance rules. Supporting + /// Using this method means that code is *not* following [Strict + /// Provenance][../index.html#strict-provenance] rules. Supporting /// [`from_exposed_addr`][] complicates specification and reasoning and may not be supported by /// tools that help you to stay conformant with the Rust memory model, so it is recommended to /// use [`addr`][pointer::addr] wherever possible. @@ -230,13 +231,13 @@ impl *const T { /// side-effect which is required for [`from_exposed_addr`][] to work is typically not /// available. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, see the - /// [module documentation][crate::ptr] for details. + /// It is unclear whether this method can be given a satisfying unambiguous specification. This + /// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance]. /// /// [`from_exposed_addr`]: from_exposed_addr #[must_use] #[inline(always)] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[unstable(feature = "exposed_provenance", issue = "95228")] pub fn expose_addr(self) -> usize { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. self.cast::<()>() as usize @@ -480,8 +481,8 @@ impl *const T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset(self, count: isize) -> Self { @@ -561,8 +562,8 @@ impl *const T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] pub const fn wrapping_byte_offset(self, count: isize) -> Self { self.cast::().wrapping_offset(count).with_metadata_of(self) @@ -728,8 +729,8 @@ impl *const T { /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset_from(self, origin: *const U) -> isize { @@ -955,8 +956,8 @@ impl *const T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_add(self, count: usize) -> Self { @@ -1049,8 +1050,8 @@ impl *const T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub(self, count: usize) -> Self { @@ -1130,8 +1131,8 @@ impl *const T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] pub const fn wrapping_byte_add(self, count: usize) -> Self { self.cast::().wrapping_add(count).with_metadata_of(self) @@ -1209,8 +1210,8 @@ impl *const T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] pub const fn wrapping_byte_sub(self, count: usize) -> Self { self.cast::().wrapping_sub(count).with_metadata_of(self) @@ -1367,10 +1368,16 @@ impl *const T { panic!("align_offset: align is not a power-of-two"); } - { - // SAFETY: `align` has been checked to be a power of 2 above - unsafe { align_offset(self, align) } + // SAFETY: `align` has been checked to be a power of 2 above + let ret = unsafe { align_offset(self, align) }; + + // Inform Miri that we want to consider the resulting pointer to be suitably aligned. + #[cfg(miri)] + if ret != usize::MAX { + intrinsics::miri_promise_symbolic_alignment(self.wrapping_add(ret).cast(), align); } + + ret } /// Returns whether the pointer is properly aligned for `T`. @@ -1644,6 +1651,24 @@ impl *const [T] { metadata(self) } + /// Returns `true` if the raw slice has a length of 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_ptr_len)] + /// use std::ptr; + /// + /// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3); + /// assert!(!slice.is_empty()); + /// ``` + #[inline(always)] + #[unstable(feature = "slice_ptr_len", issue = "71146")] + #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] + pub const fn is_empty(self) -> bool { + self.len() == 0 + } + /// Returns a raw pointer to the slice's buffer. /// /// This is equivalent to casting `self` to `*const T`, but more type-safe. diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 84b179df8c192..50cf29227ca74 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -312,22 +312,30 @@ //! For instance, ARM explicitly supports high-bit tagging, and so CHERI on ARM inherits //! that and should support it. //! -//! ## Pointer-usize-pointer roundtrips and 'exposed' provenance +//! ## Exposed Provenance //! -//! **This section is *non-normative* and is part of the [Strict Provenance] experiment.** +//! **This section is *non-normative* and is an extension to the [Strict Provenance] experiment.** //! //! As discussed above, pointer-usize-pointer roundtrips are not possible under [Strict Provenance]. -//! However, there exists legacy Rust code that is full of such roundtrips, and legacy platform APIs -//! regularly assume that `usize` can capture all the information that makes up a pointer. There -//! also might be code that cannot be ported to Strict Provenance (which is something we would [like -//! to hear about][Strict Provenance]). -//! -//! For situations like this, there is a fallback plan, a way to 'opt out' of Strict Provenance. -//! However, note that this makes your code a lot harder to specify, and the code will not work -//! (well) with tools like [Miri] and [CHERI]. -//! -//! This fallback plan is provided by the [`expose_addr`] and [`from_exposed_addr`] methods (which -//! are equivalent to `as` casts between pointers and integers). [`expose_addr`] is a lot like +//! This is by design: the goal of Strict Provenance is to provide a clear specification that we are +//! confident can be formalized unambiguously and can be subject to precise formal reasoning. +//! +//! However, there exist situations where pointer-usize-pointer roundtrips cannot be avoided, or +//! where avoiding them would require major refactoring. Legacy platform APIs also regularly assume +//! that `usize` can capture all the information that makes up a pointer. The goal of Strict +//! Provenance is not to rule out such code; the goal is to put all the *other* pointer-manipulating +//! code onto a more solid foundation. Strict Provenance is about improving the situation where +//! possible (all the code that can be written with Strict Provenance) without making things worse +//! for situations where Strict Provenance is insufficient. +//! +//! For these situations, there is a highly experimental extension to Strict Provenance called +//! *Exposed Provenance*. This extension permits pointer-usize-pointer roundtrips. However, its +//! semantics are on much less solid footing than Strict Provenance, and at this point it is not yet +//! clear where a satisfying unambiguous semantics can be defined for Exposed Provenance. +//! Furthermore, Exposed Provenance will not work (well) with tools like [Miri] and [CHERI]. +//! +//! Exposed Provenance is provided by the [`expose_addr`] and [`from_exposed_addr`] methods, which +//! are meant to replace `as` casts between pointers and integers. [`expose_addr`] is a lot like //! [`addr`], but additionally adds the provenance of the pointer to a global list of 'exposed' //! provenances. (This list is purely conceptual, it exists for the purpose of specifying Rust but //! is not materialized in actual executions, except in tools like [Miri].) [`from_exposed_addr`] @@ -341,10 +349,11 @@ //! there is *no* previously 'exposed' provenance that justifies the way the returned pointer will //! be used, the program has undefined behavior. //! -//! Using [`expose_addr`] or [`from_exposed_addr`] (or the equivalent `as` casts) means that code is +//! Using [`expose_addr`] or [`from_exposed_addr`] (or the `as` casts) means that code is //! *not* following Strict Provenance rules. The goal of the Strict Provenance experiment is to -//! determine whether it is possible to use Rust without [`expose_addr`] and [`from_exposed_addr`]. -//! If this is successful, it would be a major win for avoiding specification complexity and to +//! determine how far one can get in Rust without the use of [`expose_addr`] and +//! [`from_exposed_addr`], and to encourage code to be written with Strict Provenance APIs only. +//! Maximizing the amount of such code is a major win for avoiding specification complexity and to //! facilitate adoption of tools like [CHERI] and [Miri] that can be a big help in increasing the //! confidence in (unsafe) Rust code. //! @@ -505,6 +514,10 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { /// Creates a null raw pointer. /// +/// This function is equivalent to zero-initializing the pointer: +/// `MaybeUninit::<*const T>::zeroed().assume_init()`. +/// The resulting pointer has the address 0. +/// /// # Examples /// /// ``` @@ -512,6 +525,7 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { /// /// let p: *const i32 = ptr::null(); /// assert!(p.is_null()); +/// assert_eq!(p as usize, 0); // this pointer has the address 0 /// ``` #[inline(always)] #[must_use] @@ -526,6 +540,10 @@ pub const fn null() -> *const T { /// Creates a null mutable raw pointer. /// +/// This function is equivalent to zero-initializing the pointer: +/// `MaybeUninit::<*mut T>::zeroed().assume_init()`. +/// The resulting pointer has the address 0. +/// /// # Examples /// /// ``` @@ -533,6 +551,7 @@ pub const fn null() -> *const T { /// /// let p: *mut i32 = ptr::null_mut(); /// assert!(p.is_null()); +/// assert_eq!(p as usize, 0); // this pointer has the address 0 /// ``` #[inline(always)] #[must_use] @@ -609,12 +628,12 @@ pub const fn invalid_mut(addr: usize) -> *mut T { /// Convert an address back to a pointer, picking up a previously 'exposed' provenance. /// -/// This is equivalent to `addr as *const T`. The provenance of the returned pointer is that of *any* -/// pointer that was previously exposed by passing it to [`expose_addr`][pointer::expose_addr], -/// or a `ptr as usize` cast. In addition, memory which is outside the control of the Rust abstract -/// machine (MMIO registers, for example) is always considered to be exposed, so long as this memory -/// is disjoint from memory that will be used by the abstract machine such as the stack, heap, -/// and statics. +/// This is a more rigorously specified alternative to `addr as *const T`. The provenance of the +/// returned pointer is that of *any* pointer that was previously exposed by passing it to +/// [`expose_addr`][pointer::expose_addr], or a `ptr as usize` cast. In addition, memory which is +/// outside the control of the Rust abstract machine (MMIO registers, for example) is always +/// considered to be exposed, so long as this memory is disjoint from memory that will be used by +/// the abstract machine such as the stack, heap, and statics. /// /// If there is no 'exposed' provenance that justifies the way this pointer will be used, /// the program has undefined behavior. In particular, the aliasing rules still apply: pointers @@ -629,7 +648,8 @@ pub const fn invalid_mut(addr: usize) -> *mut T { /// On platforms with multiple address spaces, it is your responsibility to ensure that the /// address makes sense in the address space that this pointer will be used with. /// -/// Using this method means that code is *not* following strict provenance rules. "Guessing" a +/// Using this function means that code is *not* following [Strict +/// Provenance][../index.html#strict-provenance] rules. "Guessing" a /// suitable provenance complicates specification and reasoning and may not be supported by /// tools that help you to stay conformant with the Rust memory model, so it is recommended to /// use [`with_addr`][pointer::with_addr] wherever possible. @@ -639,13 +659,13 @@ pub const fn invalid_mut(addr: usize) -> *mut T { /// since it is generally not possible to actually *compute* which provenance the returned /// pointer has to pick up. /// -/// This API and its claimed semantics are part of the Strict Provenance experiment, see the -/// [module documentation][crate::ptr] for details. +/// It is unclear whether this function can be given a satisfying unambiguous specification. This +/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance]. #[must_use] #[inline(always)] -#[unstable(feature = "strict_provenance", issue = "95228")] +#[unstable(feature = "exposed_provenance", issue = "95228")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -#[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead +#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead pub fn from_exposed_addr(addr: usize) -> *const T where T: Sized, @@ -656,18 +676,20 @@ where /// Convert an address back to a mutable pointer, picking up a previously 'exposed' provenance. /// -/// This is equivalent to `addr as *mut T`. The provenance of the returned pointer is that of *any* -/// pointer that was previously passed to [`expose_addr`][pointer::expose_addr] or a `ptr as usize` -/// cast. If there is no previously 'exposed' provenance that justifies the way this pointer will be -/// used, the program has undefined behavior. Note that there is no algorithm that decides which -/// provenance will be used. You can think of this as "guessing" the right provenance, and the guess -/// will be "maximally in your favor", in the sense that if there is any way to avoid undefined -/// behavior, then that is the guess that will be taken. +/// This is a more rigorously specified alternative to `addr as *mut T`. The provenance of the +/// returned pointer is that of *any* pointer that was previously passed to +/// [`expose_addr`][pointer::expose_addr] or a `ptr as usize` cast. If there is no previously +/// 'exposed' provenance that justifies the way this pointer will be used, the program has undefined +/// behavior. Note that there is no algorithm that decides which provenance will be used. You can +/// think of this as "guessing" the right provenance, and the guess will be "maximally in your +/// favor", in the sense that if there is any way to avoid undefined behavior, then that is the +/// guess that will be taken. /// /// On platforms with multiple address spaces, it is your responsibility to ensure that the /// address makes sense in the address space that this pointer will be used with. /// -/// Using this method means that code is *not* following strict provenance rules. "Guessing" a +/// Using this function means that code is *not* following [Strict +/// Provenance][../index.html#strict-provenance] rules. "Guessing" a /// suitable provenance complicates specification and reasoning and may not be supported by /// tools that help you to stay conformant with the Rust memory model, so it is recommended to /// use [`with_addr`][pointer::with_addr] wherever possible. @@ -677,13 +699,13 @@ where /// since it is generally not possible to actually *compute* which provenance the returned /// pointer has to pick up. /// -/// This API and its claimed semantics are part of the Strict Provenance experiment, see the -/// [module documentation][crate::ptr] for details. +/// It is unclear whether this function can be given a satisfying unambiguous specification. This +/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance]. #[must_use] #[inline(always)] -#[unstable(feature = "strict_provenance", issue = "95228")] +#[unstable(feature = "exposed_provenance", issue = "95228")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -#[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead +#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead pub fn from_exposed_addr_mut(addr: usize) -> *mut T where T: Sized, @@ -1888,14 +1910,15 @@ pub fn eq(a: *const T, b: *const T) -> bool { /// # Examples /// /// ``` -/// #![feature(ptr_addr_eq)] +/// use std::ptr; /// /// let whole: &[i32; 3] = &[1, 2, 3]; /// let first: &i32 = &whole[0]; -/// assert!(std::ptr::addr_eq(whole, first)); -/// assert!(!std::ptr::eq::(whole, first)); +/// +/// assert!(ptr::addr_eq(whole, first)); +/// assert!(!ptr::eq::(whole, first)); /// ``` -#[unstable(feature = "ptr_addr_eq", issue = "116324")] +#[stable(feature = "ptr_addr_eq", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[must_use = "pointer comparison produces a value"] pub fn addr_eq(p: *const T, q: *const U) -> bool { @@ -1911,8 +1934,7 @@ pub fn addr_eq(p: *const T, q: *const U) -> bool { /// # Examples /// /// ``` -/// use std::collections::hash_map::DefaultHasher; -/// use std::hash::{Hash, Hasher}; +/// use std::hash::{DefaultHasher, Hash, Hasher}; /// use std::ptr; /// /// let five = 5; @@ -1989,9 +2011,18 @@ impl fmt::Debug for F { /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// -/// Note, however, that the `expr` in `addr_of!(expr)` is still subject to all -/// the usual rules. In particular, `addr_of!(*ptr::null())` is Undefined -/// Behavior because it dereferences a null pointer. +/// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads +/// from the place or requires the place to be dereferenceable. This means that +/// `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned. +/// Note however that `addr_of!((*ptr).field)` still requires the projection to +/// `field` to be in-bounds, using the same rules as [`offset`]. +/// +/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside +/// `addr_of!` like everywhere else, in which case a reference is created to call `Deref::deref` or +/// `Index::index`, respectively. The statements above only apply when no such coercions are +/// applied. +/// +/// [`offset`]: pointer::offset /// /// # Example /// @@ -2029,9 +2060,18 @@ pub macro addr_of($place:expr) { /// as all other references. This macro can create a raw pointer *without* creating /// a reference first. /// -/// Note, however, that the `expr` in `addr_of_mut!(expr)` is still subject to all -/// the usual rules. In particular, `addr_of_mut!(*ptr::null_mut())` is Undefined -/// Behavior because it dereferences a null pointer. +/// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads +/// from the place or requires the place to be dereferenceable. This means that +/// `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned. +/// Note however that `addr_of_mut!((*ptr).field)` still requires the projection to +/// `field` to be in-bounds, using the same rules as [`offset`]. +/// +/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside +/// `addr_of_mut!` like everywhere else, in which case a reference is created to call `Deref::deref` +/// or `Index::index`, respectively. The statements above only apply when no such coercions are +/// applied. +/// +/// [`offset`]: pointer::offset /// /// # Examples /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 64695d63f0c9a..3aaae679a6f7c 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -193,10 +193,10 @@ impl *mut T { /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. /// /// If using those APIs is not possible because there is no way to preserve a pointer with the - /// required provenance, use [`expose_addr`][pointer::expose_addr] and - /// [`from_exposed_addr_mut`][from_exposed_addr_mut] instead. However, note that this makes - /// your code less portable and less amenable to tools that check for compliance with the Rust - /// memory model. + /// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts + /// or [`expose_addr`][pointer::expose_addr] and [`from_exposed_addr`][from_exposed_addr] + /// instead. However, note that this makes your code less portable and less amenable to tools + /// that check for compliance with the Rust memory model. /// /// On most platforms this will produce a value with the same bytes as the original /// pointer, because all the bytes are dedicated to describing the address. @@ -226,7 +226,8 @@ impl *mut T { /// later call [`from_exposed_addr_mut`][] to reconstitute the original pointer including its /// provenance. (Reconstructing address space information, if required, is your responsibility.) /// - /// Using this method means that code is *not* following Strict Provenance rules. Supporting + /// Using this method means that code is *not* following [Strict + /// Provenance][../index.html#strict-provenance] rules. Supporting /// [`from_exposed_addr_mut`][] complicates specification and reasoning and may not be supported /// by tools that help you to stay conformant with the Rust memory model, so it is recommended /// to use [`addr`][pointer::addr] wherever possible. @@ -237,13 +238,13 @@ impl *mut T { /// side-effect which is required for [`from_exposed_addr_mut`][] to work is typically not /// available. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, see the - /// [module documentation][crate::ptr] for details. + /// It is unclear whether this method can be given a satisfying unambiguous specification. This + /// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance]. /// /// [`from_exposed_addr_mut`]: from_exposed_addr_mut #[must_use] #[inline(always)] - #[unstable(feature = "strict_provenance", issue = "95228")] + #[unstable(feature = "exposed_provenance", issue = "95228")] pub fn expose_addr(self) -> usize { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. self.cast::<()>() as usize @@ -259,7 +260,7 @@ impl *mut T { /// This is equivalent to using [`wrapping_offset`][pointer::wrapping_offset] to offset /// `self` to the given address, and therefore has all the same capabilities and restrictions. /// - /// This API and its claimed semantics are part of the Strict Provenance experiment, + /// This API and its claimed semantics are an extension to the Strict Provenance experiment, /// see the [module documentation][crate::ptr] for details. #[must_use] #[inline] @@ -495,8 +496,8 @@ impl *mut T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset(self, count: isize) -> Self { @@ -575,8 +576,8 @@ impl *mut T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] pub const fn wrapping_byte_offset(self, count: isize) -> Self { self.cast::().wrapping_offset(count).with_metadata_of(self) @@ -900,8 +901,8 @@ impl *mut T { /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset_from(self, origin: *const U) -> isize { @@ -1056,8 +1057,8 @@ impl *mut T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_add(self, count: usize) -> Self { @@ -1150,8 +1151,8 @@ impl *mut T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub(self, count: usize) -> Self { @@ -1231,8 +1232,8 @@ impl *mut T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] pub const fn wrapping_byte_add(self, count: usize) -> Self { self.cast::().wrapping_add(count).with_metadata_of(self) @@ -1310,8 +1311,8 @@ impl *mut T { /// leaving the metadata untouched. #[must_use] #[inline(always)] - #[stable(feature = "pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pointer_byte_offsets", since = "1.75.0")] + #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")] #[rustc_allow_const_fn_unstable(set_ptr_value)] pub const fn wrapping_byte_sub(self, count: usize) -> Self { self.cast::().wrapping_sub(count).with_metadata_of(self) @@ -1634,10 +1635,19 @@ impl *mut T { panic!("align_offset: align is not a power-of-two"); } - { - // SAFETY: `align` has been checked to be a power of 2 above - unsafe { align_offset(self, align) } + // SAFETY: `align` has been checked to be a power of 2 above + let ret = unsafe { align_offset(self, align) }; + + // Inform Miri that we want to consider the resulting pointer to be suitably aligned. + #[cfg(miri)] + if ret != usize::MAX { + intrinsics::miri_promise_symbolic_alignment( + self.wrapping_add(ret).cast_const().cast(), + align, + ); } + + ret } /// Returns whether the pointer is properly aligned for `T`. @@ -1920,10 +1930,10 @@ impl *mut [T] { /// /// ``` /// #![feature(slice_ptr_len)] + /// use std::ptr; /// - /// let mut a = [1, 2, 3]; - /// let ptr = &mut a as *mut [_]; - /// assert!(!ptr.is_empty()); + /// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3); + /// assert!(!slice.is_empty()); /// ``` #[inline(always)] #[unstable(feature = "slice_ptr_len", issue = "71146")] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index ae673b7799ffe..c99fe36de6d82 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -2,11 +2,14 @@ use crate::cmp::Ordering; use crate::convert::From; use crate::fmt; use crate::hash; +use crate::intrinsics; use crate::intrinsics::assert_unsafe_precondition; use crate::marker::Unsize; +use crate::mem::SizedTypeProperties; use crate::mem::{self, MaybeUninit}; use crate::num::NonZeroUsize; use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::ptr; use crate::ptr::Unique; use crate::slice::{self, SliceIndex}; @@ -471,41 +474,1047 @@ impl NonNull { unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } } - /// See [`pointer::add`] for semantics and safety requirements. + /// Calculates the offset from a pointer. + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined + /// Behavior: + /// + /// * Both the starting and resulting pointer must be either in bounds or one + /// byte past the end of the same [allocated object]. + /// + /// * The computed offset, **in bytes**, cannot overflow an `isize`. + /// + /// * The offset being in bounds cannot rely on "wrapping around" the address + /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize. + /// + /// The compiler and standard library generally tries to ensure allocations + /// never reach a size where an offset is a concern. For instance, `Vec` + /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so + /// `vec.as_ptr().add(vec.len())` is always safe. + /// + /// Most platforms fundamentally can't even construct such an allocation. + /// For instance, no known 64-bit platform can ever serve a request + /// for 263 bytes due to page-table limitations or splitting the address space. + /// However, some 32-bit and 16-bit platforms may successfully serve a request for + /// more than `isize::MAX` bytes with things like Physical Address + /// Extension. As such, memory acquired directly from allocators or memory + /// mapped files *may* be too large to handle with this function. + /// + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// #![feature(non_null_convenience)] + /// use std::ptr::NonNull; + /// + /// let mut s = [1, 2, 3]; + /// let ptr: NonNull = NonNull::new(s.as_mut_ptr()).unwrap(); + /// + /// unsafe { + /// println!("{}", ptr.offset(1).read()); + /// println!("{}", ptr.offset(2).read()); + /// } + /// ``` + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn offset(self, count: isize) -> NonNull + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `offset`. + // Additionally safety contract of `offset` guarantees that the resulting pointer is + // pointing to an allocation, there can't be an allocation at null, thus it's safe to + // construct `NonNull`. + unsafe { NonNull { pointer: intrinsics::offset(self.pointer, count) } } + } + + /// Calculates the offset from a pointer in bytes. + /// + /// `count` is in units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [offset][pointer::offset] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[must_use] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_offset(self, count: isize) -> Self { + // SAFETY: the caller must uphold the safety contract for `offset` and `byte_offset` has + // the same safety contract. + // Additionally safety contract of `offset` guarantees that the resulting pointer is + // pointing to an allocation, there can't be an allocation at null, thus it's safe to + // construct `NonNull`. + unsafe { NonNull { pointer: self.pointer.byte_offset(count) } } + } + + /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined + /// Behavior: + /// + /// * Both the starting and resulting pointer must be either in bounds or one + /// byte past the end of the same [allocated object]. + /// + /// * The computed offset, **in bytes**, cannot overflow an `isize`. + /// + /// * The offset being in bounds cannot rely on "wrapping around" the address + /// space. That is, the infinite-precision sum must fit in a `usize`. + /// + /// The compiler and standard library generally tries to ensure allocations + /// never reach a size where an offset is a concern. For instance, `Vec` + /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so + /// `vec.as_ptr().add(vec.len())` is always safe. + /// + /// Most platforms fundamentally can't even construct such an allocation. + /// For instance, no known 64-bit platform can ever serve a request + /// for 263 bytes due to page-table limitations or splitting the address space. + /// However, some 32-bit and 16-bit platforms may successfully serve a request for + /// more than `isize::MAX` bytes with things like Physical Address + /// Extension. As such, memory acquired directly from allocators or memory + /// mapped files *may* be too large to handle with this function. + /// + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// #![feature(non_null_convenience)] + /// use std::ptr::NonNull; + /// + /// let s: &str = "123"; + /// let ptr: NonNull = NonNull::new(s.as_ptr().cast_mut()).unwrap(); + /// + /// unsafe { + /// println!("{}", ptr.add(1).read() as char); + /// println!("{}", ptr.add(2).read() as char); + /// } + /// ``` + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn add(self, count: usize) -> Self + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `offset`. + // Additionally safety contract of `offset` guarantees that the resulting pointer is + // pointing to an allocation, there can't be an allocation at null, thus it's safe to + // construct `NonNull`. + unsafe { NonNull { pointer: intrinsics::offset(self.pointer, count) } } + } + + /// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`). + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`add`][NonNull::add] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[must_use] + #[inline(always)] + #[rustc_allow_const_fn_unstable(set_ptr_value)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_add(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `add` and `byte_add` has the same + // safety contract. + // Additionally safety contract of `add` guarantees that the resulting pointer is pointing + // to an allocation, there can't be an allocation at null, thus it's safe to construct + // `NonNull`. + unsafe { NonNull { pointer: self.pointer.byte_add(count) } } + } + + /// Calculates the offset from a pointer (convenience for + /// `.offset((count as isize).wrapping_neg())`). + /// + /// `count` is in units of T; e.g., a `count` of 3 represents a pointer + /// offset of `3 * size_of::()` bytes. + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined + /// Behavior: + /// + /// * Both the starting and resulting pointer must be either in bounds or one + /// byte past the end of the same [allocated object]. + /// + /// * The computed offset cannot exceed `isize::MAX` **bytes**. + /// + /// * The offset being in bounds cannot rely on "wrapping around" the address + /// space. That is, the infinite-precision sum must fit in a usize. + /// + /// The compiler and standard library generally tries to ensure allocations + /// never reach a size where an offset is a concern. For instance, `Vec` + /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so + /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe. + /// + /// Most platforms fundamentally can't even construct such an allocation. + /// For instance, no known 64-bit platform can ever serve a request + /// for 263 bytes due to page-table limitations or splitting the address space. + /// However, some 32-bit and 16-bit platforms may successfully serve a request for + /// more than `isize::MAX` bytes with things like Physical Address + /// Extension. As such, memory acquired directly from allocators or memory + /// mapped files *may* be too large to handle with this function. + /// + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Examples + /// + /// ``` + /// #![feature(non_null_convenience)] + /// use std::ptr::NonNull; + /// + /// let s: &str = "123"; + /// + /// unsafe { + /// let end: NonNull = NonNull::new(s.as_ptr().cast_mut()).unwrap().add(3); + /// println!("{}", end.sub(1).read() as char); + /// println!("{}", end.sub(2).read() as char); + /// } + /// ``` + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[must_use = "returns a new pointer rather than modifying its argument"] + // We could always go back to wrapping if unchecked becomes unacceptable + #[rustc_allow_const_fn_unstable(const_int_unchecked_arith)] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn sub(self, count: usize) -> Self + where + T: Sized, + { + if T::IS_ZST { + // Pointer arithmetic does nothing when the pointee is a ZST. + self + } else { + // SAFETY: the caller must uphold the safety contract for `offset`. + // Because the pointee is *not* a ZST, that means that `count` is + // at most `isize::MAX`, and thus the negation cannot overflow. + unsafe { self.offset(intrinsics::unchecked_sub(0, count as isize)) } + } + } + + /// Calculates the offset from a pointer in bytes (convenience for + /// `.byte_offset((count as isize).wrapping_neg())`). + /// + /// `count` is in units of bytes. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`sub`][NonNull::sub] on it. See that method for documentation + /// and safety requirements. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[must_use] + #[inline(always)] + #[rustc_allow_const_fn_unstable(set_ptr_value)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_sub(self, count: usize) -> Self { + // SAFETY: the caller must uphold the safety contract for `sub` and `byte_sub` has the same + // safety contract. + // Additionally safety contract of `sub` guarantees that the resulting pointer is pointing + // to an allocation, there can't be an allocation at null, thus it's safe to construct + // `NonNull`. + unsafe { NonNull { pointer: self.pointer.byte_sub(count) } } + } + + /// Calculates the distance between two pointers. The returned value is in + /// units of T: the distance in bytes divided by `mem::size_of::()`. + /// + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. + /// + /// [`offset`]: #method.offset + /// + /// # Safety + /// + /// If any of the following conditions are violated, the result is Undefined + /// Behavior: + /// + /// * Both `self` and `origin` must be either in bounds or one + /// byte past the end of the same [allocated object]. + /// + /// * Both pointers must be *derived from* a pointer to the same object. + /// (See below for an example.) + /// + /// * The distance between the pointers, in bytes, must be an exact multiple + /// of the size of `T`. + /// + /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`. + /// + /// * The distance being in bounds cannot rely on "wrapping around" the address space. + /// + /// Rust types are never larger than `isize::MAX` and Rust allocations never wrap around the + /// address space, so two pointers within some value of any Rust type `T` will always satisfy + /// the last two conditions. The standard library also generally ensures that allocations + /// never reach a size where an offset is a concern. For instance, `Vec` and `Box` ensure they + /// never allocate more than `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())` + /// always satisfies the last two conditions. + /// + /// Most platforms fundamentally can't even construct such a large allocation. + /// For instance, no known 64-bit platform can ever serve a request + /// for 263 bytes due to page-table limitations or splitting the address space. + /// However, some 32-bit and 16-bit platforms may successfully serve a request for + /// more than `isize::MAX` bytes with things like Physical Address + /// Extension. As such, memory acquired directly from allocators or memory + /// mapped files *may* be too large to handle with this function. + /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on + /// such large allocations either.) + /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// + /// [`add`]: #method.add + /// [allocated object]: crate::ptr#allocated-object + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(non_null_convenience)] + /// use std::ptr::NonNull; + /// + /// let a = [0; 5]; + /// let ptr1: NonNull = NonNull::from(&a[1]); + /// let ptr2: NonNull = NonNull::from(&a[3]); + /// unsafe { + /// assert_eq!(ptr2.offset_from(ptr1), 2); + /// assert_eq!(ptr1.offset_from(ptr2), -2); + /// assert_eq!(ptr1.offset(2), ptr2); + /// assert_eq!(ptr2.offset(-2), ptr1); + /// } + /// ``` + /// + /// *Incorrect* usage: + /// + /// ```rust,no_run + /// #![feature(non_null_convenience, strict_provenance)] + /// use std::ptr::NonNull; + /// + /// let ptr1 = NonNull::new(Box::into_raw(Box::new(0u8))).unwrap(); + /// let ptr2 = NonNull::new(Box::into_raw(Box::new(1u8))).unwrap(); + /// let diff = (ptr2.addr().get() as isize).wrapping_sub(ptr1.addr().get() as isize); + /// // Make ptr2_other an "alias" of ptr2, but derived from ptr1. + /// let ptr2_other = NonNull::new(ptr1.as_ptr().wrapping_byte_offset(diff)).unwrap(); + /// assert_eq!(ptr2.addr(), ptr2_other.addr()); + /// // Since ptr2_other and ptr2 are derived from pointers to different objects, + /// // computing their offset is undefined behavior, even though + /// // they point to the same address! + /// unsafe { + /// let zero = ptr2_other.offset_from(ptr2); // Undefined Behavior + /// } + /// ``` + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn offset_from(self, origin: NonNull) -> isize + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `offset_from`. + unsafe { self.pointer.offset_from(origin.pointer) } + } + + /// Calculates the distance between two pointers. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`offset_from`][NonNull::offset_from] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_offset_from(self, origin: NonNull) -> isize { + // SAFETY: the caller must uphold the safety contract for `byte_offset_from`. + unsafe { self.pointer.byte_offset_from(origin.pointer) } + } + + // N.B. `wrapping_offset``, `wrapping_add`, etc are not implemented because they can wrap to null + + /// Calculates the distance between two pointers, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// This computes the same value that [`offset_from`](#method.offset_from) + /// would compute, but with the added precondition that the offset is + /// guaranteed to be non-negative. This method is equivalent to + /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`, + /// but it provides slightly more information to the optimizer, which can + /// sometimes allow it to optimize slightly better with some backends. + /// + /// This method can be though of as recovering the `count` that was passed + /// to [`add`](#method.add) (or, with the parameters in the other order, + /// to [`sub`](#method.sub)). The following are all equivalent, assuming + /// that their safety preconditions are met: + /// ```rust + /// # #![feature(non_null_convenience)] + /// # unsafe fn blah(ptr: std::ptr::NonNull, origin: std::ptr::NonNull, count: usize) -> bool { + /// ptr.sub_ptr(origin) == count + /// # && + /// origin.add(count) == ptr + /// # && + /// ptr.sub(count) == origin + /// # } + /// ``` + /// + /// # Safety + /// + /// - The distance between the pointers must be non-negative (`self >= origin`) + /// + /// - *All* the safety conditions of [`offset_from`](#method.offset_from) + /// apply to this method as well; see it for the full details. + /// + /// Importantly, despite the return type of this method being able to represent + /// a larger offset, it's still *not permitted* to pass pointers which differ + /// by more than `isize::MAX` *bytes*. As such, the result of this method will + /// always be less than or equal to `isize::MAX as usize`. + /// + /// # Panics + /// + /// This function panics if `T` is a Zero-Sized Type ("ZST"). + /// + /// # Examples + /// + /// ``` + /// #![feature(non_null_convenience)] + /// use std::ptr::NonNull; + /// + /// let a = [0; 5]; + /// let ptr1: NonNull = NonNull::from(&a[1]); + /// let ptr2: NonNull = NonNull::from(&a[3]); + /// unsafe { + /// assert_eq!(ptr2.sub_ptr(ptr1), 2); + /// assert_eq!(ptr1.add(2), ptr2); + /// assert_eq!(ptr2.sub(2), ptr1); + /// assert_eq!(ptr2.sub_ptr(ptr2), 0); + /// } + /// + /// // This would be incorrect, as the pointers are not correctly ordered: + /// // ptr1.sub_ptr(ptr2) + /// ``` + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + // #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + // #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn sub_ptr(self, subtracted: NonNull) -> usize + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `sub_ptr`. + unsafe { self.pointer.sub_ptr(subtracted.pointer) } + } + + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// See [`ptr::read`] for safety concerns and examples. + /// + /// [`ptr::read`]: crate::ptr::read() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn read(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read`. + unsafe { ptr::read(self.pointer) } + } + + /// Performs a volatile read of the value from `self` without moving it. This + /// leaves the memory in `self` unchanged. + /// + /// Volatile operations are intended to act on I/O memory, and are guaranteed + /// to not be elided or reordered by the compiler across other volatile + /// operations. + /// + /// See [`ptr::read_volatile`] for safety concerns and examples. + /// + /// [`ptr::read_volatile`]: crate::ptr::read_volatile() + #[unstable(feature = "non_null_convenience", issue = "117691")] #[inline] - pub(crate) const unsafe fn add(self, delta: usize) -> Self + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn read_volatile(self) -> T where T: Sized, { - // SAFETY: We require that the delta stays in-bounds of the object, and - // thus it cannot become null, as that would require wrapping the - // address space, which no legal objects are allowed to do. - // And the caller promised the `delta` is sound to add. - unsafe { NonNull { pointer: self.pointer.add(delta) } } + // SAFETY: the caller must uphold the safety contract for `read_volatile`. + unsafe { ptr::read_volatile(self.pointer) } } - /// See [`pointer::sub`] for semantics and safety requirements. + /// Reads the value from `self` without moving it. This leaves the + /// memory in `self` unchanged. + /// + /// Unlike `read`, the pointer may be unaligned. + /// + /// See [`ptr::read_unaligned`] for safety concerns and examples. + /// + /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] #[inline] - pub(crate) const unsafe fn sub(self, delta: usize) -> Self + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn read_unaligned(self) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `read_unaligned`. + unsafe { ptr::read_unaligned(self.pointer) } + } + + /// Copies `count * size_of` bytes from `self` to `dest`. The source + /// and destination may overlap. + /// + /// NOTE: this has the *same* argument order as [`ptr::copy`]. + /// + /// See [`ptr::copy`] for safety concerns and examples. + /// + /// [`ptr::copy`]: crate::ptr::copy() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_to(self, dest: NonNull, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { ptr::copy(self.pointer, dest.as_ptr(), count) } + } + + /// Copies `count * size_of` bytes from `self` to `dest`. The source + /// and destination may *not* overlap. + /// + /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`]. + /// + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. + /// + /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { ptr::copy_nonoverlapping(self.pointer, dest.as_ptr(), count) } + } + + /// Copies `count * size_of` bytes from `src` to `self`. The source + /// and destination may overlap. + /// + /// NOTE: this has the *opposite* argument order of [`ptr::copy`]. + /// + /// See [`ptr::copy`] for safety concerns and examples. + /// + /// [`ptr::copy`]: crate::ptr::copy() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_from(self, src: NonNull, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy`. + unsafe { ptr::copy(src.pointer, self.as_ptr(), count) } + } + + /// Copies `count * size_of` bytes from `src` to `self`. The source + /// and destination may *not* overlap. + /// + /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`]. + /// + /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. + /// + /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`. + unsafe { ptr::copy_nonoverlapping(src.pointer, self.as_ptr(), count) } + } + + /// Executes the destructor (if any) of the pointed-to value. + /// + /// See [`ptr::drop_in_place`] for safety concerns and examples. + /// + /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + pub unsafe fn drop_in_place(self) { + // SAFETY: the caller must uphold the safety contract for `drop_in_place`. + unsafe { ptr::drop_in_place(self.as_ptr()) } + } + + /// Overwrites a memory location with the given value without reading or + /// dropping the old value. + /// + /// See [`ptr::write`] for safety concerns and examples. + /// + /// [`ptr::write`]: crate::ptr::write() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + //#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn write(self, val: T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write`. + unsafe { ptr::write(self.as_ptr(), val) } + } + + /// Invokes memset on the specified pointer, setting `count * size_of::()` + /// bytes of memory starting at `self` to `val`. + /// + /// See [`ptr::write_bytes`] for safety concerns and examples. + /// + /// [`ptr::write_bytes`]: crate::ptr::write_bytes() + #[doc(alias = "memset")] + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + //#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn write_bytes(self, val: u8, count: usize) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write_bytes`. + unsafe { ptr::write_bytes(self.as_ptr(), val, count) } + } + + /// Performs a volatile write of a memory location with the given value without + /// reading or dropping the old value. + /// + /// Volatile operations are intended to act on I/O memory, and are guaranteed + /// to not be elided or reordered by the compiler across other volatile + /// operations. + /// + /// See [`ptr::write_volatile`] for safety concerns and examples. + /// + /// [`ptr::write_volatile`]: crate::ptr::write_volatile() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub unsafe fn write_volatile(self, val: T) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `write_volatile`. + unsafe { ptr::write_volatile(self.as_ptr(), val) } + } + + /// Overwrites a memory location with the given value without reading or + /// dropping the old value. + /// + /// Unlike `write`, the pointer may be unaligned. + /// + /// See [`ptr::write_unaligned`] for safety concerns and examples. + /// + /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + //#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn write_unaligned(self, val: T) where T: Sized, { - // SAFETY: We require that the delta stays in-bounds of the object, and - // thus it cannot become null, as no legal objects can be allocated - // in such as way that the null address is part of them. - // And the caller promised the `delta` is sound to subtract. - unsafe { NonNull { pointer: self.pointer.sub(delta) } } + // SAFETY: the caller must uphold the safety contract for `write_unaligned`. + unsafe { ptr::write_unaligned(self.as_ptr(), val) } } - /// See [`pointer::sub_ptr`] for semantics and safety requirements. + /// Replaces the value at `self` with `src`, returning the old + /// value, without dropping either. + /// + /// See [`ptr::replace`] for safety concerns and examples. + /// + /// [`ptr::replace`]: crate::ptr::replace() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + pub unsafe fn replace(self, src: T) -> T + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `replace`. + unsafe { ptr::replace(self.as_ptr(), src) } + } + + /// Swaps the values at two mutable locations of the same type, without + /// deinitializing either. They may overlap, unlike `mem::swap` which is + /// otherwise equivalent. + /// + /// See [`ptr::swap`] for safety concerns and examples. + /// + /// [`ptr::swap`]: crate::ptr::swap() + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + //#[rustc_const_unstable(feature = "const_swap", issue = "83163")] + #[inline(always)] + pub const unsafe fn swap(self, with: NonNull) + where + T: Sized, + { + // SAFETY: the caller must uphold the safety contract for `swap`. + unsafe { ptr::swap(self.as_ptr(), with.as_ptr()) } + } + + /// Computes the offset that needs to be applied to the pointer in order to make it aligned to + /// `align`. + /// + /// If it is not possible to align the pointer, the implementation returns + /// `usize::MAX`. It is permissible for the implementation to *always* + /// return `usize::MAX`. Only your algorithm's performance can depend + /// on getting a usable offset here, not its correctness. + /// + /// The offset is expressed in number of `T` elements, and not bytes. + /// + /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go + /// beyond the allocation that the pointer points into. It is up to the caller to ensure that + /// the returned offset is correct in all terms other than alignment. + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two. + /// + /// # Examples + /// + /// Accessing adjacent `u8` as `u16` + /// + /// ``` + /// #![feature(non_null_convenience)] + /// use std::mem::align_of; + /// use std::ptr::NonNull; + /// + /// # unsafe { + /// let x = [5_u8, 6, 7, 8, 9]; + /// let ptr = NonNull::new(x.as_ptr() as *mut u8).unwrap(); + /// let offset = ptr.align_offset(align_of::()); + /// + /// if offset < x.len() - 1 { + /// let u16_ptr = ptr.add(offset).cast::(); + /// assert!(u16_ptr.read() == u16::from_ne_bytes([5, 6]) || u16_ptr.read() == u16::from_ne_bytes([6, 7])); + /// } else { + /// // while the pointer can be aligned via `offset`, it would point + /// // outside the allocation + /// } + /// # } + /// ``` + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + //#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")] + #[must_use] #[inline] - pub(crate) const unsafe fn sub_ptr(self, subtrahend: Self) -> usize + pub const fn align_offset(self, align: usize) -> usize where T: Sized, { - // SAFETY: The caller promised that this is safe to do, and - // the non-nullness is irrelevant to the operation. - unsafe { self.pointer.sub_ptr(subtrahend.pointer) } + if !align.is_power_of_two() { + panic!("align_offset: align is not a power-of-two"); + } + + { + // SAFETY: `align` has been checked to be a power of 2 above. + unsafe { ptr::align_offset(self.pointer, align) } + } + } + + /// Returns whether the pointer is properly aligned for `T`. + /// + /// # Examples + /// + /// ``` + /// #![feature(pointer_is_aligned)] + /// use std::ptr::NonNull; + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let data = AlignedI32(42); + /// let ptr = NonNull::::from(&data); + /// + /// assert!(ptr.is_aligned()); + /// assert!(!NonNull::new(ptr.as_ptr().wrapping_byte_add(1)).unwrap().is_aligned()); + /// ``` + /// + /// # At compiletime + /// **Note: Alignment at compiletime is experimental and subject to change. See the + /// [tracking issue] for details.** + /// + /// At compiletime, the compiler may not know where a value will end up in memory. + /// Calling this function on a pointer created from a reference at compiletime will only + /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer + /// is never aligned if cast to a type with a stricter alignment than the reference's + /// underlying allocation. + /// + /// ``` + /// #![feature(pointer_is_aligned)] + /// #![feature(const_pointer_is_aligned)] + /// #![feature(non_null_convenience)] + /// #![feature(const_option)] + /// #![feature(const_nonnull_new)] + /// use std::ptr::NonNull; + /// + /// // On some platforms, the alignment of primitives is less than their size. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// #[repr(align(8))] + /// struct AlignedI64(i64); + /// + /// const _: () = { + /// let data = [AlignedI32(42), AlignedI32(42)]; + /// let ptr = NonNull::::new(&data[0] as *const _ as *mut _).unwrap(); + /// assert!(ptr.is_aligned()); + /// + /// // At runtime either `ptr1` or `ptr2` would be aligned, but at compiletime neither is aligned. + /// let ptr1 = ptr.cast::(); + /// let ptr2 = unsafe { ptr.add(1).cast::() }; + /// assert!(!ptr1.is_aligned()); + /// assert!(!ptr2.is_aligned()); + /// }; + /// ``` + /// + /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime + /// pointer is aligned, even if the compiletime pointer wasn't aligned. + /// + /// ``` + /// #![feature(pointer_is_aligned)] + /// #![feature(const_pointer_is_aligned)] + /// + /// // On some platforms, the alignment of primitives is less than their size. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// #[repr(align(8))] + /// struct AlignedI64(i64); + /// + /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned. + /// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42); + /// const _: () = assert!(!COMPTIME_PTR.cast::().is_aligned()); + /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).cast::().is_aligned()); + /// + /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned. + /// let runtime_ptr = COMPTIME_PTR; + /// assert_ne!( + /// runtime_ptr.cast::().is_aligned(), + /// runtime_ptr.wrapping_add(1).cast::().is_aligned(), + /// ); + /// ``` + /// + /// If a pointer is created from a fixed address, this function behaves the same during + /// runtime and compiletime. + /// + /// ``` + /// #![feature(pointer_is_aligned)] + /// #![feature(const_pointer_is_aligned)] + /// #![feature(const_option)] + /// #![feature(const_nonnull_new)] + /// use std::ptr::NonNull; + /// + /// // On some platforms, the alignment of primitives is less than their size. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// #[repr(align(8))] + /// struct AlignedI64(i64); + /// + /// const _: () = { + /// let ptr = NonNull::new(40 as *mut AlignedI32).unwrap(); + /// assert!(ptr.is_aligned()); + /// + /// // For pointers with a known address, runtime and compiletime behavior are identical. + /// let ptr1 = ptr.cast::(); + /// let ptr2 = NonNull::new(ptr.as_ptr().wrapping_add(1)).unwrap().cast::(); + /// assert!(ptr1.is_aligned()); + /// assert!(!ptr2.is_aligned()); + /// }; + /// ``` + /// + /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203 + #[unstable(feature = "pointer_is_aligned", issue = "96284")] + #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")] + #[must_use] + #[inline] + pub const fn is_aligned(self) -> bool + where + T: Sized, + { + self.pointer.is_aligned() + } + + /// Returns whether the pointer is aligned to `align`. + /// + /// For non-`Sized` pointees this operation considers only the data pointer, + /// ignoring the metadata. + /// + /// # Panics + /// + /// The function panics if `align` is not a power-of-two (this includes 0). + /// + /// # Examples + /// + /// ``` + /// #![feature(pointer_is_aligned)] + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// let data = AlignedI32(42); + /// let ptr = &data as *const AlignedI32; + /// + /// assert!(ptr.is_aligned_to(1)); + /// assert!(ptr.is_aligned_to(2)); + /// assert!(ptr.is_aligned_to(4)); + /// + /// assert!(ptr.wrapping_byte_add(2).is_aligned_to(2)); + /// assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4)); + /// + /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8)); + /// ``` + /// + /// # At compiletime + /// **Note: Alignment at compiletime is experimental and subject to change. See the + /// [tracking issue] for details.** + /// + /// At compiletime, the compiler may not know where a value will end up in memory. + /// Calling this function on a pointer created from a reference at compiletime will only + /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer + /// cannot be stricter aligned than the reference's underlying allocation. + /// + /// ``` + /// #![feature(pointer_is_aligned)] + /// #![feature(const_pointer_is_aligned)] + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// const _: () = { + /// let data = AlignedI32(42); + /// let ptr = &data as *const AlignedI32; + /// + /// assert!(ptr.is_aligned_to(1)); + /// assert!(ptr.is_aligned_to(2)); + /// assert!(ptr.is_aligned_to(4)); + /// + /// // At compiletime, we know for sure that the pointer isn't aligned to 8. + /// assert!(!ptr.is_aligned_to(8)); + /// assert!(!ptr.wrapping_add(1).is_aligned_to(8)); + /// }; + /// ``` + /// + /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime + /// pointer is aligned, even if the compiletime pointer wasn't aligned. + /// + /// ``` + /// #![feature(pointer_is_aligned)] + /// #![feature(const_pointer_is_aligned)] + /// + /// // On some platforms, the alignment of i32 is less than 4. + /// #[repr(align(4))] + /// struct AlignedI32(i32); + /// + /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned. + /// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42); + /// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8)); + /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8)); + /// + /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned. + /// let runtime_ptr = COMPTIME_PTR; + /// assert_ne!( + /// runtime_ptr.is_aligned_to(8), + /// runtime_ptr.wrapping_add(1).is_aligned_to(8), + /// ); + /// ``` + /// + /// If a pointer is created from a fixed address, this function behaves the same during + /// runtime and compiletime. + /// + /// ``` + /// #![feature(pointer_is_aligned)] + /// #![feature(const_pointer_is_aligned)] + /// + /// const _: () = { + /// let ptr = 40 as *const u8; + /// assert!(ptr.is_aligned_to(1)); + /// assert!(ptr.is_aligned_to(2)); + /// assert!(ptr.is_aligned_to(4)); + /// assert!(ptr.is_aligned_to(8)); + /// assert!(!ptr.is_aligned_to(16)); + /// }; + /// ``` + /// + /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203 + #[unstable(feature = "pointer_is_aligned", issue = "96284")] + #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")] + #[must_use] + #[inline] + pub const fn is_aligned_to(self, align: usize) -> bool { + self.pointer.is_aligned_to(align) } } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 50127b27f8bfc..90c346e98bccf 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -835,8 +835,6 @@ impl Result { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// let x: u8 = "4" /// .parse::() /// .inspect(|x| println!("original: {x}")) @@ -844,7 +842,7 @@ impl Result { /// .expect("failed to parse number"); /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] pub fn inspect(self, f: F) -> Self { if let Ok(ref t) = self { f(t); @@ -858,8 +856,6 @@ impl Result { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// use std::{fs, io}; /// /// fn read() -> io::Result { @@ -868,7 +864,7 @@ impl Result { /// } /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] pub fn inspect_err(self, f: F) -> Self { if let Err(ref e) = self { f(e); diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 1da3a87e117aa..373b4aee47a06 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -1,9 +1,9 @@ //! Indexing implementations for `[T]`. -use crate::intrinsics::assert_unsafe_precondition; use crate::intrinsics::const_eval_select; use crate::intrinsics::unchecked_sub; use crate::ops; +use crate::panic::debug_assert_nounwind; use crate::ptr; #[stable(feature = "rust1", since = "1.0.0")] @@ -225,31 +225,28 @@ unsafe impl SliceIndex<[T]> for usize { #[inline] unsafe fn get_unchecked(self, slice: *const [T]) -> *const T { - let this = self; + debug_assert_nounwind!( + self < slice.len(), + "slice::get_unchecked requires that the index is within the slice", + ); // SAFETY: the caller guarantees that `slice` is not dangling, so it // cannot be longer than `isize::MAX`. They also guarantee that // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, // so the call to `add` is safe. unsafe { - assert_unsafe_precondition!( - "slice::get_unchecked requires that the index is within the slice", - [T](this: usize, slice: *const [T]) => this < slice.len() - ); + crate::intrinsics::assume(self < slice.len()); slice.as_ptr().add(self) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T { - let this = self; + debug_assert_nounwind!( + self < slice.len(), + "slice::get_unchecked_mut requires that the index is within the slice", + ); // SAFETY: see comments for `get_unchecked` above. - unsafe { - assert_unsafe_precondition!( - "slice::get_unchecked_mut requires that the index is within the slice", - [T](this: usize, slice: *mut [T]) => this < slice.len() - ); - slice.as_mut_ptr().add(self) - } + unsafe { slice.as_mut_ptr().add(self) } } #[inline] @@ -293,32 +290,25 @@ unsafe impl SliceIndex<[T]> for ops::IndexRange { #[inline] unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { - let end = self.end(); + debug_assert_nounwind!( + self.end() <= slice.len(), + "slice::get_unchecked requires that the index is within the slice" + ); // SAFETY: the caller guarantees that `slice` is not dangling, so it // cannot be longer than `isize::MAX`. They also guarantee that // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, // so the call to `add` is safe. - - unsafe { - assert_unsafe_precondition!( - "slice::get_unchecked requires that the index is within the slice", - [T](end: usize, slice: *const [T]) => end <= slice.len() - ); - ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len()) - } + unsafe { ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len()) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { - let end = self.end(); + debug_assert_nounwind!( + self.end() <= slice.len(), + "slice::get_unchecked_mut requires that the index is within the slice", + ); // SAFETY: see comments for `get_unchecked` above. - unsafe { - assert_unsafe_precondition!( - "slice::get_unchecked_mut requires that the index is within the slice", - [T](end: usize, slice: *mut [T]) => end <= slice.len() - ); - ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len()) - } + unsafe { ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len()) } } #[inline] @@ -369,17 +359,15 @@ unsafe impl SliceIndex<[T]> for ops::Range { #[inline] unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { - let this = ops::Range { ..self }; + debug_assert_nounwind!( + self.end >= self.start && self.end <= slice.len(), + "slice::get_unchecked requires that the range is within the slice", + ); // SAFETY: the caller guarantees that `slice` is not dangling, so it // cannot be longer than `isize::MAX`. They also guarantee that // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, // so the call to `add` is safe and the length calculation cannot overflow. unsafe { - assert_unsafe_precondition!( - "slice::get_unchecked requires that the range is within the slice", - [T](this: ops::Range, slice: *const [T]) => - this.end >= this.start && this.end <= slice.len() - ); let new_len = unchecked_sub(self.end, self.start); ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) } @@ -387,14 +375,12 @@ unsafe impl SliceIndex<[T]> for ops::Range { #[inline] unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { - let this = ops::Range { ..self }; + debug_assert_nounwind!( + self.end >= self.start && self.end <= slice.len(), + "slice::get_unchecked_mut requires that the range is within the slice", + ); // SAFETY: see comments for `get_unchecked` above. unsafe { - assert_unsafe_precondition!( - "slice::get_unchecked_mut requires that the range is within the slice", - [T](this: ops::Range, slice: *mut [T]) => - this.end >= this.start && this.end <= slice.len() - ); let new_len = unchecked_sub(self.end, self.start); ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) } diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 3a8b59d727b4a..da7ceb2dd0a0d 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -20,20 +20,6 @@ const fn contains_zero_byte(x: usize) -> bool { x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0 } -#[inline] -#[cfg(target_pointer_width = "16")] -#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")] -const fn repeat_byte(b: u8) -> usize { - (b as usize) << 8 | b as usize -} - -#[inline] -#[cfg(not(target_pointer_width = "16"))] -#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")] -const fn repeat_byte(b: u8) -> usize { - (b as usize) * (usize::MAX / 255) -} - /// Returns the first index matching the byte `x` in `text`. #[inline] #[must_use] @@ -93,7 +79,7 @@ const fn memchr_aligned(x: u8, text: &[u8]) -> Option { } // search the body of the text - let repeated_x = repeat_byte(x); + let repeated_x = usize::repeat_u8(x); while offset <= len - 2 * USIZE_BYTES { // SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes // between the offset and the end of the slice. @@ -149,7 +135,7 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { // Search the body of the text, make sure we don't cross min_aligned_offset. // offset is always aligned, so just testing `>` is sufficient and avoids possible // overflow. - let repeated_x = repeat_byte(x); + let repeated_x = usize::repeat_u8(x); let chunk_bytes = mem::size_of::(); while offset > min_aligned_offset { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 45080eda2ce2f..dec9f194863ef 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -6,15 +6,16 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::cmp::Ordering::{self, Greater, Less}; +use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::fmt; -use crate::intrinsics::{assert_unsafe_precondition, exact_div}; +use crate::intrinsics::exact_div; use crate::marker::Copy; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZeroUsize; use crate::ops::{Bound, FnMut, OneSidedRange, Range, RangeBounds}; use crate::option::Option; use crate::option::Option::{None, Some}; +use crate::panic::debug_assert_nounwind; use crate::ptr; use crate::result::Result; use crate::result::Result::{Err, Ok}; @@ -640,6 +641,11 @@ impl [T] { /// Calling this method with an out-of-bounds index is *[undefined behavior]* /// even if the resulting reference is not used. /// + /// You can think of this like `.get(index).unwrap_unchecked()`. It's UB + /// to call `.get_unchecked(len)`, even if you immediately convert to a + /// pointer. And it's UB to call `.get_unchecked(..len + 1)`, + /// `.get_unchecked(..=len)`, or similar. + /// /// [`get`]: slice::get /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// @@ -675,6 +681,11 @@ impl [T] { /// Calling this method with an out-of-bounds index is *[undefined behavior]* /// even if the resulting reference is not used. /// + /// You can think of this like `.get_mut(index).unwrap_unchecked()`. It's + /// UB to call `.get_unchecked_mut(len)`, even if you immediately convert + /// to a pointer. And it's UB to call `.get_unchecked_mut(..len + 1)`, + /// `.get_unchecked_mut(..=len)`, or similar. + /// /// [`get_mut`]: slice::get_mut /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// @@ -919,14 +930,14 @@ impl [T] { #[unstable(feature = "slice_swap_unchecked", issue = "88539")] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { - let this = self; - let ptr = this.as_mut_ptr(); + debug_assert_nounwind!( + a < self.len() && b < self.len(), + "slice::swap_unchecked requires that the indices are within the slice", + ); + + let ptr = self.as_mut_ptr(); // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()` unsafe { - assert_unsafe_precondition!( - "slice::swap_unchecked requires that the indices are within the slice", - [T](a: usize, b: usize, this: &mut [T]) => a < this.len() && b < this.len() - ); ptr::swap(ptr.add(a), ptr.add(b)); } } @@ -1034,11 +1045,11 @@ impl [T] { /// # Examples /// /// ``` - /// let slice = ['r', 'u', 's', 't']; - /// let mut iter = slice.windows(2); - /// assert_eq!(iter.next().unwrap(), &['r', 'u']); - /// assert_eq!(iter.next().unwrap(), &['u', 's']); - /// assert_eq!(iter.next().unwrap(), &['s', 't']); + /// let slice = ['l', 'o', 'r', 'e', 'm']; + /// let mut iter = slice.windows(3); + /// assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']); + /// assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']); + /// assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']); /// assert!(iter.next().is_none()); /// ``` /// @@ -1259,15 +1270,12 @@ impl [T] { #[inline] #[must_use] pub const unsafe fn as_chunks_unchecked(&self) -> &[[T; N]] { - let this = self; + debug_assert_nounwind!( + N != 0 && self.len() % N == 0, + "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks", + ); // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length - let new_len = unsafe { - assert_unsafe_precondition!( - "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks", - [T](this: &[T], N: usize) => N != 0 && this.len() % N == 0 - ); - exact_div(self.len(), N) - }; + let new_len = unsafe { exact_div(self.len(), N) }; // SAFETY: We cast a slice of `new_len * N` elements into // a slice of `new_len` many `N` elements chunks. unsafe { from_raw_parts(self.as_ptr().cast(), new_len) } @@ -1416,15 +1424,12 @@ impl [T] { #[inline] #[must_use] pub const unsafe fn as_chunks_unchecked_mut(&mut self) -> &mut [[T; N]] { - let this = &*self; + debug_assert_nounwind!( + N != 0 && self.len() % N == 0, + "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks", + ); // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length - let new_len = unsafe { - assert_unsafe_precondition!( - "slice::as_chunks_unchecked_mut requires `N != 0` and the slice to split exactly into `N`-element chunks", - [T](this: &[T], N: usize) => N != 0 && this.len() % N == 0 - ); - exact_div(this.len(), N) - }; + let new_len = unsafe { exact_div(self.len(), N) }; // SAFETY: We cast a slice of `new_len * N` elements into // a slice of `new_len` many `N` elements chunks. unsafe { from_raw_parts_mut(self.as_mut_ptr().cast(), new_len) } @@ -1957,14 +1962,13 @@ impl [T] { let len = self.len(); let ptr = self.as_ptr(); + debug_assert_nounwind!( + mid <= len, + "slice::split_at_unchecked requires the index to be within the slice", + ); + // SAFETY: Caller has to check that `0 <= mid <= self.len()` - unsafe { - assert_unsafe_precondition!( - "slice::split_at_unchecked requires the index to be within the slice", - (mid: usize, len: usize) => mid <= len - ); - (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) - } + unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) } } /// Divides one mutable slice into two at an index, without doing bounds checking. @@ -2008,17 +2012,16 @@ impl [T] { let len = self.len(); let ptr = self.as_mut_ptr(); + debug_assert_nounwind!( + mid <= len, + "slice::split_at_mut_unchecked requires the index to be within the slice", + ); + // SAFETY: Caller has to check that `0 <= mid <= self.len()`. // // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference // is fine. - unsafe { - assert_unsafe_precondition!( - "slice::split_at_mut_unchecked requires the index to be within the slice", - (mid: usize, len: usize) => mid <= len - ); - (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) - } + unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } } /// Divides one slice into an array and a remainder slice at an index. @@ -2844,14 +2847,13 @@ impl [T] { // we have `left + size/2 < self.len()`, and this is in-bounds. let cmp = f(unsafe { self.get_unchecked(mid) }); - // The reason why we use if/else control flow rather than match - // is because match reorders comparison operations, which is perf sensitive. - // This is x86 asm for u8: https://rust.godbolt.org/z/8Y8Pra. - if cmp == Less { - left = mid + 1; - } else if cmp == Greater { - right = mid; - } else { + // This control flow produces conditional moves, which results in + // fewer branches and instructions than if/else or matching on + // cmp::Ordering. + // This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx. + left = if cmp == Less { mid + 1 } else { left }; + right = if cmp == Greater { mid } else { right }; + if cmp == Equal { // SAFETY: same as the `get_unchecked` above unsafe { crate::intrinsics::assume(mid < self.len()) }; return Ok(mid); @@ -3866,6 +3868,12 @@ impl [T] { } else { let (left, rest) = self.split_at(offset); let (us_len, ts_len) = rest.align_to_offsets::(); + // Inform Miri that we want to consider the "middle" pointer to be suitably aligned. + #[cfg(miri)] + crate::intrinsics::miri_promise_symbolic_alignment( + rest.as_ptr().cast(), + mem::align_of::(), + ); // SAFETY: now `rest` is definitely aligned, so `from_raw_parts` below is okay, // since the caller guarantees that we can transmute `T` to `U` safely. unsafe { @@ -3936,6 +3944,12 @@ impl [T] { let (us_len, ts_len) = rest.align_to_offsets::(); let rest_len = rest.len(); let mut_ptr = rest.as_mut_ptr(); + // Inform Miri that we want to consider the "middle" pointer to be suitably aligned. + #[cfg(miri)] + crate::intrinsics::miri_promise_symbolic_alignment( + mut_ptr.cast() as *const (), + mem::align_of::(), + ); // We can't use `rest` again after this, that would invalidate its alias `mut_ptr`! // SAFETY: see comments for `align_to`. unsafe { @@ -3977,7 +3991,7 @@ impl [T] { /// /// ``` /// #![feature(portable_simd)] - /// use core::simd::SimdFloat; + /// use core::simd::prelude::*; /// /// let short = &[1, 2, 3]; /// let (prefix, middle, suffix) = short.as_simd::<4>(); @@ -3989,7 +4003,6 @@ impl [T] { /// /// fn basic_simd_sum(x: &[f32]) -> f32 { /// use std::ops::Add; - /// use std::simd::f32x4; /// let (prefix, middle, suffix) = x.as_simd(); /// let sums = f32x4::from_array([ /// prefix.iter().copied().sum(), diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index db76d26257aac..993a608f42b60 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -628,9 +628,14 @@ where let _pivot_guard = InsertionHole { src: &*tmp, dest: pivot }; let pivot = &*tmp; + let len = v.len(); + if len == 0 { + return 0; + } + // Now partition the slice. let mut l = 0; - let mut r = v.len(); + let mut r = len; loop { // SAFETY: The unsafety below involves indexing an array. // For the first one: We already do the bounds checking here with `l < r`. @@ -643,8 +648,11 @@ where } // Find the last element equal to the pivot. - while l < r && is_less(pivot, v.get_unchecked(r - 1)) { + loop { r -= 1; + if l >= r || !is_less(pivot, v.get_unchecked(r)) { + break; + } } // Are we done? @@ -653,7 +661,6 @@ where } // Swap the found pair of out-of-order elements. - r -= 1; let ptr = v.as_mut_ptr(); ptr::swap(ptr.add(l), ptr.add(r)); l += 1; diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index c30f01b3c06a4..dd2efb0051672 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -8,6 +8,7 @@ use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::ops::Try; use crate::option; use crate::slice::{self, Split as SliceSplit}; +use core::num::NonZeroUsize; use super::from_utf8_unchecked; use super::pattern::Pattern; @@ -49,6 +50,55 @@ impl<'a> Iterator for Chars<'a> { super::count::count_chars(self.as_str()) } + #[inline] + fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZeroUsize> { + const CHUNK_SIZE: usize = 32; + + if remainder >= CHUNK_SIZE { + let mut chunks = self.iter.as_slice().array_chunks::(); + let mut bytes_skipped: usize = 0; + + while remainder > CHUNK_SIZE + && let Some(chunk) = chunks.next() + { + bytes_skipped += CHUNK_SIZE; + + let mut start_bytes = [false; CHUNK_SIZE]; + + for i in 0..CHUNK_SIZE { + start_bytes[i] = !super::validations::utf8_is_cont_byte(chunk[i]); + } + + remainder -= start_bytes.into_iter().map(|i| i as u8).sum::() as usize; + } + + // SAFETY: The amount of bytes exists since we just iterated over them, + // so advance_by will succeed. + unsafe { self.iter.advance_by(bytes_skipped).unwrap_unchecked() }; + + // skip trailing continuation bytes + while self.iter.len() > 0 { + let b = self.iter.as_slice()[0]; + if !super::validations::utf8_is_cont_byte(b) { + break; + } + // SAFETY: We just peeked at the byte, therefore it exists + unsafe { self.iter.advance_by(1).unwrap_unchecked() }; + } + } + + while (remainder > 0) && (self.iter.len() > 0) { + remainder -= 1; + let b = self.iter.as_slice()[0]; + let slurp = super::validations::utf8_char_width(b); + // SAFETY: utf8 validity requires that the string must contain + // the continuation bytes (if any) + unsafe { self.iter.advance_by(slurp).unwrap_unchecked() }; + } + + NonZeroUsize::new(remainder).map_or(Ok(()), Err) + } + #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.iter.len(); diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index d5d6d60acf61d..caa54e00f319f 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -806,6 +806,8 @@ unsafe impl<'a, const N: usize> ReverseSearcher<'a> for CharArraySearcher<'a, N> searcher_methods!(reverse); } +impl<'a, const N: usize> DoubleEndedSearcher<'a> for CharArraySearcher<'a, N> {} + /// Searches for chars that are equal to any of the [`char`]s in the array. /// /// # Examples @@ -826,6 +828,8 @@ unsafe impl<'a, 'b, const N: usize> ReverseSearcher<'a> for CharArrayRefSearcher searcher_methods!(reverse); } +impl<'a, 'b, const N: usize> DoubleEndedSearcher<'a> for CharArrayRefSearcher<'a, 'b, N> {} + ///////////////////////////////////////////////////////////////////////////// // Impl for &[char] ///////////////////////////////////////////////////////////////////////////// @@ -1736,9 +1740,9 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { debug_assert!(needle.len() > 1); use crate::ops::BitAnd; + use crate::simd::cmp::SimdPartialEq; use crate::simd::mask8x16 as Mask; use crate::simd::u8x16 as Block; - use crate::simd::{SimdPartialEq, ToBitMask}; let first_probe = needle[0]; let last_byte_offset = needle.len() - 1; @@ -1761,7 +1765,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { }; // do a naive search if the haystack is too small to fit - if haystack.len() < Block::LANES + last_byte_offset { + if haystack.len() < Block::LEN + last_byte_offset { return Some(haystack.windows(needle.len()).any(|c| c == needle)); } @@ -1808,7 +1812,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { let eq_first: Mask = a.simd_eq(first_probe); let eq_last: Mask = b.simd_eq(second_probe); let both = eq_first.bitand(eq_last); - let mask = both.to_bitmask(); + let mask = both.to_bitmask() as u16; return mask; }; @@ -1818,32 +1822,32 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { // The loop condition must ensure that there's enough headroom to read LANE bytes, // and not only at the current index but also at the index shifted by block_offset const UNROLL: usize = 4; - while i + last_byte_offset + UNROLL * Block::LANES < haystack.len() && !result { + while i + last_byte_offset + UNROLL * Block::LEN < haystack.len() && !result { let mut masks = [0u16; UNROLL]; for j in 0..UNROLL { - masks[j] = test_chunk(i + j * Block::LANES); + masks[j] = test_chunk(i + j * Block::LEN); } for j in 0..UNROLL { let mask = masks[j]; if mask != 0 { - result |= check_mask(i + j * Block::LANES, mask, result); + result |= check_mask(i + j * Block::LEN, mask, result); } } - i += UNROLL * Block::LANES; + i += UNROLL * Block::LEN; } - while i + last_byte_offset + Block::LANES < haystack.len() && !result { + while i + last_byte_offset + Block::LEN < haystack.len() && !result { let mask = test_chunk(i); if mask != 0 { result |= check_mask(i, mask, result); } - i += Block::LANES; + i += Block::LEN; } // Process the tail that didn't fit into LANES-sized steps. // This simply repeats the same procedure but as right-aligned chunk instead // of a left-aligned one. The last byte must be exactly flush with the string end so // we don't miss a single byte or read out of bounds. - let i = haystack.len() - last_byte_offset - Block::LANES; + let i = haystack.len() - last_byte_offset - Block::LEN; let mask = test_chunk(i); if mask != 0 { result |= check_mask(i, mask, result); diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 16fb1dad7230f..777ad0d818b50 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -1,8 +1,8 @@ //! Trait implementations for `str`. use crate::cmp::Ordering; -use crate::intrinsics::assert_unsafe_precondition; use crate::ops; +use crate::panic::debug_assert_nounwind; use crate::ptr; use crate::slice::SliceIndex; @@ -191,39 +191,35 @@ unsafe impl SliceIndex for ops::Range { #[inline] unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { let slice = slice as *const [u8]; + + debug_assert_nounwind!( + // We'd like to check that the bounds are on char boundaries, + // but there's not really a way to do so without reading + // behind the pointer, which has aliasing implications. + // It's also not possible to move this check up to + // `str::get_unchecked` without adding a special function + // to `SliceIndex` just for this. + self.end >= self.start && self.end <= slice.len(), + "str::get_unchecked requires that the range is within the string slice", + ); + // SAFETY: the caller guarantees that `self` is in bounds of `slice` // which satisfies all the conditions for `add`. - let ptr = unsafe { - let this = ops::Range { ..self }; - assert_unsafe_precondition!( - "str::get_unchecked requires that the range is within the string slice", - (this: ops::Range, slice: *const [u8]) => - // We'd like to check that the bounds are on char boundaries, - // but there's not really a way to do so without reading - // behind the pointer, which has aliasing implications. - // It's also not possible to move this check up to - // `str::get_unchecked` without adding a special function - // to `SliceIndex` just for this. - this.end >= this.start && this.end <= slice.len() - ); - slice.as_ptr().add(self.start) - }; + let ptr = unsafe { slice.as_ptr().add(self.start) }; let len = self.end - self.start; ptr::slice_from_raw_parts(ptr, len) as *const str } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { let slice = slice as *mut [u8]; + + debug_assert_nounwind!( + self.end >= self.start && self.end <= slice.len(), + "str::get_unchecked_mut requires that the range is within the string slice", + ); + // SAFETY: see comments for `get_unchecked`. - let ptr = unsafe { - let this = ops::Range { ..self }; - assert_unsafe_precondition!( - "str::get_unchecked_mut requires that the range is within the string slice", - (this: ops::Range, slice: *mut [u8]) => - this.end >= this.start && this.end <= slice.len() - ); - slice.as_mut_ptr().add(self.start) - }; + let ptr = unsafe { slice.as_mut_ptr().add(self.start) }; let len = self.end - self.start; ptr::slice_from_raw_parts_mut(ptr, len) as *mut str } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index b5ad3f280e6b1..5f1f41e68658c 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -4,26 +4,12 @@ //! threads, and are the building blocks of other concurrent //! types. //! -//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically `atomic_ref`. -//! Basically, creating a *shared reference* to one of the Rust atomic types corresponds to creating -//! an `atomic_ref` in C++; the `atomic_ref` is destroyed when the lifetime of the shared reference -//! ends. (A Rust atomic type that is exclusively owned or behind a mutable reference does *not* -//! correspond to an "atomic object" in C++, since it can be accessed via non-atomic operations.) -//! //! This module defines atomic versions of a select number of primitive //! types, including [`AtomicBool`], [`AtomicIsize`], [`AtomicUsize`], //! [`AtomicI8`], [`AtomicU16`], etc. //! Atomic types present operations that, when used correctly, synchronize //! updates between threads. //! -//! Each method takes an [`Ordering`] which represents the strength of -//! the memory barrier for that operation. These orderings are the -//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2]. -//! -//! [cpp]: https://en.cppreference.com/w/cpp/atomic -//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order -//! [2]: ../../../nomicon/atomics.html -//! //! Atomic variables are safe to share between threads (they implement [`Sync`]) //! but they do not themselves provide the mechanism for sharing and follow the //! [threading model](../../../std/thread/index.html#the-threading-model) of Rust. @@ -36,6 +22,75 @@ //! the constant initializers like [`AtomicBool::new`]. Atomic statics //! are often used for lazy global initialization. //! +//! ## Memory model for atomic accesses +//! +//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically `atomic_ref`. +//! Basically, creating a *shared reference* to one of the Rust atomic types corresponds to creating +//! an `atomic_ref` in C++; the `atomic_ref` is destroyed when the lifetime of the shared reference +//! ends. (A Rust atomic type that is exclusively owned or behind a mutable reference does *not* +//! correspond to an "atomic object" in C++, since it can be accessed via non-atomic operations.) +//! +//! [cpp]: https://en.cppreference.com/w/cpp/atomic +//! +//! Each method takes an [`Ordering`] which represents the strength of +//! the memory barrier for that operation. These orderings are the +//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2]. +//! +//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order +//! [2]: ../../../nomicon/atomics.html +//! +//! Since C++ does not support mixing atomic and non-atomic accesses, or non-synchronized +//! different-sized accesses to the same data, Rust does not support those operations either. +//! Note that both of those restrictions only apply if the accesses are non-synchronized. +//! +//! ```rust,no_run undefined_behavior +//! use std::sync::atomic::{AtomicU16, AtomicU8, Ordering}; +//! use std::mem::transmute; +//! use std::thread; +//! +//! let atomic = AtomicU16::new(0); +//! +//! thread::scope(|s| { +//! // This is UB: mixing atomic and non-atomic accesses +//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); +//! }); +//! +//! thread::scope(|s| { +//! // This is UB: even reads are not allowed to be mixed +//! s.spawn(|| atomic.load(Ordering::Relaxed)); +//! s.spawn(|| unsafe { atomic.as_ptr().read() }); +//! }); +//! +//! thread::scope(|s| { +//! // This is fine, `join` synchronizes the code in a way such that atomic +//! // and non-atomic accesses can't happen "at the same time" +//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! handle.join().unwrap(); +//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); +//! }); +//! +//! thread::scope(|s| { +//! // This is UB: using different-sized atomic accesses to the same data +//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! s.spawn(|| unsafe { +//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic); +//! differently_sized.store(2, Ordering::Relaxed); +//! }); +//! }); +//! +//! thread::scope(|s| { +//! // This is fine, `join` synchronizes the code in a way such that +//! // differently-sized accesses can't happen "at the same time" +//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); +//! handle.join().unwrap(); +//! s.spawn(|| unsafe { +//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic); +//! differently_sized.store(2, Ordering::Relaxed); +//! }); +//! }); +//! ``` +//! //! # Portability //! //! All atomic types in this module are guaranteed to be [lock-free] if they're @@ -383,17 +438,13 @@ impl AtomicBool { /// * `ptr` must be aligned to `align_of::()` (note that on some platforms this can /// be bigger than `align_of::()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * Non-atomic accesses to the value behind `ptr` must have a happens-before relationship - /// with atomic accesses via the returned value (or vice-versa). - /// * In other words, time periods where the value is accessed atomically may not overlap - /// with periods where the value is accessed non-atomically. - /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the - /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. - /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done - /// from the same thread. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. /// /// [valid]: crate::ptr#safety - #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[stable(feature = "atomic_from_ptr", since = "1.75.0")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { // SAFETY: guaranteed by the caller @@ -1185,19 +1236,13 @@ impl AtomicPtr { /// * `ptr` must be aligned to `align_of::>()` (note that on some platforms this /// can be bigger than `align_of::<*mut T>()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * Non-atomic accesses to the value behind `ptr` must have a happens-before relationship - /// with atomic accesses via the returned value (or vice-versa). - /// * In other words, time periods where the value is accessed atomically may not overlap - /// with periods where the value is accessed non-atomically. - /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the - /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. - /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done - /// from the same thread. - /// * This method should not be used to create overlapping or mixed-size atomic accesses, as - /// these are not supported by the memory model. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. /// /// [valid]: crate::ptr#safety - #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[stable(feature = "atomic_from_ptr", since = "1.75.0")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr { // SAFETY: guaranteed by the caller @@ -2167,20 +2212,13 @@ macro_rules! atomic_int { `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this \ can be bigger than `align_of::<", stringify!($int_type), ">()`).")] /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * Non-atomic accesses to the value behind `ptr` must have a happens-before - /// relationship with atomic accesses via the returned value (or vice-versa). - /// * In other words, time periods where the value is accessed atomically may not - /// overlap with periods where the value is accessed non-atomically. - /// * This requirement is trivially satisfied if `ptr` is never used non-atomically - /// for the duration of lifetime `'a`. Most use cases should be able to follow - /// this guideline. - /// * This requirement is also trivially satisfied if all accesses (atomic or not) are - /// done from the same thread. - /// * This method should not be used to create overlapping or mixed-size atomic - /// accesses, as these are not supported by the memory model. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. /// /// [valid]: crate::ptr#safety - #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[stable(feature = "atomic_from_ptr", since = "1.75.0")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { // SAFETY: guaranteed by the caller diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index b63fd5c9095fc..817e39942c053 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -231,6 +231,10 @@ impl fmt::Debug for Context<'_> { /// this might be done to wake a future when a blocking function call completes on another /// thread. /// +/// Note that it is preferable to use `waker.clone_from(&new_waker)` instead +/// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker +/// unnecessarily if the two wakers [wake the same task](Self::will_wake). +/// /// [`Future::poll()`]: core::future::Future::poll /// [`Poll::Pending`]: core::task::Poll::Pending #[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401 @@ -302,7 +306,9 @@ impl Waker { /// when the `Waker`s would awaken the same task. However, if this function /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. /// - /// This function is primarily used for optimization purposes. + /// This function is primarily used for optimization purposes — for example, + /// this type's [`clone_from`](Self::clone_from) implementation uses it to + /// avoid cloning the waker when they would wake the same task anyway. #[inline] #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] @@ -382,6 +388,13 @@ impl Clone for Waker { waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, } } + + #[inline] + fn clone_from(&mut self, source: &Self) { + if !self.will_wake(source) { + *self = source.clone(); + } + } } #[stable(feature = "futures_api", since = "1.36.0")] diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 6ef35d8414be5..b677776443fe0 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -461,6 +461,27 @@ impl Duration { self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128 } + /// Computes the absolute difference between `self` and `other`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(duration_abs_diff)] + /// use std::time::Duration; + /// + /// assert_eq!(Duration::new(100, 0).abs_diff(Duration::new(80, 0)), Duration::new(20, 0)); + /// assert_eq!(Duration::new(100, 400_000_000).abs_diff(Duration::new(110, 0)), Duration::new(9, 600_000_000)); + /// ``` + #[unstable(feature = "duration_abs_diff", issue = "117618")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs_diff(self, other: Duration) -> Duration { + if let Some(res) = self.checked_sub(other) { res } else { other.checked_sub(self).unwrap() } + } + /// Checked `Duration` addition. Computes `self + other`, returning [`None`] /// if overflow occurred. /// diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index ff292ff2dcbfb..765f73636fb8e 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -50,22 +50,19 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[unstable(feature = "structural_match", issue = "31434")] - impl<$($T: ConstParamTy),+> ConstParamTy for ($($T,)+) - {} + impl<$($T: ConstParamTy),+> ConstParamTy for ($($T,)+) {} } maybe_tuple_doc! { $($T)+ @ #[unstable(feature = "structural_match", issue = "31434")] - impl<$($T),+> StructuralPartialEq for ($($T,)+) - {} + impl<$($T),+> StructuralPartialEq for ($($T,)+) {} } maybe_tuple_doc! { $($T)+ @ #[unstable(feature = "structural_match", issue = "31434")] - impl<$($T),+> StructuralEq for ($($T,)+) - {} + impl<$($T),+> StructuralEq for ($($T,)+) {} } maybe_tuple_doc! { @@ -118,7 +115,7 @@ macro_rules! tuple_impls { impl<$($T: Default),+> Default for ($($T,)+) { #[inline] fn default() -> ($($T,)+) { - ($({ let x: $T = Default::default(); x},)+) + ($($T::default(),)+) } } } @@ -196,7 +193,7 @@ macro_rules! lexical_partial_cmp { ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { match ($a).partial_cmp(&$b) { Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+), - ordering => ordering + ordering => ordering } }; ($a:expr, $b:expr) => { ($a).partial_cmp(&$b) }; @@ -206,7 +203,7 @@ macro_rules! lexical_cmp { ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { match ($a).cmp(&$b) { Equal => lexical_cmp!($($rest_a, $rest_b),+), - ordering => ordering + ordering => ordering } }; ($a:expr, $b:expr) => { ($a).cmp(&$b) }; diff --git a/library/core/tests/fmt/num.rs b/library/core/tests/fmt/num.rs index b9ede65c9ff09..bc387a46ea7dd 100644 --- a/library/core/tests/fmt/num.rs +++ b/library/core/tests/fmt/num.rs @@ -128,28 +128,43 @@ fn test_format_int_exp_precision() { let big_int: u32 = 314_159_265; assert_eq!(format!("{big_int:.1e}"), format!("{:.1e}", f64::from(big_int))); - //test adding precision + // test adding precision assert_eq!(format!("{:.10e}", i8::MIN), "-1.2800000000e2"); assert_eq!(format!("{:.10e}", i16::MIN), "-3.2768000000e4"); assert_eq!(format!("{:.10e}", i32::MIN), "-2.1474836480e9"); assert_eq!(format!("{:.20e}", i64::MIN), "-9.22337203685477580800e18"); assert_eq!(format!("{:.40e}", i128::MIN), "-1.7014118346046923173168730371588410572800e38"); - //test rounding + // test rounding assert_eq!(format!("{:.1e}", i8::MIN), "-1.3e2"); assert_eq!(format!("{:.1e}", i16::MIN), "-3.3e4"); assert_eq!(format!("{:.1e}", i32::MIN), "-2.1e9"); assert_eq!(format!("{:.1e}", i64::MIN), "-9.2e18"); assert_eq!(format!("{:.1e}", i128::MIN), "-1.7e38"); - //test huge precision + // test huge precision assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000))); //test zero precision assert_eq!(format!("{:.0e}", 1), format!("1e0",)); assert_eq!(format!("{:.0e}", 35), format!("4e1",)); - //test padding with precision (and sign) + // test padding with precision (and sign) assert_eq!(format!("{:+10.3e}", 1), " +1.000e0"); + + // test precision remains correct when rounding to next power + #[cfg(miri)] // can't cover all of `i16` in Miri + let range = [i16::MIN, -1, 1, i16::MAX]; + #[cfg(not(miri))] + let range = i16::MIN..=i16::MAX; + for i in range { + for p in 0..=5 { + assert_eq!( + format!("{i:.p$e}"), + format!("{:.p$e}", f32::from(i)), + "integer {i} at precision {p}" + ); + } + } } #[test] diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 033bd1ed6ed9e..5268f32c03198 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -167,7 +167,7 @@ fn test_indirect_hasher() { #[test] fn test_build_hasher_object_safe() { - use std::collections::hash_map::{DefaultHasher, RandomState}; + use std::hash::{DefaultHasher, RandomState}; let _: &dyn BuildHasher = &RandomState::new(); } diff --git a/library/std/src/io/readbuf/tests.rs b/library/core/tests/io/borrowed_buf.rs similarity index 98% rename from library/std/src/io/readbuf/tests.rs rename to library/core/tests/io/borrowed_buf.rs index 89a2f6b2271bd..69511e49acdbc 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/core/tests/io/borrowed_buf.rs @@ -1,5 +1,5 @@ -use super::BorrowedBuf; -use crate::mem::MaybeUninit; +use core::io::BorrowedBuf; +use core::mem::MaybeUninit; /// Test that BorrowedBuf has the correct numbers when created with new #[test] diff --git a/library/core/tests/io/mod.rs b/library/core/tests/io/mod.rs new file mode 100644 index 0000000000000..a24893a525a9d --- /dev/null +++ b/library/core/tests/io/mod.rs @@ -0,0 +1 @@ +mod borrowed_buf; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index df7b34ce73b42..c531117bed5ad 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -23,10 +23,12 @@ #![feature(const_likely)] #![feature(const_location_fields)] #![feature(core_intrinsics)] +#![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] #![feature(div_duration)] +#![feature(duration_abs_diff)] #![feature(duration_consts_float)] #![feature(duration_constants)] #![feature(exact_size_is_empty)] @@ -109,12 +111,13 @@ #![feature(slice_flatten)] #![feature(error_generic_member_access)] #![feature(error_in_core)] -#![feature(trait_upcasting)] +#![cfg_attr(bootstrap, feature(trait_upcasting))] #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] #![feature(offset_of)] #![feature(iter_map_windows)] +#![allow(internal_features)] #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] @@ -135,6 +138,7 @@ mod fmt; mod future; mod hash; mod intrinsics; +mod io; mod iter; mod lazy; #[cfg(test)] @@ -167,7 +171,7 @@ mod waker; #[allow(dead_code)] // Not used in all configurations. pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = std::hash::RandomState::new().build_hasher(); core::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 5c2e18745ea21..20498b16cb22b 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -565,3 +565,24 @@ fn offset_of_addr() { assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr()); assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr()); } + +#[test] +fn const_maybe_uninit_zeroed() { + // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term) + #[repr(C)] + struct Foo { + a: Option<&'static str>, + b: Bar, + c: f32, + d: *const u8, + } + #[repr(C)] + struct Bar(usize); + struct FooPtr(*const Foo); + unsafe impl Sync for FooPtr {} + + static UNINIT: FooPtr = FooPtr([unsafe { MaybeUninit::zeroed().assume_init() }].as_ptr()); + const SIZE: usize = size_of::(); + + assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]); +} diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index 5defeb50d40f9..5dc012bab4adb 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -568,3 +568,11 @@ fn zip_unzip_roundtrip() { let a = z.unzip(); assert_eq!(a, (x, y)); } + +#[test] +fn as_slice() { + assert_eq!(Some(42).as_slice(), &[42]); + assert_eq!(Some(43).as_mut_slice(), &[43]); + assert_eq!(None::.as_slice(), &[]); + assert_eq!(None::.as_mut_slice(), &[]); +} diff --git a/library/core/tests/simd.rs b/library/core/tests/simd.rs index 565c8975eb94f..b8b5f26ca3fa4 100644 --- a/library/core/tests/simd.rs +++ b/library/core/tests/simd.rs @@ -1,5 +1,4 @@ -use core::simd::f32x4; -use core::simd::SimdFloat; +use core::simd::prelude::*; #[test] fn testing() { diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs index bd6e63edbb9e5..24ab4be9d8c9f 100644 --- a/library/core/tests/time.rs +++ b/library/core/tests/time.rs @@ -73,6 +73,19 @@ fn nanos() { assert_eq!(Duration::from_nanos(1_000_000_001).subsec_nanos(), 1); } +#[test] +fn abs_diff() { + assert_eq!(Duration::new(2, 0).abs_diff(Duration::new(1, 0)), Duration::new(1, 0)); + assert_eq!(Duration::new(1, 0).abs_diff(Duration::new(2, 0)), Duration::new(1, 0)); + assert_eq!(Duration::new(1, 0).abs_diff(Duration::new(1, 0)), Duration::new(0, 0)); + assert_eq!(Duration::new(1, 1).abs_diff(Duration::new(0, 2)), Duration::new(0, 999_999_999)); + assert_eq!(Duration::new(1, 1).abs_diff(Duration::new(2, 1)), Duration::new(1, 0)); + assert_eq!(Duration::MAX.abs_diff(Duration::MAX), Duration::ZERO); + assert_eq!(Duration::ZERO.abs_diff(Duration::ZERO), Duration::ZERO); + assert_eq!(Duration::MAX.abs_diff(Duration::ZERO), Duration::MAX); + assert_eq!(Duration::ZERO.abs_diff(Duration::MAX), Duration::MAX); +} + #[test] fn add() { assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), Duration::new(0, 1)); diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index 6e097e2caf24b..8fd64279ac5a7 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -81,6 +81,16 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 { } core::intrinsics::unreachable(); } + } else if #[cfg(target_os = "teeos")] { + mod teeos { + extern "C" { + pub fn TEE_Panic(code: u32) -> !; + } + } + + unsafe fn abort() -> ! { + teeos::TEE_Panic(1); + } } else { unsafe fn abort() -> ! { core::intrinsics::abort(); diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 9363fde5de2e7..7a0bae34642d6 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -49,6 +49,7 @@ cfg_if::cfg_if! { } else if #[cfg(any( all(target_family = "windows", target_env = "gnu"), target_os = "psp", + target_os = "xous", target_os = "solid_asp3", all(target_family = "unix", not(target_os = "espidf")), all(target_vendor = "fortanix", target_env = "sgx"), diff --git a/library/portable-simd/.github/workflows/ci.yml b/library/portable-simd/.github/workflows/ci.yml index 1ff377fce3467..90543044ea845 100644 --- a/library/portable-simd/.github/workflows/ci.yml +++ b/library/portable-simd/.github/workflows/ci.yml @@ -167,40 +167,33 @@ jobs: RUSTFLAGS: ${{ matrix.rustflags }} cross-tests: - name: "${{ matrix.target }} (via cross)" + name: "${{ matrix.target_feature }} on ${{ matrix.target }} (via cross)" runs-on: ubuntu-latest strategy: fail-fast: false - # TODO: Sadly, we cant configure target-feature in a meaningful way - # because `cross` doesn't tell qemu to enable any non-default cpu - # features, nor does it give us a way to do so. - # - # Ultimately, we'd like to do something like [rust-lang/stdarch][stdarch]. - # This is a lot more complex... but in practice it's likely that we can just - # snarf the docker config from around [here][1000-dockerfiles]. - # - # [stdarch]: https://github.com/rust-lang/stdarch/blob/a5db4eaf/.github/workflows/main.yml#L67 - # [1000-dockerfiles]: https://github.com/rust-lang/stdarch/tree/a5db4eaf/ci/docker matrix: target: - - i586-unknown-linux-gnu - # 32-bit arm has a few idiosyncracies like having subnormal flushing - # to zero on by default. Ideally we'd set - armv7-unknown-linux-gnueabihf - - aarch64-unknown-linux-gnu - # Note: The issue above means neither of these mips targets will use - # MSA (mips simd) but MIPS uses a nonstandard binary representation - # for NaNs which makes it worth testing on despite that. + - thumbv7neon-unknown-linux-gnueabihf # includes neon by default + - aarch64-unknown-linux-gnu # includes neon by default + - powerpc-unknown-linux-gnu + - powerpc64le-unknown-linux-gnu # includes altivec by default + - riscv64gc-unknown-linux-gnu + # MIPS uses a nonstandard binary representation for NaNs which makes it worth testing + # non-nightly since https://github.com/rust-lang/rust/pull/113274 # - mips-unknown-linux-gnu # - mips64-unknown-linux-gnuabi64 - - riscv64gc-unknown-linux-gnu - # TODO this test works, but it appears to time out - # - powerpc-unknown-linux-gnu - # TODO this test is broken, but it appears to be a problem with QEMU, not us. - # - powerpc64le-unknown-linux-gnu - # TODO enable this once a new version of cross is released + # Lots of errors in QEMU and no real hardware to test on. Not clear if it's QEMU or bad codegen. # - powerpc64-unknown-linux-gnu + target_feature: [default] + include: + - { target: powerpc64le-unknown-linux-gnu, target_feature: "+vsx" } + # Fails due to QEMU floating point errors, probably handling subnormals incorrectly. + # This target is somewhat redundant, since ppc64le has altivec as well. + # - { target: powerpc-unknown-linux-gnu, target_feature: "+altivec" } + # We should test this, but cross currently can't run it + # - { target: riscv64gc-unknown-linux-gnu, target_feature: "+v,+zvl128b" } steps: - uses: actions/checkout@v2 @@ -217,11 +210,27 @@ jobs: # being part of the tarball means we can't just use the download/latest # URL :( run: | - CROSS_URL=https://github.com/rust-embedded/cross/releases/download/v0.2.1/cross-v0.2.1-x86_64-unknown-linux-gnu.tar.gz + CROSS_URL=https://github.com/cross-rs/cross/releases/download/v0.2.5/cross-x86_64-unknown-linux-gnu.tar.gz mkdir -p "$HOME/.bin" curl -sfSL --retry-delay 10 --retry 5 "${CROSS_URL}" | tar zxf - -C "$HOME/.bin" echo "$HOME/.bin" >> $GITHUB_PATH + - name: Configure Emulated CPUs + run: | + echo "CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc -cpu e600" >> $GITHUB_ENV + # echo "CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER=qemu-riscv64 -cpu rv64,zba=true,zbb=true,v=true,vlen=256,vext_spec=v1.0" >> $GITHUB_ENV + + - name: Configure RUSTFLAGS + shell: bash + run: | + case "${{ matrix.target_feature }}" in + default) + echo "RUSTFLAGS=" >> $GITHUB_ENV;; + *) + echo "RUSTFLAGS=-Ctarget-feature=${{ matrix.target_feature }}" >> $GITHUB_ENV + ;; + esac + - name: Test (debug) run: cross test --verbose --target=${{ matrix.target }} @@ -229,7 +238,7 @@ jobs: run: cross test --verbose --target=${{ matrix.target }} --release features: - name: "Check cargo features (${{ matrix.simd }} × ${{ matrix.features }})" + name: "Test cargo features (${{ matrix.simd }} × ${{ matrix.features }})" runs-on: ubuntu-latest strategy: fail-fast: false @@ -240,12 +249,8 @@ jobs: features: - "" - "--features std" - - "--features generic_const_exprs" - - "--features std --features generic_const_exprs" - "--features all_lane_counts" - - "--features all_lane_counts --features std" - - "--features all_lane_counts --features generic_const_exprs" - - "--features all_lane_counts --features std --features generic_const_exprs" + - "--all-features" steps: - uses: actions/checkout@v2 @@ -257,9 +262,9 @@ jobs: run: echo "CPU_FEATURE=$(lscpu | grep -o avx512[a-z]* | sed s/avx/+avx/ | tr '\n' ',' )" >> $GITHUB_ENV - name: Check build if: ${{ matrix.simd == '' }} - run: RUSTFLAGS="-Dwarnings" cargo check --all-targets --no-default-features ${{ matrix.features }} + run: RUSTFLAGS="-Dwarnings" cargo test --all-targets --no-default-features ${{ matrix.features }} - name: Check AVX if: ${{ matrix.simd == 'avx512' && contains(env.CPU_FEATURE, 'avx512') }} run: | echo "Found AVX features: $CPU_FEATURE" - RUSTFLAGS="-Dwarnings -Ctarget-feature=$CPU_FEATURE" cargo check --all-targets --no-default-features ${{ matrix.features }} + RUSTFLAGS="-Dwarnings -Ctarget-feature=$CPU_FEATURE" cargo test --all-targets --no-default-features ${{ matrix.features }} diff --git a/library/portable-simd/.gitignore b/library/portable-simd/.gitignore index 96ef6c0b944e2..ea8c4bf7f35f6 100644 --- a/library/portable-simd/.gitignore +++ b/library/portable-simd/.gitignore @@ -1,2 +1 @@ /target -Cargo.lock diff --git a/library/portable-simd/Cargo.lock b/library/portable-simd/Cargo.lock new file mode 100644 index 0000000000000..46312c09657d5 --- /dev/null +++ b/library/portable-simd/Cargo.lock @@ -0,0 +1,304 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "core_simd" +version = "0.1.0" +dependencies = [ + "proptest", + "std_float", + "test_helpers", + "wasm-bindgen", + "wasm-bindgen-test", +] + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12e6c80c1139113c28ee4670dc50cc42915228b51f56a9e407f0ec60f966646f" +dependencies = [ + "bitflags", + "byteorder", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_xorshift" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" +dependencies = [ + "rand_core", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "std_float" +version = "0.1.0" +dependencies = [ + "core_simd", +] + +[[package]] +name = "syn" +version = "2.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "test_helpers" +version = "0.1.0" +dependencies = [ + "proptest", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] diff --git a/library/portable-simd/crates/core_simd/Cargo.toml b/library/portable-simd/crates/core_simd/Cargo.toml index d1a3a515a7e81..b4a8fd70f4c0e 100644 --- a/library/portable-simd/crates/core_simd/Cargo.toml +++ b/library/portable-simd/crates/core_simd/Cargo.toml @@ -12,7 +12,6 @@ license = "MIT OR Apache-2.0" default = ["as_crate"] as_crate = [] std = [] -generic_const_exprs = [] all_lane_counts = [] [target.'cfg(target_arch = "wasm32")'.dev-dependencies] diff --git a/library/portable-simd/crates/core_simd/examples/dot_product.rs b/library/portable-simd/crates/core_simd/examples/dot_product.rs index a7973ec740411..f047010a65c16 100644 --- a/library/portable-simd/crates/core_simd/examples/dot_product.rs +++ b/library/portable-simd/crates/core_simd/examples/dot_product.rs @@ -6,7 +6,7 @@ #![feature(slice_as_chunks)] // Add these imports to use the stdsimd library #![feature(portable_simd)] -use core_simd::simd::*; +use core_simd::simd::prelude::*; // This is your barebones dot product implementation: // Take 2 vectors, multiply them element wise and *then* diff --git a/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs b/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs index 39f530f68f57a..bad86414401d7 100644 --- a/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs +++ b/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs @@ -2,8 +2,7 @@ // Code ported from the `packed_simd` crate // Run this code with `cargo test --example matrix_inversion` #![feature(array_chunks, portable_simd)] -use core_simd::simd::*; -use Which::*; +use core_simd::simd::prelude::*; // Gotta define our own 4x4 matrix since Rust doesn't ship multidim arrays yet :^) #[derive(Copy, Clone, Debug, PartialEq, PartialOrd)] @@ -164,10 +163,10 @@ pub fn simd_inv4x4(m: Matrix4x4) -> Option { let m_2 = f32x4::from_array(m[2]); let m_3 = f32x4::from_array(m[3]); - const SHUFFLE01: [Which; 4] = [First(0), First(1), Second(0), Second(1)]; - const SHUFFLE02: [Which; 4] = [First(0), First(2), Second(0), Second(2)]; - const SHUFFLE13: [Which; 4] = [First(1), First(3), Second(1), Second(3)]; - const SHUFFLE23: [Which; 4] = [First(2), First(3), Second(2), Second(3)]; + const SHUFFLE01: [usize; 4] = [0, 1, 4, 5]; + const SHUFFLE02: [usize; 4] = [0, 2, 4, 6]; + const SHUFFLE13: [usize; 4] = [1, 3, 5, 7]; + const SHUFFLE23: [usize; 4] = [2, 3, 6, 7]; let tmp = simd_swizzle!(m_0, m_1, SHUFFLE01); let row1 = simd_swizzle!(m_2, m_3, SHUFFLE01); @@ -180,58 +179,58 @@ pub fn simd_inv4x4(m: Matrix4x4) -> Option { let row2 = simd_swizzle!(tmp, row3, SHUFFLE02); let row3 = simd_swizzle!(row3, tmp, SHUFFLE13); - let tmp = (row2 * row3).reverse().rotate_lanes_right::<2>(); + let tmp = (row2 * row3).reverse().rotate_elements_right::<2>(); let minor0 = row1 * tmp; let minor1 = row0 * tmp; - let tmp = tmp.rotate_lanes_right::<2>(); + let tmp = tmp.rotate_elements_right::<2>(); let minor0 = (row1 * tmp) - minor0; let minor1 = (row0 * tmp) - minor1; - let minor1 = minor1.rotate_lanes_right::<2>(); + let minor1 = minor1.rotate_elements_right::<2>(); - let tmp = (row1 * row2).reverse().rotate_lanes_right::<2>(); + let tmp = (row1 * row2).reverse().rotate_elements_right::<2>(); let minor0 = (row3 * tmp) + minor0; let minor3 = row0 * tmp; - let tmp = tmp.rotate_lanes_right::<2>(); + let tmp = tmp.rotate_elements_right::<2>(); let minor0 = minor0 - row3 * tmp; let minor3 = row0 * tmp - minor3; - let minor3 = minor3.rotate_lanes_right::<2>(); + let minor3 = minor3.rotate_elements_right::<2>(); - let tmp = (row3 * row1.rotate_lanes_right::<2>()) + let tmp = (row3 * row1.rotate_elements_right::<2>()) .reverse() - .rotate_lanes_right::<2>(); - let row2 = row2.rotate_lanes_right::<2>(); + .rotate_elements_right::<2>(); + let row2 = row2.rotate_elements_right::<2>(); let minor0 = row2 * tmp + minor0; let minor2 = row0 * tmp; - let tmp = tmp.rotate_lanes_right::<2>(); + let tmp = tmp.rotate_elements_right::<2>(); let minor0 = minor0 - row2 * tmp; let minor2 = row0 * tmp - minor2; - let minor2 = minor2.rotate_lanes_right::<2>(); + let minor2 = minor2.rotate_elements_right::<2>(); - let tmp = (row0 * row1).reverse().rotate_lanes_right::<2>(); + let tmp = (row0 * row1).reverse().rotate_elements_right::<2>(); let minor2 = minor2 + row3 * tmp; let minor3 = row2 * tmp - minor3; - let tmp = tmp.rotate_lanes_right::<2>(); + let tmp = tmp.rotate_elements_right::<2>(); let minor2 = row3 * tmp - minor2; let minor3 = minor3 - row2 * tmp; - let tmp = (row0 * row3).reverse().rotate_lanes_right::<2>(); + let tmp = (row0 * row3).reverse().rotate_elements_right::<2>(); let minor1 = minor1 - row2 * tmp; let minor2 = row1 * tmp + minor2; - let tmp = tmp.rotate_lanes_right::<2>(); + let tmp = tmp.rotate_elements_right::<2>(); let minor1 = row2 * tmp + minor1; let minor2 = minor2 - row1 * tmp; - let tmp = (row0 * row2).reverse().rotate_lanes_right::<2>(); + let tmp = (row0 * row2).reverse().rotate_elements_right::<2>(); let minor1 = row3 * tmp + minor1; let minor3 = minor3 - row1 * tmp; - let tmp = tmp.rotate_lanes_right::<2>(); + let tmp = tmp.rotate_elements_right::<2>(); let minor1 = minor1 - row3 * tmp; let minor3 = row1 * tmp + minor3; let det = row0 * minor0; - let det = det.rotate_lanes_right::<2>() + det; - let det = det.reverse().rotate_lanes_right::<2>() + det; + let det = det.rotate_elements_right::<2>() + det; + let det = det.reverse().rotate_elements_right::<2>() + det; if det.reduce_sum() == 0. { return None; diff --git a/library/portable-simd/crates/core_simd/examples/nbody.rs b/library/portable-simd/crates/core_simd/examples/nbody.rs index df38a00967feb..65820d1340bd7 100644 --- a/library/portable-simd/crates/core_simd/examples/nbody.rs +++ b/library/portable-simd/crates/core_simd/examples/nbody.rs @@ -1,11 +1,12 @@ #![feature(portable_simd)] +#![allow(clippy::excessive_precision)] extern crate std_float; /// Benchmarks game nbody code /// Taken from the `packed_simd` crate /// Run this benchmark with `cargo test --example nbody` mod nbody { - use core_simd::simd::*; + use core_simd::simd::prelude::*; #[allow(unused)] // False positive? use std_float::StdFloat; diff --git a/library/portable-simd/crates/core_simd/examples/spectral_norm.rs b/library/portable-simd/crates/core_simd/examples/spectral_norm.rs index d576bd0ccee03..bc7934c252235 100644 --- a/library/portable-simd/crates/core_simd/examples/spectral_norm.rs +++ b/library/portable-simd/crates/core_simd/examples/spectral_norm.rs @@ -1,6 +1,6 @@ #![feature(portable_simd)] -use core_simd::simd::*; +use core_simd::simd::prelude::*; fn a(i: usize, j: usize) -> f64 { ((i + j) * (i + j + 1) / 2 + i + 1) as f64 diff --git a/library/portable-simd/crates/core_simd/src/core_simd_docs.md b/library/portable-simd/crates/core_simd/src/core_simd_docs.md index 15e8ed0253e14..bf412e035b513 100644 --- a/library/portable-simd/crates/core_simd/src/core_simd_docs.md +++ b/library/portable-simd/crates/core_simd/src/core_simd_docs.md @@ -2,3 +2,38 @@ Portable SIMD module. This module offers a portable abstraction for SIMD operations that is not bound to any particular hardware architecture. + +# What is "portable"? + +This module provides a SIMD implementation that is fast and predictable on any target. + +### Portable SIMD works on every target + +Unlike target-specific SIMD in `std::arch`, portable SIMD compiles for every target. +In this regard, it is just like "regular" Rust. + +### Portable SIMD is consistent between targets + +A program using portable SIMD can expect identical behavior on any target. +In most regards, [`Simd`] can be thought of as a parallelized `[T; N]` and operates like a sequence of `T`. + +This has one notable exception: a handful of older architectures (e.g. `armv7` and `powerpc`) flush [subnormal](`f32::is_subnormal`) `f32` values to zero. +On these architectures, subnormal `f32` input values are replaced with zeros, and any operation producing subnormal `f32` values produces zeros instead. +This doesn't affect most architectures or programs. + +### Operations use the best instructions available + +Operations provided by this module compile to the best available SIMD instructions. + +Portable SIMD is not a low-level vendor library, and operations in portable SIMD _do not_ necessarily map to a single instruction. +Instead, they map to a reasonable implementation of the operation for the target. + +Consistency between targets is not compromised to use faster or fewer instructions. +In some cases, `std::arch` will provide a faster function that has slightly different behavior than the `std::simd` equivalent. +For example, `_mm_min_ps`[^1] can be slightly faster than [`SimdFloat::simd_min`](`num::SimdFloat::simd_min`), but does not conform to the IEEE standard also used by [`f32::min`]. +When necessary, [`Simd`] can be converted to the types provided by `std::arch` to make use of target-specific functions. + +Many targets simply don't have SIMD, or don't support SIMD for a particular element type. +In those cases, regular scalar operations are generated instead. + +[^1]: `_mm_min_ps(x, y)` is equivalent to `x.simd_lt(y).select(x, y)` diff --git a/library/portable-simd/crates/core_simd/src/fmt.rs b/library/portable-simd/crates/core_simd/src/fmt.rs index b7317969cbb49..3a540f5a04908 100644 --- a/library/portable-simd/crates/core_simd/src/fmt.rs +++ b/library/portable-simd/crates/core_simd/src/fmt.rs @@ -1,9 +1,9 @@ use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; use core::fmt; -impl fmt::Debug for Simd +impl fmt::Debug for Simd where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, T: SimdElement + fmt::Debug, { /// A `Simd` has a debug format like the one for `[T]`: diff --git a/library/portable-simd/crates/core_simd/src/intrinsics.rs b/library/portable-simd/crates/core_simd/src/intrinsics.rs index dd6698e2ba56c..b27893bc7294d 100644 --- a/library/portable-simd/crates/core_simd/src/intrinsics.rs +++ b/library/portable-simd/crates/core_simd/src/intrinsics.rs @@ -160,4 +160,10 @@ extern "platform-intrinsic" { /// convert an exposed address back to a pointer pub(crate) fn simd_from_exposed_addr(addr: T) -> U; + + // Integer operations + pub(crate) fn simd_bswap(x: T) -> T; + pub(crate) fn simd_bitreverse(x: T) -> T; + pub(crate) fn simd_ctlz(x: T) -> T; + pub(crate) fn simd_cttz(x: T) -> T; } diff --git a/library/portable-simd/crates/core_simd/src/iter.rs b/library/portable-simd/crates/core_simd/src/iter.rs index 328c995b81ddd..b3732fd74d5f6 100644 --- a/library/portable-simd/crates/core_simd/src/iter.rs +++ b/library/portable-simd/crates/core_simd/src/iter.rs @@ -6,9 +6,9 @@ use core::{ macro_rules! impl_traits { { $type:ty } => { - impl Sum for Simd<$type, LANES> + impl Sum for Simd<$type, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn sum>(iter: I) -> Self { @@ -16,9 +16,9 @@ macro_rules! impl_traits { } } - impl Product for Simd<$type, LANES> + impl Product for Simd<$type, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn product>(iter: I) -> Self { @@ -26,9 +26,9 @@ macro_rules! impl_traits { } } - impl<'a, const LANES: usize> Sum<&'a Self> for Simd<$type, LANES> + impl<'a, const N: usize> Sum<&'a Self> for Simd<$type, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn sum>(iter: I) -> Self { @@ -36,9 +36,9 @@ macro_rules! impl_traits { } } - impl<'a, const LANES: usize> Product<&'a Self> for Simd<$type, LANES> + impl<'a, const N: usize> Product<&'a Self> for Simd<$type, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn product>(iter: I) -> Self { diff --git a/library/portable-simd/crates/core_simd/src/lane_count.rs b/library/portable-simd/crates/core_simd/src/lane_count.rs index 2b91eb9e80047..4cd7265ed671e 100644 --- a/library/portable-simd/crates/core_simd/src/lane_count.rs +++ b/library/portable-simd/crates/core_simd/src/lane_count.rs @@ -4,11 +4,11 @@ mod sealed { use sealed::Sealed; /// Specifies the number of lanes in a SIMD vector as a type. -pub struct LaneCount; +pub struct LaneCount; -impl LaneCount { +impl LaneCount { /// The number of bytes in a bitmask with this many lanes. - pub const BITMASK_LEN: usize = (LANES + 7) / 8; + pub const BITMASK_LEN: usize = (N + 7) / 8; } /// Statically guarantees that a lane count is marked as supported. @@ -21,7 +21,7 @@ pub trait SupportedLaneCount: Sealed { type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>; } -impl Sealed for LaneCount {} +impl Sealed for LaneCount {} macro_rules! supported_lane_count { ($($lanes:literal),+) => { diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs index fde406bda7060..64ba9705ef523 100644 --- a/library/portable-simd/crates/core_simd/src/lib.rs +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -5,6 +5,7 @@ const_mut_refs, convert_float_to_int, decl_macro, + inline_const, intra_doc_pointers, platform_intrinsics, repr_simd, @@ -14,10 +15,9 @@ strict_provenance, ptr_metadata )] -#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))] -#![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))] #![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really #![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)] +#![allow(internal_features)] #![unstable(feature = "portable_simd", issue = "86656")] //! Portable SIMD module. diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs index fea687bdc1aef..0623d2bf3d121 100644 --- a/library/portable-simd/crates/core_simd/src/masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks.rs @@ -1,4 +1,4 @@ -//! Types and traits associated with masking lanes of vectors. +//! Types and traits associated with masking elements of vectors. //! Types representing #![allow(non_camel_case_types)] @@ -12,13 +12,9 @@ )] mod mask_impl; -mod to_bitmask; -pub use to_bitmask::ToBitMask; - -#[cfg(feature = "generic_const_exprs")] -pub use to_bitmask::{bitmask_len, ToBitMaskArray}; - -use crate::simd::{intrinsics, LaneCount, Simd, SimdElement, SimdPartialEq, SupportedLaneCount}; +use crate::simd::{ + cmp::SimdPartialEq, intrinsics, LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount, +}; use core::cmp::Ordering; use core::{fmt, mem}; @@ -32,13 +28,17 @@ mod sealed { /// prevent us from ever removing that bound, or from implementing `MaskElement` on /// non-`PartialEq` types in the future. pub trait Sealed { - fn valid(values: Simd) -> bool + fn valid(values: Simd) -> bool where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, Self: SimdElement; fn eq(self, other: Self) -> bool; + fn as_usize(self) -> usize; + + type Unsigned: SimdElement; + const TRUE: Self; const FALSE: Self; @@ -50,15 +50,15 @@ use sealed::Sealed; /// /// # Safety /// Type must be a signed integer. -pub unsafe trait MaskElement: SimdElement + Sealed {} +pub unsafe trait MaskElement: SimdElement + SimdCast + Sealed {} macro_rules! impl_element { - { $ty:ty } => { + { $ty:ty, $unsigned:ty } => { impl Sealed for $ty { #[inline] - fn valid(value: Simd) -> bool + fn valid(value: Simd) -> bool where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { (value.simd_eq(Simd::splat(0 as _)) | value.simd_eq(Simd::splat(-1 as _))).all() } @@ -66,6 +66,13 @@ macro_rules! impl_element { #[inline] fn eq(self, other: Self) -> bool { self == other } + #[inline] + fn as_usize(self) -> usize { + self as usize + } + + type Unsigned = $unsigned; + const TRUE: Self = -1; const FALSE: Self = 0; } @@ -75,36 +82,36 @@ macro_rules! impl_element { } } -impl_element! { i8 } -impl_element! { i16 } -impl_element! { i32 } -impl_element! { i64 } -impl_element! { isize } +impl_element! { i8, u8 } +impl_element! { i16, u16 } +impl_element! { i32, u32 } +impl_element! { i64, u64 } +impl_element! { isize, usize } -/// A SIMD vector mask for `LANES` elements of width specified by `Element`. +/// A SIMD vector mask for `N` elements of width specified by `Element`. /// -/// Masks represent boolean inclusion/exclusion on a per-lane basis. +/// Masks represent boolean inclusion/exclusion on a per-element basis. /// /// The layout of this type is unspecified, and may change between platforms /// and/or Rust versions, and code should not assume that it is equivalent to -/// `[T; LANES]`. -#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435 -pub struct Mask(mask_impl::Mask) +/// `[T; N]`. +#[repr(transparent)] +pub struct Mask(mask_impl::Mask) where T: MaskElement, - LaneCount: SupportedLaneCount; + LaneCount: SupportedLaneCount; -impl Copy for Mask +impl Copy for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { } -impl Clone for Mask +impl Clone for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn clone(&self) -> Self { @@ -112,12 +119,12 @@ where } } -impl Mask +impl Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - /// Construct a mask by setting all lanes to the given value. + /// Construct a mask by setting all elements to the given value. #[inline] pub fn splat(value: bool) -> Self { Self(mask_impl::Mask::splat(value)) @@ -125,7 +132,7 @@ where /// Converts an array of bools to a SIMD mask. #[inline] - pub fn from_array(array: [bool; LANES]) -> Self { + pub fn from_array(array: [bool; N]) -> Self { // SAFETY: Rust's bool has a layout of 1 byte (u8) with a value of // true: 0b_0000_0001 // false: 0b_0000_0000 @@ -133,16 +140,15 @@ where // This would be hypothetically valid as an "in-place" transmute, // but these are "dependently-sized" types, so copy elision it is! unsafe { - let bytes: [u8; LANES] = mem::transmute_copy(&array); - let bools: Simd = - intrinsics::simd_ne(Simd::from_array(bytes), Simd::splat(0u8)); + let bytes: [u8; N] = mem::transmute_copy(&array); + let bools: Simd = intrinsics::simd_ne(Simd::from_array(bytes), Simd::splat(0u8)); Mask::from_int_unchecked(intrinsics::simd_cast(bools)) } } /// Converts a SIMD mask to an array of bools. #[inline] - pub fn to_array(self) -> [bool; LANES] { + pub fn to_array(self) -> [bool; N] { // This follows mostly the same logic as from_array. // SAFETY: Rust's bool has a layout of 1 byte (u8) with a value of // true: 0b_0000_0001 @@ -154,7 +160,7 @@ where // This would be hypothetically valid as an "in-place" transmute, // but these are "dependently-sized" types, so copy elision it is! unsafe { - let mut bytes: Simd = intrinsics::simd_cast(self.to_int()); + let mut bytes: Simd = intrinsics::simd_cast(self.to_int()); bytes &= Simd::splat(1i8); mem::transmute_copy(&bytes) } @@ -164,10 +170,10 @@ where /// represents `true`. /// /// # Safety - /// All lanes must be either 0 or -1. + /// All elements must be either 0 or -1. #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd) -> Self { + pub unsafe fn from_int_unchecked(value: Simd) -> Self { // Safety: the caller must confirm this invariant unsafe { Self(mask_impl::Mask::from_int_unchecked(value)) } } @@ -176,11 +182,11 @@ where /// represents `true`. /// /// # Panics - /// Panics if any lane is not 0 or -1. + /// Panics if any element is not 0 or -1. #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] #[track_caller] - pub fn from_int(value: Simd) -> Self { + pub fn from_int(value: Simd) -> Self { assert!(T::valid(value), "all values must be either 0 or -1",); // Safety: the validity has been checked unsafe { Self::from_int_unchecked(value) } @@ -190,121 +196,244 @@ where /// represents `true`. #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd { + pub fn to_int(self) -> Simd { self.0.to_int() } - /// Converts the mask to a mask of any other lane size. + /// Converts the mask to a mask of any other element size. #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn cast(self) -> Mask { + pub fn cast(self) -> Mask { Mask(self.0.convert()) } - /// Tests the value of the specified lane. + /// Tests the value of the specified element. /// /// # Safety - /// `lane` must be less than `LANES`. + /// `index` must be less than `self.len()`. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub unsafe fn test_unchecked(&self, lane: usize) -> bool { + pub unsafe fn test_unchecked(&self, index: usize) -> bool { // Safety: the caller must confirm this invariant - unsafe { self.0.test_unchecked(lane) } + unsafe { self.0.test_unchecked(index) } } - /// Tests the value of the specified lane. + /// Tests the value of the specified element. /// /// # Panics - /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + /// Panics if `index` is greater than or equal to the number of elements in the vector. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] #[track_caller] - pub fn test(&self, lane: usize) -> bool { - assert!(lane < LANES, "lane index out of range"); - // Safety: the lane index has been checked - unsafe { self.test_unchecked(lane) } + pub fn test(&self, index: usize) -> bool { + assert!(index < N, "element index out of range"); + // Safety: the element index has been checked + unsafe { self.test_unchecked(index) } } - /// Sets the value of the specified lane. + /// Sets the value of the specified element. /// /// # Safety - /// `lane` must be less than `LANES`. + /// `index` must be less than `self.len()`. #[inline] - pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { + pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) { // Safety: the caller must confirm this invariant unsafe { - self.0.set_unchecked(lane, value); + self.0.set_unchecked(index, value); } } - /// Sets the value of the specified lane. + /// Sets the value of the specified element. /// /// # Panics - /// Panics if `lane` is greater than or equal to the number of lanes in the vector. + /// Panics if `index` is greater than or equal to the number of elements in the vector. #[inline] #[track_caller] - pub fn set(&mut self, lane: usize, value: bool) { - assert!(lane < LANES, "lane index out of range"); - // Safety: the lane index has been checked + pub fn set(&mut self, index: usize, value: bool) { + assert!(index < N, "element index out of range"); + // Safety: the element index has been checked unsafe { - self.set_unchecked(lane, value); + self.set_unchecked(index, value); } } - /// Returns true if any lane is set, or false otherwise. + /// Returns true if any element is set, or false otherwise. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] pub fn any(self) -> bool { self.0.any() } - /// Returns true if all lanes are set, or false otherwise. + /// Returns true if all elements are set, or false otherwise. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] pub fn all(self) -> bool { self.0.all() } + + /// Create a bitmask from a mask. + /// + /// Each bit is set if the corresponding element in the mask is `true`. + /// If the mask contains more than 64 elements, the bitmask is truncated to the first 64. + #[inline] + #[must_use = "method returns a new integer and does not mutate the original value"] + pub fn to_bitmask(self) -> u64 { + self.0.to_bitmask_integer() + } + + /// Create a mask from a bitmask. + /// + /// For each bit, if it is set, the corresponding element in the mask is set to `true`. + /// If the mask contains more than 64 elements, the remainder are set to `false`. + #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] + pub fn from_bitmask(bitmask: u64) -> Self { + Self(mask_impl::Mask::from_bitmask_integer(bitmask)) + } + + /// Create a bitmask vector from a mask. + /// + /// Each bit is set if the corresponding element in the mask is `true`. + /// The remaining bits are unset. + /// + /// The bits are packed into the first N bits of the vector: + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::mask32x8; + /// let mask = mask32x8::from_array([true, false, true, false, false, false, true, false]); + /// assert_eq!(mask.to_bitmask_vector()[0], 0b01000101); + /// ``` + #[inline] + #[must_use = "method returns a new integer and does not mutate the original value"] + pub fn to_bitmask_vector(self) -> Simd { + self.0.to_bitmask_vector() + } + + /// Create a mask from a bitmask vector. + /// + /// For each bit, if it is set, the corresponding element in the mask is set to `true`. + /// + /// The bits are packed into the first N bits of the vector: + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::{mask32x8, u8x8}; + /// let bitmask = u8x8::from_array([0b01000101, 0, 0, 0, 0, 0, 0, 0]); + /// assert_eq!( + /// mask32x8::from_bitmask_vector(bitmask), + /// mask32x8::from_array([true, false, true, false, false, false, true, false]), + /// ); + /// ``` + #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] + pub fn from_bitmask_vector(bitmask: Simd) -> Self { + Self(mask_impl::Mask::from_bitmask_vector(bitmask)) + } + + /// Find the index of the first set element. + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::mask32x8; + /// assert_eq!(mask32x8::splat(false).first_set(), None); + /// assert_eq!(mask32x8::splat(true).first_set(), Some(0)); + /// + /// let mask = mask32x8::from_array([false, true, false, false, true, false, false, true]); + /// assert_eq!(mask.first_set(), Some(1)); + /// ``` + #[inline] + #[must_use = "method returns the index and does not mutate the original value"] + pub fn first_set(self) -> Option { + // If bitmasks are efficient, using them is better + if cfg!(target_feature = "sse") && N <= 64 { + let tz = self.to_bitmask().trailing_zeros(); + return if tz == 64 { None } else { Some(tz as usize) }; + } + + // To find the first set index: + // * create a vector 0..N + // * replace unset mask elements in that vector with -1 + // * perform _unsigned_ reduce-min + // * check if the result is -1 or an index + + let index = Simd::from_array( + const { + let mut index = [0; N]; + let mut i = 0; + while i < N { + index[i] = i; + i += 1; + } + index + }, + ); + + // Safety: the input and output are integer vectors + let index: Simd = unsafe { intrinsics::simd_cast(index) }; + + let masked_index = self.select(index, Self::splat(true).to_int()); + + // Safety: the input and output are integer vectors + let masked_index: Simd = unsafe { intrinsics::simd_cast(masked_index) }; + + // Safety: the input is an integer vector + let min_index: T::Unsigned = unsafe { intrinsics::simd_reduce_min(masked_index) }; + + // Safety: the return value is the unsigned version of T + let min_index: T = unsafe { core::mem::transmute_copy(&min_index) }; + + if min_index.eq(T::TRUE) { + None + } else { + Some(min_index.as_usize()) + } + } } // vector/array conversion -impl From<[bool; LANES]> for Mask +impl From<[bool; N]> for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] - fn from(array: [bool; LANES]) -> Self { + fn from(array: [bool; N]) -> Self { Self::from_array(array) } } -impl From> for [bool; LANES] +impl From> for [bool; N] where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] - fn from(vector: Mask) -> Self { + fn from(vector: Mask) -> Self { vector.to_array() } } -impl Default for Mask +impl Default for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] - #[must_use = "method returns a defaulted mask with all lanes set to false (0)"] + #[must_use = "method returns a defaulted mask with all elements set to false (0)"] fn default() -> Self { Self::splat(false) } } -impl PartialEq for Mask +impl PartialEq for Mask where T: MaskElement + PartialEq, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] @@ -313,10 +442,10 @@ where } } -impl PartialOrd for Mask +impl PartialOrd for Mask where T: MaskElement + PartialOrd, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] #[must_use = "method returns a new Ordering and does not mutate the original value"] @@ -325,23 +454,23 @@ where } } -impl fmt::Debug for Mask +impl fmt::Debug for Mask where T: MaskElement + fmt::Debug, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() - .entries((0..LANES).map(|lane| self.test(lane))) + .entries((0..N).map(|i| self.test(i))) .finish() } } -impl core::ops::BitAnd for Mask +impl core::ops::BitAnd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -351,10 +480,10 @@ where } } -impl core::ops::BitAnd for Mask +impl core::ops::BitAnd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -364,23 +493,23 @@ where } } -impl core::ops::BitAnd> for bool +impl core::ops::BitAnd> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Output = Mask; + type Output = Mask; #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - fn bitand(self, rhs: Mask) -> Mask { + fn bitand(self, rhs: Mask) -> Mask { Mask::splat(self) & rhs } } -impl core::ops::BitOr for Mask +impl core::ops::BitOr for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -390,10 +519,10 @@ where } } -impl core::ops::BitOr for Mask +impl core::ops::BitOr for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -403,23 +532,23 @@ where } } -impl core::ops::BitOr> for bool +impl core::ops::BitOr> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Output = Mask; + type Output = Mask; #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - fn bitor(self, rhs: Mask) -> Mask { + fn bitor(self, rhs: Mask) -> Mask { Mask::splat(self) | rhs } } -impl core::ops::BitXor for Mask +impl core::ops::BitXor for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -429,10 +558,10 @@ where } } -impl core::ops::BitXor for Mask +impl core::ops::BitXor for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -442,25 +571,25 @@ where } } -impl core::ops::BitXor> for bool +impl core::ops::BitXor> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Output = Mask; + type Output = Mask; #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - fn bitxor(self, rhs: Mask) -> Self::Output { + fn bitxor(self, rhs: Mask) -> Self::Output { Mask::splat(self) ^ rhs } } -impl core::ops::Not for Mask +impl core::ops::Not for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Output = Mask; + type Output = Mask; #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] fn not(self) -> Self::Output { @@ -468,10 +597,10 @@ where } } -impl core::ops::BitAndAssign for Mask +impl core::ops::BitAndAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn bitand_assign(&mut self, rhs: Self) { @@ -479,10 +608,10 @@ where } } -impl core::ops::BitAndAssign for Mask +impl core::ops::BitAndAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn bitand_assign(&mut self, rhs: bool) { @@ -490,10 +619,10 @@ where } } -impl core::ops::BitOrAssign for Mask +impl core::ops::BitOrAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn bitor_assign(&mut self, rhs: Self) { @@ -501,10 +630,10 @@ where } } -impl core::ops::BitOrAssign for Mask +impl core::ops::BitOrAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn bitor_assign(&mut self, rhs: bool) { @@ -512,10 +641,10 @@ where } } -impl core::ops::BitXorAssign for Mask +impl core::ops::BitXorAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn bitxor_assign(&mut self, rhs: Self) { @@ -523,10 +652,10 @@ where } } -impl core::ops::BitXorAssign for Mask +impl core::ops::BitXorAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn bitxor_assign(&mut self, rhs: bool) { @@ -537,12 +666,12 @@ where macro_rules! impl_from { { $from:ty => $($to:ty),* } => { $( - impl From> for Mask<$to, LANES> + impl From> for Mask<$to, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] - fn from(value: Mask<$from, LANES>) -> Self { + fn from(value: Mask<$from, N>) -> Self { value.cast() } } diff --git a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs index 20465ba9b07ec..6ddff07fea254 100644 --- a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs +++ b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs @@ -1,30 +1,30 @@ #![allow(unused_imports)] use super::MaskElement; use crate::simd::intrinsics; -use crate::simd::{LaneCount, Simd, SupportedLaneCount, ToBitMask}; +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; use core::marker::PhantomData; /// A mask where each lane is represented by a single bit. #[repr(transparent)] -pub struct Mask( - as SupportedLaneCount>::BitMask, +pub struct Mask( + as SupportedLaneCount>::BitMask, PhantomData, ) where T: MaskElement, - LaneCount: SupportedLaneCount; + LaneCount: SupportedLaneCount; -impl Copy for Mask +impl Copy for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { } -impl Clone for Mask +impl Clone for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn clone(&self) -> Self { @@ -32,10 +32,10 @@ where } } -impl PartialEq for Mask +impl PartialEq for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -43,10 +43,10 @@ where } } -impl PartialOrd for Mask +impl PartialOrd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn partial_cmp(&self, other: &Self) -> Option { @@ -54,17 +54,17 @@ where } } -impl Eq for Mask +impl Eq for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { } -impl Ord for Mask +impl Ord for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn cmp(&self, other: &Self) -> core::cmp::Ordering { @@ -72,22 +72,22 @@ where } } -impl Mask +impl Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] pub fn splat(value: bool) -> Self { - let mut mask = as SupportedLaneCount>::BitMask::default(); + let mut mask = as SupportedLaneCount>::BitMask::default(); if value { mask.as_mut().fill(u8::MAX) } else { mask.as_mut().fill(u8::MIN) } - if LANES % 8 > 0 { - *mask.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - LANES % 8); + if N % 8 > 0 { + *mask.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - N % 8); } Self(mask, PhantomData) } @@ -107,7 +107,7 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd { + pub fn to_int(self) -> Simd { unsafe { intrinsics::simd_select_bitmask(self.0, Simd::splat(T::TRUE), Simd::splat(T::FALSE)) } @@ -115,51 +115,47 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd) -> Self { + pub unsafe fn from_int_unchecked(value: Simd) -> Self { unsafe { Self(intrinsics::simd_bitmask(value), PhantomData) } } - #[cfg(feature = "generic_const_exprs")] #[inline] - #[must_use = "method returns a new array and does not mutate the original value"] - pub fn to_bitmask_array(self) -> [u8; N] { - assert!(core::mem::size_of::() == N); - - // Safety: converting an integer to an array of bytes of the same size is safe - unsafe { core::mem::transmute_copy(&self.0) } + #[must_use = "method returns a new vector and does not mutate the original value"] + pub fn to_bitmask_vector(self) -> Simd { + let mut bitmask = Simd::splat(0); + bitmask.as_mut_array()[..self.0.as_ref().len()].copy_from_slice(self.0.as_ref()); + bitmask } - #[cfg(feature = "generic_const_exprs")] #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn from_bitmask_array(bitmask: [u8; N]) -> Self { - assert!(core::mem::size_of::() == N); - - // Safety: converting an array of bytes to an integer of the same size is safe - Self(unsafe { core::mem::transmute_copy(&bitmask) }, PhantomData) + pub fn from_bitmask_vector(bitmask: Simd) -> Self { + let mut bytes = as SupportedLaneCount>::BitMask::default(); + let len = bytes.as_ref().len(); + bytes.as_mut().copy_from_slice(&bitmask.as_array()[..len]); + Self(bytes, PhantomData) } #[inline] - pub fn to_bitmask_integer(self) -> U - where - super::Mask: ToBitMask, - { - // Safety: these are the same types - unsafe { core::mem::transmute_copy(&self.0) } + pub fn to_bitmask_integer(self) -> u64 { + let mut bitmask = [0u8; 8]; + bitmask[..self.0.as_ref().len()].copy_from_slice(self.0.as_ref()); + u64::from_ne_bytes(bitmask) } #[inline] - pub fn from_bitmask_integer(bitmask: U) -> Self - where - super::Mask: ToBitMask, - { - // Safety: these are the same types - unsafe { Self(core::mem::transmute_copy(&bitmask), PhantomData) } + pub fn from_bitmask_integer(bitmask: u64) -> Self { + let mut bytes = as SupportedLaneCount>::BitMask::default(); + let len = bytes.as_mut().len(); + bytes + .as_mut() + .copy_from_slice(&bitmask.to_ne_bytes()[..len]); + Self(bytes, PhantomData) } #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn convert(self) -> Mask + pub fn convert(self) -> Mask where U: MaskElement, { @@ -180,11 +176,11 @@ where } } -impl core::ops::BitAnd for Mask +impl core::ops::BitAnd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, - as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, + LaneCount: SupportedLaneCount, + as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, { type Output = Self; #[inline] @@ -197,11 +193,11 @@ where } } -impl core::ops::BitOr for Mask +impl core::ops::BitOr for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, - as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, + LaneCount: SupportedLaneCount, + as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, { type Output = Self; #[inline] @@ -214,10 +210,10 @@ where } } -impl core::ops::BitXor for Mask +impl core::ops::BitXor for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -230,10 +226,10 @@ where } } -impl core::ops::Not for Mask +impl core::ops::Not for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -242,8 +238,8 @@ where for x in self.0.as_mut() { *x = !*x; } - if LANES % 8 > 0 { - *self.0.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - LANES % 8); + if N % 8 > 0 { + *self.0.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - N % 8); } self } diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs index 1d13c45b8e70b..63964f455e05c 100644 --- a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs @@ -1,29 +1,25 @@ //! Masks that take up full SIMD vector registers. -use super::MaskElement; use crate::simd::intrinsics; -use crate::simd::{LaneCount, Simd, SupportedLaneCount, ToBitMask}; - -#[cfg(feature = "generic_const_exprs")] -use crate::simd::ToBitMaskArray; +use crate::simd::{LaneCount, MaskElement, Simd, SupportedLaneCount}; #[repr(transparent)] -pub struct Mask(Simd) +pub struct Mask(Simd) where T: MaskElement, - LaneCount: SupportedLaneCount; + LaneCount: SupportedLaneCount; -impl Copy for Mask +impl Copy for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { } -impl Clone for Mask +impl Clone for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] @@ -32,10 +28,10 @@ where } } -impl PartialEq for Mask +impl PartialEq for Mask where T: MaskElement + PartialEq, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -43,10 +39,10 @@ where } } -impl PartialOrd for Mask +impl PartialOrd for Mask where T: MaskElement + PartialOrd, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn partial_cmp(&self, other: &Self) -> Option { @@ -54,17 +50,17 @@ where } } -impl Eq for Mask +impl Eq for Mask where T: MaskElement + Eq, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { } -impl Ord for Mask +impl Ord for Mask where T: MaskElement + Ord, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn cmp(&self, other: &Self) -> core::cmp::Ordering { @@ -101,10 +97,10 @@ macro_rules! impl_reverse_bits { impl_reverse_bits! { u8, u16, u32, u64 } -impl Mask +impl Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] @@ -125,19 +121,19 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd { + pub fn to_int(self) -> Simd { self.0 } #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd) -> Self { + pub unsafe fn from_int_unchecked(value: Simd) -> Self { Self(value) } #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn convert(self) -> Mask + pub fn convert(self) -> Mask where U: MaskElement, { @@ -145,62 +141,50 @@ where unsafe { Mask(intrinsics::simd_cast(self.0)) } } - #[cfg(feature = "generic_const_exprs")] #[inline] - #[must_use = "method returns a new array and does not mutate the original value"] - pub fn to_bitmask_array(self) -> [u8; N] - where - super::Mask: ToBitMaskArray, - [(); as ToBitMaskArray>::BYTES]: Sized, - { - assert_eq!( as ToBitMaskArray>::BYTES, N); + #[must_use = "method returns a new vector and does not mutate the original value"] + pub fn to_bitmask_vector(self) -> Simd { + let mut bitmask = Simd::splat(0); - // Safety: N is the correct bitmask size + // Safety: Bytes is the right size array unsafe { // Compute the bitmask - let bitmask: [u8; as ToBitMaskArray>::BYTES] = + let mut bytes: as SupportedLaneCount>::BitMask = intrinsics::simd_bitmask(self.0); - // Transmute to the return type, previously asserted to be the same size - let mut bitmask: [u8; N] = core::mem::transmute_copy(&bitmask); - // LLVM assumes bit order should match endianness if cfg!(target_endian = "big") { - for x in bitmask.as_mut() { - *x = x.reverse_bits(); + for x in bytes.as_mut() { + *x = x.reverse_bits() } - }; + } - bitmask + bitmask.as_mut_array()[..bytes.as_ref().len()].copy_from_slice(bytes.as_ref()); } + + bitmask } - #[cfg(feature = "generic_const_exprs")] #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn from_bitmask_array(mut bitmask: [u8; N]) -> Self - where - super::Mask: ToBitMaskArray, - [(); as ToBitMaskArray>::BYTES]: Sized, - { - assert_eq!( as ToBitMaskArray>::BYTES, N); + pub fn from_bitmask_vector(bitmask: Simd) -> Self { + let mut bytes = as SupportedLaneCount>::BitMask::default(); - // Safety: N is the correct bitmask size + // Safety: Bytes is the right size array unsafe { + let len = bytes.as_ref().len(); + bytes.as_mut().copy_from_slice(&bitmask.as_array()[..len]); + // LLVM assumes bit order should match endianness if cfg!(target_endian = "big") { - for x in bitmask.as_mut() { + for x in bytes.as_mut() { *x = x.reverse_bits(); } } - // Transmute to the bitmask type, previously asserted to be the same size - let bitmask: [u8; as ToBitMaskArray>::BYTES] = - core::mem::transmute_copy(&bitmask); - // Compute the regular mask Self::from_int_unchecked(intrinsics::simd_select_bitmask( - bitmask, + bytes, Self::splat(true).to_int(), Self::splat(false).to_int(), )) @@ -208,40 +192,81 @@ where } #[inline] - pub(crate) fn to_bitmask_integer(self) -> U + unsafe fn to_bitmask_impl(self) -> U where - super::Mask: ToBitMask, + LaneCount: SupportedLaneCount, { - // Safety: U is required to be the appropriate bitmask type - let bitmask: U = unsafe { intrinsics::simd_bitmask(self.0) }; + let resized = self.to_int().resize::(T::FALSE); + + // Safety: `resized` is an integer vector with length M, which must match T + let bitmask: U = unsafe { intrinsics::simd_bitmask(resized) }; // LLVM assumes bit order should match endianness if cfg!(target_endian = "big") { - bitmask.reverse_bits(LANES) + bitmask.reverse_bits(M) } else { bitmask } } #[inline] - pub(crate) fn from_bitmask_integer(bitmask: U) -> Self + unsafe fn from_bitmask_impl(bitmask: U) -> Self where - super::Mask: ToBitMask, + LaneCount: SupportedLaneCount, { // LLVM assumes bit order should match endianness let bitmask = if cfg!(target_endian = "big") { - bitmask.reverse_bits(LANES) + bitmask.reverse_bits(M) } else { bitmask }; - // Safety: U is required to be the appropriate bitmask type - unsafe { - Self::from_int_unchecked(intrinsics::simd_select_bitmask( + // SAFETY: `mask` is the correct bitmask type for a u64 bitmask + let mask: Simd = unsafe { + intrinsics::simd_select_bitmask( bitmask, - Self::splat(true).to_int(), - Self::splat(false).to_int(), - )) + Simd::::splat(T::TRUE), + Simd::::splat(T::FALSE), + ) + }; + + // SAFETY: `mask` only contains `T::TRUE` or `T::FALSE` + unsafe { Self::from_int_unchecked(mask.resize::(T::FALSE)) } + } + + #[inline] + pub(crate) fn to_bitmask_integer(self) -> u64 { + // TODO modify simd_bitmask to zero-extend output, making this unnecessary + if N <= 8 { + // Safety: bitmask matches length + unsafe { self.to_bitmask_impl::() as u64 } + } else if N <= 16 { + // Safety: bitmask matches length + unsafe { self.to_bitmask_impl::() as u64 } + } else if N <= 32 { + // Safety: bitmask matches length + unsafe { self.to_bitmask_impl::() as u64 } + } else { + // Safety: bitmask matches length + unsafe { self.to_bitmask_impl::() } + } + } + + #[inline] + pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { + // TODO modify simd_bitmask_select to truncate input, making this unnecessary + if N <= 8 { + // Safety: bitmask matches length + unsafe { Self::from_bitmask_impl::(bitmask as u8) } + } else if N <= 16 { + // Safety: bitmask matches length + unsafe { Self::from_bitmask_impl::(bitmask as u16) } + } else if N <= 32 { + // Safety: bitmask matches length + unsafe { Self::from_bitmask_impl::(bitmask as u32) } + } else { + // Safety: bitmask matches length + unsafe { Self::from_bitmask_impl::(bitmask) } } } @@ -260,21 +285,21 @@ where } } -impl From> for Simd +impl From> for Simd where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] - fn from(value: Mask) -> Self { + fn from(value: Mask) -> Self { value.0 } } -impl core::ops::BitAnd for Mask +impl core::ops::BitAnd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -285,10 +310,10 @@ where } } -impl core::ops::BitOr for Mask +impl core::ops::BitOr for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -299,10 +324,10 @@ where } } -impl core::ops::BitXor for Mask +impl core::ops::BitXor for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -313,10 +338,10 @@ where } } -impl core::ops::Not for Mask +impl core::ops::Not for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; #[inline] diff --git a/library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs deleted file mode 100644 index fc7d6b781f2f5..0000000000000 --- a/library/portable-simd/crates/core_simd/src/masks/to_bitmask.rs +++ /dev/null @@ -1,97 +0,0 @@ -use super::{mask_impl, Mask, MaskElement}; -use crate::simd::{LaneCount, SupportedLaneCount}; - -mod sealed { - pub trait Sealed {} -} -pub use sealed::Sealed; - -impl Sealed for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} - -/// Converts masks to and from integer bitmasks. -/// -/// Each bit of the bitmask corresponds to a mask lane, starting with the LSB. -pub trait ToBitMask: Sealed { - /// The integer bitmask type. - type BitMask; - - /// Converts a mask to a bitmask. - fn to_bitmask(self) -> Self::BitMask; - - /// Converts a bitmask to a mask. - fn from_bitmask(bitmask: Self::BitMask) -> Self; -} - -/// Converts masks to and from byte array bitmasks. -/// -/// Each bit of the bitmask corresponds to a mask lane, starting with the LSB of the first byte. -#[cfg(feature = "generic_const_exprs")] -pub trait ToBitMaskArray: Sealed { - /// The length of the bitmask array. - const BYTES: usize; - - /// Converts a mask to a bitmask. - fn to_bitmask_array(self) -> [u8; Self::BYTES]; - - /// Converts a bitmask to a mask. - fn from_bitmask_array(bitmask: [u8; Self::BYTES]) -> Self; -} - -macro_rules! impl_integer_intrinsic { - { $(impl ToBitMask for Mask<_, $lanes:literal>)* } => { - $( - impl ToBitMask for Mask { - type BitMask = $int; - - #[inline] - fn to_bitmask(self) -> $int { - self.0.to_bitmask_integer() - } - - #[inline] - fn from_bitmask(bitmask: $int) -> Self { - Self(mask_impl::Mask::from_bitmask_integer(bitmask)) - } - } - )* - } -} - -impl_integer_intrinsic! { - impl ToBitMask for Mask<_, 1> - impl ToBitMask for Mask<_, 2> - impl ToBitMask for Mask<_, 4> - impl ToBitMask for Mask<_, 8> - impl ToBitMask for Mask<_, 16> - impl ToBitMask for Mask<_, 32> - impl ToBitMask for Mask<_, 64> -} - -/// Returns the minimum number of bytes in a bitmask with `lanes` lanes. -#[cfg(feature = "generic_const_exprs")] -pub const fn bitmask_len(lanes: usize) -> usize { - (lanes + 7) / 8 -} - -#[cfg(feature = "generic_const_exprs")] -impl ToBitMaskArray for Mask -where - LaneCount: SupportedLaneCount, -{ - const BYTES: usize = bitmask_len(LANES); - - #[inline] - fn to_bitmask_array(self) -> [u8; Self::BYTES] { - self.0.to_bitmask_array() - } - - #[inline] - fn from_bitmask_array(bitmask: [u8; Self::BYTES]) -> Self { - Mask(mask_impl::Mask::from_bitmask_array(bitmask)) - } -} diff --git a/library/portable-simd/crates/core_simd/src/mod.rs b/library/portable-simd/crates/core_simd/src/mod.rs index 19426769858b0..fd016f1c6f7ab 100644 --- a/library/portable-simd/crates/core_simd/src/mod.rs +++ b/library/portable-simd/crates/core_simd/src/mod.rs @@ -3,37 +3,37 @@ mod swizzle; pub(crate) mod intrinsics; -#[cfg(feature = "generic_const_exprs")] -mod to_bytes; - mod alias; mod cast; -mod elements; -mod eq; mod fmt; mod iter; mod lane_count; mod masks; mod ops; -mod ord; mod select; mod swizzle_dyn; +mod to_bytes; mod vector; mod vendor; -#[doc = include_str!("core_simd_docs.md")] pub mod simd { + #![doc = include_str!("core_simd_docs.md")] + pub mod prelude; + pub mod num; + + pub mod ptr; + + pub mod cmp; + pub(crate) use crate::core_simd::intrinsics; pub use crate::core_simd::alias::*; pub use crate::core_simd::cast::*; - pub use crate::core_simd::elements::*; - pub use crate::core_simd::eq::*; pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount}; pub use crate::core_simd::masks::*; - pub use crate::core_simd::ord::*; pub use crate::core_simd::swizzle::*; + pub use crate::core_simd::to_bytes::ToBytes; pub use crate::core_simd::vector::*; } diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs index b007456cf2cc5..8a1b083f03982 100644 --- a/library/portable-simd/crates/core_simd/src/ops.rs +++ b/library/portable-simd/crates/core_simd/src/ops.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Simd, SimdElement, SimdPartialEq, SupportedLaneCount}; +use crate::simd::{cmp::SimdPartialEq, LaneCount, Simd, SimdElement, SupportedLaneCount}; use core::ops::{Add, Mul}; use core::ops::{BitAnd, BitOr, BitXor}; use core::ops::{Div, Rem, Sub}; @@ -6,12 +6,13 @@ use core::ops::{Shl, Shr}; mod assign; mod deref; +mod shift_scalar; mod unary; -impl core::ops::Index for Simd +impl core::ops::Index for Simd where T: SimdElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, I: core::slice::SliceIndex<[T]>, { type Output = I::Output; @@ -21,10 +22,10 @@ where } } -impl core::ops::IndexMut for Simd +impl core::ops::IndexMut for Simd where T: SimdElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, I: core::slice::SliceIndex<[T]>, { #[inline] diff --git a/library/portable-simd/crates/core_simd/src/ops/assign.rs b/library/portable-simd/crates/core_simd/src/ops/assign.rs index d2b48614fc966..0e87785025a38 100644 --- a/library/portable-simd/crates/core_simd/src/ops/assign.rs +++ b/library/portable-simd/crates/core_simd/src/ops/assign.rs @@ -8,7 +8,7 @@ use core::ops::{ShlAssign, ShrAssign}; // non-commutative bit binary op-assignme // Arithmetic macro_rules! assign_ops { - ($(impl $assignTrait:ident for Simd + ($(impl $assignTrait:ident for Simd where Self: $trait:ident, { @@ -16,11 +16,11 @@ macro_rules! assign_ops { $call:ident } })*) => { - $(impl $assignTrait for Simd + $(impl $assignTrait for Simd where Self: $trait, T: SimdElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn $assign_call(&mut self, rhs: U) { @@ -32,7 +32,7 @@ macro_rules! assign_ops { assign_ops! { // Arithmetic - impl AddAssign for Simd + impl AddAssign for Simd where Self: Add, { @@ -41,7 +41,7 @@ assign_ops! { } } - impl MulAssign for Simd + impl MulAssign for Simd where Self: Mul, { @@ -50,7 +50,7 @@ assign_ops! { } } - impl SubAssign for Simd + impl SubAssign for Simd where Self: Sub, { @@ -59,7 +59,7 @@ assign_ops! { } } - impl DivAssign for Simd + impl DivAssign for Simd where Self: Div, { @@ -67,7 +67,7 @@ assign_ops! { div } } - impl RemAssign for Simd + impl RemAssign for Simd where Self: Rem, { @@ -77,7 +77,7 @@ assign_ops! { } // Bitops - impl BitAndAssign for Simd + impl BitAndAssign for Simd where Self: BitAnd, { @@ -86,7 +86,7 @@ assign_ops! { } } - impl BitOrAssign for Simd + impl BitOrAssign for Simd where Self: BitOr, { @@ -95,7 +95,7 @@ assign_ops! { } } - impl BitXorAssign for Simd + impl BitXorAssign for Simd where Self: BitXor, { @@ -104,7 +104,7 @@ assign_ops! { } } - impl ShlAssign for Simd + impl ShlAssign for Simd where Self: Shl, { @@ -113,7 +113,7 @@ assign_ops! { } } - impl ShrAssign for Simd + impl ShrAssign for Simd where Self: Shr, { diff --git a/library/portable-simd/crates/core_simd/src/ops/deref.rs b/library/portable-simd/crates/core_simd/src/ops/deref.rs index 302bf148bd3ef..89a60ba114146 100644 --- a/library/portable-simd/crates/core_simd/src/ops/deref.rs +++ b/library/portable-simd/crates/core_simd/src/ops/deref.rs @@ -5,16 +5,16 @@ use super::*; macro_rules! deref_lhs { - (impl $trait:ident for $simd:ty { + (impl $trait:ident for $simd:ty { fn $call:ident }) => { - impl $trait<$simd> for &$simd + impl $trait<$simd> for &$simd where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Output = Simd; + type Output = Simd; #[inline] #[must_use = "operator returns a new vector without mutating the inputs"] @@ -26,16 +26,16 @@ macro_rules! deref_lhs { } macro_rules! deref_rhs { - (impl $trait:ident for $simd:ty { + (impl $trait:ident for $simd:ty { fn $call:ident }) => { - impl $trait<&$simd> for $simd + impl $trait<&$simd> for $simd where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Output = Simd; + type Output = Simd; #[inline] #[must_use = "operator returns a new vector without mutating the inputs"] @@ -47,25 +47,25 @@ macro_rules! deref_rhs { } macro_rules! deref_ops { - ($(impl $trait:ident for $simd:ty { + ($(impl $trait:ident for $simd:ty { fn $call:ident })*) => { $( deref_rhs! { - impl $trait for $simd { + impl $trait for $simd { fn $call } } deref_lhs! { - impl $trait for $simd { + impl $trait for $simd { fn $call } } - impl<'lhs, 'rhs, T, const LANES: usize> $trait<&'rhs $simd> for &'lhs $simd + impl<'lhs, 'rhs, T, const N: usize> $trait<&'rhs $simd> for &'lhs $simd where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = $simd; @@ -81,44 +81,44 @@ macro_rules! deref_ops { deref_ops! { // Arithmetic - impl Add for Simd { + impl Add for Simd { fn add } - impl Mul for Simd { + impl Mul for Simd { fn mul } - impl Sub for Simd { + impl Sub for Simd { fn sub } - impl Div for Simd { + impl Div for Simd { fn div } - impl Rem for Simd { + impl Rem for Simd { fn rem } // Bitops - impl BitAnd for Simd { + impl BitAnd for Simd { fn bitand } - impl BitOr for Simd { + impl BitOr for Simd { fn bitor } - impl BitXor for Simd { + impl BitXor for Simd { fn bitxor } - impl Shl for Simd { + impl Shl for Simd { fn shl } - impl Shr for Simd { + impl Shr for Simd { fn shr } } diff --git a/library/portable-simd/crates/core_simd/src/ops/shift_scalar.rs b/library/portable-simd/crates/core_simd/src/ops/shift_scalar.rs new file mode 100644 index 0000000000000..f5115a5a5e935 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/ops/shift_scalar.rs @@ -0,0 +1,62 @@ +// Shift operations uniquely typically only have a scalar on the right-hand side. +// Here, we implement shifts for scalar RHS arguments. + +use crate::simd::{LaneCount, Simd, SupportedLaneCount}; + +macro_rules! impl_splatted_shifts { + { impl $trait:ident :: $trait_fn:ident for $ty:ty } => { + impl core::ops::$trait<$ty> for Simd<$ty, N> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + #[inline] + fn $trait_fn(self, rhs: $ty) -> Self::Output { + self.$trait_fn(Simd::splat(rhs)) + } + } + + impl core::ops::$trait<&$ty> for Simd<$ty, N> + where + LaneCount: SupportedLaneCount, + { + type Output = Self; + #[inline] + fn $trait_fn(self, rhs: &$ty) -> Self::Output { + self.$trait_fn(Simd::splat(*rhs)) + } + } + + impl<'lhs, const N: usize> core::ops::$trait<$ty> for &'lhs Simd<$ty, N> + where + LaneCount: SupportedLaneCount, + { + type Output = Simd<$ty, N>; + #[inline] + fn $trait_fn(self, rhs: $ty) -> Self::Output { + self.$trait_fn(Simd::splat(rhs)) + } + } + + impl<'lhs, const N: usize> core::ops::$trait<&$ty> for &'lhs Simd<$ty, N> + where + LaneCount: SupportedLaneCount, + { + type Output = Simd<$ty, N>; + #[inline] + fn $trait_fn(self, rhs: &$ty) -> Self::Output { + self.$trait_fn(Simd::splat(*rhs)) + } + } + }; + { $($ty:ty),* } => { + $( + impl_splatted_shifts! { impl Shl::shl for $ty } + impl_splatted_shifts! { impl Shr::shr for $ty } + )* + } +} + +// In the past there were inference issues when generically splatting arguments. +// Enumerate them instead. +impl_splatted_shifts! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize } diff --git a/library/portable-simd/crates/core_simd/src/ops/unary.rs b/library/portable-simd/crates/core_simd/src/ops/unary.rs index 4ad02215034be..a651aa73e9524 100644 --- a/library/portable-simd/crates/core_simd/src/ops/unary.rs +++ b/library/portable-simd/crates/core_simd/src/ops/unary.rs @@ -3,11 +3,11 @@ use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; use core::ops::{Neg, Not}; // unary ops macro_rules! neg { - ($(impl Neg for Simd<$scalar:ty, LANES>)*) => { - $(impl Neg for Simd<$scalar, LANES> + ($(impl Neg for Simd<$scalar:ty, N>)*) => { + $(impl Neg for Simd<$scalar, N> where $scalar: SimdElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; @@ -22,27 +22,27 @@ macro_rules! neg { } neg! { - impl Neg for Simd + impl Neg for Simd - impl Neg for Simd + impl Neg for Simd - impl Neg for Simd + impl Neg for Simd - impl Neg for Simd + impl Neg for Simd - impl Neg for Simd + impl Neg for Simd - impl Neg for Simd + impl Neg for Simd - impl Neg for Simd + impl Neg for Simd } macro_rules! not { - ($(impl Not for Simd<$scalar:ty, LANES>)*) => { - $(impl Not for Simd<$scalar, LANES> + ($(impl Not for Simd<$scalar:ty, N>)*) => { + $(impl Not for Simd<$scalar, N> where $scalar: SimdElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Output = Self; @@ -56,23 +56,23 @@ macro_rules! not { } not! { - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd - impl Not for Simd + impl Not for Simd } diff --git a/library/portable-simd/crates/core_simd/src/select.rs b/library/portable-simd/crates/core_simd/src/select.rs index 065c5987d3fc9..cdcf8eeec815a 100644 --- a/library/portable-simd/crates/core_simd/src/select.rs +++ b/library/portable-simd/crates/core_simd/src/select.rs @@ -1,15 +1,15 @@ use crate::simd::intrinsics; use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount}; -impl Mask +impl Mask where T: MaskElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - /// Choose lanes from two vectors. + /// Choose elements from two vectors. /// - /// For each lane in the mask, choose the corresponding lane from `true_values` if - /// that lane mask is true, and `false_values` if that lane mask is false. + /// For each element in the mask, choose the corresponding element from `true_values` if + /// that element mask is true, and `false_values` if that element mask is false. /// /// # Examples /// ``` @@ -23,11 +23,7 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn select( - self, - true_values: Simd, - false_values: Simd, - ) -> Simd + pub fn select(self, true_values: Simd, false_values: Simd) -> Simd where U: SimdElement, { @@ -36,10 +32,10 @@ where unsafe { intrinsics::simd_select(self.to_int(), true_values, false_values) } } - /// Choose lanes from two masks. + /// Choose elements from two masks. /// - /// For each lane in the mask, choose the corresponding lane from `true_values` if - /// that lane mask is true, and `false_values` if that lane mask is false. + /// For each element in the mask, choose the corresponding element from `true_values` if + /// that element mask is true, and `false_values` if that element mask is false. /// /// # Examples /// ``` diff --git a/library/portable-simd/crates/core_simd/src/simd/cmp.rs b/library/portable-simd/crates/core_simd/src/simd/cmp.rs new file mode 100644 index 0000000000000..a8d81dbf20f16 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/simd/cmp.rs @@ -0,0 +1,7 @@ +//! Traits for comparing and ordering vectors. + +mod eq; +mod ord; + +pub use eq::*; +pub use ord::*; diff --git a/library/portable-simd/crates/core_simd/src/eq.rs b/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs similarity index 74% rename from library/portable-simd/crates/core_simd/src/eq.rs rename to library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs index 80763c0727278..f132fa2cc0cae 100644 --- a/library/portable-simd/crates/core_simd/src/eq.rs +++ b/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs @@ -1,5 +1,7 @@ use crate::simd::{ - intrinsics, LaneCount, Mask, Simd, SimdConstPtr, SimdElement, SimdMutPtr, SupportedLaneCount, + intrinsics, + ptr::{SimdConstPtr, SimdMutPtr}, + LaneCount, Mask, Simd, SimdElement, SupportedLaneCount, }; /// Parallel `PartialEq`. @@ -7,11 +9,11 @@ pub trait SimdPartialEq { /// The mask type returned by each comparison. type Mask; - /// Test if each lane is equal to the corresponding lane in `other`. + /// Test if each element is equal to the corresponding element in `other`. #[must_use = "method returns a new mask and does not mutate the original value"] fn simd_eq(self, other: Self) -> Self::Mask; - /// Test if each lane is equal to the corresponding lane in `other`. + /// Test if each element is equal to the corresponding element in `other`. #[must_use = "method returns a new mask and does not mutate the original value"] fn simd_ne(self, other: Self) -> Self::Mask; } @@ -19,11 +21,11 @@ pub trait SimdPartialEq { macro_rules! impl_number { { $($number:ty),* } => { $( - impl SimdPartialEq for Simd<$number, LANES> + impl SimdPartialEq for Simd<$number, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Mask = Mask<<$number as SimdElement>::Mask, LANES>; + type Mask = Mask<<$number as SimdElement>::Mask, N>; #[inline] fn simd_eq(self, other: Self) -> Self::Mask { @@ -48,9 +50,9 @@ impl_number! { f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } macro_rules! impl_mask { { $($integer:ty),* } => { $( - impl SimdPartialEq for Mask<$integer, LANES> + impl SimdPartialEq for Mask<$integer, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Mask = Self; @@ -74,11 +76,11 @@ macro_rules! impl_mask { impl_mask! { i8, i16, i32, i64, isize } -impl SimdPartialEq for Simd<*const T, LANES> +impl SimdPartialEq for Simd<*const T, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Mask = Mask; + type Mask = Mask; #[inline] fn simd_eq(self, other: Self) -> Self::Mask { @@ -91,11 +93,11 @@ where } } -impl SimdPartialEq for Simd<*mut T, LANES> +impl SimdPartialEq for Simd<*mut T, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Mask = Mask; + type Mask = Mask; #[inline] fn simd_eq(self, other: Self) -> Self::Mask { diff --git a/library/portable-simd/crates/core_simd/src/ord.rs b/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs similarity index 79% rename from library/portable-simd/crates/core_simd/src/ord.rs rename to library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs index b2455190e8231..4e9d49ea2211a 100644 --- a/library/portable-simd/crates/core_simd/src/ord.rs +++ b/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs @@ -1,44 +1,47 @@ use crate::simd::{ - intrinsics, LaneCount, Mask, Simd, SimdConstPtr, SimdMutPtr, SimdPartialEq, SupportedLaneCount, + cmp::SimdPartialEq, + intrinsics, + ptr::{SimdConstPtr, SimdMutPtr}, + LaneCount, Mask, Simd, SupportedLaneCount, }; /// Parallel `PartialOrd`. pub trait SimdPartialOrd: SimdPartialEq { - /// Test if each lane is less than the corresponding lane in `other`. + /// Test if each element is less than the corresponding element in `other`. #[must_use = "method returns a new mask and does not mutate the original value"] fn simd_lt(self, other: Self) -> Self::Mask; - /// Test if each lane is less than or equal to the corresponding lane in `other`. + /// Test if each element is less than or equal to the corresponding element in `other`. #[must_use = "method returns a new mask and does not mutate the original value"] fn simd_le(self, other: Self) -> Self::Mask; - /// Test if each lane is greater than the corresponding lane in `other`. + /// Test if each element is greater than the corresponding element in `other`. #[must_use = "method returns a new mask and does not mutate the original value"] fn simd_gt(self, other: Self) -> Self::Mask; - /// Test if each lane is greater than or equal to the corresponding lane in `other`. + /// Test if each element is greater than or equal to the corresponding element in `other`. #[must_use = "method returns a new mask and does not mutate the original value"] fn simd_ge(self, other: Self) -> Self::Mask; } /// Parallel `Ord`. pub trait SimdOrd: SimdPartialOrd { - /// Returns the lane-wise maximum with `other`. + /// Returns the element-wise maximum with `other`. #[must_use = "method returns a new vector and does not mutate the original value"] fn simd_max(self, other: Self) -> Self; - /// Returns the lane-wise minimum with `other`. + /// Returns the element-wise minimum with `other`. #[must_use = "method returns a new vector and does not mutate the original value"] fn simd_min(self, other: Self) -> Self; - /// Restrict each lane to a certain interval. + /// Restrict each element to a certain interval. /// - /// For each lane, returns `max` if `self` is greater than `max`, and `min` if `self` is + /// For each element, returns `max` if `self` is greater than `max`, and `min` if `self` is /// less than `min`. Otherwise returns `self`. /// /// # Panics /// - /// Panics if `min > max` on any lane. + /// Panics if `min > max` on any element. #[must_use = "method returns a new vector and does not mutate the original value"] fn simd_clamp(self, min: Self, max: Self) -> Self; } @@ -46,9 +49,9 @@ pub trait SimdOrd: SimdPartialOrd { macro_rules! impl_integer { { $($integer:ty),* } => { $( - impl SimdPartialOrd for Simd<$integer, LANES> + impl SimdPartialOrd for Simd<$integer, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { @@ -79,9 +82,9 @@ macro_rules! impl_integer { } } - impl SimdOrd for Simd<$integer, LANES> + impl SimdOrd for Simd<$integer, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_max(self, other: Self) -> Self { @@ -98,7 +101,7 @@ macro_rules! impl_integer { fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), - "each lane in `min` must be less than or equal to the corresponding lane in `max`", + "each element in `min` must be less than or equal to the corresponding element in `max`", ); self.simd_max(min).simd_min(max) } @@ -112,9 +115,9 @@ impl_integer! { u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } macro_rules! impl_float { { $($float:ty),* } => { $( - impl SimdPartialOrd for Simd<$float, LANES> + impl SimdPartialOrd for Simd<$float, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { @@ -153,9 +156,9 @@ impl_float! { f32, f64 } macro_rules! impl_mask { { $($integer:ty),* } => { $( - impl SimdPartialOrd for Mask<$integer, LANES> + impl SimdPartialOrd for Mask<$integer, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { @@ -186,9 +189,9 @@ macro_rules! impl_mask { } } - impl SimdOrd for Mask<$integer, LANES> + impl SimdOrd for Mask<$integer, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_max(self, other: Self) -> Self { @@ -205,7 +208,7 @@ macro_rules! impl_mask { fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), - "each lane in `min` must be less than or equal to the corresponding lane in `max`", + "each element in `min` must be less than or equal to the corresponding element in `max`", ); self.simd_max(min).simd_min(max) } @@ -216,9 +219,9 @@ macro_rules! impl_mask { impl_mask! { i8, i16, i32, i64, isize } -impl SimdPartialOrd for Simd<*const T, LANES> +impl SimdPartialOrd for Simd<*const T, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { @@ -241,9 +244,9 @@ where } } -impl SimdOrd for Simd<*const T, LANES> +impl SimdOrd for Simd<*const T, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_max(self, other: Self) -> Self { @@ -260,15 +263,15 @@ where fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), - "each lane in `min` must be less than or equal to the corresponding lane in `max`", + "each element in `min` must be less than or equal to the corresponding element in `max`", ); self.simd_max(min).simd_min(max) } } -impl SimdPartialOrd for Simd<*mut T, LANES> +impl SimdPartialOrd for Simd<*mut T, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { @@ -291,9 +294,9 @@ where } } -impl SimdOrd for Simd<*mut T, LANES> +impl SimdOrd for Simd<*mut T, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { #[inline] fn simd_max(self, other: Self) -> Self { @@ -310,7 +313,7 @@ where fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), - "each lane in `min` must be less than or equal to the corresponding lane in `max`", + "each element in `min` must be less than or equal to the corresponding element in `max`", ); self.simd_max(min).simd_min(max) } diff --git a/library/portable-simd/crates/core_simd/src/elements.rs b/library/portable-simd/crates/core_simd/src/simd/num.rs similarity index 63% rename from library/portable-simd/crates/core_simd/src/elements.rs rename to library/portable-simd/crates/core_simd/src/simd/num.rs index dc7f52a4d576c..22a4802ec6cb5 100644 --- a/library/portable-simd/crates/core_simd/src/elements.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num.rs @@ -1,15 +1,13 @@ -mod const_ptr; +//! Traits for vectors with numeric elements. + mod float; mod int; -mod mut_ptr; mod uint; mod sealed { pub trait Sealed {} } -pub use const_ptr::*; pub use float::*; pub use int::*; -pub use mut_ptr::*; pub use uint::*; diff --git a/library/portable-simd/crates/core_simd/src/elements/float.rs b/library/portable-simd/crates/core_simd/src/simd/num/float.rs similarity index 80% rename from library/portable-simd/crates/core_simd/src/elements/float.rs rename to library/portable-simd/crates/core_simd/src/simd/num/float.rs index 501c1c5ddd3f2..fc0b99e87a68e 100644 --- a/library/portable-simd/crates/core_simd/src/elements/float.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/float.rs @@ -1,7 +1,7 @@ use super::sealed::Sealed; use crate::simd::{ - intrinsics, LaneCount, Mask, Simd, SimdCast, SimdElement, SimdPartialEq, SimdPartialOrd, - SupportedLaneCount, + cmp::{SimdPartialEq, SimdPartialOrd}, + intrinsics, LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, }; /// Operations on SIMD vectors of floats. @@ -28,7 +28,7 @@ pub trait SimdFloat: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{SimdFloat, SimdInt, Simd}; + /// # use simd::prelude::*; /// let floats: Simd = Simd::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]); /// let ints = floats.cast::(); /// assert_eq!(ints, Simd::from_array([1, -4, i32::MAX, 0])); @@ -63,64 +63,64 @@ pub trait SimdFloat: Copy + Sealed { Self::Scalar: core::convert::FloatToInt; /// Raw transmutation to an unsigned integer vector type with the - /// same size and number of lanes. + /// same size and number of elements. #[must_use = "method returns a new vector and does not mutate the original value"] fn to_bits(self) -> Self::Bits; /// Raw transmutation from an unsigned integer vector type with the - /// same size and number of lanes. + /// same size and number of elements. #[must_use = "method returns a new vector and does not mutate the original value"] fn from_bits(bits: Self::Bits) -> Self; - /// Produces a vector where every lane has the absolute value of the - /// equivalently-indexed lane in `self`. + /// Produces a vector where every element has the absolute value of the + /// equivalently-indexed element in `self`. #[must_use = "method returns a new vector and does not mutate the original value"] fn abs(self) -> Self; - /// Takes the reciprocal (inverse) of each lane, `1/x`. + /// Takes the reciprocal (inverse) of each element, `1/x`. #[must_use = "method returns a new vector and does not mutate the original value"] fn recip(self) -> Self; - /// Converts each lane from radians to degrees. + /// Converts each element from radians to degrees. #[must_use = "method returns a new vector and does not mutate the original value"] fn to_degrees(self) -> Self; - /// Converts each lane from degrees to radians. + /// Converts each element from degrees to radians. #[must_use = "method returns a new vector and does not mutate the original value"] fn to_radians(self) -> Self; - /// Returns true for each lane if it has a positive sign, including + /// Returns true for each element if it has a positive sign, including /// `+0.0`, `NaN`s with positive sign bit and positive infinity. #[must_use = "method returns a new mask and does not mutate the original value"] fn is_sign_positive(self) -> Self::Mask; - /// Returns true for each lane if it has a negative sign, including + /// Returns true for each element if it has a negative sign, including /// `-0.0`, `NaN`s with negative sign bit and negative infinity. #[must_use = "method returns a new mask and does not mutate the original value"] fn is_sign_negative(self) -> Self::Mask; - /// Returns true for each lane if its value is `NaN`. + /// Returns true for each element if its value is `NaN`. #[must_use = "method returns a new mask and does not mutate the original value"] fn is_nan(self) -> Self::Mask; - /// Returns true for each lane if its value is positive infinity or negative infinity. + /// Returns true for each element if its value is positive infinity or negative infinity. #[must_use = "method returns a new mask and does not mutate the original value"] fn is_infinite(self) -> Self::Mask; - /// Returns true for each lane if its value is neither infinite nor `NaN`. + /// Returns true for each element if its value is neither infinite nor `NaN`. #[must_use = "method returns a new mask and does not mutate the original value"] fn is_finite(self) -> Self::Mask; - /// Returns true for each lane if its value is subnormal. + /// Returns true for each element if its value is subnormal. #[must_use = "method returns a new mask and does not mutate the original value"] fn is_subnormal(self) -> Self::Mask; - /// Returns true for each lane if its value is neither zero, infinite, + /// Returns true for each element if its value is neither zero, infinite, /// subnormal, nor `NaN`. #[must_use = "method returns a new mask and does not mutate the original value"] fn is_normal(self) -> Self::Mask; - /// Replaces each lane with a number that represents its sign. + /// Replaces each element with a number that represents its sign. /// /// * `1.0` if the number is positive, `+0.0`, or `INFINITY` /// * `-1.0` if the number is negative, `-0.0`, or `NEG_INFINITY` @@ -128,33 +128,33 @@ pub trait SimdFloat: Copy + Sealed { #[must_use = "method returns a new vector and does not mutate the original value"] fn signum(self) -> Self; - /// Returns each lane with the magnitude of `self` and the sign of `sign`. + /// Returns each element with the magnitude of `self` and the sign of `sign`. /// - /// For any lane containing a `NAN`, a `NAN` with the sign of `sign` is returned. + /// For any element containing a `NAN`, a `NAN` with the sign of `sign` is returned. #[must_use = "method returns a new vector and does not mutate the original value"] fn copysign(self, sign: Self) -> Self; - /// Returns the minimum of each lane. + /// Returns the minimum of each element. /// /// If one of the values is `NAN`, then the other value is returned. #[must_use = "method returns a new vector and does not mutate the original value"] fn simd_min(self, other: Self) -> Self; - /// Returns the maximum of each lane. + /// Returns the maximum of each element. /// /// If one of the values is `NAN`, then the other value is returned. #[must_use = "method returns a new vector and does not mutate the original value"] fn simd_max(self, other: Self) -> Self; - /// Restrict each lane to a certain interval unless it is NaN. + /// Restrict each element to a certain interval unless it is NaN. /// - /// For each lane in `self`, returns the corresponding lane in `max` if the lane is - /// greater than `max`, and the corresponding lane in `min` if the lane is less - /// than `min`. Otherwise returns the lane in `self`. + /// For each element in `self`, returns the corresponding element in `max` if the element is + /// greater than `max`, and the corresponding element in `min` if the element is less + /// than `min`. Otherwise returns the element in `self`. #[must_use = "method returns a new vector and does not mutate the original value"] fn simd_clamp(self, min: Self, max: Self) -> Self; - /// Returns the sum of the lanes of the vector. + /// Returns the sum of the elements of the vector. /// /// # Examples /// @@ -162,13 +162,13 @@ pub trait SimdFloat: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{f32x2, SimdFloat}; + /// # use simd::prelude::*; /// let v = f32x2::from_array([1., 2.]); /// assert_eq!(v.reduce_sum(), 3.); /// ``` fn reduce_sum(self) -> Self::Scalar; - /// Reducing multiply. Returns the product of the lanes of the vector. + /// Reducing multiply. Returns the product of the elements of the vector. /// /// # Examples /// @@ -176,18 +176,18 @@ pub trait SimdFloat: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{f32x2, SimdFloat}; + /// # use simd::prelude::*; /// let v = f32x2::from_array([3., 4.]); /// assert_eq!(v.reduce_product(), 12.); /// ``` fn reduce_product(self) -> Self::Scalar; - /// Returns the maximum lane in the vector. + /// Returns the maximum element in the vector. /// /// Returns values based on equality, so a vector containing both `0.` and `-0.` may /// return either. /// - /// This function will not return `NaN` unless all lanes are `NaN`. + /// This function will not return `NaN` unless all elements are `NaN`. /// /// # Examples /// @@ -195,7 +195,7 @@ pub trait SimdFloat: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{f32x2, SimdFloat}; + /// # use simd::prelude::*; /// let v = f32x2::from_array([1., 2.]); /// assert_eq!(v.reduce_max(), 2.); /// @@ -209,12 +209,12 @@ pub trait SimdFloat: Copy + Sealed { /// ``` fn reduce_max(self) -> Self::Scalar; - /// Returns the minimum lane in the vector. + /// Returns the minimum element in the vector. /// /// Returns values based on equality, so a vector containing both `0.` and `-0.` may /// return either. /// - /// This function will not return `NaN` unless all lanes are `NaN`. + /// This function will not return `NaN` unless all elements are `NaN`. /// /// # Examples /// @@ -222,7 +222,7 @@ pub trait SimdFloat: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{f32x2, SimdFloat}; + /// # use simd::prelude::*; /// let v = f32x2::from_array([3., 7.]); /// assert_eq!(v.reduce_min(), 3.); /// @@ -240,20 +240,20 @@ pub trait SimdFloat: Copy + Sealed { macro_rules! impl_trait { { $($ty:ty { bits: $bits_ty:ty, mask: $mask_ty:ty }),* } => { $( - impl Sealed for Simd<$ty, LANES> + impl Sealed for Simd<$ty, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { } - impl SimdFloat for Simd<$ty, LANES> + impl SimdFloat for Simd<$ty, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Mask = Mask<<$mask_ty as SimdElement>::Mask, LANES>; + type Mask = Mask<<$mask_ty as SimdElement>::Mask, N>; type Scalar = $ty; - type Bits = Simd<$bits_ty, LANES>; - type Cast = Simd; + type Bits = Simd<$bits_ty, N>; + type Cast = Simd; #[inline] fn cast(self) -> Self::Cast @@ -273,14 +273,14 @@ macro_rules! impl_trait { } #[inline] - fn to_bits(self) -> Simd<$bits_ty, LANES> { + fn to_bits(self) -> Simd<$bits_ty, N> { assert_eq!(core::mem::size_of::(), core::mem::size_of::()); // Safety: transmuting between vector types is safe unsafe { core::mem::transmute_copy(&self) } } #[inline] - fn from_bits(bits: Simd<$bits_ty, LANES>) -> Self { + fn from_bits(bits: Simd<$bits_ty, N>) -> Self { assert_eq!(core::mem::size_of::(), core::mem::size_of::()); // Safety: transmuting between vector types is safe unsafe { core::mem::transmute_copy(&bits) } @@ -336,7 +336,10 @@ macro_rules! impl_trait { #[inline] fn is_subnormal(self) -> Self::Mask { - self.abs().simd_ne(Self::splat(0.0)) & (self.to_bits() & Self::splat(Self::Scalar::INFINITY).to_bits()).simd_eq(Simd::splat(0)) + // On some architectures (e.g. armv7 and some ppc) subnormals are flushed to zero, + // so this comparison must be done with integers. + let not_zero = self.abs().to_bits().simd_ne(Self::splat(0.0).to_bits()); + not_zero & (self.to_bits() & Self::splat(Self::Scalar::INFINITY).to_bits()).simd_eq(Simd::splat(0)) } #[inline] @@ -373,7 +376,7 @@ macro_rules! impl_trait { fn simd_clamp(self, min: Self, max: Self) -> Self { assert!( min.simd_le(max).all(), - "each lane in `min` must be less than or equal to the corresponding lane in `max`", + "each element in `min` must be less than or equal to the corresponding element in `max`", ); let mut x = self; x = x.simd_lt(min).select(min, x); diff --git a/library/portable-simd/crates/core_simd/src/elements/int.rs b/library/portable-simd/crates/core_simd/src/simd/num/int.rs similarity index 71% rename from library/portable-simd/crates/core_simd/src/elements/int.rs rename to library/portable-simd/crates/core_simd/src/simd/num/int.rs index 6db89ff9a659e..1f1aa27278299 100644 --- a/library/portable-simd/crates/core_simd/src/elements/int.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/int.rs @@ -1,6 +1,7 @@ use super::sealed::Sealed; use crate::simd::{ - intrinsics, LaneCount, Mask, Simd, SimdCast, SimdElement, SimdPartialOrd, SupportedLaneCount, + cmp::SimdPartialOrd, intrinsics, num::SimdUint, LaneCount, Mask, Simd, SimdCast, SimdElement, + SupportedLaneCount, }; /// Operations on SIMD vectors of signed integers. @@ -11,6 +12,9 @@ pub trait SimdInt: Copy + Sealed { /// Scalar type contained by this SIMD vector type. type Scalar; + /// A SIMD vector of unsigned integers with the same element size. + type Unsigned; + /// A SIMD vector with a different element type. type Cast; @@ -28,7 +32,7 @@ pub trait SimdInt: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdInt}; + /// # use simd::prelude::*; /// use core::i32::{MIN, MAX}; /// let x = Simd::from_array([MIN, 0, 1, MAX]); /// let max = Simd::splat(MAX); @@ -46,7 +50,7 @@ pub trait SimdInt: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdInt}; + /// # use simd::prelude::*; /// use core::i32::{MIN, MAX}; /// let x = Simd::from_array([MIN, -2, -1, MAX]); /// let max = Simd::splat(MAX); @@ -57,14 +61,14 @@ pub trait SimdInt: Copy + Sealed { fn saturating_sub(self, second: Self) -> Self; /// Lanewise absolute value, implemented in Rust. - /// Every lane becomes its absolute value. + /// Every element becomes its absolute value. /// /// # Examples /// ``` /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdInt}; + /// # use simd::prelude::*; /// use core::i32::{MIN, MAX}; /// let xs = Simd::from_array([MIN, MIN +1, -5, 0]); /// assert_eq!(xs.abs(), Simd::from_array([MIN, MAX, 5, 0])); @@ -79,7 +83,7 @@ pub trait SimdInt: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdInt}; + /// # use simd::prelude::*; /// use core::i32::{MIN, MAX}; /// let xs = Simd::from_array([MIN, -2, 0, 3]); /// let unsat = xs.abs(); @@ -97,7 +101,7 @@ pub trait SimdInt: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdInt}; + /// # use simd::prelude::*; /// use core::i32::{MIN, MAX}; /// let x = Simd::from_array([MIN, -2, 3, MAX]); /// let unsat = -x; @@ -107,19 +111,19 @@ pub trait SimdInt: Copy + Sealed { /// ``` fn saturating_neg(self) -> Self; - /// Returns true for each positive lane and false if it is zero or negative. + /// Returns true for each positive element and false if it is zero or negative. fn is_positive(self) -> Self::Mask; - /// Returns true for each negative lane and false if it is zero or positive. + /// Returns true for each negative element and false if it is zero or positive. fn is_negative(self) -> Self::Mask; - /// Returns numbers representing the sign of each lane. + /// Returns numbers representing the sign of each element. /// * `0` if the number is zero /// * `1` if the number is positive /// * `-1` if the number is negative fn signum(self) -> Self; - /// Returns the sum of the lanes of the vector, with wrapping addition. + /// Returns the sum of the elements of the vector, with wrapping addition. /// /// # Examples /// @@ -127,7 +131,7 @@ pub trait SimdInt: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{i32x4, SimdInt}; + /// # use simd::prelude::*; /// let v = i32x4::from_array([1, 2, 3, 4]); /// assert_eq!(v.reduce_sum(), 10); /// @@ -137,7 +141,7 @@ pub trait SimdInt: Copy + Sealed { /// ``` fn reduce_sum(self) -> Self::Scalar; - /// Returns the product of the lanes of the vector, with wrapping multiplication. + /// Returns the product of the elements of the vector, with wrapping multiplication. /// /// # Examples /// @@ -145,7 +149,7 @@ pub trait SimdInt: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{i32x4, SimdInt}; + /// # use simd::prelude::*; /// let v = i32x4::from_array([1, 2, 3, 4]); /// assert_eq!(v.reduce_product(), 24); /// @@ -155,7 +159,7 @@ pub trait SimdInt: Copy + Sealed { /// ``` fn reduce_product(self) -> Self::Scalar; - /// Returns the maximum lane in the vector. + /// Returns the maximum element in the vector. /// /// # Examples /// @@ -163,13 +167,13 @@ pub trait SimdInt: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{i32x4, SimdInt}; + /// # use simd::prelude::*; /// let v = i32x4::from_array([1, 2, 3, 4]); /// assert_eq!(v.reduce_max(), 4); /// ``` fn reduce_max(self) -> Self::Scalar; - /// Returns the minimum lane in the vector. + /// Returns the minimum element in the vector. /// /// # Examples /// @@ -177,38 +181,58 @@ pub trait SimdInt: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{i32x4, SimdInt}; + /// # use simd::prelude::*; /// let v = i32x4::from_array([1, 2, 3, 4]); /// assert_eq!(v.reduce_min(), 1); /// ``` fn reduce_min(self) -> Self::Scalar; - /// Returns the cumulative bitwise "and" across the lanes of the vector. + /// Returns the cumulative bitwise "and" across the elements of the vector. fn reduce_and(self) -> Self::Scalar; - /// Returns the cumulative bitwise "or" across the lanes of the vector. + /// Returns the cumulative bitwise "or" across the elements of the vector. fn reduce_or(self) -> Self::Scalar; - /// Returns the cumulative bitwise "xor" across the lanes of the vector. + /// Returns the cumulative bitwise "xor" across the elements of the vector. fn reduce_xor(self) -> Self::Scalar; + + /// Reverses the byte order of each element. + fn swap_bytes(self) -> Self; + + /// Reverses the order of bits in each elemnent. + /// The least significant bit becomes the most significant bit, second least-significant bit becomes second most-significant bit, etc. + fn reverse_bits(self) -> Self; + + /// Returns the number of leading zeros in the binary representation of each element. + fn leading_zeros(self) -> Self::Unsigned; + + /// Returns the number of trailing zeros in the binary representation of each element. + fn trailing_zeros(self) -> Self::Unsigned; + + /// Returns the number of leading ones in the binary representation of each element. + fn leading_ones(self) -> Self::Unsigned; + + /// Returns the number of trailing ones in the binary representation of each element. + fn trailing_ones(self) -> Self::Unsigned; } macro_rules! impl_trait { - { $($ty:ty),* } => { + { $($ty:ident ($unsigned:ident)),* } => { $( - impl Sealed for Simd<$ty, LANES> + impl Sealed for Simd<$ty, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { } - impl SimdInt for Simd<$ty, LANES> + impl SimdInt for Simd<$ty, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Mask = Mask<<$ty as SimdElement>::Mask, LANES>; + type Mask = Mask<<$ty as SimdElement>::Mask, N>; type Scalar = $ty; - type Cast = Simd; + type Unsigned = Simd<$unsigned, N>; + type Cast = Simd; #[inline] fn cast(self) -> Self::Cast { @@ -307,9 +331,41 @@ macro_rules! impl_trait { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_xor(self) } } + + #[inline] + fn swap_bytes(self) -> Self { + // Safety: `self` is an integer vector + unsafe { intrinsics::simd_bswap(self) } + } + + #[inline] + fn reverse_bits(self) -> Self { + // Safety: `self` is an integer vector + unsafe { intrinsics::simd_bitreverse(self) } + } + + #[inline] + fn leading_zeros(self) -> Self::Unsigned { + self.cast::<$unsigned>().leading_zeros() + } + + #[inline] + fn trailing_zeros(self) -> Self::Unsigned { + self.cast::<$unsigned>().trailing_zeros() + } + + #[inline] + fn leading_ones(self) -> Self::Unsigned { + self.cast::<$unsigned>().leading_ones() + } + + #[inline] + fn trailing_ones(self) -> Self::Unsigned { + self.cast::<$unsigned>().trailing_ones() + } } )* } } -impl_trait! { i8, i16, i32, i64, isize } +impl_trait! { i8 (u8), i16 (u16), i32 (u32), i64 (u64), isize (usize) } diff --git a/library/portable-simd/crates/core_simd/src/elements/uint.rs b/library/portable-simd/crates/core_simd/src/simd/num/uint.rs similarity index 58% rename from library/portable-simd/crates/core_simd/src/elements/uint.rs rename to library/portable-simd/crates/core_simd/src/simd/num/uint.rs index 3926c395ec9ac..c955ee8fe8bd1 100644 --- a/library/portable-simd/crates/core_simd/src/elements/uint.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/uint.rs @@ -16,6 +16,12 @@ pub trait SimdUint: Copy + Sealed { #[must_use] fn cast(self) -> Self::Cast; + /// Wrapping negation. + /// + /// Like [`u32::wrapping_neg`], all applications of this function will wrap, with the exception + /// of `-0`. + fn wrapping_neg(self) -> Self; + /// Lanewise saturating add. /// /// # Examples @@ -23,7 +29,7 @@ pub trait SimdUint: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdUint}; + /// # use simd::prelude::*; /// use core::u32::MAX; /// let x = Simd::from_array([2, 1, 0, MAX]); /// let max = Simd::splat(MAX); @@ -41,7 +47,7 @@ pub trait SimdUint: Copy + Sealed { /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdUint}; + /// # use simd::prelude::*; /// use core::u32::MAX; /// let x = Simd::from_array([2, 1, 0, MAX]); /// let max = Simd::splat(MAX); @@ -51,43 +57,62 @@ pub trait SimdUint: Copy + Sealed { /// assert_eq!(sat, Simd::splat(0)); fn saturating_sub(self, second: Self) -> Self; - /// Returns the sum of the lanes of the vector, with wrapping addition. + /// Returns the sum of the elements of the vector, with wrapping addition. fn reduce_sum(self) -> Self::Scalar; - /// Returns the product of the lanes of the vector, with wrapping multiplication. + /// Returns the product of the elements of the vector, with wrapping multiplication. fn reduce_product(self) -> Self::Scalar; - /// Returns the maximum lane in the vector. + /// Returns the maximum element in the vector. fn reduce_max(self) -> Self::Scalar; - /// Returns the minimum lane in the vector. + /// Returns the minimum element in the vector. fn reduce_min(self) -> Self::Scalar; - /// Returns the cumulative bitwise "and" across the lanes of the vector. + /// Returns the cumulative bitwise "and" across the elements of the vector. fn reduce_and(self) -> Self::Scalar; - /// Returns the cumulative bitwise "or" across the lanes of the vector. + /// Returns the cumulative bitwise "or" across the elements of the vector. fn reduce_or(self) -> Self::Scalar; - /// Returns the cumulative bitwise "xor" across the lanes of the vector. + /// Returns the cumulative bitwise "xor" across the elements of the vector. fn reduce_xor(self) -> Self::Scalar; + + /// Reverses the byte order of each element. + fn swap_bytes(self) -> Self; + + /// Reverses the order of bits in each elemnent. + /// The least significant bit becomes the most significant bit, second least-significant bit becomes second most-significant bit, etc. + fn reverse_bits(self) -> Self; + + /// Returns the number of leading zeros in the binary representation of each element. + fn leading_zeros(self) -> Self; + + /// Returns the number of trailing zeros in the binary representation of each element. + fn trailing_zeros(self) -> Self; + + /// Returns the number of leading ones in the binary representation of each element. + fn leading_ones(self) -> Self; + + /// Returns the number of trailing ones in the binary representation of each element. + fn trailing_ones(self) -> Self; } macro_rules! impl_trait { - { $($ty:ty),* } => { + { $($ty:ident ($signed:ident)),* } => { $( - impl Sealed for Simd<$ty, LANES> + impl Sealed for Simd<$ty, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { } - impl SimdUint for Simd<$ty, LANES> + impl SimdUint for Simd<$ty, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { type Scalar = $ty; - type Cast = Simd; + type Cast = Simd; #[inline] fn cast(self) -> Self::Cast { @@ -95,6 +120,12 @@ macro_rules! impl_trait { unsafe { intrinsics::simd_as(self) } } + #[inline] + fn wrapping_neg(self) -> Self { + use crate::simd::num::SimdInt; + (-self.cast::<$signed>()).cast() + } + #[inline] fn saturating_add(self, second: Self) -> Self { // Safety: `self` is a vector @@ -148,9 +179,43 @@ macro_rules! impl_trait { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_xor(self) } } + + #[inline] + fn swap_bytes(self) -> Self { + // Safety: `self` is an integer vector + unsafe { intrinsics::simd_bswap(self) } + } + + #[inline] + fn reverse_bits(self) -> Self { + // Safety: `self` is an integer vector + unsafe { intrinsics::simd_bitreverse(self) } + } + + #[inline] + fn leading_zeros(self) -> Self { + // Safety: `self` is an integer vector + unsafe { intrinsics::simd_ctlz(self) } + } + + #[inline] + fn trailing_zeros(self) -> Self { + // Safety: `self` is an integer vector + unsafe { intrinsics::simd_cttz(self) } + } + + #[inline] + fn leading_ones(self) -> Self { + (!self).leading_zeros() + } + + #[inline] + fn trailing_ones(self) -> Self { + (!self).trailing_zeros() + } } )* } } -impl_trait! { u8, u16, u32, u64, usize } +impl_trait! { u8 (i8), u16 (i16), u32 (i32), u64 (i64), usize (isize) } diff --git a/library/portable-simd/crates/core_simd/src/simd/prelude.rs b/library/portable-simd/crates/core_simd/src/simd/prelude.rs index e8fdc932d490f..4b7c744c01326 100644 --- a/library/portable-simd/crates/core_simd/src/simd/prelude.rs +++ b/library/portable-simd/crates/core_simd/src/simd/prelude.rs @@ -7,8 +7,10 @@ #[doc(no_inline)] pub use super::{ - simd_swizzle, Mask, Simd, SimdConstPtr, SimdFloat, SimdInt, SimdMutPtr, SimdOrd, SimdPartialEq, - SimdPartialOrd, SimdUint, + cmp::{SimdOrd, SimdPartialEq, SimdPartialOrd}, + num::{SimdFloat, SimdInt, SimdUint}, + ptr::{SimdConstPtr, SimdMutPtr}, + simd_swizzle, Mask, Simd, }; #[rustfmt::skip] diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr.rs new file mode 100644 index 0000000000000..3f8e666911853 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/simd/ptr.rs @@ -0,0 +1,11 @@ +//! Traits for vectors of pointers. + +mod const_ptr; +mod mut_ptr; + +mod sealed { + pub trait Sealed {} +} + +pub use const_ptr::*; +pub use mut_ptr::*; diff --git a/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs similarity index 81% rename from library/portable-simd/crates/core_simd/src/elements/const_ptr.rs rename to library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs index f215f9a61d02e..97fe3fb600dfa 100644 --- a/library/portable-simd/crates/core_simd/src/elements/const_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -1,15 +1,17 @@ use super::sealed::Sealed; -use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SimdUint, SupportedLaneCount}; +use crate::simd::{ + cmp::SimdPartialEq, intrinsics, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount, +}; /// Operations on SIMD vectors of constant pointers. pub trait SimdConstPtr: Copy + Sealed { - /// Vector of `usize` with the same number of lanes. + /// Vector of `usize` with the same number of elements. type Usize; - /// Vector of `isize` with the same number of lanes. + /// Vector of `isize` with the same number of elements. type Isize; - /// Vector of const pointers with the same number of lanes. + /// Vector of const pointers with the same number of elements. type CastPtr; /// Vector of mutable pointers to the same type. @@ -18,17 +20,17 @@ pub trait SimdConstPtr: Copy + Sealed { /// Mask type used for manipulating this SIMD vector type. type Mask; - /// Returns `true` for each lane that is null. + /// Returns `true` for each element that is null. fn is_null(self) -> Self::Mask; /// Casts to a pointer of another type. /// - /// Equivalent to calling [`pointer::cast`] on each lane. + /// Equivalent to calling [`pointer::cast`] on each element. fn cast(self) -> Self::CastPtr; /// Changes constness without changing the type. /// - /// Equivalent to calling [`pointer::cast_mut`] on each lane. + /// Equivalent to calling [`pointer::cast_mut`] on each element. fn cast_mut(self) -> Self::MutPtr; /// Gets the "address" portion of the pointer. @@ -39,7 +41,7 @@ pub trait SimdConstPtr: Copy + Sealed { /// This method semantically discards *provenance* and /// *address-space* information. To properly restore that information, use [`Self::with_addr`]. /// - /// Equivalent to calling [`pointer::addr`] on each lane. + /// Equivalent to calling [`pointer::addr`] on each element. fn addr(self) -> Self::Usize; /// Creates a new pointer with the given address. @@ -47,7 +49,7 @@ pub trait SimdConstPtr: Copy + Sealed { /// This performs the same operation as a cast, but copies the *address-space* and /// *provenance* of `self` to the new pointer. /// - /// Equivalent to calling [`pointer::with_addr`] on each lane. + /// Equivalent to calling [`pointer::with_addr`] on each element. fn with_addr(self, addr: Self::Usize) -> Self; /// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use @@ -56,39 +58,36 @@ pub trait SimdConstPtr: Copy + Sealed { /// Convert an address back to a pointer, picking up a previously "exposed" provenance. /// - /// Equivalent to calling [`core::ptr::from_exposed_addr`] on each lane. + /// Equivalent to calling [`core::ptr::from_exposed_addr`] on each element. fn from_exposed_addr(addr: Self::Usize) -> Self; /// Calculates the offset from a pointer using wrapping arithmetic. /// - /// Equivalent to calling [`pointer::wrapping_offset`] on each lane. + /// Equivalent to calling [`pointer::wrapping_offset`] on each element. fn wrapping_offset(self, offset: Self::Isize) -> Self; /// Calculates the offset from a pointer using wrapping arithmetic. /// - /// Equivalent to calling [`pointer::wrapping_add`] on each lane. + /// Equivalent to calling [`pointer::wrapping_add`] on each element. fn wrapping_add(self, count: Self::Usize) -> Self; /// Calculates the offset from a pointer using wrapping arithmetic. /// - /// Equivalent to calling [`pointer::wrapping_sub`] on each lane. + /// Equivalent to calling [`pointer::wrapping_sub`] on each element. fn wrapping_sub(self, count: Self::Usize) -> Self; } -impl Sealed for Simd<*const T, LANES> where - LaneCount: SupportedLaneCount -{ -} +impl Sealed for Simd<*const T, N> where LaneCount: SupportedLaneCount {} -impl SimdConstPtr for Simd<*const T, LANES> +impl SimdConstPtr for Simd<*const T, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Usize = Simd; - type Isize = Simd; - type CastPtr = Simd<*const U, LANES>; - type MutPtr = Simd<*mut T, LANES>; - type Mask = Mask; + type Usize = Simd; + type Isize = Simd; + type CastPtr = Simd<*const U, N>; + type MutPtr = Simd<*mut T, N>; + type Mask = Mask; #[inline] fn is_null(self) -> Self::Mask { diff --git a/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs similarity index 81% rename from library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs rename to library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs index 4bdc6a14ce4a6..e35633d0433dd 100644 --- a/library/portable-simd/crates/core_simd/src/elements/mut_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -1,15 +1,17 @@ use super::sealed::Sealed; -use crate::simd::{intrinsics, LaneCount, Mask, Simd, SimdPartialEq, SimdUint, SupportedLaneCount}; +use crate::simd::{ + cmp::SimdPartialEq, intrinsics, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount, +}; /// Operations on SIMD vectors of mutable pointers. pub trait SimdMutPtr: Copy + Sealed { - /// Vector of `usize` with the same number of lanes. + /// Vector of `usize` with the same number of elements. type Usize; - /// Vector of `isize` with the same number of lanes. + /// Vector of `isize` with the same number of elements. type Isize; - /// Vector of const pointers with the same number of lanes. + /// Vector of const pointers with the same number of elements. type CastPtr; /// Vector of constant pointers to the same type. @@ -18,17 +20,17 @@ pub trait SimdMutPtr: Copy + Sealed { /// Mask type used for manipulating this SIMD vector type. type Mask; - /// Returns `true` for each lane that is null. + /// Returns `true` for each element that is null. fn is_null(self) -> Self::Mask; /// Casts to a pointer of another type. /// - /// Equivalent to calling [`pointer::cast`] on each lane. + /// Equivalent to calling [`pointer::cast`] on each element. fn cast(self) -> Self::CastPtr; /// Changes constness without changing the type. /// - /// Equivalent to calling [`pointer::cast_const`] on each lane. + /// Equivalent to calling [`pointer::cast_const`] on each element. fn cast_const(self) -> Self::ConstPtr; /// Gets the "address" portion of the pointer. @@ -36,7 +38,7 @@ pub trait SimdMutPtr: Copy + Sealed { /// This method discards pointer semantic metadata, so the result cannot be /// directly cast into a valid pointer. /// - /// Equivalent to calling [`pointer::addr`] on each lane. + /// Equivalent to calling [`pointer::addr`] on each element. fn addr(self) -> Self::Usize; /// Creates a new pointer with the given address. @@ -44,7 +46,7 @@ pub trait SimdMutPtr: Copy + Sealed { /// This performs the same operation as a cast, but copies the *address-space* and /// *provenance* of `self` to the new pointer. /// - /// Equivalent to calling [`pointer::with_addr`] on each lane. + /// Equivalent to calling [`pointer::with_addr`] on each element. fn with_addr(self, addr: Self::Usize) -> Self; /// Gets the "address" portion of the pointer, and "exposes" the provenance part for future use @@ -53,37 +55,36 @@ pub trait SimdMutPtr: Copy + Sealed { /// Convert an address back to a pointer, picking up a previously "exposed" provenance. /// - /// Equivalent to calling [`core::ptr::from_exposed_addr_mut`] on each lane. + /// Equivalent to calling [`core::ptr::from_exposed_addr_mut`] on each element. fn from_exposed_addr(addr: Self::Usize) -> Self; /// Calculates the offset from a pointer using wrapping arithmetic. /// - /// Equivalent to calling [`pointer::wrapping_offset`] on each lane. + /// Equivalent to calling [`pointer::wrapping_offset`] on each element. fn wrapping_offset(self, offset: Self::Isize) -> Self; /// Calculates the offset from a pointer using wrapping arithmetic. /// - /// Equivalent to calling [`pointer::wrapping_add`] on each lane. + /// Equivalent to calling [`pointer::wrapping_add`] on each element. fn wrapping_add(self, count: Self::Usize) -> Self; /// Calculates the offset from a pointer using wrapping arithmetic. /// - /// Equivalent to calling [`pointer::wrapping_sub`] on each lane. + /// Equivalent to calling [`pointer::wrapping_sub`] on each element. fn wrapping_sub(self, count: Self::Usize) -> Self; } -impl Sealed for Simd<*mut T, LANES> where LaneCount: SupportedLaneCount -{} +impl Sealed for Simd<*mut T, N> where LaneCount: SupportedLaneCount {} -impl SimdMutPtr for Simd<*mut T, LANES> +impl SimdMutPtr for Simd<*mut T, N> where - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - type Usize = Simd; - type Isize = Simd; - type CastPtr = Simd<*mut U, LANES>; - type ConstPtr = Simd<*const T, LANES>; - type Mask = Mask; + type Usize = Simd; + type Isize = Simd; + type CastPtr = Simd<*mut U, N>; + type ConstPtr = Simd<*const T, N>; + type Mask = Mask; #[inline] fn is_null(self) -> Self::Mask { diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs index 68f20516cf5bc..ec8548d557458 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle.rs @@ -1,17 +1,15 @@ use crate::simd::intrinsics; -use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount}; -/// Constructs a new SIMD vector by copying elements from selected lanes in other vectors. +/// Constructs a new SIMD vector by copying elements from selected elements in other vectors. /// -/// When swizzling one vector, lanes are selected by a `const` array of `usize`, -/// like [`Swizzle`]. +/// When swizzling one vector, elements are selected like [`Swizzle::swizzle`]. /// -/// When swizzling two vectors, lanes are selected by a `const` array of [`Which`], -/// like [`Swizzle2`]. +/// When swizzling two vectors, elements are selected like [`Swizzle::concat_swizzle`]. /// /// # Examples /// -/// With a single SIMD vector, the const array specifies lane indices in that vector: +/// With a single SIMD vector, the const array specifies element indices in that vector: /// ``` /// # #![feature(portable_simd)] /// # use core::simd::{u32x2, u32x4, simd_swizzle}; @@ -21,25 +19,27 @@ use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; /// let r: u32x4 = simd_swizzle!(v, [3, 0, 1, 2]); /// assert_eq!(r.to_array(), [13, 10, 11, 12]); /// -/// // Changing the number of lanes +/// // Changing the number of elements /// let r: u32x2 = simd_swizzle!(v, [3, 1]); /// assert_eq!(r.to_array(), [13, 11]); /// ``` /// -/// With two input SIMD vectors, the const array uses `Which` to specify the source of each index: +/// With two input SIMD vectors, the const array specifies element indices in the concatenation of +/// those vectors: /// ``` /// # #![feature(portable_simd)] -/// # use core::simd::{u32x2, u32x4, simd_swizzle, Which}; -/// use Which::{First, Second}; +/// # #[cfg(feature = "as_crate")] use core_simd::simd; +/// # #[cfg(not(feature = "as_crate"))] use core::simd; +/// # use simd::{u32x2, u32x4, simd_swizzle}; /// let a = u32x4::from_array([0, 1, 2, 3]); /// let b = u32x4::from_array([4, 5, 6, 7]); /// /// // Keeping the same size -/// let r: u32x4 = simd_swizzle!(a, b, [First(0), First(1), Second(2), Second(3)]); +/// let r: u32x4 = simd_swizzle!(a, b, [0, 1, 6, 7]); /// assert_eq!(r.to_array(), [0, 1, 6, 7]); /// -/// // Changing the number of lanes -/// let r: u32x2 = simd_swizzle!(a, b, [First(0), Second(0)]); +/// // Changing the number of elements +/// let r: u32x2 = simd_swizzle!(a, b, [0, 4]); /// assert_eq!(r.to_array(), [0, 4]); /// ``` #[allow(unused_macros)] @@ -50,7 +50,7 @@ pub macro simd_swizzle { { use $crate::simd::Swizzle; struct Impl; - impl Swizzle for Impl { + impl Swizzle<{$index.len()}> for Impl { const INDEX: [usize; {$index.len()}] = $index; } Impl::swizzle($vector) @@ -60,204 +60,194 @@ pub macro simd_swizzle { $first:expr, $second:expr, $index:expr $(,)? ) => { { - use $crate::simd::{Which, Swizzle2}; + use $crate::simd::Swizzle; struct Impl; - impl Swizzle2 for Impl { - const INDEX: [Which; {$index.len()}] = $index; + impl Swizzle<{$index.len()}> for Impl { + const INDEX: [usize; {$index.len()}] = $index; } - Impl::swizzle2($first, $second) + Impl::concat_swizzle($first, $second) } } } -/// Specifies a lane index into one of two SIMD vectors. -/// -/// This is an input type for [Swizzle2] and helper macros like [simd_swizzle]. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Which { - /// Index of a lane in the first input SIMD vector. - First(usize), - /// Index of a lane in the second input SIMD vector. - Second(usize), -} - /// Create a vector from the elements of another vector. -pub trait Swizzle { - /// Map from the lanes of the input vector to the output vector. - const INDEX: [usize; OUTPUT_LANES]; +pub trait Swizzle { + /// Map from the elements of the input vector to the output vector. + const INDEX: [usize; N]; - /// Create a new vector from the lanes of `vector`. + /// Create a new vector from the elements of `vector`. /// /// Lane `i` of the output is `vector[Self::INDEX[i]]`. #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - fn swizzle(vector: Simd) -> Simd + fn swizzle(vector: Simd) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - // Safety: `vector` is a vector, and `INDEX_IMPL` is a const array of u32. - unsafe { intrinsics::simd_shuffle(vector, vector, Self::INDEX_IMPL) } + // Safety: `vector` is a vector, and the index is a const array of u32. + unsafe { + intrinsics::simd_shuffle( + vector, + vector, + const { + let mut output = [0; N]; + let mut i = 0; + while i < N { + let index = Self::INDEX[i]; + assert!(index as u32 as usize == index); + assert!( + index < M, + "source element index exceeds input vector length" + ); + output[i] = index as u32; + i += 1; + } + output + }, + ) + } } -} - -/// Create a vector from the elements of two other vectors. -pub trait Swizzle2 { - /// Map from the lanes of the input vectors to the output vector - const INDEX: [Which; OUTPUT_LANES]; - /// Create a new vector from the lanes of `first` and `second`. + /// Create a new vector from the elements of `first` and `second`. /// - /// Lane `i` is `first[j]` when `Self::INDEX[i]` is `First(j)`, or `second[j]` when it is - /// `Second(j)`. + /// Lane `i` of the output is `concat[Self::INDEX[i]]`, where `concat` is the concatenation of + /// `first` and `second`. #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - fn swizzle2( - first: Simd, - second: Simd, - ) -> Simd + fn concat_swizzle(first: Simd, second: Simd) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - // Safety: `first` and `second` are vectors, and `INDEX_IMPL` is a const array of u32. - unsafe { intrinsics::simd_shuffle(first, second, Self::INDEX_IMPL) } - } -} - -/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here. -/// This trait hides `INDEX_IMPL` from the public API. -trait SwizzleImpl { - const INDEX_IMPL: [u32; OUTPUT_LANES]; -} - -impl SwizzleImpl - for T -where - T: Swizzle + ?Sized, -{ - const INDEX_IMPL: [u32; OUTPUT_LANES] = { - let mut output = [0; OUTPUT_LANES]; - let mut i = 0; - while i < OUTPUT_LANES { - let index = Self::INDEX[i]; - assert!(index as u32 as usize == index); - assert!(index < INPUT_LANES, "source lane exceeds input lane count",); - output[i] = index as u32; - i += 1; + // Safety: `first` and `second` are vectors, and the index is a const array of u32. + unsafe { + intrinsics::simd_shuffle( + first, + second, + const { + let mut output = [0; N]; + let mut i = 0; + while i < N { + let index = Self::INDEX[i]; + assert!(index as u32 as usize == index); + assert!( + index < 2 * M, + "source element index exceeds input vector length" + ); + output[i] = index as u32; + i += 1; + } + output + }, + ) } - output - }; -} - -/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here. -/// This trait hides `INDEX_IMPL` from the public API. -trait Swizzle2Impl { - const INDEX_IMPL: [u32; OUTPUT_LANES]; -} + } -impl Swizzle2Impl - for T -where - T: Swizzle2 + ?Sized, -{ - const INDEX_IMPL: [u32; OUTPUT_LANES] = { - let mut output = [0; OUTPUT_LANES]; - let mut i = 0; - while i < OUTPUT_LANES { - let (offset, index) = match Self::INDEX[i] { - Which::First(index) => (false, index), - Which::Second(index) => (true, index), - }; - assert!(index < INPUT_LANES, "source lane exceeds input lane count",); + /// Create a new mask from the elements of `mask`. + /// + /// Element `i` of the output is `concat[Self::INDEX[i]]`, where `concat` is the concatenation of + /// `first` and `second`. + #[inline] + #[must_use = "method returns a new mask and does not mutate the original inputs"] + fn swizzle_mask(mask: Mask) -> Mask + where + T: MaskElement, + LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, + { + // SAFETY: all elements of this mask come from another mask + unsafe { Mask::from_int_unchecked(Self::swizzle(mask.to_int())) } + } - // lanes are indexed by the first vector, then second vector - let index = if offset { index + INPUT_LANES } else { index }; - assert!(index as u32 as usize == index); - output[i] = index as u32; - i += 1; - } - output - }; + /// Create a new mask from the elements of `first` and `second`. + /// + /// Element `i` of the output is `concat[Self::INDEX[i]]`, where `concat` is the concatenation of + /// `first` and `second`. + #[inline] + #[must_use = "method returns a new mask and does not mutate the original inputs"] + fn concat_swizzle_mask(first: Mask, second: Mask) -> Mask + where + T: MaskElement, + LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, + { + // SAFETY: all elements of this mask come from another mask + unsafe { Mask::from_int_unchecked(Self::concat_swizzle(first.to_int(), second.to_int())) } + } } -impl Simd +impl Simd where T: SimdElement, - LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, { - /// Reverse the order of the lanes in the vector. + /// Reverse the order of the elements in the vector. #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn reverse(self) -> Self { - const fn reverse_index() -> [usize; LANES] { - let mut index = [0; LANES]; - let mut i = 0; - while i < LANES { - index[i] = LANES - i - 1; - i += 1; - } - index - } - struct Reverse; - impl Swizzle for Reverse { - const INDEX: [usize; LANES] = reverse_index::(); + impl Swizzle for Reverse { + const INDEX: [usize; N] = const { + let mut index = [0; N]; + let mut i = 0; + while i < N { + index[i] = N - i - 1; + i += 1; + } + index + }; } Reverse::swizzle(self) } /// Rotates the vector such that the first `OFFSET` elements of the slice move to the end - /// while the last `LANES - OFFSET` elements move to the front. After calling `rotate_lanes_left`, - /// the element previously in lane `OFFSET` will become the first element in the slice. + /// while the last `self.len() - OFFSET` elements move to the front. After calling `rotate_elements_left`, + /// the element previously at index `OFFSET` will become the first element in the slice. #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn rotate_lanes_left(self) -> Self { - const fn rotate_index() -> [usize; LANES] { - let offset = OFFSET % LANES; - let mut index = [0; LANES]; - let mut i = 0; - while i < LANES { - index[i] = (i + offset) % LANES; - i += 1; - } - index - } - + pub fn rotate_elements_left(self) -> Self { struct Rotate; - impl Swizzle for Rotate { - const INDEX: [usize; LANES] = rotate_index::(); + impl Swizzle for Rotate { + const INDEX: [usize; N] = const { + let offset = OFFSET % N; + let mut index = [0; N]; + let mut i = 0; + while i < N { + index[i] = (i + offset) % N; + i += 1; + } + index + }; } Rotate::::swizzle(self) } - /// Rotates the vector such that the first `LANES - OFFSET` elements of the vector move to - /// the end while the last `OFFSET` elements move to the front. After calling `rotate_lanes_right`, - /// the element previously at index `LANES - OFFSET` will become the first element in the slice. + /// Rotates the vector such that the first `self.len() - OFFSET` elements of the vector move to + /// the end while the last `OFFSET` elements move to the front. After calling `rotate_elements_right`, + /// the element previously at index `self.len() - OFFSET` will become the first element in the slice. #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn rotate_lanes_right(self) -> Self { - const fn rotate_index() -> [usize; LANES] { - let offset = LANES - OFFSET % LANES; - let mut index = [0; LANES]; - let mut i = 0; - while i < LANES { - index[i] = (i + offset) % LANES; - i += 1; - } - index - } - + pub fn rotate_elements_right(self) -> Self { struct Rotate; - impl Swizzle for Rotate { - const INDEX: [usize; LANES] = rotate_index::(); + impl Swizzle for Rotate { + const INDEX: [usize; N] = const { + let offset = N - OFFSET % N; + let mut index = [0; N]; + let mut i = 0; + while i < N { + index[i] = (i + offset) % N; + i += 1; + } + index + }; } Rotate::::swizzle(self) @@ -265,7 +255,7 @@ where /// Interleave two vectors. /// - /// The resulting vectors contain lanes taken alternatively from `self` and `other`, first + /// The resulting vectors contain elements taken alternatively from `self` and `other`, first /// filling the first result, and then the second. /// /// The reverse of this operation is [`Simd::deinterleave`]. @@ -282,18 +272,13 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn interleave(self, other: Self) -> (Self, Self) { - const fn interleave(high: bool) -> [Which; LANES] { - let mut idx = [Which::First(0); LANES]; + const fn interleave(high: bool) -> [usize; N] { + let mut idx = [0; N]; let mut i = 0; - while i < LANES { - // Treat the source as a concatenated vector - let dst_index = if high { i + LANES } else { i }; - let src_index = dst_index / 2 + (dst_index % 2) * LANES; - idx[i] = if src_index < LANES { - Which::First(src_index) - } else { - Which::Second(src_index % LANES) - }; + while i < N { + let dst_index = if high { i + N } else { i }; + let src_index = dst_index / 2 + (dst_index % 2) * N; + idx[i] = src_index; i += 1; } idx @@ -302,24 +287,27 @@ where struct Lo; struct Hi; - impl Swizzle2 for Lo { - const INDEX: [Which; LANES] = interleave::(false); + impl Swizzle for Lo { + const INDEX: [usize; N] = interleave::(false); } - impl Swizzle2 for Hi { - const INDEX: [Which; LANES] = interleave::(true); + impl Swizzle for Hi { + const INDEX: [usize; N] = interleave::(true); } - (Lo::swizzle2(self, other), Hi::swizzle2(self, other)) + ( + Lo::concat_swizzle(self, other), + Hi::concat_swizzle(self, other), + ) } /// Deinterleave two vectors. /// - /// The first result takes every other lane of `self` and then `other`, starting with - /// the first lane. + /// The first result takes every other element of `self` and then `other`, starting with + /// the first element. /// - /// The second result takes every other lane of `self` and then `other`, starting with - /// the second lane. + /// The second result takes every other element of `self` and then `other`, starting with + /// the second element. /// /// The reverse of this operation is [`Simd::interleave`]. /// @@ -335,17 +323,11 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn deinterleave(self, other: Self) -> (Self, Self) { - const fn deinterleave(second: bool) -> [Which; LANES] { - let mut idx = [Which::First(0); LANES]; + const fn deinterleave(second: bool) -> [usize; N] { + let mut idx = [0; N]; let mut i = 0; - while i < LANES { - // Treat the source as a concatenated vector - let src_index = i * 2 + second as usize; - idx[i] = if src_index < LANES { - Which::First(src_index) - } else { - Which::Second(src_index % LANES) - }; + while i < N { + idx[i] = i * 2 + second as usize; i += 1; } idx @@ -354,14 +336,52 @@ where struct Even; struct Odd; - impl Swizzle2 for Even { - const INDEX: [Which; LANES] = deinterleave::(false); + impl Swizzle for Even { + const INDEX: [usize; N] = deinterleave::(false); } - impl Swizzle2 for Odd { - const INDEX: [Which; LANES] = deinterleave::(true); + impl Swizzle for Odd { + const INDEX: [usize; N] = deinterleave::(true); } - (Even::swizzle2(self, other), Odd::swizzle2(self, other)) + ( + Even::concat_swizzle(self, other), + Odd::concat_swizzle(self, other), + ) + } + + /// Resize a vector. + /// + /// If `M` > `N`, extends the length of a vector, setting the new elements to `value`. + /// If `M` < `N`, truncates the vector to the first `M` elements. + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::u32x4; + /// let x = u32x4::from_array([0, 1, 2, 3]); + /// assert_eq!(x.resize::<8>(9).to_array(), [0, 1, 2, 3, 9, 9, 9, 9]); + /// assert_eq!(x.resize::<2>(9).to_array(), [0, 1]); + /// ``` + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn resize(self, value: T) -> Simd + where + LaneCount: SupportedLaneCount, + { + struct Resize; + impl Swizzle for Resize { + const INDEX: [usize; M] = const { + let mut index = [0; M]; + let mut i = 0; + while i < M { + index[i] = if i < N { i } else { N }; + i += 1; + } + index + }; + } + Resize::::concat_swizzle(self, Simd::splat(value)) } } diff --git a/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs b/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs index ce621792534e1..bd8a38e350d3b 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs @@ -86,7 +86,7 @@ where #[inline] #[allow(clippy::let_and_return)] unsafe fn avx2_pshufb(bytes: Simd, idxs: Simd) -> Simd { - use crate::simd::SimdPartialOrd; + use crate::simd::cmp::SimdPartialOrd; #[cfg(target_arch = "x86")] use core::arch::x86; #[cfg(target_arch = "x86_64")] @@ -149,7 +149,7 @@ where // On x86, make sure the top bit is set. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] let idxs = { - use crate::simd::SimdPartialOrd; + use crate::simd::cmp::SimdPartialOrd; idxs.simd_lt(Simd::splat(N as u8)) .select(idxs, Simd::splat(u8::MAX)) }; diff --git a/library/portable-simd/crates/core_simd/src/to_bytes.rs b/library/portable-simd/crates/core_simd/src/to_bytes.rs index b36b1a347b226..222526c4ab30a 100644 --- a/library/portable-simd/crates/core_simd/src/to_bytes.rs +++ b/library/portable-simd/crates/core_simd/src/to_bytes.rs @@ -1,24 +1,125 @@ +use crate::simd::{ + num::{SimdFloat, SimdInt, SimdUint}, + LaneCount, Simd, SimdElement, SupportedLaneCount, +}; + +mod sealed { + use super::*; + pub trait Sealed {} + impl Sealed for Simd where LaneCount: SupportedLaneCount {} +} +use sealed::Sealed; + +/// Convert SIMD vectors to vectors of bytes +pub trait ToBytes: Sealed { + /// This type, reinterpreted as bytes. + type Bytes: Copy + + Unpin + + Send + + Sync + + AsRef<[u8]> + + AsMut<[u8]> + + SimdUint + + 'static; + + /// Return the memory representation of this integer as a byte array in native byte + /// order. + fn to_ne_bytes(self) -> Self::Bytes; + + /// Return the memory representation of this integer as a byte array in big-endian + /// (network) byte order. + fn to_be_bytes(self) -> Self::Bytes; + + /// Return the memory representation of this integer as a byte array in little-endian + /// byte order. + fn to_le_bytes(self) -> Self::Bytes; + + /// Create a native endian integer value from its memory representation as a byte array + /// in native endianness. + fn from_ne_bytes(bytes: Self::Bytes) -> Self; + + /// Create an integer value from its representation as a byte array in big endian. + fn from_be_bytes(bytes: Self::Bytes) -> Self; + + /// Create an integer value from its representation as a byte array in little endian. + fn from_le_bytes(bytes: Self::Bytes) -> Self; +} + +macro_rules! swap_bytes { + { f32, $x:expr } => { Simd::from_bits($x.to_bits().swap_bytes()) }; + { f64, $x:expr } => { Simd::from_bits($x.to_bits().swap_bytes()) }; + { $ty:ty, $x:expr } => { $x.swap_bytes() } +} + macro_rules! impl_to_bytes { - { $ty:ty, $size:literal } => { - impl crate::simd::Simd<$ty, LANES> - where - crate::simd::LaneCount: crate::simd::SupportedLaneCount, - crate::simd::LaneCount<{{ $size * LANES }}>: crate::simd::SupportedLaneCount, - { - /// Return the memory representation of this integer as a byte array in native byte - /// order. - pub fn to_ne_bytes(self) -> crate::simd::Simd { + { $ty:tt, 1 } => { impl_to_bytes! { $ty, 1 * [1, 2, 4, 8, 16, 32, 64] } }; + { $ty:tt, 2 } => { impl_to_bytes! { $ty, 2 * [1, 2, 4, 8, 16, 32] } }; + { $ty:tt, 4 } => { impl_to_bytes! { $ty, 4 * [1, 2, 4, 8, 16] } }; + { $ty:tt, 8 } => { impl_to_bytes! { $ty, 8 * [1, 2, 4, 8] } }; + { $ty:tt, 16 } => { impl_to_bytes! { $ty, 16 * [1, 2, 4] } }; + { $ty:tt, 32 } => { impl_to_bytes! { $ty, 32 * [1, 2] } }; + { $ty:tt, 64 } => { impl_to_bytes! { $ty, 64 * [1] } }; + + { $ty:tt, $size:literal * [$($elems:literal),*] } => { + $( + impl ToBytes for Simd<$ty, $elems> { + type Bytes = Simd; + + #[inline] + fn to_ne_bytes(self) -> Self::Bytes { // Safety: transmuting between vectors is safe - unsafe { core::mem::transmute_copy(&self) } + unsafe { + #![allow(clippy::useless_transmute)] + core::mem::transmute(self) + } + } + + #[inline] + fn to_be_bytes(mut self) -> Self::Bytes { + if !cfg!(target_endian = "big") { + self = swap_bytes!($ty, self); + } + self.to_ne_bytes() + } + + #[inline] + fn to_le_bytes(mut self) -> Self::Bytes { + if !cfg!(target_endian = "little") { + self = swap_bytes!($ty, self); + } + self.to_ne_bytes() } - /// Create a native endian integer value from its memory representation as a byte array - /// in native endianness. - pub fn from_ne_bytes(bytes: crate::simd::Simd) -> Self { + #[inline] + fn from_ne_bytes(bytes: Self::Bytes) -> Self { // Safety: transmuting between vectors is safe - unsafe { core::mem::transmute_copy(&bytes) } + unsafe { + #![allow(clippy::useless_transmute)] + core::mem::transmute(bytes) + } + } + + #[inline] + fn from_be_bytes(bytes: Self::Bytes) -> Self { + let ret = Self::from_ne_bytes(bytes); + if cfg!(target_endian = "big") { + ret + } else { + swap_bytes!($ty, ret) + } + } + + #[inline] + fn from_le_bytes(bytes: Self::Bytes) -> Self { + let ret = Self::from_ne_bytes(bytes); + if cfg!(target_endian = "little") { + ret + } else { + swap_bytes!($ty, ret) + } } } + )* } } @@ -39,3 +140,6 @@ impl_to_bytes! { i64, 8 } impl_to_bytes! { isize, 4 } #[cfg(target_pointer_width = "64")] impl_to_bytes! { isize, 8 } + +impl_to_bytes! { f32, 4 } +impl_to_bytes! { f64, 8 } diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs index 9aa7bacfce981..105c06741c58b 100644 --- a/library/portable-simd/crates/core_simd/src/vector.rs +++ b/library/portable-simd/crates/core_simd/src/vector.rs @@ -1,6 +1,8 @@ use crate::simd::{ - intrinsics, LaneCount, Mask, MaskElement, SimdConstPtr, SimdMutPtr, SimdPartialOrd, - SupportedLaneCount, Swizzle, + cmp::SimdPartialOrd, + intrinsics, + ptr::{SimdConstPtr, SimdMutPtr}, + LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, }; use core::convert::{TryFrom, TryInto}; @@ -110,7 +112,7 @@ where T: SimdElement, { /// Number of elements in this vector. - pub const LANES: usize = N; + pub const LEN: usize = N; /// Returns the number of elements in this SIMD vector. /// @@ -118,13 +120,16 @@ where /// /// ``` /// # #![feature(portable_simd)] - /// # use core::simd::u32x4; + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::u32x4; /// let v = u32x4::splat(0); - /// assert_eq!(v.lanes(), 4); + /// assert_eq!(v.len(), 4); /// ``` #[inline] - pub const fn lanes(&self) -> usize { - Self::LANES + #[allow(clippy::len_without_is_empty)] + pub const fn len(&self) -> usize { + Self::LEN } /// Constructs a new SIMD vector with all elements set to the given value. @@ -133,7 +138,9 @@ where /// /// ``` /// # #![feature(portable_simd)] - /// # use core::simd::u32x4; + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::u32x4; /// let v = u32x4::splat(8); /// assert_eq!(v.as_array(), &[8, 8, 8, 8]); /// ``` @@ -142,10 +149,10 @@ where // This is preferred over `[value; N]`, since it's explicitly a splat: // https://github.com/rust-lang/rust/issues/97804 struct Splat; - impl Swizzle<1, N> for Splat { + impl Swizzle for Splat { const INDEX: [usize; N] = [0; N]; } - Splat::swizzle(Simd::::from([value])) + Splat::swizzle::(Simd::::from([value])) } /// Returns an array reference containing the entire SIMD vector. @@ -271,7 +278,7 @@ where #[track_caller] pub const fn from_slice(slice: &[T]) -> Self { assert!( - slice.len() >= Self::LANES, + slice.len() >= Self::LEN, "slice length must be at least the number of elements" ); // SAFETY: We just checked that the slice contains @@ -301,7 +308,7 @@ where #[track_caller] pub fn copy_to_slice(self, slice: &mut [T]) { assert!( - slice.len() >= Self::LANES, + slice.len() >= Self::LEN, "slice length must be at least the number of elements" ); // SAFETY: We just checked that the slice contains @@ -394,7 +401,7 @@ where /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdPartialOrd, Mask}; + /// # use simd::{Simd, cmp::SimdPartialOrd, Mask}; /// let vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; /// let idxs = Simd::from_array([9, 3, 0, 5]); // Includes an out-of-bounds index /// let alt = Simd::from_array([-5, -4, -3, -2]); @@ -434,7 +441,7 @@ where /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdConstPtr}; + /// # use simd::prelude::*; /// let values = [6, 2, 4, 9]; /// let offsets = Simd::from_array([1, 0, 0, 3]); /// let source = Simd::splat(values.as_ptr()).wrapping_add(offsets); @@ -467,7 +474,7 @@ where /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Mask, Simd, SimdConstPtr}; + /// # use simd::prelude::*; /// let values = [6, 2, 4, 9]; /// let enable = Mask::from_array([true, true, false, true]); /// let offsets = Simd::from_array([1, 0, 0, 3]); @@ -550,7 +557,7 @@ where /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdPartialOrd, Mask}; + /// # use simd::{Simd, cmp::SimdPartialOrd, Mask}; /// let mut vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; /// let idxs = Simd::from_array([9, 3, 0, 0]); /// let vals = Simd::from_array([-27, 82, -41, 124]); @@ -604,7 +611,7 @@ where /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Simd, SimdMutPtr}; + /// # use simd::{Simd, ptr::SimdMutPtr}; /// let mut values = [0; 4]; /// let offset = Simd::from_array([3, 2, 1, 0]); /// let ptrs = Simd::splat(values.as_mut_ptr()).wrapping_add(offset); @@ -631,7 +638,7 @@ where /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{Mask, Simd, SimdMutPtr}; + /// # use simd::{Mask, Simd, ptr::SimdMutPtr}; /// let mut values = [0; 4]; /// let offset = Simd::from_array([3, 2, 1, 0]); /// let ptrs = Simd::splat(values.as_mut_ptr()).wrapping_add(offset); diff --git a/library/portable-simd/crates/core_simd/src/vendor.rs b/library/portable-simd/crates/core_simd/src/vendor.rs index 9fb70218c9543..6223bedb4e13c 100644 --- a/library/portable-simd/crates/core_simd/src/vendor.rs +++ b/library/portable-simd/crates/core_simd/src/vendor.rs @@ -21,7 +21,7 @@ macro_rules! from_transmute { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod x86; -#[cfg(any(target_arch = "wasm32"))] +#[cfg(target_arch = "wasm32")] mod wasm32; #[cfg(any(target_arch = "aarch64", target_arch = "arm",))] diff --git a/library/portable-simd/crates/core_simd/src/vendor/x86.rs b/library/portable-simd/crates/core_simd/src/vendor/x86.rs index 0dd47015ed22f..66aaf90eef597 100644 --- a/library/portable-simd/crates/core_simd/src/vendor/x86.rs +++ b/library/portable-simd/crates/core_simd/src/vendor/x86.rs @@ -1,6 +1,6 @@ use crate::simd::*; -#[cfg(any(target_arch = "x86"))] +#[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] diff --git a/library/portable-simd/crates/core_simd/tests/cast.rs b/library/portable-simd/crates/core_simd/tests/cast.rs index 00545936ea2a6..185e1945faa2f 100644 --- a/library/portable-simd/crates/core_simd/tests/cast.rs +++ b/library/portable-simd/crates/core_simd/tests/cast.rs @@ -3,7 +3,7 @@ macro_rules! cast_types { ($start:ident, $($target:ident),*) => { mod $start { #[allow(unused)] - use core_simd::simd::{Simd, SimdInt, SimdUint, SimdFloat}; + use core_simd::simd::prelude::*; type Vector = Simd<$start, N>; $( mod $target { diff --git a/library/portable-simd/crates/core_simd/tests/masks.rs b/library/portable-simd/crates/core_simd/tests/masks.rs index 9f8bad1c36c08..00fc2a24e27a6 100644 --- a/library/portable-simd/crates/core_simd/tests/masks.rs +++ b/library/portable-simd/crates/core_simd/tests/masks.rs @@ -72,7 +72,6 @@ macro_rules! test_mask_api { #[test] fn roundtrip_bitmask_conversion() { - use core_simd::simd::ToBitMask; let values = [ true, false, false, true, false, false, true, false, true, true, false, false, false, false, false, true, @@ -85,8 +84,6 @@ macro_rules! test_mask_api { #[test] fn roundtrip_bitmask_conversion_short() { - use core_simd::simd::ToBitMask; - let values = [ false, false, false, true, ]; @@ -125,18 +122,17 @@ macro_rules! test_mask_api { cast_impl::(); } - #[cfg(feature = "generic_const_exprs")] #[test] - fn roundtrip_bitmask_array_conversion() { - use core_simd::simd::ToBitMaskArray; + fn roundtrip_bitmask_vector_conversion() { + use core_simd::simd::ToBytes; let values = [ true, false, false, true, false, false, true, false, true, true, false, false, false, false, false, true, ]; let mask = Mask::<$type, 16>::from_array(values); - let bitmask = mask.to_bitmask_array(); - assert_eq!(bitmask, [0b01001001, 0b10000011]); - assert_eq!(Mask::<$type, 16>::from_bitmask_array(bitmask), mask); + let bitmask = mask.to_bitmask_vector(); + assert_eq!(bitmask.resize::<2>(0).to_ne_bytes()[..2], [0b01001001, 0b10000011]); + assert_eq!(Mask::<$type, 16>::from_bitmask_vector(bitmask), mask); } } } diff --git a/library/portable-simd/crates/core_simd/tests/ops_macros.rs b/library/portable-simd/crates/core_simd/tests/ops_macros.rs index 3a02f3f01e1cf..aa565a137527e 100644 --- a/library/portable-simd/crates/core_simd/tests/ops_macros.rs +++ b/library/portable-simd/crates/core_simd/tests/ops_macros.rs @@ -6,7 +6,7 @@ macro_rules! impl_unary_op_test { { $scalar:ty, $trait:ident :: $fn:ident, $scalar_fn:expr } => { test_helpers::test_lanes! { fn $fn() { - test_helpers::test_unary_elementwise( + test_helpers::test_unary_elementwise_flush_subnormals( & as core::ops::$trait>::$fn, &$scalar_fn, &|_| true, @@ -31,7 +31,7 @@ macro_rules! impl_binary_op_test { test_helpers::test_lanes! { fn normal() { - test_helpers::test_binary_elementwise( + test_helpers::test_binary_elementwise_flush_subnormals( & as core::ops::$trait>::$fn, &$scalar_fn, &|_, _| true, @@ -39,7 +39,7 @@ macro_rules! impl_binary_op_test { } fn assign() { - test_helpers::test_binary_elementwise( + test_helpers::test_binary_elementwise_flush_subnormals( &|mut a, b| { as core::ops::$trait_assign>::$fn_assign(&mut a, b); a }, &$scalar_fn, &|_, _| true, @@ -68,6 +68,7 @@ macro_rules! impl_binary_checked_op_test { test_helpers::test_lanes! { fn normal() { + #![allow(clippy::redundant_closure_call)] test_helpers::test_binary_elementwise( & as core::ops::$trait>::$fn, &$scalar_fn, @@ -76,6 +77,7 @@ macro_rules! impl_binary_checked_op_test { } fn assign() { + #![allow(clippy::redundant_closure_call)] test_helpers::test_binary_elementwise( &|mut a, b| { as core::ops::$trait_assign>::$fn_assign(&mut a, b); a }, &$scalar_fn, @@ -94,11 +96,43 @@ macro_rules! impl_binary_checked_op_test { macro_rules! impl_common_integer_tests { { $vector:ident, $scalar:ident } => { test_helpers::test_lanes! { + fn shr() { + use core::ops::Shr; + let shr = |x: $scalar, y: $scalar| x.wrapping_shr(y as _); + test_helpers::test_binary_elementwise( + &<$vector:: as Shr<$vector::>>::shr, + &shr, + &|_, _| true, + ); + test_helpers::test_binary_scalar_rhs_elementwise( + &<$vector:: as Shr<$scalar>>::shr, + &shr, + &|_, _| true, + ); + } + + fn shl() { + use core::ops::Shl; + let shl = |x: $scalar, y: $scalar| x.wrapping_shl(y as _); + test_helpers::test_binary_elementwise( + &<$vector:: as Shl<$vector::>>::shl, + &shl, + &|_, _| true, + ); + test_helpers::test_binary_scalar_rhs_elementwise( + &<$vector:: as Shl<$scalar>>::shl, + &shl, + &|_, _| true, + ); + } + fn reduce_sum() { test_helpers::test_1(&|x| { + use test_helpers::subnormals::{flush, flush_in}; test_helpers::prop_assert_biteq! ( $vector::::from_array(x).reduce_sum(), x.iter().copied().fold(0 as $scalar, $scalar::wrapping_add), + flush(x.iter().copied().map(flush_in).fold(0 as $scalar, $scalar::wrapping_add)), ); Ok(()) }); @@ -106,9 +140,11 @@ macro_rules! impl_common_integer_tests { fn reduce_product() { test_helpers::test_1(&|x| { + use test_helpers::subnormals::{flush, flush_in}; test_helpers::prop_assert_biteq! ( $vector::::from_array(x).reduce_product(), x.iter().copied().fold(1 as $scalar, $scalar::wrapping_mul), + flush(x.iter().copied().map(flush_in).fold(1 as $scalar, $scalar::wrapping_mul)), ); Ok(()) }); @@ -163,6 +199,54 @@ macro_rules! impl_common_integer_tests { Ok(()) }); } + + fn swap_bytes() { + test_helpers::test_unary_elementwise( + &$vector::::swap_bytes, + &$scalar::swap_bytes, + &|_| true, + ) + } + + fn reverse_bits() { + test_helpers::test_unary_elementwise( + &$vector::::reverse_bits, + &$scalar::reverse_bits, + &|_| true, + ) + } + + fn leading_zeros() { + test_helpers::test_unary_elementwise( + &$vector::::leading_zeros, + &|x| x.leading_zeros() as _, + &|_| true, + ) + } + + fn trailing_zeros() { + test_helpers::test_unary_elementwise( + &$vector::::trailing_zeros, + &|x| x.trailing_zeros() as _, + &|_| true, + ) + } + + fn leading_ones() { + test_helpers::test_unary_elementwise( + &$vector::::leading_ones, + &|x| x.leading_ones() as _, + &|_| true, + ) + } + + fn trailing_ones() { + test_helpers::test_unary_elementwise( + &$vector::::trailing_ones, + &|x| x.trailing_ones() as _, + &|_| true, + ) + } } } } @@ -172,7 +256,7 @@ macro_rules! impl_common_integer_tests { macro_rules! impl_signed_tests { { $scalar:tt } => { mod $scalar { - use core_simd::simd::SimdInt; + use core_simd::simd::num::SimdInt; type Vector = core_simd::simd::Simd; type Scalar = $scalar; @@ -224,7 +308,7 @@ macro_rules! impl_signed_tests { } fn simd_min() { - use core_simd::simd::SimdOrd; + use core_simd::simd::cmp::SimdOrd; let a = Vector::::splat(Scalar::MIN); let b = Vector::::splat(0); assert_eq!(a.simd_min(b), a); @@ -234,7 +318,7 @@ macro_rules! impl_signed_tests { } fn simd_max() { - use core_simd::simd::SimdOrd; + use core_simd::simd::cmp::SimdOrd; let a = Vector::::splat(Scalar::MIN); let b = Vector::::splat(0); assert_eq!(a.simd_max(b), b); @@ -244,7 +328,7 @@ macro_rules! impl_signed_tests { } fn simd_clamp() { - use core_simd::simd::SimdOrd; + use core_simd::simd::cmp::SimdOrd; let min = Vector::::splat(Scalar::MIN); let max = Vector::::splat(Scalar::MAX); let zero = Vector::::splat(0); @@ -313,7 +397,7 @@ macro_rules! impl_signed_tests { macro_rules! impl_unsigned_tests { { $scalar:tt } => { mod $scalar { - use core_simd::simd::SimdUint; + use core_simd::simd::num::SimdUint; type Vector = core_simd::simd::Simd; type Scalar = $scalar; @@ -327,6 +411,16 @@ macro_rules! impl_unsigned_tests { } } + test_helpers::test_lanes! { + fn wrapping_neg() { + test_helpers::test_unary_elementwise( + &Vector::::wrapping_neg, + &Scalar::wrapping_neg, + &|_| true, + ); + } + } + impl_binary_op_test!(Scalar, Add::add, AddAssign::add_assign, Scalar::wrapping_add); impl_binary_op_test!(Scalar, Sub::sub, SubAssign::sub_assign, Scalar::wrapping_sub); impl_binary_op_test!(Scalar, Mul::mul, MulAssign::mul_assign, Scalar::wrapping_mul); @@ -348,7 +442,7 @@ macro_rules! impl_unsigned_tests { macro_rules! impl_float_tests { { $scalar:tt, $int_scalar:tt } => { mod $scalar { - use core_simd::simd::SimdFloat; + use core_simd::simd::num::SimdFloat; type Vector = core_simd::simd::Simd; type Scalar = $scalar; @@ -433,7 +527,7 @@ macro_rules! impl_float_tests { } fn to_degrees() { - test_helpers::test_unary_elementwise( + test_helpers::test_unary_elementwise_flush_subnormals( &Vector::::to_degrees, &Scalar::to_degrees, &|_| true, @@ -441,7 +535,7 @@ macro_rules! impl_float_tests { } fn to_radians() { - test_helpers::test_unary_elementwise( + test_helpers::test_unary_elementwise_flush_subnormals( &Vector::::to_radians, &Scalar::to_radians, &|_| true, @@ -511,7 +605,12 @@ macro_rules! impl_float_tests { } fn simd_clamp() { + if cfg!(all(target_arch = "powerpc64", target_feature = "vsx")) { + // https://gitlab.com/qemu-project/qemu/-/issues/1780 + return; + } test_helpers::test_3(&|value: [Scalar; LANES], mut min: [Scalar; LANES], mut max: [Scalar; LANES]| { + use test_helpers::subnormals::flush_in; for (min, max) in min.iter_mut().zip(max.iter_mut()) { if max < min { core::mem::swap(min, max); @@ -528,8 +627,20 @@ macro_rules! impl_float_tests { for i in 0..LANES { result_scalar[i] = value[i].clamp(min[i], max[i]); } + let mut result_scalar_flush = [Scalar::default(); LANES]; + for i in 0..LANES { + // Comparisons flush-to-zero, but return value selection is _not_ flushed. + let mut value = value[i]; + if flush_in(value) < flush_in(min[i]) { + value = min[i]; + } + if flush_in(value) > flush_in(max[i]) { + value = max[i]; + } + result_scalar_flush[i] = value + } let result_vector = Vector::from_array(value).simd_clamp(min.into(), max.into()).to_array(); - test_helpers::prop_assert_biteq!(result_scalar, result_vector); + test_helpers::prop_assert_biteq!(result_vector, result_scalar, result_scalar_flush); Ok(()) }) } diff --git a/library/portable-simd/crates/core_simd/tests/pointers.rs b/library/portable-simd/crates/core_simd/tests/pointers.rs index 0ae8f83b8b97d..b9f32d16e01d1 100644 --- a/library/portable-simd/crates/core_simd/tests/pointers.rs +++ b/library/portable-simd/crates/core_simd/tests/pointers.rs @@ -1,6 +1,9 @@ -#![feature(portable_simd, strict_provenance)] +#![feature(portable_simd, strict_provenance, exposed_provenance)] -use core_simd::simd::{Simd, SimdConstPtr, SimdMutPtr}; +use core_simd::simd::{ + ptr::{SimdConstPtr, SimdMutPtr}, + Simd, +}; macro_rules! common_tests { { $constness:ident } => { diff --git a/library/portable-simd/crates/core_simd/tests/round.rs b/library/portable-simd/crates/core_simd/tests/round.rs index aacf7bd3bcc2c..847766ec41ed2 100644 --- a/library/portable-simd/crates/core_simd/tests/round.rs +++ b/library/portable-simd/crates/core_simd/tests/round.rs @@ -43,7 +43,7 @@ macro_rules! float_rounding_test { } fn fract() { - test_helpers::test_unary_elementwise( + test_helpers::test_unary_elementwise_flush_subnormals( &Vector::::fract, &Scalar::fract, &|_| true, @@ -53,7 +53,7 @@ macro_rules! float_rounding_test { test_helpers::test_lanes! { fn to_int_unchecked() { - use core_simd::simd::SimdFloat; + use core_simd::simd::num::SimdFloat; // The maximum integer that can be represented by the equivalently sized float has // all of the mantissa digits set to 1, pushed up to the MSB. const ALL_MANTISSA_BITS: IntScalar = ((1 << ::MANTISSA_DIGITS) - 1); diff --git a/library/portable-simd/crates/core_simd/tests/swizzle.rs b/library/portable-simd/crates/core_simd/tests/swizzle.rs index 8cd7c33e823fb..522d71439b77d 100644 --- a/library/portable-simd/crates/core_simd/tests/swizzle.rs +++ b/library/portable-simd/crates/core_simd/tests/swizzle.rs @@ -11,10 +11,10 @@ wasm_bindgen_test_configure!(run_in_browser); #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn swizzle() { struct Index; - impl Swizzle<4, 4> for Index { + impl Swizzle<4> for Index { const INDEX: [usize; 4] = [2, 1, 3, 0]; } - impl Swizzle<4, 2> for Index { + impl Swizzle<2> for Index { const INDEX: [usize; 2] = [1, 1]; } @@ -34,18 +34,18 @@ fn reverse() { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn rotate() { let a = Simd::from_array([1, 2, 3, 4]); - assert_eq!(a.rotate_lanes_left::<0>().to_array(), [1, 2, 3, 4]); - assert_eq!(a.rotate_lanes_left::<1>().to_array(), [2, 3, 4, 1]); - assert_eq!(a.rotate_lanes_left::<2>().to_array(), [3, 4, 1, 2]); - assert_eq!(a.rotate_lanes_left::<3>().to_array(), [4, 1, 2, 3]); - assert_eq!(a.rotate_lanes_left::<4>().to_array(), [1, 2, 3, 4]); - assert_eq!(a.rotate_lanes_left::<5>().to_array(), [2, 3, 4, 1]); - assert_eq!(a.rotate_lanes_right::<0>().to_array(), [1, 2, 3, 4]); - assert_eq!(a.rotate_lanes_right::<1>().to_array(), [4, 1, 2, 3]); - assert_eq!(a.rotate_lanes_right::<2>().to_array(), [3, 4, 1, 2]); - assert_eq!(a.rotate_lanes_right::<3>().to_array(), [2, 3, 4, 1]); - assert_eq!(a.rotate_lanes_right::<4>().to_array(), [1, 2, 3, 4]); - assert_eq!(a.rotate_lanes_right::<5>().to_array(), [4, 1, 2, 3]); + assert_eq!(a.rotate_elements_left::<0>().to_array(), [1, 2, 3, 4]); + assert_eq!(a.rotate_elements_left::<1>().to_array(), [2, 3, 4, 1]); + assert_eq!(a.rotate_elements_left::<2>().to_array(), [3, 4, 1, 2]); + assert_eq!(a.rotate_elements_left::<3>().to_array(), [4, 1, 2, 3]); + assert_eq!(a.rotate_elements_left::<4>().to_array(), [1, 2, 3, 4]); + assert_eq!(a.rotate_elements_left::<5>().to_array(), [2, 3, 4, 1]); + assert_eq!(a.rotate_elements_right::<0>().to_array(), [1, 2, 3, 4]); + assert_eq!(a.rotate_elements_right::<1>().to_array(), [4, 1, 2, 3]); + assert_eq!(a.rotate_elements_right::<2>().to_array(), [3, 4, 1, 2]); + assert_eq!(a.rotate_elements_right::<3>().to_array(), [2, 3, 4, 1]); + assert_eq!(a.rotate_elements_right::<4>().to_array(), [1, 2, 3, 4]); + assert_eq!(a.rotate_elements_right::<5>().to_array(), [4, 1, 2, 3]); } #[test] diff --git a/library/portable-simd/crates/core_simd/tests/swizzle_dyn.rs b/library/portable-simd/crates/core_simd/tests/swizzle_dyn.rs index 646cd5f338335..f21a937f01c44 100644 --- a/library/portable-simd/crates/core_simd/tests/swizzle_dyn.rs +++ b/library/portable-simd/crates/core_simd/tests/swizzle_dyn.rs @@ -1,6 +1,5 @@ #![feature(portable_simd)] use core::{fmt, ops::RangeInclusive}; -use proptest; use test_helpers::{self, biteq, make_runner, prop_assert_biteq}; fn swizzle_dyn_scalar_ver(values: [u8; N], idxs: [u8; N]) -> [u8; N] { diff --git a/library/portable-simd/crates/core_simd/tests/to_bytes.rs b/library/portable-simd/crates/core_simd/tests/to_bytes.rs index be0ee4349c579..66a7981cdc3dd 100644 --- a/library/portable-simd/crates/core_simd/tests/to_bytes.rs +++ b/library/portable-simd/crates/core_simd/tests/to_bytes.rs @@ -1,14 +1,20 @@ -#![feature(portable_simd, generic_const_exprs, adt_const_params)] -#![allow(incomplete_features)] -#![cfg(feature = "generic_const_exprs")] +#![feature(portable_simd)] -use core_simd::simd::Simd; +use core_simd::simd::{Simd, ToBytes}; #[test] fn byte_convert() { let int = Simd::::from_array([0xdeadbeef, 0x8badf00d]); - let bytes = int.to_ne_bytes(); - assert_eq!(int[0].to_ne_bytes(), bytes[..4]); - assert_eq!(int[1].to_ne_bytes(), bytes[4..]); - assert_eq!(Simd::::from_ne_bytes(bytes), int); + let ne_bytes = int.to_ne_bytes(); + let be_bytes = int.to_be_bytes(); + let le_bytes = int.to_le_bytes(); + assert_eq!(int[0].to_ne_bytes(), ne_bytes[..4]); + assert_eq!(int[1].to_ne_bytes(), ne_bytes[4..]); + assert_eq!(int[0].to_be_bytes(), be_bytes[..4]); + assert_eq!(int[1].to_be_bytes(), be_bytes[4..]); + assert_eq!(int[0].to_le_bytes(), le_bytes[..4]); + assert_eq!(int[1].to_le_bytes(), le_bytes[4..]); + assert_eq!(Simd::::from_ne_bytes(ne_bytes), int); + assert_eq!(Simd::::from_be_bytes(be_bytes), int); + assert_eq!(Simd::::from_le_bytes(le_bytes), int); } diff --git a/library/portable-simd/crates/std_float/src/lib.rs b/library/portable-simd/crates/std_float/src/lib.rs index 4ac60b10c92ef..1fef17242ca85 100644 --- a/library/portable-simd/crates/std_float/src/lib.rs +++ b/library/portable-simd/crates/std_float/src/lib.rs @@ -1,5 +1,10 @@ #![cfg_attr(feature = "as_crate", no_std)] // We are std! -#![cfg_attr(feature = "as_crate", feature(platform_intrinsics), feature(portable_simd))] +#![cfg_attr( + feature = "as_crate", + feature(platform_intrinsics), + feature(portable_simd), + allow(internal_features) +)] #[cfg(not(feature = "as_crate"))] use core::simd; #[cfg(feature = "as_crate")] @@ -144,7 +149,7 @@ where #[cfg(test)] mod tests { use super::*; - use simd::*; + use simd::prelude::*; #[test] fn everything_works() { diff --git a/library/portable-simd/crates/test_helpers/Cargo.toml b/library/portable-simd/crates/test_helpers/Cargo.toml index 1d2bc8b519aa6..23dae7c93381e 100644 --- a/library/portable-simd/crates/test_helpers/Cargo.toml +++ b/library/portable-simd/crates/test_helpers/Cargo.toml @@ -4,10 +4,8 @@ version = "0.1.0" edition = "2021" publish = false -[dependencies.proptest] -version = "0.10" -default-features = false -features = ["alloc"] +[dependencies] +proptest = { version = "0.10", default-features = false, features = ["alloc"] } [features] all_lane_counts = [] diff --git a/library/portable-simd/crates/test_helpers/src/biteq.rs b/library/portable-simd/crates/test_helpers/src/biteq.rs index 7d91260d838a6..cbc20cda0d626 100644 --- a/library/portable-simd/crates/test_helpers/src/biteq.rs +++ b/library/portable-simd/crates/test_helpers/src/biteq.rs @@ -113,6 +113,27 @@ impl core::fmt::Debug for BitEqWrapper<'_, T> { } } +#[doc(hidden)] +pub struct BitEqEitherWrapper<'a, T>(pub &'a T, pub &'a T); + +impl PartialEq> for BitEqWrapper<'_, T> { + fn eq(&self, other: &BitEqEitherWrapper<'_, T>) -> bool { + self.0.biteq(other.0) || self.0.biteq(other.1) + } +} + +impl core::fmt::Debug for BitEqEitherWrapper<'_, T> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + if self.0.biteq(self.1) { + self.0.fmt(f) + } else { + self.0.fmt(f)?; + write!(f, " or ")?; + self.1.fmt(f) + } + } +} + #[macro_export] macro_rules! prop_assert_biteq { { $a:expr, $b:expr $(,)? } => { @@ -122,5 +143,14 @@ macro_rules! prop_assert_biteq { let b = $b; proptest::prop_assert_eq!(BitEqWrapper(&a), BitEqWrapper(&b)); } - } + }; + { $a:expr, $b:expr, $c:expr $(,)? } => { + { + use $crate::biteq::{BitEqWrapper, BitEqEitherWrapper}; + let a = $a; + let b = $b; + let c = $c; + proptest::prop_assert_eq!(BitEqWrapper(&a), BitEqEitherWrapper(&b, &c)); + } + }; } diff --git a/library/portable-simd/crates/test_helpers/src/lib.rs b/library/portable-simd/crates/test_helpers/src/lib.rs index b26cdc311a215..b80c745aaf2fb 100644 --- a/library/portable-simd/crates/test_helpers/src/lib.rs +++ b/library/portable-simd/crates/test_helpers/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(stdsimd, powerpc_target_feature)] + pub mod array; #[cfg(target_arch = "wasm32")] @@ -6,6 +8,9 @@ pub mod wasm; #[macro_use] pub mod biteq; +pub mod subnormals; +use subnormals::FlushSubnormals; + /// Specifies the default strategy for testing a type. /// /// This strategy should be what "makes sense" to test. @@ -151,7 +156,6 @@ pub fn test_3< } /// Test a unary vector function against a unary scalar function, applied elementwise. -#[inline(never)] pub fn test_unary_elementwise( fv: &dyn Fn(Vector) -> VectorResult, fs: &dyn Fn(Scalar) -> ScalarResult, @@ -177,6 +181,48 @@ pub fn test_unary_elementwise( + fv: &dyn Fn(Vector) -> VectorResult, + fs: &dyn Fn(Scalar) -> ScalarResult, + check: &dyn Fn([Scalar; LANES]) -> bool, +) where + Scalar: Copy + core::fmt::Debug + DefaultStrategy + FlushSubnormals, + ScalarResult: Copy + biteq::BitEq + core::fmt::Debug + DefaultStrategy + FlushSubnormals, + Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + let flush = |x: Scalar| subnormals::flush(fs(subnormals::flush_in(x))); + test_1(&|x: [Scalar; LANES]| { + proptest::prop_assume!(check(x)); + let result_v: [ScalarResult; LANES] = fv(x.into()).into(); + let result_s: [ScalarResult; LANES] = x + .iter() + .copied() + .map(fs) + .collect::>() + .try_into() + .unwrap(); + let result_sf: [ScalarResult; LANES] = x + .iter() + .copied() + .map(flush) + .collect::>() + .try_into() + .unwrap(); + crate::prop_assert_biteq!(result_v, result_s, result_sf); + Ok(()) + }); +} + /// Test a unary vector function against a unary scalar function, applied elementwise. #[inline(never)] pub fn test_unary_mask_elementwise( @@ -204,7 +250,6 @@ pub fn test_unary_mask_elementwise( } /// Test a binary vector function against a binary scalar function, applied elementwise. -#[inline(never)] pub fn test_binary_elementwise< Scalar1, Scalar2, @@ -241,6 +286,85 @@ pub fn test_binary_elementwise< }); } +/// Test a binary vector function against a binary scalar function, applied elementwise. +/// +/// Where subnormals are flushed, use approximate equality. +pub fn test_binary_elementwise_flush_subnormals< + Scalar1, + Scalar2, + ScalarResult, + Vector1, + Vector2, + VectorResult, + const LANES: usize, +>( + fv: &dyn Fn(Vector1, Vector2) -> VectorResult, + fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult, + check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES]) -> bool, +) where + Scalar1: Copy + core::fmt::Debug + DefaultStrategy + FlushSubnormals, + Scalar2: Copy + core::fmt::Debug + DefaultStrategy + FlushSubnormals, + ScalarResult: Copy + biteq::BitEq + core::fmt::Debug + DefaultStrategy + FlushSubnormals, + Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy, + Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + let flush = |x: Scalar1, y: Scalar2| { + subnormals::flush(fs(subnormals::flush_in(x), subnormals::flush_in(y))) + }; + test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| { + proptest::prop_assume!(check(x, y)); + let result_v: [ScalarResult; LANES] = fv(x.into(), y.into()).into(); + let result_s: [ScalarResult; LANES] = x + .iter() + .copied() + .zip(y.iter().copied()) + .map(|(x, y)| fs(x, y)) + .collect::>() + .try_into() + .unwrap(); + let result_sf: [ScalarResult; LANES] = x + .iter() + .copied() + .zip(y.iter().copied()) + .map(|(x, y)| flush(x, y)) + .collect::>() + .try_into() + .unwrap(); + crate::prop_assert_biteq!(result_v, result_s, result_sf); + Ok(()) + }); +} + +/// Test a unary vector function against a unary scalar function, applied elementwise. +#[inline(never)] +pub fn test_binary_mask_elementwise( + fv: &dyn Fn(Vector1, Vector2) -> Mask, + fs: &dyn Fn(Scalar1, Scalar2) -> bool, + check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES]) -> bool, +) where + Scalar1: Copy + core::fmt::Debug + DefaultStrategy, + Scalar2: Copy + core::fmt::Debug + DefaultStrategy, + Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy, + Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy, + Mask: Into<[bool; LANES]> + From<[bool; LANES]> + Copy, +{ + test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| { + proptest::prop_assume!(check(x, y)); + let result_v: [bool; LANES] = fv(x.into(), y.into()).into(); + let result_s: [bool; LANES] = x + .iter() + .copied() + .zip(y.iter().copied()) + .map(|(x, y)| fs(x, y)) + .collect::>() + .try_into() + .unwrap(); + crate::prop_assert_biteq!(result_v, result_s); + Ok(()) + }); +} + /// Test a binary vector-scalar function against a binary scalar function, applied elementwise. #[inline(never)] pub fn test_binary_scalar_rhs_elementwise< diff --git a/library/portable-simd/crates/test_helpers/src/subnormals.rs b/library/portable-simd/crates/test_helpers/src/subnormals.rs new file mode 100644 index 0000000000000..ec0f1fb24b936 --- /dev/null +++ b/library/portable-simd/crates/test_helpers/src/subnormals.rs @@ -0,0 +1,91 @@ +pub trait FlushSubnormals: Sized { + fn flush(self) -> Self { + self + } +} + +impl FlushSubnormals for *const T {} +impl FlushSubnormals for *mut T {} + +macro_rules! impl_float { + { $($ty:ty),* } => { + $( + impl FlushSubnormals for $ty { + fn flush(self) -> Self { + let is_f32 = core::mem::size_of::() == 4; + let ppc_flush = is_f32 && cfg!(all( + any(target_arch = "powerpc", all(target_arch = "powerpc64", target_endian = "big")), + target_feature = "altivec", + not(target_feature = "vsx"), + )); + let arm_flush = is_f32 && cfg!(all(target_arch = "arm", target_feature = "neon")); + let flush = ppc_flush || arm_flush; + if flush && self.is_subnormal() { + <$ty>::copysign(0., self) + } else { + self + } + } + } + )* + } +} + +macro_rules! impl_else { + { $($ty:ty),* } => { + $( + impl FlushSubnormals for $ty {} + )* + } +} + +impl_float! { f32, f64 } +impl_else! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize } + +/// AltiVec should flush subnormal inputs to zero, but QEMU seems to only flush outputs. +/// https://gitlab.com/qemu-project/qemu/-/issues/1779 +#[cfg(all( + any(target_arch = "powerpc", target_arch = "powerpc64"), + target_feature = "altivec" +))] +fn in_buggy_qemu() -> bool { + use std::sync::OnceLock; + static BUGGY: OnceLock = OnceLock::new(); + + fn add(x: f32, y: f32) -> f32 { + #[cfg(target_arch = "powerpc")] + use core::arch::powerpc::*; + #[cfg(target_arch = "powerpc64")] + use core::arch::powerpc64::*; + + let array: [f32; 4] = + unsafe { core::mem::transmute(vec_add(vec_splats(x), vec_splats(y))) }; + array[0] + } + + *BUGGY.get_or_init(|| add(-1.0857398e-38, 0.).is_sign_negative()) +} + +#[cfg(all( + any(target_arch = "powerpc", target_arch = "powerpc64"), + target_feature = "altivec" +))] +pub fn flush_in(x: T) -> T { + if in_buggy_qemu() { + x + } else { + x.flush() + } +} + +#[cfg(not(all( + any(target_arch = "powerpc", target_arch = "powerpc64"), + target_feature = "altivec" +)))] +pub fn flush_in(x: T) -> T { + x.flush() +} + +pub fn flush(x: T) -> T { + x.flush() +} diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 991fdb1256de3..d3f1fba9369ca 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -17,8 +17,8 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] // This library is copied into rust-analyzer to allow loading rustc compiled proc macros. // Please avoid unstable features where possible to minimize the amount of changes necessary // to make it compile with rust-analyzer on stable. diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 2eb7608c7ae63..f666b18887cb1 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,8 +17,8 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -libc = { version = "0.2.149", default-features = false, features = ['rustc-dep-of-std'], public = true } -compiler_builtins = { version = "0.1.100" } +libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true } +compiler_builtins = { version = "0.1.103" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] } diff --git a/library/std/build.rs b/library/std/build.rs index ad0a82eab8ca1..0f5068b59b7e5 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -25,7 +25,6 @@ fn main() { || target.contains("vxworks") || target.contains("wasm32") || target.contains("wasm64") - || target.contains("asmjs") || target.contains("espidf") || target.contains("solid") || target.contains("nintendo-3ds") @@ -35,6 +34,7 @@ fn main() { || target.contains("xous") || target.contains("hurd") || target.contains("uefi") + || target.contains("teeos") // See src/bootstrap/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() { diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index e7110aebdea16..7fcf2ee358c46 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -95,7 +95,7 @@ use crate::fmt; use crate::panic::UnwindSafe; use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; use crate::sync::LazyLock; -use crate::sys_common::backtrace::{lock, output_filename}; +use crate::sys_common::backtrace::{lock, output_filename, set_image_base}; use crate::vec::Vec; /// A captured OS thread stack backtrace. @@ -327,6 +327,7 @@ impl Backtrace { let _lock = lock(); let mut frames = Vec::new(); let mut actual_start = None; + set_image_base(); unsafe { backtrace_rs::trace_unsynchronized(|frame| { frames.push(BacktraceFrame { diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4d109285d1645..39e94902cfe5f 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -6,16 +6,13 @@ use self::Entry::*; use hashbrown::hash_map as base; use crate::borrow::Borrow; -use crate::cell::Cell; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind; use crate::error::Error; use crate::fmt::{self, Debug}; -#[allow(deprecated)] -use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13}; +use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::FusedIterator; use crate::ops::Index; -use crate::sys; /// A [hash map] implemented with quadratic probing and SIMD lookup. /// @@ -274,7 +271,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_hasher(s); @@ -306,7 +303,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_capacity_and_hasher(10, s); @@ -717,7 +714,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let map: HashMap = HashMap::with_hasher(hasher); @@ -3072,152 +3069,6 @@ where } } -/// `RandomState` is the default state for [`HashMap`] types. -/// -/// A particular instance `RandomState` will create the same instances of -/// [`Hasher`], but the hashers created by two different `RandomState` -/// instances are unlikely to produce the same result for the same values. -/// -/// # Examples -/// -/// ``` -/// use std::collections::HashMap; -/// use std::collections::hash_map::RandomState; -/// -/// let s = RandomState::new(); -/// let mut map = HashMap::with_hasher(s); -/// map.insert(1, 2); -/// ``` -#[derive(Clone)] -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -pub struct RandomState { - k0: u64, - k1: u64, -} - -impl RandomState { - /// Constructs a new `RandomState` that is initialized with random keys. - /// - /// # Examples - /// - /// ``` - /// use std::collections::hash_map::RandomState; - /// - /// let s = RandomState::new(); - /// ``` - #[inline] - #[allow(deprecated)] - // rand - #[must_use] - #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - pub fn new() -> RandomState { - // Historically this function did not cache keys from the OS and instead - // simply always called `rand::thread_rng().gen()` twice. In #31356 it - // was discovered, however, that because we re-seed the thread-local RNG - // from the OS periodically that this can cause excessive slowdown when - // many hash maps are created on a thread. To solve this performance - // trap we cache the first set of randomly generated keys per-thread. - // - // Later in #36481 it was discovered that exposing a deterministic - // iteration order allows a form of DOS attack. To counter that we - // increment one of the seeds on every RandomState creation, giving - // every corresponding HashMap a different iteration order. - thread_local!(static KEYS: Cell<(u64, u64)> = { - Cell::new(sys::hashmap_random_keys()) - }); - - KEYS.with(|keys| { - let (k0, k1) = keys.get(); - keys.set((k0.wrapping_add(1), k1)); - RandomState { k0, k1 } - }) - } -} - -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -impl BuildHasher for RandomState { - type Hasher = DefaultHasher; - #[inline] - #[allow(deprecated)] - fn build_hasher(&self) -> DefaultHasher { - DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1)) - } -} - -/// The default [`Hasher`] used by [`RandomState`]. -/// -/// The internal algorithm is not specified, and so it and its hashes should -/// not be relied upon over releases. -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -#[allow(deprecated)] -#[derive(Clone, Debug)] -pub struct DefaultHasher(SipHasher13); - -impl DefaultHasher { - /// Creates a new `DefaultHasher`. - /// - /// This hasher is not guaranteed to be the same as all other - /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` - /// instances created through `new` or `default`. - #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] - #[inline] - #[allow(deprecated)] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - #[must_use] - pub const fn new() -> DefaultHasher { - DefaultHasher(SipHasher13::new_with_keys(0, 0)) - } -} - -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Default for DefaultHasher { - /// Creates a new `DefaultHasher` using [`new`]. - /// See its documentation for more. - /// - /// [`new`]: DefaultHasher::new - #[inline] - fn default() -> DefaultHasher { - DefaultHasher::new() - } -} - -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Hasher for DefaultHasher { - // The underlying `SipHasher13` doesn't override the other - // `write_*` methods, so it's ok not to forward them here. - - #[inline] - fn write(&mut self, msg: &[u8]) { - self.0.write(msg) - } - - #[inline] - fn write_str(&mut self, s: &str) { - self.0.write_str(s); - } - - #[inline] - fn finish(&self) -> u64 { - self.0.finish() - } -} - -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -impl Default for RandomState { - /// Constructs a new `RandomState`. - #[inline] - fn default() -> RandomState { - RandomState::new() - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for RandomState { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RandomState").finish_non_exhaustive() - } -} - #[inline] fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K, V> { match raw { diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs index 91a3776e7be84..8585376abc18b 100644 --- a/library/std/src/collections/hash/map/tests.rs +++ b/library/std/src/collections/hash/map/tests.rs @@ -1,8 +1,8 @@ use super::Entry::{Occupied, Vacant}; use super::HashMap; -use super::RandomState; use crate::assert_matches::assert_matches; use crate::cell::RefCell; +use crate::hash::RandomState; use crate::test_helpers::test_rng; use rand::Rng; use realstd::collections::TryReserveErrorKind::*; diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 6a87f6e5f2dc5..8bc5960829066 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -6,11 +6,11 @@ use hashbrown::hash_set as base; use crate::borrow::Borrow; use crate::collections::TryReserveError; use crate::fmt; -use crate::hash::{BuildHasher, Hash}; +use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::{Chain, FusedIterator}; use crate::ops::{BitAnd, BitOr, BitXor, Sub}; -use super::map::{map_try_reserve_error, RandomState}; +use super::map::map_try_reserve_error; /// A [hash set] implemented as a `HashMap` where the value is `()`. /// @@ -361,7 +361,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut set = HashSet::with_hasher(s); @@ -393,7 +393,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut set = HashSet::with_capacity_and_hasher(10, s); @@ -411,7 +411,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let set: HashSet = HashSet::with_hasher(hasher); diff --git a/library/std/src/collections/hash/set/tests.rs b/library/std/src/collections/hash/set/tests.rs index e0cd80b44f8e6..208f61e755c51 100644 --- a/library/std/src/collections/hash/set/tests.rs +++ b/library/std/src/collections/hash/set/tests.rs @@ -1,6 +1,6 @@ -use super::super::map::RandomState; use super::HashSet; +use crate::hash::RandomState; use crate::panic::{catch_unwind, AssertUnwindSafe}; use crate::sync::atomic::{AtomicU32, Ordering}; use crate::sync::Arc; diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 42f738acb9f7b..1389d24a8c519 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -439,6 +439,11 @@ pub mod hash_map { //! A hash map implemented with quadratic probing and SIMD lookup. #[stable(feature = "rust1", since = "1.0.0")] pub use super::hash::map::*; + + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub use crate::hash::random::DefaultHasher; + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub use crate::hash::random::RandomState; } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 375ff2d245044..b240e4e2c45be 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -12,14 +12,6 @@ pub use core::error::Error; #[unstable(feature = "error_generic_member_access", issue = "99301")] pub use core::error::{request_ref, request_value, Request}; -mod private { - // This is a hack to prevent `type_id` from being overridden by `Error` - // implementations, since that can enable unsound downcasting. - #[unstable(feature = "error_type_id", issue = "60784")] - #[derive(Debug)] - pub struct Internal; -} - /// An error reporter that prints an error and its sources. /// /// Report also exposes configuration options for formatting the error sources, either entirely on a diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index fa9d48771b6e2..81973182148ef 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -6,9 +6,10 @@ use crate::cmp; use crate::collections::TryReserveError; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::ops; +use crate::ops::{self, Range}; use crate::rc::Rc; -use crate::str::FromStr; +use crate::slice; +use crate::str::{from_utf8 as str_from_utf8, FromStr}; use crate::sync::Arc; use crate::sys::os_str::{Buf, Slice}; @@ -963,6 +964,83 @@ impl OsStr { self.inner.as_encoded_bytes() } + /// Takes a substring based on a range that corresponds to the return value of + /// [`OsStr::as_encoded_bytes`]. + /// + /// The range's start and end must lie on valid `OsStr` boundaries. + /// A valid `OsStr` boundary is one of: + /// - The start of the string + /// - The end of the string + /// - Immediately before a valid non-empty UTF-8 substring + /// - Immediately after a valid non-empty UTF-8 substring + /// + /// # Panics + /// + /// Panics if `range` does not lie on valid `OsStr` boundaries or if it + /// exceeds the end of the string. + /// + /// # Example + /// + /// ``` + /// #![feature(os_str_slice)] + /// + /// use std::ffi::OsStr; + /// + /// let os_str = OsStr::new("foo=bar"); + /// let bytes = os_str.as_encoded_bytes(); + /// if let Some(index) = bytes.iter().position(|b| *b == b'=') { + /// let key = os_str.slice_encoded_bytes(..index); + /// let value = os_str.slice_encoded_bytes(index + 1..); + /// assert_eq!(key, "foo"); + /// assert_eq!(value, "bar"); + /// } + /// ``` + #[unstable(feature = "os_str_slice", issue = "118485")] + pub fn slice_encoded_bytes>(&self, range: R) -> &Self { + #[track_caller] + fn check_valid_boundary(bytes: &[u8], index: usize) { + if index == 0 || index == bytes.len() { + return; + } + + // Fast path + if bytes[index - 1].is_ascii() || bytes[index].is_ascii() { + return; + } + + let (before, after) = bytes.split_at(index); + + // UTF-8 takes at most 4 bytes per codepoint, so we don't + // need to check more than that. + let after = after.get(..4).unwrap_or(after); + match str_from_utf8(after) { + Ok(_) => return, + Err(err) if err.valid_up_to() != 0 => return, + Err(_) => (), + } + + for len in 2..=4.min(index) { + let before = &before[index - len..]; + if str_from_utf8(before).is_ok() { + return; + } + } + + panic!("byte index {index} is not an OsStr boundary"); + } + + let encoded_bytes = self.as_encoded_bytes(); + let Range { start, end } = slice::range(range, ..encoded_bytes.len()); + check_valid_boundary(encoded_bytes, start); + check_valid_boundary(encoded_bytes, end); + + // SAFETY: `slice::range` ensures that `start` and `end` are valid + let slice = unsafe { encoded_bytes.get_unchecked(start..end) }; + + // SAFETY: `slice` comes from `self` and we validated the boundaries + unsafe { Self::from_encoded_bytes_unchecked(slice) } + } + /// Converts this string to its ASCII lower case equivalent in-place. /// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs index d7926749aae20..2765398d3e690 100644 --- a/library/std/src/ffi/os_str/tests.rs +++ b/library/std/src/ffi/os_str/tests.rs @@ -177,3 +177,53 @@ fn into_rc() { assert_eq!(&*rc2, os_str); assert_eq!(&*arc2, os_str); } + +#[test] +fn slice_encoded_bytes() { + let os_str = OsStr::new("123θგ🦀"); + // ASCII + let digits = os_str.slice_encoded_bytes(..3); + assert_eq!(digits, "123"); + let three = os_str.slice_encoded_bytes(2..3); + assert_eq!(three, "3"); + // 2-byte UTF-8 + let theta = os_str.slice_encoded_bytes(3..5); + assert_eq!(theta, "θ"); + // 3-byte UTF-8 + let gani = os_str.slice_encoded_bytes(5..8); + assert_eq!(gani, "გ"); + // 4-byte UTF-8 + let crab = os_str.slice_encoded_bytes(8..); + assert_eq!(crab, "🦀"); +} + +#[test] +#[should_panic(expected = "byte index 2 is not an OsStr boundary")] +fn slice_mid_char() { + let crab = OsStr::new("🦀"); + let _ = crab.slice_encoded_bytes(..2); +} + +#[cfg(windows)] +#[test] +#[should_panic(expected = "byte index 3 is not an OsStr boundary")] +fn slice_between_surrogates() { + use crate::os::windows::ffi::OsStringExt; + + let os_string = OsString::from_wide(&[0xD800, 0xD800]); + assert_eq!(os_string.as_encoded_bytes(), &[0xED, 0xA0, 0x80, 0xED, 0xA0, 0x80]); + let _ = os_string.slice_encoded_bytes(..3); +} + +#[cfg(windows)] +#[test] +fn slice_surrogate_edge() { + use crate::os::windows::ffi::OsStringExt; + + let os_string = OsString::from_wide(&[0xD800]); + let mut with_crab = os_string.clone(); + with_crab.push("🦀"); + + assert_eq!(with_crab.slice_encoded_bytes(..3), os_string); + assert_eq!(with_crab.slice_encoded_bytes(3..), "🦀"); +} diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 61c3913361717..4310e10830380 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -189,7 +189,7 @@ pub struct OpenOptions(fs_imp::OpenOptions); /// Representation of the various timestamps on a file. #[derive(Copy, Clone, Debug, Default)] -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub struct FileTimes(fs_imp::FileTimes); /// Representation of the various permissions on a file. @@ -688,7 +688,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] #[doc(alias = "futimens")] #[doc(alias = "futimes")] #[doc(alias = "SetFileTime")] @@ -699,7 +699,7 @@ impl File { /// Changes the modification time of the underlying file. /// /// This is an alias for `set_times(FileTimes::new().set_modified(time))`. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] #[inline] pub fn set_modified(&self, time: SystemTime) -> io::Result<()> { self.set_times(FileTimes::new().set_modified(time)) @@ -1413,20 +1413,20 @@ impl FileTimes { /// Create a new `FileTimes` with no times set. /// /// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] pub fn new() -> Self { Self::default() } /// Set the last access time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] pub fn set_accessed(mut self, t: SystemTime) -> Self { self.0.set_accessed(t.into_inner()); self } /// Set the last modified time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] pub fn set_modified(mut self, t: SystemTime) -> Self { self.0.set_modified(t.into_inner()); self @@ -1440,7 +1440,7 @@ impl AsInnerMut for FileTimes { } // For implementing OS extension traits in `std::os` -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl Sealed for FileTimes {} impl Permissions { diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 547a7b7052f43..3b6fbf95faf20 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -74,7 +74,7 @@ macro_rules! error_contains { // tests most of the time, but at least we do if the user has the right // permissions. pub fn got_symlink_permission(tmpdir: &TempDir) -> bool { - if cfg!(unix) { + if cfg!(not(windows)) || env::var_os("CI").is_some() { return true; } let link = tmpdir.join("some_hopefully_unique_link_name"); diff --git a/library/std/src/hash/mod.rs b/library/std/src/hash/mod.rs new file mode 100644 index 0000000000000..bd9bbf298752e --- /dev/null +++ b/library/std/src/hash/mod.rs @@ -0,0 +1,91 @@ +//! Generic hashing support. +//! +//! This module provides a generic way to compute the [hash] of a value. +//! Hashes are most commonly used with [`HashMap`] and [`HashSet`]. +//! +//! [hash]: https://en.wikipedia.org/wiki/Hash_function +//! [`HashMap`]: ../../std/collections/struct.HashMap.html +//! [`HashSet`]: ../../std/collections/struct.HashSet.html +//! +//! The simplest way to make a type hashable is to use `#[derive(Hash)]`: +//! +//! # Examples +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! #[derive(Hash)] +//! struct Person { +//! id: u32, +//! name: String, +//! phone: u64, +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert!(calculate_hash(&person1) != calculate_hash(&person2)); +//! +//! fn calculate_hash(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +//! +//! If you need more control over how a value is hashed, you need to implement +//! the [`Hash`] trait: +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! struct Person { +//! id: u32, +//! # #[allow(dead_code)] +//! name: String, +//! phone: u64, +//! } +//! +//! impl Hash for Person { +//! fn hash(&self, state: &mut H) { +//! self.id.hash(state); +//! self.phone.hash(state); +//! } +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2)); +//! +//! fn calculate_hash(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +#![stable(feature = "rust1", since = "1.0.0")] + +pub(crate) mod random; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::hash::*; + +#[stable(feature = "std_hash_exports", since = "CURRENT_RUSTC_VERSION")] +pub use self::random::{DefaultHasher, RandomState}; diff --git a/library/std/src/hash/random.rs b/library/std/src/hash/random.rs new file mode 100644 index 0000000000000..a1ccbb25369bf --- /dev/null +++ b/library/std/src/hash/random.rs @@ -0,0 +1,161 @@ +//! This module exists to isolate [`RandomState`] and [`DefaultHasher`] outside of the +//! [`collections`] module without actually publicly exporting them, so that parts of that +//! implementation can more easily be moved to the [`alloc`] crate. +//! +//! Although its items are public and contain stability attributes, they can't actually be accessed +//! outside this crate. +//! +//! [`collections`]: crate::collections +#[allow(deprecated)] +use super::{BuildHasher, Hasher, SipHasher13}; +use crate::cell::Cell; +use crate::fmt; +use crate::sys; + +/// `RandomState` is the default state for [`HashMap`] types. +/// +/// A particular instance `RandomState` will create the same instances of +/// [`Hasher`], but the hashers created by two different `RandomState` +/// instances are unlikely to produce the same result for the same values. +/// +/// [`HashMap`]: crate::collections::HashMap +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use std::hash::RandomState; +/// +/// let s = RandomState::new(); +/// let mut map = HashMap::with_hasher(s); +/// map.insert(1, 2); +/// ``` +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +#[derive(Clone)] +pub struct RandomState { + k0: u64, + k1: u64, +} + +impl RandomState { + /// Constructs a new `RandomState` that is initialized with random keys. + /// + /// # Examples + /// + /// ``` + /// use std::hash::RandomState; + /// + /// let s = RandomState::new(); + /// ``` + #[inline] + #[allow(deprecated)] + // rand + #[must_use] + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub fn new() -> RandomState { + // Historically this function did not cache keys from the OS and instead + // simply always called `rand::thread_rng().gen()` twice. In #31356 it + // was discovered, however, that because we re-seed the thread-local RNG + // from the OS periodically that this can cause excessive slowdown when + // many hash maps are created on a thread. To solve this performance + // trap we cache the first set of randomly generated keys per-thread. + // + // Later in #36481 it was discovered that exposing a deterministic + // iteration order allows a form of DOS attack. To counter that we + // increment one of the seeds on every RandomState creation, giving + // every corresponding HashMap a different iteration order. + thread_local!(static KEYS: Cell<(u64, u64)> = { + Cell::new(sys::hashmap_random_keys()) + }); + + KEYS.with(|keys| { + let (k0, k1) = keys.get(); + keys.set((k0.wrapping_add(1), k1)); + RandomState { k0, k1 } + }) + } +} + +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +impl BuildHasher for RandomState { + type Hasher = DefaultHasher; + #[inline] + #[allow(deprecated)] + fn build_hasher(&self) -> DefaultHasher { + DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1)) + } +} + +/// The default [`Hasher`] used by [`RandomState`]. +/// +/// The internal algorithm is not specified, and so it and its hashes should +/// not be relied upon over releases. +#[allow(deprecated)] +#[derive(Clone, Debug)] +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +pub struct DefaultHasher(SipHasher13); + +impl DefaultHasher { + /// Creates a new `DefaultHasher`. + /// + /// This hasher is not guaranteed to be the same as all other + /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` + /// instances created through `new` or `default`. + #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] + #[inline] + #[allow(deprecated)] + #[rustc_const_unstable(feature = "const_hash", issue = "104061")] + #[must_use] + pub const fn new() -> DefaultHasher { + DefaultHasher(SipHasher13::new_with_keys(0, 0)) + } +} + +#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] +impl Default for DefaultHasher { + /// Creates a new `DefaultHasher` using [`new`]. + /// See its documentation for more. + /// + /// [`new`]: DefaultHasher::new + #[inline] + fn default() -> DefaultHasher { + DefaultHasher::new() + } +} + +#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] +impl Hasher for DefaultHasher { + // The underlying `SipHasher13` doesn't override the other + // `write_*` methods, so it's ok not to forward them here. + + #[inline] + fn write(&mut self, msg: &[u8]) { + self.0.write(msg) + } + + #[inline] + fn write_str(&mut self, s: &str) { + self.0.write_str(s); + } + + #[inline] + fn finish(&self) -> u64 { + self.0.finish() + } +} + +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +impl Default for RandomState { + /// Constructs a new `RandomState`. + #[inline] + fn default() -> RandomState { + RandomState::new() + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for RandomState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RandomState").finish_non_exhaustive() + } +} diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 55aafc3db330a..6c7494a6a6ff9 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -507,6 +507,16 @@ impl Seek for BufReader { ) }) } + + /// Seeks relative to the current position. + /// + /// If the new position lies within the buffer, the buffer will not be + /// flushed, allowing for more efficient seeks. This method does not return + /// the location of the underlying reader, so the caller must track this + /// information themselves if it is required. + fn seek_relative(&mut self, offset: i64) -> io::Result<()> { + self.seek_relative(offset) + } } impl SizeHint for BufReader { diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 57d226a3771e5..d49866345cbf6 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -255,48 +255,17 @@ impl BufferedWriterSpec for BufWriter { } } -impl BufferedWriterSpec for Vec { +impl BufferedWriterSpec for Vec { fn buffer_size(&self) -> usize { cmp::max(DEFAULT_BUF_SIZE, self.capacity() - self.len()) } fn copy_from(&mut self, reader: &mut R) -> Result { - let mut bytes = 0; - - // avoid allocating before we have determined that there's anything to read - if self.capacity() == 0 { - bytes = stack_buffer_copy(&mut reader.take(DEFAULT_BUF_SIZE as u64), self)?; - if bytes == 0 { - return Ok(0); - } - } - - loop { - self.reserve(DEFAULT_BUF_SIZE); - let mut buf: BorrowedBuf<'_> = self.spare_capacity_mut().into(); - match reader.read_buf(buf.unfilled()) { - Ok(()) => {} - Err(e) if e.is_interrupted() => continue, - Err(e) => return Err(e), - }; - - let read = buf.filled().len(); - if read == 0 { - break; - } - - // SAFETY: BorrowedBuf guarantees all of its filled bytes are init - // and the number of read bytes can't exceed the spare capacity since - // that's what the buffer is borrowing from. - unsafe { self.set_len(self.len() + read) }; - bytes += read as u64; - } - - Ok(bytes) + reader.read_to_end(self).map(|bytes| u64::try_from(bytes).expect("usize overflowed u64")) } } -fn stack_buffer_copy( +pub fn stack_buffer_copy( reader: &mut R, writer: &mut W, ) -> Result { diff --git a/library/std/src/io/copy/tests.rs b/library/std/src/io/copy/tests.rs index af137eaf856f5..a1f909a3c5386 100644 --- a/library/std/src/io/copy/tests.rs +++ b/library/std/src/io/copy/tests.rs @@ -82,13 +82,16 @@ fn copy_specializes_bufreader() { #[test] fn copy_specializes_to_vec() { - let cap = 123456; - let mut source = ShortReader { cap, observed_buffer: 0, read_size: 1337 }; + let cap = DEFAULT_BUF_SIZE * 10; + let mut source = ShortReader { cap, observed_buffer: 0, read_size: DEFAULT_BUF_SIZE }; let mut sink = Vec::new(); - assert_eq!(cap as u64, io::copy(&mut source, &mut sink).unwrap()); + let copied = io::copy(&mut source, &mut sink).unwrap(); + assert_eq!(cap as u64, copied); + assert_eq!(sink.len() as u64, copied); assert!( source.observed_buffer > DEFAULT_BUF_SIZE, - "expected a large buffer to be provided to the reader" + "expected a large buffer to be provided to the reader, got {}", + source.observed_buffer ); } diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index f438325560f54..d8c8d933eb403 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -476,7 +476,7 @@ impl Read for VecDeque { } /// BufRead is implemented for `VecDeque` by reading bytes from the front of the `VecDeque`. -#[stable(feature = "vecdeque_buf_read", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "vecdeque_buf_read", since = "1.75.0")] impl BufRead for VecDeque { /// Returns the contents of the "front" slice as returned by /// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are @@ -528,3 +528,17 @@ impl Write for VecDeque { Ok(()) } } + +#[unstable(feature = "read_buf", issue = "78485")] +impl<'a> io::Write for core::io::BorrowedCursor<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + let amt = cmp::min(buf.len(), self.capacity()); + self.append(&buf[..amt]); + Ok(amt) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index aa9a2482d2d92..e3aa973741f1f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -330,7 +330,7 @@ pub use self::{ }; #[unstable(feature = "read_buf", issue = "78485")] -pub use self::readbuf::{BorrowedBuf, BorrowedCursor}; +pub use core::io::{BorrowedBuf, BorrowedCursor}; pub(crate) use error::const_io_error; mod buffered; @@ -339,7 +339,6 @@ mod cursor; mod error; mod impls; pub mod prelude; -mod readbuf; mod stdio; mod util; @@ -398,12 +397,16 @@ where } } -// This uses an adaptive system to extend the vector when it fills. We want to -// avoid paying to allocate and zero a huge chunk of memory if the reader only -// has 4 bytes while still making large reads if the reader does have a ton -// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every -// time is 4,500 times (!) slower than a default reservation size of 32 if the -// reader has a very small amount of data to return. +// Here we must serve many masters with conflicting goals: +// +// - avoid allocating unless necessary +// - avoid overallocating if we know the exact size (#89165) +// - avoid passing large buffers to readers that always initialize the free capacity if they perform short reads (#23815, #23820) +// - pass large buffers to readers that do not initialize the spare capacity. this can amortize per-call overheads +// - and finally pass not-too-small and not-too-large buffers to Windows read APIs because they manage to suffer from both problems +// at the same time, i.e. small reads suffer from syscall overhead, all reads incur initialization cost +// proportional to buffer size (#110650) +// pub(crate) fn default_read_to_end( r: &mut R, buf: &mut Vec, @@ -413,20 +416,58 @@ pub(crate) fn default_read_to_end( let start_cap = buf.capacity(); // Optionally limit the maximum bytes read on each iteration. // This adds an arbitrary fiddle factor to allow for more data than we expect. - let max_read_size = - size_hint.and_then(|s| s.checked_add(1024)?.checked_next_multiple_of(DEFAULT_BUF_SIZE)); + let mut max_read_size = size_hint + .and_then(|s| s.checked_add(1024)?.checked_next_multiple_of(DEFAULT_BUF_SIZE)) + .unwrap_or(DEFAULT_BUF_SIZE); let mut initialized = 0; // Extra initialized bytes from previous loop iteration + + const PROBE_SIZE: usize = 32; + + fn small_probe_read(r: &mut R, buf: &mut Vec) -> Result { + let mut probe = [0u8; PROBE_SIZE]; + + loop { + match r.read(&mut probe) { + Ok(n) => { + buf.extend_from_slice(&probe[..n]); + return Ok(n); + } + Err(ref e) if e.is_interrupted() => continue, + Err(e) => return Err(e), + } + } + } + + // avoid inflating empty/small vecs before we have determined that there's anything to read + if (size_hint.is_none() || size_hint == Some(0)) && buf.capacity() - buf.len() < PROBE_SIZE { + let read = small_probe_read(r, buf)?; + + if read == 0 { + return Ok(0); + } + } + loop { + if buf.len() == buf.capacity() && buf.capacity() == start_cap { + // The buffer might be an exact fit. Let's read into a probe buffer + // and see if it returns `Ok(0)`. If so, we've avoided an + // unnecessary doubling of the capacity. But if not, append the + // probe buffer to the primary buffer and let its capacity grow. + let read = small_probe_read(r, buf)?; + + if read == 0 { + return Ok(buf.len() - start_len); + } + } + if buf.len() == buf.capacity() { - buf.reserve(32); // buf is full, need more space + buf.reserve(PROBE_SIZE); // buf is full, need more space } let mut spare = buf.spare_capacity_mut(); - if let Some(size) = max_read_size { - let len = cmp::min(spare.len(), size); - spare = &mut spare[..len] - } + let buf_len = cmp::min(spare.len(), max_read_size); + spare = &mut spare[..buf_len]; let mut read_buf: BorrowedBuf<'_> = spare.into(); // SAFETY: These bytes were initialized but not filled in the previous loop @@ -435,42 +476,44 @@ pub(crate) fn default_read_to_end( } let mut cursor = read_buf.unfilled(); - match r.read_buf(cursor.reborrow()) { - Ok(()) => {} - Err(e) if e.is_interrupted() => continue, - Err(e) => return Err(e), + loop { + match r.read_buf(cursor.reborrow()) { + Ok(()) => break, + Err(e) if e.is_interrupted() => continue, + Err(e) => return Err(e), + } } - if cursor.written() == 0 { + let unfilled_but_initialized = cursor.init_ref().len(); + let bytes_read = cursor.written(); + let was_fully_initialized = read_buf.init_len() == buf_len; + + if bytes_read == 0 { return Ok(buf.len() - start_len); } // store how much was initialized but not filled - initialized = cursor.init_ref().len(); + initialized = unfilled_but_initialized; // SAFETY: BorrowedBuf's invariants mean this much memory is initialized. unsafe { - let new_len = read_buf.filled().len() + buf.len(); + let new_len = bytes_read + buf.len(); buf.set_len(new_len); } - if buf.len() == buf.capacity() && buf.capacity() == start_cap { - // The buffer might be an exact fit. Let's read into a probe buffer - // and see if it returns `Ok(0)`. If so, we've avoided an - // unnecessary doubling of the capacity. But if not, append the - // probe buffer to the primary buffer and let its capacity grow. - let mut probe = [0u8; 32]; - - loop { - match r.read(&mut probe) { - Ok(0) => return Ok(buf.len() - start_len), - Ok(n) => { - buf.extend_from_slice(&probe[..n]); - break; - } - Err(ref e) if e.is_interrupted() => continue, - Err(e) => return Err(e), - } + // Use heuristics to determine the max read size if no initial size hint was provided + if size_hint.is_none() { + // The reader is returning short reads but it doesn't call ensure_init(). + // In that case we no longer need to restrict read sizes to avoid + // initialization costs. + if !was_fully_initialized { + max_read_size = usize::MAX; + } + + // we have passed a larger buffer than previously and the + // reader still hasn't returned a short read + if buf_len >= max_read_size && bytes_read == buf_len { + max_read_size = max_read_size.saturating_mul(2); } } } @@ -557,6 +600,10 @@ where /// therefore, using something that implements [`BufRead`], such as /// [`BufReader`], will be more efficient. /// +/// Repeated calls to the reader use the same cursor, so for example +/// calling `read_to_end` twice on a [`File`] will only return the file's +/// contents once. It's recommended to first call `rewind()` in that case. +/// /// # Examples /// /// [`File`]s implement `Read`: @@ -1958,6 +2005,36 @@ pub trait Seek { fn stream_position(&mut self) -> Result { self.seek(SeekFrom::Current(0)) } + + /// Seeks relative to the current position. + /// + /// This is equivalent to `self.seek(SeekFrom::Current(offset))` but + /// doesn't return the new position which can allow some implementations + /// such as [`BufReader`] to perform more efficient seeks. + /// + /// # Example + /// + /// ```no_run + /// #![feature(seek_seek_relative)] + /// use std::{ + /// io::{self, Seek}, + /// fs::File, + /// }; + /// + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// f.seek_relative(10)?; + /// assert_eq!(f.stream_position()?, 10); + /// Ok(()) + /// } + /// ``` + /// + /// [`BufReader`]: crate::io::BufReader + #[unstable(feature = "seek_seek_relative", issue = "117374")] + fn seek_relative(&mut self, offset: i64) -> Result<()> { + self.seek(SeekFrom::Current(offset))?; + Ok(()) + } } /// Enumeration of possible methods to seek within an I/O object. @@ -2015,6 +2092,28 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) -> R } } +fn skip_until(r: &mut R, delim: u8) -> Result { + let mut read = 0; + loop { + let (done, used) = { + let available = match r.fill_buf() { + Ok(n) => n, + Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + }; + match memchr::memchr(delim, available) { + Some(i) => (true, i + 1), + None => (false, available.len()), + } + }; + r.consume(used); + read += used; + if done || used == 0 { + return Ok(read); + } + } +} + /// A `BufRead` is a type of `Read`er which has an internal buffer, allowing it /// to perform extra ways of reading. /// @@ -2218,6 +2317,68 @@ pub trait BufRead: Read { read_until(self, byte, buf) } + /// Skip all bytes until the delimiter `byte` or EOF is reached. + /// + /// This function will read (and discard) bytes from the underlying stream until the + /// delimiter or EOF is found. + /// + /// If successful, this function will return the total number of bytes read, + /// including the delimiter byte. + /// + /// This is useful for efficiently skipping data such as NUL-terminated strings + /// in binary file formats without buffering. + /// + /// This function is blocking and should be used carefully: it is possible for + /// an attacker to continuously send bytes without ever sending the delimiter + /// or EOF. + /// + /// # Errors + /// + /// This function will ignore all instances of [`ErrorKind::Interrupted`] and + /// will otherwise return any errors returned by [`fill_buf`]. + /// + /// If an I/O error is encountered then all bytes read so far will be + /// present in `buf` and its length will have been adjusted appropriately. + /// + /// [`fill_buf`]: BufRead::fill_buf + /// + /// # Examples + /// + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to read some NUL-terminated information + /// about Ferris from a binary string, skipping the fun fact: + /// + /// ``` + /// #![feature(bufread_skip_until)] + /// + /// use std::io::{self, BufRead}; + /// + /// let mut cursor = io::Cursor::new(b"Ferris\0Likes long walks on the beach\0Crustacean\0"); + /// + /// // read name + /// let mut name = Vec::new(); + /// let num_bytes = cursor.read_until(b'\0', &mut name) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 7); + /// assert_eq!(name, b"Ferris\0"); + /// + /// // skip fun fact + /// let num_bytes = cursor.skip_until(b'\0') + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 30); + /// + /// // read animal type + /// let mut animal = Vec::new(); + /// let num_bytes = cursor.read_until(b'\0', &mut animal) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 11); + /// assert_eq!(animal, b"Crustacean\0"); + /// ``` + #[unstable(feature = "bufread_skip_until", issue = "111735")] + fn skip_until(&mut self, byte: u8) -> Result { + skip_until(self, byte) + } + /// Read all bytes until a newline (the `0xA` byte) is reached, and append /// them to the provided `String` buffer. /// diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 6d30f5e6c6c8d..bda5b721adc63 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -25,6 +25,36 @@ fn read_until() { assert_eq!(v, []); } +#[test] +fn skip_until() { + let bytes: &[u8] = b"read\0ignore\0read\0ignore\0read\0ignore\0"; + let mut reader = BufReader::new(bytes); + + // read from the bytes, alternating between + // consuming `read\0`s and skipping `ignore\0`s + loop { + // consume `read\0` + let mut out = Vec::new(); + let read = reader.read_until(0, &mut out).unwrap(); + if read == 0 { + // eof + break; + } else { + assert_eq!(out, b"read\0"); + assert_eq!(read, b"read\0".len()); + } + + // skip past `ignore\0` + let skipped = reader.skip_until(0).unwrap(); + assert_eq!(skipped, b"ignore\0".len()); + } + + // ensure we are at the end of the byte slice and that we can skip no further + // also ensure skip_until matches the behavior of read_until at EOF + let skipped = reader.skip_until(0).unwrap(); + assert_eq!(skipped, 0); +} + #[test] fn split() { let buf = Cursor::new(&b"12"[..]); diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f57c8d4e7e282..52b1fe822d6c2 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -227,7 +227,7 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![doc(rust_logo)] #![doc(cfg_hide( not(test), not(any(test, bootstrap)), @@ -310,12 +310,14 @@ // tidy-alphabetical-start #![feature(char_internals)] #![feature(core_intrinsics)] +#![feature(core_io_borrowed_buf)] #![feature(duration_constants)] #![feature(error_generic_member_access)] #![feature(error_in_core)] #![feature(error_iter)] #![feature(exact_size_is_empty)] #![feature(exclusive_wrapper)] +#![feature(exposed_provenance)] #![feature(extend_one)] #![feature(float_gamma)] #![feature(float_minimum_maximum)] @@ -335,10 +337,12 @@ #![feature(portable_simd)] #![feature(prelude_2024)] #![feature(ptr_as_uninit)] +#![feature(ptr_from_ref)] #![feature(raw_os_nonzero)] #![feature(round_ties_even)] #![feature(slice_internals)] #![feature(slice_ptr_get)] +#![feature(slice_range)] #![feature(std_internals)] #![feature(str_internals)] #![feature(strict_provenance)] @@ -493,8 +497,6 @@ pub use core::convert; pub use core::default; #[stable(feature = "futures_api", since = "1.36.0")] pub use core::future; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::hash; #[stable(feature = "core_hint", since = "1.27.0")] pub use core::hint; #[stable(feature = "i128", since = "1.26.0")] @@ -564,6 +566,7 @@ pub mod env; pub mod error; pub mod ffi; pub mod fs; +pub mod hash; pub mod io; pub mod net; pub mod num; @@ -582,9 +585,10 @@ pub mod time; #[unstable(feature = "portable_simd", issue = "86656")] mod std_float; -#[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] #[unstable(feature = "portable_simd", issue = "86656")] pub mod simd { + #![doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] + #[doc(inline)] pub use crate::std_float::StdFloat; #[doc(inline)] @@ -715,7 +719,7 @@ pub(crate) mod test_helpers { #[track_caller] pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = crate::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = crate::hash::RandomState::new().build_hasher(); core::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs index 0d2a7189032b7..e5df4de0b7f71 100644 --- a/library/std/src/os/ios/fs.rs +++ b/library/std/src/os/ios/fs.rs @@ -144,14 +144,14 @@ impl MetadataExt for Metadata { } /// OS-specific extensions to [`fs::FileTimes`]. -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub trait FileTimesExt: Sealed { /// Set the creation time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] fn set_created(self, t: SystemTime) -> Self; } -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl FileTimesExt for fs::FileTimes { fn set_created(mut self, t: SystemTime) -> Self { self.as_inner_mut().set_created(t.into_inner()); diff --git a/library/std/src/os/l4re/raw.rs b/library/std/src/os/l4re/raw.rs index 12c0293285a5e..8fb6e99ecfa1e 100644 --- a/library/std/src/os/l4re/raw.rs +++ b/library/std/src/os/l4re/raw.rs @@ -31,7 +31,6 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; target_arch = "powerpc", target_arch = "sparc", target_arch = "arm", - target_arch = "asmjs", target_arch = "wasm32" ))] mod arch { diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index 2b3ff76d7a4a7..51af432d0568d 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -152,6 +152,12 @@ pub trait CommandExt: Sealed { /// in a guaranteed race-free manner (e.g. if the `clone3` system call /// is supported). Otherwise, [`pidfd`] will return an error. /// + /// If a pidfd has been successfully created and not been taken from the `Child` + /// then calls to `kill()`, `wait()` and `try_wait()` will use the pidfd + /// instead of the pid. This can prevent pid recycling races, e.g. + /// those caused by rogue libraries in the same process prematurely reaping + /// zombie children via `waitpid(-1, ...)` calls. + /// /// [`Command`]: process::Command /// [`Child`]: process::Child /// [`pidfd`]: fn@ChildExt::pidfd diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs index a568f9b26baa9..c29dd62bc06f0 100644 --- a/library/std/src/os/linux/raw.rs +++ b/library/std/src/os/linux/raw.rs @@ -31,7 +31,6 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; target_arch = "powerpc", target_arch = "sparc", target_arch = "arm", - target_arch = "asmjs", target_arch = "wasm32" ))] mod arch { diff --git a/library/std/src/os/macos/fs.rs b/library/std/src/os/macos/fs.rs index 098b073372340..573426d1a8646 100644 --- a/library/std/src/os/macos/fs.rs +++ b/library/std/src/os/macos/fs.rs @@ -150,14 +150,14 @@ impl MetadataExt for Metadata { } /// OS-specific extensions to [`fs::FileTimes`]. -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub trait FileTimesExt: Sealed { /// Set the creation time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] fn set_created(self, t: SystemTime) -> Self; } -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl FileTimesExt for fs::FileTimes { fn set_created(mut self, t: SystemTime) -> Self { self.as_inner_mut().set_created(t.into_inner()); diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index f82034663d4e6..19b4fe22093c3 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -1,8 +1,55 @@ //! SOLID-specific extensions to general I/O primitives +//! +//! Just like raw pointers, raw SOLID Sockets file descriptors point to +//! resources with dynamic lifetimes, and they can dangle if they outlive their +//! resources or be forged if they're created from invalid values. +//! +//! This module provides three types for representing raw file descriptors +//! with different ownership properties: raw, borrowed, and owned, which are +//! analogous to types used for representing pointers: +//! +//! | Type | Analogous to | +//! | ------------------ | ------------ | +//! | [`RawFd`] | `*const _` | +//! | [`BorrowedFd<'a>`] | `&'a _` | +//! | [`OwnedFd`] | `Box<_>` | +//! +//! Like raw pointers, `RawFd` values are primitive values. And in new code, +//! they should be considered unsafe to do I/O on (analogous to dereferencing +//! them). Rust did not always provide this guidance, so existing code in the +//! Rust ecosystem often doesn't mark `RawFd` usage as unsafe. Once the +//! `io_safety` feature is stable, libraries will be encouraged to migrate, +//! either by adding `unsafe` to APIs that dereference `RawFd` values, or by +//! using to `BorrowedFd` or `OwnedFd` instead. +//! +//! Like references, `BorrowedFd` values are tied to a lifetime, to ensure +//! that they don't outlive the resource they point to. These are safe to +//! use. `BorrowedFd` values may be used in APIs which provide safe access to +//! any system call except for: +//! +//! - `close`, because that would end the dynamic lifetime of the resource +//! without ending the lifetime of the file descriptor. +//! +//! - `dup2`/`dup3`, in the second argument, because this argument is +//! closed and assigned a new resource, which may break the assumptions +//! other code using that file descriptor. +//! +//! `BorrowedFd` values may be used in APIs which provide safe access to `dup` +//! system calls, so types implementing `AsFd` or `From` should not +//! assume they always have exclusive access to the underlying file +//! description. +//! +//! Like boxes, `OwnedFd` values conceptually own the resource they point to, +//! and free (close) it when they are dropped. +//! +//! [`BorrowedFd<'a>`]: crate::os::solid::io::BorrowedFd #![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "solid_ext", issue = "none")] +use crate::fmt; +use crate::marker::PhantomData; +use crate::mem::forget; use crate::net; use crate::sys; use crate::sys_common::{self, AsInner, FromInner, IntoInner}; @@ -10,6 +57,253 @@ use crate::sys_common::{self, AsInner, FromInner, IntoInner}; /// Raw file descriptors. pub type RawFd = i32; +/// A borrowed SOLID Sockets file descriptor. +/// +/// This has a lifetime parameter to tie it to the lifetime of something that +/// owns the socket. +/// +/// This uses `repr(transparent)` and has the representation of a host file +/// descriptor, so it can be used in FFI in places where a socket is passed as +/// an argument, it is not captured or consumed, and it never has the value +/// `SOLID_NET_INVALID_FD`. +/// +/// This type's `.to_owned()` implementation returns another `BorrowedFd` +/// rather than an `OwnedFd`. It just makes a trivial copy of the raw +/// socket, which is then borrowed under the same lifetime. +#[derive(Copy, Clone)] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(0)] +// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`. +#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] +#[rustc_nonnull_optimization_guaranteed] +pub struct BorrowedFd<'socket> { + fd: RawFd, + _phantom: PhantomData<&'socket OwnedFd>, +} + +/// An owned SOLID Sockets file descriptor. +/// +/// This closes the file descriptor on drop. +/// +/// This uses `repr(transparent)` and has the representation of a host file +/// descriptor, so it can be used in FFI in places where a socket is passed as +/// an argument, it is not captured or consumed, and it never has the value +/// `SOLID_NET_INVALID_FD`. +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(0)] +// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`. +#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] +#[rustc_nonnull_optimization_guaranteed] +pub struct OwnedFd { + fd: RawFd, +} + +impl BorrowedFd<'_> { + /// Return a `BorrowedFd` holding the given raw file descriptor. + /// + /// # Safety + /// + /// The resource pointed to by `fd` must remain open for the duration of + /// the returned `BorrowedFd`, and it must not have the value + /// `SOLID_NET_INVALID_FD`. + #[inline] + pub const unsafe fn borrow_raw(fd: RawFd) -> Self { + assert!(fd != -1 as RawFd); + // SAFETY: we just asserted that the value is in the valid range and + // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) + unsafe { Self { fd, _phantom: PhantomData } } + } +} + +impl OwnedFd { + /// Creates a new `OwnedFd` instance that shares the same underlying file + /// description as the existing `OwnedFd` instance. + pub fn try_clone(&self) -> crate::io::Result { + self.as_fd().try_clone_to_owned() + } +} + +impl BorrowedFd<'_> { + /// Creates a new `OwnedFd` instance that shares the same underlying file + /// description as the existing `BorrowedFd` instance. + pub fn try_clone_to_owned(&self) -> crate::io::Result { + let fd = sys::net::cvt(unsafe { sys::net::netc::dup(self.as_raw_fd()) })?; + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) + } +} + +impl AsRawFd for BorrowedFd<'_> { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +impl AsRawFd for OwnedFd { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +impl IntoRawFd for OwnedFd { + #[inline] + fn into_raw_fd(self) -> RawFd { + let fd = self.fd; + forget(self); + fd + } +} + +impl FromRawFd for OwnedFd { + /// Constructs a new instance of `Self` from the given raw file descriptor. + /// + /// # Safety + /// + /// The resource pointed to by `fd` must be open and suitable for assuming + /// ownership. The resource must not require any cleanup other than `close`. + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> Self { + assert_ne!(fd, -1 as RawFd); + // SAFETY: we just asserted that the value is in the valid range and + // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) + unsafe { Self { fd } } + } +} + +impl Drop for OwnedFd { + #[inline] + fn drop(&mut self) { + unsafe { sys::net::netc::close(self.fd) }; + } +} + +impl fmt::Debug for BorrowedFd<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BorrowedFd").field("fd", &self.fd).finish() + } +} + +impl fmt::Debug for OwnedFd { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OwnedFd").field("fd", &self.fd).finish() + } +} + +macro_rules! impl_is_terminal { + ($($t:ty),*$(,)?) => {$( + #[unstable(feature = "sealed", issue = "none")] + impl crate::sealed::Sealed for $t {} + + #[stable(feature = "is_terminal", since = "1.70.0")] + impl crate::io::IsTerminal for $t { + #[inline] + fn is_terminal(&self) -> bool { + crate::sys::io::is_terminal(self) + } + } + )*} +} + +impl_is_terminal!(BorrowedFd<'_>, OwnedFd); + +/// A trait to borrow the SOLID Sockets file descriptor from an underlying +/// object. +pub trait AsFd { + /// Borrows the file descriptor. + fn as_fd(&self) -> BorrowedFd<'_>; +} + +impl AsFd for &T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +impl AsFd for &mut T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +impl AsFd for BorrowedFd<'_> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + *self + } +} + +impl AsFd for OwnedFd { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + // Safety: `OwnedFd` and `BorrowedFd` have the same validity + // invariants, and the `BorrowedFd` is bounded by the lifetime + // of `&self`. + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + +macro_rules! impl_owned_fd_traits { + ($($t:ident)*) => {$( + impl AsFd for net::$t { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + self.as_inner().socket().as_fd() + } + } + + impl From for OwnedFd { + #[inline] + fn from(socket: net::$t) -> OwnedFd { + socket.into_inner().into_socket().into_inner() + } + } + + impl From for net::$t { + #[inline] + fn from(owned_fd: OwnedFd) -> Self { + Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned_fd))) + } + } + )*}; +} +impl_owned_fd_traits! { TcpStream TcpListener UdpSocket } + +/// This impl allows implementing traits that require `AsFd` on Arc. +/// ``` +/// # #[cfg(target_os = "solid_asp3")] mod group_cfg { +/// # use std::os::solid::io::AsFd; +/// use std::net::UdpSocket; +/// use std::sync::Arc; +/// +/// trait MyTrait: AsFd {} +/// impl MyTrait for Arc {} +/// impl MyTrait for Box {} +/// # } +/// ``` +impl AsFd for crate::sync::Arc { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + (**self).as_fd() + } +} + +impl AsFd for crate::rc::Rc { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + (**self).as_fd() + } +} + +impl AsFd for Box { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + (**self).as_fd() + } +} + /// A trait to extract the raw SOLID Sockets file descriptor from an underlying /// object. pub trait AsRawFd { @@ -84,7 +378,7 @@ macro_rules! impl_as_raw_fd { impl AsRawFd for net::$t { #[inline] fn as_raw_fd(&self) -> RawFd { - *self.as_inner().socket().as_inner() + self.as_inner().socket().as_raw_fd() } } )*}; @@ -97,7 +391,7 @@ macro_rules! impl_from_raw_fd { impl FromRawFd for net::$t { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::$t { - let socket = sys::net::Socket::from_inner(fd); + let socket = unsafe { sys::net::Socket::from_raw_fd(fd) }; net::$t::from_inner(sys_common::net::$t::from_inner(socket)) } } @@ -111,7 +405,7 @@ macro_rules! impl_into_raw_fd { impl IntoRawFd for net::$t { #[inline] fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() + self.into_inner().into_socket().into_raw_fd() } } )*}; diff --git a/library/std/src/os/solid/mod.rs b/library/std/src/os/solid/mod.rs index 4328ba7c34022..0bb83c73ddf7c 100644 --- a/library/std/src/os/solid/mod.rs +++ b/library/std/src/os/solid/mod.rs @@ -13,5 +13,5 @@ pub mod prelude { pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use super::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; + pub use super::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; } diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs index 2838501817c2c..ee215dd598441 100644 --- a/library/std/src/os/watchos/fs.rs +++ b/library/std/src/os/watchos/fs.rs @@ -144,14 +144,14 @@ impl MetadataExt for Metadata { } /// OS-specific extensions to [`fs::FileTimes`]. -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub trait FileTimesExt: Sealed { /// Set the creation time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] fn set_created(self, t: SystemTime) -> Self; } -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl FileTimesExt for fs::FileTimes { fn set_created(mut self, t: SystemTime) -> Self { self.as_inner_mut().set_created(t.into_inner()); diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 3b591a35dd725..1b013d1c154c9 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -528,14 +528,14 @@ impl FileTypeExt for fs::FileType { } /// Windows-specific extensions to [`fs::FileTimes`]. -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub trait FileTimesExt: Sealed { /// Set the creation time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] fn set_created(self, t: SystemTime) -> Self; } -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl FileTimesExt for fs::FileTimes { fn set_created(mut self, t: SystemTime) -> Self { self.as_inner_mut().set_created(t.into_inner()); diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 274af08a3881c..b0540872c0b62 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -504,7 +504,7 @@ impl AsHandle for fs::File { impl From for OwnedHandle { #[inline] fn from(file: fs::File) -> OwnedHandle { - file.into_inner().into_inner().into_inner().into() + file.into_inner().into_inner().into_inner() } } diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index c80b9e28499bc..65f161f32e75f 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -127,7 +127,7 @@ impl BorrowedSocket<'_> { info.iAddressFamily, info.iSocketType, info.iProtocol, - &mut info, + &info, 0, sys::c::WSA_FLAG_OVERLAPPED | sys::c::WSA_FLAG_NO_HANDLE_INHERIT, ) @@ -147,7 +147,7 @@ impl BorrowedSocket<'_> { info.iAddressFamily, info.iSocketType, info.iProtocol, - &mut info, + &info, 0, sys::c::WSA_FLAG_OVERLAPPED, ) diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index d00e79476f382..5bf0154eae306 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -347,7 +347,7 @@ impl ChildExt for process::Child { /// /// This trait is sealed: it cannot be implemented outside the standard library. /// This is so that future additional methods are not breaking changes. -#[unstable(feature = "windows_process_exit_code_from", issue = "none")] +#[unstable(feature = "windows_process_exit_code_from", issue = "111688")] pub trait ExitCodeExt: Sealed { /// Creates a new `ExitCode` from the raw underlying `u32` return value of /// a process. @@ -355,11 +355,11 @@ pub trait ExitCodeExt: Sealed { /// The exit code should not be 259, as this conflicts with the `STILL_ACTIVE` /// macro returned from the `GetExitCodeProcess` function to signal that the /// process has yet to run to completion. - #[unstable(feature = "windows_process_exit_code_from", issue = "none")] + #[unstable(feature = "windows_process_exit_code_from", issue = "111688")] fn from_raw(raw: u32) -> Self; } -#[unstable(feature = "windows_process_exit_code_from", issue = "none")] +#[unstable(feature = "windows_process_exit_code_from", issue = "111688")] impl ExitCodeExt for process::ExitCode { fn from_raw(raw: u32) -> Self { process::ExitCode::from_inner(From::from(raw)) diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index f12ffbf2e0166..dbc0f7d9df35d 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1,8 +1,7 @@ use super::*; -use crate::collections::hash_map::DefaultHasher; use crate::collections::{BTreeSet, HashSet}; -use crate::hash::Hasher; +use crate::hash::{DefaultHasher, Hasher}; use crate::rc::Rc; use crate::sync::Arc; use core::hint::black_box; @@ -1461,8 +1460,7 @@ fn test_eq_receivers() { #[test] pub fn test_compare() { - use crate::collections::hash_map::DefaultHasher; - use crate::hash::{Hash, Hasher}; + use crate::hash::{DefaultHasher, Hash, Hasher}; fn hash(t: T) -> u64 { let mut s = DefaultHasher::new(); diff --git a/library/std/src/process.rs b/library/std/src/process.rs index ad29eeb6a0bed..6004ed51bd164 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1108,7 +1108,7 @@ impl fmt::Debug for Command { /// /// The default format approximates a shell invocation of the program along with its /// arguments. It does not include most of the other command properties. The output is not guaranteed to work - /// (e.g. due to lack of shell-escaping or differences in path resolution) + /// (e.g. due to lack of shell-escaping or differences in path resolution). /// On some platforms you can use [the alternate syntax] to show more fields. /// /// Note that the debug implementation is platform-specific. @@ -1961,7 +1961,7 @@ impl ExitCode { } /// The default value is [`ExitCode::SUCCESS`] -#[stable(feature = "process_exitcode_default", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "process_exitcode_default", since = "1.75.0")] impl Default for ExitCode { fn default() -> Self { ExitCode::SUCCESS diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index f4963090795db..b8873a3b59a0b 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -13,22 +13,65 @@ use crate::sync::Once; /// /// # Examples /// +/// Using `OnceCell` to store a function’s previously computed value (a.k.a. +/// ‘lazy static’ or ‘memoizing’): +/// /// ``` /// use std::sync::OnceLock; /// -/// static CELL: OnceLock = OnceLock::new(); +/// struct DeepThought { +/// answer: String, +/// } +/// +/// impl DeepThought { +/// # fn great_question() -> String { +/// # "42".to_string() +/// # } +/// # +/// fn new() -> Self { +/// Self { +/// // M3 Ultra takes about 16 million years in --release config +/// answer: Self::great_question(), +/// } +/// } +/// } +/// +/// fn computation() -> &'static DeepThought { +/// // n.b. static items do not call [`Drop`] on program termination, so if +/// // [`DeepThought`] impls Drop, that will not be used for this instance. +/// static COMPUTATION: OnceLock = OnceLock::new(); +/// COMPUTATION.get_or_init(|| DeepThought::new()) +/// } +/// +/// // The `DeepThought` is built, stored in the `OnceLock`, and returned. +/// let _ = computation().answer; +/// // The `DeepThought` is retrieved from the `OnceLock` and returned. +/// let _ = computation().answer; +/// ``` +/// +/// Writing to a `OnceLock` from a separate thread: +/// +/// ``` +/// use std::sync::OnceLock; +/// +/// static CELL: OnceLock = OnceLock::new(); +/// +/// // `OnceLock` has not been written to yet. /// assert!(CELL.get().is_none()); /// +/// // Spawn a thread and write to `OnceLock`. /// std::thread::spawn(|| { -/// let value: &String = CELL.get_or_init(|| { -/// "Hello, World!".to_string() -/// }); -/// assert_eq!(value, "Hello, World!"); -/// }).join().unwrap(); +/// let value = CELL.get_or_init(|| 12345); +/// assert_eq!(value, &12345); +/// }) +/// .join() +/// .unwrap(); /// -/// let value: Option<&String> = CELL.get(); -/// assert!(value.is_some()); -/// assert_eq!(value.unwrap().as_str(), "Hello, World!"); +/// // `OnceLock` now contains the value. +/// assert_eq!( +/// CELL.get(), +/// Some(&12345), +/// ); /// ``` #[stable(feature = "once_cell", since = "1.70.0")] pub struct OnceLock { diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index ac7c800ff6f8c..5d8967bfbe686 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -532,7 +532,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { } #[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for RwLockReadGuard<'_, T> { +impl fmt::Debug for RwLockReadGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } @@ -546,7 +546,7 @@ impl fmt::Display for RwLockReadGuard<'_, T> { } #[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for RwLockWriteGuard<'_, T> { +impl fmt::Debug for RwLockWriteGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs index d58aa6c27b8cd..b7357460f3931 100644 --- a/library/std/src/sys/common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -14,7 +14,6 @@ use crate::ptr; target_arch = "powerpc", target_arch = "powerpc64", target_arch = "sparc", - target_arch = "asmjs", target_arch = "wasm32", target_arch = "hexagon", all(target_arch = "riscv32", not(target_os = "espidf")), diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 159ffe7ac9635..88420bd3612c8 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -53,6 +53,9 @@ cfg_if::cfg_if! { } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { mod sgx; pub use self::sgx::*; + } else if #[cfg(target_os = "teeos")] { + mod teeos; + pub use self::teeos::*; } else { mod unsupported; pub use self::unsupported::*; diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs index 386a399f53228..0fff53f18875b 100644 --- a/library/std/src/sys/personality/mod.rs +++ b/library/std/src/sys/personality/mod.rs @@ -28,6 +28,7 @@ cfg_if::cfg_if! { } else if #[cfg(any( all(target_family = "windows", target_env = "gnu"), target_os = "psp", + target_os = "xous", target_os = "solid_asp3", all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re")), all(target_vendor = "fortanix", target_env = "sgx"), diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 1eae0fc0642b4..a768e2406c8a8 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -5,9 +5,10 @@ use crate::{ io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}, mem, net::{Shutdown, SocketAddr}, + os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd}, ptr, str, sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}, - sys_common::{AsInner, FromInner, IntoInner}, + sys_common::{FromInner, IntoInner}, time::Duration, }; @@ -28,102 +29,6 @@ const fn max_iov() -> usize { 1024 } -/// A file descriptor. -#[rustc_layout_scalar_valid_range_start(0)] -// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a -// 32-bit c_int. Below is -2, in two's complement, but that only works out -// because c_int is 32 bits. -#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] -struct FileDesc { - fd: c_int, -} - -impl FileDesc { - #[inline] - fn new(fd: c_int) -> FileDesc { - assert_ne!(fd, -1i32); - // Safety: we just asserted that the value is in the valid range and - // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - unsafe { FileDesc { fd } } - } - - #[inline] - fn raw(&self) -> c_int { - self.fd - } - - /// Extracts the actual file descriptor without closing it. - #[inline] - fn into_raw(self) -> c_int { - let fd = self.fd; - mem::forget(self); - fd - } - - fn read(&self, buf: &mut [u8]) -> io::Result { - let ret = cvt(unsafe { - netc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT)) - })?; - Ok(ret as usize) - } - - fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - let ret = cvt(unsafe { - netc::readv( - self.fd, - bufs.as_ptr() as *const netc::iovec, - cmp::min(bufs.len(), max_iov()) as c_int, - ) - })?; - Ok(ret as usize) - } - - #[inline] - fn is_read_vectored(&self) -> bool { - true - } - - fn write(&self, buf: &[u8]) -> io::Result { - let ret = cvt(unsafe { - netc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT)) - })?; - Ok(ret as usize) - } - - fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { - let ret = cvt(unsafe { - netc::writev( - self.fd, - bufs.as_ptr() as *const netc::iovec, - cmp::min(bufs.len(), max_iov()) as c_int, - ) - })?; - Ok(ret as usize) - } - - #[inline] - fn is_write_vectored(&self) -> bool { - true - } - - fn duplicate(&self) -> io::Result { - cvt(unsafe { netc::dup(self.fd) }).map(Self::new) - } -} - -impl AsInner for FileDesc { - #[inline] - fn as_inner(&self) -> &c_int { - &self.fd - } -} - -impl Drop for FileDesc { - fn drop(&mut self) { - unsafe { netc::close(self.fd) }; - } -} - #[doc(hidden)] pub trait IsMinusOne { fn is_minus_one(&self) -> bool; @@ -212,7 +117,7 @@ pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind { pub fn init() {} -pub struct Socket(FileDesc); +pub struct Socket(OwnedFd); impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { @@ -226,16 +131,13 @@ impl Socket { pub fn new_raw(fam: c_int, ty: c_int) -> io::Result { unsafe { let fd = cvt(netc::socket(fam, ty, 0))?; - let fd = FileDesc::new(fd); - let socket = Socket(fd); - - Ok(socket) + Ok(Self::from_raw_fd(fd)) } } pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { let (addr, len) = addr.into_inner(); - cvt(unsafe { netc::connect(self.0.raw(), addr.as_ptr(), len) })?; + cvt(unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; Ok(()) } @@ -264,14 +166,14 @@ impl Socket { timeout.tv_usec = 1; } - let fds = netc::fd_set { num_fds: 1, fds: [self.0.raw()] }; + let fds = netc::fd_set { num_fds: 1, fds: [self.as_raw_fd()] }; let mut writefds = fds; let mut errorfds = fds; let n = unsafe { cvt(netc::select( - self.0.raw() + 1, + self.as_raw_fd() + 1, ptr::null_mut(), &mut writefds, &mut errorfds, @@ -294,18 +196,17 @@ impl Socket { } pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result { - let fd = cvt_r(|| unsafe { netc::accept(self.0.raw(), storage, len) })?; - let fd = FileDesc::new(fd); - Ok(Socket(fd)) + let fd = cvt_r(|| unsafe { netc::accept(self.as_raw_fd(), storage, len) })?; + unsafe { Ok(Self::from_raw_fd(fd)) } } pub fn duplicate(&self) -> io::Result { - self.0.duplicate().map(Socket) + Ok(Self(self.0.try_clone()?)) } fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> { let ret = cvt(unsafe { - netc::recv(self.0.raw(), buf.as_mut().as_mut_ptr().cast(), buf.capacity(), flags) + netc::recv(self.as_raw_fd(), buf.as_mut().as_mut_ptr().cast(), buf.capacity(), flags) })?; unsafe { buf.advance(ret as usize); @@ -330,12 +231,19 @@ impl Socket { } pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - self.0.read_vectored(bufs) + let ret = cvt(unsafe { + netc::readv( + self.as_raw_fd(), + bufs.as_ptr() as *const netc::iovec, + cmp::min(bufs.len(), max_iov()) as c_int, + ) + })?; + Ok(ret as usize) } #[inline] pub fn is_read_vectored(&self) -> bool { - self.0.is_read_vectored() + true } fn recv_from_with_flags( @@ -348,7 +256,7 @@ impl Socket { let n = cvt(unsafe { netc::recvfrom( - self.0.raw(), + self.as_raw_fd(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags, @@ -368,16 +276,30 @@ impl Socket { } pub fn write(&self, buf: &[u8]) -> io::Result { - self.0.write(buf) + let ret = cvt(unsafe { + netc::write( + self.as_raw_fd(), + buf.as_ptr() as *const c_void, + cmp::min(buf.len(), READ_LIMIT), + ) + })?; + Ok(ret as usize) } pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { - self.0.write_vectored(bufs) + let ret = cvt(unsafe { + netc::writev( + self.as_raw_fd(), + bufs.as_ptr() as *const netc::iovec, + cmp::min(bufs.len(), max_iov()) as c_int, + ) + })?; + Ok(ret as usize) } #[inline] pub fn is_write_vectored(&self) -> bool { - self.0.is_write_vectored() + true } pub fn set_timeout(&self, dur: Option, kind: c_int) -> io::Result<()> { @@ -423,7 +345,7 @@ impl Socket { Shutdown::Read => netc::SHUT_RD, Shutdown::Both => netc::SHUT_RDWR, }; - cvt(unsafe { netc::shutdown(self.0.raw(), how) })?; + cvt(unsafe { netc::shutdown(self.as_raw_fd(), how) })?; Ok(()) } @@ -454,7 +376,7 @@ impl Socket { pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_int; cvt(unsafe { - netc::ioctl(*self.as_inner(), netc::FIONBIO, (&mut nonblocking) as *mut c_int as _) + netc::ioctl(self.as_raw_fd(), netc::FIONBIO, (&mut nonblocking) as *mut c_int as _) }) .map(drop) } @@ -466,25 +388,48 @@ impl Socket { // This method is used by sys_common code to abstract over targets. pub fn as_raw(&self) -> c_int { - *self.as_inner() + self.as_raw_fd() } } -impl AsInner for Socket { +impl FromInner for Socket { #[inline] - fn as_inner(&self) -> &c_int { - self.0.as_inner() + fn from_inner(sock: OwnedFd) -> Socket { + Socket(sock) } } -impl FromInner for Socket { - fn from_inner(fd: c_int) -> Socket { - Socket(FileDesc::new(fd)) +impl IntoInner for Socket { + #[inline] + fn into_inner(self) -> OwnedFd { + self.0 } } -impl IntoInner for Socket { - fn into_inner(self) -> c_int { - self.0.into_raw() +impl AsFd for Socket { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +impl AsRawFd for Socket { + #[inline] + fn as_raw_fd(&self) -> c_int { + self.0.as_raw_fd() + } +} + +impl FromRawFd for Socket { + #[inline] + unsafe fn from_raw_fd(fd: c_int) -> Socket { + unsafe { Self(FromRawFd::from_raw_fd(fd)) } + } +} + +impl IntoRawFd for Socket { + #[inline] + fn into_raw_fd(self) -> c_int { + self.0.into_raw_fd() } } diff --git a/library/std/src/sys/teeos/alloc.rs b/library/std/src/sys/teeos/alloc.rs new file mode 100644 index 0000000000000..e236819aa2388 --- /dev/null +++ b/library/std/src/sys/teeos/alloc.rs @@ -0,0 +1,57 @@ +use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::ptr; +use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + // jemalloc provides alignment less than MIN_ALIGN for small allocations. + // So only rely on MIN_ALIGN if size >= align. + // Also see and + // . + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + libc::malloc(layout.size()) as *mut u8 + } else { + aligned_malloc(&layout) + } + } + + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + // See the comment above in `alloc` for why this check looks the way it does. + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + libc::calloc(layout.size(), 1) as *mut u8 + } else { + let ptr = self.alloc(layout); + if !ptr.is_null() { + ptr::write_bytes(ptr, 0, layout.size()); + } + ptr + } + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { + libc::free(ptr as *mut libc::c_void) + } + + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= new_size { + libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 + } else { + realloc_fallback(self, ptr, layout, new_size) + } + } +} + +#[inline] +unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + let mut out = ptr::null_mut(); + // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. + // Since these are all powers of 2, we can just use max. + let align = layout.align().max(crate::mem::size_of::()); + let ret = libc::posix_memalign(&mut out, align, layout.size()); + if ret != 0 { ptr::null_mut() } else { out as *mut u8 } +} diff --git a/library/std/src/sys/teeos/locks/condvar.rs b/library/std/src/sys/teeos/locks/condvar.rs new file mode 100644 index 0000000000000..c08e8145b8c32 --- /dev/null +++ b/library/std/src/sys/teeos/locks/condvar.rs @@ -0,0 +1,100 @@ +use crate::cell::UnsafeCell; +use crate::ptr; +use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; +use crate::sys::locks::mutex::{self, Mutex}; +use crate::sys::time::TIMESPEC_MAX; +use crate::sys_common::lazy_box::{LazyBox, LazyInit}; +use crate::time::Duration; + +extern "C" { + pub fn pthread_cond_timedwait( + cond: *mut libc::pthread_cond_t, + lock: *mut libc::pthread_mutex_t, + adstime: *const libc::timespec, + ) -> libc::c_int; +} + +struct AllocatedCondvar(UnsafeCell); + +pub struct Condvar { + inner: LazyBox, + mutex: AtomicPtr, +} + +#[inline] +fn raw(c: &Condvar) -> *mut libc::pthread_cond_t { + c.inner.0.get() +} + +unsafe impl Send for AllocatedCondvar {} +unsafe impl Sync for AllocatedCondvar {} + +impl LazyInit for AllocatedCondvar { + fn init() -> Box { + let condvar = Box::new(AllocatedCondvar(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER))); + + let r = unsafe { libc::pthread_cond_init(condvar.0.get(), crate::ptr::null()) }; + assert_eq!(r, 0); + + condvar + } +} + +impl Drop for AllocatedCondvar { + #[inline] + fn drop(&mut self) { + let r = unsafe { libc::pthread_cond_destroy(self.0.get()) }; + debug_assert_eq!(r, 0); + } +} + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { inner: LazyBox::new(), mutex: AtomicPtr::new(ptr::null_mut()) } + } + + #[inline] + fn verify(&self, mutex: *mut libc::pthread_mutex_t) { + match self.mutex.compare_exchange(ptr::null_mut(), mutex, Relaxed, Relaxed) { + Ok(_) => {} // Stored the address + Err(n) if n == mutex => {} // Lost a race to store the same address + _ => panic!("attempted to use a condition variable with two mutexes"), + } + } + + #[inline] + pub fn notify_one(&self) { + let r = unsafe { libc::pthread_cond_signal(raw(self)) }; + debug_assert_eq!(r, 0); + } + + #[inline] + pub fn notify_all(&self) { + let r = unsafe { libc::pthread_cond_broadcast(raw(self)) }; + debug_assert_eq!(r, 0); + } + + #[inline] + pub unsafe fn wait(&self, mutex: &Mutex) { + let mutex = mutex::raw(mutex); + self.verify(mutex); + let r = libc::pthread_cond_wait(raw(self), mutex); + debug_assert_eq!(r, 0); + } + + pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + use crate::sys::time::Timespec; + + let mutex = mutex::raw(mutex); + self.verify(mutex); + + let timeout = Timespec::now(libc::CLOCK_MONOTONIC) + .checked_add_duration(&dur) + .and_then(|t| t.to_timespec()) + .unwrap_or(TIMESPEC_MAX); + + let r = pthread_cond_timedwait(raw(self), mutex, &timeout); + assert!(r == libc::ETIMEDOUT || r == 0); + r == 0 + } +} diff --git a/library/std/src/sys/teeos/locks/mod.rs b/library/std/src/sys/teeos/locks/mod.rs new file mode 100644 index 0000000000000..c58e9c7fd4541 --- /dev/null +++ b/library/std/src/sys/teeos/locks/mod.rs @@ -0,0 +1,8 @@ +pub mod condvar; +#[path = "../../unix/locks/pthread_mutex.rs"] +pub mod mutex; +pub mod rwlock; + +pub(crate) use condvar::Condvar; +pub(crate) use mutex::Mutex; +pub(crate) use rwlock::RwLock; diff --git a/library/std/src/sys/teeos/locks/rwlock.rs b/library/std/src/sys/teeos/locks/rwlock.rs new file mode 100644 index 0000000000000..27cdb88788fc3 --- /dev/null +++ b/library/std/src/sys/teeos/locks/rwlock.rs @@ -0,0 +1,44 @@ +use crate::sys::locks::mutex::Mutex; + +/// we do not supported rwlock, so use mutex to simulate rwlock. +/// it's useful because so many code in std will use rwlock. +pub struct RwLock { + inner: Mutex, +} + +impl RwLock { + #[inline] + pub const fn new() -> RwLock { + RwLock { inner: Mutex::new() } + } + + #[inline] + pub fn read(&self) { + unsafe { self.inner.lock() }; + } + + #[inline] + pub fn try_read(&self) -> bool { + unsafe { self.inner.try_lock() } + } + + #[inline] + pub fn write(&self) { + unsafe { self.inner.lock() }; + } + + #[inline] + pub unsafe fn try_write(&self) -> bool { + unsafe { self.inner.try_lock() } + } + + #[inline] + pub unsafe fn read_unlock(&self) { + unsafe { self.inner.unlock() }; + } + + #[inline] + pub unsafe fn write_unlock(&self) { + unsafe { self.inner.unlock() }; + } +} diff --git a/library/std/src/sys/teeos/mod.rs b/library/std/src/sys/teeos/mod.rs new file mode 100644 index 0000000000000..ed8c54b2c36fb --- /dev/null +++ b/library/std/src/sys/teeos/mod.rs @@ -0,0 +1,167 @@ +//! System bindings for the Teeos platform +//! +//! This module contains the facade (aka platform-specific) implementations of +//! OS level functionality for Teeos. +#![allow(unsafe_op_in_unsafe_fn)] +#![allow(unused_variables)] +#![allow(dead_code)] + +pub use self::rand::hashmap_random_keys; + +pub mod alloc; +#[path = "../unsupported/args.rs"] +pub mod args; +#[path = "../unix/cmath.rs"] +pub mod cmath; +#[path = "../unsupported/env.rs"] +pub mod env; +pub mod locks; +//pub mod fd; +#[path = "../unsupported/fs.rs"] +pub mod fs; +#[path = "../unsupported/io.rs"] +pub mod io; +#[path = "../unix/memchr.rs"] +pub mod memchr; +pub mod net; +#[path = "../unsupported/once.rs"] +pub mod once; +pub mod os; +#[path = "../unix/os_str.rs"] +pub mod os_str; +#[path = "../unix/path.rs"] +pub mod path; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +#[path = "../unsupported/process.rs"] +pub mod process; +mod rand; +pub mod stdio; +pub mod thread; +pub mod thread_local_dtor; +#[path = "../unix/thread_local_key.rs"] +pub mod thread_local_key; +#[path = "../unsupported/thread_parking.rs"] +pub mod thread_parking; +#[allow(non_upper_case_globals)] +#[path = "../unix/time.rs"] +pub mod time; + +use crate::io::ErrorKind; + +pub fn abort_internal() -> ! { + unsafe { libc::abort() } +} + +// Trusted Applications are loaded as dynamic libraries on Teeos, +// so this should never be called. +pub fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {} + +// SAFETY: must be called only once during runtime cleanup. +// this is not guaranteed to run, for example when the program aborts. +pub unsafe fn cleanup() { + unimplemented!() + // We do NOT have stack overflow handler, because TEE OS will kill TA when it happens. + // So cleanup is commented + // stack_overflow::cleanup(); +} + +#[inline] +pub(crate) fn is_interrupted(errno: i32) -> bool { + errno == libc::EINTR +} + +// Note: code below is 1:1 copied from unix/mod.rs +pub fn decode_error_kind(errno: i32) -> ErrorKind { + use ErrorKind::*; + match errno as libc::c_int { + libc::E2BIG => ArgumentListTooLong, + libc::EADDRINUSE => AddrInUse, + libc::EADDRNOTAVAIL => AddrNotAvailable, + libc::EBUSY => ResourceBusy, + libc::ECONNABORTED => ConnectionAborted, + libc::ECONNREFUSED => ConnectionRefused, + libc::ECONNRESET => ConnectionReset, + libc::EDEADLK => Deadlock, + libc::EDQUOT => FilesystemQuotaExceeded, + libc::EEXIST => AlreadyExists, + libc::EFBIG => FileTooLarge, + libc::EHOSTUNREACH => HostUnreachable, + libc::EINTR => Interrupted, + libc::EINVAL => InvalidInput, + libc::EISDIR => IsADirectory, + libc::ELOOP => FilesystemLoop, + libc::ENOENT => NotFound, + libc::ENOMEM => OutOfMemory, + libc::ENOSPC => StorageFull, + libc::ENOSYS => Unsupported, + libc::EMLINK => TooManyLinks, + libc::ENAMETOOLONG => InvalidFilename, + libc::ENETDOWN => NetworkDown, + libc::ENETUNREACH => NetworkUnreachable, + libc::ENOTCONN => NotConnected, + libc::ENOTDIR => NotADirectory, + libc::ENOTEMPTY => DirectoryNotEmpty, + libc::EPIPE => BrokenPipe, + libc::EROFS => ReadOnlyFilesystem, + libc::ESPIPE => NotSeekable, + libc::ESTALE => StaleNetworkFileHandle, + libc::ETIMEDOUT => TimedOut, + libc::ETXTBSY => ExecutableFileBusy, + libc::EXDEV => CrossesDevices, + + libc::EACCES | libc::EPERM => PermissionDenied, + + // These two constants can have the same value on some systems, + // but different values on others, so we can't use a match + // clause + x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock, + + _ => Uncategorized, + } +} + +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +pub fn cvt(t: T) -> crate::io::Result { + if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) } +} + +pub fn cvt_r(mut f: F) -> crate::io::Result +where + T: IsMinusOne, + F: FnMut() -> T, +{ + loop { + match cvt(f()) { + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + other => return other, + } + } +} + +pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> { + if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) } +} + +use crate::io as std_io; +pub fn unsupported() -> std_io::Result { + Err(unsupported_err()) +} + +pub fn unsupported_err() -> std_io::Error { + std_io::Error::new(std_io::ErrorKind::Unsupported, "operation not supported on this platform") +} diff --git a/library/std/src/sys/teeos/net.rs b/library/std/src/sys/teeos/net.rs new file mode 100644 index 0000000000000..0df681dbfa552 --- /dev/null +++ b/library/std/src/sys/teeos/net.rs @@ -0,0 +1,372 @@ +use crate::fmt; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; +use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::sys::unsupported; +use crate::time::Duration; + +pub struct TcpStream(!); + +impl TcpStream { + pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { + unsupported() + } + + pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result { + unsupported() + } + + pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { + self.0 + } + + pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { + self.0 + } + + pub fn read_timeout(&self) -> io::Result> { + self.0 + } + + pub fn write_timeout(&self) -> io::Result> { + self.0 + } + + pub fn peek(&self, _: &mut [u8]) -> io::Result { + self.0 + } + + pub fn read(&self, _: &mut [u8]) -> io::Result { + self.0 + } + + pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> { + self.0 + } + + pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result { + self.0 + } + + pub fn is_read_vectored(&self) -> bool { + self.0 + } + + pub fn write(&self, _: &[u8]) -> io::Result { + self.0 + } + + pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result { + self.0 + } + + pub fn is_write_vectored(&self) -> bool { + self.0 + } + + pub fn peer_addr(&self) -> io::Result { + self.0 + } + + pub fn socket_addr(&self) -> io::Result { + self.0 + } + + pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { + self.0 + } + + pub fn duplicate(&self) -> io::Result { + self.0 + } + + pub fn set_linger(&self, _: Option) -> io::Result<()> { + self.0 + } + + pub fn linger(&self) -> io::Result> { + self.0 + } + + pub fn set_nodelay(&self, _: bool) -> io::Result<()> { + self.0 + } + + pub fn nodelay(&self) -> io::Result { + self.0 + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + self.0 + } + + pub fn ttl(&self) -> io::Result { + self.0 + } + + pub fn take_error(&self) -> io::Result> { + self.0 + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + self.0 + } +} + +impl fmt::Debug for TcpStream { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0 + } +} + +pub struct TcpListener(!); + +impl TcpListener { + pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + unsupported() + } + + pub fn socket_addr(&self) -> io::Result { + self.0 + } + + pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { + self.0 + } + + pub fn duplicate(&self) -> io::Result { + self.0 + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + self.0 + } + + pub fn ttl(&self) -> io::Result { + self.0 + } + + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { + self.0 + } + + pub fn only_v6(&self) -> io::Result { + self.0 + } + + pub fn take_error(&self) -> io::Result> { + self.0 + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + self.0 + } +} + +impl fmt::Debug for TcpListener { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0 + } +} + +pub struct UdpSocket(!); + +impl UdpSocket { + pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { + unsupported() + } + + pub fn peer_addr(&self) -> io::Result { + self.0 + } + + pub fn socket_addr(&self) -> io::Result { + self.0 + } + + pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.0 + } + + pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.0 + } + + pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { + self.0 + } + + pub fn duplicate(&self) -> io::Result { + self.0 + } + + pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { + self.0 + } + + pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { + self.0 + } + + pub fn read_timeout(&self) -> io::Result> { + self.0 + } + + pub fn write_timeout(&self) -> io::Result> { + self.0 + } + + pub fn set_broadcast(&self, _: bool) -> io::Result<()> { + self.0 + } + + pub fn broadcast(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { + self.0 + } + + pub fn multicast_loop_v4(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { + self.0 + } + + pub fn multicast_ttl_v4(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { + self.0 + } + + pub fn multicast_loop_v6(&self) -> io::Result { + self.0 + } + + pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { + self.0 + } + + pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { + self.0 + } + + pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { + self.0 + } + + pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { + self.0 + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + self.0 + } + + pub fn ttl(&self) -> io::Result { + self.0 + } + + pub fn take_error(&self) -> io::Result> { + self.0 + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + self.0 + } + + pub fn recv(&self, _: &mut [u8]) -> io::Result { + self.0 + } + + pub fn peek(&self, _: &mut [u8]) -> io::Result { + self.0 + } + + pub fn send(&self, _: &[u8]) -> io::Result { + self.0 + } + + pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { + self.0 + } +} + +impl fmt::Debug for UdpSocket { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0 + } +} + +pub struct LookupHost(!); + +impl LookupHost { + pub fn port(&self) -> u16 { + self.0 + } +} + +impl Iterator for LookupHost { + type Item = SocketAddr; + fn next(&mut self) -> Option { + self.0 + } +} + +impl TryFrom<&str> for LookupHost { + type Error = io::Error; + + fn try_from(_v: &str) -> io::Result { + unsupported() + } +} + +impl<'a> TryFrom<(&'a str, u16)> for LookupHost { + type Error = io::Error; + + fn try_from(_v: (&'a str, u16)) -> io::Result { + unsupported() + } +} + +#[allow(nonstandard_style)] +pub mod netc { + pub const AF_INET: u8 = 0; + pub const AF_INET6: u8 = 1; + pub type sa_family_t = u8; + + #[derive(Copy, Clone)] + pub struct in_addr { + pub s_addr: u32, + } + + #[derive(Copy, Clone)] + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: u16, + pub sin_addr: in_addr, + } + + #[derive(Copy, Clone)] + pub struct in6_addr { + pub s6_addr: [u8; 16], + } + + #[derive(Copy, Clone)] + pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: u16, + pub sin6_addr: in6_addr, + pub sin6_flowinfo: u32, + pub sin6_scope_id: u32, + } + + #[derive(Copy, Clone)] + pub struct sockaddr {} +} + +pub type Socket = UdpSocket; diff --git a/library/std/src/sys/teeos/os.rs b/library/std/src/sys/teeos/os.rs new file mode 100644 index 0000000000000..e54a92f01f86b --- /dev/null +++ b/library/std/src/sys/teeos/os.rs @@ -0,0 +1,134 @@ +//! Implementation of `std::os` functionality for teeos + +use core::marker::PhantomData; + +use crate::error::Error as StdError; +use crate::ffi::{OsStr, OsString}; +use crate::fmt; +use crate::io; +use crate::path; +use crate::path::PathBuf; + +use super::unsupported; + +pub fn errno() -> i32 { + unsafe { (*libc::__errno_location()) as i32 } +} + +// Hardcoded to return 4096, since `sysconf` is only implemented as a stub. +pub fn page_size() -> usize { + // unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }; + 4096 +} + +// Everything below are stubs and copied from unsupported.rs + +pub fn error_string(_errno: i32) -> String { + "error string unimplemented".to_string() +} + +pub fn getcwd() -> io::Result { + unsupported() +} + +pub fn chdir(_: &path::Path) -> io::Result<()> { + unsupported() +} + +pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); + +pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { + panic!("unsupported") +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = PathBuf; + fn next(&mut self) -> Option { + self.0 + } +} + +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths(_paths: I) -> Result +where + I: Iterator, + T: AsRef, +{ + Err(JoinPathsError) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "not supported on this platform yet".fmt(f) + } +} + +impl StdError for JoinPathsError { + #[allow(deprecated)] + fn description(&self) -> &str { + "not supported on this platform yet" + } +} + +pub fn current_exe() -> io::Result { + unsupported() +} + +pub struct Env(!); + +impl Env { + // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self(inner) = self; + match *inner {} + } +} + +impl fmt::Debug for Env { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self(inner) = self; + match *inner {} + } +} + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + let Self(inner) = self; + match *inner {} + } +} + +pub fn env() -> Env { + panic!("not supported on this platform") +} + +pub fn getenv(_: &OsStr) -> Option { + None +} + +pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) +} + +pub fn unsetenv(_: &OsStr) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) +} + +pub fn temp_dir() -> PathBuf { + panic!("no filesystem on this platform") +} + +pub fn home_dir() -> Option { + None +} + +pub fn exit(_code: i32) -> ! { + panic!("TA should not call `exit`") +} + +pub fn getpid() -> u32 { + panic!("no pids on this platform") +} diff --git a/library/std/src/sys/teeos/rand.rs b/library/std/src/sys/teeos/rand.rs new file mode 100644 index 0000000000000..b45c3bb40e782 --- /dev/null +++ b/library/std/src/sys/teeos/rand.rs @@ -0,0 +1,21 @@ +pub fn hashmap_random_keys() -> (u64, u64) { + const KEY_LEN: usize = core::mem::size_of::(); + + let mut v = [0u8; KEY_LEN * 2]; + imp::fill_bytes(&mut v); + + let key1 = v[0..KEY_LEN].try_into().unwrap(); + let key2 = v[KEY_LEN..].try_into().unwrap(); + + (u64::from_ne_bytes(key1), u64::from_ne_bytes(key2)) +} + +mod imp { + extern "C" { + fn TEE_GenerateRandom(randomBuffer: *mut core::ffi::c_void, randomBufferLen: libc::size_t); + } + + pub fn fill_bytes(v: &mut [u8]) { + unsafe { TEE_GenerateRandom(v.as_mut_ptr() as _, v.len() * crate::mem::size_of::()) } + } +} diff --git a/library/std/src/sys/teeos/stdio.rs b/library/std/src/sys/teeos/stdio.rs new file mode 100644 index 0000000000000..9ca04f2927323 --- /dev/null +++ b/library/std/src/sys/teeos/stdio.rs @@ -0,0 +1,88 @@ +#![deny(unsafe_op_in_unsafe_fn)] + +use crate::io; +use core::arch::asm; + +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; + +const KCALL_DEBUG_CMD_PUT_BYTES: i64 = 2; + +unsafe fn debug_call(cap_ref: u64, call_no: i64, arg1: u64, arg2: u64) -> i32 { + let ret: u64; + unsafe { + asm!( + "svc #99", + inout("x0") cap_ref => ret, + in("x1") call_no, + in("x2") arg1, + in("x3") arg2, + ); + } + + ret as i32 +} + +fn print_buf(s: &[u8]) -> io::Result { + // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`. + const MAX_LEN: usize = 512; + let len = if s.len() > MAX_LEN { MAX_LEN } else { s.len() }; + let result = unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, s.as_ptr() as u64, len as u64) }; + + if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) } +} + +impl Stdin { + pub const fn new() -> Stdin { + Stdin + } +} + +impl io::Read for Stdin { + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + Ok(0) + } +} + +impl Stdout { + pub const fn new() -> Stdout { + Stdout + } +} + +impl io::Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + print_buf(buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Stderr { + pub const fn new() -> Stderr { + Stderr + } +} + +impl io::Write for Stderr { + fn write(&mut self, buf: &[u8]) -> io::Result { + print_buf(buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +pub const STDIN_BUF_SIZE: usize = 0; + +pub fn is_ebadf(err: &io::Error) -> bool { + err.raw_os_error() == Some(libc::EBADF as i32) +} + +pub fn panic_output() -> Option { + Some(Stderr::new()) +} diff --git a/library/std/src/sys/teeos/thread.rs b/library/std/src/sys/teeos/thread.rs new file mode 100644 index 0000000000000..155f333f90616 --- /dev/null +++ b/library/std/src/sys/teeos/thread.rs @@ -0,0 +1,164 @@ +use core::convert::TryInto; + +use crate::cmp; +use crate::ffi::CStr; +use crate::io; +use crate::mem; +use crate::num::NonZeroUsize; +use crate::ptr; +use crate::sys::os; +use crate::time::Duration; + +pub const DEFAULT_MIN_STACK_SIZE: usize = 8 * 1024; + +pub struct Thread { + id: libc::pthread_t, +} + +// Some platforms may have pthread_t as a pointer in which case we still want +// a thread to be Send/Sync +unsafe impl Send for Thread {} +unsafe impl Sync for Thread {} + +extern "C" { + pub fn TEE_Wait(timeout: u32) -> u32; +} + +impl Thread { + // unsafe: see thread::Builder::spawn_unchecked for safety requirements + pub unsafe fn new(stack: usize, p: Box) -> io::Result { + let p = Box::into_raw(Box::new(p)); + let mut native: libc::pthread_t = mem::zeroed(); + let mut attr: libc::pthread_attr_t = mem::zeroed(); + assert_eq!(libc::pthread_attr_init(&mut attr), 0); + assert_eq!( + libc::pthread_attr_settee( + &mut attr, + libc::TEESMP_THREAD_ATTR_CA_INHERIT, + libc::TEESMP_THREAD_ATTR_TASK_ID_INHERIT, + libc::TEESMP_THREAD_ATTR_HAS_SHADOW, + ), + 0, + ); + + let stack_size = cmp::max(stack, min_stack_size(&attr)); + + match libc::pthread_attr_setstacksize(&mut attr, stack_size) { + 0 => {} + n => { + assert_eq!(n, libc::EINVAL); + // EINVAL means |stack_size| is either too small or not a + // multiple of the system page size. Because it's definitely + // >= PTHREAD_STACK_MIN, it must be an alignment issue. + // Round up to the nearest page and try again. + let page_size = os::page_size(); + let stack_size = + (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); + assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0); + } + }; + + let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); + // Note: if the thread creation fails and this assert fails, then p will + // be leaked. However, an alternative design could cause double-free + // which is clearly worse. + assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); + + return if ret != 0 { + // The thread failed to start and as a result p was not consumed. Therefore, it is + // safe to reconstruct the box so that it gets deallocated. + drop(Box::from_raw(p)); + Err(io::Error::from_raw_os_error(ret)) + } else { + // The new thread will start running earliest after the next yield. + // We add a yield here, so that the user does not have to. + Thread::yield_now(); + Ok(Thread { id: native }) + }; + + extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void { + unsafe { + // Next, set up our stack overflow handler which may get triggered if we run + // out of stack. + // this is not necessary in TEE. + //let _handler = stack_overflow::Handler::new(); + // Finally, let's run some code. + Box::from_raw(main as *mut Box)(); + } + ptr::null_mut() + } + } + + pub fn yield_now() { + let ret = unsafe { libc::sched_yield() }; + debug_assert_eq!(ret, 0); + } + + /// This does not do anything on teeos + pub fn set_name(_name: &CStr) { + // Both pthread_setname_np and prctl are not available to the TA, + // so we can't implement this currently. If the need arises please + // contact the teeos rustzone team. + } + + /// only main thread could wait for sometime in teeos + pub fn sleep(dur: Duration) { + let sleep_millis = dur.as_millis(); + let final_sleep: u32 = + if sleep_millis >= u32::MAX as u128 { u32::MAX } else { sleep_millis as u32 }; + unsafe { + let _ = TEE_Wait(final_sleep); + } + } + + /// must join, because no pthread_detach supported + pub fn join(self) { + unsafe { + let ret = libc::pthread_join(self.id, ptr::null_mut()); + mem::forget(self); + assert!(ret == 0, "failed to join thread: {}", io::Error::from_raw_os_error(ret)); + } + } + + pub fn id(&self) -> libc::pthread_t { + self.id + } + + pub fn into_id(self) -> libc::pthread_t { + let id = self.id; + mem::forget(self); + id + } +} + +impl Drop for Thread { + fn drop(&mut self) { + // we can not call detach, so just panic if thread spawn without join + panic!("thread must join, detach is not supported!"); + } +} + +// Note: Both `sched_getaffinity` and `sysconf` are available but not functional on +// teeos, so this function always returns an Error! +pub fn available_parallelism() -> io::Result { + Err(io::Error::new( + io::ErrorKind::NotFound, + "The number of hardware threads is not known for the target platform", + )) +} + +// stub +pub mod guard { + use crate::ops::Range; + pub type Guard = Range; + pub unsafe fn current() -> Option { + None + } + pub unsafe fn init() -> Option { + None + } +} + +fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { + libc::PTHREAD_STACK_MIN.try_into().expect("Infallible") +} diff --git a/library/std/src/sys/teeos/thread_local_dtor.rs b/library/std/src/sys/teeos/thread_local_dtor.rs new file mode 100644 index 0000000000000..5c6bc4d675011 --- /dev/null +++ b/library/std/src/sys/teeos/thread_local_dtor.rs @@ -0,0 +1,4 @@ +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { + use crate::sys_common::thread_local_dtor::register_dtor_fallback; + register_dtor_fallback(t, dtor); +} diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs index 3bb492fa98bcf..3d4ba509829d3 100644 --- a/library/std/src/sys/unix/env.rs +++ b/library/std/src/sys/unix/env.rs @@ -174,17 +174,6 @@ pub mod os { pub const EXE_EXTENSION: &str = "elf"; } -#[cfg(all(target_os = "emscripten", target_arch = "asmjs"))] -pub mod os { - pub const FAMILY: &str = "unix"; - pub const OS: &str = "emscripten"; - pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".so"; - pub const DLL_EXTENSION: &str = "so"; - pub const EXE_SUFFIX: &str = ".js"; - pub const EXE_EXTENSION: &str = "js"; -} - #[cfg(all(target_os = "emscripten", target_arch = "wasm32"))] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 40eb910fdc388..e3455cfef3380 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1300,13 +1300,17 @@ impl File { pub fn set_times(&self, times: FileTimes) -> io::Result<()> { #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))] - let to_timespec = |time: Option| { - match time { - Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts), - Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too large to set as a file time")), - Some(_) => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too small to set as a file time")), - None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), - } + let to_timespec = |time: Option| match time { + Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts), + Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "timestamp is too large to set as a file time" + )), + Some(_) => Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "timestamp is too small to set as a file time" + )), + None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), }; cfg_if::cfg_if! { if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] { diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index dc3c037c0cb78..881b3a25c5152 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -180,7 +180,7 @@ pub fn getcwd() -> io::Result { } #[cfg(target_os = "espidf")] -pub fn chdir(p: &path::Path) -> io::Result<()> { +pub fn chdir(_p: &path::Path) -> io::Result<()> { super::unsupported::unsupported() } @@ -274,15 +274,19 @@ pub fn current_exe() -> io::Result { return path.canonicalize(); } // Search PWD to infer current_exe. - if let Some(pstr) = path.to_str() && pstr.contains("/") { + if let Some(pstr) = path.to_str() + && pstr.contains("/") + { return getcwd().map(|cwd| cwd.join(path))?.canonicalize(); } // Search PATH to infer current_exe. if let Some(p) = getenv(OsStr::from_bytes("PATH".as_bytes())) { for search_path in split_paths(&p) { let pb = search_path.join(&path); - if pb.is_file() && let Ok(metadata) = crate::fs::metadata(&pb) && - metadata.permissions().mode() & 0o111 != 0 { + if pb.is_file() + && let Ok(metadata) = crate::fs::metadata(&pb) + && metadata.permissions().mode() & 0o111 != 0 + { return pb.canonicalize(); } } diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 72aca4e665939..ee86a5f88dd78 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -9,6 +9,8 @@ use core::ffi::NonZero_c_int; #[cfg(target_os = "linux")] use crate::os::linux::process::PidFd; +#[cfg(target_os = "linux")] +use crate::os::unix::io::AsRawFd; #[cfg(any( target_os = "macos", @@ -696,11 +698,12 @@ impl Command { msg.msg_iov = &mut iov as *mut _ as *mut _; msg.msg_iovlen = 1; - msg.msg_controllen = mem::size_of_val(&cmsg.buf) as _; - msg.msg_control = &mut cmsg.buf as *mut _ as *mut _; // only attach cmsg if we successfully acquired the pidfd if pidfd >= 0 { + msg.msg_controllen = mem::size_of_val(&cmsg.buf) as _; + msg.msg_control = &mut cmsg.buf as *mut _ as *mut _; + let hdr = CMSG_FIRSTHDR(&mut msg as *mut _ as *mut _); (*hdr).cmsg_level = SOL_SOCKET; (*hdr).cmsg_type = SCM_RIGHTS; @@ -717,7 +720,7 @@ impl Command { // so we get a consistent SEQPACKET order match cvt_r(|| libc::sendmsg(sock.as_raw(), &msg, 0)) { Ok(0) => {} - _ => rtabort!("failed to communicate with parent process"), + other => rtabort!("failed to communicate with parent process. {:?}", other), } } } @@ -748,7 +751,7 @@ impl Command { msg.msg_controllen = mem::size_of::() as _; msg.msg_control = &mut cmsg as *mut _ as *mut _; - match cvt_r(|| libc::recvmsg(sock.as_raw(), &mut msg, 0)) { + match cvt_r(|| libc::recvmsg(sock.as_raw(), &mut msg, libc::MSG_CMSG_CLOEXEC)) { Err(_) => return -1, Ok(_) => {} } @@ -787,7 +790,7 @@ pub struct Process { // On Linux, stores the pidfd created for this child. // This is None if the user did not request pidfd creation, // or if the pidfd could not be created for some reason - // (e.g. the `clone3` syscall was not available). + // (e.g. the `pidfd_open` syscall was not available). #[cfg(target_os = "linux")] pidfd: Option, } @@ -816,10 +819,23 @@ impl Process { // and used for another process, and we probably shouldn't be killing // random processes, so return Ok because the process has exited already. if self.status.is_some() { - Ok(()) - } else { - cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) + return Ok(()); + } + #[cfg(target_os = "linux")] + if let Some(pid_fd) = self.pidfd.as_ref() { + // pidfd_send_signal predates pidfd_open. so if we were able to get an fd then sending signals will work too + return cvt(unsafe { + libc::syscall( + libc::SYS_pidfd_send_signal, + pid_fd.as_raw_fd(), + libc::SIGKILL, + crate::ptr::null::<()>(), + 0, + ) + }) + .map(drop); } + cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) } pub fn wait(&mut self) -> io::Result { @@ -827,6 +843,17 @@ impl Process { if let Some(status) = self.status { return Ok(status); } + #[cfg(target_os = "linux")] + if let Some(pid_fd) = self.pidfd.as_ref() { + let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; + + cvt_r(|| unsafe { + libc::waitid(libc::P_PIDFD, pid_fd.as_raw_fd() as u32, &mut siginfo, libc::WEXITED) + })?; + let status = ExitStatus::from_waitid_siginfo(siginfo); + self.status = Some(status); + return Ok(status); + } let mut status = 0 as c_int; cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?; self.status = Some(ExitStatus::new(status)); @@ -837,6 +864,25 @@ impl Process { if let Some(status) = self.status { return Ok(Some(status)); } + #[cfg(target_os = "linux")] + if let Some(pid_fd) = self.pidfd.as_ref() { + let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; + + cvt(unsafe { + libc::waitid( + libc::P_PIDFD, + pid_fd.as_raw_fd() as u32, + &mut siginfo, + libc::WEXITED | libc::WNOHANG, + ) + })?; + if unsafe { siginfo.si_pid() } == 0 { + return Ok(None); + } + let status = ExitStatus::from_waitid_siginfo(siginfo); + self.status = Some(status); + return Ok(Some(status)); + } let mut status = 0 as c_int; let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?; if pid == 0 { @@ -866,6 +912,20 @@ impl ExitStatus { ExitStatus(status) } + #[cfg(target_os = "linux")] + pub fn from_waitid_siginfo(siginfo: libc::siginfo_t) -> ExitStatus { + let status = unsafe { siginfo.si_status() }; + + match siginfo.si_code { + libc::CLD_EXITED => ExitStatus((status & 0xff) << 8), + libc::CLD_KILLED => ExitStatus(status), + libc::CLD_DUMPED => ExitStatus(status | 0x80), + libc::CLD_CONTINUED => ExitStatus(0xffff), + libc::CLD_STOPPED | libc::CLD_TRAPPED => ExitStatus(((status & 0xff) << 8) | 0x7f), + _ => unreachable!("waitid() should only return the above codes"), + } + } + fn exited(&self) -> bool { libc::WIFEXITED(self.0) } diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs index 6aa79e7f9e710..6e952ed7c42af 100644 --- a/library/std/src/sys/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/unix/process/process_unix/tests.rs @@ -64,7 +64,8 @@ fn test_command_fork_no_unwind() { #[test] #[cfg(target_os = "linux")] fn test_command_pidfd() { - use crate::os::fd::RawFd; + use crate::assert_matches::assert_matches; + use crate::os::fd::{AsRawFd, RawFd}; use crate::os::linux::process::{ChildExt, CommandExt}; use crate::process::Command; @@ -78,10 +79,22 @@ fn test_command_pidfd() { }; // always exercise creation attempts - let child = Command::new("echo").create_pidfd(true).spawn().unwrap(); + let mut child = Command::new("false").create_pidfd(true).spawn().unwrap(); // but only check if we know that the kernel supports pidfds if pidfd_open_available { - assert!(child.pidfd().is_ok()) + assert!(child.pidfd().is_ok()); } + if let Ok(pidfd) = child.pidfd() { + let flags = super::cvt(unsafe { libc::fcntl(pidfd.as_raw_fd(), libc::F_GETFD) }).unwrap(); + assert!(flags & libc::FD_CLOEXEC != 0); + } + let status = child.wait().expect("error waiting on pidfd"); + assert_eq!(status.code(), Some(1)); + + let mut child = Command::new("sleep").arg("1000").create_pidfd(true).spawn().unwrap(); + assert_matches!(child.try_wait(), Ok(None)); + child.kill().expect("failed to kill child"); + let status = child.wait().expect("error waiting on pidfd"); + assert_eq!(status.signal(), Some(libc::SIGKILL)); } diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index 06399e8a27427..667fd51696249 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -23,6 +23,8 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { /// This is necessary because the __cxa_thread_atexit_impl implementation /// std links to by default may be a C or C++ implementation that was not /// compiled using the Clang integer normalization option. + #[cfg(sanitizer_cfi_normalize_integers)] + use core::ffi::c_int; #[cfg(not(sanitizer_cfi_normalize_integers))] #[cfi_encoding = "i"] #[repr(transparent)] diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index f2e86a4fb2b1b..f62eb828ee5d4 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -23,11 +23,11 @@ struct Nanoseconds(u32); #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SystemTime { - pub(in crate::sys::unix) t: Timespec, + pub(crate) t: Timespec, } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub(in crate::sys::unix) struct Timespec { +pub(crate) struct Timespec { tv_sec: i64, tv_nsec: Nanoseconds, } @@ -239,11 +239,11 @@ impl From for Timespec { not(target_arch = "riscv32") ))] #[repr(C)] -pub(in crate::sys::unix) struct __timespec64 { - pub(in crate::sys::unix) tv_sec: i64, +pub(crate) struct __timespec64 { + pub(crate) tv_sec: i64, #[cfg(target_endian = "big")] _padding: i32, - pub(in crate::sys::unix) tv_nsec: i32, + pub(crate) tv_nsec: i32, #[cfg(target_endian = "little")] _padding: i32, } @@ -255,7 +255,7 @@ pub(in crate::sys::unix) struct __timespec64 { not(target_arch = "riscv32") ))] impl __timespec64 { - pub(in crate::sys::unix) fn new(tv_sec: i64, tv_nsec: i32) -> Self { + pub(crate) fn new(tv_sec: i64, tv_nsec: i32) -> Self { Self { tv_sec, tv_nsec, _padding: 0 } } } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 437aae3ae7f7f..e823866545226 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -477,12 +477,13 @@ impl File { } pub fn set_times(&self, times: FileTimes) -> io::Result<()> { - let to_timestamp = |time: Option| { - match time { - Some(time) if let Some(ts) = time.to_wasi_timestamp() => Ok(ts), - Some(_) => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too large to set as a file time")), - None => Ok(0), - } + let to_timestamp = |time: Option| match time { + Some(time) if let Some(ts) = time.to_wasi_timestamp() => Ok(ts), + Some(_) => Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "timestamp is too large to set as a file time" + )), + None => Ok(0), }; self.fd.filestat_set_times( to_timestamp(times.accessed)?, diff --git a/library/std/src/sys/windows/api.rs b/library/std/src/sys/windows/api.rs index e9f0bbfbe2e7d..a7ea59e85f786 100644 --- a/library/std/src/sys/windows/api.rs +++ b/library/std/src/sys/windows/api.rs @@ -48,7 +48,7 @@ use super::c; /// converted to a `u32`. Clippy would warn about this but, alas, it's not run /// on the standard library. const fn win32_size_of() -> u32 { - // Const assert that the size is less than u32::MAX. + // Const assert that the size does not exceed u32::MAX. // Uses a trait to workaround restriction on using generic types in inner items. trait Win32SizeOf: Sized { const WIN32_SIZE_OF: u32 = { @@ -132,7 +132,7 @@ pub fn set_file_information_by_handle( size: u32, ) -> Result<(), WinError> { let result = c::SetFileInformationByHandle(handle, class, info, size); - (result != 0).then_some(()).ok_or_else(|| get_last_error()) + (result != 0).then_some(()).ok_or_else(get_last_error) } // SAFETY: The `SetFileInformation` trait ensures that this is safe. unsafe { set_info(handle, T::CLASS, info.as_ptr(), info.size()) } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index a349e24b03951..7435b21be4c90 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -3,6 +3,7 @@ #![allow(nonstandard_style)] #![cfg_attr(test, allow(dead_code))] #![unstable(issue = "none", feature = "windows_c")] +#![allow(clippy::style)] use crate::ffi::CStr; use crate::mem; @@ -46,6 +47,8 @@ pub use FD_SET as fd_set; pub use LINGER as linger; pub use TIMEVAL as timeval; +pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(-1i32 as _); + // https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170 pub const EXIT_SUCCESS: u32 = 0; pub const EXIT_FAILURE: u32 = 1; @@ -81,7 +84,7 @@ pub fn nt_success(status: NTSTATUS) -> bool { impl UNICODE_STRING { pub fn from_ref(slice: &[u16]) -> Self { - let len = slice.len() * mem::size_of::(); + let len = mem::size_of_val(slice); Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ } } } diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst index 38bf15b7c7202..f91e1054a040b 100644 --- a/library/std/src/sys/windows/c/windows_sys.lst +++ b/library/std/src/sys/windows/c/windows_sys.lst @@ -2,6 +2,7 @@ --config flatten std --filter // tidy-alphabetical-start +!Windows.Win32.Foundation.INVALID_HANDLE_VALUE Windows.Wdk.Storage.FileSystem.FILE_COMPLETE_IF_OPLOCKED Windows.Wdk.Storage.FileSystem.FILE_CONTAINS_EXTENDED_CREATE_INFORMATION Windows.Wdk.Storage.FileSystem.FILE_CREATE @@ -1923,7 +1924,6 @@ Windows.Win32.Foundation.HANDLE_FLAG_INHERIT Windows.Win32.Foundation.HANDLE_FLAG_PROTECT_FROM_CLOSE Windows.Win32.Foundation.HANDLE_FLAGS Windows.Win32.Foundation.HMODULE -Windows.Win32.Foundation.INVALID_HANDLE_VALUE Windows.Win32.Foundation.MAX_PATH Windows.Win32.Foundation.NO_ERROR Windows.Win32.Foundation.NTSTATUS @@ -2483,7 +2483,6 @@ Windows.Win32.System.SystemInformation.GetSystemTimeAsFileTime Windows.Win32.System.SystemInformation.GetWindowsDirectoryW Windows.Win32.System.SystemInformation.PROCESSOR_ARCHITECTURE Windows.Win32.System.SystemInformation.SYSTEM_INFO -Windows.Win32.System.SystemServices.ALL_PROCESSOR_GROUPS Windows.Win32.System.SystemServices.DLL_PROCESS_DETACH Windows.Win32.System.SystemServices.DLL_THREAD_DETACH Windows.Win32.System.SystemServices.EXCEPTION_MAXIMUM_PARAMETERS @@ -2492,6 +2491,7 @@ Windows.Win32.System.SystemServices.IO_REPARSE_TAG_SYMLINK Windows.Win32.System.Threading.ABOVE_NORMAL_PRIORITY_CLASS Windows.Win32.System.Threading.AcquireSRWLockExclusive Windows.Win32.System.Threading.AcquireSRWLockShared +Windows.Win32.System.Threading.ALL_PROCESSOR_GROUPS Windows.Win32.System.Threading.BELOW_NORMAL_PRIORITY_CLASS Windows.Win32.System.Threading.CREATE_BREAKAWAY_FROM_JOB Windows.Win32.System.Threading.CREATE_DEFAULT_ERROR_MODE diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs index e0509e6a5dd79..b38b70c8983e6 100644 --- a/library/std/src/sys/windows/c/windows_sys.rs +++ b/library/std/src/sys/windows/c/windows_sys.rs @@ -4,7 +4,7 @@ // regenerate the bindings. // // ignore-tidy-filelength -// Bindings generated by `windows-bindgen` 0.51.1 +// Bindings generated by `windows-bindgen` 0.52.0 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] #[link(name = "advapi32")] @@ -63,7 +63,7 @@ extern "system" { lpnewfilename: PCWSTR, lpprogressroutine: LPPROGRESS_ROUTINE, lpdata: *const ::core::ffi::c_void, - pbcancel: *mut i32, + pbcancel: *mut BOOL, dwcopyflags: u32, ) -> BOOL; } @@ -619,7 +619,7 @@ extern "system" { lpmultibytestr: PSTR, cbmultibyte: i32, lpdefaultchar: PCSTR, - lpuseddefaultchar: *mut i32, + lpuseddefaultchar: *mut BOOL, ) -> i32; } #[link(name = "kernel32")] @@ -869,7 +869,7 @@ pub const AF_INET: ADDRESS_FAMILY = 2u16; pub const AF_INET6: ADDRESS_FAMILY = 23u16; pub const AF_UNIX: u16 = 1u16; pub const AF_UNSPEC: ADDRESS_FAMILY = 0u16; -pub const ALL_PROCESSOR_GROUPS: u32 = 65535u32; +pub const ALL_PROCESSOR_GROUPS: u16 = 65535u16; #[repr(C)] pub union ARM64_NT_NEON128 { pub Anonymous: ARM64_NT_NEON128_0, @@ -3498,7 +3498,6 @@ impl ::core::clone::Clone for INIT_ONCE { } pub const INIT_ONCE_INIT_FAILED: u32 = 4u32; pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32; -pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(-1i32 as _); pub const INVALID_SOCKET: SOCKET = -1i32 as _; #[repr(C)] pub struct IN_ADDR { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index d7e36b9a3fff6..f57034cc8d589 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -156,7 +156,7 @@ impl DirEntry { } pub fn path(&self) -> PathBuf { - self.root.join(&self.file_name()) + self.root.join(self.file_name()) } pub fn file_name(&self) -> OsString { @@ -548,7 +548,7 @@ impl File { let user = super::args::from_wide_to_user_path( subst.iter().copied().chain([0]).collect(), )?; - Ok(PathBuf::from(OsString::from_wide(&user.strip_suffix(&[0]).unwrap_or(&user)))) + Ok(PathBuf::from(OsString::from_wide(user.strip_suffix(&[0]).unwrap_or(&user)))) } else { Ok(PathBuf::from(OsString::from_wide(subst))) } @@ -786,7 +786,7 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result< // tricked into following a symlink. However, it may not be available in // earlier versions of Windows. static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE); - let mut object = c::OBJECT_ATTRIBUTES { + let object = c::OBJECT_ATTRIBUTES { ObjectName: &mut name_str, RootDirectory: parent.as_raw_handle(), Attributes: ATTRIBUTES.load(Ordering::Relaxed), @@ -795,7 +795,7 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result< let status = c::NtCreateFile( &mut handle, access, - &mut object, + &object, &mut io_status, crate::ptr::null_mut(), 0, @@ -874,7 +874,7 @@ impl fmt::Debug for File { // FIXME(#24570): add more info here (e.g., mode) let mut b = f.debug_struct("File"); b.field("handle", &self.handle.as_raw_handle()); - if let Ok(path) = get_path(&self) { + if let Ok(path) = get_path(self) { b.field("path", &path); } b.finish() @@ -1193,7 +1193,7 @@ pub fn readlink(path: &Path) -> io::Result { let mut opts = OpenOptions::new(); opts.access_mode(0); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); - let file = File::open(&path, &opts)?; + let file = File::open(path, &opts)?; file.readlink() } @@ -1407,7 +1407,7 @@ pub fn symlink_junction, Q: AsRef>( #[allow(dead_code)] fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> { let d = DirBuilder::new(); - d.mkdir(&junction)?; + d.mkdir(junction)?; let mut opts = OpenOptions::new(); opts.write(true); diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index 56d0d6c088737..c4495f81a5a3a 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -81,7 +81,7 @@ impl Handle { let res = unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), None) }; match res { - Ok(read) => Ok(read as usize), + Ok(read) => Ok(read), // The special treatment of BrokenPipe is to deal with Windows // pipe semantics, which yields this error when *reading* from @@ -107,7 +107,7 @@ impl Handle { unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), Some(offset)) }; match res { - Ok(read) => Ok(read as usize), + Ok(read) => Ok(read), Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0), Err(e) => Err(e), } @@ -121,7 +121,7 @@ impl Handle { Ok(read) => { // Safety: `read` bytes were written to the initialized portion of the buffer unsafe { - cursor.advance(read as usize); + cursor.advance(read); } Ok(()) } @@ -189,7 +189,7 @@ impl Handle { } pub fn write(&self, buf: &[u8]) -> io::Result { - self.synchronous_write(&buf, None) + self.synchronous_write(buf, None) } pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { @@ -202,7 +202,7 @@ impl Handle { } pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { - self.synchronous_write(&buf, Some(offset)) + self.synchronous_write(buf, Some(offset)) } pub fn try_clone(&self) -> io::Result { diff --git a/library/std/src/sys/windows/io.rs b/library/std/src/sys/windows/io.rs index 9b540ee071f4f..649826d25cef7 100644 --- a/library/std/src/sys/windows/io.rs +++ b/library/std/src/sys/windows/io.rs @@ -36,7 +36,7 @@ impl<'a> IoSlice<'a> { #[inline] pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.vec.buf as *mut u8, self.vec.len as usize) } + unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) } } } @@ -70,12 +70,12 @@ impl<'a> IoSliceMut<'a> { #[inline] pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.vec.buf as *mut u8, self.vec.len as usize) } + unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) } } #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.len as usize) } + unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) } } } diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index c4e56e13be325..9c83d6eb8bf68 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -63,7 +63,7 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) { // Normally, `thread::spawn` will call `Thread::set_name` but since this thread already // exists, we have to call it ourselves. - thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0")); + thread::Thread::set_name(CStr::from_bytes_with_nul_unchecked(b"main\0")); } // SAFETY: must be called only once during runtime cleanup. @@ -150,7 +150,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { pub fn unrolled_find_u16s(needle: u16, haystack: &[u16]) -> Option { let ptr = haystack.as_ptr(); - let mut start = &haystack[..]; + let mut start = haystack; // For performance reasons unfold the loop eight times. while start.len() >= 8 { diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index c29b863665f15..6cd758ec5c32d 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -162,7 +162,7 @@ impl Socket { let mut timeout = c::timeval { tv_sec: cmp::min(timeout.as_secs(), c_long::MAX as u64) as c_long, - tv_usec: (timeout.subsec_nanos() / 1000) as c_long, + tv_usec: timeout.subsec_micros() as c_long, }; if timeout.tv_sec == 0 && timeout.tv_usec == 0 { diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs index 8cc905101de7a..829dd5eb97ac2 100644 --- a/library/std/src/sys/windows/os.rs +++ b/library/std/src/sys/windows/os.rs @@ -297,7 +297,7 @@ pub fn getenv(k: &OsStr) -> Option { let k = to_u16s(k).ok()?; super::fill_utf16_buf( |buf, sz| unsafe { c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) }, - |buf| OsStringExt::from_wide(buf), + OsStringExt::from_wide, ) .ok() } @@ -356,7 +356,7 @@ pub fn home_dir() -> Option { crate::env::var_os("HOME") .or_else(|| crate::env::var_os("USERPROFILE")) .map(PathBuf::from) - .or_else(|| home_dir_crt()) + .or_else(home_dir_crt) } pub fn exit(code: i32) -> ! { @@ -364,5 +364,5 @@ pub fn exit(code: i32) -> ! { } pub fn getpid() -> u32 { - unsafe { c::GetCurrentProcessId() as u32 } + unsafe { c::GetCurrentProcessId() } } diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index 8c0e07b35662f..d9684f2175313 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -78,7 +78,7 @@ impl<'a> PrefixParserSlice<'a, '_> { fn strip_prefix(&self, prefix: &str) -> Option { self.prefix[self.index..] .starts_with(prefix.as_bytes()) - .then(|| Self { index: self.index + prefix.len(), ..*self }) + .then_some(Self { index: self.index + prefix.len(), ..*self }) } fn prefix_bytes(&self) -> &'a [u8] { @@ -104,7 +104,9 @@ pub fn parse_prefix(path: &OsStr) -> Option> { // The meaning of verbatim paths can change when they use a different // separator. - if let Some(parser) = parser.strip_prefix(r"?\") && !parser.prefix_bytes().iter().any(|&x| x == b'/') { + if let Some(parser) = parser.strip_prefix(r"?\") + && !parser.prefix_bytes().iter().any(|&x| x == b'/') + { // \\?\ if let Some(parser) = parser.strip_prefix(r"UNC\") { // \\?\UNC\server\share @@ -145,12 +147,10 @@ pub fn parse_prefix(path: &OsStr) -> Option> { None } } - } else if let Some(drive) = parse_drive(path) { - // C: - Some(Disk(drive)) } else { - // no prefix - None + // If it has a drive like `C:` then it's a disk. + // Otherwise there is no prefix. + parse_drive(path).map(Disk) } } @@ -250,7 +250,7 @@ pub(crate) fn get_long_path(mut path: Vec, prefer_verbatim: bool) -> io::Re // \\?\UNC\ const UNC_PREFIX: &[u16] = &[SEP, SEP, QUERY, SEP, U, N, C, SEP]; - if path.starts_with(VERBATIM_PREFIX) || path.starts_with(NT_PREFIX) || path == &[0] { + if path.starts_with(VERBATIM_PREFIX) || path.starts_with(NT_PREFIX) || path == [0] { // Early return for paths that are already verbatim or empty. return Ok(path); } else if path.len() < LEGACY_MAX_PATH { diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index f4078d359448e..9ec775959fd45 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -245,7 +245,7 @@ impl Command { } pub fn get_current_dir(&self) -> Option<&Path> { - self.cwd.as_ref().map(|cwd| Path::new(cwd)) + self.cwd.as_ref().map(Path::new) } pub unsafe fn raw_attribute( @@ -463,7 +463,7 @@ fn resolve_exe<'a>( // Search the directories given by `search_paths`. let result = search_paths(parent_paths, child_paths, |mut path| { - path.push(&exe_path); + path.push(exe_path); if !has_extension { path.set_extension(EXE_EXTENSION); } @@ -597,7 +597,7 @@ impl Stdio { opts.read(stdio_id == c::STD_INPUT_HANDLE); opts.write(stdio_id != c::STD_INPUT_HANDLE); opts.security_attributes(&mut sa); - File::open(Path::new("NUL"), &opts).map(|file| file.into_inner()) + File::open(Path::new(r"\\.\NUL"), &opts).map(|file| file.into_inner()) } } } @@ -657,7 +657,7 @@ impl Process { } pub fn id(&self) -> u32 { - unsafe { c::GetProcessId(self.handle.as_raw_handle()) as u32 } + unsafe { c::GetProcessId(self.handle.as_raw_handle()) } } pub fn main_thread_handle(&self) -> BorrowedHandle<'_> { @@ -917,9 +917,8 @@ fn make_proc_thread_attribute_list( ) }; - let mut proc_thread_attribute_list = ProcThreadAttributeList( - vec![MaybeUninit::uninit(); required_size as usize].into_boxed_slice(), - ); + let mut proc_thread_attribute_list = + ProcThreadAttributeList(vec![MaybeUninit::uninit(); required_size].into_boxed_slice()); // Once we've allocated the necessary memory, it's safe to invoke // `InitializeProcThreadAttributeList` to properly initialize the list. diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs index a9ff909aa6794..819a48266d949 100644 --- a/library/std/src/sys/windows/stdio.rs +++ b/library/std/src/sys/windows/stdio.rs @@ -195,7 +195,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result io::Result= 0xDCEE && first_code_unit_remaining <= 0xDFFF { + if matches!(first_code_unit_remaining, 0xDCEE..=0xDFFF) { // low surrogate // We just hope this works, and give up otherwise let _ = write_u16s(handle, &utf16[written..written + 1]); @@ -266,7 +266,7 @@ impl io::Read for Stdin { let mut bytes_copied = self.incomplete_utf8.read(buf); if bytes_copied == buf.len() { - return Ok(bytes_copied); + Ok(bytes_copied) } else if buf.len() - bytes_copied < 4 { // Not enough space to get a UTF-8 byte. We will use the incomplete UTF8. let mut utf16_buf = [MaybeUninit::new(0); 1]; @@ -332,7 +332,7 @@ fn read_u16s_fixup_surrogates( // and it is not 0, so we know that `buf[amount - 1]` have been // initialized. let last_char = unsafe { buf[amount - 1].assume_init() }; - if last_char >= 0xD800 && last_char <= 0xDBFF { + if matches!(last_char, 0xD800..=0xDBFF) { // high surrogate *surrogate = last_char; amount -= 1; diff --git a/library/std/src/sys/windows/time.rs b/library/std/src/sys/windows/time.rs index bece48e799f8c..09e78a29304f9 100644 --- a/library/std/src/sys/windows/time.rs +++ b/library/std/src/sys/windows/time.rs @@ -1,7 +1,7 @@ use crate::cmp::Ordering; use crate::fmt; use crate::mem; -use crate::ptr::{null, null_mut}; +use crate::ptr::null; use crate::sys::c; use crate::sys_common::IntoInner; use crate::time::Duration; @@ -240,7 +240,7 @@ impl WaitableTimer { c::TIMER_ALL_ACCESS, ) }; - if handle != null_mut() { Ok(Self { handle }) } else { Err(()) } + if !handle.is_null() { Ok(Self { handle }) } else { Err(()) } } pub fn set(&self, duration: Duration) -> Result<(), ()> { // Convert the Duration to a format similar to FILETIME. diff --git a/library/std/src/sys/xous/mod.rs b/library/std/src/sys/xous/mod.rs index 6d5c218d19570..c2550dcfd8315 100644 --- a/library/std/src/sys/xous/mod.rs +++ b/library/std/src/sys/xous/mod.rs @@ -28,7 +28,6 @@ pub mod process; pub mod stdio; pub mod thread; pub mod thread_local_key; -#[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; pub mod time; diff --git a/library/std/src/sys/xous/os.rs b/library/std/src/sys/xous/os.rs index 3d19fa4b31af4..8d2eaee8aa617 100644 --- a/library/std/src/sys/xous/os.rs +++ b/library/std/src/sys/xous/os.rs @@ -7,6 +7,28 @@ use crate::marker::PhantomData; use crate::os::xous::ffi::Error as XousError; use crate::path::{self, PathBuf}; +#[cfg(not(test))] +#[cfg(feature = "panic_unwind")] +mod eh_unwinding { + pub(crate) struct EhFrameFinder(usize /* eh_frame */); + pub(crate) static mut EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder(0); + impl EhFrameFinder { + pub(crate) unsafe fn init(&mut self, eh_frame: usize) { + unsafe { + EH_FRAME_SETTINGS.0 = eh_frame; + } + } + } + unsafe impl unwind::EhFrameFinder for EhFrameFinder { + fn find(&self, _pc: usize) -> Option { + Some(unwind::FrameInfo { + text_base: None, + kind: unwind::FrameInfoKind::EhFrame(self.0), + }) + } + } +} + #[cfg(not(test))] mod c_compat { use crate::os::xous::ffi::exit; @@ -20,7 +42,12 @@ mod c_compat { } #[no_mangle] - pub extern "C" fn _start() { + pub extern "C" fn _start(eh_frame: usize) { + #[cfg(feature = "panic_unwind")] + unsafe { + super::eh_unwinding::EH_FRAME_SETTINGS.init(eh_frame); + unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok(); + } exit(unsafe { main() }); } diff --git a/library/std/src/sys/xous/thread_parking.rs b/library/std/src/sys/xous/thread_parking.rs new file mode 100644 index 0000000000000..aa39c6d27185f --- /dev/null +++ b/library/std/src/sys/xous/thread_parking.rs @@ -0,0 +1,94 @@ +use crate::os::xous::ffi::{blocking_scalar, scalar}; +use crate::os::xous::services::{ticktimer_server, TicktimerScalar}; +use crate::pin::Pin; +use crate::ptr; +use crate::sync::atomic::{ + AtomicI8, + Ordering::{Acquire, Release}, +}; +use crate::time::Duration; + +const NOTIFIED: i8 = 1; +const EMPTY: i8 = 0; +const PARKED: i8 = -1; + +pub struct Parker { + state: AtomicI8, +} + +impl Parker { + pub unsafe fn new_in_place(parker: *mut Parker) { + unsafe { parker.write(Parker { state: AtomicI8::new(EMPTY) }) } + } + + fn index(&self) -> usize { + ptr::from_ref(self).addr() + } + + pub unsafe fn park(self: Pin<&Self>) { + // Change NOTIFIED to EMPTY and EMPTY to PARKED. + let state = self.state.fetch_sub(1, Acquire); + if state == NOTIFIED { + return; + } + + // The state was set to PARKED. Wait until the `unpark` wakes us up. + blocking_scalar( + ticktimer_server(), + TicktimerScalar::WaitForCondition(self.index(), 0).into(), + ) + .expect("failed to send WaitForCondition command"); + + self.state.swap(EMPTY, Acquire); + } + + pub unsafe fn park_timeout(self: Pin<&Self>, timeout: Duration) { + // Change NOTIFIED to EMPTY and EMPTY to PARKED. + let state = self.state.fetch_sub(1, Acquire); + if state == NOTIFIED { + return; + } + + // A value of zero indicates an indefinite wait. Clamp the number of + // milliseconds to the allowed range. + let millis = usize::max(timeout.as_millis().try_into().unwrap_or(usize::MAX), 1); + + let was_timeout = blocking_scalar( + ticktimer_server(), + TicktimerScalar::WaitForCondition(self.index(), millis).into(), + ) + .expect("failed to send WaitForCondition command")[0] + != 0; + + let state = self.state.swap(EMPTY, Acquire); + if was_timeout && state == NOTIFIED { + // The state was set to NOTIFIED after we returned from the wait + // but before we reset the state. Therefore, a wakeup is on its + // way, which we need to consume here. + // NOTICE: this is a priority hole. + blocking_scalar( + ticktimer_server(), + TicktimerScalar::WaitForCondition(self.index(), 0).into(), + ) + .expect("failed to send WaitForCondition command"); + } + } + + pub fn unpark(self: Pin<&Self>) { + let state = self.state.swap(NOTIFIED, Release); + if state == PARKED { + // The thread is parked, wake it up. + blocking_scalar( + ticktimer_server(), + TicktimerScalar::NotifyCondition(self.index(), 1).into(), + ) + .expect("failed to send NotifyCondition command"); + } + } +} + +impl Drop for Parker { + fn drop(&mut self) { + scalar(ticktimer_server(), TicktimerScalar::FreeCondition(self.index()).into()).ok(); + } +} diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index 84e2c5d8d7f70..adfe721cfa9ad 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -64,6 +64,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: let mut first_omit = true; // Start immediately if we're not using a short backtrace. let mut start = print_fmt != PrintFmt::Short; + set_image_base(); backtrace_rs::trace_unsynchronized(|frame| { if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { return false; @@ -213,3 +214,14 @@ pub fn output_filename( } fmt::Display::fmt(&file.display(), fmt) } + +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] +pub fn set_image_base() { + let image_base = crate::os::fortanix_sgx::mem::image_base(); + backtrace_rs::set_image_base(crate::ptr::invalid_mut(image_base as _)); +} + +#[cfg(not(all(target_vendor = "fortanix", target_env = "sgx")))] +pub fn set_image_base() { + // nothing to do for platforms other than SGX +} diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index e18638f2a5f54..851832a377cf8 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -43,15 +43,15 @@ cfg_if::cfg_if! { } cfg_if::cfg_if! { - if #[cfg(any(target_os = "l4re", - target_os = "uefi", - feature = "restricted-std", - all(target_family = "wasm", not(target_os = "emscripten")), - target_os = "xous", - all(target_vendor = "fortanix", target_env = "sgx")))] { - pub use crate::sys::net; - } else { + if #[cfg(any( + all(unix, not(target_os = "l4re")), + windows, + target_os = "hermit", + target_os = "solid_asp3" + ))] { pub mod net; + } else { + pub use crate::sys::net; } } diff --git a/library/std/src/sys_common/once/futex.rs b/library/std/src/sys_common/once/futex.rs index 42db5fad4b451..609085dcd4712 100644 --- a/library/std/src/sys_common/once/futex.rs +++ b/library/std/src/sys_common/once/futex.rs @@ -128,7 +128,8 @@ impl Once { RUNNING | QUEUED => { // Set the state to QUEUED if it is not already. if state == RUNNING - && let Err(new) = self.state.compare_exchange_weak(RUNNING, QUEUED, Relaxed, Acquire) + && let Err(new) = + self.state.compare_exchange_weak(RUNNING, QUEUED, Relaxed, Acquire) { state = new; continue; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 4097eb5549efe..8498937809e71 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -548,10 +548,6 @@ impl Builder { let main = Box::new(main); // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the // lifetime change is justified. - #[cfg(bootstrap)] - let main = - unsafe { mem::transmute::, Box>(main) }; - #[cfg(not(bootstrap))] let main = unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + 'static)) }; Ok(JoinInner { @@ -1585,6 +1581,7 @@ impl<'scope, T> JoinInner<'scope, T> { /// [`thread::Builder::spawn`]: Builder::spawn /// [`thread::spawn`]: spawn #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(target_os = "teeos", must_use)] pub struct JoinHandle(JoinInner<'static, T>); #[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs index 358c2c3f9b2f3..1aad6549e76c3 100644 --- a/library/std/tests/common/mod.rs +++ b/library/std/tests/common/mod.rs @@ -1,17 +1,17 @@ #![allow(unused)] +use rand::RngCore; use std::env; use std::fs; use std::path::{Path, PathBuf}; use std::thread; -use rand::RngCore; /// Copied from `std::test_helpers::test_rng`, since these tests rely on the /// seed not being the same for every RNG invocation too. #[track_caller] pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = std::hash::RandomState::new().build_hasher(); core::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); diff --git a/library/test/src/helpers/shuffle.rs b/library/test/src/helpers/shuffle.rs index ca503106c556c..2ac3bfbd4d6f2 100644 --- a/library/test/src/helpers/shuffle.rs +++ b/library/test/src/helpers/shuffle.rs @@ -1,7 +1,6 @@ use crate::cli::TestOpts; use crate::types::{TestDescAndFn, TestId, TestName}; -use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; +use std::hash::{DefaultHasher, Hasher}; use std::time::{SystemTime, UNIX_EPOCH}; pub fn get_shuffle_seed(opts: &TestOpts) -> Option { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index bddf75dffbb62..2fa5a8e5e388a 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -16,8 +16,8 @@ #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(internal_output_capture)] #![feature(staged_api)] #![feature(process_exitcode_internals)] @@ -264,8 +264,8 @@ pub fn run_tests( where F: FnMut(TestEvent) -> io::Result<()>, { - use std::collections::{self, HashMap}; - use std::hash::BuildHasherDefault; + use std::collections::HashMap; + use std::hash::{BuildHasherDefault, DefaultHasher}; use std::sync::mpsc::RecvTimeoutError; struct RunningTest { @@ -286,8 +286,7 @@ where } // Use a deterministic hasher - type TestMap = - HashMap>; + type TestMap = HashMap>; struct TimeoutEntry { id: TestId, diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index eab2717c45233..b7418d1189c77 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -15,12 +15,12 @@ doc = false [dependencies] core = { path = "../core" } -libc = { version = "0.2.79", features = ['rustc-dep-of-std'], default-features = false } +libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false } compiler_builtins = "0.1.0" cfg-if = "1.0" -[build-dependencies] -cc = "1.0.76" +[target.'cfg(target_os = "xous")'.dependencies] +unwinding = { version = "0.2.1", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false } [features] diff --git a/library/unwind/build.rs b/library/unwind/build.rs deleted file mode 100644 index 5c3c02fb6adac..0000000000000 --- a/library/unwind/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::env; - -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=CARGO_CFG_MIRI"); - - if env::var_os("CARGO_CFG_MIRI").is_some() { - // Miri doesn't need the linker flags or a libunwind build. - return; - } - - let target = env::var("TARGET").expect("TARGET was not set"); - if target.contains("android") { - let build = cc::Build::new(); - - // Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus - // check if we have `libunwind` available and if so use it. Otherwise - // fall back to `libgcc` to support older ndk versions. - let has_unwind = build.is_flag_supported("-lunwind").expect("Unable to invoke compiler"); - - if has_unwind { - println!("cargo:rustc-cfg=feature=\"system-llvm-libunwind\""); - } - } -} diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index e86408a9ed2bd..eeee98f754e09 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -26,6 +26,9 @@ cfg_if::cfg_if! { ))] { mod libunwind; pub use libunwind::*; + } else if #[cfg(target_os = "xous")] { + mod unwinding; + pub use unwinding::*; } else { // no unwinder on the system! // - wasm32 (not emscripten, which is "unix" family) @@ -76,14 +79,10 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(feature = "llvm-libunwind")] { compile_error!("`llvm-libunwind` is not supported for Android targets"); - } else if #[cfg(feature = "system-llvm-libunwind")] { + } else { #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "unwind", cfg(not(target_feature = "crt-static")))] extern "C" {} - } else { - #[link(name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] - #[link(name = "gcc", cfg(not(target_feature = "crt-static")))] - extern "C" {} } } // Android's unwinding library depends on dl_iterate_phdr in `libdl`. diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index dba64aa74ce60..1b5f6f9dde36c 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -103,7 +103,10 @@ pub type _Unwind_Exception_Cleanup_Fn = // and RFC 2841 #[cfg_attr( any( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all( + feature = "llvm-libunwind", + any(target_os = "fuchsia", target_os = "linux", target_os = "xous") + ), all(target_os = "windows", target_env = "gnu", target_abi = "llvm") ), link(name = "unwind", kind = "static", modifiers = "-bundle") @@ -134,7 +137,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe pub use _Unwind_Action::*; #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] extern "C" { @@ -192,7 +195,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe pub const UNWIND_IP_REG: c_int = 15; #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] extern "C" { @@ -258,14 +261,14 @@ cfg_if::cfg_if! { if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { // Not 32-bit iOS #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] extern "C-unwind" { pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; } #[cfg_attr( - all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), + all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), link(name = "unwind", kind = "static", modifiers = "-bundle") )] extern "C" { diff --git a/library/unwind/src/unwinding.rs b/library/unwind/src/unwinding.rs new file mode 100644 index 0000000000000..1a4187b22200d --- /dev/null +++ b/library/unwind/src/unwinding.rs @@ -0,0 +1,105 @@ +#![allow(nonstandard_style)] + +use libc::{c_int, c_void}; + +#[repr(C)] +#[derive(Copy, Clone, PartialEq)] +pub enum _Unwind_Action { + _UA_SEARCH_PHASE = 1, + _UA_CLEANUP_PHASE = 2, + _UA_HANDLER_FRAME = 4, + _UA_FORCE_UNWIND = 8, + _UA_END_OF_STACK = 16, +} +pub use _Unwind_Action::*; + +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum _Unwind_Reason_Code { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, + _URC_FAILURE = 9, // used only by ARM EHABI +} +pub use _Unwind_Reason_Code::*; + +pub use unwinding::abi::UnwindContext; +pub use unwinding::abi::UnwindException; +pub enum _Unwind_Context {} + +pub use unwinding::custom_eh_frame_finder::{ + set_custom_eh_frame_finder, EhFrameFinder, FrameInfo, FrameInfoKind, +}; + +pub type _Unwind_Exception_Class = u64; +pub type _Unwind_Word = *const u8; +pub type _Unwind_Ptr = *const u8; + +pub const unwinder_private_data_size: usize = core::mem::size_of::() + - core::mem::size_of::<_Unwind_Exception_Class>() + - core::mem::size_of::<_Unwind_Exception_Cleanup_Fn>(); + +pub type _Unwind_Exception_Cleanup_Fn = + extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); + +#[repr(C)] +pub struct _Unwind_Exception { + pub exception_class: _Unwind_Exception_Class, + pub exception_cleanup: _Unwind_Exception_Cleanup_Fn, + pub private: [_Unwind_Word; unwinder_private_data_size], +} + +pub unsafe fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_GetDataRelBase(ctx) as _Unwind_Ptr +} + +pub unsafe fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_GetTextRelBase(ctx) as _Unwind_Ptr +} + +pub unsafe fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_GetRegionStart(ctx) as _Unwind_Ptr +} + +pub unsafe fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_SetGR(ctx, reg_index, value as usize) +} + +pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word) { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_SetIP(ctx, value as usize) +} + +pub unsafe fn _Unwind_GetIPInfo( + ctx: *mut _Unwind_Context, + ip_before_insn: *mut c_int, +) -> _Unwind_Word { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + let ip_before_insn = unsafe { &mut *(ip_before_insn as *mut c_int) }; + unsafe { &*(unwinding::abi::_Unwind_GetIPInfo(ctx, ip_before_insn) as _Unwind_Word) } +} + +pub unsafe fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void { + let ctx = unsafe { &mut *(ctx as *mut UnwindContext<'_>) }; + unwinding::abi::_Unwind_GetLanguageSpecificData(ctx) +} + +pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code { + let exception = unsafe { &mut *(exception as *mut UnwindException) }; + unsafe { core::mem::transmute(unwinding::abi::_Unwind_RaiseException(exception)) } +} + +pub unsafe fn _Unwind_DeleteException(exception: *mut _Unwind_Exception) { + let exception = unsafe { &mut *(exception as *mut UnwindException) }; + unsafe { unwinding::abi::_Unwind_DeleteException(exception) } +} diff --git a/rustfmt.toml b/rustfmt.toml index 88700779e87be..e292a3107420e 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -39,4 +39,5 @@ ignore = [ # these are ignored by a standard cargo fmt run "compiler/rustc_codegen_cranelift/y.rs", # running rustfmt breaks this file "compiler/rustc_codegen_cranelift/scripts", + "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", # uses edition 2024 ] diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 346bfb30fecf9..f452b944e75be 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -180,16 +180,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.2" @@ -323,15 +313,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hex" version = "0.4.3" @@ -389,9 +370,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "linux-raw-sys" @@ -443,16 +424,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" version = "0.32.0" @@ -514,25 +485,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index e4d359141cec1..24951cf20fa08 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -42,7 +42,7 @@ filetime = "0.2" hex = "0.4" home = "0.5.4" ignore = "0.4.10" -libc = "0.2" +libc = "0.2.150" object = { version = "0.32.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] } once_cell = "1.7.2" opener = "0.5" diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index e7998a40a6520..d0a069f45e138 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -183,7 +183,7 @@ Some general areas that you may be interested in modifying are: If you make a major change on bootstrap configuration, please remember to: -+ Update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs`. ++ Update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs`. * Update `change-id = {pull-request-id}` in `config.example.toml`. A 'major change' includes diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 1a1125a107fe1..fea194a80efbb 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -211,7 +211,7 @@ def require(cmd, exit=True, exception=False): if exception: raise elif exit: - eprint("error: unable to run `{}`: {}".format(' '.join(cmd), exc)) + eprint("ERROR: unable to run `{}`: {}".format(' '.join(cmd), exc)) eprint("Please make sure it's installed and in the path.") sys.exit(1) return None @@ -616,22 +616,6 @@ def download_toolchain(self): with output(self.rustc_stamp()) as rust_stamp: rust_stamp.write(key) - def _download_component_helper( - self, filename, pattern, tarball_suffix, rustc_cache, - ): - key = self.stage0_compiler.date - - tarball = os.path.join(rustc_cache, filename) - if not os.path.exists(tarball): - get( - self.download_url, - "dist/{}/{}".format(key, filename), - tarball, - self.checksums_sha256, - verbose=self.verbose, - ) - unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose) - def should_fix_bins_and_dylibs(self): """Whether or not `fix_bin_or_dylib` needs to be run; can only be True on NixOS or if config.toml has `build.patch-binaries-for-nix` set. @@ -681,7 +665,7 @@ def get_answer(): answer = self._should_fix_bins_and_dylibs = get_answer() if answer: - eprint("info: You seem to be using Nix.") + eprint("INFO: You seem to be using Nix.") return answer def fix_bin_or_dylib(self, fname): @@ -727,7 +711,7 @@ def fix_bin_or_dylib(self, fname): "nix-build", "-E", nix_expr, "-o", nix_deps_dir, ]) except subprocess.CalledProcessError as reason: - eprint("warning: failed to call nix-build:", reason) + eprint("WARNING: failed to call nix-build:", reason) return self.nix_deps_dir = nix_deps_dir @@ -747,7 +731,7 @@ def fix_bin_or_dylib(self, fname): try: subprocess.check_output([patchelf] + patchelf_args + [fname]) except subprocess.CalledProcessError as reason: - eprint("warning: failed to call patchelf:", reason) + eprint("WARNING: failed to call patchelf:", reason) return def rustc_stamp(self): @@ -946,6 +930,8 @@ def build_bootstrap_cmd(self, env): target_linker = self.get_toml("linker", build_section) if target_linker is not None: env["RUSTFLAGS"] += " -C linker=" + target_linker + # When changing this list, also update the corresponding list in `Builder::cargo` + # in `src/bootstrap/src/core/builder.rs`. env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" if self.warnings == "default": deny_warnings = self.get_toml("deny-warnings", "rust") != "false" @@ -1005,7 +991,7 @@ def check_vendored_status(self): if 'SUDO_USER' in os.environ and not self.use_vendored_sources: if os.getuid() == 0: self.use_vendored_sources = True - eprint('info: looks like you\'re trying to run this command as root') + eprint('INFO: looks like you\'re trying to run this command as root') eprint(' and so in order to preserve your $HOME this will now') eprint(' use vendored sources by default.') @@ -1017,14 +1003,14 @@ def check_vendored_status(self): "--sync ./src/tools/rust-analyzer/Cargo.toml " \ "--sync ./compiler/rustc_codegen_cranelift/Cargo.toml " \ "--sync ./src/bootstrap/Cargo.toml " - eprint('error: vendoring required, but vendor directory does not exist.') + eprint('ERROR: vendoring required, but vendor directory does not exist.') eprint(' Run `cargo vendor {}` to initialize the ' 'vendor directory.'.format(sync_dirs)) eprint('Alternatively, use the pre-vendored `rustc-src` dist component.') raise Exception("{} not found".format(vendor_dir)) if not os.path.exists(cargo_dir): - eprint('error: vendoring required, but .cargo/config does not exist.') + eprint('ERROR: vendoring required, but .cargo/config does not exist.') raise Exception("{} not found".format(cargo_dir)) else: if os.path.exists(cargo_dir): @@ -1083,6 +1069,11 @@ def bootstrap(args): include_file = 'config.{}.toml'.format(profile_aliases.get(profile) or profile) include_dir = os.path.join(rust_root, 'src', 'bootstrap', 'defaults') include_path = os.path.join(include_dir, include_file) + + if not os.path.exists(include_path): + raise Exception("Unrecognized config profile '{}'. Check src/bootstrap/defaults" + " for available options.".format(profile)) + # HACK: This works because `self.get_toml()` returns the first match it finds for a # specific key, so appending our defaults at the end allows the user to override them with open(include_path) as included_toml: @@ -1125,7 +1116,7 @@ def main(): # process has to happen before anything is printed out. if help_triggered: eprint( - "info: Downloading and building bootstrap before processing --help command.\n" + "INFO: Downloading and building bootstrap before processing --help command.\n" " See src/bootstrap/README.md for help with common commands.") exit_code = 0 diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index e6caabec4f640..6da410ed2f279 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -34,7 +34,7 @@ def serialize_and_parse(configure_args, bootstrap_args=None): # Verify this is actually valid TOML. tomllib.loads(build.config_toml) except ImportError: - print("warning: skipping TOML validation, need at least python 3.11", file=sys.stderr) + print("WARNING: skipping TOML validation, need at least python 3.11", file=sys.stderr) return build diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 626ca6cf2e7a7..544a42d9ada1a 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -253,7 +253,7 @@ def parse_args(args): if not found: unknown_args.append(arg) - # Note: here and a few other places, we use [-1] to apply the *last* value + # NOTE: here and a few other places, we use [-1] to apply the *last* value # passed. But if option-checking is enabled, then the known_args loop will # also assert that options are only passed once. option_checking = ('option-checking' not in known_args @@ -477,7 +477,7 @@ def configure_section(lines, config): # These are used by rpm, but aren't accepted by x.py. # Give a warning that they're ignored, but not a hard error. if key in ["infodir", "localstatedir"]: - print("warning: {} will be ignored".format(key)) + print("WARNING: {} will be ignored".format(key)) else: raise RuntimeError("failed to find config line for {}".format(key)) diff --git a/src/bootstrap/defaults/config.codegen.toml b/src/bootstrap/defaults/config.codegen.toml index 113df88d7c349..7c33ce958c929 100644 --- a/src/bootstrap/defaults/config.codegen.toml +++ b/src/bootstrap/defaults/config.codegen.toml @@ -10,7 +10,7 @@ assertions = true # enable warnings during the llvm compilation enable-warnings = true # build llvm from source -download-ci-llvm = false +download-ci-llvm = "if-unchanged" [rust] # This enables `RUSTC_LOG=debug`, avoiding confusing situations diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml index b98b13119e8ad..b27b524b873b7 100644 --- a/src/bootstrap/defaults/config.compiler.toml +++ b/src/bootstrap/defaults/config.compiler.toml @@ -17,4 +17,4 @@ lto = "off" [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-available" +download-ci-llvm = "if-unchanged" diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index f362c4111f107..087544397f5ea 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -13,4 +13,4 @@ lto = "off" [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-available" +download-ci-llvm = "if-unchanged" diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 79424f28d27b7..6e6c366002792 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -21,4 +21,4 @@ compiler-docs = true [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-available" +download-ci-llvm = "if-unchanged" diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index ffc38057900ad..9998fe2f5db8f 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/113996 +Last change is for: https://github.com/rust-lang/rust/pull/116881 diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index d87fb6a9cef0c..952ef40ed424d 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -9,11 +9,14 @@ use std::io::Write; #[cfg(all(any(unix, windows), not(target_os = "solaris")))] use std::process; -use std::{env, fs}; +use std::{ + env, fs, + io::{self, IsTerminal}, +}; -#[cfg(all(any(unix, windows), not(target_os = "solaris")))] -use bootstrap::t; -use bootstrap::{find_recent_config_change_ids, Build, Config, Subcommand, CONFIG_CHANGE_HISTORY}; +use bootstrap::{ + find_recent_config_change_ids, t, Build, Config, Subcommand, CONFIG_CHANGE_HISTORY, +}; fn main() { let args = env::args().skip(1).collect::>(); @@ -63,7 +66,7 @@ fn main() { if suggest_setup { println!("WARNING: you have not made a `config.toml`"); println!( - "help: consider running `./x.py setup` or copying `config.example.toml` by running \ + "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \ `cp config.example.toml config.toml`" ); } else if let Some(suggestion) = &changelog_suggestion { @@ -76,7 +79,7 @@ fn main() { if suggest_setup { println!("WARNING: you have not made a `config.toml`"); println!( - "help: consider running `./x.py setup` or copying `config.example.toml` by running \ + "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \ `cp config.example.toml config.toml`" ); } else if let Some(suggestion) = &changelog_suggestion { @@ -97,7 +100,7 @@ fn main() { } if suggest_setup || changelog_suggestion.is_some() { - println!("note: this message was printed twice to make it more likely to be seen"); + println!("NOTE: this message was printed twice to make it more likely to be seen"); } } @@ -108,32 +111,47 @@ fn check_version(config: &Config) -> Option { msg.push_str("WARNING: The use of `changelog-seen` is deprecated. Please refer to `change-id` option in `config.example.toml` instead.\n"); } - let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap(); - let suggestion = if let Some(id) = config.change_id { - if &id != latest_config_id { - msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); - let change_links: Vec = find_recent_config_change_ids(id) - .iter() - .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}")) - .collect(); - if !change_links.is_empty() { - msg.push_str("To see more detail about these changes, visit the following PRs:\n"); - for link in change_links { - msg.push_str(&format!(" - {link}\n")); - } - } - msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); - format!("update `config.toml` to use `change-id = {latest_config_id}` instead") - } else { + let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id; + let warned_id_path = config.out.join("bootstrap").join(".last-warned-change-id"); + + if let Some(id) = config.change_id { + if id == latest_change_id { return None; } + + if let Ok(last_warned_id) = fs::read_to_string(&warned_id_path) { + if latest_change_id.to_string() == last_warned_id { + return None; + } + } + + let changes = find_recent_config_change_ids(id); + + if !changes.is_empty() { + msg.push_str("There have been changes to x.py since you last updated:\n"); + + for change in changes { + msg.push_str(&format!(" [{}] {}\n", change.severity.to_string(), change.summary)); + msg.push_str(&format!( + " - PR Link https://github.com/rust-lang/rust/pull/{}\n", + change.change_id + )); + } + + msg.push_str("NOTE: to silence this warning, "); + msg.push_str(&format!( + "update `config.toml` to use `change-id = {latest_change_id}` instead" + )); + + if io::stdout().is_terminal() { + t!(fs::write(warned_id_path, latest_change_id.to_string())); + } + } } else { msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); - format!("add `change-id = {latest_config_id}` at the top of `config.toml`") + msg.push_str("NOTE: to silence this warning, "); + msg.push_str(&format!("add `change-id = {latest_change_id}` at the top of `config.toml`")); }; - msg.push_str("note: to silence this warning, "); - msg.push_str(&suggestion); - Some(msg) } diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index 3041fd37ac80a..4dd7f8281a493 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -16,11 +16,11 @@ //! never get replaced. use std::env; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{Child, Command}; use std::time::Instant; -use dylib_util::{dylib_path, dylib_path_var}; +use dylib_util::{dylib_path, dylib_path_var, exe}; #[path = "../utils/bin_helpers.rs"] mod bin_helpers; @@ -29,9 +29,14 @@ mod bin_helpers; mod dylib_util; fn main() { - let args = env::args_os().skip(1).collect::>(); - let arg = |name| args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str()); - + let orig_args = env::args_os().skip(1).collect::>(); + let mut args = orig_args.clone(); + let arg = + |name| orig_args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str()); + + // We don't use the stage in this shim, but let's parse it to make sure that we're invoked + // by bootstrap, or that we provide a helpful error message if not. + bin_helpers::parse_rustc_stage(); let verbose = bin_helpers::parse_rustc_verbose(); // Detect whether or not we're a build script depending on whether --target @@ -44,7 +49,8 @@ fn main() { // determine the version of the compiler, the real compiler needs to be // used. Currently, these two states are differentiated based on whether // --target and -vV is/isn't passed. - let (rustc, libdir) = if target.is_none() && version.is_none() { + let is_build_script = target.is_none() && version.is_none(); + let (rustc, libdir) = if is_build_script { ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR") } else { ("RUSTC_REAL", "RUSTC_LIBDIR") @@ -53,12 +59,47 @@ fn main() { let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"); let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new); - let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc)); + let rustc_real = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc)); let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir)); let mut dylib_path = dylib_path(); dylib_path.insert(0, PathBuf::from(&libdir)); - let mut cmd = Command::new(rustc); + // if we're running clippy, trust cargo-clippy to set clippy-driver appropriately (and don't override it with rustc). + // otherwise, substitute whatever cargo thinks rustc should be with RUSTC_REAL. + // NOTE: this means we ignore RUSTC in the environment. + // FIXME: We might want to consider removing RUSTC_REAL and setting RUSTC directly? + // NOTE: we intentionally pass the name of the host, not the target. + let host = env::var("CFG_COMPILER_BUILD_TRIPLE").unwrap(); + let is_clippy = args[0].to_string_lossy().ends_with(&exe("clippy-driver", &host)); + let rustc_driver = if is_clippy { + if is_build_script { + // Don't run clippy on build scripts (for one thing, we may not have libstd built with + // the appropriate version yet, e.g. for stage 1 std). + // Also remove the `clippy-driver` param in addition to the RUSTC param. + args.drain(..2); + rustc_real + } else { + args.remove(0) + } + } else { + // Cargo doesn't respect RUSTC_WRAPPER for version information >:( + // don't remove the first arg if we're being run as RUSTC instead of RUSTC_WRAPPER. + // Cargo also sometimes doesn't pass the `.exe` suffix on Windows - add it manually. + let current_exe = env::current_exe().expect("couldn't get path to rustc shim"); + let arg0 = exe(args[0].to_str().expect("only utf8 paths are supported"), &host); + if Path::new(&arg0) == current_exe { + args.remove(0); + } + rustc_real + }; + + let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER_REAL") { + let mut cmd = Command::new(wrapper); + cmd.arg(rustc_driver); + cmd + } else { + Command::new(rustc_driver) + }; cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); // Get the name of the crate we're compiling, if any. @@ -111,7 +152,7 @@ fn main() { { cmd.arg("-Ztls-model=initial-exec"); } - } else { + } else if std::env::var("MIRI").is_err() { // Find any host flags that were passed by bootstrap. // The flags are stored in a RUSTC_HOST_FLAGS variable, separated by spaces. if let Ok(flags) = std::env::var("RUSTC_HOST_FLAGS") { @@ -242,7 +283,7 @@ fn main() { if status.success() { std::process::exit(0); - // note: everything below here is unreachable. do not put code that + // NOTE: everything below here is unreachable. do not put code that // should run on success, after this block. } if verbose > 0 { diff --git a/src/bootstrap/src/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs index dbbce6fe22047..90bd822699c1f 100644 --- a/src/bootstrap/src/bin/rustdoc.rs +++ b/src/bootstrap/src/bin/rustdoc.rs @@ -3,7 +3,6 @@ //! See comments in `src/bootstrap/rustc.rs` for more information. use std::env; -use std::ffi::OsString; use std::path::PathBuf; use std::process::Command; @@ -52,15 +51,6 @@ fn main() { if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } - if let Some(linker) = env::var_os("RUSTDOC_LINKER") { - let mut arg = OsString::from("-Clinker="); - arg.push(&linker); - cmd.arg(arg); - } - if let Ok(no_threads) = env::var("RUSTDOC_LLD_NO_THREADS") { - cmd.arg("-Clink-arg=-fuse-ld=lld"); - cmd.arg(format!("-Clink-arg=-Wl,{no_threads}")); - } // Cargo doesn't pass RUSTDOCFLAGS to proc_macros: // https://github.com/rust-lang/cargo/issues/4423 // Thus, if we are on stage 0, we explicitly set `--cfg=bootstrap`. @@ -70,9 +60,7 @@ fn main() { cmd.arg("--cfg=bootstrap"); } cmd.arg("-Zunstable-options"); - // #[cfg(bootstrap)] - cmd.arg("--check-cfg=values(bootstrap)"); - // cmd.arg("--check-cfg=cfg(bootstrap)"); + cmd.arg("--check-cfg=cfg(bootstrap)"); if verbose > 1 { eprintln!( diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 121925b56a056..ecaaf91aec12f 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -376,12 +376,12 @@ impl Step for RustAnalyzer { let compiler = builder.compiler(builder.top_stage, builder.config.build); let target = self.target; - builder.ensure(Std::new(target)); + builder.ensure(Rustc::new(target, builder)); let mut cargo = prepare_tool_cargo( builder, compiler, - Mode::ToolStd, + Mode::ToolRustc, target, cargo_subcommand(builder.kind), "src/tools/rust-analyzer", @@ -414,7 +414,7 @@ impl Step for RustAnalyzer { /// Cargo's output path in a given stage, compiled by a particular /// compiler for the specified target. fn stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf { - builder.cargo_out(compiler, Mode::ToolStd, target).join(".rust-analyzer-check.stamp") + builder.cargo_out(compiler, Mode::ToolRustc, target).join(".rust-analyzer-check.stamp") } } } @@ -463,10 +463,6 @@ macro_rules! tool_check_step { cargo.arg("--all-targets"); } - // Enable internal lints for clippy and rustdoc - // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` - // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 - cargo.rustflag("-Zunstable-options"); let _guard = builder.msg_check(&concat!(stringify!($name), " artifacts").to_lowercase(), target); run_cargo( builder, diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 679770ce0ec78..a3fb330ddfb6f 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -68,6 +68,12 @@ macro_rules! clean_crate_tree { let compiler = self.compiler; let target = compiler.host; let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean"); + + // Since https://github.com/rust-lang/rust/pull/111076 enables + // unstable cargo feature (`public-dependency`), we need to ensure + // that unstable features are enabled before reading libstd Cargo.toml. + cargo.env("RUSTC_BOOTSTRAP", "1"); + for krate in &*self.crates { cargo.arg("-p"); cargo.arg(krate); @@ -139,7 +145,7 @@ fn clean_specific_stage(build: &Build, stage: u32) { fn clean_default(build: &Build) { rm_rf(&build.out.join("tmp")); rm_rf(&build.out.join("dist")); - rm_rf(&build.out.join("bootstrap")); + rm_rf(&build.out.join("bootstrap").join(".last-warned-change-id")); rm_rf(&build.out.join("rustfmt.stamp")); for host in &build.hosts { @@ -178,7 +184,7 @@ fn rm_rf(path: &Path) { && p.file_name().and_then(std::ffi::OsStr::to_str) == Some("bootstrap.exe") { - eprintln!("warning: failed to delete '{}'.", p.display()); + eprintln!("WARNING: failed to delete '{}'.", p.display()); return Ok(()); } Err(e) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 1eed534150bb6..dcc2bf9cd7b07 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -141,7 +141,7 @@ impl Step for Std { if builder.config.keep_stage.contains(&compiler.stage) || builder.config.keep_stage_std.contains(&compiler.stage) { - builder.info("Warning: Using a potentially old libstd. This may not behave well."); + builder.info("WARNING: Using a potentially old libstd. This may not behave well."); copy_third_party_objects(builder, &compiler, target); copy_self_contained_objects(builder, &compiler, target); @@ -413,11 +413,6 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car let mut features = String::new(); - // Cranelift doesn't support `asm`. - if stage != 0 && builder.config.default_codegen_backend().unwrap_or_default() == "cranelift" { - features += " compiler-builtins-no-asm"; - } - if builder.no_std(target) == Some(true) { features += " compiler-builtins-mem"; if !target.starts_with("bpf") { @@ -597,7 +592,9 @@ impl Step for StdLink { .join("stage0/lib/rustlib") .join(&host) .join("codegen-backends"); - builder.cp_r(&stage0_codegen_backends, &sysroot_codegen_backends); + if stage0_codegen_backends.exists() { + builder.cp_r(&stage0_codegen_backends, &sysroot_codegen_backends); + } } } } @@ -822,8 +819,8 @@ impl Step for Rustc { builder.ensure(Std::new(compiler, target)); if builder.config.keep_stage.contains(&compiler.stage) { - builder.info("Warning: Using a potentially old librustc. This may not behave well."); - builder.info("Warning: Use `--keep-stage-std` if you want to rebuild the compiler when it changes"); + builder.info("WARNING: Using a potentially old librustc. This may not behave well."); + builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes"); builder.ensure(RustcLink::from_rustc(self, compiler)); return; } @@ -890,7 +887,9 @@ impl Step for Rustc { } else if let Some(path) = &builder.config.rust_profile_use { if compiler.stage == 1 { cargo.rustflag(&format!("-Cprofile-use={path}")); - cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function"); + if builder.is_verbose() { + cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function"); + } true } else { false @@ -1006,6 +1005,13 @@ pub fn rustc_cargo_env( .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("CFG_VERSION", builder.rust_version()); + // Some tools like Cargo detect their own git information in build scripts. When omit-git-hash + // is enabled in config.toml, we pass this environment variable to tell build scripts to avoid + // detecting git information on their own. + if builder.config.omit_git_hash { + cargo.env("CFG_OMIT_GIT_HASH", "1"); + } + if let Some(backend) = builder.config.default_codegen_backend() { cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend); } @@ -1208,8 +1214,8 @@ fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool { } if needs_codegen_backend_config { run.builder.info( - "Warning: no codegen-backends config matched the requested path to build a codegen backend. \ - Help: add backend to codegen-backends in config.toml.", + "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \ + HELP: add backend to codegen-backends in config.toml.", ); return true; } @@ -1255,7 +1261,7 @@ impl Step for CodegenBackend { if builder.config.keep_stage.contains(&compiler.stage) { builder.info( - "Warning: Using a potentially old codegen backend. \ + "WARNING: Using a potentially old codegen backend. \ This may not behave well.", ); // Codegen backends are linked separately from this step today, so we don't do @@ -1530,14 +1536,14 @@ impl Step for Sysroot { let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust"); if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) { eprintln!( - "warning: creating symbolic link `{}` to `{}` failed with {}", + "WARNING: creating symbolic link `{}` to `{}` failed with {}", sysroot_lib_rustlib_src_rust.display(), builder.src.display(), e, ); if builder.config.rust_remap_debuginfo { eprintln!( - "warning: some `tests/ui` tests will fail when lacking `{}`", + "WARNING: some `tests/ui` tests will fail when lacking `{}`", sysroot_lib_rustlib_src_rust.display(), ); } @@ -1550,7 +1556,7 @@ impl Step for Sysroot { symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust) { eprintln!( - "warning: creating symbolic link `{}` to `{}` failed with {}", + "WARNING: creating symbolic link `{}` to `{}` failed with {}", sysroot_lib_rustlib_rustcsrc_rust.display(), builder.src.display(), e, @@ -1803,10 +1809,6 @@ pub fn run_cargo( is_check: bool, rlib_only_metadata: bool, ) -> Vec { - if builder.config.dry_run() { - return Vec::new(); - } - // `target_root_dir` looks like $dir/$target/release let target_root_dir = stamp.parent().unwrap(); // `target_deps_dir` looks like $dir/$target/release/deps @@ -1913,6 +1915,10 @@ pub fn run_cargo( crate::exit!(1); } + if builder.config.dry_run() { + return Vec::new(); + } + // Ok now we need to actually find all the files listed in `toplevel`. We've // got a list of prefix/extensions and we basically just need to find the // most recent file in the `deps` folder corresponding to each one. @@ -1968,9 +1974,6 @@ pub fn stream_cargo( cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { let mut cargo = Command::from(cargo); - if builder.config.dry_run() { - return true; - } // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. let mut message_format = if builder.config.json_output { @@ -1989,9 +1992,14 @@ pub fn stream_cargo( } builder.verbose(&format!("running: {cargo:?}")); + + if builder.config.dry_run() { + return true; + } + let mut child = match cargo.spawn() { Ok(child) => child, - Err(e) => panic!("failed to execute command: {cargo:?}\nerror: {e}"), + Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"), }; // Spawn Cargo slurping up its JSON output. We'll start building up the @@ -2055,7 +2063,7 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) } let previous_mtime = FileTime::from_last_modification_time(&path.metadata().unwrap()); - // Note: `output` will propagate any errors here. + // NOTE: `output` will propagate any errors here. output(Command::new("strip").arg("--strip-debug").arg(path)); // After running `strip`, we have to set the file modification time to what it was before, diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index b578c5ec29500..c485481b9a1eb 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1298,6 +1298,10 @@ impl Step for CodegenBackend { } fn run(self, builder: &Builder<'_>) -> Option { + if builder.config.dry_run() { + return None; + } + // This prevents rustc_codegen_cranelift from being built for "dist" // or "install" on the stable/beta channels. It is not yet stable and // should not be included. @@ -1305,6 +1309,10 @@ impl Step for CodegenBackend { return None; } + if !builder.config.rust_codegen_backends.contains(&self.backend) { + return None; + } + if self.backend == "cranelift" { if !target_supports_cranelift_backend(self.compiler.host) { builder.info("target not supported by rustc_codegen_cranelift. skipping"); @@ -1343,12 +1351,15 @@ impl Step for CodegenBackend { let backends_dst = PathBuf::from("lib").join(&backends_rel); let backend_name = format!("rustc_codegen_{}", backend); + let mut found_backend = false; for backend in fs::read_dir(&backends_src).unwrap() { let file_name = backend.unwrap().file_name(); if file_name.to_str().unwrap().contains(&backend_name) { tarball.add_file(backends_src.join(file_name), &backends_dst, 0o644); + found_backend = true; } } + assert!(found_backend); Some(tarball.generate()) } @@ -1619,14 +1630,11 @@ impl Step for Extended { prepare("rust-analysis"); prepare("clippy"); prepare("rust-analyzer"); - for tool in &["rust-docs", "rust-demangler", "miri"] { + for tool in &["rust-docs", "rust-demangler", "miri", "rustc-codegen-cranelift"] { if built_tools.contains(tool) { prepare(tool); } } - if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("cranelift")) { - prepare("rustc-codegen-cranelift"); - } // create an 'uninstall' package builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); pkgbuild("uninstall"); @@ -2208,23 +2216,19 @@ impl Step for RustDev { builder.ensure(crate::core::build_steps::llvm::Lld { target }); let src_bindir = builder.llvm_out(target).join("bin"); - // If updating this list, you likely want to change + // If updating this, you likely want to change // src/bootstrap/download-ci-llvm-stamp as well, otherwise local users // will not pick up the extra file until LLVM gets bumped. - for bin in &[ - "llvm-config", - "llvm-ar", - "llvm-objdump", - "llvm-profdata", - "llvm-bcanalyzer", - "llvm-cov", - "llvm-dwp", - "llvm-nm", - "llvm-dwarfdump", - "llvm-dis", - "llvm-tblgen", - ] { - tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755); + // We should include all the build artifacts obtained from a source build, + // so that you can use the downloadable LLVM as if you’ve just run a full source build. + if src_bindir.exists() { + for entry in walkdir::WalkDir::new(&src_bindir) { + let entry = t!(entry); + if entry.file_type().is_file() && !entry.path_is_symlink() { + let name = entry.file_name().to_str().unwrap(); + tarball.add_file(src_bindir.join(name), "bin", 0o755); + } + } } // We don't build LLD on some platforms, so only add it if it exists diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 628a4ece8e904..cf3f5bc983ef0 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -7,8 +7,9 @@ //! Everything here is basically just a shim around calling either `rustbook` or //! `rustdoc`. -use std::fs; +use std::io::{self, Write}; use std::path::{Path, PathBuf}; +use std::{fs, mem}; use crate::core::build_steps::compile; use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool}; @@ -388,6 +389,104 @@ impl Step for Standalone { } } +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Releases { + compiler: Compiler, + target: TargetSelection, +} + +impl Step for Releases { + type Output = (); + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + let builder = run.builder; + run.path("RELEASES.md").alias("releases").default_condition(builder.config.docs) + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Releases { + compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build), + target: run.target, + }); + } + + /// Generates HTML release notes to include in the final docs bundle. + /// + /// This uses the same stylesheet and other tools as Standalone, but the + /// RELEASES.md file is included at the root of the repository and gets + /// the headline added. In the end, the conversion is done by Rustdoc. + fn run(self, builder: &Builder<'_>) { + let target = self.target; + let compiler = self.compiler; + let _guard = builder.msg_doc(compiler, "releases", target); + let out = builder.doc_out(target); + t!(fs::create_dir_all(&out)); + + builder.ensure(Standalone { + compiler: builder.compiler(builder.top_stage, builder.config.build), + target, + }); + + let version_info = builder.ensure(SharedAssets { target: self.target }).version_info; + + let favicon = builder.src.join("src/doc/favicon.inc"); + let footer = builder.src.join("src/doc/footer.inc"); + let full_toc = builder.src.join("src/doc/full-toc.inc"); + + let html = out.join("releases.html"); + let tmppath = out.join("releases.md"); + let inpath = builder.src.join("RELEASES.md"); + let rustdoc = builder.rustdoc(compiler); + if !up_to_date(&inpath, &html) + || !up_to_date(&footer, &html) + || !up_to_date(&favicon, &html) + || !up_to_date(&full_toc, &html) + || !(builder.config.dry_run() + || up_to_date(&version_info, &html) + || up_to_date(&rustdoc, &html)) + { + let mut tmpfile = t!(fs::File::create(&tmppath)); + t!(tmpfile.write_all(b"% Rust Release Notes\n\n")); + t!(io::copy(&mut t!(fs::File::open(&inpath)), &mut tmpfile)); + mem::drop(tmpfile); + let mut cmd = builder.rustdoc_cmd(compiler); + + // Needed for --index-page flag + cmd.arg("-Z").arg("unstable-options"); + + cmd.arg("--html-after-content") + .arg(&footer) + .arg("--html-before-content") + .arg(&version_info) + .arg("--html-in-header") + .arg(&favicon) + .arg("--markdown-no-toc") + .arg("--markdown-css") + .arg("rust.css") + .arg("--index-page") + .arg(&builder.src.join("src/doc/index.md")) + .arg("--markdown-playground-url") + .arg("https://play.rust-lang.org/") + .arg("-o") + .arg(&out) + .arg(&tmppath); + + if !builder.config.docs_minification { + cmd.arg("--disable-minification"); + } + + builder.run(&mut cmd); + } + + // We open doc/RELEASES.html as the default if invoked as `x.py doc --open RELEASES.md` + // with no particular explicit doc requested (e.g. library/core). + if builder.was_invoked_explicitly::(Kind::Doc) { + builder.open_in_browser(&html); + } + } +} + #[derive(Debug, Clone)] pub struct SharedAssetsPaths { pub version_info: PathBuf, @@ -685,19 +784,6 @@ impl Step for Rustc { target, ); - // This uses a shared directory so that librustdoc documentation gets - // correctly built and merged with the rustc documentation. This is - // needed because rustdoc is built in a different directory from - // rustc. rustdoc needs to be able to see everything, for example when - // merging the search index, or generating local (relative) links. - let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc"); - t!(fs::create_dir_all(out_dir.parent().unwrap())); - symlink_dir_force(&builder.config, &out, &out_dir); - // Cargo puts proc macros in `target/doc` even if you pass `--target` - // explicitly (https://github.com/rust-lang/cargo/issues/7677). - let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc"); - symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); - // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc"); cargo.rustdocflag("--document-private-items"); @@ -724,6 +810,7 @@ impl Step for Rustc { let mut to_open = None; + let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc"); for krate in &*self.crates { // Create all crate output directories first to make sure rustdoc uses // relative links. @@ -736,8 +823,29 @@ impl Step for Rustc { } } + // This uses a shared directory so that librustdoc documentation gets + // correctly built and merged with the rustc documentation. + // + // This is needed because rustdoc is built in a different directory from + // rustc. rustdoc needs to be able to see everything, for example when + // merging the search index, or generating local (relative) links. + symlink_dir_force(&builder.config, &out, &out_dir); + // Cargo puts proc macros in `target/doc` even if you pass `--target` + // explicitly (https://github.com/rust-lang/cargo/issues/7677). + let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc"); + symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); + builder.run(&mut cargo.into()); + if !builder.config.dry_run() { + // Sanity check on linked compiler crates + for krate in &*self.crates { + let dir_name = krate.replace("-", "_"); + // Making sure the directory exists and is not empty. + assert!(out.join(&*dir_name).read_dir().unwrap().next().is_some()); + } + } + if builder.paths.iter().any(|path| path.ends_with("compiler")) { // For `x.py doc compiler --open`, open `rustc_middle` by default. let index = out.join("rustc_middle").join("index.html"); @@ -756,10 +864,10 @@ macro_rules! tool_doc { $should_run: literal, $path: literal, $(rustc_tool = $rustc_tool:literal, )? - $(in_tree = $in_tree:literal, )? - [$($extra_arg: literal),+ $(,)?] - $(,)? - ) => { + $(in_tree = $in_tree:literal ,)? + $(is_library = $is_library:expr,)? + $(crates = $crates:expr)? + ) => { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $tool { target: TargetSelection, @@ -812,17 +920,6 @@ macro_rules! tool_doc { SourceType::Submodule }; - // Symlink compiler docs to the output directory of rustdoc documentation. - let out_dirs = [ - builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"), - // Cargo uses a different directory for proc macros. - builder.stage_out(compiler, Mode::ToolRustc).join("doc"), - ]; - for out_dir in out_dirs { - t!(fs::create_dir_all(&out_dir)); - symlink_dir_force(&builder.config, &out, &out_dir); - } - // Build cargo command. let mut cargo = prepare_tool_cargo( builder, @@ -839,9 +936,13 @@ macro_rules! tool_doc { // Only include compiler crates, no dependencies of those, such as `libc`. cargo.arg("--no-deps"); - $( - cargo.arg($extra_arg); - )+ + if false $(|| $is_library)? { + cargo.arg("--lib"); + } + + $(for krate in $crates { + cargo.arg("-p").arg(krate); + })? cargo.rustdocflag("--document-private-items"); // Since we always pass --document-private-items, there's no need to warn about linking to private items. @@ -851,62 +952,68 @@ macro_rules! tool_doc { cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); + let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); + $(for krate in $crates { + let dir_name = krate.replace("-", "_"); + t!(fs::create_dir_all(out_dir.join(&*dir_name))); + })? + + // Symlink compiler docs to the output directory of rustdoc documentation. + symlink_dir_force(&builder.config, &out, &out_dir); + let proc_macro_out_dir = builder.stage_out(compiler, Mode::ToolRustc).join("doc"); + symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); + let _guard = builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); builder.run(&mut cargo.into()); + + if !builder.config.dry_run() { + // Sanity check on linked doc directories + $(for krate in $crates { + let dir_name = krate.replace("-", "_"); + // Making sure the directory exists and is not empty. + assert!(out.join(&*dir_name).read_dir().unwrap().next().is_some()); + })? + } } } } } -tool_doc!( - Rustdoc, - "rustdoc-tool", - "src/tools/rustdoc", - ["-p", "rustdoc", "-p", "rustdoc-json-types"] -); +tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", crates = ["rustdoc", "rustdoc-json-types"]); tool_doc!( Rustfmt, "rustfmt-nightly", "src/tools/rustfmt", - ["-p", "rustfmt-nightly", "-p", "rustfmt-config_proc_macro"], + crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"] ); -tool_doc!(Clippy, "clippy", "src/tools/clippy", ["-p", "clippy_utils"]); -tool_doc!(Miri, "miri", "src/tools/miri", ["-p", "miri"]); +tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_config", "clippy_utils"]); +tool_doc!(Miri, "miri", "src/tools/miri", crates = ["miri"]); tool_doc!( Cargo, "cargo", "src/tools/cargo", rustc_tool = false, in_tree = false, - [ - "-p", + crates = [ "cargo", - "-p", + "cargo-credential", "cargo-platform", - "-p", - "cargo-util", - "-p", - "crates-io", - "-p", "cargo-test-macro", - "-p", "cargo-test-support", - "-p", - "cargo-credential", - "-p", + "cargo-util", + "crates-io", "mdman", - // FIXME: this trips a license check in tidy. - // "-p", - // "resolver-tests", + "rustfix", ] ); -tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["-p", "tidy"]); +tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, crates = ["tidy"]); tool_doc!( Bootstrap, "bootstrap", "src/bootstrap", rustc_tool = false, - ["--lib", "-p", "bootstrap"] + is_library = true, + crates = ["bootstrap"] ); #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 0e260e69c85a6..e792d38b7ea67 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -89,7 +89,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result>, Str return Ok(None); } - get_git_modified_files(Some(&build.config.src), &vec!["rs"]) + get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &vec!["rs"]) } #[derive(serde_derive::Deserialize)] @@ -142,14 +142,17 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { }; if in_working_tree { let untracked_paths_output = output( - build.config.git().arg("status").arg("--porcelain").arg("--untracked-files=normal"), + build + .config + .git() + .arg("status") + .arg("--porcelain") + .arg("-z") + .arg("--untracked-files=normal"), + ); + let untracked_paths = untracked_paths_output.split_terminator('\0').filter_map( + |entry| entry.strip_prefix("?? "), // returns None if the prefix doesn't match ); - let untracked_paths = untracked_paths_output - .lines() - .filter(|entry| entry.starts_with("??")) - .map(|entry| { - entry.split(' ').nth(1).expect("every git status entry should list a path") - }); let mut untracked_count = 0; for untracked_path in untracked_paths { println!("skip untracked path {untracked_path} during rustfmt invocations"); diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 9d03350c7232e..6b4a8f597eab5 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -269,7 +269,7 @@ install!((self, builder, _config), } }; RustDemangler, alias = "rust-demangler", Self::should_build(_config), only_hosts: true, { - // Note: Even though `should_build` may return true for `extended` default tools, + // NOTE: Even though `should_build` may return true for `extended` default tools, // dist::RustDemangler may still return None, unless the target-dependent `profiler` config // is also true, or the `tools` array explicitly includes "rust-demangler". if let Some(tarball) = builder.ensure(dist::RustDemangler { diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 5b45430772167..7c119b0273b7c 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -15,12 +15,13 @@ use std::fs::{self, File}; use std::io; use std::path::{Path, PathBuf}; use std::process::Command; +use std::sync::OnceLock; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; use crate::utils::channel; use crate::utils::helpers::{self, exe, get_clang_cl_resource_dir, output, t, up_to_date}; -use crate::{CLang, GitRepo, Kind}; +use crate::{generate_smart_stamp_hash, CLang, GitRepo, Kind}; use build_helper::ci::CiEnv; use build_helper::git::get_git_merge_base; @@ -105,8 +106,16 @@ pub fn prebuilt_llvm_config( let llvm_cmake_dir = out_dir.join("lib/cmake/llvm"); let res = LlvmResult { llvm_config: build_llvm_config, llvm_cmake_dir }; + static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); + let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { + generate_smart_stamp_hash( + &builder.config.src.join("src/llvm-project"), + &builder.in_tree_llvm_info.sha().unwrap_or_default(), + ) + }); + let stamp = out_dir.join("llvm-finished-building"); - let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha()); + let stamp = HashStamp::new(stamp, Some(smart_stamp_hash)); if stamp.is_done() { if stamp.hash.is_none() { @@ -132,8 +141,8 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { // walk back further to the last bors merge commit that actually changed LLVM. The first // step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD` // in that case. - let closest_upstream = - get_git_merge_base(Some(&config.src)).unwrap_or_else(|_| "HEAD".into()); + let closest_upstream = get_git_merge_base(&config.git_config(), Some(&config.src)) + .unwrap_or_else(|_| "HEAD".into()); let mut rev_list = config.git(); rev_list.args(&[ PathBuf::from("rev-list"), @@ -156,9 +165,9 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { if llvm_sha.is_empty() { eprintln!("error: could not find commit hash for downloading LLVM"); - eprintln!("help: maybe your repository history is too shallow?"); - eprintln!("help: consider disabling `download-ci-llvm`"); - eprintln!("help: or fetch enough history to include one upstream commit"); + eprintln!("HELP: maybe your repository history is too shallow?"); + eprintln!("HELP: consider disabling `download-ci-llvm`"); + eprintln!("HELP: or fetch enough history to include one upstream commit"); panic!(); } @@ -560,11 +569,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { let version = output(cmd.arg("--version")); let mut parts = version.split('.').take(2).filter_map(|s| s.parse::().ok()); if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) { - if major >= 15 { + if major >= 16 { return; } } - panic!("\n\nbad LLVM version: {version}, need >=15.0\n\n") + panic!("\n\nbad LLVM version: {version}, need >=16.0\n\n") } fn configure_cmake( diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 435ebb6df90d0..fe84b95f90c8b 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -1,6 +1,7 @@ use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::t; +use crate::utils::change_tracker::CONFIG_CHANGE_HISTORY; use crate::Config; -use crate::{t, CONFIG_CHANGE_HISTORY}; use sha2::Digest; use std::env::consts::EXE_SUFFIX; use std::fmt::Write as _; @@ -122,6 +123,27 @@ impl Step for Profile { return; } + let path = &run.builder.config.config.clone().unwrap_or(PathBuf::from("config.toml")); + if path.exists() { + eprintln!(); + eprintln!( + "ERROR: you asked for a new config file, but one already exists at `{}`", + t!(path.canonicalize()).display() + ); + + match prompt_user( + "Do you wish to override the existing configuration (which will allow the setup process to continue)?: [y/N]", + ) { + Ok(Some(PromptResult::Yes)) => { + t!(fs::remove_file(path)); + } + _ => { + println!("Exiting."); + crate::exit!(1); + } + } + } + // for Profile, `run.paths` will have 1 and only 1 element // this is because we only accept at most 1 path from user input. // If user calls `x.py setup` without arguments, the interactive TUI @@ -147,6 +169,15 @@ impl Step for Profile { } fn run(self, builder: &Builder<'_>) { + // During ./x.py setup once you select the codegen profile. + // The submodule will be downloaded. It does not work in the + // tarball case since they don't include Git and submodules + // are already included. + if !builder.rust_info().is_from_tarball() { + if self == Profile::Codegen { + builder.update_submodule(&Path::new("src/llvm-project")); + } + } setup(&builder.build.config, self) } } @@ -182,7 +213,7 @@ pub fn setup(config: &Config, profile: Profile) { if profile == Profile::Tools { eprintln!(); eprintln!( - "note: the `tools` profile sets up the `stage2` toolchain (use \ + "NOTE: the `tools` profile sets up the `stage2` toolchain (use \ `rustup toolchain link 'name' build/host/stage2` to use rustc)" ) } @@ -195,21 +226,8 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) { if profile == Profile::None { return; } - if path.exists() { - eprintln!(); - eprintln!( - "error: you asked `x.py` to setup a new config file, but one already exists at `{}`", - path.display() - ); - eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display()); - eprintln!( - "note: this will use the configuration in {}", - profile.include_path(&config.src).display() - ); - crate::exit!(1); - } - let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap(); + let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id; let settings = format!( "# Includes one of the default files in src/bootstrap/defaults\n\ profile = \"{profile}\"\n\ @@ -397,8 +415,8 @@ pub fn interactive_path() -> io::Result { break match parse_with_abbrev(&input) { Ok(profile) => profile, Err(err) => { - eprintln!("error: {err}"); - eprintln!("note: press Ctrl+C to exit"); + eprintln!("ERROR: {err}"); + eprintln!("NOTE: press Ctrl+C to exit"); continue; } }; @@ -427,8 +445,8 @@ fn prompt_user(prompt: &str) -> io::Result> { "p" | "print" => return Ok(Some(PromptResult::Print)), "" => return Ok(None), _ => { - eprintln!("error: unrecognized option '{}'", input.trim()); - eprintln!("note: press Ctrl+C to exit"); + eprintln!("ERROR: unrecognized option '{}'", input.trim()); + eprintln!("NOTE: press Ctrl+C to exit"); } }; } @@ -469,7 +487,8 @@ fn install_git_hook_maybe(config: &Config) -> io::Result<()> { assert!(output.status.success(), "failed to run `git`"); PathBuf::from(t!(String::from_utf8(output.stdout)).trim()) })); - let dst = git.join("hooks").join("pre-push"); + let hooks_dir = git.join("hooks"); + let dst = hooks_dir.join("pre-push"); if dst.exists() { // The git hook has already been set up, or the user already has a custom hook. return Ok(()); @@ -486,11 +505,15 @@ undesirable, simply delete the `pre-push` file from .git/hooks." println!("Ok, skipping installation!"); return Ok(()); } + if !hooks_dir.exists() { + // We need to (try to) create the hooks directory first. + let _ = fs::create_dir(hooks_dir); + } let src = config.src.join("src").join("etc").join("pre-push.sh"); match fs::hard_link(src, &dst) { Err(e) => { eprintln!( - "error: could not create hook {}: do you already have the git hook installed?\n{}", + "ERROR: could not create hook {}: do you already have the git hook installed?\n{}", dst.display(), e ); @@ -526,12 +549,13 @@ impl Step for Vscode { if config.dry_run() { return; } - t!(create_vscode_settings_maybe(&config)); + while !t!(create_vscode_settings_maybe(&config)) {} } } /// Create a `.vscode/settings.json` file for rustc development, or just print it -fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { +/// If this method should be re-called, it returns `false`. +fn create_vscode_settings_maybe(config: &Config) -> io::Result { let (current_hash, historical_hashes) = SETTINGS_HASHES.split_last().unwrap(); let vscode_settings = config.src.join(".vscode").join("settings.json"); // If None, no settings.json exists @@ -544,7 +568,7 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { hasher.update(¤t); let hash = hex::encode(hasher.finalize().as_slice()); if hash == *current_hash { - return Ok(()); + return Ok(true); } else if historical_hashes.contains(&hash.as_str()) { mismatched_settings = Some(true); } else { @@ -556,21 +580,21 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { ); match mismatched_settings { Some(true) => eprintln!( - "warning: existing `.vscode/settings.json` is out of date, x.py will update it" + "WARNING: existing `.vscode/settings.json` is out of date, x.py will update it" ), Some(false) => eprintln!( - "warning: existing `.vscode/settings.json` has been modified by user, x.py will back it up and replace it" + "WARNING: existing `.vscode/settings.json` has been modified by user, x.py will back it up and replace it" ), _ => (), } let should_create = match prompt_user( - "Would you like to create/update `settings.json`, or only print suggested settings?: [y/p/N]", + "Would you like to create/update settings.json? (Press 'p' to preview values): [y/N]", )? { Some(PromptResult::Yes) => true, Some(PromptResult::Print) => false, _ => { println!("Ok, skipping settings!"); - return Ok(()); + return Ok(true); } }; if should_create { @@ -586,7 +610,7 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { // exists and is not current version or outdated, so back it up let mut backup = vscode_settings.clone(); backup.set_extension("json.bak"); - eprintln!("warning: copying `settings.json` to `settings.json.bak`"); + eprintln!("WARNING: copying `settings.json` to `settings.json.bak`"); fs::copy(&vscode_settings, &backup)?; "Updated" } @@ -597,5 +621,5 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { } else { println!("\n{RUST_ANALYZER_SETTINGS}"); } - Ok(()) + Ok(should_create) } diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 82fb10cebe07d..93da27560c65c 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -9,8 +9,13 @@ use crate::core::builder::Builder; /// Suggests a list of possible `x.py` commands to run based on modified files in branch. pub fn suggest(builder: &Builder<'_>, run: bool) { - let suggestions = - builder.tool_cmd(Tool::SuggestTests).output().expect("failed to run `suggest-tests` tool"); + let git_config = builder.config.git_config(); + let suggestions = builder + .tool_cmd(Tool::SuggestTests) + .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository) + .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch) + .output() + .expect("failed to run `suggest-tests` tool"); if !suggestions.status.success() { println!("failed to run `suggest-tests` tool ({})", suggestions.status); @@ -68,6 +73,6 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { build.build(); } } else { - println!("help: consider using the `--run` flag to automatically run suggested tests"); + println!("HELP: consider using the `--run` flag to automatically run suggested tests"); } } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index e2b515a30867b..77a4f2c4cb201 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -29,8 +29,8 @@ use crate::utils; use crate::utils::cache::{Interned, INTERNER}; use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ - self, add_link_lib_path, dylib_path, dylib_path_var, output, t, - target_supports_cranelift_backend, up_to_date, + self, add_link_lib_path, add_rustdoc_cargo_lld_flags, add_rustdoc_lld_flags, dylib_path, + dylib_path_var, output, t, target_supports_cranelift_backend, up_to_date, LldThreads, }; use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests}; use crate::{envify, CLang, DocTests, GitRepo, Mode}; @@ -49,9 +49,9 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[ ("i686-unknown-linux-musl", "x86_64-unknown-linux-musl"), ("i686-pc-windows-msvc", "x86_64-pc-windows-msvc"), ("i686-pc-windows-gnu", "x86_64-pc-windows-gnu"), - ("i686-apple-darwin", "x86_64-apple-darwin"), // ARM Macs don't have a corresponding 32-bit target that they can (easily) // build for, so there is no entry for "aarch64-apple-darwin" here. + // Likewise, i686 for macOS is no longer possible to build. ]; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -271,13 +271,14 @@ impl Step for Cargotest { let _time = helpers::timeit(&builder); let mut cmd = builder.tool_cmd(Tool::CargoTest); - builder.run_delaying_failure( - cmd.arg(&cargo) - .arg(&out_dir) - .args(builder.config.test_args()) - .env("RUSTC", builder.rustc(compiler)) - .env("RUSTDOC", builder.rustdoc(compiler)), - ); + let mut cmd = cmd + .arg(&cargo) + .arg(&out_dir) + .args(builder.config.test_args()) + .env("RUSTC", builder.rustc(compiler)) + .env("RUSTDOC", builder.rustdoc(compiler)); + add_rustdoc_cargo_lld_flags(&mut cmd, builder, compiler.host, LldThreads::No); + builder.run_delaying_failure(cmd); } } @@ -369,7 +370,7 @@ impl Step for RustAnalyzer { // We don't need to build the whole Rust Analyzer for the proc-macro-srv test suite, // but we do need the standard library to be present. - builder.ensure(compile::Std::new(compiler, host)); + builder.ensure(compile::Rustc::new(compiler, host)); let workspace_path = "src/tools/rust-analyzer"; // until the whole RA test suite runs on `i686`, we only run @@ -378,7 +379,7 @@ impl Step for RustAnalyzer { let mut cargo = tool::prepare_tool_cargo( builder, compiler, - Mode::ToolStd, + Mode::ToolRustc, host, "test", crate_path, @@ -862,15 +863,8 @@ impl Step for RustdocTheme { .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("RUSTDOC_REAL", builder.rustdoc(self.compiler)) .env("RUSTC_BOOTSTRAP", "1"); - if let Some(linker) = builder.linker(self.compiler.host) { - cmd.env("RUSTDOC_LINKER", linker); - } - if builder.is_fuse_ld_lld(self.compiler.host) { - cmd.env( - "RUSTDOC_LLD_NO_THREADS", - helpers::lld_flag_no_threads(self.compiler.host.contains("windows")), - ); - } + add_rustdoc_lld_flags(&mut cmd, builder, self.compiler.host, LldThreads::No); + builder.run_delaying_failure(&mut cmd); } } @@ -1005,6 +999,7 @@ impl Step for RustdocGUI { let run = run.suite_path("tests/rustdoc-gui"); run.lazy_default_condition(Box::new(move || { builder.config.nodejs.is_some() + && builder.doc_tests != DocTests::Only && builder .config .npm @@ -1044,6 +1039,8 @@ impl Step for RustdocGUI { cmd.env("RUSTDOC", builder.rustdoc(self.compiler)) .env("RUSTC", builder.rustc(self.compiler)); + add_rustdoc_cargo_lld_flags(&mut cmd, builder, self.compiler.host, LldThreads::No); + for path in &builder.paths { if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) { if !p.ends_with(".goml") { @@ -1127,10 +1124,10 @@ impl Step for Tidy { let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap(); eprintln!( "\ -error: no `rustfmt` binary found in {PATH} -info: `rust.channel` is currently set to \"{CHAN}\" -help: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file -help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`", +ERROR: no `rustfmt` binary found in {PATH} +INFO: `rust.channel` is currently set to \"{CHAN}\" +HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file +HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`", PATH = inferred_rustfmt_dir.display(), CHAN = builder.config.channel, ); @@ -1162,7 +1159,8 @@ help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/tidy") + let default = run.builder.doc_tests != DocTests::Only; + run.path("src/tools/tidy").default_condition(default) } fn make_run(run: RunConfig<'_>) { @@ -1183,7 +1181,7 @@ impl Step for ExpandYamlAnchors { /// appropriate configuration for all our CI providers. This step ensures the tool was called /// by the user before committing CI changes. fn run(self, builder: &Builder<'_>) { - // Note: `.github/` is not included in dist-src tarballs + // NOTE: `.github/` is not included in dist-src tarballs if !builder.src.join(".github/workflows/ci.yml").exists() { builder.info("Skipping YAML anchors check: GitHub Actions config not found"); return; @@ -1305,6 +1303,47 @@ macro_rules! test_definitions { }; } +/// Declares an alias for running the [`Coverage`] tests in only one mode. +/// Adapted from [`test_definitions`]. +macro_rules! coverage_test_alias { + ($name:ident { + alias_and_mode: $alias_and_mode:expr, + default: $default:expr, + only_hosts: $only_hosts:expr $(,)? + }) => { + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub struct $name { + pub compiler: Compiler, + pub target: TargetSelection, + } + + impl $name { + const MODE: &'static str = $alias_and_mode; + } + + impl Step for $name { + type Output = (); + const DEFAULT: bool = $default; + const ONLY_HOSTS: bool = $only_hosts; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias($alias_and_mode) + } + + fn make_run(run: RunConfig<'_>) { + let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); + + run.builder.ensure($name { compiler, target: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + Coverage { compiler: self.compiler, target: self.target } + .run_unified_suite(builder, Self::MODE) + } + } + }; +} + default_test!(Ui { path: "tests/ui", mode: "ui", suite: "ui" }); default_test!(RunPassValgrind { @@ -1349,17 +1388,70 @@ host_test!(RunMakeFullDeps { default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" }); -default_test!(CoverageMap { - path: "tests/coverage-map", - mode: "coverage-map", - suite: "coverage-map" +/// Custom test step that is responsible for running the coverage tests +/// in multiple different modes. +/// +/// Each individual mode also has its own alias that will run the tests in +/// just that mode. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Coverage { + pub compiler: Compiler, + pub target: TargetSelection, +} + +impl Coverage { + const PATH: &'static str = "tests/coverage"; + const SUITE: &'static str = "coverage"; + + fn run_unified_suite(&self, builder: &Builder<'_>, mode: &'static str) { + builder.ensure(Compiletest { + compiler: self.compiler, + target: self.target, + mode, + suite: Self::SUITE, + path: Self::PATH, + compare_mode: None, + }) + } +} + +impl Step for Coverage { + type Output = (); + const DEFAULT: bool = false; + const ONLY_HOSTS: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.suite_path(Self::PATH) + } + + fn make_run(run: RunConfig<'_>) { + let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); + + run.builder.ensure(Coverage { compiler, target: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + self.run_unified_suite(builder, CoverageMap::MODE); + self.run_unified_suite(builder, CoverageRun::MODE); + } +} + +// Aliases for running the coverage tests in only one mode. +coverage_test_alias!(CoverageMap { + alias_and_mode: "coverage-map", + default: true, + only_hosts: false, +}); +coverage_test_alias!(CoverageRun { + alias_and_mode: "coverage-run", + default: true, + only_hosts: true, }); -host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" }); -host_test!(RunCoverageRustdoc { - path: "tests/run-coverage-rustdoc", - mode: "run-coverage", - suite: "run-coverage-rustdoc" +host_test!(CoverageRunRustdoc { + path: "tests/coverage-run-rustdoc", + mode: "coverage-run", + suite: "coverage-run-rustdoc" }); // For the mir-opt suite we do not use macros, as we need custom behavior when blessing. @@ -1470,12 +1562,16 @@ impl Step for Compiletest { /// compiletest `mode` and `suite` arguments. For example `mode` can be /// "run-pass" or `suite` can be something like `debuginfo`. fn run(self, builder: &Builder<'_>) { + if builder.doc_tests == DocTests::Only { + return; + } + if builder.top_stage == 0 && env::var("COMPILETEST_FORCE_STAGE0").is_err() { eprintln!("\ -error: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail -help: to test the compiler, use `--stage 1` instead -help: to test the standard library, use `--stage 0 library/std` instead -note: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`." +ERROR: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail +HELP: to test the compiler, use `--stage 1` instead +HELP: to test the standard library, use `--stage 0 library/std` instead +NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`." ); crate::exit!(1); } @@ -1546,7 +1642,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the || (mode == "ui" && is_rustdoc) || mode == "js-doc-test" || mode == "rustdoc-json" - || suite == "run-coverage-rustdoc" + || suite == "coverage-run-rustdoc" { cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler)); } @@ -1568,7 +1664,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--coverage-dump-path").arg(coverage_dump); } - if mode == "run-coverage" { + if mode == "coverage-run" { // The demangler doesn't need the current compiler, so we can avoid // unnecessary rebuilds by using the bootstrap compiler instead. let rust_demangler = builder @@ -1731,6 +1827,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--json"); + if builder.config.rust_debug_assertions_std { + cmd.arg("--with-debug-assertions"); + }; + let mut llvm_components_passed = false; let mut copts_passed = false; if builder.config.llvm_enabled() { @@ -1760,11 +1860,11 @@ note: if you're sure you want to do this, please open an issue as to why. In the } if !builder.config.dry_run() - && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "run-coverage") + && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "coverage-run") { // The llvm/bin directory contains many useful cross-platform // tools. Pass the path to run-make tests so they can use them. - // (The run-coverage tests also need these tools to process + // (The coverage-run tests also need these tools to process // coverage reports.) let llvm_bin_path = llvm_config .parent() @@ -1838,6 +1938,11 @@ note: if you're sure you want to do this, please open an issue as to why. In the } } } + + // Some UI tests trigger behavior in rustc where it reads $CARGO and changes behavior if it exists. + // To make the tests work that rely on it not being set, make sure it is not set. + cmd.env_remove("CARGO"); + cmd.env("RUSTC_BOOTSTRAP", "1"); // Override the rustc version used in symbol hashes to reduce the amount of normalization // needed when diffing test output. @@ -1877,6 +1982,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--git-hash"); } + let git_config = builder.config.git_config(); + cmd.arg("--git-repository").arg(git_config.git_repository); + cmd.arg("--nightly-branch").arg(git_config.nightly_branch); + builder.ci_env.force_coloring_in_ci(&mut cmd); #[cfg(feature = "build-metrics")] @@ -2224,6 +2333,8 @@ impl Step for CrateLibrustc { } fn run(self, builder: &Builder<'_>) { + builder.ensure(compile::Std::new(self.compiler, self.target)); + builder.ensure(Crate { compiler: self.compiler, target: self.target, diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index d5f759ea159aa..37cd96e7c63ec 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -203,6 +203,16 @@ pub fn prepare_tool_cargo( if !features.is_empty() { cargo.arg("--features").arg(&features.join(", ")); } + + // Enable internal lints for clippy and rustdoc + // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` + // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 + // + // NOTE: We unconditionally set this here to avoid recompiling tools between `x check $tool` + // and `x test $tool` executions. + // See https://github.com/rust-lang/rust/issues/116538 + cargo.rustflag("-Zunstable-options"); + cargo } @@ -422,7 +432,7 @@ impl Step for Rustdoc { fn make_run(run: RunConfig<'_>) { run.builder.ensure(Rustdoc { - // Note: this is somewhat unique in that we actually want a *target* + // NOTE: this is somewhat unique in that we actually want a *target* // compiler here, because rustdoc *is* a compiler. We won't be using // this as the compiler to build with, but rather this is "what // compiler are we producing"? @@ -454,7 +464,7 @@ impl Step for Rustdoc { // compiler, since you do just as much work. if !builder.config.dry_run() && builder.download_rustc() && build_compiler.stage == 0 { println!( - "warning: `download-rustc` does nothing when building stage1 tools; consider using `--stage 2` instead" + "WARNING: `download-rustc` does nothing when building stage1 tools; consider using `--stage 2` instead" ); } @@ -603,8 +613,7 @@ pub struct RustAnalyzer { } impl RustAnalyzer { - pub const ALLOW_FEATURES: &'static str = - "proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink"; + pub const ALLOW_FEATURES: &'static str = "rustc_private,proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink"; } impl Step for RustAnalyzer { @@ -636,7 +645,7 @@ impl Step for RustAnalyzer { compiler: self.compiler, target: self.target, tool: "rust-analyzer", - mode: Mode::ToolStd, + mode: Mode::ToolRustc, path: "src/tools/rust-analyzer", extra_features: vec!["rust-analyzer/in-rust-tree".to_owned()], is_optional_tool: false, @@ -787,9 +796,9 @@ macro_rules! tool_extended { } } -// Note: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs` +// NOTE: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs` // to make `./x.py build ` work. -// Note: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to +// NOTE: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to // invoke Cargo to build bootstrap. See the comment there for more details. tool_extended!((self, builder), Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true; diff --git a/src/bootstrap/src/core/build_steps/toolstate.rs b/src/bootstrap/src/core/build_steps/toolstate.rs index f892577ccbf78..a451f92b6bcbb 100644 --- a/src/bootstrap/src/core/build_steps/toolstate.rs +++ b/src/bootstrap/src/core/build_steps/toolstate.rs @@ -172,7 +172,7 @@ impl Step for ToolStateCheck { for (tool, _) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) { if !toolstates.contains_key(*tool) { did_error = true; - eprintln!("error: Tool `{tool}` was not recorded in tool state."); + eprintln!("ERROR: Tool `{tool}` was not recorded in tool state."); } } @@ -190,7 +190,7 @@ impl Step for ToolStateCheck { if state != ToolState::TestPass { if !is_nightly { did_error = true; - eprintln!("error: Tool `{tool}` should be test-pass but is {state}"); + eprintln!("ERROR: Tool `{tool}` should be test-pass but is {state}"); } else if in_beta_week { let old_state = old_toolstate .iter() @@ -200,14 +200,14 @@ impl Step for ToolStateCheck { if state < old_state { did_error = true; eprintln!( - "error: Tool `{tool}` has regressed from {old_state} to {state} during beta week." + "ERROR: Tool `{tool}` has regressed from {old_state} to {state} during beta week." ); } else { // This warning only appears in the logs, which most // people won't read. It's mostly here for testing and // debugging. eprintln!( - "warning: Tool `{tool}` is not test-pass (is `{state}`), \ + "WARNING: Tool `{tool}` is not test-pass (is `{state}`), \ this should be fixed before beta is branched." ); } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 44cdbe38de365..43d9a14661c37 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -10,6 +10,7 @@ use std::io::{BufRead, BufReader}; use std::ops::Deref; use std::path::{Path, PathBuf}; use std::process::Command; +use std::sync::OnceLock; use std::time::{Duration, Instant}; use crate::core::build_steps::llvm; @@ -18,18 +19,19 @@ use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, s use crate::core::config::flags::{Color, Subcommand}; use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection}; use crate::utils::cache::{Cache, Interned, INTERNER}; -use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t}; +use crate::utils::helpers::{ + self, add_dylib_path, add_link_lib_path, add_rustdoc_lld_flags, dylib_path, dylib_path_var, + exe, libdir, output, t, LldThreads, +}; use crate::Crate; use crate::EXTRA_CHECK_CFGS; use crate::{Build, CLang, DocTests, GitRepo, Mode}; pub use crate::Compiler; -// FIXME: -// - use std::lazy for `Lazy` -// - use std::cell for `OnceCell` -// Once they get stabilized and reach beta. + use clap::ValueEnum; -use once_cell::sync::{Lazy, OnceCell}; +// FIXME: replace with std::lazy after it gets stabilized and reaches beta +use once_cell::sync::Lazy; #[cfg(test)] #[path = "../tests/builder.rs"] @@ -386,13 +388,13 @@ impl StepDescription { } if !paths.is_empty() { - eprintln!("error: no `{}` rules matched {:?}", builder.kind.as_str(), paths,); + eprintln!("ERROR: no `{}` rules matched {:?}", builder.kind.as_str(), paths,); eprintln!( - "help: run `x.py {} --help --verbose` to show a list of available paths", + "HELP: run `x.py {} --help --verbose` to show a list of available paths", builder.kind.as_str() ); eprintln!( - "note: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`" + "NOTE: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`" ); crate::exit!(1); } @@ -495,7 +497,7 @@ impl<'a> ShouldRun<'a> { /// /// [`path`]: ShouldRun::path pub fn paths(mut self, paths: &[&str]) -> Self { - static SUBMODULES_PATHS: OnceCell> = OnceCell::new(); + static SUBMODULES_PATHS: OnceLock> = OnceLock::new(); let init_submodules_paths = |src: &PathBuf| { let file = File::open(src.join(".gitmodules")).unwrap(); @@ -727,8 +729,9 @@ impl<'a> Builder<'a> { test::Tidy, test::Ui, test::RunPassValgrind, + test::Coverage, test::CoverageMap, - test::RunCoverage, + test::CoverageRun, test::MirOpt, test::Codegen, test::CodegenUnits, @@ -739,7 +742,7 @@ impl<'a> Builder<'a> { test::CodegenCranelift, test::CodegenGCC, test::Rustdoc, - test::RunCoverageRustdoc, + test::CoverageRunRustdoc, test::Pretty, test::Crate, test::CrateLibrustc, @@ -809,6 +812,7 @@ impl<'a> Builder<'a> { doc::StyleGuide, doc::Tidy, doc::Bootstrap, + doc::Releases, ), Kind::Dist => describe!( dist::Docs, @@ -1150,6 +1154,43 @@ impl<'a> Builder<'a> { self.ensure(tool::Rustdoc { compiler }) } + pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> Command { + let initial_sysroot_bin = self.initial_rustc.parent().unwrap(); + // Set PATH to include the sysroot bin dir so clippy can find cargo. + let path = t!(env::join_paths( + // The sysroot comes first in PATH to avoid using rustup's cargo. + std::iter::once(PathBuf::from(initial_sysroot_bin)) + .chain(env::split_paths(&t!(env::var("PATH")))) + )); + + if run_compiler.stage == 0 { + // `ensure(Clippy { stage: 0 })` *builds* clippy with stage0, it doesn't use the beta clippy. + let cargo_clippy = self.build.config.download_clippy(); + let mut cmd = Command::new(cargo_clippy); + cmd.env("PATH", &path); + return cmd; + } + + let build_compiler = self.compiler(run_compiler.stage - 1, self.build.build); + self.ensure(tool::Clippy { + compiler: build_compiler, + target: self.build.build, + extra_features: vec![], + }); + let cargo_clippy = self.ensure(tool::CargoClippy { + compiler: build_compiler, + target: self.build.build, + extra_features: vec![], + }); + let mut dylib_path = dylib_path(); + dylib_path.insert(0, self.sysroot(run_compiler).join("lib")); + + let mut cmd = Command::new(cargo_clippy.unwrap()); + cmd.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + cmd.env("PATH", path); + cmd + } + pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command { let mut cmd = Command::new(&self.bootstrap_out.join("rustdoc")); cmd.env("RUSTC_STAGE", compiler.stage.to_string()) @@ -1172,9 +1213,7 @@ impl<'a> Builder<'a> { cmd.env_remove("MAKEFLAGS"); cmd.env_remove("MFLAGS"); - if let Some(linker) = self.linker(compiler.host) { - cmd.env("RUSTDOC_LINKER", linker); - } + add_rustdoc_lld_flags(&mut cmd, self, compiler.host, LldThreads::Yes); cmd } @@ -1200,7 +1239,12 @@ impl<'a> Builder<'a> { target: TargetSelection, cmd: &str, ) -> Command { - let mut cargo = Command::new(&self.initial_cargo); + let mut cargo = if cmd == "clippy" { + self.cargo_clippy_cmd(compiler) + } else { + Command::new(&self.initial_cargo) + }; + // Run cargo from the source root so it can find .cargo/config. // This matters when using vendoring and the working directory is outside the repository. cargo.current_dir(&self.src); @@ -1324,6 +1368,23 @@ impl<'a> Builder<'a> { compiler.stage }; + // We synthetically interpret a stage0 compiler used to build tools as a + // "raw" compiler in that it's the exact snapshot we download. Normally + // the stage0 build means it uses libraries build by the stage0 + // compiler, but for tools we just use the precompiled libraries that + // we've downloaded + let use_snapshot = mode == Mode::ToolBootstrap; + assert!(!use_snapshot || stage == 0 || self.local_rebuild); + + let maybe_sysroot = self.sysroot(compiler); + let sysroot = if use_snapshot { self.rustc_snapshot_sysroot() } else { &maybe_sysroot }; + let libdir = self.rustc_libdir(compiler); + + let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8"); + if !matches!(self.config.dry_run, DryRun::SelfCheck) { + self.verbose_than(0, &format!("using sysroot {sysroot_str}")); + } + let mut rustflags = Rustflags::new(target); if stage != 0 { if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") { @@ -1335,41 +1396,16 @@ impl<'a> Builder<'a> { cargo.args(s.split_whitespace()); } rustflags.env("RUSTFLAGS_BOOTSTRAP"); - if cmd == "clippy" { - // clippy overwrites sysroot if we pass it to cargo. - // Pass it directly to clippy instead. - // NOTE: this can't be fixed in clippy because we explicitly don't set `RUSTC`, - // so it has no way of knowing the sysroot. - rustflags.arg("--sysroot"); - rustflags.arg( - self.sysroot(compiler) - .as_os_str() - .to_str() - .expect("sysroot must be valid UTF-8"), - ); - // Only run clippy on a very limited subset of crates (in particular, not build scripts). - cargo.arg("-Zunstable-options"); - // Explicitly does *not* set `--cfg=bootstrap`, since we're using a nightly clippy. - let host_version = Command::new("rustc").arg("--version").output().map_err(|_| ()); - let output = host_version.and_then(|output| { - if output.status.success() { - Ok(output) - } else { - Err(()) - } - }).unwrap_or_else(|_| { - eprintln!( - "error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component" - ); - eprintln!("help: try `rustup component add clippy`"); - crate::exit!(1); - }); - if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") { - rustflags.arg("--cfg=bootstrap"); - } - } else { - rustflags.arg("--cfg=bootstrap"); - } + rustflags.arg("--cfg=bootstrap"); + } + + if cmd == "clippy" { + // clippy overwrites sysroot if we pass it to cargo. + // Pass it directly to clippy instead. + // NOTE: this can't be fixed in clippy because we explicitly don't set `RUSTC`, + // so it has no way of knowing the sysroot. + rustflags.arg("--sysroot"); + rustflags.arg(sysroot_str); } let use_new_symbol_mangling = match self.config.rust_new_symbol_mangling { @@ -1403,9 +1439,6 @@ impl<'a> Builder<'a> { rustflags.arg("-Zunstable-options"); } - // #[cfg(bootstrap)] - let use_new_check_cfg_syntax = self.local_rebuild; - // Enable compile-time checking of `cfg` names, values and Cargo `features`. // // Note: `std`, `alloc` and `core` imports some dependencies by #[path] (like @@ -1413,17 +1446,9 @@ impl<'a> Builder<'a> { // features but cargo isn't involved in the #[path] process and so cannot pass the // complete list of features, so for that reason we don't enable checking of // features for std crates. - if use_new_check_cfg_syntax { - cargo.arg("-Zcheck-cfg"); - if mode == Mode::Std { - rustflags.arg("--check-cfg=cfg(feature,values(any()))"); - } - } else { - cargo.arg(if mode != Mode::Std { - "-Zcheck-cfg=names,values,output,features" - } else { - "-Zcheck-cfg=names,values,output" - }); + cargo.arg("-Zcheck-cfg"); + if mode == Mode::Std { + rustflags.arg("--check-cfg=cfg(feature,values(any()))"); } // Add extra cfg not defined in/by rustc @@ -1444,12 +1469,8 @@ impl<'a> Builder<'a> { .collect::(), None => String::new(), }; - if use_new_check_cfg_syntax { - let values = values.strip_prefix(",").unwrap_or(&values); // remove the first `,` - rustflags.arg(&format!("--check-cfg=cfg({name},values({values}))")); - } else { - rustflags.arg(&format!("--check-cfg=values({name}{values})")); - } + let values = values.strip_prefix(",").unwrap_or(&values); // remove the first `,` + rustflags.arg(&format!("--check-cfg=cfg({name},values({values}))")); } } @@ -1465,11 +1486,7 @@ impl<'a> Builder<'a> { // We also declare that the flag is expected, which we need to do to not // get warnings about it being unexpected. hostflags.arg("-Zunstable-options"); - if use_new_check_cfg_syntax { - hostflags.arg("--check-cfg=cfg(bootstrap)"); - } else { - hostflags.arg("--check-cfg=values(bootstrap)"); - } + hostflags.arg("--check-cfg=cfg(bootstrap)"); // FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`, // but this breaks CI. At the very least, stage0 `rustdoc` needs `--cfg bootstrap`. See @@ -1583,18 +1600,6 @@ impl<'a> Builder<'a> { let want_rustdoc = self.doc_tests != DocTests::No; - // We synthetically interpret a stage0 compiler used to build tools as a - // "raw" compiler in that it's the exact snapshot we download. Normally - // the stage0 build means it uses libraries build by the stage0 - // compiler, but for tools we just use the precompiled libraries that - // we've downloaded - let use_snapshot = mode == Mode::ToolBootstrap; - assert!(!use_snapshot || stage == 0 || self.local_rebuild); - - let maybe_sysroot = self.sysroot(compiler); - let sysroot = if use_snapshot { self.rustc_snapshot_sysroot() } else { &maybe_sysroot }; - let libdir = self.rustc_libdir(compiler); - // Clear the output directory if the real rustc we're using has changed; // Cargo cannot detect this as it thinks rustc is bootstrap/debug/rustc. // @@ -1630,10 +1635,19 @@ impl<'a> Builder<'a> { ) .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir()) .env("RUSTC_BREAK_ON_ICE", "1"); - // Clippy support is a hack and uses the default `cargo-clippy` in path. - // Don't override RUSTC so that the `cargo-clippy` in path will be run. - if cmd != "clippy" { - cargo.env("RUSTC", self.bootstrap_out.join("rustc")); + + // Set RUSTC_WRAPPER to the bootstrap shim, which switches between beta and in-tree + // sysroot depending on whether we're building build scripts. + // NOTE: we intentionally use RUSTC_WRAPPER so that we can support clippy - RUSTC is not + // respected by clippy-driver; RUSTC_WRAPPER happens earlier, before clippy runs. + cargo.env("RUSTC_WRAPPER", self.bootstrap_out.join("rustc")); + // NOTE: we also need to set RUSTC so cargo can run `rustc -vV`; apparently that ignores RUSTC_WRAPPER >:( + cargo.env("RUSTC", self.bootstrap_out.join("rustc")); + + // Someone might have set some previous rustc wrapper (e.g. + // sccache) before bootstrap overrode it. Respect that variable. + if let Some(existing_wrapper) = env::var_os("RUSTC_WRAPPER") { + cargo.env("RUSTC_WRAPPER_REAL", existing_wrapper); } // Dealing with rpath here is a little special, so let's go into some @@ -1891,7 +1905,6 @@ impl<'a> Builder<'a> { // some code doesn't go through this `rustc` wrapper. lint_flags.push("-Wrust_2018_idioms"); lint_flags.push("-Wunused_lifetimes"); - lint_flags.push("-Wsemicolon_in_expressions_from_macros"); if self.config.deny_warnings { lint_flags.push("-Dwarnings"); @@ -1981,6 +1994,16 @@ impl<'a> Builder<'a> { rustflags.arg("-Ccontrol-flow-guard"); } + // If EHCont Guard is enabled, pass the `-Zehcont-guard` flag to rustc when compiling the + // standard library, since this might be linked into the final outputs produced by rustc. + // Since this mitigation is only available on Windows, only enable it for the standard + // library in case the compiler is run on a non-Windows platform. + // This is not needed for stage 0 artifacts because these will only be used for building + // the stage 1 compiler. + if cfg!(windows) && mode == Mode::Std && self.config.ehcont_guard && compiler.stage >= 1 { + rustflags.arg("-Zehcont-guard"); + } + // For `cargo doc` invocations, make rustdoc print the Rust version into the docs // This replaces spaces with tabs because RUSTDOCFLAGS does not // support arguments with regular spaces. Hopefully someday Cargo will @@ -1991,7 +2014,11 @@ impl<'a> Builder<'a> { // Environment variables *required* throughout the build // // FIXME: should update code to not require this env var + + // The host this new compiler will *run* on. cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple); + // The host this new compiler is being *built* on. + cargo.env("CFG_COMPILER_BUILD_TRIPLE", compiler.host.triple); // Set this for all builds to make sure doc builds also get it. cargo.env("CFG_RELEASE_CHANNEL", &self.config.channel); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f56e46010f371..22e8ce8365b1f 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -17,19 +17,21 @@ use std::io::IsTerminal; use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; +use std::sync::OnceLock; use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; +use crate::core::build_steps::llvm; use crate::core::config::flags::{Color, Flags, Warnings}; use crate::utils::cache::{Interned, INTERNER}; use crate::utils::channel::{self, GitInfo}; use crate::utils::helpers::{exe, output, t}; use build_helper::exit; -use once_cell::sync::OnceCell; use semver::Version; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; pub use crate::core::config::flags::Subcommand; +use build_helper::git::GitConfig; macro_rules! check_ci_llvm { ($name:expr) => { @@ -246,6 +248,7 @@ pub struct Config { pub local_rebuild: bool, pub jemalloc: bool, pub control_flow_guard: bool, + pub ehcont_guard: bool, // dist misc pub dist_sign_folder: Option, @@ -318,6 +321,7 @@ pub struct Stage0Config { pub artifacts_server: String, pub artifacts_with_llvm_assertions_server: String, pub git_merge_commit_email: String, + pub git_repository: String, pub nightly_branch: String, } #[derive(Default, Deserialize, Clone)] @@ -1016,6 +1020,7 @@ define_config! { test_compare_mode: Option = "test-compare-mode", llvm_libunwind: Option = "llvm-libunwind", control_flow_guard: Option = "control-flow-guard", + ehcont_guard: Option = "ehcont-guard", new_symbol_mangling: Option = "new-symbol-mangling", profile_generate: Option = "profile-generate", profile_use: Option = "profile-use", @@ -1072,6 +1077,7 @@ impl Config { config.bindir = "bin".into(); config.dist_include_mingw_linker = true; config.dist_compression_profile = "fast".into(); + config.rustc_parallel = true; config.stdout_is_tty = std::io::stdout().is_terminal(); config.stderr_is_tty = std::io::stderr().is_terminal(); @@ -1429,7 +1435,9 @@ impl Config { set(&mut config.use_lld, rust.use_lld); set(&mut config.lld_enabled, rust.lld); set(&mut config.llvm_tools_enabled, rust.llvm_tools); - config.rustc_parallel = rust.parallel_compiler.unwrap_or(false); + config.rustc_parallel = rust + .parallel_compiler + .unwrap_or(config.channel == "dev" || config.channel == "nightly"); config.rustc_default_linker = rust.default_linker; config.musl_root = rust.musl_root.map(PathBuf::from); config.save_toolstates = rust.save_toolstates.map(PathBuf::from); @@ -1446,6 +1454,7 @@ impl Config { config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit; set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo); set(&mut config.control_flow_guard, rust.control_flow_guard); + set(&mut config.ehcont_guard, rust.ehcont_guard); config.llvm_libunwind_default = rust .llvm_libunwind .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")); @@ -1458,7 +1467,7 @@ impl Config { 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. \ + 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}'."); } @@ -1527,17 +1536,7 @@ impl Config { config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default()); let asserts = llvm_assertions.unwrap_or(false); - config.llvm_from_ci = match llvm.download_ci_llvm { - Some(StringOrBool::String(s)) => { - assert_eq!(s, "if-available", "unknown option `{s}` for download-ci-llvm"); - crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts) - } - Some(StringOrBool::Bool(b)) => b, - None => { - config.channel == "dev" - && crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts) - } - }; + config.llvm_from_ci = config.parse_download_ci_llvm(llvm.download_ci_llvm, asserts); if config.llvm_from_ci { // None of the LLVM options, except assertions, are supported @@ -1812,9 +1811,9 @@ impl Config { } (channel, version) => { let src = self.src.display(); - eprintln!("error: failed to determine artifact channel and/or version"); + eprintln!("ERROR: failed to determine artifact channel and/or version"); eprintln!( - "help: consider using a git checkout or ensure these files are readable" + "HELP: consider using a git checkout or ensure these files are readable" ); if let Err(channel) = channel { eprintln!("reading {src}/src/ci/channel failed: {channel:?}"); @@ -1908,7 +1907,7 @@ impl Config { } pub(crate) fn download_rustc_commit(&self) -> Option<&str> { - static DOWNLOAD_RUSTC: OnceCell> = OnceCell::new(); + static DOWNLOAD_RUSTC: OnceLock> = OnceLock::new(); if self.dry_run() && DOWNLOAD_RUSTC.get().is_none() { // avoid trying to actually download the commit return self.download_rustc_commit.as_deref(); @@ -2006,6 +2005,13 @@ impl Config { self.rust_codegen_backends.get(0).cloned() } + pub fn git_config(&self) -> GitConfig<'_> { + GitConfig { + git_repository: &self.stage0_metadata.config.git_repository, + nightly_branch: &self.stage0_metadata.config.nightly_branch, + } + } + pub fn check_build_rustc_version(&self, rustc_path: &str) { if self.dry_run() { return; @@ -2070,10 +2076,10 @@ impl Config { ); let commit = merge_base.trim_end(); if commit.is_empty() { - println!("error: could not find commit hash for downloading rustc"); - println!("help: maybe your repository history is too shallow?"); - println!("help: consider disabling `download-rustc`"); - println!("help: or fetch enough history to include one upstream commit"); + println!("ERROR: could not find commit hash for downloading rustc"); + println!("HELP: maybe your repository history is too shallow?"); + println!("HELP: consider disabling `download-rustc`"); + println!("HELP: or fetch enough history to include one upstream commit"); crate::exit!(1); } @@ -2087,20 +2093,110 @@ impl Config { if if_unchanged { if self.verbose > 0 { println!( - "warning: saw changes to compiler/ or library/ since {commit}; \ + "WARNING: saw changes to compiler/ or library/ since {commit}; \ ignoring `download-rustc`" ); } return None; } println!( - "warning: `download-rustc` is enabled, but there are changes to \ + "WARNING: `download-rustc` is enabled, but there are changes to \ compiler/ or library/" ); } Some(commit.to_string()) } + + fn parse_download_ci_llvm( + &self, + download_ci_llvm: Option, + asserts: bool, + ) -> bool { + match download_ci_llvm { + None => self.channel == "dev" && llvm::is_ci_llvm_available(&self, asserts), + Some(StringOrBool::Bool(b)) => b, + // FIXME: "if-available" is deprecated. Remove this block later (around mid 2024) + // to not break builds between the recent-to-old checkouts. + Some(StringOrBool::String(s)) if s == "if-available" => { + llvm::is_ci_llvm_available(&self, asserts) + } + Some(StringOrBool::String(s)) if s == "if-unchanged" => { + // Git is needed to track modifications here, but tarball source is not available. + // If not modified here or built through tarball source, we maintain consistency + // with '"if available"'. + if !self.rust_info.is_from_tarball() + && self + .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) + .is_none() + { + // there are some untracked changes in the the given paths. + false + } else { + llvm::is_ci_llvm_available(&self, asserts) + } + } + Some(StringOrBool::String(other)) => { + panic!("unrecognized option for download-ci-llvm: {:?}", other) + } + } + } + + /// Returns the last commit in which any of `modified_paths` were changed, + /// or `None` if there are untracked changes in the working directory and `if_unchanged` is true. + pub fn last_modified_commit( + &self, + modified_paths: &[&str], + option_name: &str, + if_unchanged: bool, + ) -> Option { + // Handle running from a directory other than the top level + let top_level = output(self.git().args(&["rev-parse", "--show-toplevel"])); + let top_level = top_level.trim_end(); + + // Look for a version to compare to based on the current commit. + // Only commits merged by bors will have CI artifacts. + let merge_base = output( + self.git() + .arg("rev-list") + .arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email)) + .args(&["-n1", "--first-parent", "HEAD"]), + ); + let commit = merge_base.trim_end(); + if commit.is_empty() { + println!("error: could not find commit hash for downloading components from CI"); + println!("help: maybe your repository history is too shallow?"); + println!("help: consider disabling `{option_name}`"); + println!("help: or fetch enough history to include one upstream commit"); + crate::exit!(1); + } + + // Warn if there were changes to the compiler or standard library since the ancestor commit. + let mut git = self.git(); + git.args(&["diff-index", "--quiet", &commit, "--"]); + + for path in modified_paths { + git.arg(format!("{top_level}/{path}")); + } + + let has_changes = !t!(git.status()).success(); + if has_changes { + if if_unchanged { + if self.verbose > 0 { + println!( + "warning: saw changes to one of {modified_paths:?} since {commit}; \ + ignoring `{option_name}`" + ); + } + return None; + } + println!( + "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}" + ); + } + + Some(commit.to_string()) + } } fn set(field: &mut T, val: Option) { diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 64af114f998ea..2a301007ab478 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -190,7 +190,7 @@ impl Flags { if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) = HelpVerboseOnly::try_parse_from(it.clone()) { - println!("note: updating submodules before printing available paths"); + println!("NOTE: updating submodules before printing available paths"); let config = Config::parse(&[String::from("build")]); let build = Build::new(config); let paths = Builder::get_help(&build, subcommand); diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 5541a2f3e35ec..1f2ee6a6b736c 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -5,10 +5,10 @@ use std::{ io::{BufRead, BufReader, BufWriter, ErrorKind, Write}, path::{Path, PathBuf}, process::{Command, Stdio}, + sync::OnceLock, }; use build_helper::ci::CiEnv; -use once_cell::sync::OnceCell; use xz2::bufread::XzDecoder; use crate::core::build_steps::llvm::detect_llvm_sha; @@ -16,7 +16,7 @@ use crate::core::config::RustfmtMetadata; use crate::utils::helpers::{check_run, exe, program_out_of_date}; use crate::{t, Config}; -static SHOULD_FIX_BINS_AND_DYLIBS: OnceCell = OnceCell::new(); +static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock = OnceLock::new(); /// `Config::try_run` wrapper for this module to avoid warnings on `try_run`, since we don't have access to a `builder` yet. fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> { @@ -114,7 +114,7 @@ impl Config { is_nixos }); if val { - eprintln!("info: You seem to be using Nix."); + eprintln!("INFO: You seem to be using Nix."); } val } @@ -131,7 +131,7 @@ impl Config { println!("attempting to patch {}", fname.display()); // Only build `.nix-deps` once. - static NIX_DEPS_DIR: OnceCell = OnceCell::new(); + static NIX_DEPS_DIR: OnceLock = OnceLock::new(); let mut nix_build_succeeded = true; let nix_deps_dir = NIX_DEPS_DIR.get_or_init(|| { // Run `nix-build` to "build" each dependency (which will likely reuse @@ -208,7 +208,10 @@ impl Config { Some(other) => panic!("unsupported protocol {other} in {url}"), None => panic!("no protocol in {url}"), } - t!(std::fs::rename(&tempfile, dest_path)); + t!( + std::fs::rename(&tempfile, dest_path), + format!("failed to rename {tempfile:?} to {dest_path:?}") + ); } fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { @@ -375,6 +378,32 @@ enum DownloadSource { /// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions. impl Config { + pub(crate) fn download_clippy(&self) -> PathBuf { + self.verbose("downloading stage0 clippy artifacts"); + + let date = &self.stage0_metadata.compiler.date; + let version = &self.stage0_metadata.compiler.version; + let host = self.build; + + let bin_root = self.out.join(host.triple).join("stage0"); + let clippy_stamp = bin_root.join(".clippy-stamp"); + let cargo_clippy = bin_root.join("bin").join(exe("cargo-clippy", host)); + if cargo_clippy.exists() && !program_out_of_date(&clippy_stamp, &date) { + return cargo_clippy; + } + + let filename = format!("clippy-{version}-{host}.tar.xz"); + self.download_component(DownloadSource::Dist, filename, "clippy-preview", date, "stage0"); + if self.should_fix_bins_and_dylibs() { + self.fix_bin_or_dylib(&cargo_clippy); + self.fix_bin_or_dylib(&cargo_clippy.with_file_name(exe("clippy-driver", host))); + } + + cargo_clippy + } + + /// NOTE: rustfmt is a completely different toolchain than the bootstrap compiler, so it can't + /// reuse target directories or artifacts pub(crate) fn maybe_download_rustfmt(&self) -> Option { let RustfmtMetadata { date, version } = self.stage0_metadata.rustfmt.as_ref()?; let channel = format!("{version}-{date}"); @@ -544,6 +573,10 @@ impl Config { key: &str, destination: &str, ) { + if self.dry_run() { + return; + } + let cache_dst = self.out.join("cache"); let cache_dir = cache_dst.join(key); if !cache_dir.exists() { @@ -606,10 +639,10 @@ impl Config { let mut help_on_error = ""; if destination == "ci-rustc" { - help_on_error = "error: failed to download pre-built rustc from CI + help_on_error = "ERROR: failed to download pre-built rustc from CI -note: old builds get deleted after a certain time -help: if trying to compile an old commit of rustc, disable `download-rustc` in config.toml: +NOTE: old builds get deleted after a certain time +HELP: if trying to compile an old commit of rustc, disable `download-rustc` in config.toml: [rust] download-rustc = false @@ -685,10 +718,10 @@ download-rustc = false let filename = format!("rust-dev-{}-{}.tar.xz", version, self.build.triple); let tarball = rustc_cache.join(&filename); if !tarball.exists() { - let help_on_error = "error: failed to download llvm from ci + let help_on_error = "ERROR: failed to download llvm from ci - help: old builds get deleted after a certain time - help: if trying to compile an old commit of rustc, disable `download-ci-llvm` in config.toml: + HELP: old builds get deleted after a certain time + HELP: if trying to compile an old commit of rustc, disable `download-ci-llvm` in config.toml: [llvm] download-ci-llvm = false diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index d7f49a6d11b9c..60a89e9bf0709 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -25,12 +25,13 @@ use std::io; use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; use std::str; +use std::sync::OnceLock; use build_helper::ci::{gha, CiEnv}; use build_helper::exit; use build_helper::util::fail; use filetime::FileTime; -use once_cell::sync::OnceCell; +use sha2::digest::Digest; use termcolor::{ColorChoice, StandardStream, WriteColor}; use utils::channel::GitInfo; @@ -46,9 +47,10 @@ use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, syml mod core; mod utils; -pub use crate::core::builder::PathSet; -pub use crate::core::config::flags::Subcommand; -pub use crate::core::config::Config; +pub use core::builder::PathSet; +pub use core::config::flags::Subcommand; +pub use core::config::Config; +pub use utils::change_tracker::{find_recent_config_change_ids, CONFIG_CHANGE_HISTORY}; const LLVM_TOOLS: &[&str] = &[ "llvm-cov", // used to generate coverage report @@ -69,16 +71,6 @@ const LLVM_TOOLS: &[&str] = &[ /// LLD file names for all flavors. const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; -/// Keeps track of major changes made to the bootstrap configuration. -/// -/// These values also represent the IDs of the PRs that caused major changes. -/// You can visit `https://github.com/rust-lang/rust/pull/{any-id-from-the-list}` to -/// check for more details regarding each change. -/// -/// If you make any major changes (such as adding new values or changing default values), please -/// ensure that the associated PR ID is added to the end of this list. -pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998]; - /// Extra --check-cfg to add when building /// (Mode restriction, config name, config values (if any)) const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ @@ -97,7 +89,7 @@ const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ /* Extra values not defined in the built-in targets yet, but used in std */ (Some(Mode::Std), "target_env", Some(&["libnx"])), // (Some(Mode::Std), "target_os", Some(&[])), - (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])), + (Some(Mode::Std), "target_arch", Some(&["spirv", "nvptx", "xtensa"])), /* Extra names used by dependencies */ // FIXME: Used by serde_json, but we should not be triggering on external dependencies. (Some(Mode::Rustc), "no_btreemap_remove_entry", None), @@ -914,7 +906,7 @@ impl Build { /// Returns the sysroot of the snapshot compiler. fn rustc_snapshot_sysroot(&self) -> &Path { - static SYSROOT_CACHE: OnceCell = once_cell::sync::OnceCell::new(); + static SYSROOT_CACHE: OnceLock = OnceLock::new(); SYSROOT_CACHE.get_or_init(|| { let mut rustc = Command::new(&self.initial_rustc); rustc.args(&["--print", "sysroot"]); @@ -1197,11 +1189,10 @@ impl Build { .filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) .collect::>(); - // If we're compiling on macOS then we add a few unconditional flags - // indicating that we want libc++ (more filled out than libstdc++) and - // we want to compile for 10.7. This way we can ensure that + // If we're compiling C++ on macOS then we add a flag indicating that + // we want libc++ (more filled out than libstdc++), ensuring that // LLVM/etc are all properly compiled. - if target.contains("apple-darwin") { + if matches!(c, CLang::Cxx) && target.contains("apple-darwin") { base.push("-stdlib=libc++".into()); } @@ -1568,7 +1559,7 @@ impl Build { if !stamp.exists() { eprintln!( - "Error: Unable to find the stamp file {}, did you try to keep a nonexistent build stage?", + "ERROR: Unable to find the stamp file {}, did you try to keep a nonexistent build stage?", stamp.display() ); crate::exit!(1); @@ -1697,7 +1688,7 @@ impl Build { self.verbose_than(1, &format!("Install {src:?} to {dst:?}")); t!(fs::create_dir_all(dstdir)); if !src.exists() { - panic!("Error: File \"{}\" not found!", src.display()); + panic!("ERROR: File \"{}\" not found!", src.display()); } self.copy_internal(src, &dst, true); chmod(&dst, perms); @@ -1849,15 +1840,44 @@ fn envify(s: &str) -> String { .collect() } -pub fn find_recent_config_change_ids(current_id: usize) -> Vec { - let index = CONFIG_CHANGE_HISTORY - .iter() - .position(|&id| id == current_id) - .expect(&format!("Value `{}` was not found in `CONFIG_CHANGE_HISTORY`.", current_id)); - - CONFIG_CHANGE_HISTORY - .iter() - .skip(index + 1) // Skip the current_id and IDs before it - .cloned() - .collect() +/// Computes a hash representing the state of a repository/submodule and additional input. +/// +/// It uses `git diff` for the actual changes, and `git status` for including the untracked +/// files in the specified directory. The additional input is also incorporated into the +/// computation of the hash. +/// +/// # Parameters +/// +/// - `dir`: A reference to the directory path of the target repository/submodule. +/// - `additional_input`: An additional input to be included in the hash. +/// +/// # Panics +/// +/// In case of errors during `git` command execution (e.g., in tarball sources), default values +/// are used to prevent panics. +pub fn generate_smart_stamp_hash(dir: &Path, additional_input: &str) -> String { + let diff = Command::new("git") + .current_dir(dir) + .arg("diff") + .output() + .map(|o| String::from_utf8(o.stdout).unwrap_or_default()) + .unwrap_or_default(); + + let status = Command::new("git") + .current_dir(dir) + .arg("status") + .arg("--porcelain") + .arg("-z") + .arg("--untracked-files=normal") + .output() + .map(|o| String::from_utf8(o.stdout).unwrap_or_default()) + .unwrap_or_default(); + + let mut hasher = sha2::Sha256::new(); + + hasher.update(diff); + hasher.update(status); + hasher.update(additional_input); + + hex::encode(hasher.finalize().as_slice()) } diff --git a/src/bootstrap/src/tests/builder.rs b/src/bootstrap/src/tests/builder.rs index 96139f7b099ce..744015e8e8204 100644 --- a/src/bootstrap/src/tests/builder.rs +++ b/src/bootstrap/src/tests/builder.rs @@ -1,6 +1,6 @@ use super::*; -use crate::core::config::{Config, DryRun, TargetSelection}; use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::config::{Config, DryRun, TargetSelection}; use std::thread; fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config { diff --git a/src/bootstrap/src/tests/config.rs b/src/bootstrap/src/tests/config.rs index 59bd52a94dc83..a8106ca8ff923 100644 --- a/src/bootstrap/src/tests/config.rs +++ b/src/bootstrap/src/tests/config.rs @@ -24,19 +24,19 @@ fn download_ci_llvm() { } let parse_llvm = |s| parse(s).llvm_from_ci; - let if_available = parse_llvm("llvm.download-ci-llvm = \"if-available\""); + let if_unchanged = parse_llvm("llvm.download-ci-llvm = \"if-unchanged\""); assert!(parse_llvm("llvm.download-ci-llvm = true")); assert!(!parse_llvm("llvm.download-ci-llvm = false")); - assert_eq!(parse_llvm(""), if_available); - assert_eq!(parse_llvm("rust.channel = \"dev\""), if_available); + assert_eq!(parse_llvm(""), if_unchanged); + assert_eq!(parse_llvm("rust.channel = \"dev\""), if_unchanged); assert!(!parse_llvm("rust.channel = \"stable\"")); assert!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\"")); assert!(parse_llvm( - "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-available\"" + "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" )); assert!(!parse_llvm( - "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-available\"" + "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" )); } diff --git a/src/bootstrap/src/utils/bin_helpers.rs b/src/bootstrap/src/utils/bin_helpers.rs index b9177c490ac28..c90fd2805e283 100644 --- a/src/bootstrap/src/utils/bin_helpers.rs +++ b/src/bootstrap/src/utils/bin_helpers.rs @@ -18,12 +18,11 @@ pub(crate) fn parse_rustc_verbose() -> usize { /// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`. /// /// If "RUSTC_STAGE" was not set, the program will be terminated with 101. -#[allow(unused)] pub(crate) fn parse_rustc_stage() -> String { std::env::var("RUSTC_STAGE").unwrap_or_else(|_| { // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead. - eprintln!("rustc shim: fatal: RUSTC_STAGE was not set"); - eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap"); + eprintln!("rustc shim: FATAL: RUSTC_STAGE was not set"); + eprintln!("rustc shim: NOTE: use `x.py build -vvv` to see all environment variables set by bootstrap"); std::process::exit(101); }) } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs new file mode 100644 index 0000000000000..887b596b7868a --- /dev/null +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -0,0 +1,89 @@ +//! This module facilitates the tracking system for major changes made to the bootstrap, +//! with the goal of keeping developers synchronized with important modifications in +//! the bootstrap. + +#[derive(Clone, Debug)] +pub struct ChangeInfo { + /// Represents the ID of PR caused major change on bootstrap. + pub change_id: usize, + pub severity: ChangeSeverity, + /// Provides a short summary of the change that will guide developers + /// on "how to handle/behave" in response to the changes. + pub summary: &'static str, +} + +#[derive(Clone, Debug)] +pub enum ChangeSeverity { + /// Used when build configurations continue working as before. + Info, + /// Used when the default value of an option changes, or support for an option is removed entirely, + /// potentially requiring developers to update their build configurations. + Warning, +} + +impl ToString for ChangeSeverity { + fn to_string(&self) -> String { + match self { + ChangeSeverity::Info => "INFO".to_string(), + ChangeSeverity::Warning => "WARNING".to_string(), + } + } +} + +pub fn find_recent_config_change_ids(current_id: usize) -> Vec { + if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) { + // If the current change-id is greater than the most recent one, return + // an empty list (it may be due to switching from a recent branch to an + // older one); otherwise, return the full list (assuming the user provided + // the incorrect change-id by accident). + if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) { + if ¤t_id > &config.change_id { + return Vec::new(); + } + } + + return CONFIG_CHANGE_HISTORY.to_vec(); + } + + let index = + CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap(); + + CONFIG_CHANGE_HISTORY + .iter() + .skip(index + 1) // Skip the current_id and IDs before it + .cloned() + .collect() +} + +/// Keeps track of major changes made to the bootstrap configuration. +/// +/// If you make any major changes (such as adding new values or changing default values), +/// please ensure adding `ChangeInfo` to the end(because the list must be sorted by the merge date) +/// of this list. +pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ + ChangeInfo { + change_id: 115898, + severity: ChangeSeverity::Info, + summary: "Implementation of this change-tracking system. Ignore this.", + }, + ChangeInfo { + change_id: 116998, + severity: ChangeSeverity::Info, + summary: "Removed android-ndk r15 support in favor of android-ndk r25b.", + }, + ChangeInfo { + change_id: 117435, + severity: ChangeSeverity::Info, + summary: "New option `rust.parallel-compiler` added to config.toml.", + }, + ChangeInfo { + change_id: 116881, + severity: ChangeSeverity::Warning, + summary: "Default value of `download-ci-llvm` was changed for `codegen` profile.", + }, + ChangeInfo { + change_id: 117813, + severity: ChangeSeverity::Info, + summary: "Use of the `if-available` value for `download-ci-llvm` is deprecated; prefer using the new `if-unchanged` value.", + }, +]; diff --git a/src/bootstrap/src/utils/dylib.rs b/src/bootstrap/src/utils/dylib.rs index 279a6a010f1d5..b6e7aec1756b6 100644 --- a/src/bootstrap/src/utils/dylib.rs +++ b/src/bootstrap/src/utils/dylib.rs @@ -25,3 +25,16 @@ pub fn dylib_path() -> Vec { }; std::env::split_paths(&var).collect() } + +/// Given an executable called `name`, return the filename for the +/// executable for a particular target. +#[allow(dead_code)] +pub fn exe(name: &str, target: &str) -> String { + if target.contains("windows") { + format!("{name}.exe") + } else if target.contains("uefi") { + format!("{name}.efi") + } else { + name.to_string() + } +} diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 82a5607d9037d..483c52480778b 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -5,16 +5,17 @@ use build_helper::util::fail; use std::env; +use std::ffi::{OsStr, OsString}; use std::fs; use std::io; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::str; +use std::sync::OnceLock; use std::time::{Instant, SystemTime, UNIX_EPOCH}; use crate::core::builder::Builder; use crate::core::config::{Config, TargetSelection}; -use crate::OnceCell; pub use crate::utils::dylib::{dylib_path, dylib_path_var}; @@ -44,16 +45,8 @@ macro_rules! t { } pub use t; -/// Given an executable called `name`, return the filename for the -/// executable for a particular target. pub fn exe(name: &str, target: TargetSelection) -> String { - if target.contains("windows") { - format!("{name}.exe") - } else if target.contains("uefi") { - format!("{name}.efi") - } else { - name.to_string() - } + crate::utils::dylib::exe(name, &target.triple) } /// Returns `true` if the file name given looks like a dynamic library. @@ -233,7 +226,7 @@ pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { let status = match cmd.status() { Ok(status) => status, Err(e) => { - println!("failed to execute command: {cmd:?}\nerror: {e}"); + println!("failed to execute command: {cmd:?}\nERROR: {e}"); return false; } }; @@ -262,7 +255,7 @@ pub fn make(host: &str) -> PathBuf { pub fn output(cmd: &mut Command) -> String { let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, - Err(e) => fail(&format!("failed to execute command: {cmd:?}\nerror: {e}")), + Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")), }; if !output.status.success() { panic!( @@ -327,7 +320,7 @@ pub(crate) fn absolute(path: &Path) -> PathBuf { } #[cfg(not(any(unix, windows)))] { - println!("warning: bootstrap is not supported on non-unix platforms"); + println!("WARNING: bootstrap is not supported on non-unix platforms"); t!(std::fs::canonicalize(t!(std::env::current_dir()))).join(path) } } @@ -377,7 +370,6 @@ fn absolute_unix(path: &Path) -> io::Result { #[cfg(windows)] fn absolute_windows(path: &std::path::Path) -> std::io::Result { - use std::ffi::OsString; use std::io::Error; use std::os::windows::ffi::{OsStrExt, OsStringExt}; use std::ptr::null_mut; @@ -444,7 +436,7 @@ pub fn get_clang_cl_resource_dir(clang_cl_path: &str) -> PathBuf { } pub fn lld_flag_no_threads(is_windows: bool) -> &'static str { - static LLD_NO_THREADS: OnceCell<(&'static str, &'static str)> = OnceCell::new(); + static LLD_NO_THREADS: OnceLock<(&'static str, &'static str)> = OnceLock::new(); let (windows, other) = LLD_NO_THREADS.get_or_init(|| { let out = output(Command::new("lld").arg("-flavor").arg("ld").arg("--version")); let newer = match (out.find(char::is_numeric), out.find('.')) { @@ -470,3 +462,64 @@ pub fn extract_beta_rev(version: &str) -> Option { count } + +pub enum LldThreads { + Yes, + No, +} + +pub fn add_rustdoc_lld_flags( + cmd: &mut Command, + builder: &Builder<'_>, + target: TargetSelection, + lld_threads: LldThreads, +) { + cmd.args(build_rustdoc_lld_flags(builder, target, lld_threads)); +} + +pub fn add_rustdoc_cargo_lld_flags( + cmd: &mut Command, + builder: &Builder<'_>, + target: TargetSelection, + lld_threads: LldThreads, +) { + let args = build_rustdoc_lld_flags(builder, target, lld_threads); + let mut flags = cmd + .get_envs() + .find_map(|(k, v)| if k == OsStr::new("RUSTDOCFLAGS") { v } else { None }) + .unwrap_or_default() + .to_os_string(); + for arg in args { + if !flags.is_empty() { + flags.push(" "); + } + flags.push(arg); + } + if !flags.is_empty() { + cmd.env("RUSTDOCFLAGS", flags); + } +} + +fn build_rustdoc_lld_flags( + builder: &Builder<'_>, + target: TargetSelection, + lld_threads: LldThreads, +) -> Vec { + let mut args = vec![]; + + if let Some(linker) = builder.linker(target) { + let mut flag = std::ffi::OsString::from("-Clinker="); + flag.push(linker); + args.push(flag); + } + if builder.is_fuse_ld_lld(target) { + args.push(OsString::from("-Clink-arg=-fuse-ld=lld")); + if matches!(lld_threads, LldThreads::No) { + args.push(OsString::from(format!( + "-Clink-arg=-Wl,{}", + lld_flag_no_threads(target.contains("windows")) + ))); + } + } + args +} diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs index 65794f05d2d9d..174f374224c02 100644 --- a/src/bootstrap/src/utils/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -180,7 +180,7 @@ impl BuildMetrics { t!(serde_json::from_slice::(&contents)).invocations } else { println!( - "warning: overriding existing build/metrics.json, as it's not \ + "WARNING: overriding existing build/metrics.json, as it's not \ compatible with build metrics format version {CURRENT_FORMAT_VERSION}." ); Vec::new() diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs index 8ca22d00865b6..cb535f0e1632a 100644 --- a/src/bootstrap/src/utils/mod.rs +++ b/src/bootstrap/src/utils/mod.rs @@ -4,6 +4,7 @@ pub(crate) mod cache; pub(crate) mod cc_detect; +pub(crate) mod change_tracker; pub(crate) mod channel; pub(crate) mod dylib; pub(crate) mod exec; diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index f97aa9585135d..bff47f65c51f6 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -197,7 +197,7 @@ impl<'a> Renderer<'a> { println!("{stdout}"); } if let Some(message) = &failure.message { - println!("note: {message}"); + println!("NOTE: {message}"); } } } diff --git a/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile b/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile deleted file mode 100644 index 07dcb9ea928f8..0000000000000 --- a/src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - ninja-build \ - file \ - curl \ - ca-certificates \ - python3 \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils \ - bzip2 - -COPY scripts/emscripten.sh /scripts/ -RUN bash /scripts/emscripten.sh - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV PATH=$PATH:/emsdk-portable -ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/ -ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/ -ENV BINARYEN_ROOT=/emsdk-portable/upstream/ - -ENV TARGETS=asmjs-unknown-emscripten - -# Use -O1 optimizations in the link step to reduce time spent optimizing JS. -ENV EMCC_CFLAGS=-O1 - -# Emscripten installation is user-specific -ENV NO_CHANGE_USER=1 - -ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target $TARGETS - -# This is almost identical to the wasm32-unknown-emscripten target, so -# running with assertions again is not useful -ENV NO_DEBUG_ASSERTIONS=1 -ENV NO_LLVM_ASSERTIONS=1 -ENV NO_OVERFLOW_CHECKS=1 diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile index c88185a2000db..298282a764631 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux/Dockerfile @@ -26,5 +26,5 @@ ENV \ ENV HOSTS=powerpc64-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs +ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile index 3372baed999ac..adf3c67479b08 100644 --- a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile @@ -75,8 +75,7 @@ ENV RUN_MAKE_TARGETS=$RUN_MAKE_TARGETS,thumbv7m-none-eabi ENV RUN_MAKE_TARGETS=$RUN_MAKE_TARGETS,thumbv7em-none-eabi ENV RUN_MAKE_TARGETS=$RUN_MAKE_TARGETS,thumbv7em-none-eabihf -ENV TARGETS=asmjs-unknown-emscripten -ENV TARGETS=$TARGETS,wasm32-unknown-emscripten +ENV TARGETS=wasm32-unknown-emscripten ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf ENV TARGETS=$TARGETS,armv5te-unknown-linux-gnueabi @@ -96,6 +95,7 @@ ENV TARGETS=$TARGETS,thumbv8m.main-none-eabihf ENV TARGETS=$TARGETS,riscv32i-unknown-none-elf ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf +ENV TARGETS=$TARGETS,riscv32imafc-unknown-none-elf ENV TARGETS=$TARGETS,riscv64imac-unknown-none-elf ENV TARGETS=$TARGETS,riscv64gc-unknown-none-elf ENV TARGETS=$TARGETS,armebv7r-none-eabi diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 01b46118b9c1e..3f4e025111ade 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -48,9 +48,6 @@ ENV \ AR_x86_64_pc_solaris=x86_64-pc-solaris2.10-ar \ CC_x86_64_pc_solaris=x86_64-pc-solaris2.10-gcc \ CXX_x86_64_pc_solaris=x86_64-pc-solaris2.10-g++ \ - AR_x86_64_sun_solaris=x86_64-sun-solaris2.10-ar \ - CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \ - CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++ \ CC_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-gcc-9 \ CXX_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-g++-9 \ AR_x86_64_fortanix_unknown_sgx=ar \ @@ -84,8 +81,6 @@ COPY host-x86_64/dist-various-2/build-fuchsia-toolchain.sh /tmp/ RUN /tmp/build-fuchsia-toolchain.sh COPY host-x86_64/dist-various-2/build-solaris-toolchain.sh /tmp/ RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 pc -# Build deprecated target 'x86_64-sun-solaris2.10' until removed -RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 sun RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc sun COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh @@ -120,7 +115,6 @@ ENV TARGETS=$TARGETS,wasm32-wasi ENV TARGETS=$TARGETS,wasm32-wasi-preview1-threads ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,x86_64-pc-solaris -ENV TARGETS=$TARGETS,x86_64-sun-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh index 56ee348a337ec..1d9568702cc39 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh @@ -4,7 +4,7 @@ set -ex source shared.sh -LLVM=llvmorg-17.0.2 +LLVM=llvmorg-17.0.4 mkdir llvm-project cd llvm-project diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh index 3b3ec5da74bc9..e939a5d7eac4d 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh @@ -3,7 +3,8 @@ set -ex source shared.sh -GCC=8.5.0 +# Note: in the future when bumping to version 10.1.0, also take care of the sed block below. +GCC=9.5.0 curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | xzcat | tar xf - cd gcc-$GCC @@ -22,6 +23,11 @@ cd gcc-$GCC # latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server # instead here. # +# Note: in version 10.1.0, the URL used in `download_prerequisites` has changed from using FTP to +# using HTTP. When bumping to that gcc version, we can likely remove the sed replacement below, or +# the expression will need to be updated. That new URL is available at: +# https://github.com/gcc-mirror/gcc/blob/6e6e3f144a33ae504149dc992453b4f6dea12fdb/contrib/download_prerequisites#L35 +# sed -i'' 's|ftp://gcc\.gnu\.org/|https://gcc.gnu.org/|g' ./contrib/download_prerequisites ./contrib/download_prerequisites diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 85a9a5d33752f..3e3ad3eeef7c9 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -39,8 +39,14 @@ COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 + +# Run clippy just to make sure it doesn't error out; we don't actually want to gate on the warnings +# though. +# Ideally we'd use stage 1, but that ICEs: https://github.com/rust-lang/rust-clippy/issues/11230 + ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ + python3 ../x.py clippy --stage 0 -Awarnings && \ python3 ../x.py build --stage 0 src/tools/build-manifest && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py test --stage 0 core alloc std test proc_macro && \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile deleted file mode 100644 index cefdcad764397..0000000000000 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -FROM ubuntu:22.04 - -ARG DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - gcc-multilib \ - make \ - ninja-build \ - file \ - curl \ - ca-certificates \ - python3.11 \ - git \ - cmake \ - sudo \ - gdb \ - llvm-15-tools \ - llvm-15-dev \ - libedit-dev \ - libssl-dev \ - pkg-config \ - zlib1g-dev \ - xz-utils \ - nodejs \ - mingw-w64 \ - libgccjit-12-dev \ - && rm -rf /var/lib/apt/lists/* - -# Install powershell (universal package) so we can test x.ps1 on Linux -RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ - dpkg -i powershell.deb && \ - rm -f powershell.deb - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -# Make `libgccjit.so` accessible to the linker. -RUN ln -s /usr/lib/gcc/x86_64-linux-gnu/12/libgccjit.so /usr/lib/x86_64-linux-gnu/libgccjit.so - -# We are disabling CI LLVM since this builder is intentionally using a host -# LLVM, rather than the typical src/llvm-project LLVM. -ENV NO_DOWNLOAD_CI_LLVM 1 - -# This is not the latest LLVM version, so some components required by tests may -# be missing. -ENV IS_NOT_LATEST_LLVM 1 - -# Using llvm-link-shared due to libffi issues -- see #34486 -ENV RUST_CONFIGURE_ARGS \ - --build=x86_64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-15 \ - --enable-llvm-link-shared \ - $USE_NEW_MANGLING \ - --set rust.thin-lto-import-instr-limit=10 - -COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/ - -ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile index c177e7387fc8c..f4850715e82e8 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile @@ -24,8 +24,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ nodejs \ mingw-w64 \ + libgccjit-12-dev \ && rm -rf /var/lib/apt/lists/* +# Note: libgccjit needs to match the default gcc version for the linker to find it. + # Install powershell (universal package) so we can test x.ps1 on Linux RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ dpkg -i powershell.deb && \ @@ -49,6 +52,6 @@ ENV RUST_CONFIGURE_ARGS \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 -COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/ +COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/ ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/script.sh similarity index 100% rename from src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh rename to src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile index 76846f1fed7f3..f1d6b9a4ef26b 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile @@ -24,8 +24,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ nodejs \ mingw-w64 \ + libgccjit-13-dev \ && rm -rf /var/lib/apt/lists/* +# Note: libgccjit needs to match the default gcc version for the linker to find it. + # Install powershell (universal package) so we can test x.ps1 on Linux RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ dpkg -i powershell.deb && \ @@ -45,6 +48,6 @@ ENV RUST_CONFIGURE_ARGS \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 -COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/ +COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/ ENV SCRIPT /tmp/script.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index 821a09feb2d53..205ee263217ad 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -25,7 +25,16 @@ cat /tmp/toolstate/toolstates.json python3 "$X_PY" test --stage 2 check-tools python3 "$X_PY" test --stage 2 src/tools/clippy python3 "$X_PY" test --stage 2 src/tools/rustfmt -python3 "$X_PY" test --stage 2 src/tools/miri + +# Testing Miri is a bit more complicated. +# We set the GC interval to the shortest possible value (0 would be off) to increase the chance +# that bugs which only surface when the GC runs at a specific time are more likely to cause CI to fail. +# This significantly increases the runtime of our test suite, or we'd do this in PR CI too. +if [[ -z "${PR_CI_JOB:-}" ]]; then + MIRIFLAGS=-Zmiri-provenance-gc=1 python3 "$X_PY" test --stage 2 src/tools/miri +else + python3 "$X_PY" test --stage 2 src/tools/miri +fi # We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc. # Also cover some other targets via cross-testing, in particular all tier 1 targets. export BOOTSTRAP_SKIP_TARGET_SANITY=1 # we don't need `cc` for these targets diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index a2891ef95634d..636692a0954ac 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -269,14 +269,9 @@ touch $objdir/${SUMMARY_FILE} extra_env="" if [ "$ENABLE_GCC_CODEGEN" = "1" ]; then - extra_env="$EXTRA_ENV --env ENABLE_GCC_CODEGEN=1" - # If `ENABLE_GCC_CODEGEN` is set and not empty, we add the `--enable-new-symbol-mangling` - # argument to `RUST_CONFIGURE_ARGS` and set the `GCC_EXEC_PREFIX` environment variable. - # `cg_gcc` doesn't support the legacy mangling so we need to enforce the new one - # if we run `cg_gcc` tests. - extra_env="$EXTRA_ENV --env USE_NEW_MANGLING=--enable-new-symbol-mangling" + extra_env="$extra_env --env ENABLE_GCC_CODEGEN=1" # Fix rustc_codegen_gcc lto issues. - extra_env="$EXTRA_ENV --env GCC_EXEC_PREFIX=/usr/lib/gcc/" + extra_env="$extra_env --env GCC_EXEC_PREFIX=/usr/lib/gcc/" echo "Setting extra environment values for docker: $extra_env" fi @@ -302,6 +297,7 @@ docker \ --env DIST_TRY_BUILD \ --env PR_CI_JOB \ --env OBJDIR_ON_HOST="$objdir" \ + --env CODEGEN_BACKENDS \ --init \ --rm \ rust-ci \ diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index f78d446c8b7ca..437b51641fc92 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -12,6 +12,7 @@ import fcntl import glob import hashlib +import io import json import os import platform @@ -276,27 +277,60 @@ def start(self): stderr=self.subprocess_output(), ) - # Start emulator - self.log_info("Starting emulator...") - product_bundle = "terminal.qemu-" + self.triple_to_arch(self.target) + # Look up the product bundle transfer manifest. + self.log_info("Looking up the product bundle transfer manifest...") + product_name = "minimal." + self.triple_to_arch(self.target) + fuchsia_version = "14.20230811.2.1" + + # FIXME: We should be able to replace this with the machine parsable + # `ffx --machine json product lookup ...` once F15 is released. + out = subprocess.check_output( + [ + ffx_path, + "product", + "lookup", + product_name, + fuchsia_version, + "--base-url", + "gs://fuchsia/development/" + fuchsia_version, + ], + env=ffx_env, + stderr=self.subprocess_output(), + ) + + self.log_debug(out) + + for line in io.BytesIO(out): + if line.startswith(b"gs://"): + transfer_manifest_url = line.rstrip() + break + else: + raise Exception("Unable to parse transfer manifest") + + # Download the product bundle. + product_bundle_dir = os.path.join(self.tmp_dir(), 'product-bundle') subprocess.check_call( [ ffx_path, - "product-bundle", - "get", - product_bundle, + "product", + "download", + transfer_manifest_url, + product_bundle_dir, + "--force", ], env=ffx_env, stdout=self.subprocess_output(), stderr=self.subprocess_output(), ) + + # Start emulator # FIXME: condition --accel hyper on target arch matching host arch subprocess.check_call( [ ffx_path, "emu", "start", - product_bundle, + product_bundle_dir, "--headless", "--log", self.emulator_log_path(), diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index b415eb5961bb3..5b9c90273a34c 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -173,6 +173,10 @@ x--expand-yaml-anchors--remove: run: src/ci/scripts/install-clang.sh <<: *step + - name: install tidy + run: src/ci/scripts/install-tidy.sh + <<: *step + - name: install WIX run: src/ci/scripts/install-wix.sh <<: *step @@ -330,7 +334,7 @@ jobs: - name: mingw-check-tidy <<: *job-linux-4c - - name: x86_64-gnu-llvm-15 + - name: x86_64-gnu-llvm-16 env: ENABLE_GCC_CODEGEN: "1" <<: *job-linux-16c @@ -482,11 +486,6 @@ jobs: RUST_BACKTRACE: 1 <<: *job-linux-8c - - name: x86_64-gnu-llvm-15 - env: - RUST_BACKTRACE: 1 - <<: *job-linux-8c - - name: x86_64-gnu-nopt <<: *job-linux-4c @@ -565,6 +564,25 @@ jobs: DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-macos-m1 + # This target only needs to support 11.0 and up as nothing else supports the hardware + - name: aarch64-apple + env: + SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin + RUST_CONFIGURE_ARGS: >- + --enable-sanitizers + --enable-profiler + --set rust.jemalloc + --set llvm.ninja=false + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_13.4.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + <<: *job-macos-m1 + ###################### # Windows Builders # ###################### diff --git a/src/ci/run.sh b/src/ci/run.sh index 31ef55216b91c..5700172fd3ec4 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -98,8 +98,8 @@ if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" elif [ "$DEPLOY_ALT" != "" ]; then - if [ "$NO_PARALLEL_COMPILER" = "" ]; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler" + if [ "$ALT_PARALLEL_COMPILER" = "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.parallel-compiler=false" fi RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-assertions" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir" @@ -145,7 +145,7 @@ else # LLVM continuously on at least some builders to ensure it works, though. # (And PGO is its own can of worms). if [ "$NO_DOWNLOAD_CI_LLVM" = "" ]; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-available" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-unchanged" else # When building for CI we want to use the static C++ Standard library # included with LLVM, since a dynamic libstdcpp may not be available. @@ -163,6 +163,14 @@ if [ "$IS_NOT_LATEST_LLVM" = "" ]; then export COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS=1 fi +if [ "$ENABLE_GCC_CODEGEN" = "1" ]; then + # If `ENABLE_GCC_CODEGEN` is set and not empty, we add the `--enable-new-symbol-mangling` + # argument to `RUST_CONFIGURE_ARGS` and set the `GCC_EXEC_PREFIX` environment variable. + # `cg_gcc` doesn't support the legacy mangling so we need to enforce the new one + # if we run `cg_gcc` tests. + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-new-symbol-mangling" +fi + # Print the date from the local machine and the date from an external source to # check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure # Pipelines it happened that the certificates were marked as expired. diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index cbb4d5765ca3f..77164ed4117a9 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -58,7 +58,7 @@ elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then "${RUST_CONFIGURE_ARGS} --set llvm.clang-cl=$(pwd)/clang-rust/bin/clang-cl.exe" # Disable downloading CI LLVM on this builder; - # setting up clang-cl just above conflicts with the default if-available option. + # setting up clang-cl just above conflicts with the default if-unchanged option. ciCommandSetEnv NO_DOWNLOAD_CI_LLVM 1 fi diff --git a/src/ci/scripts/install-tidy.sh b/src/ci/scripts/install-tidy.sh new file mode 100755 index 0000000000000..fab126453fdc9 --- /dev/null +++ b/src/ci/scripts/install-tidy.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# This script downloads and installs the tidy binary from Homebrew. + +set -euo pipefail +IFS=$'\n\t' + +source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" + +# Only the macOS arm64/aarch64 GitHub Actions runner needs to have tidy +# installed; other platforms have it preinstalled. + +if isMacOS; then + platform=$(uname -m) + case $platform in + x86_64) + ;; + arm64) + brew install tidy-html5 + ;; + *) + echo "unsupported architecture: ${platform}" + exit 1 + esac +fi diff --git a/src/doc/book b/src/doc/book index 5b6c1ceaa62ec..71352deb20727 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 5b6c1ceaa62ecbd6caef08df39b33b3938e99deb +Subproject commit 71352deb20727b4dda9ebfe8182709d5bf17dfea diff --git a/src/doc/index.md b/src/doc/index.md index 7c97c16c20bdc..8ad5b427b552a 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -4,12 +4,6 @@ nav { display: none; } -body { - font-family: serif; -} -h1, h2, h3, h4, h5, h6 { - font-family: sans-serif; -} h3 { font-size: 1.35rem; } @@ -119,10 +113,14 @@ documentation for your project _and_ all its dependencies in their correct version, and open it in your browser. Add the flag `--document-private-items` to also show items not marked `pub`. -### The Edition Guide +### Rust Version History + +[The Release Notes](releases.html) describes the change history of the Rust +toolchain and language. [The Edition Guide](edition-guide/index.html) describes the Rust editions and -their differences. +their differences. The latest version of the toolchain supports all +historical editions. ### The `rustc` Book diff --git a/src/doc/nomicon b/src/doc/nomicon index 1842257814919..83d015105e6d4 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 1842257814919fa62e81bdecd5e8f95be2839dbb +Subproject commit 83d015105e6d490fc30d6c95da1e56152a50e228 diff --git a/src/doc/reference b/src/doc/reference index 16fd3c06d9e55..692d216f5a115 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 16fd3c06d9e558dae2d52000818274ae70c9e90a +Subproject commit 692d216f5a1151e8852ddb308ba64040e634c876 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 6709beeb7d0fb..da0a06aada31a 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 6709beeb7d0fbc5ffc91ac4893a24434123b9bfa +Subproject commit da0a06aada31a324ae84a9eaee344f6a944b9683 diff --git a/src/doc/rust.css b/src/doc/rust.css index d33ab0326031f..e0bf64c33bcf0 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -1,6 +1,7 @@ /* General structure */ body { + font-family: serif; margin: 0 auto; padding: 0 15px; font-size: 18px; @@ -17,6 +18,9 @@ body { } } +h1, h2, h3, h4, h5, h6 { + font-family: sans-serif; +} h2, h3, h4, h5, h6 { font-weight: 400; line-height: 1.1; diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index b0ee9ec8fa59a..904bb5aa7b21a 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit b0ee9ec8fa59a6c7620165e061f4747202377a62 +Subproject commit 904bb5aa7b21adad58ffae610e2830c7b0f813b0 diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 8b4d673d831ce..ad33538951441 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -15,6 +15,8 @@ - [Platform Support](platform-support.md) - [Target Tier Policy](target-tier-policy.md) - [Template for Target-specific Documentation](platform-support/TEMPLATE.md) + - [arm64e-apple-ios.md](platform-support/arm64e-apple-ios.md) + - [arm64e-apple-darwin.md](platform-support/arm64e-apple-darwin.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [\*-apple-tvos](platform-support/apple-tvos.md) - [\*-apple-watchos\*](platform-support/apple-watchos.md) @@ -41,7 +43,9 @@ - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md) - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md) - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) + - [powerpc64-ibm-aix](platform-support/aix.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) + - [riscv32*-unknown-none-elf](platform-support/riscv32imac-unknown-none-elf.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md index 172048704f48d..d4e2fc52e973f 100644 --- a/src/doc/rustc/src/exploit-mitigations.md +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -1,12 +1,12 @@ # Exploit Mitigations -This chapter documents the exploit mitigations supported by the Rust -compiler, and is by no means an extensive survey of the Rust programming -language’s security features. +This chapter documents the exploit mitigations supported by the Rust compiler, +and is by no means an extensive survey of the Rust programming language’s +security features. This chapter is for software engineers working with the Rust programming -language, and assumes prior knowledge of the Rust programming language and -its toolchain. +language, and assumes prior knowledge of the Rust programming language and its +toolchain. ## Introduction @@ -14,8 +14,8 @@ its toolchain. The Rust programming language provides memory[1] and thread[2] safety guarantees via its ownership[3], references and borrowing[4], and slice types[5] features. However, Unsafe Rust[6] introduces unsafe blocks, unsafe -functions and methods, unsafe traits, and new types that are not subject to -the borrowing rules. +functions and methods, unsafe traits, and new types that are not subject to the +borrowing rules. Parts of the Rust standard library are implemented as safe abstractions over unsafe code (and historically have been vulnerable to memory corruption[7]). @@ -23,33 +23,32 @@ Furthermore, the Rust code and documentation encourage creating safe abstractions over unsafe code. This can cause a false sense of security if unsafe code is not properly reviewed and tested. -Unsafe Rust introduces features that do not provide the same memory and -thread safety guarantees. This causes programs or libraries to be -susceptible to memory corruption (CWE-119)[8] and concurrency issues -(CWE-557)[9]. Modern C and C++ compilers provide exploit mitigations to -increase the difficulty to exploit vulnerabilities resulting from these -issues. Therefore, the Rust compiler must also support these exploit -mitigations in order to mitigate vulnerabilities resulting from the use of -Unsafe Rust. This chapter documents these exploit mitigations and how they -apply to Rust. +Unsafe Rust introduces features that do not provide the same memory and thread +safety guarantees. This causes programs or libraries to be susceptible to +memory corruption (CWE-119)[8] and concurrency issues (CWE-557)[9]. Modern C +and C++ compilers provide exploit mitigations to increase the difficulty to +exploit vulnerabilities resulting from these issues. Therefore, the Rust +compiler must also support these exploit mitigations in order to mitigate +vulnerabilities resulting from the use of Unsafe Rust. This chapter documents +these exploit mitigations and how they apply to Rust. -This chapter does not discuss the effectiveness of these exploit mitigations -as they vary greatly depending on several factors besides their design and -implementation, but rather describe what they do, so their effectiveness can -be understood within a given context. +This chapter does not discuss the effectiveness of these exploit mitigations as +they vary greatly depending on several factors besides their design and +implementation, but rather describe what they do, so their effectiveness can be +understood within a given context. ## Exploit mitigations -This section documents the exploit mitigations applicable to the Rust -compiler when building programs for the Linux operating system on the AMD64 -architecture and equivalent.1 +This section documents the exploit mitigations applicable to the Rust compiler +when building programs for the Linux operating system on the AMD64 architecture +and equivalent.1 All examples in this section were built using +nightly builds of the Rust compiler on Debian testing. -The Rust Programming Language currently has no specification. The Rust -compiler (i.e., rustc) is the language reference implementation. All -references to “the Rust compiler” in this chapter refer to the language -reference implementation. +The Rust Programming Language currently has no specification. The Rust compiler +(i.e., rustc) is the language reference implementation. All references to “the +Rust compiler” in this chapter refer to the language reference implementation. Table I \ Summary of exploit mitigations supported by the Rust compiler when building @@ -83,8 +82,8 @@ instructing the dynamic linker to load it similarly to a shared object at a random load address, thus also benefiting from address-space layout randomization (ASLR). This is also referred to as “full ASLR”. -The Rust compiler supports position-independent executable, and enables it -by default since version 0.12.0 (2014-10-09)[10]–[13]. +The Rust compiler supports position-independent executable, and enables it by +default since version 0.12.0 (2014-10-09)[10]–[13]. ```text $ readelf -h target/release/hello-rust | grep Type: @@ -93,8 +92,7 @@ $ readelf -h target/release/hello-rust | grep Type: Fig. 1. Checking if an executable is a position-independent executable. An executable with an object type of `ET_DYN` (i.e., shared object) and not -`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig. -1). +`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig. 1). ### Integer overflow checks @@ -104,8 +102,11 @@ behavior (which may cause vulnerabilities) by checking for results of signed and unsigned integer computations that cannot be represented in their type, resulting in an overflow or wraparound. -The Rust compiler supports integer overflow checks, and enables it when -debug assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20]. +The Rust compiler supports integer overflow checks, and enables it when debug +assertions are enabled since version 1.0.0 (2015-05-15)[14]–[17], but support +for it was not completed until version 1.1.0 (2015-06-25)[16]. An option to +control integer overflow checks was later stabilized in version 1.17.0 +(2017-04-27)[18]–[20]. ```compile_fail fn main() { @@ -136,21 +137,21 @@ u: 0 Fig. 4. Build and execution of hello-rust-integer with debug assertions disabled. -Integer overflow checks are enabled when debug assertions are enabled (see -Fig. 3), and disabled when debug assertions are disabled (see Fig. 4). To -enable integer overflow checks independently, use the option to control -integer overflow checks, scoped attributes, or explicit checking methods -such as `checked_add`2. -It is recommended that explicit wrapping methods such as `wrapping_add` be -used when wrapping semantics are intended, and that explicit checking and -wrapping methods always be used when using Unsafe Rust. +It is recommended that explicit wrapping methods such as `wrapping_add` be used +when wrapping semantics are intended, and that explicit checking and wrapping +methods always be used when using Unsafe Rust. -2\. See [the `u32` docs](../std/primitive.u32.html) -for more information on the checked, overflowing, saturating, and wrapping -methods (using u32 as an example). +2\. See [the `u32` docs](../std/primitive.u32.html) for more +information on the checked, overflowing, saturating, and wrapping methods +(using u32 as an example). ### Non-executable memory regions @@ -158,17 +159,16 @@ class="reversefootnote" role="doc-backlink">↩ Non-executable memory regions increase the difficulty of exploitation by limiting the memory regions that can be used to execute arbitrary code. Most modern processors provide support for the operating system to mark memory -regions as non executable, but it was previously emulated by software, such -as in grsecurity/PaX's -[PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) and -[SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors that -did not provide support for it. This is also known as “No Execute (NX) Bit”, -“Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others. +regions as non executable, but it was previously emulated by software, such as +in grsecurity/PaX’s [PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) +and [SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors +that did not provide support for it. This is also known as “No Execute (NX) +Bit”, “Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others. The Rust compiler supports non-executable memory regions, and enables it by -default since its initial release, version 0.1 (2012-01-20)[21], [22], but -has regressed since then[23]–[25], and enforced by default since version -1.8.0 (2016-04-14)[25]. +default since its initial release, version 0.1 (2012-01-20)[21], [22], but has +regressed since then[23]–[25], and enforced by default since version 1.8.0 +(2016-04-14)[25]. ```text $ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK @@ -178,9 +178,9 @@ $ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK Fig. 5. Checking if non-executable memory regions are enabled for a given binary. -The presence of an element of type `PT_GNU_STACK` in the program header -table with the `PF_X` (i.e., executable) flag unset indicates non-executable -memory regions3 are enabled for a given binary (see Fig. 5). Conversely, the presence of an element of type `PT_GNU_STACK` in the program header table with the `PF_X` flag set or the absence of an element of type @@ -196,38 +196,40 @@ class="reversefootnote" role="doc-backlink">↩ Stack clashing protection protects the stack from overlapping with another memory region—allowing arbitrary data in both to be overwritten using each -other—by reading from the stack pages as the stack grows to cause a page -fault when attempting to read from the guard page/region. This is also -referred to as “stack probes” or “stack probing”. +other—by reading from the stack pages as the stack grows to cause a page fault +when attempting to read from the guard page/region. This is also referred to as +“stack probes” or “stack probing”. The Rust compiler supports stack clashing protection via stack probing, and enables it by default since version 1.20.0 (2017-08-31)[26]–[29]. -![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.") -Fig. 6. IDA Pro listing cross references to `__rust_probestack` in -hello-rust. - ```rust -fn hello() { - println!("Hello, world!"); +fn main() { + let v: [u8; 16384] = [1; 16384]; + let first = &v[0]; + println!("The first element is: {first}"); } +``` +Fig. 6. hello-rust-stack-probe-1 program. +![Screenshot of IDA Pro listing the "unrolled loop" stack probe variant in modified hello-rust.](images/image1.png "The \"unrolled loop\" stack probe variant in modified hello-rust.") +Fig. 7. The "unrolled loop" stack probe variant in modified hello-rust. + +```rust fn main() { - let _: [u64; 1024] = [0; 1024]; - hello(); + let v: [u8; 65536] = [1; 65536]; + let first = &v[0]; + println!("The first element is: {first}"); } ``` -Fig 7. Modified hello-rust. +Fig. 8. hello-rust-stack-probe-2 program. -![Screenshot of IDA Pro listing cross references to __rust_probestack in modified hello-rust.](images/image2.png "Cross references to __rust_probestack in modified hello-rust.") -Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified -hello-rust. +![Screenshot of IDA Pro listing the "standard loop" stack probe variant in modified hello-rust.](images/image2.png "The \"standard loop\" stack probe variant in modified hello-rust.") +Fig. 9. The "standard loop" stack probe variant in modified hello-rust. -To check if stack clashing protection is enabled for a given binary, search -for cross references to `__rust_probestack`. The `__rust_probestack` is -called in the prologue of functions whose stack size is larger than a page -size (see Fig. 6), and can be forced for illustration purposes by modifying -the hello-rust example as seen in Fig. 7 and Fig. 8. +To check if stack clashing protection is enabled for a given binary, look for +any of the two stack probe variants in the prologue of functions whose stack +size is larger than a page size (see Figs. 6–9). ### Read-only relocations and immediate binding @@ -246,21 +248,20 @@ $ readelf -l target/release/hello-rust | grep GNU_RELRO ``` Fig. 9. Checking if read-only relocations is enabled for a given binary. -The presence of an element of type `PT_GNU_RELRO` in the program header -table indicates read-only relocations are enabled for a given binary (see -Fig. 9). Conversely, the absence of an element of type `PT_GNU_RELRO` in the -program header table indicates read-only relocations are not enabled for a -given binary. +The presence of an element of type `PT_GNU_RELRO` in the program header table +indicates read-only relocations are enabled for a given binary (see Fig. 9). +Conversely, the absence of an element of type `PT_GNU_RELRO` in the program +header table indicates read-only relocations are not enabled for a given +binary. **Immediate binding** protects additional segments containing relocations -(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker -to perform all relocations before transferring control to the program during -startup, so all segments containing relocations can be marked read only -(when combined with read-only relocations). This is also referred to as -“full RELRO”. +(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker to +perform all relocations before transferring control to the program during +startup, so all segments containing relocations can be marked read only (when +combined with read-only relocations). This is also referred to as “full RELRO”. -The Rust compiler supports immediate binding, and enables it by default -since version 1.21.0 (2017-10-12)[30], [31]. +The Rust compiler supports immediate binding, and enables it by default since +version 1.21.0 (2017-10-12)[30], [31]. ```text $ readelf -d target/release/hello-rust | grep BIND_NOW @@ -270,16 +271,15 @@ Fig. 10. Checking if immediate binding is enabled for a given binary. The presence of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag4 in the dynamic section indicates immediate -binding is enabled for a given binary (see Fig. 10). Conversely, the absence -of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the -dynamic section indicates immediate binding is not enabled for a given -binary. +class="footnote">4 in the dynamic section indicates immediate binding +is enabled for a given binary (see Fig. 10). Conversely, the absence of an +element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the dynamic +section indicates immediate binding is not enabled for a given binary. The presence of both an element of type `PT_GNU_RELRO` in the program header -table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` -flag in the dynamic section indicates full RELRO is enabled for a given -binary (see Fig. 9 and Fig. 10). +table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag +in the dynamic section indicates full RELRO is enabled for a given binary (see +Figs. 9–10). 4\. And the `DF_1_NOW` flag for some link editors. @@ -287,26 +287,24 @@ href="#fnref:4" class="reversefootnote" role="doc-backlink">↩ ### Heap corruption protection -Heap corruption protection protects memory allocated dynamically by -performing several checks, such as checks for corrupted links between list -elements, invalid pointers, invalid sizes, double/multiple “frees” of the -same memory allocated, and many corner cases of these. These checks are -implementation specific, and vary per allocator. +Heap corruption protection protects memory allocated dynamically by performing +several checks, such as checks for corrupted links between list elements, +invalid pointers, invalid sizes, double/multiple “frees” of the same memory +allocated, and many corner cases of these. These checks are implementation +specific, and vary per allocator. [ARM Memory Tagging Extension (MTE)](https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety), -when available, will provide hardware assistance for a probabilistic -mitigation to detect memory safety violations by tagging memory allocations, -and automatically checking that the correct tag is used on every memory -access. +when available, will provide hardware assistance for a probabilistic mitigation +to detect memory safety violations by tagging memory allocations, and +automatically checking that the correct tag is used on every memory access. Rust’s default allocator has historically been -[jemalloc](http://jemalloc.net/), and it has long been the cause of issues -and the subject of much discussion[32]–[38]. Consequently, it has been -removed as the default allocator in favor of the operating system’s standard -C library default allocator5 since version 1.32.0 -(2019-01-17)[39]. +[jemalloc](http://jemalloc.net/), and it has long been the cause of issues and +the subject of much discussion[32]–[38]. Consequently, it has been removed as +the default allocator in favor of the operating system’s standard C library +default allocator5 since version 1.32.0 (2019-01-17)[39]. ```rust,no_run fn main() { @@ -330,8 +328,7 @@ $ cargo run free(): invalid next size (normal) Aborted ``` -Fig. 12. Build and execution of hello-rust-heap with debug assertions -enabled. +Fig. 12. Build and execution of hello-rust-heap with debug assertions enabled. ```text $ cargo run --release @@ -341,47 +338,41 @@ $ cargo run --release free(): invalid next size (normal) Aborted ``` -Fig. 13. Build and execution of hello-rust-heap with debug assertions -disabled. +Fig. 13. Build and execution of hello-rust-heap with debug assertions disabled. -Heap corruption checks are being performed when using the default allocator -(i.e., the GNU Allocator) as seen in Fig. 12 and Fig. 13. +Heap corruption checks are performed when using the default allocator (i.e., +the GNU Allocator) (see Figs. 12–13). 5\. Linux's standard C library default allocator is the GNU -Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram -Gloger, which in turn is derived from dlmalloc (Doug Lea malloc) by Doug -Lea. +Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram Gloger, +which in turn is derived from dlmalloc (Doug Lea malloc) by Doug Lea. ### Stack smashing protection -Stack smashing protection protects programs from stack-based buffer -overflows by inserting a random guard value between local variables and the -saved return instruction pointer, and checking if this value has changed -when returning from a function. This is also known as “Stack Protector” or -“Stack Smashing Protector (SSP)”. +Stack smashing protection protects programs from stack-based buffer overflows +by inserting a random guard value between local variables and the saved return +instruction pointer, and checking if this value has changed when returning from +a function. This is also known as “Stack Protector” or “Stack Smashing +Protector (SSP)”. -The Rust compiler supports stack smashing protection on nightly builds[42]. +The Rust compiler supports stack smashing protection on nightly builds[40]. ![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.") -Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in -hello-rust. +Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in hello-rust. -To check if stack smashing protection is enabled for a given binary, search -for cross references to `__stack_chk_fail`. The presence of these -cross-references in Rust-compiled code (e.g., `hello_rust::main`) indicates -that the stack smashing protection is enabled (see Fig. 14). +To check if stack smashing protection is enabled for a given binary, search for +cross references to `__stack_chk_fail` (see Fig. 14). ### Forward-edge control flow protection -Forward-edge control flow protection protects programs from having its -control flow changed/hijacked by performing checks to ensure that -destinations of indirect branches are one of their valid destinations in the -control flow graph. The comprehensiveness of these checks vary per -implementation. This is also known as “forward-edge control flow integrity -(CFI)”. +Forward-edge control flow protection protects programs from having its control +flow changed/hijacked by performing checks to ensure that destinations of +indirect branches are one of their valid destinations in the control flow +graph. The comprehensiveness of these checks vary per implementation. This is +also known as “forward-edge control flow integrity (CFI)”. Newer processors provide hardware assistance for forward-edge control flow protection, such as ARM Branch Target Identification (BTI), ARM Pointer @@ -394,22 +385,19 @@ commercially available [grsecurity/PaX Reuse Attack Protector (RAP)](https://grsecurity.net/rap_faq). The Rust compiler supports forward-edge control flow protection on nightly -builds[40]-[41] 6. ```text -$ readelf -s -W target/debug/rust-cfi | grep "\.cfi" - 12: 0000000000005170 46 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_one.cfi - 15: 00000000000051a0 16 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_two.cfi - 17: 0000000000005270 396 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi4main.cfi -... +$ readelf -s -W target/release/hello-rust | grep "\.cfi" + 5: 0000000000006480 657 FUNC LOCAL DEFAULT 15 _ZN10hello_rust4main17h4e359f1dcd627c83E.cfi ``` -Fig. 15. Checking if LLVM CFI is enabled for a given binary[41]. +Fig. 15. Checking if LLVM CFI is enabled for a given binary. The presence of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and -references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge control -flow protection) is enabled for a given binary. Conversely, the absence of -symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to +references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge +control flow protection) is enabled for a given binary. Conversely, the absence +of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to `__cfi_check`) indicates that LLVM CFI is not enabled for a given binary (see Fig. 15). @@ -421,48 +409,47 @@ class="reversefootnote" role="doc-backlink">↩ ### Backward-edge control flow protection **Shadow stack** protects saved return instruction pointers from being -overwritten by storing a copy of them on a separate (shadow) stack, and -using these copies as authoritative values when returning from functions. -This is also known as “ShadowCallStack” and “Return Flow Guard”, and is -considered an implementation of backward-edge control flow protection (or -“backward-edge CFI”). +overwritten by storing a copy of them on a separate (shadow) stack, and using +these copies as authoritative values when returning from functions. This is +also known as “ShadowCallStack” and “Return Flow Guard”, and is considered an +implementation of backward-edge control flow protection (or “backward-edge +CFI”). **Safe stack** protects not only the saved return instruction pointers, but -also register spills and some local variables from being overwritten by -storing unsafe variables, such as large arrays, on a separate (unsafe) -stack, and using these unsafe variables on the separate stack instead. This -is also known as “SafeStack”, and is also considered an implementation of -backward-edge control flow protection. +also register spills and some local variables from being overwritten by storing +unsafe variables, such as large arrays, on a separate (unsafe) stack, and using +these unsafe variables on the separate stack instead. This is also known as +“SafeStack”, and is also considered an implementation of backward-edge control +flow protection. -Both shadow and safe stack are intended to be a more comprehensive -alternatives to stack smashing protection as they protect the saved return -instruction pointers (and other data in the case of safe stack) from -arbitrary writes and non-linear out-of-bounds writes. +Both shadow and safe stack are intended to be a more comprehensive alternatives +to stack smashing protection as they protect the saved return instruction +pointers (and other data in the case of safe stack) from arbitrary writes and +non-linear out-of-bounds writes. Newer processors provide hardware assistance for backward-edge control flow -protection, such as ARM Pointer Authentication, and Intel Shadow Stack as -part of Intel CET. +protection, such as ARM Pointer Authentication, and Intel Shadow Stack as part +of Intel CET. -The Rust compiler supports shadow stack for aarch64 only -7 -on nightly Rust compilers [43]-[44]. Safe stack is available on nightly -Rust compilers [45]-[46]. +The Rust compiler supports shadow stack for the AArch64 architecture7on +nightly builds[43]-[44], and also supports safe stack on nightly +builds[45]-[46]. ```text $ readelf -s target/release/hello-rust | grep __safestack_init - 1177: 00000000000057b0 444 FUNC GLOBAL DEFAULT 9 __safestack_init + 678: 0000000000008c80 426 FUNC GLOBAL DEFAULT 15 __safestack_init ``` Fig. 16. Checking if LLVM SafeStack is enabled for a given binary. -The presence of the `__safestack_init` symbol indicates that LLVM SafeStack -is enabled for a given binary (see Fig. 16). Conversely, the absence of the -`__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a -given binary. +The presence of the `__safestack_init` symbol indicates that LLVM SafeStack is +enabled for a given binary. Conversely, the absence of the `__safestack_init` +symbol indicates that LLVM SafeStack is not enabled for a given binary (see +Fig. 16). -7\. The shadow stack implementation for the AMD64 -architecture and equivalent in LLVM was removed due to performance and -security issues. +7\. The shadow stack implementation for the AMD64 architecture +and equivalent in LLVM was removed due to performance and security issues. ## Appendix @@ -470,29 +457,28 @@ role="doc-backlink">↩ As of the latest version of the [Linux Standard Base (LSB) Core Specification](https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/progheader.html), the `PT_GNU_STACK` program header indicates whether the stack should be -executable, and the absence of this header indicates that the stack should -be executable. However, the Linux kernel currently sets the -`READ_IMPLIES_EXEC` personality upon loading any executable with the -`PT_GNU_STACK` program header and the `PF_X `flag set or with the absence of -this header, resulting in not only the stack, but also all readable virtual -memory mappings being executable. +executable, and the absence of this header indicates that the stack should be +executable. However, the Linux kernel currently sets the `READ_IMPLIES_EXEC` +personality upon loading any executable with the `PT_GNU_STACK` program header +and the `PF_X` flag set or with the absence of this header, resulting in not +only the stack, but also all readable virtual memory mappings being executable. An attempt to fix this [was made in 2012](https://lore.kernel.org/lkml/f298f914-2239-44e4-8aa1-a51282e7fac0@zmail15.collab.prod.int.phx2.redhat.com/), and another [was made in 2020](https://lore.kernel.org/kernel-hardening/20200327064820.12602-1-keescook@chromium.org/). The former never landed, and the latter partially fixed it, but introduced -other issues—the absence of the `PT_GNU_STACK` program header still causes -not only the stack, but also all readable virtual memory mappings to be -executable in some architectures, such as IA-32 and equivalent (or causes -the stack to be non-executable in some architectures, such as AMD64 and -equivalent, contradicting the LSB). +other issues—the absence of the `PT_GNU_STACK` program header still causes not +only the stack, but also all readable virtual memory mappings to be executable +in some architectures, such as IA-32 and equivalent (or causes the stack to be +non-executable in some architectures, such as AMD64 and equivalent, +contradicting the LSB). -The `READ_IMPLIES_EXEC` personality needs to be completely separated from -the `PT_GNU_STACK` program header by having a separate option for it (or -setarch -X could just be used whenever `READ_IMPLIES_EXEC` is needed), and -the absence of the `PT_GNU_STACK` program header needs to have more secure -defaults (unrelated to `READ_IMPLIES_EXEC`). +The `READ_IMPLIES_EXEC` personality needs to be completely separated from the +`PT_GNU_STACK` program header by having a separate option for it (or setarch -X +could just be used whenever `READ_IMPLIES_EXEC` is needed), and the absence of +the `PT_GNU_STACK` program header needs to have more secure defaults (unrelated +to `READ_IMPLIES_EXEC`). ## References @@ -576,19 +562,19 @@ defaults (unrelated to `READ_IMPLIES_EXEC`). 25. A. Clark. “Explicitly disable stack execution on linux and bsd #30859.” GitHub. . -26. “Replace stack overflow checking with stack probes #16012.” GitHub. +26. Zoxc. “Replace stack overflow checking with stack probes #16012.” GitHub. . -27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and - clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub. - . - -28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. +27. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. . -29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. +28. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. . +29. S. Guelton, S. Ledru, J. Stone. “Bringing Stack Clash Protection to Clang / + X86 — the Open Source Way.” The LLVM Project Blog. + . + 30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by default #29877.” GitHub. . @@ -621,16 +607,16 @@ defaults (unrelated to `READ_IMPLIES_EXEC`). 39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub. . -40. R. de C Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support +40. bbjornse. “Add codegen option for using LLVM stack smash protection #84197.” + GitHub. + +41. R. de C. Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support for Rust #89653.” GitHub. . -41. “ControlFlowIntegrity.” The Rust Unstable Book. +42. “ControlFlowIntegrity.” The Rust Unstable Book. [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity). -42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.” - GitHub. - -43. ivanloz. “Add support for LLVM ShadowCallStack. #98208.” GitHub. +43. I. Lozano. “Add support for LLVM ShadowCallStack #98208.” GitHub. . 44. “ShadowCallStack.” The Rust Unstable Book. diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png index ee2d3fd4f43c6..0da45e56620da 100644 Binary files a/src/doc/rustc/src/images/image1.png and b/src/doc/rustc/src/images/image1.png differ diff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png index 03061e1f0b12d..a9cf23f873772 100644 Binary files a/src/doc/rustc/src/images/image2.png and b/src/doc/rustc/src/images/image2.png differ diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png index ef02c605ead8a..844a2fe67472d 100644 Binary files a/src/doc/rustc/src/images/image3.png and b/src/doc/rustc/src/images/image3.png differ diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md index 11d7b5b59381b..9daa0810126b7 100644 --- a/src/doc/rustc/src/json.md +++ b/src/doc/rustc/src/json.md @@ -11,9 +11,11 @@ If parsing the output with Rust, the [`cargo_metadata`](https://crates.io/crates/cargo_metadata) crate provides some support for parsing the messages. -When parsing, care should be taken to be forwards-compatible with future changes -to the format. Optional values may be `null`. New fields may be added. Enumerated -fields like "level" or "suggestion_applicability" may add new values. +Each type of message has a `$message_type` field which can be used to +distinguish the different formats. When parsing, care should be taken +to be forwards-compatible with future changes to the format. Optional +values may be `null`. New fields may be added. Enumerated fields like +"level" or "suggestion_applicability" may add new values. ## Diagnostics @@ -29,6 +31,8 @@ Diagnostics have the following format: ```javascript { + /* Type of this message */ + "$message_type": "diagnostic", /* The primary message. */ "message": "unused variable: `x`", /* The diagnostic code. @@ -217,6 +221,8 @@ flag][option-emit] documentation. ```javascript { + /* Type of this message */ + "$message_type": "artifact", /* The filename that was generated. */ "artifact": "libfoo.rlib", /* The kind of artifact that was generated. Possible values: @@ -239,6 +245,8 @@ information, even if the diagnostics have been suppressed (such as with an ```javascript { + /* Type of this message */ + "$message_type": "future_incompat", /* An array of objects describing a warning that will become a hard error in the future. */ diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 6a979869a59a6..457e8d90a433d 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -148,7 +148,6 @@ target | std | notes `armv7a-none-eabi` | * | Bare ARMv7-A `armv7r-none-eabi` | * | Bare ARMv7-R `armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat -`asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten `i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87] `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87] `i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87] @@ -160,13 +159,13 @@ target | std | notes [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] -`riscv32i-unknown-none-elf` | * | Bare RISC-V (RV32I ISA) -`riscv32imac-unknown-none-elf` | * | Bare RISC-V (RV32IMAC ISA) -`riscv32imc-unknown-none-elf` | * | Bare RISC-V (RV32IMC ISA) +[`riscv32imac-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA) +[`riscv32i-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32I ISA) +[`riscv32imc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA) `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA) `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA) `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23) -`sparcv9-sun-solaris` | ✓ | SPARC Solaris 10/11, illumos +`sparcv9-sun-solaris` | ✓ | SPARC Solaris 11, illumos `thumbv6m-none-eabi` | * | Bare ARMv6-M `thumbv7em-none-eabi` | * | Bare ARMv7E-M `thumbv7em-none-eabihf` | * | Bare ARMV7E-M, hardfloat @@ -185,7 +184,7 @@ target | std | notes `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android -`x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos +`x86_64-pc-solaris` | ✓ | 64-bit Solaris 11, illumos `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat `x86_64-unknown-redox` | ✓ | Redox OS @@ -216,6 +215,8 @@ host tools. target | std | host | notes -------|:---:|:----:|------- +[`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS +[`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md) | ✓ | ✓ | ARM64e Apple Darwin `aarch64-apple-ios-macabi` | ? | | Apple Catalyst on ARM64 [`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS [`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS Simulator @@ -310,10 +311,11 @@ target | std | host | notes `powerpc64-wrs-vxworks` | ? | | `powerpc64le-unknown-linux-musl` | ? | | [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64 -`powerpc64-ibm-aix` | ? | | 64-bit AIX (7.2 and newer) +[`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer) `riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33) `riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches) -`riscv32im-unknown-none-elf` | * | | Bare RISC-V (RV32IM ISA) +[`riscv32imafc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA) +[`riscv32im-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | | Bare RISC-V (RV32IM ISA) [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF @@ -341,7 +343,6 @@ target | std | host | notes [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS | [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support -`x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md index 9233a36db3d7e..7a6609b2d769f 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md @@ -39,7 +39,7 @@ Create the following shell scripts that wrap Clang from the OpenHarmony SDK: ```sh #!/bin/sh exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ - --target aarch64-linux-gnu \ + -target aarch64-linux-gnu \ "$@" ``` @@ -48,7 +48,7 @@ exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ ```sh #!/bin/sh exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ - --target aarch64-linux-gnu \ + -target aarch64-linux-gnu \ "$@" ``` @@ -81,6 +81,13 @@ ranlib = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ranlib" llvm-config = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-config" ``` +```text +note: You need to insert "/usr/include/x86_64-linux-gnu/" into environment variable: $C_INCLUDE_PATH + if some header files like bits/xxx.h not found. +note: You can install gcc-aarch64-linux-gnu,g++-aarch64-linux-gnu if some files like crti.o not found. +note: You may need to install libc6-dev-i386 libc6-dev if "gnu/stubs-32.h" not found. +``` + ## Building Rust programs Rust does not yet ship pre-compiled artifacts for this target. To compile for @@ -91,7 +98,7 @@ this target, you will either need to build Rust with the target enabled (see You will need to configure the linker to use in `~/.cargo/config`: ```toml [target.aarch64-unknown-teeos] -linker = "/path/to/aarch64-unknown-teeos-clang.sh" +linker = "/path/to/aarch64-unknown-teeos-clang.sh" # or aarch64-linux-gnu-ld ``` ## Testing diff --git a/src/doc/rustc/src/platform-support/aix.md b/src/doc/rustc/src/platform-support/aix.md new file mode 100644 index 0000000000000..c3ce71a183568 --- /dev/null +++ b/src/doc/rustc/src/platform-support/aix.md @@ -0,0 +1,26 @@ +# `powerpc64-ibm-aix` + +**Tier: 3** + +Rust for AIX operating system, currently only 64-bit PowerPC is supported. + +## Target maintainers + +- QIU Chaofan `qiucofan@cn.ibm.com`, https://github.com/ecnelises +- Kai LUO, `lkail@cn.ibm.com`, https://github.com/bzEq + +## Requirements + +This target supports host tools, std and alloc. This target cannot be cross-compiled as for now, mainly because of the unavailability of system linker on other platforms. + +Binary built for this target is expected to run on Power7 or newer CPU, and AIX 7.2 or newer version. + +Binary format of this platform is [XCOFF](https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format). Archive file format is ['AIX big format'](https://www.ibm.com/docs/en/aix/7.2?topic=formats-ar-file-format-big). + +## Testing + +This target supports running test suites natively, but it's not available to cross-compile and execute in emulator. + +## Interoperability with C code + +This target supports C code. C code compiled by XL, Open XL and Clang are compatible with Rust. Typical triple of AIX on 64-bit PowerPC of these compilers are also `powerpc64-ibm-aix`. diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md b/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md new file mode 100644 index 0000000000000..f93555129a20f --- /dev/null +++ b/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md @@ -0,0 +1,36 @@ +# `arm64e-apple-darwin` + +**Tier: 3 (with Host Tools)** + +ARM64e macOS (11.0+, Big Sur+) + +## Target maintainers + +- Artyom Tetyukhin ([@arttet](https://github.com/https://github.com/arttet)) + +## Requirements + +Target for `macOS` on late-generation `M` series Apple chips. + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: + +```toml +[build] +target = [ "arm64e-apple-darwin" ] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. +To compile for this target, you will need to build Rust with the target enabled (see [Building the target](#building-the-target) above). + +## Testing + +The target does support running binaries on macOS platforms with `arm64e` architecture. + +## Cross-compilation toolchains and C code + +The targets do support `C` code. +To build compatible `C` code, you have to use XCode with the same compiler and flags. diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-ios.md b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md new file mode 100644 index 0000000000000..2b2e0289975f2 --- /dev/null +++ b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md @@ -0,0 +1,37 @@ +# `arm64e-apple-ios` + +**Tier: 3** + +ARM64e iOS (12.0+) + +## Target maintainers + +- Artyom Tetyukhin ([@arttet](https://github.com/https://github.com/arttet)) + +## Requirements + +These targets only support cross-compilation. +The targets do support `std`. + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: + +```toml +[build] +target = [ "arm64e-apple-ios" ] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. +To compile for this target, you will need to build Rust with the target enabled (see [Building the target](#building-the-target) above). + +## Testing + +The target does support running binaries on iOS platforms with `arm64e` architecture. + +## Cross-compilation toolchains and C code + +The targets do support `C` code. +To build compatible `C` code, you have to use XCode with the same compiler and flags. diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index f7cce35b1232b..34ab3cdaf25e5 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -692,10 +692,12 @@ Fuchsia's test runner interacts with the Fuchsia emulator and is located at test environment with: ```sh -src/ci/docker/scripts/fuchsia-test-runner.py start \ +( \ + src/ci/docker/scripts/fuchsia-test-runner.py start \ --rust-build ${RUST_SRC_PATH}/build \ --sdk ${SDK_PATH} \ --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} \ +) ``` Where `${RUST_SRC_PATH}/build` is the `build-dir` set in `config.toml` and diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 9f0662783a4ec..2a741fa3d0241 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -121,10 +121,8 @@ export build_env=' env $build_env \ ./x.py build \ - --target aarch64-unknown-nto-qnx710 \ - --target x86_64-pc-nto-qnx710 \ - --target x86_64-unknown-linux-gnu \ - rustc library/core library/alloc + --target aarch64-unknown-nto-qnx710,x86_64-pc-nto-qnx710,x86_64-unknown-linux-gnu \ + rustc library/core library/alloc library/std ``` ## Running the Rust test suite diff --git a/src/doc/rustc/src/platform-support/riscv32i-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32i-unknown-none-elf.md new file mode 100644 index 0000000000000..edfe07fc0537b --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32i-unknown-none-elf.md @@ -0,0 +1 @@ +riscv32imac-unknown-none-elf.md diff --git a/src/doc/rustc/src/platform-support/riscv32im-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32im-unknown-none-elf.md new file mode 100644 index 0000000000000..edfe07fc0537b --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32im-unknown-none-elf.md @@ -0,0 +1 @@ +riscv32imac-unknown-none-elf.md diff --git a/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md new file mode 100644 index 0000000000000..a069f3d3aa9c3 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md @@ -0,0 +1,34 @@ +# `riscv32{i,im,imc,imac,imafc}-unknown-none-elf` + +**Tier: 2/3** + +Bare-metal target for RISC-V CPUs with the RV32I, RV32IM, RV32IMC, RV32IMAFC and RV32IMAC ISAs. + +## Target maintainers + +* Rust Embedded Working Group, [RISC-V team](https://github.com/rust-embedded/wg#the-risc-v-team) + +## Requirements + +The target is cross-compiled, and uses static linking. No external toolchain +is required and the default `rust-lld` linker works, but you must specify +a linker script. The [`riscv-rt`] crate provides a suitable one. The +[`riscv-rust-quickstart`] repository gives an example of an RV32 project. + +[`riscv-rt`]: https://crates.io/crates/riscv-rt +[`riscv-rust-quickstart`]: https://github.com/riscv-rust/riscv-rust-quickstart + +## Building the target + +This target is included in Rust and can be installed via `rustup`. + +## Testing + +This is a cross-compiled no-std target, which must be run either in a simulator +or by programming them onto suitable hardware. It is not possible to run the +Rust testsuite on this target. + +## Cross-compilation toolchains and C code + +This target supports C code. If interlinking with C or C++, you may need to use +riscv64-unknown-elf-gcc as a linker instead of rust-lld. diff --git a/src/doc/rustc/src/platform-support/riscv32imafc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32imafc-unknown-none-elf.md new file mode 100644 index 0000000000000..edfe07fc0537b --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32imafc-unknown-none-elf.md @@ -0,0 +1 @@ +riscv32imac-unknown-none-elf.md diff --git a/src/doc/rustc/src/platform-support/riscv32imc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32imc-unknown-none-elf.md new file mode 100644 index 0000000000000..edfe07fc0537b --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32imc-unknown-none-elf.md @@ -0,0 +1 @@ +riscv32imac-unknown-none-elf.md diff --git a/src/doc/rustdoc/src/read-documentation/search.md b/src/doc/rustdoc/src/read-documentation/search.md index 56a5016d0cee0..1f45bd6c6b827 100644 --- a/src/doc/rustdoc/src/read-documentation/search.md +++ b/src/doc/rustdoc/src/read-documentation/search.md @@ -72,6 +72,7 @@ the standard library and functions that are included in the results list: | [`stdout, [u8]`][stdoutu8] | `Stdout::write` | | [`any -> !`][] | `panic::panic_any` | | [`vec::intoiter -> [T]`][iterasslice] | `IntoIter::as_slice` and `IntoIter::next_chunk` | +| [`iterator, fnmut -> T`][iterreduce] | `Iterator::reduce` and `Iterator::find` | [`usize -> vec`]: ../../std/vec/struct.Vec.html?search=usize%20-%3E%20vec&filter-crate=std [`vec, vec -> bool`]: ../../std/vec/struct.Vec.html?search=vec,%20vec%20-%3E%20bool&filter-crate=std @@ -81,6 +82,7 @@ the standard library and functions that are included in the results list: [`any -> !`]: ../../std/vec/struct.Vec.html?search=any%20-%3E%20!&filter-crate=std [stdoutu8]: ../../std/vec/struct.Vec.html?search=stdout%2C%20[u8]&filter-crate=std [iterasslice]: ../../std/vec/struct.Vec.html?search=vec%3A%3Aintoiter%20->%20[T]&filter-crate=std +[iterreduce]: ../../std/index.html?search=iterator%2C%20fnmut%20->%20T&filter-crate=std ### How type-based search works @@ -95,7 +97,9 @@ After deciding which items are type parameters and which are actual types, it then searches by matching up the function parameters (written before the `->`) and the return types (written after the `->`). Type matching is order-agnostic, and allows items to be left out of the query, but items that are present in the -query must be present in the function for it to match. +query must be present in the function for it to match. The `self` parameter is +treated the same as any other parameter, and `Self` is resolved to the +underlying type's name. Function signature searches can query generics, wrapped in angle brackets, and traits will be normalized like types in the search engine if no type parameters @@ -103,8 +107,37 @@ match them. For example, a function with the signature `fn my_function>(input: I) -> usize` can be matched with the following queries: -* `Iterator -> usize` -* `Iterator -> usize` +* `Iterator -> usize` +* `Iterator -> usize` (you can leave out the `Item=` part) +* `Iterator -> usize` (you can leave out iterator's generic entirely) +* `T -> usize` (you can match with a generic parameter) + +Each of the above queries is progressively looser, except the last one +would not match `dyn Iterator`, since that's not a type parameter. + +If a bound has multiple associated types, specifying the name allows you to +pick which one gets matched. If no name is specified, then the query will +match of any of them. For example, + +```rust +pub trait MyTrait { + type First; + type Second; +} + +/// This function can be found using the following search queries: +/// +/// MyTrait -> bool +/// MyTrait -> bool +/// MyTrait -> bool +/// MyTrait -> bool +/// +/// The following queries, however, will *not* match it: +/// +/// MyTrait -> bool +/// MyTrait -> bool +pub fn my_fn(x: impl MyTrait) -> bool { true } +``` Generics and function parameters are order-agnostic, but sensitive to nesting and number of matches. For example, a function with the signature @@ -134,6 +167,10 @@ Most of these limitations should be addressed in future version of Rustdoc. with that bound, it'll match, but `option -> T where T: Default` cannot be precisely searched for (use `option -> Default`). + * Supertraits, type aliases, and Deref are all ignored. Search mostly + operates on type signatures *as written*, and not as they are + represented within the compiler. + * Type parameters match type parameters, such that `Option` matches `Option`, but never match concrete types in function signatures. A trait named as if it were a type, such as `Option`, will match @@ -183,7 +220,8 @@ slice = OPEN-SQUARE-BRACKET [ nonempty-arg-list ] CLOSE-SQUARE-BRACKET arg = [type-filter *WS COLON *WS] (path [generics] / slice / [!]) type-sep = COMMA/WS *(COMMA/WS) nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) -generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list ] *(type-sep) +generic-arg-list = *(type-sep) arg [ EQUAL arg ] *(type-sep arg [ EQUAL arg ]) *(type-sep) +generics = OPEN-ANGLE-BRACKET [ generic-arg-list ] *(type-sep) CLOSE-ANGLE-BRACKET return-args = RETURN-ARROW *(type-sep) nonempty-arg-list @@ -230,6 +268,7 @@ DOUBLE-COLON = "::" QUOTE = %x22 COMMA = "," RETURN-ARROW = "->" +EQUAL = "=" ALPHA = %x41-5A / %x61-7A ; A-Z / a-z DIGIT = %x30-39 diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index 0e15c79076fa4..a5b9169c9f3d1 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -35,6 +35,9 @@ and `cfg!(name = "value")` call. It will check that the `"value"` specified is p list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` lint diagnostic. The default diagnostic level for this lint is `Warn`. +The command line `--cfg` arguments are currently *NOT* checked but may very well be checked in +the future. + To enable checking of values, but to provide an empty set of expected values, use these forms: ```bash @@ -187,70 +190,3 @@ fn shoot_lasers() {} // the cfg(feature) list fn write_shakespeare() {} ``` - -## The deprecated `names(...)` form - -The `names(...)` form enables checking the names. This form uses a named list: - -```bash -rustc --check-cfg 'names(name1, name2, ... nameN)' -``` - -where each `name` is a bare identifier (has no quotes). The order of the names is not significant. - -If `--check-cfg names(...)` is specified at least once, then `rustc` will check all references to -condition names. `rustc` will check every `#[cfg]` attribute, `#[cfg_attr]` attribute, `cfg` clause -inside `#[link]` attribute and `cfg!(...)` call against the provided list of expected condition -names. If a name is not present in this list, then `rustc` will report an `unexpected_cfgs` lint -diagnostic. The default diagnostic level for this lint is `Warn`. - -If `--check-cfg names(...)` is not specified, then `rustc` will not check references to condition -names. - -`--check-cfg names(...)` may be specified more than once. The result is that the list of valid -condition names is merged across all options. It is legal for a condition name to be specified -more than once; redundantly specifying a condition name has no effect. - -To enable checking condition names with an empty set of valid condition names, use the following -form. The parentheses are required. - -```bash -rustc --check-cfg 'names()' -``` - -Note that `--check-cfg 'names()'` is _not_ equivalent to omitting the option entirely. -The first form enables checking condition names, while specifying that there are no valid -condition names (outside of the set of well-known names defined by `rustc`). Omitting the -`--check-cfg 'names(...)'` option does not enable checking condition names. - -## The deprecated `values(...)` form - -The `values(...)` form enables checking the values within list-valued conditions. It has this -form: - -```bash -rustc --check-cfg `values(name, "value1", "value2", ... "valueN")' -``` - -where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal -string. `name` specifies the name of the condition, such as `feature` or `target_os`. - -When the `values(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]` -attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]` -and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the -list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` -lint diagnostic. The default diagnostic level for this lint is `Warn`. - -To enable checking of values, but to provide an empty set of valid values, use this form: - -```bash -rustc --check-cfg `values(name)` -``` - -The `--check-cfg values(...)` option can be repeated, both for the same condition name and for -different names. If it is repeated for the same condition name, then the sets of values for that -condition are merged together. - -If `values()` is specified, then `rustc` will enable the checking of well-known values defined -by itself. Note that it's necessary to specify the `values()` form to enable the checking of -well known values, specifying the other forms doesn't implicitly enable it. diff --git a/src/doc/unstable-book/src/compiler-flags/function-return.md b/src/doc/unstable-book/src/compiler-flags/function-return.md new file mode 100644 index 0000000000000..d044a6f68aaab --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/function-return.md @@ -0,0 +1,25 @@ +# `function-return` + +The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116853. + +------------------------ + +Option `-Zfunction-return` controls how function returns are converted. + +It is equivalent to [Clang]'s and [GCC]'s `-mfunction-return`. The Linux kernel +uses it for RETHUNK builds. For details, see [LLVM commit 2240d72f15f3] ("[X86] +initial -mfunction-return=thunk-extern support") which introduces the feature. + +Supported values for this option are: + + - `keep`: do not convert function returns. + - `thunk-extern`: convert function returns (`ret`) to jumps (`jmp`) + to an external symbol called `__x86_return_thunk`. + +Like in Clang, GCC's values `thunk` and `thunk-inline` are not supported. + +Only x86 and non-large code models are supported. + +[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mfunction-return +[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mfunction-return +[LLVM commit 2240d72f15f3]: https://github.com/llvm/llvm-project/commit/2240d72f15f3b7b9d9fb65450f9bf635fd310f6f diff --git a/src/doc/unstable-book/src/compiler-flags/llvm-module-flag.md b/src/doc/unstable-book/src/compiler-flags/llvm-module-flag.md new file mode 100644 index 0000000000000..454ad0a9a6dd6 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/llvm-module-flag.md @@ -0,0 +1,12 @@ +# `llvm-module-flag` + +--------------------- + +This flag allows adding a key/value to the `!llvm.module.flags` metadata in the +LLVM-IR for a compiled Rust module. The syntax is + +`-Z llvm_module_flag=:::` + +Currently only u32 values are supported but the type is required to be specified +for forward compatibility. The `behavior` element must match one of the named +LLVM [metadata behaviors](https://llvm.org/docs/LangRef.html#module-flags-metadata) diff --git a/src/doc/unstable-book/src/language-features/link-arg-attribute.md b/src/doc/unstable-book/src/language-features/link-arg-attribute.md new file mode 100644 index 0000000000000..09915a7f2748d --- /dev/null +++ b/src/doc/unstable-book/src/language-features/link-arg-attribute.md @@ -0,0 +1,21 @@ +# `link_arg_attribute` + +The tracking issue for this feature is: [#99427] + +------ + +The `link_arg_attribute` feature allows passing arguments into the linker +from inside of the source code. Order is preserved for link attributes as +they were defined on a single extern block: + +```rust,no_run +#![feature(link_arg_attribute)] + +#[link(kind = "link-arg", name = "--start-group")] +#[link(kind = "static", name = "c")] +#[link(kind = "static", name = "gcc")] +#[link(kind = "link-arg", name = "--end-group")] +extern "C" {} +``` + +[#99427]: https://github.com/rust-lang/rust/issues/99427 diff --git a/src/doc/unstable-book/src/language-features/trait-upcasting.md b/src/doc/unstable-book/src/language-features/trait-upcasting.md deleted file mode 100644 index 3697ae38f9d81..0000000000000 --- a/src/doc/unstable-book/src/language-features/trait-upcasting.md +++ /dev/null @@ -1,27 +0,0 @@ -# `trait_upcasting` - -The tracking issue for this feature is: [#65991] - -[#65991]: https://github.com/rust-lang/rust/issues/65991 - ------------------------- - -The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a -trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo` -so long as `Bar: Foo`. - -```rust,edition2018 -#![feature(trait_upcasting)] -#![allow(incomplete_features)] - -trait Foo {} - -trait Bar: Foo {} - -impl Foo for i32 {} - -impl Bar for T {} - -let bar: &dyn Bar = &123; -let foo: &dyn Foo = bar; -``` diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index f3917b978dfd5..e13e95ef70888 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,7 +9,7 @@ path = "lib.rs" [dependencies] arrayvec = { version = "0.7", default-features = false } askama = { version = "0.12", default-features = false, features = ["config"] } -itertools = "0.10.1" +itertools = "0.11" indexmap = "2" minifier = "0.3.0" once_cell = "1.10.0" diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index bdf6a0f6b239e..007c5e113b71f 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -723,7 +723,7 @@ where fn region_name(region: Region<'_>) -> Option { match *region { - ty::ReEarlyBound(r) => Some(r.name), + ty::ReEarlyParam(r) => Some(r.name), _ => None, } } @@ -743,7 +743,7 @@ impl<'a, 'tcx> TypeFolder> for RegionReplacer<'a, 'tcx> { match *r { // These are the regions that can be seen in the AST. ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned().unwrap_or(r), - ty::ReEarlyBound(_) | ty::ReStatic | ty::ReLateBound(..) | ty::ReError(_) => r, + ty::ReEarlyParam(_) | ty::ReStatic | ty::ReBound(..) | ty::ReError(_) => r, r => bug!("unexpected region: {r:?}"), } } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index ab5aec12fe7cb..0445daf0d4d72 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -164,8 +164,8 @@ impl Cfg { /// Renders the configuration for human display, as a short HTML description. pub(crate) fn render_short_html(&self) -> String { let mut msg = Display(self, Format::ShortHtml).to_string(); - if self.should_capitalize_first_letter() && - let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) + if self.should_capitalize_first_letter() + && let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) { msg[i..i + 1].make_ascii_uppercase(); } @@ -516,7 +516,6 @@ impl<'a> fmt::Display for Display<'a> { (sym::target_arch, Some(arch)) => match arch.as_str() { "aarch64" => "AArch64", "arm" => "ARM", - "asmjs" => "JavaScript", "loongarch64" => "LoongArch LA64", "m68k" => "M68k", "csky" => "CSKY", diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 013814b1f7dca..014bcb1a88172 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -374,15 +374,17 @@ pub(crate) fn build_impl( // Only inline impl if the implemented trait is // reachable in rustdoc generated documentation - if !did.is_local() && let Some(traitref) = associated_trait { + if !did.is_local() + && let Some(traitref) = associated_trait + { let did = traitref.def_id; if !cx.cache.effective_visibilities.is_directly_public(tcx, did) { return; } - if let Some(stab) = tcx.lookup_stability(did) && - stab.is_unstable() && - stab.feature == sym::rustc_private + if let Some(stab) = tcx.lookup_stability(did) + && stab.is_unstable() + && stab.feature == sym::rustc_private { return; } @@ -514,7 +516,10 @@ pub(crate) fn build_impl( } while let Some(ty) = stack.pop() { - if let Some(did) = ty.def_id(&cx.cache) && !document_hidden && tcx.is_doc_hidden(did) { + if let Some(did) = ty.def_id(&cx.cache) + && !document_hidden + && tcx.is_doc_hidden(did) + { return; } if let Some(generics) = ty.generics() { @@ -580,7 +585,8 @@ fn build_module_items( let res = item.res.expect_non_local(); if let Some(def_id) = res.opt_def_id() && let Some(allowed_def_ids) = allowed_def_ids - && !allowed_def_ids.contains(&def_id) { + && !allowed_def_ids.contains(&def_id) + { continue; } if let Some(def_id) = res.mod_def_id() { @@ -599,7 +605,7 @@ fn build_module_items( let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { name: None, - attrs: Box::new(clean::Attributes::default()), + attrs: Box::default(), // We can use the item's `DefId` directly since the only information ever used // from it is `DefId.krate`. item_id: ItemId::DefId(did), @@ -634,7 +640,7 @@ fn build_module_items( pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String { if let Some(did) = did.as_local() { - let hir_id = tcx.hir().local_def_id_to_hir_id(did); + let hir_id = tcx.local_def_id_to_hir_id(did); rustc_hir_pretty::id_to_string(&tcx.hir(), hir_id) } else { tcx.rendered_const(did).clone() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e6e2d60f2e5bf..688751627f3ee 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -54,7 +54,9 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< let mut inserted = FxHashSet::default(); items.extend(doc.foreigns.iter().map(|(item, renamed)| { let item = clean_maybe_renamed_foreign_item(cx, item, *renamed); - if let Some(name) = item.name && (cx.render_options.document_hidden || !item.is_doc_hidden()) { + if let Some(name) = item.name + && (cx.render_options.document_hidden || !item.is_doc_hidden()) + { inserted.insert((item.type_(), name)); } item @@ -85,7 +87,9 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< } let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id); for item in &v { - if let Some(name) = item.name && (cx.render_options.document_hidden || !item.is_doc_hidden()) { + if let Some(name) = item.name + && (cx.render_options.document_hidden || !item.is_doc_hidden()) + { inserted.insert((item.type_(), name)); } } @@ -286,12 +290,10 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option Some(Lifetime::statik()), _ if !region.has_name() => None, - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => { - Some(Lifetime(name)) - } - ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)), - ty::ReLateBound(..) - | ty::ReFree(..) + ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => Some(Lifetime(name)), + ty::ReEarlyParam(ref data) => Some(Lifetime(data.name)), + ty::ReBound(..) + | ty::ReLateParam(..) | ty::ReVar(..) | ty::ReError(_) | ty::RePlaceholder(..) @@ -593,13 +595,13 @@ fn clean_generic_param<'tcx>( }, ) } - hir::GenericParamKind::Const { ty, default } => ( + hir::GenericParamKind::Const { ty, default, is_host_effect } => ( param.name.ident().name, GenericParamDefKind::Const { ty: Box::new(clean_ty(ty, cx)), default: default .map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())), - is_host_effect: cx.tcx.has_attr(param.def_id, sym::rustc_host), + is_host_effect, }, ), }; @@ -819,12 +821,7 @@ fn clean_ty_generics<'tcx>( { let pred = clean_predicate(*pred, cx)?; - bounds.extend( - pred.get_bounds() - .into_iter() - .flatten() - .cloned() - ); + bounds.extend(pred.get_bounds().into_iter().flatten().cloned()); if let Some(proj) = projection && let lhs = clean_projection(proj.map_bound(|p| p.projection_ty), cx, None) @@ -991,10 +988,8 @@ fn clean_proc_macro<'tcx>( cx: &mut DocContext<'tcx>, ) -> ItemKind { let attrs = cx.tcx.hir().attrs(item.hir_id()); - if kind == MacroKind::Derive && - let Some(derive_name) = attrs - .lists(sym::proc_macro_derive) - .find_map(|mi| mi.ident()) + if kind == MacroKind::Derive + && let Some(derive_name) = attrs.lists(sym::proc_macro_derive).find_map(|mi| mi.ident()) { *name = derive_name.name; } @@ -1156,7 +1151,9 @@ fn clean_fn_decl_with_args<'tcx>( hir::FnRetTy::Return(typ) => clean_ty(typ, cx), hir::FnRetTy::DefaultReturn(..) => Type::Tuple(Vec::new()), }; - if let Some(header) = header && header.is_async() { + if let Some(header) = header + && header.is_async() + { output = output.sugared_async_return_type(); } FnDecl { inputs: args, output, c_variadic: decl.c_variadic } @@ -1608,14 +1605,16 @@ fn first_non_private<'tcx>( continue; } - if let Some(def_id) = child.res.opt_def_id() && target_def_id == def_id { + if let Some(def_id) = child.res.opt_def_id() + && target_def_id == def_id + { let mut last_path_res = None; 'reexps: for reexp in child.reexport_chain.iter() { - if let Some(use_def_id) = reexp.id() && - let Some(local_use_def_id) = use_def_id.as_local() && - let Some(hir::Node::Item(item)) = hir.find_by_def_id(local_use_def_id) && - !item.ident.name.is_empty() && - let hir::ItemKind::Use(path, _) = item.kind + if let Some(use_def_id) = reexp.id() + && let Some(local_use_def_id) = use_def_id.as_local() + && let Some(hir::Node::Item(item)) = hir.find_by_def_id(local_use_def_id) + && !item.ident.name.is_empty() + && let hir::ItemKind::Use(path, _) = item.kind { for res in &path.res { if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { @@ -1626,7 +1625,8 @@ fn first_non_private<'tcx>( // We never check for "cx.render_options.document_private" // because if a re-export is not fully public, it's never // documented. - cx.tcx.local_visibility(local_use_def_id).is_public() { + cx.tcx.local_visibility(local_use_def_id).is_public() + { break 'reexps; } last_path_res = Some((path, res)); @@ -1641,7 +1641,12 @@ fn first_non_private<'tcx>( // 1. We found a public reexport. // 2. We didn't find a public reexport so it's the "end type" path. if let Some((new_path, _)) = last_path_res { - return Some(first_non_private_clean_path(cx, path, new_path.segments, new_path.span)); + return Some(first_non_private_clean_path( + cx, + path, + new_path.segments, + new_path.span, + )); } // If `last_path_res` is `None`, it can mean two things: // @@ -1816,11 +1821,8 @@ fn maybe_expand_private_type_alias<'tcx>( } _ => None, }); - if let Some(ct) = const_ { - args.insert( - param.def_id.to_def_id(), - SubstParam::Constant(clean_const(ct, cx)), - ); + if let Some(_) = const_ { + args.insert(param.def_id.to_def_id(), SubstParam::Constant); } // FIXME(const_generics_defaults) indices.consts += 1; @@ -1930,15 +1932,13 @@ fn clean_trait_object_lifetime_bound<'tcx>( // latter contrary to `clean_middle_region`. match *region { ty::ReStatic => Some(Lifetime::statik()), - ty::ReEarlyBound(region) if region.name != kw::Empty => Some(Lifetime(region.name)), - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) - if name != kw::Empty => - { + ty::ReEarlyParam(region) if region.name != kw::Empty => Some(Lifetime(region.name)), + ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) if name != kw::Empty => { Some(Lifetime(name)) } - ty::ReEarlyBound(_) - | ty::ReLateBound(..) - | ty::ReFree(_) + ty::ReEarlyParam(_) + | ty::ReBound(..) + | ty::ReLateParam(_) | ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased @@ -2308,7 +2308,9 @@ fn clean_middle_opaque_bounds<'tcx>( _ => return None, }; - if let Some(sized) = cx.tcx.lang_items().sized_trait() && trait_ref.def_id() == sized { + if let Some(sized) = cx.tcx.lang_items().sized_trait() + && trait_ref.def_id() == sized + { has_sized = true; return None; } @@ -2534,10 +2536,12 @@ fn clean_generic_args<'tcx>( } hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), - // FIXME(effects): This will still emit `` for non-const impls of const traits - hir::GenericArg::Const(ct) - if cx.tcx.has_attr(ct.value.def_id, sym::rustc_host) => - { + // Checking for `is_desugared_from_effects` on the `AnonConst` not only accounts for the case + // where the argument is `host` but for all possible cases (e.g., `true`, `false`). + hir::GenericArg::Const(hir::ConstArg { + is_desugared_from_effects: true, + .. + }) => { return None; } hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), @@ -2683,28 +2687,27 @@ fn add_without_unwanted_attributes<'hir>( let mut attr = attr.clone(); match attr.kind { ast::AttrKind::Normal(ref mut normal) => { - if let [ident] = &*normal.item.path.segments && - let ident = ident.ident.name && - ident == sym::doc + if let [ident] = &*normal.item.path.segments + && let ident = ident.ident.name + && ident == sym::doc { match normal.item.args { ast::AttrArgs::Delimited(ref mut args) => { - let tokens = - filter_tokens_from_list(&args.tokens, |token| { - !matches!( - token, - TokenTree::Token( - Token { - kind: TokenKind::Ident( - sym::hidden | sym::inline | sym::no_inline, - _, - ), - .. - }, - _, - ), - ) - }); + let tokens = filter_tokens_from_list(&args.tokens, |token| { + !matches!( + token, + TokenTree::Token( + Token { + kind: TokenKind::Ident( + sym::hidden | sym::inline | sym::no_inline, + _, + ), + .. + }, + _, + ), + ) + }); args.tokens = TokenStream::new(tokens); attrs.push((Cow::Owned(attr), import_parent)); } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 627f15e67ac30..c35fb9ec78875 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -146,7 +146,8 @@ pub(crate) fn move_bounds_to_generic_parameters(generics: &mut clean::Generics) }) = generics.params.iter_mut().find(|param| ¶m.name == arg) { param_bounds.extend(bounds.drain(..)); - } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred + } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = + &mut pred && let Some(GenericParamDef { kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, .. diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a718cb37d89f8..7a5cf8031375d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -345,7 +345,7 @@ pub(crate) fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span { || tcx.def_span(def_id), |local| { let hir = tcx.hir(); - hir.span_with_body(hir.local_def_id_to_hir_id(local)) + hir.span_with_body(tcx.local_def_id_to_hir_id(local)) }, )) } @@ -498,7 +498,7 @@ impl Item { } pub(crate) fn is_crate(&self) -> bool { - self.is_mod() && self.def_id().map_or(false, |did| did.is_crate_root()) + self.is_mod() && self.def_id().is_some_and(|did| did.is_crate_root()) } pub(crate) fn is_mod(&self) -> bool { self.type_() == ItemType::Module @@ -1269,8 +1269,8 @@ impl GenericBound { pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { use rustc_hir::TraitBoundModifier as TBM; - if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self && - Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() + if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self + && Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() { return true; } @@ -1327,6 +1327,7 @@ impl WherePredicate { pub(crate) enum GenericParamDefKind { Lifetime { outlives: ThinVec }, Type { did: DefId, bounds: ThinVec, default: Option>, synthetic: bool }, + // Option> makes this type smaller than `Option` would. Const { ty: Box, default: Option>, is_host_effect: bool }, } @@ -1622,7 +1623,7 @@ impl Type { /// functions. pub(crate) fn sugared_async_return_type(self) -> Type { if let Type::ImplTrait(mut v) = self - && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _ )) = v.pop() + && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop() && let Some(segment) = trait_.segments.pop() && let GenericArgs::AngleBracketed { mut bindings, .. } = segment.args && let Some(binding) = bindings.pop() @@ -1650,6 +1651,13 @@ impl Type { } } + pub(crate) fn generic_args(&self) -> Option<&GenericArgs> { + match self { + Type::Path { path, .. } => path.generic_args(), + _ => None, + } + } + pub(crate) fn generics(&self) -> Option> { match self { Type::Path { path, .. } => path.generics(), @@ -2190,6 +2198,10 @@ impl Path { } } + pub(crate) fn generic_args(&self) -> Option<&GenericArgs> { + self.segments.last().map(|seg| &seg.args) + } + pub(crate) fn generics(&self) -> Option> { self.segments.last().and_then(|seg| { if let GenericArgs::AngleBracketed { ref args, .. } = seg.args { @@ -2231,6 +2243,39 @@ impl GenericArgs { GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(), } } + pub(crate) fn bindings<'a>(&'a self) -> Box + 'a> { + match self { + &GenericArgs::AngleBracketed { ref bindings, .. } => Box::new(bindings.iter().cloned()), + &GenericArgs::Parenthesized { ref output, .. } => Box::new( + output + .as_ref() + .map(|ty| TypeBinding { + assoc: PathSegment { + name: sym::Output, + args: GenericArgs::AngleBracketed { + args: Vec::new().into_boxed_slice(), + bindings: ThinVec::new(), + }, + }, + kind: TypeBindingKind::Equality { term: Term::Type((**ty).clone()) }, + }) + .into_iter(), + ), + } + } +} + +impl<'a> IntoIterator for &'a GenericArgs { + type IntoIter = Box + 'a>; + type Item = GenericArg; + fn into_iter(self) -> Self::IntoIter { + match self { + &GenericArgs::AngleBracketed { ref args, .. } => Box::new(args.iter().cloned()), + &GenericArgs::Parenthesized { ref inputs, .. } => { + Box::new(inputs.iter().cloned().map(GenericArg::Type)) + } + } + } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -2442,7 +2487,7 @@ impl Import { } pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool { - self.source.did.map_or(false, |did| tcx.is_doc_hidden(did)) + self.source.did.is_some_and(|did| tcx.is_doc_hidden(did)) } } @@ -2501,7 +2546,7 @@ pub(crate) enum TypeBindingKind { pub(crate) enum SubstParam { Type(Type), Lifetime(Lifetime), - Constant(Constant), + Constant, } impl SubstParam { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index dea7bfaf7e22f..82f4a38384dd1 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -124,11 +124,7 @@ pub(crate) fn ty_args_to_args<'tcx>( ))) } GenericArgKind::Const(ct) => { - // FIXME(effects): this relies on the host effect being called `host`, which users could also name - // their const generics. - // FIXME(effects): this causes `host = true` and `host = false` generics to also be emitted. - if let ty::ConstKind::Param(p) = ct.kind() - && p.name == sym::host + if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } = params[index].kind { return None; } @@ -307,7 +303,8 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { debug!("trying to get a name from pattern: {p:?}"); Symbol::intern(&match p.kind { - PatKind::Wild | PatKind::Struct(..) => return kw::Underscore, + // FIXME(never_patterns): does this make sense? + PatKind::Wild | PatKind::Never | PatKind::Struct(..) => return kw::Underscore, PatKind::Binding(_, _, ident, _) => return ident.name, PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), PatKind::Or(pats) => { @@ -447,8 +444,8 @@ pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { return true; } - if let hir::ExprKind::Unary(hir::UnOp::Neg, expr) = &expr.kind && - let hir::ExprKind::Lit(_) = &expr.kind + if let hir::ExprKind::Unary(hir::UnOp::Neg, expr) = &expr.kind + && let hir::ExprKind::Lit(_) = &expr.kind { return true; } @@ -577,9 +574,8 @@ pub(crate) fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Opti /// This function exists because it runs on `hir::Attributes` whereas the other is a /// `clean::Attributes` method. pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool { - tcx.get_attrs(did, sym::doc).any(|attr| { - attr.meta_item_list().map_or(false, |l| rustc_attr::list_contains_name(&l, flag)) - }) + tcx.get_attrs(did, sym::doc) + .any(|attr| attr.meta_item_list().is_some_and(|l| rustc_attr::list_contains_name(&l, flag))) } /// A link to `doc.rust-lang.org` that includes the channel name. Use this instead of manual links @@ -588,7 +584,7 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool { /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable. pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL"); pub(crate) static DOC_CHANNEL: Lazy<&'static str> = - Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap()); + Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit('/').filter(|c| !c.is_empty()).next().unwrap()); /// Render a sequence of macro arms in a format suitable for displaying to the user /// as part of an item declaration. @@ -647,17 +643,16 @@ pub(crate) fn inherits_doc_hidden( ) -> bool { let hir = tcx.hir(); while let Some(id) = tcx.opt_local_parent(def_id) { - if let Some(stop_at) = stop_at && id == stop_at { + if let Some(stop_at) = stop_at + && id == stop_at + { return false; } def_id = id; if tcx.is_doc_hidden(def_id.to_def_id()) { return true; - } else if let Some(node) = hir.find_by_def_id(def_id) && - matches!( - node, - hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }), - ) + } else if let Some(node) = hir.find_by_def_id(def_id) + && matches!(node, hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),) { // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly // on them, they don't inherit it from the parent context. diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 99aa979027f4f..8e8b7ab346b3c 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -798,7 +798,7 @@ impl Options { /// Returns `true` if the file given as `self.input` is a Markdown file. pub(crate) fn markdown_input(&self) -> bool { - self.input.extension().map_or(false, |e| e == "md" || e == "markdown") + self.input.extension().is_some_and(|e| e == "md" || e == "markdown") } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 6d9f8b820c485..8215926ee331f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -107,12 +107,12 @@ impl<'tcx> DocContext<'tcx> { r } - /// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds. + /// Like `tcx.local_def_id_to_hir_id()`, but skips calling it on fake DefIds. /// (This avoids a slice-index-out-of-bounds panic.) pub(crate) fn as_local_hir_id(tcx: TyCtxt<'_>, item_id: ItemId) -> Option { match item_id { ItemId::DefId(real_id) => { - real_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) + real_id.as_local().map(|def_id| tcx.local_def_id_to_hir_id(def_id)) } // FIXME: Can this be `Some` for `Auto` or `Blanket`? _ => None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 2412865801d6d..172b72436278a 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -127,17 +127,17 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { options, false, opts, - Some(compiler.session().parse_sess.clone_source_map()), + Some(compiler.sess.parse_sess.clone_source_map()), None, enable_per_target_ignores, ); let mut hir_collector = HirCollector { - sess: compiler.session(), + sess: &compiler.sess, collector: &mut collector, map: tcx.hir(), codes: ErrorCodes::from( - compiler.session().opts.unstable_features.is_nightly_build(), + compiler.sess.opts.unstable_features.is_nightly_build(), ), tcx, }; @@ -150,7 +150,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { collector }); - if compiler.session().diagnostic().has_errors_or_lint_errors().is_some() { + if compiler.sess.diagnostic().has_errors_or_lint_errors().is_some() { FatalError.raise(); } @@ -597,15 +597,15 @@ pub(crate) fn make_test( loop { match parser.parse_item(ForceCollect::No) { Ok(Some(item)) => { - if !found_main && - let ast::ItemKind::Fn(..) = item.kind && - item.ident.name == sym::main + if !found_main + && let ast::ItemKind::Fn(..) = item.kind + && item.ident.name == sym::main { found_main = true; } - if !found_extern_crate && - let ast::ItemKind::ExternCrate(original) = item.kind + if !found_extern_crate + && let ast::ItemKind::ExternCrate(original) = item.kind { // This code will never be reached if `crate_name` is none because // `found_extern_crate` is initialized to `true` if it is none. @@ -957,10 +957,10 @@ impl Collector { fn get_filename(&self) -> FileName { if let Some(ref source_map) = self.source_map { let filename = source_map.span_to_filename(self.position); - if let FileName::Real(ref filename) = filename && - let Ok(cur_dir) = env::current_dir() && - let Some(local_path) = filename.local_path() && - let Ok(path) = local_path.strip_prefix(&cur_dir) + if let FileName::Real(ref filename) = filename + && let Ok(cur_dir) = env::current_dir() + && let Some(local_path) = filename.local_path() + && let Ok(path) = local_path.strip_prefix(&cur_dir) { return path.to_owned().into(); } @@ -1207,7 +1207,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> { sp: Span, nested: F, ) { - let ast_attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id)); + let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id)); if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) { if !cfg.matches(&self.sess.parse_sess, Some(self.tcx.features())) { return; diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index abff77253eadd..9802097ea290c 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -230,14 +230,14 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // If the impl is from a masked crate or references something from a // masked crate then remove it completely. - if let clean::ImplItem(ref i) = *item.kind && - (self.cache.masked_crates.contains(&item.item_id.krate()) + if let clean::ImplItem(ref i) = *item.kind + && (self.cache.masked_crates.contains(&item.item_id.krate()) || i.trait_ .as_ref() - .map_or(false, |t| is_from_private_dep(self.tcx, self.cache, t.def_id())) + .is_some_and(|t| is_from_private_dep(self.tcx, self.cache, t.def_id())) || i.for_ .def_id(self.cache) - .map_or(false, |d| is_from_private_dep(self.tcx, self.cache, d))) + .is_some_and(|d| is_from_private_dep(self.tcx, self.cache, d))) { return None; } @@ -249,9 +249,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } // Collect all the implementors of traits. - if let clean::ImplItem(ref i) = *item.kind && - let Some(trait_) = &i.trait_ && - !i.kind.is_blanket() + if let clean::ImplItem(ref i) = *item.kind + && let Some(trait_) = &i.trait_ + && !i.kind.is_blanket() { self.cache .implementors @@ -264,8 +264,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { if let Some(s) = item.name.or_else(|| { if item.is_stripped() { None - } else if let clean::ImportItem(ref i) = *item.kind && - let clean::ImportKind::Simple(s) = i.kind { + } else if let clean::ImportItem(ref i) = *item.kind + && let clean::ImportKind::Simple(s) = i.kind + { Some(s) } else { None @@ -278,7 +279,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { .cache .parent_stack .last() - .map_or(false, |parent| parent.is_trait_impl()) => + .is_some_and(|parent| parent.is_trait_impl()) => { // skip associated items in trait impls ((None, None), false) @@ -340,7 +341,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // A crate has a module at its root, containing all items, // which should not be indexed. The crate-item itself is // inserted later on when serializing the search-index. - if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root()) + if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root()) && let ty = item.type_() && (ty != ItemType::StructField || u16::from_str_radix(s.as_str(), 10).is_err()) @@ -357,7 +358,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { desc, parent, parent_idx: None, - impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = self.cache.parent_stack.last() { + impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = + self.cache.parent_stack.last() + { item_id.as_def_id() } else { None @@ -366,6 +369,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { &item, self.tcx, clean_impl_generics(self.cache.parent_stack.last()).as_ref(), + parent, self.cache, ), aliases: item.attrs.get_doc_aliases(), @@ -493,9 +497,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { clean::Type::Path { ref path } | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => { dids.insert(path.def_id()); - if let Some(generics) = path.generics() && - let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).instantiate_identity().kind() && - adt.is_fundamental() { + if let Some(generics) = path.generics() + && let ty::Adt(adt, _) = + self.tcx.type_of(path.def_id()).instantiate_identity().kind() + && adt.is_fundamental() + { for ty in generics { if let Some(did) = ty.def_id(self.cache) { dids.insert(did); diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index def3a90c8e812..e80da46adb4ca 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -16,6 +16,13 @@ use crate::clean; /// Consequently, every change to this type should be synchronized to /// the `itemTypes` mapping table in `html/static/js/search.js`. /// +/// The search engine in search.js also uses item type numbers as a tie breaker when +/// sorting results. Keywords and primitives are given first because we want them to be easily +/// found by new users who don't know about advanced features like type filters. The rest are +/// mostly in an arbitrary order, but it's easier to test the search engine when +/// it's deterministic, and these are strictly finer-grained than language namespaces, so +/// using the path and the item type together to sort ensures that search sorting is stable. +/// /// In addition, code in `html::render` uses this enum to generate CSS classes, page prefixes, and /// module headings. If you are adding to this enum and want to ensure that the sidebar also prints /// a heading, edit the listing in `html/render.rs`, function `sidebar_module`. This uses an @@ -23,32 +30,34 @@ use crate::clean; #[derive(Copy, PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)] #[repr(u8)] pub(crate) enum ItemType { - Module = 0, - ExternCrate = 1, - Import = 2, - Struct = 3, - Enum = 4, - Function = 5, - TypeAlias = 6, - Static = 7, - Trait = 8, - Impl = 9, - TyMethod = 10, - Method = 11, - StructField = 12, - Variant = 13, - Macro = 14, - Primitive = 15, - AssocType = 16, - Constant = 17, - AssocConst = 18, - Union = 19, - ForeignType = 20, - Keyword = 21, + Keyword = 0, + Primitive = 1, + Module = 2, + ExternCrate = 3, + Import = 4, + Struct = 5, + Enum = 6, + Function = 7, + TypeAlias = 8, + Static = 9, + Trait = 10, + Impl = 11, + TyMethod = 12, + Method = 13, + StructField = 14, + Variant = 15, + Macro = 16, + AssocType = 17, + Constant = 18, + AssocConst = 19, + Union = 20, + ForeignType = 21, OpaqueTy = 22, ProcAttribute = 23, ProcDerive = 24, TraitAlias = 25, + // This number is reserved for use in JavaScript + // Generic = 26, } impl Serialize for ItemType { @@ -140,8 +149,7 @@ impl From for ItemType { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::Closure - | DefKind::Coroutine => Self::ForeignType, + | DefKind::Closure => Self::ForeignType, } } } diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index e607a16ad5457..0056fb4853088 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -9,21 +9,6 @@ pub(crate) use renderer::{run_format, FormatRenderer}; use crate::clean::{self, ItemId}; use crate::html::render::Context; -/// Specifies whether rendering directly implemented trait items or ones from a certain Deref -/// impl. -pub(crate) enum AssocItemRender<'a> { - All, - DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, -} - -/// For different handling of associated items from the Deref target of a type rather than the type -/// itself. -#[derive(Copy, Clone, PartialEq)] -pub(crate) enum RenderMode { - Normal, - ForDeref { mut_: bool }, -} - /// Metadata about implementations for a type or trait. #[derive(Clone, Debug)] pub(crate) struct Impl { diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index c49f1a4d37ec1..2535668b83f5a 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,5 +1,4 @@ use rustc_middle::ty::TyCtxt; -use rustc_span::Symbol; use crate::clean; use crate::config::RenderOptions; @@ -68,7 +67,6 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( // Render the crate documentation let mut work = vec![(format_renderer.make_child_renderer(), krate.module)]; - let unknown = Symbol::intern(""); while let Some((mut cx, item)) = work.pop() { if item.is_mod() && T::RUN_ON_MODULE { // modules are special because they add a namespace. We also need to @@ -90,8 +88,10 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( cx.mod_item_out()?; // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special // cases. Use an explicit match instead. - } else if item.name.is_some() && !item.is_extern_crate() { - prof.generic_activity_with_arg("render_item", item.name.unwrap_or(unknown).as_str()) + } else if let Some(item_name) = item.name + && !item.is_extern_crate() + { + prof.generic_activity_with_arg("render_item", item_name.as_str()) .run(|| cx.item(item))?; } } diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 4a19d0a44c365..ea4b573aeb955 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -38,3 +38,39 @@ impl<'a> fmt::Display for Escape<'a> { Ok(()) } } + +/// Wrapper struct which will emit the HTML-escaped version of the contained +/// string when passed to a format string. +/// +/// This is only safe to use for text nodes. If you need your output to be +/// safely contained in an attribute, use [`Escape`]. If you don't know the +/// difference, use [`Escape`]. +pub(crate) struct EscapeBodyText<'a>(pub &'a str); + +impl<'a> fmt::Display for EscapeBodyText<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + // Because the internet is always right, turns out there's not that many + // characters to escape: http://stackoverflow.com/questions/7381974 + let EscapeBodyText(s) = *self; + let pile_o_bits = s; + let mut last = 0; + for (i, ch) in s.char_indices() { + let s = match ch { + '>' => ">", + '<' => "<", + '&' => "&", + _ => continue, + }; + fmt.write_str(&pile_o_bits[last..i])?; + fmt.write_str(s)?; + // NOTE: we only expect single byte characters here - which is fine as long as we + // only match single byte characters + last = i + 1; + } + + if last < s.len() { + fmt.write_str(&pile_o_bits[last..])?; + } + Ok(()) + } +} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 29fd880af50e2..a9c0ab557cb33 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -367,7 +367,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( if ending == Ending::Newline { let mut clause = " ".repeat(indent.saturating_sub(1)); - write!(clause, "where{where_preds},")?; + write!(clause, "

")?; clause } else { // insert a newline after a single space but before multiple spaces at the start @@ -1166,13 +1166,17 @@ fn fmt_type<'cx>( // we need to surround them with angle brackets in some cases (e.g. `::P`). if f.alternate() { - if let Some(trait_) = trait_ && should_show_cast { + if let Some(trait_) = trait_ + && should_show_cast + { write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))? } else { write!(f, "{:#}::", self_type.print(cx))? } } else { - if let Some(trait_) = trait_ && should_show_cast { + if let Some(trait_) = trait_ + && should_show_cast + { write!(f, "<{} as {}>::", self_type.print(cx), trait_.print(cx))? } else { write!(f, "{}::", self_type.print(cx))? @@ -1268,16 +1272,23 @@ impl clean::Impl { write!(f, " for ")?; } - if let clean::Type::Tuple(types) = &self.for_ && - let [clean::Type::Generic(name)] = &types[..] && - (self.kind.is_fake_variadic() || self.kind.is_auto()) + if let clean::Type::Tuple(types) = &self.for_ + && let [clean::Type::Generic(name)] = &types[..] + && (self.kind.is_fake_variadic() || self.kind.is_auto()) { // Hardcoded anchor library/core/src/primitive_docs.rs // Link should match `# Trait implementations` - primitive_link_fragment(f, PrimitiveType::Tuple, format_args!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?; - } else if let clean::BareFunction(bare_fn) = &self.for_ && - let [clean::Argument { type_: clean::Type::Generic(name), .. }] = &bare_fn.decl.inputs.values[..] && - (self.kind.is_fake_variadic() || self.kind.is_auto()) + primitive_link_fragment( + f, + PrimitiveType::Tuple, + format_args!("({name}₁, {name}₂, …, {name}ₙ)"), + "#trait-implementations-1", + cx, + )?; + } else if let clean::BareFunction(bare_fn) = &self.for_ + && let [clean::Argument { type_: clean::Type::Generic(name), .. }] = + &bare_fn.decl.inputs.values[..] + && (self.kind.is_fake_variadic() || self.kind.is_auto()) { // Hardcoded anchor library/core/src/primitive_docs.rs // Link should match `# Trait implementations` @@ -1286,22 +1297,18 @@ impl clean::Impl { let unsafety = bare_fn.unsafety.print_with_space(); let abi = print_abi_with_space(bare_fn.abi); if f.alternate() { - write!( - f, - "{hrtb:#}{unsafety}{abi:#}", - )?; + write!(f, "{hrtb:#}{unsafety}{abi:#}",)?; } else { - write!( - f, - "{hrtb}{unsafety}{abi}", - )?; + write!(f, "{hrtb}{unsafety}{abi}",)?; } - let ellipsis = if bare_fn.decl.c_variadic { - ", ..." - } else { - "" - }; - primitive_link_fragment(f, PrimitiveType::Tuple, format_args!("fn ({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), "#trait-implementations-1", cx)?; + let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" }; + primitive_link_fragment( + f, + PrimitiveType::Tuple, + format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), + "#trait-implementations-1", + cx, + )?; // Write output. if !bare_fn.decl.output.is_unit() { write!(f, " -> ")?; @@ -1447,7 +1454,9 @@ impl clean::FnDecl { let amp = if f.alternate() { "&" } else { "&" }; write!(f, "(")?; - if let Some(n) = line_wrapping_indent && !self.inputs.values.is_empty() { + if let Some(n) = line_wrapping_indent + && !self.inputs.values.is_empty() + { write!(f, "\n{}", Indent(n + 4))?; } for (i, input) in self.inputs.values.iter().enumerate() { diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index d8e36139a7804..1cdc792a819a8 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -6,7 +6,7 @@ //! Use the `render_with_highlighting` to highlight some rust code. use crate::clean::PrimitiveType; -use crate::html::escape::Escape; +use crate::html::escape::EscapeBodyText; use crate::html::render::{Context, LinkFromSrc}; use std::collections::VecDeque; @@ -185,22 +185,30 @@ impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> { if self.pending_elems.is_empty() { return false; } - if let Some((_, parent_class)) = self.closing_tags.last() && - can_merge(current_class, Some(*parent_class), "") + if let Some((_, parent_class)) = self.closing_tags.last() + && can_merge(current_class, Some(*parent_class), "") { for (text, class) in self.pending_elems.iter() { - string(self.out, Escape(text), *class, &self.href_context, false); + string(self.out, EscapeBodyText(text), *class, &self.href_context, false); } } else { // We only want to "open" the tag ourselves if we have more than one pending and if the // current parent tag is not the same as our pending content. - let close_tag = if self.pending_elems.len() > 1 && let Some(current_class) = current_class { + let close_tag = if self.pending_elems.len() > 1 + && let Some(current_class) = current_class + { Some(enter_span(self.out, current_class, &self.href_context)) } else { None }; for (text, class) in self.pending_elems.iter() { - string(self.out, Escape(text), *class, &self.href_context, close_tag.is_none()); + string( + self.out, + EscapeBodyText(text), + *class, + &self.href_context, + close_tag.is_none(), + ); } if let Some(close_tag) = close_tag { exit_span(self.out, close_tag); @@ -260,10 +268,12 @@ pub(super) fn write_code( Highlight::Token { text, class } => { // If we received a `ExitSpan` event and then have a non-compatible `Class`, we // need to close the ``. - let need_current_class_update = if let Some(pending) = token_handler.pending_exit_span && - !can_merge(Some(pending), class, text) { - token_handler.handle_exit_span(); - true + let need_current_class_update = if let Some(pending) = + token_handler.pending_exit_span + && !can_merge(Some(pending), class, text) + { + token_handler.handle_exit_span(); + true // If the two `Class` are different, time to flush the current content and start // a new one. } else if !can_merge(token_handler.current_class, class, text) { @@ -293,7 +303,8 @@ pub(super) fn write_code( } } if should_add { - let closing_tag = enter_span(token_handler.out, class, &token_handler.href_context); + let closing_tag = + enter_span(token_handler.out, class, &token_handler.href_context); token_handler.closing_tags.push((closing_tag, class)); } @@ -302,8 +313,14 @@ pub(super) fn write_code( } Highlight::ExitSpan => { token_handler.current_class = None; - token_handler.pending_exit_span = - Some(token_handler.closing_tags.last().as_ref().expect("ExitSpan without EnterSpan").1); + token_handler.pending_exit_span = Some( + token_handler + .closing_tags + .last() + .as_ref() + .expect("ExitSpan without EnterSpan") + .1, + ); } }; }); @@ -466,7 +483,9 @@ impl<'a> PeekIter<'a> { } /// Returns the next item after the current one. It doesn't interfere with `peek_next` output. fn peek(&mut self) -> Option<&(TokenKind, &'a str)> { - if self.stored.is_empty() && let Some(next) = self.iter.next() { + if self.stored.is_empty() + && let Some(next) = self.iter.next() + { self.stored.push_back(next); } self.stored.front() diff --git a/src/librustdoc/html/highlight/fixtures/dos_line.html b/src/librustdoc/html/highlight/fixtures/dos_line.html index 30b50ca7c662c..b98e6712590c2 100644 --- a/src/librustdoc/html/highlight/fixtures/dos_line.html +++ b/src/librustdoc/html/highlight/fixtures/dos_line.html @@ -1,3 +1,3 @@ pub fn foo() { -println!("foo"); +println!("foo"); } diff --git a/src/librustdoc/html/highlight/fixtures/sample.html b/src/librustdoc/html/highlight/fixtures/sample.html index fced2eacd9e72..aa735e81597c7 100644 --- a/src/librustdoc/html/highlight/fixtures/sample.html +++ b/src/librustdoc/html/highlight/fixtures/sample.html @@ -8,12 +8,12 @@ .lifetime { color: #B76514; } .question-mark { color: #ff9011; } -
#![crate_type = "lib"]
+
#![crate_type = "lib"]
 
 use std::path::{Path, PathBuf};
 
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "windows")]
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "windows")]
 fn main() -> () {
     let foo = true && false || true;
     let _: *const () = 0;
@@ -22,7 +22,7 @@
     let _ = *foo;
     mac!(foo, &mut bar);
     assert!(self.length < N && index <= self.length);
-    ::std::env::var("gateau").is_ok();
+    ::std::env::var("gateau").is_ok();
     #[rustfmt::skip]
     let s:std::path::PathBuf = std::path::PathBuf::new();
     let mut s = String::new();
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 2807dfed07237..abc27bcdf0782 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -841,7 +841,7 @@ impl<'tcx> ExtraInfo<'tcx> {
         if let Some(def_id) = self.def_id.as_local() {
             self.tcx.struct_span_lint_hir(
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
-                self.tcx.hir().local_def_id_to_hir_id(def_id),
+                self.tcx.local_def_id_to_hir_id(def_id),
                 self.sp,
                 msg,
                 |l| l,
@@ -857,7 +857,7 @@ impl<'tcx> ExtraInfo<'tcx> {
         if let Some(def_id) = self.def_id.as_local() {
             self.tcx.struct_span_lint_hir(
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
-                self.tcx.hir().local_def_id_to_hir_id(def_id),
+                self.tcx.local_def_id_to_hir_id(def_id),
                 self.sp,
                 msg,
                 |lint| lint.help(help),
@@ -1119,10 +1119,10 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> {
                     return None;
                 }
                 let indices = self.parse_string(pos)?;
-                if let Some((_, c)) = self.inner.peek().copied() &&
-                    c != '{' &&
-                    !is_separator(c) &&
-                    c != '('
+                if let Some((_, c)) = self.inner.peek().copied()
+                    && c != '{'
+                    && !is_separator(c)
+                    && c != '('
                 {
                     self.emit_error(format!("expected ` `, `{{` or `,` after `\"`, found `{c}`"));
                     return None;
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 50777134d70e5..f0199703c4e16 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -176,9 +176,9 @@ impl<'tcx> Context<'tcx> {
         let mut render_redirect_pages = self.render_redirect_pages;
         // If the item is stripped but inlined, links won't point to the item so no need to generate
         // a file for it.
-        if it.is_stripped() &&
-            let Some(def_id) = it.def_id() &&
-            def_id.is_local()
+        if it.is_stripped()
+            && let Some(def_id) = it.def_id()
+            && def_id.is_local()
         {
             if self.is_inside_inlined_module || self.shared.cache.inlined_items.contains(&def_id) {
                 // For now we're forced to generate a redirect page for stripped items until
@@ -371,7 +371,9 @@ impl<'tcx> Context<'tcx> {
 
             path = href.into_inner().to_string_lossy().into_owned();
 
-            if let Some(c) = path.as_bytes().last() && *c != b'/' {
+            if let Some(c) = path.as_bytes().last()
+                && *c != b'/'
+            {
                 path.push('/');
             }
 
@@ -741,9 +743,10 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             shared.fs.write(scrape_examples_help_file, v)?;
         }
 
-        if let Some(ref redirections) = shared.redirections && !redirections.borrow().is_empty() {
-            let redirect_map_path =
-                self.dst.join(crate_name.as_str()).join("redirect-map.json");
+        if let Some(ref redirections) = shared.redirections
+            && !redirections.borrow().is_empty()
+        {
+            let redirect_map_path = self.dst.join(crate_name.as_str()).join("redirect-map.json");
             let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
             shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
             shared.fs.write(redirect_map_path, paths)?;
@@ -790,7 +793,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             }
         }
         if !self.is_inside_inlined_module {
-            if let Some(def_id) = item.def_id() && self.cache().inlined_items.contains(&def_id) {
+            if let Some(def_id) = item.def_id()
+                && self.cache().inlined_items.contains(&def_id)
+            {
                 self.is_inside_inlined_module = true;
             }
         } else if !self.cache().document_hidden && item.is_doc_hidden() {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index c52fa01bdc413..58599de76ea12 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -66,7 +66,7 @@ use crate::clean::{self, ItemId, RenderedLink, SelfTy};
 use crate::error::Error;
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
-use crate::formats::{AssocItemRender, Impl, RenderMode};
+use crate::formats::Impl;
 use crate::html::escape::Escape;
 use crate::html::format::{
     display_fn, href, join_with_double_colon, print_abi_with_space, print_constness_with_space,
@@ -89,6 +89,21 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ {
     })
 }
 
+/// Specifies whether rendering directly implemented trait items or ones from a certain Deref
+/// impl.
+pub(crate) enum AssocItemRender<'a> {
+    All,
+    DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool },
+}
+
+/// For different handling of associated items from the Deref target of a type rather than the type
+/// itself.
+#[derive(Copy, Clone, PartialEq)]
+pub(crate) enum RenderMode {
+    Normal,
+    ForDeref { mut_: bool },
+}
+
 // Helper structs for rendering items/sidebars and carrying along contextual
 // information
 
@@ -113,6 +128,7 @@ pub(crate) struct IndexItem {
 pub(crate) struct RenderType {
     id: Option,
     generics: Option>,
+    bindings: Option)>>,
 }
 
 impl Serialize for RenderType {
@@ -129,10 +145,15 @@ impl Serialize for RenderType {
             Some(RenderTypeId::Index(idx)) => *idx,
             _ => panic!("must convert render types to indexes before serializing"),
         };
-        if let Some(generics) = &self.generics {
+        if self.generics.is_some() || self.bindings.is_some() {
             let mut seq = serializer.serialize_seq(None)?;
             seq.serialize_element(&id)?;
-            seq.serialize_element(generics)?;
+            seq.serialize_element(self.generics.as_ref().map(Vec::as_slice).unwrap_or_default())?;
+            if self.bindings.is_some() {
+                seq.serialize_element(
+                    self.bindings.as_ref().map(Vec::as_slice).unwrap_or_default(),
+                )?;
+            }
             seq.end()
         } else {
             id.serialize(serializer)
@@ -140,13 +161,31 @@ impl Serialize for RenderType {
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Copy, Debug)]
 pub(crate) enum RenderTypeId {
     DefId(DefId),
     Primitive(clean::PrimitiveType),
+    AssociatedType(Symbol),
     Index(isize),
 }
 
+impl Serialize for RenderTypeId {
+    fn serialize(&self, serializer: S) -> Result
+    where
+        S: Serializer,
+    {
+        let id = match &self {
+            // 0 is a sentinel, everything else is one-indexed
+            // concrete type
+            RenderTypeId::Index(idx) if *idx >= 0 => idx + 1,
+            // generic type parameter
+            RenderTypeId::Index(idx) => *idx,
+            _ => panic!("must convert render types to indexes before serializing"),
+        };
+        id.serialize(serializer)
+    }
+}
+
 /// Full type of functions/methods in the search index.
 #[derive(Debug)]
 pub(crate) struct IndexItemFunctionType {
@@ -171,16 +210,23 @@ impl Serialize for IndexItemFunctionType {
         } else {
             let mut seq = serializer.serialize_seq(None)?;
             match &self.inputs[..] {
-                [one] if one.generics.is_none() => seq.serialize_element(one)?,
+                [one] if one.generics.is_none() && one.bindings.is_none() => {
+                    seq.serialize_element(one)?
+                }
                 _ => seq.serialize_element(&self.inputs)?,
             }
             match &self.output[..] {
                 [] if self.where_clause.is_empty() => {}
-                [one] if one.generics.is_none() => seq.serialize_element(one)?,
+                [one] if one.generics.is_none() && one.bindings.is_none() => {
+                    seq.serialize_element(one)?
+                }
                 _ => seq.serialize_element(&self.output)?,
             }
             for constraint in &self.where_clause {
-                if let [one] = &constraint[..] && one.generics.is_none() {
+                if let [one] = &constraint[..]
+                    && one.generics.is_none()
+                    && one.bindings.is_none()
+                {
                     seq.serialize_element(one)?;
                 } else {
                     seq.serialize_element(constraint)?;
@@ -627,7 +673,7 @@ fn short_item_info(
                     format!("Deprecating in {version}")
                 }
             }
-            DeprecatedSince::Future => String::from("Deprecating in a future Rust version"),
+            DeprecatedSince::Future => String::from("Deprecating in a future version"),
             DeprecatedSince::NonStandard(since) => {
                 format!("Deprecated since {}", Escape(since.as_str()))
             }
@@ -915,7 +961,9 @@ fn render_stability_since_raw_with_extra(
     containing_const_ver: Option,
     extra_class: &str,
 ) -> bool {
-    let stable_version = if ver != containing_ver && let Some(ver) = &ver {
+    let stable_version = if ver != containing_ver
+        && let Some(ver) = &ver
+    {
         since_to_string(ver)
     } else {
         None
@@ -1097,7 +1145,7 @@ impl<'a> AssocItemLink<'a> {
 fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) {
     write!(
         w,
-        "

\ + "

\ {title}\ §\

" @@ -1348,8 +1396,7 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O if let Some(trait_) = &impl_.trait_ { let trait_did = trait_.def_id(); - if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable_trait(cx.tcx())) - { + if cx.cache().traits.get(&trait_did).is_some_and(|t| t.is_notable_trait(cx.tcx())) { has_notable_trait = true; } } @@ -1384,7 +1431,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { if let Some(trait_) = &impl_.trait_ { let trait_did = trait_.def_id(); - if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable_trait(cx.tcx())) { + if cx.cache().traits.get(&trait_did).is_some_and(|t| t.is_notable_trait(cx.tcx())) { if out.is_empty() { write!( &mut out, @@ -1394,15 +1441,10 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { ); } - //use the "where" class here to make it small - write!( - &mut out, - "{}", - impl_.print(false, cx) - ); + write!(&mut out, "
{}
", impl_.print(false, cx)); for it in &impl_.items { if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { - out.push_str(" "); + out.push_str("
"); let empty_set = FxHashSet::default(); let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set); assoc_type( @@ -1415,7 +1457,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { 0, cx, ); - out.push_str(";"); + out.push_str(";
"); } } } @@ -1901,7 +1943,7 @@ pub(crate) fn render_impl_summary( if show_def_docs { for it in &inner_impl.items { if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { - w.write_str(" "); + w.write_str("
"); assoc_type( w, it, @@ -1912,7 +1954,7 @@ pub(crate) fn render_impl_summary( 0, cx, ); - w.write_str(";"); + w.write_str(";
"); } } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index d226701ba4ade..ff7ce01e807c4 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -22,12 +22,13 @@ use super::{ item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls, render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl, render_rightside, render_stability_since_raw, - render_stability_since_raw_with_extra, AssocItemLink, Context, ImplRenderingParameters, + render_stability_since_raw_with_extra, AssocItemLink, AssocItemRender, Context, + ImplRenderingParameters, RenderMode, }; use crate::clean; use crate::config::ModuleSorting; use crate::formats::item_type::ItemType; -use crate::formats::{AssocItemRender, Impl, RenderMode}; +use crate::formats::Impl; use crate::html::escape::Escape; use crate::html::format::{ display_fn, join_with_double_colon, print_abi_with_space, print_constness_with_space, @@ -369,8 +370,8 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: if let (Some(a), Some(b)) = (s1, s2) { match (a.is_stable(), b.is_stable()) { (true, true) | (false, false) => {} - (false, true) => return Ordering::Less, - (true, false) => return Ordering::Greater, + (false, true) => return Ordering::Greater, + (true, false) => return Ordering::Less, } } let lhs = i1.name.unwrap_or(kw::Empty); @@ -429,7 +430,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: last_section = Some(my_section); write!( w, - "

\ + "

\ {name}\

{ITEM_TABLE_OPEN}", id = cx.derive_id(my_section.id()), @@ -596,8 +597,10 @@ fn extra_info_tags<'a, 'tcx: 'a>( // The "rustc_private" crates are permanently unstable so it makes no sense // to render "unstable" everywhere. - if item.stability(tcx).as_ref().map(|s| s.is_unstable() && s.feature != sym::rustc_private) - == Some(true) + if item + .stability(tcx) + .as_ref() + .is_some_and(|s| s.is_unstable() && s.feature != sym::rustc_private) { write!(f, "{}", tag_html("unstable", "", "Experimental"))?; } @@ -824,7 +827,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) { write!( w, - "

\ + "

\ {1}§\

{2}", id, title, extra_content @@ -974,8 +977,9 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // if any Types with the same name but different DefId have been found. let mut implementor_dups: FxHashMap = FxHashMap::default(); for implementor in implementors { - if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache) && - !did.is_local() { + if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache) + && !did.is_local() + { extern_crates.insert(did.krate); } match implementor.inner_impl().for_.without_borrowed_ref() { @@ -1152,9 +1156,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: .take(cx.current.len()) .chain(std::iter::once("trait.impl")) .collect(); - if let Some(did) = it.item_id.as_def_id() && - let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) } && - let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern) { + if let Some(did) = it.item_id.as_def_id() + && let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) } + && let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern) + { js_src_path.extend(fqp[..fqp.len() - 1].iter().copied()); js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap())); } else { @@ -1255,7 +1260,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c if let Some(inner_type) = &t.inner_type { write!( w, - "

\ + "

\ Aliased Type§

" ); @@ -1499,10 +1504,12 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( s: &'a [clean::Item], ) -> impl fmt::Display + 'a + Captures<'cx> { display_fn(|f| { - if s.iter() - .all(|field| matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))) + if !s.is_empty() + && s.iter().all(|field| { + matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) + }) { - return f.write_str("/* private fields */"); + return f.write_str("/* private fields */"); } for (i, ty) in s.iter().enumerate() { @@ -1564,8 +1571,8 @@ fn should_show_enum_discriminant( ) -> bool { let mut has_variants_with_value = false; for variant in variants { - if let clean::VariantItem(ref var) = *variant.kind && - matches!(var.kind, clean::VariantKind::CLike) + if let clean::VariantItem(ref var) = *variant.kind + && matches!(var.kind, clean::VariantKind::CLike) { has_variants_with_value |= var.discriminant.is_some(); } else { @@ -1659,7 +1666,7 @@ fn render_enum_fields( } if variants_stripped && !is_non_exhaustive { - w.write_str(" // some variants omitted\n"); + w.write_str(" // some variants omitted\n"); } if toggle { toggle_close(&mut w); @@ -1678,7 +1685,7 @@ fn item_variants( let tcx = cx.tcx(); write!( w, - "

\ + "

\ Variants{}§\

\ {}\ @@ -1706,8 +1713,8 @@ fn item_variants( " rightside", ); w.write_str("

"); - if let clean::VariantItem(ref var) = *variant.kind && - let clean::VariantKind::CLike = var.kind + if let clean::VariantItem(ref var) = *variant.kind + && let clean::VariantKind::CLike = var.kind { display_c_like_variant( w, @@ -1730,7 +1737,14 @@ fn item_variants( w.write_str("

"); let heading_and_fields = match &variant_data.kind { - clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)), + clean::VariantKind::Struct(s) => { + // If there is no field to display, no need to add the heading. + if s.fields.iter().any(|f| !f.is_doc_hidden()) { + Some(("Fields", &s.fields)) + } else { + None + } + } clean::VariantKind::Tuple(fields) => { // Documentation on tuple variant fields is rare, so to reduce noise we only emit // the section if at least one field is documented. @@ -1765,7 +1779,7 @@ fn item_variants( write!( w, "
\ - \ + \ §\ {f}: {t}\ ", @@ -1804,7 +1818,8 @@ fn item_proc_macro( let name = it.name.expect("proc-macros always have names"); match m.kind { MacroKind::Bang => { - write!(buffer, "{name}!() {{ /* proc-macro */ }}").unwrap(); + write!(buffer, "{name}!() {{ /* proc-macro */ }}") + .unwrap(); } MacroKind::Attr => { write!(buffer, "#[{name}]").unwrap(); @@ -1812,7 +1827,12 @@ fn item_proc_macro( MacroKind::Derive => { write!(buffer, "#[derive({name})]").unwrap(); if !m.helpers.is_empty() { - buffer.write_str("\n{\n // Attributes available to this derive:\n").unwrap(); + buffer + .write_str( + "\n{\n \ + // Attributes available to this derive:\n", + ) + .unwrap(); for attr in &m.helpers { writeln!(buffer, " #[{attr}]").unwrap(); } @@ -1922,7 +1942,7 @@ fn item_fields( if fields.peek().is_some() { write!( w, - "

\ + "

\ {}{}§\

\ {}", @@ -1936,7 +1956,7 @@ fn item_fields( let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField)); write!( w, - "\ + "\ §\ {field_name}: {ty}\ ", @@ -2174,7 +2194,7 @@ fn render_union<'a, 'cx: 'a>( } if it.has_stripped_entries().unwrap() { - write!(f, " /* private fields */\n")?; + write!(f, " /* private fields */\n")?; } if toggle { toggle_close(&mut f); @@ -2260,11 +2280,11 @@ fn render_struct_fields( if has_visible_fields { if has_stripped_entries { - write!(w, "\n{tab} /* private fields */"); + write!(w, "\n{tab} /* private fields */"); } write!(w, "\n{tab}"); } else if has_stripped_entries { - write!(w, " /* private fields */ "); + write!(w, " /* private fields */ "); } if toggle { toggle_close(&mut w); @@ -2273,10 +2293,12 @@ fn render_struct_fields( } Some(CtorKind::Fn) => { w.write_str("("); - if fields.iter().all(|field| { - matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) - }) { - write!(w, "/* private fields */"); + if !fields.is_empty() + && fields.iter().all(|field| { + matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) + }) + { + write!(w, "/* private fields */"); } else { for (i, field) in fields.iter().enumerate() { if i > 0 { diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index af1dab5949613..b3ae720fcf609 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -3,8 +3,10 @@ use std::collections::BTreeMap; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_middle::ty::TyCtxt; +use rustc_span::def_id::DefId; use rustc_span::symbol::Symbol; use serde::ser::{Serialize, SerializeSeq, SerializeStruct, Serializer}; +use thin_vec::ThinVec; use crate::clean; use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate}; @@ -22,6 +24,7 @@ pub(crate) fn build_index<'tcx>( ) -> String { let mut itemid_to_pathid = FxHashMap::default(); let mut primitives = FxHashMap::default(); + let mut associated_types = FxHashMap::default(); let mut crate_paths = vec![]; // Attach all orphan items to the type's definition if the type @@ -38,7 +41,13 @@ pub(crate) fn build_index<'tcx>( parent: Some(parent), parent_idx: None, impl_id, - search_type: get_function_type_for_search(item, tcx, impl_generics.as_ref(), cache), + search_type: get_function_type_for_search( + item, + tcx, + impl_generics.as_ref(), + Some(parent), + cache, + ), aliases: item.attrs.get_doc_aliases(), deprecation: item.deprecation(tcx), }); @@ -76,83 +85,139 @@ pub(crate) fn build_index<'tcx>( let mut search_index = std::mem::replace(&mut cache.search_index, Vec::new()); for item in search_index.iter_mut() { fn insert_into_map( - ty: &mut RenderType, map: &mut FxHashMap, itemid: F, lastpathid: &mut isize, crate_paths: &mut Vec<(ItemType, Vec)>, item_type: ItemType, path: &[Symbol], - ) { + ) -> RenderTypeId { match map.entry(itemid) { - Entry::Occupied(entry) => ty.id = Some(RenderTypeId::Index(*entry.get())), + Entry::Occupied(entry) => RenderTypeId::Index(*entry.get()), Entry::Vacant(entry) => { let pathid = *lastpathid; entry.insert(pathid); *lastpathid += 1; crate_paths.push((item_type, path.to_vec())); - ty.id = Some(RenderTypeId::Index(pathid)); + RenderTypeId::Index(pathid) } } } - fn convert_render_type( - ty: &mut RenderType, + fn convert_render_type_id( + id: RenderTypeId, cache: &mut Cache, itemid_to_pathid: &mut FxHashMap, primitives: &mut FxHashMap, + associated_types: &mut FxHashMap, lastpathid: &mut isize, crate_paths: &mut Vec<(ItemType, Vec)>, - ) { - if let Some(generics) = &mut ty.generics { - for item in generics { - convert_render_type( - item, - cache, - itemid_to_pathid, - primitives, - lastpathid, - crate_paths, - ); - } - } + ) -> Option { let Cache { ref paths, ref external_paths, .. } = *cache; - let Some(id) = ty.id.clone() else { - assert!(ty.generics.is_some()); - return; - }; match id { RenderTypeId::DefId(defid) => { if let Some(&(ref fqp, item_type)) = paths.get(&defid).or_else(|| external_paths.get(&defid)) { - insert_into_map( - ty, + Some(insert_into_map( itemid_to_pathid, ItemId::DefId(defid), lastpathid, crate_paths, item_type, fqp, - ); + )) } else { - ty.id = None; + None } } RenderTypeId::Primitive(primitive) => { let sym = primitive.as_sym(); - insert_into_map( - ty, + Some(insert_into_map( primitives, sym, lastpathid, crate_paths, ItemType::Primitive, &[sym], + )) + } + RenderTypeId::Index(_) => Some(id), + RenderTypeId::AssociatedType(sym) => Some(insert_into_map( + associated_types, + sym, + lastpathid, + crate_paths, + ItemType::AssocType, + &[sym], + )), + } + } + + fn convert_render_type( + ty: &mut RenderType, + cache: &mut Cache, + itemid_to_pathid: &mut FxHashMap, + primitives: &mut FxHashMap, + associated_types: &mut FxHashMap, + lastpathid: &mut isize, + crate_paths: &mut Vec<(ItemType, Vec)>, + ) { + if let Some(generics) = &mut ty.generics { + for item in generics { + convert_render_type( + item, + cache, + itemid_to_pathid, + primitives, + associated_types, + lastpathid, + crate_paths, ); } - RenderTypeId::Index(_) => {} } + if let Some(bindings) = &mut ty.bindings { + bindings.retain_mut(|(associated_type, constraints)| { + let converted_associated_type = convert_render_type_id( + *associated_type, + cache, + itemid_to_pathid, + primitives, + associated_types, + lastpathid, + crate_paths, + ); + let Some(converted_associated_type) = converted_associated_type else { + return false; + }; + *associated_type = converted_associated_type; + for constraint in constraints { + convert_render_type( + constraint, + cache, + itemid_to_pathid, + primitives, + associated_types, + lastpathid, + crate_paths, + ); + } + true + }); + } + let Some(id) = ty.id.clone() else { + assert!(ty.generics.is_some()); + return; + }; + ty.id = convert_render_type_id( + id, + cache, + itemid_to_pathid, + primitives, + associated_types, + lastpathid, + crate_paths, + ); } if let Some(search_type) = &mut item.search_type { for item in &mut search_type.inputs { @@ -161,6 +226,7 @@ pub(crate) fn build_index<'tcx>( cache, &mut itemid_to_pathid, &mut primitives, + &mut associated_types, &mut lastpathid, &mut crate_paths, ); @@ -171,6 +237,7 @@ pub(crate) fn build_index<'tcx>( cache, &mut itemid_to_pathid, &mut primitives, + &mut associated_types, &mut lastpathid, &mut crate_paths, ); @@ -182,6 +249,7 @@ pub(crate) fn build_index<'tcx>( cache, &mut itemid_to_pathid, &mut primitives, + &mut associated_types, &mut lastpathid, &mut crate_paths, ); @@ -228,10 +296,11 @@ pub(crate) fn build_index<'tcx>( let mut associated_item_duplicates = FxHashMap::<(isize, ItemType, Symbol), usize>::default(); for &item in &crate_items { - if item.impl_id.is_some() && let Some(parent_idx) = item.parent_idx { - let count = associated_item_duplicates - .entry((parent_idx, item.ty, item.name)) - .or_insert(0); + if item.impl_id.is_some() + && let Some(parent_idx) = item.parent_idx + { + let count = + associated_item_duplicates.entry((parent_idx, item.ty, item.name)).or_insert(0); *count += 1; } } @@ -441,12 +510,39 @@ pub(crate) fn get_function_type_for_search<'tcx>( item: &clean::Item, tcx: TyCtxt<'tcx>, impl_generics: Option<&(clean::Type, clean::Generics)>, + parent: Option, cache: &Cache, ) -> Option { + let mut trait_info = None; + let impl_or_trait_generics = impl_generics.or_else(|| { + if let Some(def_id) = parent + && let Some(trait_) = cache.traits.get(&def_id) + && let Some((path, _)) = + cache.paths.get(&def_id).or_else(|| cache.external_paths.get(&def_id)) + { + let path = clean::Path { + res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, def_id), + segments: path + .iter() + .map(|name| clean::PathSegment { + name: *name, + args: clean::GenericArgs::AngleBracketed { + args: Vec::new().into_boxed_slice(), + bindings: ThinVec::new(), + }, + }) + .collect(), + }; + trait_info = Some((clean::Type::Path { path }, trait_.generics.clone())); + Some(trait_info.as_ref().unwrap()) + } else { + None + } + }); let (mut inputs, mut output, where_clause) = match *item.kind { - clean::FunctionItem(ref f) => get_fn_inputs_and_outputs(f, tcx, impl_generics, cache), - clean::MethodItem(ref m, _) => get_fn_inputs_and_outputs(m, tcx, impl_generics, cache), - clean::TyMethodItem(ref m) => get_fn_inputs_and_outputs(m, tcx, impl_generics, cache), + clean::FunctionItem(ref f) | clean::MethodItem(ref f, _) | clean::TyMethodItem(ref f) => { + get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache) + } _ => return None, }; @@ -456,14 +552,23 @@ pub(crate) fn get_function_type_for_search<'tcx>( Some(IndexItemFunctionType { inputs, output, where_clause }) } -fn get_index_type(clean_type: &clean::Type, generics: Vec) -> RenderType { +fn get_index_type( + clean_type: &clean::Type, + generics: Vec, + rgen: &mut FxHashMap)>, +) -> RenderType { RenderType { - id: get_index_type_id(clean_type), + id: get_index_type_id(clean_type, rgen), generics: if generics.is_empty() { None } else { Some(generics) }, + bindings: None, } } -fn get_index_type_id(clean_type: &clean::Type) -> Option { +fn get_index_type_id( + clean_type: &clean::Type, + rgen: &mut FxHashMap)>, +) -> Option { + use rustc_hir::def::{DefKind, Res}; match *clean_type { clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())), clean::DynTrait(ref bounds, _) => { @@ -471,18 +576,27 @@ fn get_index_type_id(clean_type: &clean::Type) -> Option { } clean::Primitive(p) => Some(RenderTypeId::Primitive(p)), clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => { - get_index_type_id(type_) + get_index_type_id(type_, rgen) } // The type parameters are converted to generics in `simplify_fn_type` clean::Slice(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Slice)), clean::Array(_, _) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Array)), clean::Tuple(_) => Some(RenderTypeId::Primitive(clean::PrimitiveType::Tuple)), + clean::QPath(ref data) => { + if data.self_type.is_self_type() + && let Some(clean::Path { res: Res::Def(DefKind::Trait, trait_), .. }) = data.trait_ + { + let idx = -isize::try_from(rgen.len() + 1).unwrap(); + let (idx, _) = rgen + .entry(SimplifiedParam::AssociatedType(trait_, data.assoc.name)) + .or_insert_with(|| (idx, Vec::new())); + Some(RenderTypeId::Index(*idx)) + } else { + None + } + } // Not supported yet - clean::BareFunction(_) - | clean::Generic(_) - | clean::ImplTrait(_) - | clean::QPath { .. } - | clean::Infer => None, + clean::BareFunction(_) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None, } } @@ -492,6 +606,9 @@ enum SimplifiedParam { Symbol(Symbol), // every argument-position impl trait is its own type parameter Anonymous(isize), + // in a trait definition, the associated types are all bound to + // their own type parameter + AssociatedType(DefId, Symbol), } /// The point of this function is to lower generics and types into the simplified form that the @@ -522,10 +639,17 @@ fn simplify_fn_type<'tcx, 'a>( } // First, check if it's "Self". + let mut is_self = false; let mut arg = if let Some(self_) = self_ { match &*arg { - Type::BorrowedRef { type_, .. } if type_.is_self_type() => self_, - type_ if type_.is_self_type() => self_, + Type::BorrowedRef { type_, .. } if type_.is_self_type() => { + is_self = true; + self_ + } + type_ if type_.is_self_type() => { + is_self = true; + self_ + } arg => arg, } } else { @@ -584,11 +708,19 @@ fn simplify_fn_type<'tcx, 'a>( } } if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) { - res.push(RenderType { id: Some(RenderTypeId::Index(*idx)), generics: None }); + res.push(RenderType { + id: Some(RenderTypeId::Index(*idx)), + generics: None, + bindings: None, + }); } else { let idx = -isize::try_from(rgen.len() + 1).unwrap(); rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds)); - res.push(RenderType { id: Some(RenderTypeId::Index(idx)), generics: None }); + res.push(RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }); } } else if let Type::ImplTrait(ref bounds) = *arg { let mut type_bounds = Vec::new(); @@ -610,12 +742,16 @@ fn simplify_fn_type<'tcx, 'a>( } if is_return && !type_bounds.is_empty() { // In parameter position, `impl Trait` is a unique thing. - res.push(RenderType { id: None, generics: Some(type_bounds) }); + res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None }); } else { // In parameter position, `impl Trait` is the same as an unnamed generic parameter. let idx = -isize::try_from(rgen.len() + 1).unwrap(); rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds)); - res.push(RenderType { id: Some(RenderTypeId::Index(idx)), generics: None }); + res.push(RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }); } } else if let Type::Slice(ref ty) = *arg { let mut ty_generics = Vec::new(); @@ -630,7 +766,7 @@ fn simplify_fn_type<'tcx, 'a>( is_return, cache, ); - res.push(get_index_type(arg, ty_generics)); + res.push(get_index_type(arg, ty_generics, rgen)); } else if let Type::Array(ref ty, _) = *arg { let mut ty_generics = Vec::new(); simplify_fn_type( @@ -644,7 +780,7 @@ fn simplify_fn_type<'tcx, 'a>( is_return, cache, ); - res.push(get_index_type(arg, ty_generics)); + res.push(get_index_type(arg, ty_generics, rgen)); } else if let Type::Tuple(ref tys) = *arg { let mut ty_generics = Vec::new(); for ty in tys { @@ -660,7 +796,7 @@ fn simplify_fn_type<'tcx, 'a>( cache, ); } - res.push(get_index_type(arg, ty_generics)); + res.push(get_index_type(arg, ty_generics, rgen)); } else { // This is not a type parameter. So for example if we have `T, U: Option`, and we're // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't. @@ -668,12 +804,16 @@ fn simplify_fn_type<'tcx, 'a>( // So in here, we can add it directly and look for its own type parameters (so for `Option`, // we will look for them but not for `T`). let mut ty_generics = Vec::new(); - if let Some(arg_generics) = arg.generics() { - for gen in arg_generics.iter() { + let mut ty_bindings = Vec::new(); + if let Some(arg_generics) = arg.generic_args() { + for ty in arg_generics.into_iter().filter_map(|gen| match gen { + clean::GenericArg::Type(ty) => Some(ty), + _ => None, + }) { simplify_fn_type( self_, generics, - gen, + &ty, tcx, recurse + 1, &mut ty_generics, @@ -682,17 +822,180 @@ fn simplify_fn_type<'tcx, 'a>( cache, ); } + for binding in arg_generics.bindings() { + simplify_fn_binding( + self_, + generics, + &binding, + tcx, + recurse + 1, + &mut ty_bindings, + rgen, + is_return, + cache, + ); + } + } + // Every trait associated type on self gets assigned to a type parameter index + // this same one is used later for any appearances of these types + // + // for example, Iterator::next is: + // + // trait Iterator { + // fn next(&mut self) -> Option + // } + // + // Self is technically just Iterator, but we want to pretend it's more like this: + // + // fn next(self: Iterator) -> Option + if is_self + && let Type::Path { path } = arg + && let def_id = path.def_id() + && let Some(trait_) = cache.traits.get(&def_id) + && trait_.items.iter().any(|at| at.is_ty_associated_type()) + { + for assoc_ty in &trait_.items { + if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind + && let Some(name) = assoc_ty.name + { + let idx = -isize::try_from(rgen.len() + 1).unwrap(); + let (idx, stored_bounds) = rgen + .entry(SimplifiedParam::AssociatedType(def_id, name)) + .or_insert_with(|| (idx, Vec::new())); + let idx = *idx; + if stored_bounds.is_empty() { + // Can't just pass stored_bounds to simplify_fn_type, + // because it also accepts rgen as a parameter. + // Instead, have it fill in this local, then copy it into the map afterward. + let mut type_bounds = Vec::new(); + for bound in bounds { + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut type_bounds, + rgen, + is_return, + cache, + ); + } + } + let stored_bounds = &mut rgen + .get_mut(&SimplifiedParam::AssociatedType(def_id, name)) + .unwrap() + .1; + if stored_bounds.is_empty() { + *stored_bounds = type_bounds; + } + } + ty_bindings.push(( + RenderTypeId::AssociatedType(name), + vec![RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }], + )) + } + } } - let id = get_index_type_id(&arg); + let id = get_index_type_id(&arg, rgen); if id.is_some() || !ty_generics.is_empty() { res.push(RenderType { id, + bindings: if ty_bindings.is_empty() { None } else { Some(ty_bindings) }, generics: if ty_generics.is_empty() { None } else { Some(ty_generics) }, }); } } } +fn simplify_fn_binding<'tcx, 'a>( + self_: Option<&'a Type>, + generics: &Generics, + binding: &'a clean::TypeBinding, + tcx: TyCtxt<'tcx>, + recurse: usize, + res: &mut Vec<(RenderTypeId, Vec)>, + rgen: &mut FxHashMap)>, + is_return: bool, + cache: &Cache, +) { + let mut ty_binding_constraints = Vec::new(); + let ty_binding_assoc = RenderTypeId::AssociatedType(binding.assoc.name); + for gen in &binding.assoc.args { + match gen { + clean::GenericArg::Type(arg) => simplify_fn_type( + self_, + generics, + &arg, + tcx, + recurse + 1, + &mut ty_binding_constraints, + rgen, + is_return, + cache, + ), + clean::GenericArg::Lifetime(_) + | clean::GenericArg::Const(_) + | clean::GenericArg::Infer => {} + } + } + for binding in binding.assoc.args.bindings() { + simplify_fn_binding( + self_, + generics, + &binding, + tcx, + recurse + 1, + res, + rgen, + is_return, + cache, + ); + } + match &binding.kind { + clean::TypeBindingKind::Equality { term } => { + if let clean::Term::Type(arg) = &term { + simplify_fn_type( + self_, + generics, + arg, + tcx, + recurse + 1, + &mut ty_binding_constraints, + rgen, + is_return, + cache, + ); + } + } + clean::TypeBindingKind::Constraint { bounds } => { + for bound in &bounds[..] { + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut ty_binding_constraints, + rgen, + is_return, + cache, + ); + } + } + } + } + res.push((ty_binding_assoc, ty_binding_constraints)); +} + /// Return the full list of types when bounds have been resolved. /// /// i.e. `fn foo>(x: u32, y: B)` will return @@ -700,13 +1003,15 @@ fn simplify_fn_type<'tcx, 'a>( fn get_fn_inputs_and_outputs<'tcx>( func: &Function, tcx: TyCtxt<'tcx>, - impl_generics: Option<&(clean::Type, clean::Generics)>, + impl_or_trait_generics: Option<&(clean::Type, clean::Generics)>, cache: &Cache, ) -> (Vec, Vec, Vec>) { let decl = &func.decl; + let mut rgen: FxHashMap)> = Default::default(); + let combined_generics; - let (self_, generics) = if let Some((impl_self, impl_generics)) = impl_generics { + let (self_, generics) = if let Some((impl_self, impl_generics)) = impl_or_trait_generics { match (impl_generics.is_empty(), func.generics.is_empty()) { (true, _) => (Some(impl_self), &func.generics), (_, true) => (Some(impl_self), impl_generics), @@ -728,8 +1033,6 @@ fn get_fn_inputs_and_outputs<'tcx>( (None, &func.generics) }; - let mut rgen: FxHashMap)> = Default::default(); - let mut arg_types = Vec::new(); for arg in decl.inputs.values.iter() { simplify_fn_type( diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index ba4aaaff5a749..3d28937eb99e1 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -435,9 +435,9 @@ fn sidebar_deref_methods<'a>( } // Recurse into any further impls that might exist for `target` - if let Some(target_did) = target.def_id(c) && - let Some(target_impls) = c.impls.get(&target_did) && - let Some(target_deref_impl) = target_impls.iter().find(|i| { + if let Some(target_did) = target.def_id(c) + && let Some(target_impls) = c.impls.get(&target_did) + && let Some(target_deref_impl) = target_impls.iter().find(|i| { i.inner_impl() .trait_ .as_ref() @@ -445,14 +445,7 @@ fn sidebar_deref_methods<'a>( .unwrap_or(false) }) { - sidebar_deref_methods( - cx, - out, - target_deref_impl, - target_impls, - derefs, - used_links, - ); + sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs, used_links); } } } @@ -494,8 +487,13 @@ fn sidebar_module(items: &[clean::Item]) -> LinkBlock<'static> { && it .name .or_else(|| { - if let clean::ImportItem(ref i) = *it.kind && - let clean::ImportKind::Simple(s) = i.kind { Some(s) } else { None } + if let clean::ImportItem(ref i) = *it.kind + && let clean::ImportKind::Simple(s) = i.kind + { + Some(s) + } else { + None + } }) .is_some() }) diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs index 377daaeb9d487..ee581173a4a11 100644 --- a/src/librustdoc/html/render/type_layout.rs +++ b/src/librustdoc/html/render/type_layout.rs @@ -42,37 +42,35 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( let ty = tcx.type_of(ty_def_id).instantiate_identity(); let type_layout = tcx.layout_of(param_env.and(ty)); - let variants = - if let Ok(type_layout) = type_layout && - let Variants::Multiple { variants, tag, tag_encoding, .. } = - type_layout.layout.variants() && - !variants.is_empty() - { - let tag_size = - if let TagEncoding::Niche { .. } = tag_encoding { - 0 - } else if let Primitive::Int(i, _) = tag.primitive() { - i.size().bytes() - } else { - span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") - }; - variants - .iter_enumerated() - .map(|(variant_idx, variant_layout)| { - let Adt(adt, _) = type_layout.ty.kind() else { - span_bug!(tcx.def_span(ty_def_id), "not an adt") - }; - let name = adt.variant(variant_idx).name; - let is_unsized = variant_layout.abi.is_unsized(); - let is_uninhabited = variant_layout.abi.is_uninhabited(); - let size = variant_layout.size.bytes() - tag_size; - let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size }; - (name, type_layout_size) - }) - .collect() + let variants = if let Ok(type_layout) = type_layout + && let Variants::Multiple { variants, tag, tag_encoding, .. } = + type_layout.layout.variants() + && !variants.is_empty() + { + let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { + 0 + } else if let Primitive::Int(i, _) = tag.primitive() { + i.size().bytes() } else { - Vec::new() + span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") }; + variants + .iter_enumerated() + .map(|(variant_idx, variant_layout)| { + let Adt(adt, _) = type_layout.ty.kind() else { + span_bug!(tcx.def_span(ty_def_id), "not an adt") + }; + let name = adt.variant(variant_idx).name; + let is_unsized = variant_layout.abi.is_unsized(); + let is_uninhabited = variant_layout.abi.is_uninhabited(); + let size = variant_layout.size.bytes() - tag_size; + let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size }; + (name, type_layout_size) + }) + .collect() + } else { + Vec::new() + }; let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| { let is_unsized = layout.abi.is_unsized(); diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 3e58dd96ed92a..b04776e91dc74 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -15,14 +15,14 @@ use rustc_span::Symbol; use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; -use super::{collect_paths_for_type, ensure_trailing_slash, Context}; +use super::{collect_paths_for_type, ensure_trailing_slash, Context, RenderMode}; use crate::clean::{Crate, Item, ItemId, ItemKind}; use crate::config::{EmitType, RenderOptions}; use crate::docfs::PathError; use crate::error::Error; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; -use crate::formats::{Impl, RenderMode}; +use crate::formats::Impl; use crate::html::format::Buffer; use crate::html::render::{AssocItemLink, ImplRenderingParameters}; use crate::html::{layout, static_files}; @@ -356,15 +356,12 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; let content = format!( "

List of all crates

    {}
", - krates - .iter() - .map(|s| { - format!( - "
  • {s}
  • ", - trailing_slash = ensure_trailing_slash(s), - ) - }) - .collect::() + krates.iter().format_with("", |k, f| { + f(&format_args!( + "
  • {k}
  • ", + trailing_slash = ensure_trailing_slash(k), + )) + }) ); let v = layout::render(&shared.layout, &page, "", content, &shared.style_files); shared.fs.write(dst, v)?; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index ce620c226de59..e160ec12f52bb 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -90,7 +90,9 @@ impl LocalSourcesCollector<'_, '_> { ); let mut href = href.into_inner().to_string_lossy().into_owned(); - if let Some(c) = href.as_bytes().last() && *c != b'/' { + if let Some(c) = href.as_bytes().last() + && *c != b'/' + { href.push('/'); } let mut src_fname = p.file_name().expect("source has no filename").to_os_string(); @@ -212,7 +214,9 @@ impl SourceCollector<'_, '_> { let root_path = PathBuf::from("../../").join(root_path.into_inner()); let mut root_path = root_path.to_string_lossy(); - if let Some(c) = root_path.as_bytes().last() && *c != b'/' { + if let Some(c) = root_path.as_bytes().last() + && *c != b'/' + { root_path += "/"; } let mut cur = self.dst.join(cur.into_inner()); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 9efdcd601170e..6e61969a8c190 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -205,7 +205,7 @@ ul.all-items { #toggle-all-docs, a.anchor, -.small-section-header a, +.section-header a, #src-sidebar a, .rust a, .sidebar h2 a, @@ -703,11 +703,8 @@ pre, .rustdoc.src .example-wrap { background: var(--table-alt-row-background-color); } -/* Shift "where ..." part of method or fn definition down a line */ -.method .where, -.fn .where, -.where.fmt-newline { - display: block; +/* "where ..." clauses with block display are also smaller */ +div.where { white-space: pre-wrap; font-size: 0.875rem; } @@ -742,13 +739,13 @@ nav.sub { margin: 0 0 15px 0; } -.small-section-header { +.section-header { /* fields use tags, but should get their own lines */ display: block; position: relative; } -.small-section-header:hover > .anchor, .impl:hover > .anchor, +.section-header:hover > .anchor, .impl:hover > .anchor, .trait-impl:hover > .anchor, .variant:hover > .anchor { display: initial; } @@ -761,11 +758,11 @@ nav.sub { .anchor.field { left: -5px; } -.small-section-header > .anchor { +.section-header > .anchor { left: -15px; padding-right: 8px; } -h2.small-section-header > .anchor { +h2.section-header > .anchor { padding-right: 6px; } @@ -1084,15 +1081,9 @@ so that we can apply CSS-filters to change the arrow color in themes */ } .item-info .stab { - /* This min-height is needed to unify the height of the stab elements because some of them - have emojis. - */ - min-height: 36px; - display: flex; + display: block; padding: 3px; margin-bottom: 5px; - align-items: center; - vertical-align: text-bottom; } .item-name .stab { margin-left: 0.3125em; @@ -1115,17 +1106,26 @@ so that we can apply CSS-filters to change the arrow color in themes */ color: var(--stab-code-color); } -.stab .emoji { +.stab .emoji, .item-info .stab::before { font-size: 1.25rem; +} +.stab .emoji { margin-right: 0.3rem; } +.item-info .stab::before { + /* ensure badges with emoji and without it have same height */ + content: "\0"; + width: 0; + display: inline-block; + color: transparent; +} /* Black one-pixel outline around emoji shapes */ .emoji { text-shadow: 1px 0 0 black, -1px 0 0 black, - 0 1px 0 black, + 0 1px 0 black, 0 -1px 0 black; } diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js index c7811b43d1641..2338931a18fd2 100644 --- a/src/librustdoc/html/static/js/externs.js +++ b/src/librustdoc/html/static/js/externs.js @@ -14,6 +14,7 @@ function initSearch(searchIndex){} * pathWithoutLast: Array, * pathLast: string, * generics: Array, + * bindings: Map<(string|integer), Array>, * }} */ let QueryElement; @@ -24,6 +25,7 @@ let QueryElement; * totalElems: number, * typeFilter: (null|string), * userQuery: string, + * isInBinding: (null|string), * }} */ let ParserState; @@ -191,8 +193,9 @@ let FunctionSearchType; /** * @typedef {{ * id: (null|number), - * ty: (null|number), + * ty: number, * generics: Array, + * bindings: Map>, * }} */ let FunctionType; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 7c052606abacb..d613997cd7ff5 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -25,19 +25,9 @@ function showMain() { removeClass(document.getElementById(MAIN_ID), "hidden"); } -function elemIsInParent(elem, parent) { - while (elem && elem !== document.body) { - if (elem === parent) { - return true; - } - elem = elem.parentElement; - } - return false; -} - function blurHandler(event, parentElem, hideCallback) { - if (!elemIsInParent(document.activeElement, parentElem) && - !elemIsInParent(event.relatedTarget, parentElem) + if (!parentElem.contains(document.activeElement) && + !parentElem.contains(event.relatedTarget) ) { hideCallback(); } @@ -54,7 +44,7 @@ function setMobileTopbar() { if (mobileTopbar) { const mobileTitle = document.createElement("h2"); mobileTitle.className = "location"; - if (hasClass(document.body, "crate")) { + if (hasClass(document.querySelector(".rustdoc"), "crate")) { mobileTitle.innerText = `Crate ${window.currentCrate}`; } else if (locationTitle) { mobileTitle.innerHTML = locationTitle.innerHTML; @@ -485,7 +475,7 @@ function preLoadCss(cssUrl) { return; } - const modpath = hasClass(document.body, "mod") ? "../" : ""; + const modpath = hasClass(document.querySelector(".rustdoc"), "mod") ? "../" : ""; const h3 = document.createElement("h3"); h3.innerHTML = `${longty}`; @@ -1118,7 +1108,7 @@ function preLoadCss(cssUrl) { if (ev.pointerType !== "mouse") { return; } - if (!e.TOOLTIP_FORCE_VISIBLE && !elemIsInParent(ev.relatedTarget, e)) { + if (!e.TOOLTIP_FORCE_VISIBLE && !e.contains(ev.relatedTarget)) { // See "Tooltip pointer leave gesture" below. setTooltipHoverTimeout(e, false); addClass(wrapper, "fade-out"); @@ -1178,10 +1168,10 @@ function preLoadCss(cssUrl) { function tooltipBlurHandler(event) { if (window.CURRENT_TOOLTIP_ELEMENT && - !elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT) && - !elemIsInParent(event.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT) && - !elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE) && - !elemIsInParent(event.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE) + !window.CURRENT_TOOLTIP_ELEMENT.contains(document.activeElement) && + !window.CURRENT_TOOLTIP_ELEMENT.contains(event.relatedTarget) && + !window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(document.activeElement) && + !window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(event.relatedTarget) ) { // Work around a difference in the focus behaviour between Firefox, Chrome, and Safari. // When I click the button on an already-opened tooltip popover, Safari @@ -1248,8 +1238,8 @@ function preLoadCss(cssUrl) { if (ev.pointerType !== "mouse") { return; } - if (!e.TOOLTIP_FORCE_VISIBLE && - !elemIsInParent(ev.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT)) { + if (!e.TOOLTIP_FORCE_VISIBLE && window.CURRENT_TOOLTIP_ELEMENT && + !window.CURRENT_TOOLTIP_ELEMENT.contains(ev.relatedTarget)) { // Tooltip pointer leave gesture: // // Designing a good hover microinteraction is a matter of guessing user @@ -1328,8 +1318,7 @@ function preLoadCss(cssUrl) { const infos = [ `For a full list of all search features, take a look here.`, +href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.html">here.`, "Prefix searches with a type followed by a colon (e.g., fn:) to \ restrict the search to a given item kind.", "Accepted kinds are: fn, mod, struct, \ diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 48c9a53a28310..8f68796ad26b8 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -18,36 +18,38 @@ if (!Array.prototype.toSpliced) { // This mapping table should match the discriminants of // `rustdoc::formats::item_type::ItemType` type in Rust. const itemTypes = [ + "keyword", + "primitive", "mod", "externcrate", "import", - "struct", + "struct", // 5 "enum", "fn", "type", "static", - "trait", + "trait", // 10 "impl", "tymethod", "method", "structfield", - "variant", + "variant", // 15 "macro", - "primitive", "associatedtype", "constant", "associatedconstant", - "union", + "union", // 20 "foreigntype", - "keyword", "existential", "attr", "derive", - "traitalias", + "traitalias", // 25 "generic", ]; const longItemTypes = [ + "keyword", + "primitive type", "module", "extern crate", "re-export", @@ -63,13 +65,11 @@ const longItemTypes = [ "struct field", "enum variant", "macro", - "primitive type", "assoc type", "constant", "assoc const", "union", "foreign type", - "keyword", "existential type", "attribute macro", "derive macro", @@ -77,8 +77,6 @@ const longItemTypes = [ ]; // used for special search precedence -const TY_PRIMITIVE = itemTypes.indexOf("primitive"); -const TY_KEYWORD = itemTypes.indexOf("keyword"); const TY_GENERIC = itemTypes.indexOf("generic"); const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../"; @@ -289,16 +287,12 @@ function initSearch(rawSearchIndex) { } } - function isWhitespace(c) { - return " \t\n\r".indexOf(c) !== -1; - } - function isSpecialStartCharacter(c) { return "<\"".indexOf(c) !== -1; } function isEndCharacter(c) { - return ",>-]".indexOf(c) !== -1; + return "=,>-]".indexOf(c) !== -1; } function isStopCharacter(c) { @@ -398,7 +392,7 @@ function initSearch(rawSearchIndex) { * @return {boolean} */ function isSeparatorCharacter(c) { - return c === ","; + return c === "," || c === "="; } /** @@ -410,7 +404,7 @@ function initSearch(rawSearchIndex) { * @return {boolean} */ function isPathSeparator(c) { - return c === ":" || isWhitespace(c); + return c === ":" || c === " "; } /** @@ -427,7 +421,7 @@ function initSearch(rawSearchIndex) { const c = parserState.userQuery[pos - 1]; if (c === lookingFor) { return true; - } else if (!isWhitespace(c)) { + } else if (c !== " ") { break; } pos -= 1; @@ -456,7 +450,7 @@ function initSearch(rawSearchIndex) { function skipWhitespace(parserState) { while (parserState.pos < parserState.userQuery.length) { const c = parserState.userQuery[parserState.pos]; - if (!isWhitespace(c)) { + if (c !== " ") { break; } parserState.pos += 1; @@ -475,8 +469,6 @@ function initSearch(rawSearchIndex) { const path = name.trim(); if (path.length === 0 && generics.length === 0) { throw ["Unexpected ", parserState.userQuery[parserState.pos]]; - } else if (path === "*") { - throw ["Unexpected ", "*"]; } if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) { throw ["Cannot have more than one element if you use quotes"]; @@ -500,6 +492,8 @@ function initSearch(rawSearchIndex) { " does not accept generic parameters", ]; } + const bindingName = parserState.isInBinding; + parserState.isInBinding = null; return { name: "never", id: null, @@ -507,21 +501,20 @@ function initSearch(rawSearchIndex) { pathWithoutLast: [], pathLast: "never", generics: [], + bindings: new Map(), typeFilter: "primitive", + bindingName, }; } + const quadcolon = /::\s*::/.exec(path); if (path.startsWith("::")) { throw ["Paths cannot start with ", "::"]; } else if (path.endsWith("::")) { throw ["Paths cannot end with ", "::"]; - } else if (path.includes("::::")) { - throw ["Unexpected ", "::::"]; - } else if (path.includes(" ::")) { - throw ["Unexpected ", " ::"]; - } else if (path.includes(":: ")) { - throw ["Unexpected ", ":: "]; - } - const pathSegments = path.split(/::|\s+/); + } else if (quadcolon !== null) { + throw ["Unexpected ", quadcolon[0]]; + } + const pathSegments = path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/); // In case we only have something like `

    `, there is no name. if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) { if (generics.length > 0 || prevIs(parserState, ">")) { @@ -542,14 +535,27 @@ function initSearch(rawSearchIndex) { if (isInGenerics) { parserState.genericsElems += 1; } + const bindingName = parserState.isInBinding; + parserState.isInBinding = null; + const bindings = new Map(); return { name: name.trim(), id: null, fullPath: pathSegments, pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1), pathLast: pathSegments[pathSegments.length - 1], - generics: generics, + generics: generics.filter(gen => { + // Syntactically, bindings are parsed as generics, + // but the query engine treats them differently. + if (gen.bindingName !== null) { + bindings.set(gen.bindingName.name, [gen, ...gen.bindingName.generics]); + return false; + } + return true; + }), + bindings, typeFilter, + bindingName, }; } @@ -589,7 +595,7 @@ function initSearch(rawSearchIndex) { } else { while (parserState.pos + 1 < parserState.length) { const next_c = parserState.userQuery[parserState.pos + 1]; - if (!isWhitespace(next_c)) { + if (next_c !== " ") { break; } parserState.pos += 1; @@ -608,6 +614,7 @@ function initSearch(rawSearchIndex) { } } else if ( c === "[" || + c === "=" || isStopCharacter(c) || isSpecialStartCharacter(c) || isSeparatorCharacter(c) @@ -657,6 +664,7 @@ function initSearch(rawSearchIndex) { parserState.pos += 1; getItemsBefore(query, parserState, generics, "]"); const typeFilter = parserState.typeFilter; + const isInBinding = parserState.isInBinding; if (typeFilter !== null && typeFilter !== "primitive") { throw [ "Invalid search type: primitive ", @@ -667,10 +675,16 @@ function initSearch(rawSearchIndex) { ]; } parserState.typeFilter = null; + parserState.isInBinding = null; parserState.totalElems += 1; if (isInGenerics) { parserState.genericsElems += 1; } + for (const gen of generics) { + if (gen.bindingName !== null) { + throw ["Type parameter ", "=", " cannot be within slice ", "[]"]; + } + } elems.push({ name: "[]", id: null, @@ -679,6 +693,8 @@ function initSearch(rawSearchIndex) { pathLast: "[]", generics, typeFilter: "primitive", + bindingName: isInBinding, + bindings: new Map(), }); } else { const isStringElem = parserState.userQuery[start] === "\""; @@ -705,15 +721,38 @@ function initSearch(rawSearchIndex) { if (start >= end && generics.length === 0) { return; } - elems.push( - createQueryElement( - query, - parserState, - parserState.userQuery.slice(start, end), - generics, - isInGenerics - ) - ); + if (parserState.userQuery[parserState.pos] === "=") { + if (parserState.isInBinding) { + throw ["Cannot write ", "=", " twice in a binding"]; + } + if (!isInGenerics) { + throw ["Type parameter ", "=", " must be within generics list"]; + } + const name = parserState.userQuery.slice(start, end).trim(); + if (name === "!") { + throw ["Type parameter ", "=", " key cannot be ", "!", " never type"]; + } + if (name.includes("!")) { + throw ["Type parameter ", "=", " key cannot be ", "!", " macro"]; + } + if (name.includes("::")) { + throw ["Type parameter ", "=", " key cannot contain ", "::", " path"]; + } + if (name.includes(":")) { + throw ["Type parameter ", "=", " key cannot contain ", ":", " type"]; + } + parserState.isInBinding = { name, generics }; + } else { + elems.push( + createQueryElement( + query, + parserState, + parserState.userQuery.slice(start, end), + generics, + isInGenerics + ) + ); + } } } @@ -737,6 +776,8 @@ function initSearch(rawSearchIndex) { // If this is a generic, keep the outer item's type filter around. const oldTypeFilter = parserState.typeFilter; parserState.typeFilter = null; + const oldIsInBinding = parserState.isInBinding; + parserState.isInBinding = null; let extra = ""; if (endChar === ">") { @@ -752,6 +793,9 @@ function initSearch(rawSearchIndex) { while (parserState.pos < parserState.length) { const c = parserState.userQuery[parserState.pos]; if (c === endChar) { + if (parserState.isInBinding) { + throw ["Unexpected ", endChar, " after ", "="]; + } break; } else if (isSeparatorCharacter(c)) { parserState.pos += 1; @@ -791,7 +835,9 @@ function initSearch(rawSearchIndex) { throw [ "Expected ", ",", - " or ", + ", ", + "=", + ", or ", endChar, ...extra, ", found ", @@ -801,6 +847,8 @@ function initSearch(rawSearchIndex) { throw [ "Expected ", ",", + " or ", + "=", ...extra, ", found ", c, @@ -828,6 +876,7 @@ function initSearch(rawSearchIndex) { parserState.pos += 1; parserState.typeFilter = oldTypeFilter; + parserState.isInBinding = oldIsInBinding; } /** @@ -900,7 +949,7 @@ function initSearch(rawSearchIndex) { query.literalSearch = false; foundStopChar = true; continue; - } else if (isWhitespace(c)) { + } else if (c === " ") { skipWhitespace(parserState); continue; } @@ -1054,8 +1103,13 @@ function initSearch(rawSearchIndex) { for (const elem2 of elem.generics) { convertTypeFilterOnElem(elem2); } + for (const constraints of elem.bindings.values()) { + for (const constraint of constraints) { + convertTypeFilterOnElem(constraint); + } + } } - userQuery = userQuery.trim(); + userQuery = userQuery.trim().replace(/\r|\n|\t/g, " "); const parserState = { length: userQuery.length, pos: 0, @@ -1063,6 +1117,7 @@ function initSearch(rawSearchIndex) { totalElems: 0, genericsElems: 0, typeFilter: null, + isInBinding: null, userQuery: userQuery.toLowerCase(), }; let query = newParsedQuery(userQuery); @@ -1251,16 +1306,6 @@ function initSearch(rawSearchIndex) { return (a > b ? +1 : -1); } - // special precedence for primitive and keyword pages - if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) || - (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) { - return -1; - } - if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) || - (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) { - return 1; - } - // sort by description (no description goes later) a = (aaa.item.desc === ""); b = (bbb.item.desc === ""); @@ -1308,36 +1353,6 @@ function initSearch(rawSearchIndex) { return transformResults(result_list); } - /** - * This function checks generics in search query `queryElem` can all be found in the - * search index (`fnType`), - * - * This function returns `true` if it matches, and also writes the results to mgensInout. - * It returns `false` if no match is found, and leaves mgensInout untouched. - * - * @param {FunctionType} fnType - The object to check. - * @param {QueryElement} queryElem - The element from the parsed query. - * @param {[FunctionType]} whereClause - Trait bounds for generic items. - * @param {Map|null} mgensInout - Map functions generics to query generics. - * - * @return {boolean} - Returns true if a match, false otherwise. - */ - function checkGenerics(fnType, queryElem, whereClause, mgensInout) { - return unifyFunctionTypes( - fnType.generics, - queryElem.generics, - whereClause, - mgensInout, - mgens => { - if (mgensInout) { - for (const [fid, qid] of mgens.entries()) { - mgensInout.set(fid, qid); - } - } - return true; - } - ); - } /** * This function checks if a list of search query `queryElems` can all be found in the * search index (`fnTypes`). @@ -1348,7 +1363,7 @@ function initSearch(rawSearchIndex) { * then this function will try with a different solution, or bail with false if it * runs out of candidates. * - * @param {Array} fnTypes - The objects to check. + * @param {Array} fnTypesIn - The objects to check. * @param {Array} queryElems - The elements from the parsed query. * @param {[FunctionType]} whereClause - Trait bounds for generic items. * @param {Map|null} mgensIn @@ -1359,9 +1374,9 @@ function initSearch(rawSearchIndex) { */ function unifyFunctionTypes(fnTypesIn, queryElems, whereClause, mgensIn, solutionCb) { /** - * @type Map + * @type Map|null */ - let mgens = new Map(mgensIn); + const mgens = mgensIn === null ? null : new Map(mgensIn); if (queryElems.length === 0) { return !solutionCb || solutionCb(mgens); } @@ -1369,204 +1384,249 @@ function initSearch(rawSearchIndex) { return false; } const ql = queryElems.length; - let fl = fnTypesIn.length; + const fl = fnTypesIn.length; + + // One element fast path / base case + if (ql === 1 && queryElems[0].generics.length === 0 + && queryElems[0].bindings.size === 0) { + const queryElem = queryElems[0]; + for (const fnType of fnTypesIn) { + if (!unifyFunctionTypeIsMatchCandidate(fnType, queryElem, whereClause, mgens)) { + continue; + } + if (fnType.id < 0 && queryElem.id < 0) { + if (mgens && mgens.has(fnType.id) && + mgens.get(fnType.id) !== queryElem.id) { + continue; + } + const mgensScratch = new Map(mgens); + mgensScratch.set(fnType.id, queryElem.id); + if (!solutionCb || solutionCb(mgensScratch)) { + return true; + } + } else if (!solutionCb || solutionCb(mgens ? new Map(mgens) : null)) { + // unifyFunctionTypeIsMatchCandidate already checks that ids match + return true; + } + } + for (const fnType of fnTypesIn) { + if (!unifyFunctionTypeIsUnboxCandidate(fnType, queryElem, whereClause, mgens)) { + continue; + } + if (fnType.id < 0) { + if (mgens && mgens.has(fnType.id) && + mgens.get(fnType.id) !== 0) { + continue; + } + const mgensScratch = new Map(mgens); + mgensScratch.set(fnType.id, 0); + if (unifyFunctionTypes( + whereClause[(-fnType.id) - 1], + queryElems, + whereClause, + mgensScratch, + solutionCb + )) { + return true; + } + } else if (unifyFunctionTypes( + fnType.generics, + queryElems, + whereClause, + mgens ? new Map(mgens) : null, + solutionCb + )) { + return true; + } + } + return false; + } + + // Multiple element recursive case /** * @type Array */ - let fnTypes = fnTypesIn.slice(); + const fnTypes = fnTypesIn.slice(); /** - * loop works by building up a solution set in the working arrays + * Algorithm works by building up a solution set in the working arrays * fnTypes gets mutated in place to make this work, while queryElems - * is left alone + * is left alone. + * + * It works backwards, because arrays can be cheaply truncated that way. * - * vvvvvvv `i` points here - * queryElems = [ good, good, good, unknown, unknown ], - * fnTypes = [ good, good, good, unknown, unknown ], - * ---------------- ^^^^^^^^^^^^^^^^ `j` iterates after `i`, - * | looking for candidates - * everything before `i` is the - * current working solution + * vvvvvvv `queryElem` + * queryElems = [ unknown, unknown, good, good, good ] + * fnTypes = [ unknown, unknown, good, good, good ] + * ^^^^^^^^^^^^^^^^ loop over these elements to find candidates * * Everything in the current working solution is known to be a good * match, but it might not be the match we wind up going with, because * there might be more than one candidate match, and we need to try them all * before giving up. So, to handle this, it backtracks on failure. - * - * @type Array<{ - * "fnTypesScratch": Array, - * "queryElemsOffset": integer, - * "fnTypesOffset": integer - * }> */ - const backtracking = []; - let i = 0; - let j = 0; - const backtrack = () => { - while (backtracking.length !== 0) { - // this session failed, but there are other possible solutions - // to backtrack, reset to (a copy of) the old array, do the swap or unboxing - const { - fnTypesScratch, - mgensScratch, - queryElemsOffset, - fnTypesOffset, - unbox, - } = backtracking.pop(); - mgens = new Map(mgensScratch); - const fnType = fnTypesScratch[fnTypesOffset]; - const queryElem = queryElems[queryElemsOffset]; - if (unbox) { - if (fnType.id < 0) { - if (mgens.has(fnType.id) && mgens.get(fnType.id) !== 0) { - continue; - } - mgens.set(fnType.id, 0); - } - const generics = fnType.id < 0 ? - whereClause[(-fnType.id) - 1] : - fnType.generics; - fnTypes = fnTypesScratch.toSpliced(fnTypesOffset, 1, ...generics); - fl = fnTypes.length; - // re-run the matching algorithm on this item - i = queryElemsOffset - 1; - } else { - if (fnType.id < 0) { - if (mgens.has(fnType.id) && mgens.get(fnType.id) !== queryElem.id) { - continue; - } - mgens.set(fnType.id, queryElem.id); - } - fnTypes = fnTypesScratch.slice(); - fl = fnTypes.length; - const tmp = fnTypes[queryElemsOffset]; - fnTypes[queryElemsOffset] = fnTypes[fnTypesOffset]; - fnTypes[fnTypesOffset] = tmp; - // this is known as a good match; go to the next one - i = queryElemsOffset; - } - return true; + const flast = fl - 1; + const qlast = ql - 1; + const queryElem = queryElems[qlast]; + let queryElemsTmp = null; + for (let i = flast; i >= 0; i -= 1) { + const fnType = fnTypes[i]; + if (!unifyFunctionTypeIsMatchCandidate(fnType, queryElem, whereClause, mgens)) { + continue; } - return false; - }; - for (i = 0; i !== ql; ++i) { - const queryElem = queryElems[i]; - /** - * list of potential function types that go with the current query element. - * @type Array - */ - const matchCandidates = []; - let fnTypesScratch = null; - let mgensScratch = null; - // don't try anything before `i`, because they've already been - // paired off with the other query elements - for (j = i; j !== fl; ++j) { - const fnType = fnTypes[j]; - if (unifyFunctionTypeIsMatchCandidate(fnType, queryElem, whereClause, mgens)) { - if (!fnTypesScratch) { - fnTypesScratch = fnTypes.slice(); + let mgensScratch; + if (fnType.id < 0) { + mgensScratch = new Map(mgens); + if (mgensScratch.has(fnType.id) + && mgensScratch.get(fnType.id) !== queryElem.id) { + continue; + } + mgensScratch.set(fnType.id, queryElem.id); + } else { + mgensScratch = mgens; + } + // fnTypes[i] is a potential match + // fnTypes[flast] is the last item in the list + // swap them, and drop the potential match from the list + // check if the remaining function types also match + fnTypes[i] = fnTypes[flast]; + fnTypes.length = flast; + if (!queryElemsTmp) { + queryElemsTmp = queryElems.slice(0, qlast); + } + const passesUnification = unifyFunctionTypes( + fnTypes, + queryElemsTmp, + whereClause, + mgensScratch, + mgensScratch => { + if (fnType.generics.length === 0 && queryElem.generics.length === 0 + && fnType.bindings.size === 0 && queryElem.bindings.size === 0) { + return !solutionCb || solutionCb(mgensScratch); } - unifyFunctionTypes( - fnType.generics, - queryElem.generics, + const solution = unifyFunctionTypeCheckBindings( + fnType, + queryElem, whereClause, - mgens, - mgensScratch => { - matchCandidates.push({ - fnTypesScratch, - mgensScratch, - queryElemsOffset: i, - fnTypesOffset: j, - unbox: false, - }); - return false; // "reject" all candidates to gather all of them - } + mgensScratch ); - } - if (unifyFunctionTypeIsUnboxCandidate(fnType, queryElem, whereClause, mgens)) { - if (!fnTypesScratch) { - fnTypesScratch = fnTypes.slice(); + if (!solution) { + return false; } - if (!mgensScratch) { - mgensScratch = new Map(mgens); + const simplifiedGenerics = solution.simplifiedGenerics; + for (const simplifiedMgens of solution.mgens) { + const passesUnification = unifyFunctionTypes( + simplifiedGenerics, + queryElem.generics, + whereClause, + simplifiedMgens, + solutionCb + ); + if (passesUnification) { + return true; + } } - backtracking.push({ - fnTypesScratch, - mgensScratch, - queryElemsOffset: i, - fnTypesOffset: j, - unbox: true, - }); - } - } - if (matchCandidates.length === 0) { - if (backtrack()) { - continue; - } else { return false; } + ); + if (passesUnification) { + return true; } - // use the current candidate - const {fnTypesOffset: candidate, mgensScratch: mgensNew} = matchCandidates.pop(); - if (fnTypes[candidate].id < 0 && queryElems[i].id < 0) { - mgens.set(fnTypes[candidate].id, queryElems[i].id); - } - for (const [fid, qid] of mgensNew) { - mgens.set(fid, qid); - } - // `i` and `j` are paired off - // `queryElems[i]` is left in place - // `fnTypes[j]` is swapped with `fnTypes[i]` to pair them off - const tmp = fnTypes[candidate]; - fnTypes[candidate] = fnTypes[i]; - fnTypes[i] = tmp; - // write other candidates to backtracking queue - for (const otherCandidate of matchCandidates) { - backtracking.push(otherCandidate); - } - // If we're on the last item, check the solution with the callback - // backtrack if the callback says its unsuitable - while (i === (ql - 1) && solutionCb && !solutionCb(mgens)) { - if (!backtrack()) { - return false; + // backtrack + fnTypes[flast] = fnTypes[i]; + fnTypes[i] = fnType; + fnTypes.length = fl; + } + for (let i = flast; i >= 0; i -= 1) { + const fnType = fnTypes[i]; + if (!unifyFunctionTypeIsUnboxCandidate(fnType, queryElem, whereClause, mgens)) { + continue; + } + let mgensScratch; + if (fnType.id < 0) { + mgensScratch = new Map(mgens); + if (mgensScratch.has(fnType.id) && mgensScratch.get(fnType.id) !== 0) { + continue; } + mgensScratch.set(fnType.id, 0); + } else { + mgensScratch = mgens; + } + const generics = fnType.id < 0 ? + whereClause[(-fnType.id) - 1] : + fnType.generics; + const bindings = fnType.bindings ? + Array.from(fnType.bindings.values()).flat() : + []; + const passesUnification = unifyFunctionTypes( + fnTypes.toSpliced(i, 1, ...generics, ...bindings), + queryElems, + whereClause, + mgensScratch, + solutionCb + ); + if (passesUnification) { + return true; } } - return true; + return false; } - function unifyFunctionTypeIsMatchCandidate(fnType, queryElem, whereClause, mgens) { + /** + * Check if this function is a match candidate. + * + * This function is all the fast checks that don't require backtracking. + * It checks that two items are not named differently, and is load-bearing for that. + * It also checks that, if the query has generics, the function type must have generics + * or associated type bindings: that's not load-bearing, but it prevents unnecessary + * backtracking later. + * + * @param {FunctionType} fnType + * @param {QueryElement} queryElem + * @param {[FunctionSearchType]} whereClause - Trait bounds for generic items. + * @param {Map|null} mgensIn - Map functions generics to query generics. + * @returns {boolean} + */ + function unifyFunctionTypeIsMatchCandidate(fnType, queryElem, whereClause, mgensIn) { // type filters look like `trait:Read` or `enum:Result` if (!typePassesFilter(queryElem.typeFilter, fnType.ty)) { return false; } // fnType.id < 0 means generic // queryElem.id < 0 does too - // mgens[fnType.id] = queryElem.id - // or, if mgens[fnType.id] = 0, then we've matched this generic with a bare trait + // mgensIn[fnType.id] = queryElem.id + // or, if mgensIn[fnType.id] = 0, then we've matched this generic with a bare trait // and should make that same decision everywhere it appears if (fnType.id < 0 && queryElem.id < 0) { - if (mgens.has(fnType.id) && mgens.get(fnType.id) !== queryElem.id) { - return false; - } - for (const [fid, qid] of mgens.entries()) { - if (fnType.id !== fid && queryElem.id === qid) { + if (mgensIn) { + if (mgensIn.has(fnType.id) && mgensIn.get(fnType.id) !== queryElem.id) { return false; } - if (fnType.id === fid && queryElem.id !== qid) { - return false; + for (const [fid, qid] of mgensIn.entries()) { + if (fnType.id !== fid && queryElem.id === qid) { + return false; + } + if (fnType.id === fid && queryElem.id !== qid) { + return false; + } } } + return true; } else { if (queryElem.id === typeNameIdOfArrayOrSlice && (fnType.id === typeNameIdOfSlice || fnType.id === typeNameIdOfArray) ) { // [] matches primitive:array or primitive:slice // if it matches, then we're fine, and this is an appropriate match candidate - } else if (fnType.id !== queryElem.id) { + } else if (fnType.id !== queryElem.id || queryElem.id === null) { return false; } // If the query elem has generics, and the function doesn't, // it can't match. - if (fnType.generics.length === 0 && queryElem.generics.length !== 0) { + if ((fnType.generics.length + fnType.bindings.size) === 0 && + queryElem.generics.length !== 0 + ) { + return false; + } + if (fnType.bindings.size < queryElem.bindings.size) { return false; } // If the query element is a path (it contains `::`), we need to check if this @@ -1595,9 +1655,87 @@ function initSearch(rawSearchIndex) { return false; } } + return true; } - return true; } + /** + * This function checks the associated type bindings. Any that aren't matched get converted + * to generics, and this function returns an array of the function's generics with these + * simplified bindings added to them. That is, it takes a path like this: + * + * Iterator + * + * ... if queryElem itself has an `Item=` in it, then this function returns an empty array. + * But if queryElem contains no Item=, then this function returns a one-item array with the + * ID of u32 in it, and the rest of the matching engine acts as if `Iterator` were + * the type instead. + * + * @param {FunctionType} fnType + * @param {QueryElement} queryElem + * @param {[FunctionType]} whereClause - Trait bounds for generic items. + * @param {Map} mgensIn - Map functions generics to query generics. + * Never modified. + * @returns {false|{mgens: [Map], simplifiedGenerics: [FunctionType]}} + */ + function unifyFunctionTypeCheckBindings(fnType, queryElem, whereClause, mgensIn) { + if (fnType.bindings.size < queryElem.bindings.size) { + return false; + } + let simplifiedGenerics = fnType.generics || []; + if (fnType.bindings.size > 0) { + let mgensSolutionSet = [mgensIn]; + for (const [name, constraints] of queryElem.bindings.entries()) { + if (mgensSolutionSet.length === 0) { + return false; + } + if (!fnType.bindings.has(name)) { + return false; + } + const fnTypeBindings = fnType.bindings.get(name); + mgensSolutionSet = mgensSolutionSet.flatMap(mgens => { + const newSolutions = []; + unifyFunctionTypes( + fnTypeBindings, + constraints, + whereClause, + mgens, + newMgens => { + newSolutions.push(newMgens); + // return `false` makes unifyFunctionTypes return the full set of + // possible solutions + return false; + } + ); + return newSolutions; + }); + } + if (mgensSolutionSet.length === 0) { + return false; + } + const binds = Array.from(fnType.bindings.entries()).flatMap(entry => { + const [name, constraints] = entry; + if (queryElem.bindings.has(name)) { + return []; + } else { + return constraints; + } + }); + if (simplifiedGenerics.length > 0) { + simplifiedGenerics = [...simplifiedGenerics, ...binds]; + } else { + simplifiedGenerics = binds; + } + return { simplifiedGenerics, mgens: mgensSolutionSet }; + } + return { simplifiedGenerics, mgens: [mgensIn] }; + } + /** + * @param {FunctionType} fnType + * @param {QueryElement} queryElem + * @param {[FunctionType]} whereClause - Trait bounds for generic items. + * @param {Map|null} mgens - Map functions generics to query generics. + * @returns {boolean} + */ function unifyFunctionTypeIsUnboxCandidate(fnType, queryElem, whereClause, mgens) { if (fnType.id < 0 && queryElem.id >= 0) { if (!whereClause) { @@ -1605,16 +1743,29 @@ function initSearch(rawSearchIndex) { } // mgens[fnType.id] === 0 indicates that we committed to unboxing this generic // mgens[fnType.id] === null indicates that we haven't decided yet - if (mgens.has(fnType.id) && mgens.get(fnType.id) !== 0) { + if (mgens && mgens.has(fnType.id) && mgens.get(fnType.id) !== 0) { return false; } + // Where clauses can represent cyclical data. + // `null` prevents it from trying to unbox in an infinite loop + const mgensTmp = new Map(mgens); + mgensTmp.set(fnType.id, null); // This is only a potential unbox if the search query appears in the where clause // for example, searching `Read -> usize` should find // `fn read_all(R) -> Result` // generic `R` is considered "unboxed" - return checkIfInList(whereClause[(-fnType.id) - 1], queryElem, whereClause); - } else if (fnType.generics && fnType.generics.length > 0) { - return checkIfInList(fnType.generics, queryElem, whereClause); + return checkIfInList( + whereClause[(-fnType.id) - 1], + queryElem, + whereClause, + mgensTmp + ); + } else if (fnType.generics.length > 0 || fnType.bindings.size > 0) { + const simplifiedGenerics = [ + ...fnType.generics, + ...Array.from(fnType.bindings.values()).flat(), + ]; + return checkIfInList(simplifiedGenerics, queryElem, whereClause, mgens); } return false; } @@ -1626,12 +1777,13 @@ function initSearch(rawSearchIndex) { * @param {Array} list * @param {QueryElement} elem - The element from the parsed query. * @param {[FunctionType]} whereClause - Trait bounds for generic items. + * @param {Map|null} mgens - Map functions generics to query generics. * * @return {boolean} - Returns true if found, false otherwise. */ - function checkIfInList(list, elem, whereClause) { + function checkIfInList(list, elem, whereClause, mgens) { for (const entry of list) { - if (checkType(entry, elem, whereClause)) { + if (checkType(entry, elem, whereClause, mgens)) { return true; } } @@ -1645,42 +1797,29 @@ function initSearch(rawSearchIndex) { * @param {Row} row * @param {QueryElement} elem - The element from the parsed query. * @param {[FunctionType]} whereClause - Trait bounds for generic items. + * @param {Map|null} mgens - Map functions generics to query generics. * * @return {boolean} - Returns true if the type matches, false otherwise. */ - function checkType(row, elem, whereClause) { - if (row.id === null) { - // This is a pure "generic" search, no need to run other checks. - return row.generics.length > 0 - ? checkIfInList(row.generics, elem, whereClause) - : false; - } - - if (row.id < 0 && elem.id >= 0) { - const gid = (-row.id) - 1; - return checkIfInList(whereClause[gid], elem, whereClause); - } - - if (row.id < 0 && elem.id < 0) { - return true; - } - - const matchesExact = row.id === elem.id; - const matchesArrayOrSlice = elem.id === typeNameIdOfArrayOrSlice && - (row.id === typeNameIdOfSlice || row.id === typeNameIdOfArray); - - if ((matchesExact || matchesArrayOrSlice) && - typePassesFilter(elem.typeFilter, row.ty)) { - if (elem.generics.length > 0) { - return checkGenerics(row, elem, whereClause, new Map()); + function checkType(row, elem, whereClause, mgens) { + if (row.bindings.size === 0 && elem.bindings.size === 0) { + if (elem.id < 0) { + return row.id < 0 || checkIfInList(row.generics, elem, whereClause, mgens); + } + if (row.id > 0 && elem.id > 0 && elem.pathWithoutLast.length === 0 && + typePassesFilter(elem.typeFilter, row.ty) && elem.generics.length === 0 && + // special case + elem.id !== typeNameIdOfArrayOrSlice + ) { + return row.id === elem.id || checkIfInList( + row.generics, + elem, + whereClause, + mgens + ); } - return true; } - - // If the current item does not match, try [unboxing] the generic. - // [unboxing]: - // https://ndmitchell.com/downloads/slides-hoogle_fast_type_searching-09_aug_2008.pdf - return checkIfInList(row.generics, elem, whereClause); + return unifyFunctionTypes([row], [elem], whereClause, mgens); } function checkPath(contains, ty, maxEditDistance) { @@ -1696,26 +1835,16 @@ function initSearch(rawSearchIndex) { const length = path.length; const clength = contains.length; - if (clength > length) { - return maxEditDistance + 1; - } - for (let i = 0; i < length; ++i) { - if (i + clength > length) { - break; - } + pathiter: for (let i = length - clength; i >= 0; i -= 1) { let dist_total = 0; - let aborted = false; for (let x = 0; x < clength; ++x) { const dist = editDistance(path[i + x], contains[x], maxEditDistance); if (dist > maxEditDistance) { - aborted = true; - break; + continue pathiter; } dist_total += dist; } - if (!aborted) { - ret_dist = Math.min(ret_dist, Math.round(dist_total / clength)); - } + ret_dist = Math.min(ret_dist, Math.round(dist_total / clength)); } return ret_dist; } @@ -2025,7 +2154,7 @@ function initSearch(rawSearchIndex) { elem.id = match; } if ((elem.id === null && parsedQuery.totalElems > 1 && elem.typeFilter === -1 - && elem.generics.length === 0) + && elem.generics.length === 0 && elem.bindings.size === 0) || elem.typeFilter === TY_GENERIC) { if (genericSymbols.has(elem.name)) { elem.id = genericSymbols.get(elem.name); @@ -2068,6 +2197,23 @@ function initSearch(rawSearchIndex) { for (const elem2 of elem.generics) { convertNameToId(elem2); } + elem.bindings = new Map(Array.from(elem.bindings.entries()) + .map(entry => { + const [name, constraints] = entry; + if (!typeNameIdMap.has(name)) { + parsedQuery.error = [ + "Type parameter ", + name, + " does not exist", + ]; + } + for (const elem2 of constraints) { + convertNameToId(elem2); + } + + return [typeNameIdMap.get(name), constraints]; + }) + ); } for (const elem of parsedQuery.elems) { @@ -2269,10 +2415,7 @@ function initSearch(rawSearchIndex) { * @param {boolean} display - True if this is the active tab */ function addTab(array, query, display) { - let extraClass = ""; - if (display === true) { - extraClass = " active"; - } + const extraClass = display ? " active" : ""; const output = document.createElement("div"); let length = 0; @@ -2514,13 +2657,9 @@ ${item.displayPath}${name}\ /** * Perform a search based on the current state of the search input element * and display the results. - * @param {Event} [e] - The event that triggered this search, if any * @param {boolean} [forced] */ - function search(e, forced) { - if (e) { - e.preventDefault(); - } + function search(forced) { const query = parseQuery(searchState.input.value.trim()); let filterCrates = getFilterCrates(); @@ -2584,16 +2723,39 @@ ${item.displayPath}${name}\ function buildItemSearchType(type, lowercasePaths) { const PATH_INDEX_DATA = 0; const GENERICS_DATA = 1; - let pathIndex, generics; + const BINDINGS_DATA = 2; + let pathIndex, generics, bindings; if (typeof type === "number") { pathIndex = type; generics = []; + bindings = new Map(); } else { pathIndex = type[PATH_INDEX_DATA]; generics = buildItemSearchTypeAll( type[GENERICS_DATA], lowercasePaths ); + if (type.length > BINDINGS_DATA) { + bindings = new Map(type[BINDINGS_DATA].map(binding => { + const [assocType, constraints] = binding; + // Associated type constructors are represented sloppily in rustdoc's + // type search, to make the engine simpler. + // + // MyType=Result> is equivalent to MyType>=T> + // and both are, essentially + // MyType)>, except the tuple isn't actually there. + // It's more like the value of a type binding is naturally an array, + // which rustdoc calls "constraints". + // + // As a result, the key should never have generics on it. + return [ + buildItemSearchType(assocType, lowercasePaths).id, + buildItemSearchTypeAll(constraints, lowercasePaths), + ]; + })); + } else { + bindings = new Map(); + } } if (pathIndex < 0) { // types less than 0 are generic parameters @@ -2603,6 +2765,7 @@ ${item.displayPath}${name}\ ty: TY_GENERIC, path: null, generics, + bindings, }; } if (pathIndex === 0) { @@ -2612,6 +2775,7 @@ ${item.displayPath}${name}\ ty: null, path: null, generics, + bindings, }; } const item = lowercasePaths[pathIndex - 1]; @@ -2620,6 +2784,7 @@ ${item.displayPath}${name}\ ty: item.ty, path: item.path, generics, + bindings, }; } @@ -2766,7 +2931,7 @@ ${item.displayPath}${name}\ // https://mathiasbynens.be/notes/shapes-ics const crateRow = { crate: crate, - ty: 1, // == ExternCrate + ty: 3, // == ExternCrate name: crate, path: "", desc: crateCorpus.doc, @@ -3031,7 +3196,8 @@ ${item.displayPath}${name}\ // popping a state (Firefox), which is why search() is // called both here and at the end of the startSearch() // function. - search(e); + e.preventDefault(); + search(); } else { searchState.input.value = ""; // When browsing back from search results the main page @@ -3066,7 +3232,7 @@ ${item.displayPath}${name}\ // before paste back the previous search, you get the old search results without // the filter. To prevent this, we need to remove the previous results. currentResults = null; - search(undefined, true); + search(true); } /** diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 63947789c5419..70a2825265ec1 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -1,6 +1,6 @@ // Local js definitions: /* global getSettingValue, updateLocalStorage, updateTheme */ -/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */ +/* global addClass, removeClass, onEach, onEachLazy, blurHandler */ /* global MAIN_ID, getVar, getSettingsButton */ "use strict"; @@ -232,7 +232,7 @@ const settingsButton = getSettingsButton(); const settingsMenu = document.getElementById("settings"); settingsButton.onclick = event => { - if (elemIsInParent(event.target, settingsMenu)) { + if (settingsMenu.contains(event.target)) { return; } event.preventDefault(); diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index c69641092ab97..37250ba5a1fda 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -51,22 +51,11 @@ function removeClass(elem, className) { * Run a callback for every element of an Array. * @param {Array} arr - The array to iterate over * @param {function(?)} func - The callback - * @param {boolean} [reversed] - Whether to iterate in reverse */ -function onEach(arr, func, reversed) { - if (arr && arr.length > 0) { - if (reversed) { - for (let i = arr.length - 1; i >= 0; --i) { - if (func(arr[i])) { - return true; - } - } - } else { - for (const elem of arr) { - if (func(elem)) { - return true; - } - } +function onEach(arr, func) { + for (const elem of arr) { + if (func(elem)) { + return true; } } return false; @@ -80,14 +69,12 @@ function onEach(arr, func, reversed) { * https://developer.mozilla.org/en-US/docs/Web/API/NodeList * @param {NodeList|HTMLCollection} lazyArray - An array to iterate over * @param {function(?)} func - The callback - * @param {boolean} [reversed] - Whether to iterate in reverse */ // eslint-disable-next-line no-unused-vars -function onEachLazy(lazyArray, func, reversed) { +function onEachLazy(lazyArray, func) { return onEach( Array.prototype.slice.call(lazyArray), - func, - reversed); + func); } function updateLocalStorage(name, value) { diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html index f6d2fa3489081..8db7986fa7506 100644 --- a/src/librustdoc/html/templates/item_union.html +++ b/src/librustdoc/html/templates/item_union.html @@ -4,13 +4,13 @@

    {{ self.document() | safe }} {% if self.fields_iter().peek().is_some() %} -

    {# #} +

    {# #} Fields§ {# #}

    {% for (field, ty) in self.fields_iter() %} {% let name = field.name.expect("union field name") %} {# #} + class="{{ ItemType::StructField +}} section-header"> {# #} § {# #} {{ name }}: {{+ self.print_ty(ty) | safe }} {# #} diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index ebf817673bfef..3f6147bb916fd 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -10,7 +10,6 @@ {# #} {# #} {# #} - {# #} {# #} {# #} diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index b8b7785a2a191..e0516bb42fe40 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -1,4 +1,4 @@ -

    {# #} +

    {# #} Layout§ {# #}

    {# #}
    {# #} @@ -54,7 +54,7 @@

    {# #} Note: Encountered an error during type layout; {#+ #} the type failed to be normalized. {# #}

    {# #} - {% when Err(LayoutError::Cycle) %} + {% when Err(LayoutError::Cycle(_)) %}

    {# #} Note: Encountered an error during type layout; {#+ #} the type's layout depended on the type's layout itself. {# #} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 285923251f73f..61376ab31dd28 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -250,15 +250,16 @@ pub(crate) fn id_from_item_inner( // their parent module, which isn't present in the output JSON items. So // instead, we directly get the primitive symbol and convert it to u32 to // generate the ID. - if matches!(tcx.def_kind(def_id), DefKind::Mod) && - let Some(prim) = tcx.get_attrs(*def_id, sym::rustc_doc_primitive) - .find_map(|attr| attr.value_str()) { + if matches!(tcx.def_kind(def_id), DefKind::Mod) + && let Some(prim) = tcx + .get_attrs(*def_id, sym::rustc_doc_primitive) + .find_map(|attr| attr.value_str()) + { format!(":{}", prim.as_u32()) } else { - tcx - .opt_item_name(*def_id) - .map(|n| format!(":{}", n.as_u32())) - .unwrap_or_default() + tcx.opt_item_name(*def_id) + .map(|n| format!(":{}", n.as_u32())) + .unwrap_or_default() } } }; diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 27e8a27ba2f25..c1d90020e87e4 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -80,9 +80,9 @@ impl<'tcx> JsonRenderer<'tcx> { // document primitive items in an arbitrary crate by using // `rustc_doc_primitive`. let mut is_primitive_impl = false; - if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind && - impl_.trait_.is_none() && - let clean::types::Type::Primitive(_) = impl_.for_ + if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind + && impl_.trait_.is_none() + && let clean::types::Type::Primitive(_) = impl_.for_ { is_primitive_impl = true; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index dda06d4c9c1d7..1c02e0ba76ecf 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -53,6 +53,7 @@ extern crate rustc_interface; extern crate rustc_lexer; extern crate rustc_lint; extern crate rustc_lint_defs; +extern crate rustc_log; extern crate rustc_macros; extern crate rustc_metadata; extern crate rustc_middle; @@ -175,7 +176,7 @@ pub fn main() { // in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml). init_logging(&handler); - rustc_driver::init_env_logger(&handler, "RUSTDOC_LOG"); + rustc_driver::init_logger(&handler, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")); let exit_code = rustc_driver::catch_with_exit_code(|| match get_args(&handler) { Some(args) => main_args(&mut handler, &args, using_internal_features), @@ -793,17 +794,10 @@ fn main_args( let config = core::create_config(options, &render_options, using_internal_features); interface::run_compiler(config, |compiler| { - let sess = compiler.session(); + let sess = &compiler.sess; if sess.opts.describe_lints { - let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); - let registered_lints = if let Some(register_lints) = compiler.register_lints() { - register_lints(sess, &mut lint_store); - true - } else { - false - }; - rustc_driver::describe_lints(sess, &lint_store, registered_lints); + rustc_driver::describe_lints(sess); return Ok(()); } diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index d1c4cc1f5952d..21a31b9df9308 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -79,9 +79,9 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - let def_id = item.item_id.expect_def_id().expect_local(); // check if parent is trait impl - if let Some(parent_def_id) = cx.tcx.opt_local_parent(def_id) && - let Some(parent_node) = cx.tcx.hir().find_by_def_id(parent_def_id) && - matches!( + if let Some(parent_def_id) = cx.tcx.opt_local_parent(def_id) + && let Some(parent_node) = cx.tcx.hir().find_by_def_id(parent_def_id) + && matches!( parent_node, hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }), @@ -100,7 +100,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - } let (level, source) = cx.tcx.lint_level_at_node( crate::lint::MISSING_DOC_CODE_EXAMPLES, - cx.tcx.hir().local_def_id_to_hir_id(def_id), + cx.tcx.local_def_id_to_hir_id(def_id), ); level != lint::Level::Allow || matches!(source, LintLevelSource::Default) } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index fcd078858948e..6b536e97c43cf 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -303,7 +303,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { Res::Def(DefKind::Enum, did) => match tcx.type_of(did).instantiate_identity().kind() { ty::Adt(def, _) if def.is_enum() => { if let Some(variant) = def.variants().iter().find(|v| v.name == variant_name) - && let Some(field) = variant.fields.iter().find(|f| f.name == variant_field_name) { + && let Some(field) = + variant.fields.iter().find(|f| f.name == variant_field_name) + { Ok((ty_res, field.did)) } else { Err(UnresolvedPath { @@ -973,7 +975,8 @@ impl LinkCollector<'_, '_> { && let Some(def_id) = item.item_id.as_def_id() && let Some(def_id) = def_id.as_local() && !self.cx.tcx.effective_visibilities(()).is_exported(def_id) - && !has_primitive_or_keyword_docs(&item.attrs.other_attrs) { + && !has_primitive_or_keyword_docs(&item.attrs.other_attrs) + { // Skip link resolution for non-exported items. return; } @@ -1250,9 +1253,10 @@ impl LinkCollector<'_, '_> { // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether. // However I'm not sure how to check that across crates. - if let Some(candidate) = candidates.get(0) && - candidate.0 == Res::Primitive(PrimitiveType::RawPointer) && - key.path_str.contains("::") // We only want to check this if this is an associated item. + if let Some(candidate) = candidates.get(0) + && candidate.0 == Res::Primitive(PrimitiveType::RawPointer) + && key.path_str.contains("::") + // We only want to check this if this is an associated item. { if key.item_id.is_local() && !self.cx.tcx.features().intra_doc_pointers { self.report_rawptr_assoc_feature_gate(diag.dox, &diag.link_range, diag.item); @@ -1318,8 +1322,8 @@ impl LinkCollector<'_, '_> { for other_ns in [TypeNS, ValueNS, MacroNS] { if other_ns != expected_ns { if let Ok(res) = - self.resolve(path_str, other_ns, item_id, module_id) && - !res.is_empty() + self.resolve(path_str, other_ns, item_id, module_id) + && !res.is_empty() { err = ResolutionFailure::WrongNamespace { res: full_res(self.cx.tcx, res[0]), @@ -1892,8 +1896,10 @@ fn resolution_failure( }; let is_struct_variant = |did| { if let ty::Adt(def, _) = tcx.type_of(did).instantiate_identity().kind() - && def.is_enum() - && let Some(variant) = def.variants().iter().find(|v| v.name == res.name(tcx)) { + && def.is_enum() + && let Some(variant) = + def.variants().iter().find(|v| v.name == res.name(tcx)) + { // ctor is `None` if variant is a struct variant.ctor.is_none() } else { @@ -1918,7 +1924,6 @@ fn resolution_failure( Variant | Field | Closure - | Coroutine | AssocTy | AssocConst | AssocFn diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index a57321b5822e4..b6f73d3fdcda2 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -154,9 +154,9 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // scan through included items ahead of time to splice in Deref targets to the "valid" sets for it in new_items_external.iter().chain(new_items_local.iter()) { - if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind && - trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() && - cleaner.keep_impl(for_, true) + if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind + && trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() + && cleaner.keep_impl(for_, true) { let target = items .iter() @@ -198,7 +198,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> cleaner.keep_impl( for_, trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(), - ) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into())) + ) || trait_.as_ref().is_some_and(|t| cleaner.keep_impl_with_def_id(t.def_id().into())) || kind.is_blanket() } else { true @@ -250,8 +250,8 @@ impl<'cache> DocVisitor for ItemAndAliasCollector<'cache> { fn visit_item(&mut self, i: &Item) { self.items.insert(i.item_id); - if let TypeAliasItem(alias) = &*i.kind && - let Some(did) = alias.type_.def_id(self.cache) + if let TypeAliasItem(alias) = &*i.kind + && let Some(did) = alias.type_.def_id(self.cache) { self.items.insert(ItemId::DefId(did)); } diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index ac8a75a4f18c9..e9b9e36a53030 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -98,7 +98,7 @@ fn check_rust_syntax( // Finally build and emit the completed diagnostic. // All points of divergence have been handled earlier so this can be // done the same way whether the span is precise or not. - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(local_id); cx.tcx.struct_span_lint_hir(crate::lint::INVALID_RUST_CODEBLOCKS, hir_id, sp, msg, |lint| { let explanation = if is_ignore { "`ignore` code blocks require valid Rust code for syntax highlighting; \ diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs index 00d15a3ca8d13..4a80c22ed0851 100644 --- a/src/librustdoc/passes/lint/html_tags.rs +++ b/src/librustdoc/passes/lint/html_tags.rs @@ -213,7 +213,9 @@ fn extract_path_backwards(text: &str, end_pos: usize) -> Option { .take_while(|(_, c)| is_id_start(*c) || is_id_continue(*c)) .reduce(|_accum, item| item) .and_then(|(new_pos, c)| is_id_start(c).then_some(new_pos)); - if let Some(new_pos) = new_pos && current_pos != new_pos { + if let Some(new_pos) = new_pos + && current_pos != new_pos + { current_pos = new_pos; continue; } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 0c15bf5f764ff..472781e7d2294 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -87,7 +87,7 @@ fn check_redundant_explicit_link<'md>( let link_data = collect_link_data(&mut offset_iter); if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { - if &link_data.display_link.replace("`", "") != resolvable_link { + if &link_data.display_link.replace('`', "") != resolvable_link { // Skips if display link does not match to actual // resolvable link, usually happens if display link // has several segments, e.g. diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index b35618415943f..df955421ba487 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -208,24 +208,25 @@ impl<'a> DocFolder for ImplStripper<'a, '_> { // Because we don't inline in `maybe_inline_local` if the output format is JSON, // we need to make a special check for JSON output: we want to keep it unless it has // a `#[doc(hidden)]` attribute if the `for_` type is exported. - if let Some(did) = imp.for_.def_id(self.cache) && - !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did) + if let Some(did) = imp.for_.def_id(self.cache) + && !imp.for_.is_assoc_ty() + && !self.should_keep_impl(&i, did) { debug!("ImplStripper: impl item for stripped type; removing"); return None; } - if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) && - !self.should_keep_impl(&i, did) { + if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) + && !self.should_keep_impl(&i, did) + { debug!("ImplStripper: impl item for stripped trait; removing"); return None; } if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { for typaram in generics { - if let Some(did) = typaram.def_id(self.cache) && !self.should_keep_impl(&i, did) + if let Some(did) = typaram.def_id(self.cache) + && !self.should_keep_impl(&i, did) { - debug!( - "ImplStripper: stripped item in trait's generics; removing impl" - ); + debug!("ImplStripper: stripped item in trait's generics; removing impl"); return None; } } diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index dd52deef6724e..14680fdb064f4 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -325,7 +325,7 @@ pub(crate) fn run( // Save output to provided path let mut encoder = FileEncoder::new(options.output_path).map_err(|e| e.to_string())?; calls.encode(&mut encoder); - encoder.finish().map_err(|e| e.to_string())?; + encoder.finish().map_err(|(_path, e)| e.to_string())?; Ok(()) }; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 549fd67e32ad1..bef151745d8f0 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -135,14 +135,16 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // macro in the same module. let mut inserted = FxHashSet::default(); for child in self.cx.tcx.module_children_local(CRATE_DEF_ID) { - if !child.reexport_chain.is_empty() && - let Res::Def(DefKind::Macro(_), def_id) = child.res && - let Some(local_def_id) = def_id.as_local() && - self.cx.tcx.has_attr(def_id, sym::macro_export) && - inserted.insert(def_id) + if !child.reexport_chain.is_empty() + && let Res::Def(DefKind::Macro(_), def_id) = child.res + && let Some(local_def_id) = def_id.as_local() + && self.cx.tcx.has_attr(def_id, sym::macro_export) + && inserted.insert(def_id) { let item = self.cx.tcx.hir().expect_item(local_def_id); - top_level_module.items.insert((local_def_id, Some(item.ident.name)), (item, None, None)); + top_level_module + .items + .insert((local_def_id, Some(item.ident.name)), (item, None, None)); } } @@ -240,7 +242,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; let document_hidden = self.cx.render_options.document_hidden; - let use_attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id)); + let use_attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id)); // Don't inline `doc(hidden)` imports so they can be stripped at a later stage. let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline) || (document_hidden && use_attrs.lists(sym::doc).has_word(sym::hidden)); @@ -444,8 +446,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { continue; } - let attrs = - tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(item.owner_id.def_id)); + let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(item.owner_id.def_id)); // If there was a private module in the current path then don't bother inlining // anything as it will probably be stripped anyway. diff --git a/src/llvm-project b/src/llvm-project index fef3d7b14ede4..7738295178045 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit fef3d7b14ede45d051dc688aae0bb8c8b02a0566 +Subproject commit 7738295178045041669876bf32b0543ec8319a5c diff --git a/src/stage0.json b/src/stage0.json index 32dc8a2f83c6c..5625e7219f82c 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -4,6 +4,7 @@ "artifacts_server": "https://ci-artifacts.rust-lang.org/rustc-builds", "artifacts_with_llvm_assertions_server": "https://ci-artifacts.rust-lang.org/rustc-builds-alt", "git_merge_commit_email": "bors@rust-lang.org", + "git_repository": "rust-lang/rust", "nightly_branch": "master" }, "__comments": [ @@ -17,385 +18,425 @@ "tool is executed." ], "compiler": { - "date": "2023-10-04", + "date": "2023-11-13", "version": "beta" }, "rustfmt": { - "date": "2023-10-04", + "date": "2023-11-13", "version": "nightly" }, "checksums_sha256": { - "dist/2023-10-04/cargo-beta-aarch64-apple-darwin.tar.gz": "a684803e2f7a6c5741b89d3cc471544978ca60256e1d9621978eb190c83e6e2a", - "dist/2023-10-04/cargo-beta-aarch64-apple-darwin.tar.xz": "f6b618c037bf5eb84e7e775fb646f1fd37fc175c321faab0c2a5b39eb4553729", - "dist/2023-10-04/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "47178d02b0d92eb0a1ce511a08ced08c5bf21571d2e560d64d7d00f9d7dc8d76", - "dist/2023-10-04/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "4580c08291405a349c384e34f5ccc728956ff169b7c86c528dbb1e4258a08a77", - "dist/2023-10-04/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "31ca3f2a4d11cdae30925f22154d833e1975b622dbc9bfeb73888fa8666d07f0", - "dist/2023-10-04/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "525dc3440d5bc10c29476e5dcf26c82887459b37fa4adb6f0c45d6f955a9b8e0", - "dist/2023-10-04/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "fac19194eb9261b0df166bccc757d77b78f12c015faf4fd02440978a835ac5b4", - "dist/2023-10-04/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "97e9e2970306e3148307f0a90720764bc74a9e161fe9efe09fb3919a6624e22f", - "dist/2023-10-04/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "805d20b6d572cf1fcfa9f036c9af7133284edf5b67c9ac2e635aaf4eae2d07a5", - "dist/2023-10-04/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "b482d11edee594d984c4da214a0d6dd3dd5538eabe6c6a04b8b36ad4d6918b9d", - "dist/2023-10-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "f052ee2d6b5f09d63cc43acbc3e13f044d39bc8cd411286b1fd0318802689e3f", - "dist/2023-10-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "3a428c893b46f7ef5e893438b48225d633190e2c99e475429a08556e16ed993e", - "dist/2023-10-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "cfdf1f990b6bdd43ad0e0b898065637ab422c4ca4489b78f0ed481684bd4c9a4", - "dist/2023-10-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "93239e235a34898e959d891f8d70a75e012f35af62f5576d1b2173fce8979d30", - "dist/2023-10-04/cargo-beta-i686-pc-windows-gnu.tar.gz": "a27be9e3c589d8d92a9b4d95fc6684d4f05951f985485cc516359ea600cb9b4d", - "dist/2023-10-04/cargo-beta-i686-pc-windows-gnu.tar.xz": "9339b0ee5395f75ee8ebfeaeb95582e5922e0f3fc268f59d47c2cc110844f269", - "dist/2023-10-04/cargo-beta-i686-pc-windows-msvc.tar.gz": "6bf3edf4612263ed698bb920e946065e964cd4f7fa6e864b029b8593997b1a0e", - "dist/2023-10-04/cargo-beta-i686-pc-windows-msvc.tar.xz": "46cd39b56d8a6d4724a99574907ddb81a6d170ceccca35a9201b8a61bd3e8190", - "dist/2023-10-04/cargo-beta-i686-unknown-linux-gnu.tar.gz": "f99efe464f62d1c11c035c8ee0fe649380522c8fce7273218ff8a818bbc1628d", - "dist/2023-10-04/cargo-beta-i686-unknown-linux-gnu.tar.xz": "32f68b074e6b9ca7bd216d8d924d0b796c3a6ba81b90d8a0ecbd1904a61867c2", - "dist/2023-10-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "d1b0179d8c8ab0541bfaf7830bafc0d384616785081c0149ebb80d009860261c", - "dist/2023-10-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "1265182fc1962018c2754359acbc7b7d07860bdd26eb388c8e332786fbbd678a", - "dist/2023-10-04/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "500f736aeea0a5648bd4703b772d9d9077272daf08c334c281d71f9c19150e1d", - "dist/2023-10-04/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "97e40806dfd8921b7c4347d2d6ebadb66dd315c3d30c0ba3e0b30fcc3de9f1d4", - "dist/2023-10-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "1bf735bbae45eb55f4156504299d41c169d3d923ca8615e333e181a0e4b744c4", - "dist/2023-10-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "2ab0afd75f20e290fac1063ac0ac8cec98f847918360d95326350671d3b0e05d", - "dist/2023-10-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "9092667b450f758c39420530a131e87bcf6c911cb3f2b0177ec6fa4dfb7e58fe", - "dist/2023-10-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "50417b4be7631069b8059df56f0834fc65951c5057124b681b7a97a00ff774b6", - "dist/2023-10-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "cfb8e229f98f43a612bbf0d6d29f42cbfe2ccae4e3ef03fbb0bd7ea4ced10154", - "dist/2023-10-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "32059ff422870f3d45f419f7a59de696fff9474aac1bc4ae20a527079b95cf86", - "dist/2023-10-04/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "d14942f7492df24a577464a2929c2251c1493a70d822b7c38b500e559fce18e8", - "dist/2023-10-04/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "f7688d17e33d49f6fe26a0e7d0d24dfa6fa99e3b1703f6b99dddca46f1080c89", - "dist/2023-10-04/cargo-beta-x86_64-apple-darwin.tar.gz": "9da00b7617cf14e3f5f32c6cfc8e0f4b4197747a6864a962dbaa8725279b52a4", - "dist/2023-10-04/cargo-beta-x86_64-apple-darwin.tar.xz": "a3735ff5fd823461eb411d11b1e675fa890907c859e353ec9c239fc85bc5df1e", - "dist/2023-10-04/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "9f98eb4b034acf6ee9315a7067a62668883d25fd95b306c3083feeb56b907ac5", - "dist/2023-10-04/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "93d0653eae1839dda931ba4e26afb32527a59ca3b4502778135cc5d9608bfeb6", - "dist/2023-10-04/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "23f8e3f8abb551e7c71b391b63d5a9514f49e03d89c0bf4877c94bfd9f1f3754", - "dist/2023-10-04/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "1e8c3996be4a94b54df4f1d5d5f514f254963ed479e40885cc943970d9c31ebb", - "dist/2023-10-04/cargo-beta-x86_64-unknown-freebsd.tar.gz": "3761bb7b4fb64fa4791d09b88fac9da690a422d611935f1627ea96dd43b1d229", - "dist/2023-10-04/cargo-beta-x86_64-unknown-freebsd.tar.xz": "d0a2bac9df9073f766ca0ac2a16b17b6ebf870913ca962c063e6cc9967a32ab8", - "dist/2023-10-04/cargo-beta-x86_64-unknown-illumos.tar.gz": "71d42631ac9867750c5ef86061b2ce6ac1fa56dc24eb07fe5fb13a97e2acffa1", - "dist/2023-10-04/cargo-beta-x86_64-unknown-illumos.tar.xz": "72002ff2f148fdd864fbd4a82ec4fe7fb33c6acf7a7186e30ee4a74759f593f9", - "dist/2023-10-04/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "774be8387ae3849a82447cc20b2bd1daf4d42c7a80faaf5090e153f78d96de9f", - "dist/2023-10-04/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "6f6794bf506362614b97d96f10d6d5171676205beedb655636d82e8344a47011", - "dist/2023-10-04/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "c5ef0aa9f422014bf4d1873f09c77818d2de51fd7d6c030b617cd106402a0f21", - "dist/2023-10-04/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "82ece6a6f7eff45d842ba1cd28e3e86ddac0c49fedca3039dac00d01d99a26e7", - "dist/2023-10-04/cargo-beta-x86_64-unknown-netbsd.tar.gz": "42627d918e4dbb692ef45ff162d7eb39e9126dc30f29cb96b787f0029d11e1d2", - "dist/2023-10-04/cargo-beta-x86_64-unknown-netbsd.tar.xz": "de92a4f9f58e728c63d47a39973c2ef396a073a6fa26bdadf0e833cee9722980", - "dist/2023-10-04/rust-std-beta-aarch64-apple-darwin.tar.gz": "150828b9c7e49d7555eaf989dd6fe84b2b30d06145f48b635ad04e893b537311", - "dist/2023-10-04/rust-std-beta-aarch64-apple-darwin.tar.xz": "c1006b9c0c7d0bf104146b52c92f004811988cc8b73474ef690208e78645a348", - "dist/2023-10-04/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "df8cd652323cdf204683789b902f440e8aa614b9950e096837bc3b6a32a58e80", - "dist/2023-10-04/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "f9bdde6063001b69002ad21777eb52b37ce78ea3ce04131cf81b8f40b0e16c84", - "dist/2023-10-04/rust-std-beta-aarch64-apple-ios.tar.gz": "db0362e805a012249fae465b205970035181a43a19a58d87dd475ebdbb986dc2", - "dist/2023-10-04/rust-std-beta-aarch64-apple-ios.tar.xz": "72fd22f528bb211b0d5ac807f590fac72b1698f7d118e1b3507e6994b3896cb0", - "dist/2023-10-04/rust-std-beta-aarch64-linux-android.tar.gz": "f691fd6cf51e9aad3a11c2b613646b06308ef9558fe04f274458b68a742d6efe", - "dist/2023-10-04/rust-std-beta-aarch64-linux-android.tar.xz": "65fc6a17622bcf0039b34699537f233d193b03514c039258395dff2de8ca5197", - "dist/2023-10-04/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "a99e89663dc6ade963dc13b468fc310ad7b8a17e4d417bc210a39feb6413422c", - "dist/2023-10-04/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "120579d0abbd68b692271290ae926f6677f97930ade6861ae71be0033db5437b", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "7663940abb0a080daac14573199e81b3000d80a27dcfd8f3d8c6d295efa1216a", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "59d7eef17b6cc40cf6af729abf173ecc43c03bf38516bf59fe27321db384972d", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "69647628d78604fdbdb830d23f661d31f997d77635ea0c123d1ca0017b18460d", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "93e15186a1ddd33f3cd7737ff5da28bccfd5644c9a579691611ee2e1308cdd4d", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "b8ac97fef649854f78a9290054728f40b90e5ce55dcde7cdd128e2a5a09224f0", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "4b0d7b2bf742425ddf024d7103b8651f662993038f66b9db915713ba8f039540", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "37847cacdcf142fc557bafcfd8b3ed3c9c5532757bf6c06e6493d21356e18f04", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "c64925fcbd6b7f97926fac45d789e70734d3895c46cc958c190815f8cd8f4989", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-none.tar.gz": "a566b9c1784c919317f33678f889a15107fd31a403d50f6cf42036ff14ae507f", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-none.tar.xz": "a1267921d98e56f36937e72a1dcd60624f94de6e9948fd86715f83fb152ff52b", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-uefi.tar.gz": "0fd6a5925d5a69ae7c7f277ab503ddeeef9168ea815492b21a77a07d8e49142e", - "dist/2023-10-04/rust-std-beta-aarch64-unknown-uefi.tar.xz": "8477f0f15e1fd594b05e918f1940ee56a9458353eaac83f355d935ff2971df20", - "dist/2023-10-04/rust-std-beta-arm-linux-androideabi.tar.gz": "63ea0d1311b4c7a10a185dad0f13e53cac6f7de0047b96e6f23f872f84243339", - "dist/2023-10-04/rust-std-beta-arm-linux-androideabi.tar.xz": "9b35c8013417cdd08480640c609c3e0384814944b81e6f85f8741f53a768c944", - "dist/2023-10-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "290589b2438e6ef92366d86916d33f19504dbbe7adeb3e8b12786e524080fee2", - "dist/2023-10-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "ce39b799f490f0f7c8d166177d6a4174641872d2fbbd80d7d94dadfc1603b77e", - "dist/2023-10-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "5def5470a2c06adb70ab6373b35abdb2404987a41ea2b324d8852849540ed503", - "dist/2023-10-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "dfa329c8da739dab40cd111d9399ae2e38e7db8f8e07fda64117fa146b3d071c", - "dist/2023-10-04/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "94cbc1d6984b6018c373f5e7fd250f0bd2de4b4767f7f0c61a70c660576faf12", - "dist/2023-10-04/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "ec393c418b2ac3d2c97814b712648a0fd318dcdec381b4a49409dbb59079cb33", - "dist/2023-10-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "4765d35d61d4bb0a8d7dd9f2e6e1b17a9c27ac27fe24f111a42aca6b2dfe2fcf", - "dist/2023-10-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "07ee14b28ceec5e76f411b607d68cccb3bac17ed708e180081837f2e05c7057e", - "dist/2023-10-04/rust-std-beta-armebv7r-none-eabi.tar.gz": "f5f35b007304d6d25a189f000a89a64cebad035e3ab7d2f1d2225c7063575db8", - "dist/2023-10-04/rust-std-beta-armebv7r-none-eabi.tar.xz": "68ede435cb805a0e7d9c3bf172fda8c20486dcb2ab655cabc5ecfa25f8564955", - "dist/2023-10-04/rust-std-beta-armebv7r-none-eabihf.tar.gz": "53f1586ef3640a35e36d2b3b4caf62e444d43da64d744d99323f9b238fd0981d", - "dist/2023-10-04/rust-std-beta-armebv7r-none-eabihf.tar.xz": "404517420148caad58da5c5903d6b64b00aaef728dc9146f1c85d3675b2f7944", - "dist/2023-10-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "333a58268238a43864b65f51d5731c76e43f56f6f7c556057307d36d1c47bfd2", - "dist/2023-10-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "fe4ac5283e9025f7ec919d324592a3b88cf8ed02bfb6bd077d46a452af1fd723", - "dist/2023-10-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "ce2edf3faf28d92d2ecace77207e0a5b68aacbaf0f202e79503fabf913472f17", - "dist/2023-10-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "12df2bab8ce8301e3dc6eca8693b19eafe31894c285c013bc4445596cc93e49a", - "dist/2023-10-04/rust-std-beta-armv7-linux-androideabi.tar.gz": "f15088dd162f584123f07d58303e5aef3ed12a479ad6e351ad9c676c9d7953e1", - "dist/2023-10-04/rust-std-beta-armv7-linux-androideabi.tar.xz": "8ac08cc08e29b8aa4425889b5ed7f309ab98a3af51c66f2a40c5a5c62efbef97", - "dist/2023-10-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "d4b8fbf3b3d96e893145aa2868f6a470ad70bd946793fc49c435eb6fc921a00e", - "dist/2023-10-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "153c726bc061d8cd01f5c6c1786d12d04e699505a927ad5ee0e385ee1ea9ded7", - "dist/2023-10-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "4dfe33527e1c54cd0a9ff653e6c81376a01119bd894f5db47fb7c716464fc876", - "dist/2023-10-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "42081a3129ffd33ff6d9bbc10a10f214f909b4700255fa57decf82161e095d85", - "dist/2023-10-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "c1693a1887633f4c0baef1bb9910c502df5a70f2deaf00ead2a40d7ad210216a", - "dist/2023-10-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "a1f0068e719d231a6c1ec12055b883773584d9fba609f01fdc32a0dc856bd516", - "dist/2023-10-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "7568f5a3e65a649f13481afe384cccf54789c99fe74e62365b4922e649a36f2a", - "dist/2023-10-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "ad2989860396bc23ca4337887cd9865fa8a4e930d648df50f193330011f2e65e", - "dist/2023-10-04/rust-std-beta-armv7a-none-eabi.tar.gz": "0ed22040479e23cbf3e82087636c6ea30d75139af30db9e95b8ea7847be1184a", - "dist/2023-10-04/rust-std-beta-armv7a-none-eabi.tar.xz": "d182765ec6d63e0fbf2c6af1ecf57c475dda93c03676e8f3958da74aa47fa168", - "dist/2023-10-04/rust-std-beta-armv7r-none-eabi.tar.gz": "cdc524d00fbafccc363b456c32cc6410cefe98d9c1d37c1e5a22db986b600e7d", - "dist/2023-10-04/rust-std-beta-armv7r-none-eabi.tar.xz": "8815ae220f5bf7bced09274a1e17dd0f95e81ef5cbe1938b738298835c47001b", - "dist/2023-10-04/rust-std-beta-armv7r-none-eabihf.tar.gz": "c641416a3d67ca2a9b797d4800e5ac12a688a7af9daaeae10465c13d0f8cdeba", - "dist/2023-10-04/rust-std-beta-armv7r-none-eabihf.tar.xz": "3ce3dde8809d41f51534d9e8fd86f1c5f34b5450a2bdfffdc2d72e9e54af6ef0", - "dist/2023-10-04/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "a3700f29bbf1f7508a438ef7ecf4cfa25acef21bc9205285736f34840932388d", - "dist/2023-10-04/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "7a6927e77caad52d111366712697b3a7e6b3fa904e0a50eb4628b70d5a92717b", - "dist/2023-10-04/rust-std-beta-i586-pc-windows-msvc.tar.gz": "97c5d4837a4e4f019293c4dce265f6d09ddf3abdc7d7ab7f08ce0b62e0278b2c", - "dist/2023-10-04/rust-std-beta-i586-pc-windows-msvc.tar.xz": "f566a6b8083d3a1e0f5cff28a5131af4bce33a1519d7a7e6fb14d7ae349e3150", - "dist/2023-10-04/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "7a344a573529887631387d8e2f3e007653216f959a8f7c543e2c2cfb52673615", - "dist/2023-10-04/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "d6543b8eb696596fd35616fdc839af08f9a386412e7a8344ed92e08d840613cf", - "dist/2023-10-04/rust-std-beta-i586-unknown-linux-musl.tar.gz": "e8790ee297ef2661d8cead7875d3fa511d7ec4be5aac858562ddc107257648d7", - "dist/2023-10-04/rust-std-beta-i586-unknown-linux-musl.tar.xz": "8998fc7c0d7ecb5a06fae1799f2aa044cf3680546461ec9033115476f3acd2db", - "dist/2023-10-04/rust-std-beta-i686-linux-android.tar.gz": "f918380c6e01128fb16a047d6adc7a8fd3cb3c14bd18d25690ebc69c9a8f0f22", - "dist/2023-10-04/rust-std-beta-i686-linux-android.tar.xz": "cafedd439975af0f45894e111b89b03adee21136dd43558cb049608914b0a8fb", - "dist/2023-10-04/rust-std-beta-i686-pc-windows-gnu.tar.gz": "442d40afabdd05fbbe8b8570133dc119da6c6f8396a1cd6879a21b58c570dbbd", - "dist/2023-10-04/rust-std-beta-i686-pc-windows-gnu.tar.xz": "31c86d09c30d670a4915412d3fed90e0bc640f6b359ddb88ecc4c75f50b68b41", - "dist/2023-10-04/rust-std-beta-i686-pc-windows-msvc.tar.gz": "e0b23dd8a1a4805a1d13275e29edef5b5cfd34b271029262b943eda877c074c5", - "dist/2023-10-04/rust-std-beta-i686-pc-windows-msvc.tar.xz": "a954096bc423910cda8816093bcff11a3996d55239c19c3f9285f584057fdcde", - "dist/2023-10-04/rust-std-beta-i686-unknown-freebsd.tar.gz": "84c060e799148378223c56742d9bfef40b15252204f91bd49677083f48fff722", - "dist/2023-10-04/rust-std-beta-i686-unknown-freebsd.tar.xz": "faa471809786a5cef68807de3da9c0c9e0943b7f92014e232ab6693e1b081a9f", - "dist/2023-10-04/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "43ce123cd3f014b33444c853dc91a9921ba9af0b8d52e65c56386b7e300fa595", - "dist/2023-10-04/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "4792bc927d4dc0af996a47c4e82ab37244d0d28052b56abef6dfda60d8e58ac4", - "dist/2023-10-04/rust-std-beta-i686-unknown-linux-musl.tar.gz": "e609884e147deaa8265cd3f9150384d45d43689ba68cfe6e2ca003773d4f31f3", - "dist/2023-10-04/rust-std-beta-i686-unknown-linux-musl.tar.xz": "c27b005cc23453bc2ec9401515fc792d589619119f8f1006d8c9444f1592c1a7", - "dist/2023-10-04/rust-std-beta-i686-unknown-uefi.tar.gz": "e4fb77aefbc3ae63b81019eacfd35b6cee6f801ac2ff397a598d2ddaf84989dc", - "dist/2023-10-04/rust-std-beta-i686-unknown-uefi.tar.xz": "890d607b35053df912d0f3925f8c7af17ef3a66c267f31eadb8aada9b4491b3d", - "dist/2023-10-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "c07d08b9a17aebf127d01715259f5be3fc8e67d1e4a114a5f7eb9489c36ec529", - "dist/2023-10-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "27bffe29093dc3ad55cce741607a354035c8a2d40f8480b131c9608fbd9a86d9", - "dist/2023-10-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "ce7ebda42e41ad68924f2194c1dbb17f2487d2d6426669835e8dca3dc3f0f623", - "dist/2023-10-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "3564c11a5540b25f6c3ef24f47e64bf88d76aefacab01e0b28b0a48e4c0e9d73", - "dist/2023-10-04/rust-std-beta-loongarch64-unknown-none.tar.gz": "2aa6dfa17a120b2ef4e7899ed32a04e472725404b205739c12bff1829c05c7a9", - "dist/2023-10-04/rust-std-beta-loongarch64-unknown-none.tar.xz": "37cd947a8cc912e9c3fe07fd4b3ed310255cb45321ac48753cb8cbeee8b56fd4", - "dist/2023-10-04/rust-std-beta-mips-unknown-linux-musl.tar.gz": "5dc9a8b4a421a1be0fd4aff1256d98d76aa13ec38b10b0ba7fbb7ae7d0633354", - "dist/2023-10-04/rust-std-beta-mips-unknown-linux-musl.tar.xz": "c4762f98a836bd93c68fbac17c99e443bd05cae9897f3d1d3f6f39388659bfff", - "dist/2023-10-04/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "b1cb089447954c3a9d5244e2f08367db5fbd569eb986dc437cfa70f0dc5a9a6b", - "dist/2023-10-04/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "9d245bcfd07a430725c274504f5c8f80ea71027ca63f4442cdf4e950bb49683a", - "dist/2023-10-04/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "4bc42a59bb123188ea2cf143b169b5c5c25b1c10e6b9aaaa00fd5292e2cb4e1c", - "dist/2023-10-04/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "d58b61471e5bf9279b31b6dd15970efac0a7efef95478d46504bb79643641edf", - "dist/2023-10-04/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "d7982143a43ae7d2de013747558b808cdf5acf146eaadd32ee1f5baf3354b7dd", - "dist/2023-10-04/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "e48fd58c266991b24012eccf24212bcaa9f2ca76b93cae50b3b48efdb1c3b715", - "dist/2023-10-04/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "918d45e2212b240c975986d6db96b92bba1f51b2d66ec265c3b87dfd338bc548", - "dist/2023-10-04/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "311aed63bdb7316627a362a9606cd5ca680c4f77bbb9abc74998fea09e2b057b", - "dist/2023-10-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "6787ea0c089880a7fdbddb8565847597c4a25a19cc54fa7186e0468a377ee75e", - "dist/2023-10-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "20b812085cbf0b92cb0b0ac16cf6f3ef21a2b8d43e4185f4170850138361c944", - "dist/2023-10-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "41067f3710f1727c5e2410731f15cc72e15633921bc13295bb28096aae9feaae", - "dist/2023-10-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "8e771dcb137daf00ed15bf4d33418bc238da1f7352fc2ba3dee941e3af3635a2", - "dist/2023-10-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "bd69748bc81f972fb41d1ac5816cab38d810619692e9b2b762bdc346f2c84771", - "dist/2023-10-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "90d79aa923e15aee4e9aaed6721db1288712f473263cff3780dc66d7d7cf7b57", - "dist/2023-10-04/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "a1396acdfd52c857969db1ed6dbb3c29cf76f9744e39ee86eda25f7c3b6fb140", - "dist/2023-10-04/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "93fd04c8c70b30dae02c690c1326edf00090b5f22332dcecbfb0130b4288e795", - "dist/2023-10-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "a0592ab2d956ed79049548010c21d1043306502df200873ee0ab82185699da8d", - "dist/2023-10-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "a304cff2944d1c317940851980a55033f1918c8d4dd52636bc20fb93c0131927", - "dist/2023-10-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "46adfdd25bdcd3c8a9fd60cba9cb1c699b49a5c77b4e4d5aa1020c0985f7c6b2", - "dist/2023-10-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "c78bf8bc612d14ae2d619aeeba6ce10031113793bdce9ee2554d17fea74cf5ca", - "dist/2023-10-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "018d34e11a065100d45b7c529a3de5ddc5912affb74e4978bede24b6995bd394", - "dist/2023-10-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "d3d9062f44c575705ebe2a6d1f176a79fb6f0baf7095cd620184cfe69ff57ab7", - "dist/2023-10-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "a3edcf33b7241e9e06466c24c6325a1c7b7f2c0ef2107042827154480532ea05", - "dist/2023-10-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "d34eabbd010d9c30fb5c07d3bc854d13d629270a679d033a10d5359a3cf14423", - "dist/2023-10-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "1efd3a8cc38d94fec1b2f69fc286a5eb25b50eddf8bf2ded9d236456dc8af4f0", - "dist/2023-10-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "df58f0a2d80a6580c1f39d8dc59e785d624730a265c107dc35b264f20a6cbb75", - "dist/2023-10-04/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "d139f332dd3a40dae7689a673fc66997f318d690eb0a2b0704344fc2f5c3ed2a", - "dist/2023-10-04/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "fd46fd9ffd848d00ebf11002c40698b443c9ee9e056d342c8ebb28ce9f397d08", - "dist/2023-10-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "fd681ec7011de04cf347465594a65fef58882f298e527f22461fb9afc05d353e", - "dist/2023-10-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "5400c302976234fb4b952b7fa159ab2ec5fd19c8c7657b41dd7bcf925b59e769", - "dist/2023-10-04/rust-std-beta-sparcv9-sun-solaris.tar.gz": "93208b2ba15339c0d95434bb04e37ec98fc8a13ef9f92cf92fe0ea55b69e15fa", - "dist/2023-10-04/rust-std-beta-sparcv9-sun-solaris.tar.xz": "3a96871a781637bd885b374a30460196eb9cd064d31b269909c155537085e4e2", - "dist/2023-10-04/rust-std-beta-thumbv6m-none-eabi.tar.gz": "2367449493235e192851f8f7f891be6a4c6fa7663fceb04fa6d160380190159f", - "dist/2023-10-04/rust-std-beta-thumbv6m-none-eabi.tar.xz": "71592f9e4cb8f25ba7034fb797b1fb1cdd3cb9d44d12a8dcc0d450e125e89cd0", - "dist/2023-10-04/rust-std-beta-thumbv7em-none-eabi.tar.gz": "53bc65c17358c3645003068b0d9f231e543f7229e6c389b78aa95d32ded4eecc", - "dist/2023-10-04/rust-std-beta-thumbv7em-none-eabi.tar.xz": "0325e27cdfa9d1adcdf6be09515c3b71f8700a06c87579d314a56dd92ecdd82b", - "dist/2023-10-04/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "0810093364e500892abfc716e9ea44c51bb4f3e0d554fb6a5ccc5aa51bbe003a", - "dist/2023-10-04/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "21d2b3ec401dece48893c011e791c04f1233c9f579762ce6ed8ec665aa1747d2", - "dist/2023-10-04/rust-std-beta-thumbv7m-none-eabi.tar.gz": "76912f5ccc8582048be7a8e4800e2068fc395c85a28ba99f7ffd103f4a8cf98e", - "dist/2023-10-04/rust-std-beta-thumbv7m-none-eabi.tar.xz": "85282a5e52b22501b1aa805da1bb41805591d2a9c4aaabf62a2fc2096469dac2", - "dist/2023-10-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "0e0ec736578012bb05f6f4c3a2156af0255097d74a31586390d4ba9a64d73021", - "dist/2023-10-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "fbf578e9ed1903a14f10231d1d149b9efe701f9fb7ffe96231dfebab6e2de123", - "dist/2023-10-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "8f25cce159bc95b8e4678840fc9c0c4d0f6be50c70c54afc8324756e92da0e03", - "dist/2023-10-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "72226d027daef70c7b6dc7cacf2cb118e99cf4fa5c9cb7affe2214ae79eff6ac", - "dist/2023-10-04/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "5101557cafc2ae9c7acd05f62259618835bb852802863a268784bcc091fca31d", - "dist/2023-10-04/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "f68fd847bea42413ed67d9160926e25174e9e45037d7bca016d86bcceb40c779", - "dist/2023-10-04/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "abcd1dd5293ff16d4ccebfccbd2ef9954389554eacfa7d80c64a67e1bb550c83", - "dist/2023-10-04/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "24ef9d6f0a7f43c22ece67c6ea52a7df1a704e386d867d8f563f9ab0b1f4fbe6", - "dist/2023-10-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "ad415b127acce0ab1ece6b21d12b3bde7b98b0185c8bff9cdad967430081eacb", - "dist/2023-10-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "69be4cf95dcf1ca7d2de6f9ce6580a9a30d033839d3629d371b640325fb7a852", - "dist/2023-10-04/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "9d04e4d8314594175458d1cd8ee1fa93e0289fa0b94ab3280224d4b5bcb4ebae", - "dist/2023-10-04/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "cd4292ce22cdc5553e28ad53ed130408de0c7f1f5af0ad2d1e8c06fd74aa3de8", - "dist/2023-10-04/rust-std-beta-wasm32-unknown-unknown.tar.gz": "a7d5382ac87dca13292b816164aae7ecd5b1221d672f2c03b7d236937ab66e3b", - "dist/2023-10-04/rust-std-beta-wasm32-unknown-unknown.tar.xz": "4f165c1f17ebc81875d6d310619c880581a5bfbaeecfa89743f9771894046214", - "dist/2023-10-04/rust-std-beta-wasm32-wasi-preview1-threads.tar.gz": "4ce6dcb79a483cc1c298d19386fe3782429371c7d3a6bfa4f614cceed8f5dc5e", - "dist/2023-10-04/rust-std-beta-wasm32-wasi-preview1-threads.tar.xz": "2b98636f16a3b988ee27cae0915906593e34d4a6475b37370ca541d53aff1ff3", - "dist/2023-10-04/rust-std-beta-wasm32-wasi.tar.gz": "02b684cc228945097c7ba2340fe7c6ca37ad01ad2c4385b70f0c49aa8d6fcc07", - "dist/2023-10-04/rust-std-beta-wasm32-wasi.tar.xz": "68addf98d1fa241ebe10fc9c3d4fdc00f694c5c603dacd6f306cac07802043bb", - "dist/2023-10-04/rust-std-beta-x86_64-apple-darwin.tar.gz": "f49920ef48466960edf9f21bb7c5374bd9edbbc8c5f6c47eb068e5081e3adaf7", - "dist/2023-10-04/rust-std-beta-x86_64-apple-darwin.tar.xz": "b20cffe93d14408618e149c922114061aedadcdb59e65c72bbbb06e378381ac7", - "dist/2023-10-04/rust-std-beta-x86_64-apple-ios.tar.gz": "22cb46613453e6c5a6cffcda03d7a0337b978b64209afec29d4132b121a7b13d", - "dist/2023-10-04/rust-std-beta-x86_64-apple-ios.tar.xz": "bc65c441d62c0d3fe2432a265cacc8f5e871ee9e894b5572f2e1511c4398c173", - "dist/2023-10-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "18c6e2495d8be9598e515229e4ea683c1ea2866f9a299dde52ebfbb3d0e1df4d", - "dist/2023-10-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "b9f57cd15a15701e0dc77c4b7de1f02444318a338bc176abd7737219746c840e", - "dist/2023-10-04/rust-std-beta-x86_64-linux-android.tar.gz": "b7299cf0a98d7eb7a28ecd57fbdc4fdc8bc6cde32cdaab27e9c5b4e323647908", - "dist/2023-10-04/rust-std-beta-x86_64-linux-android.tar.xz": "ff3190da0a9f11e43bd53b795bea384481026c5d426ac91768e0818a4c35c0ca", - "dist/2023-10-04/rust-std-beta-x86_64-pc-solaris.tar.gz": "2e602b85e49de5efbcc425c33c64bb85dd40cd7fe7b740a8e2953aa193bc4884", - "dist/2023-10-04/rust-std-beta-x86_64-pc-solaris.tar.xz": "e3120a09217977bd0fca8c10909319f1d5b2cf1c3a14d1a0bfa894a25c1dd30d", - "dist/2023-10-04/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "84508811863e1da5bb903fdbc1fe8335e15455469f58f243052b1d8e3885f3d1", - "dist/2023-10-04/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "105de75121b217dafb5b3432bbfcaee0432fc84d17bbfe0d8f6d27a7c9e3ad6c", - "dist/2023-10-04/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "559f9d676c36a236131a73776879103f68b7782ecfbacb7207bc443de44457e7", - "dist/2023-10-04/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "7baa8e4a543211d2235965d681f6d92127f2adc0a51c25d2fbb123715fb512c1", - "dist/2023-10-04/rust-std-beta-x86_64-sun-solaris.tar.gz": "ac20916902c464c9a9ee037b53f90e3b0cd3ec4c7b642deae88dc5f60bf98a8e", - "dist/2023-10-04/rust-std-beta-x86_64-sun-solaris.tar.xz": "c25d29435a43a607ff21204fb109675496229b975fbe879ce88bbb0c290f6cdf", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "8aae13ca12a349bcc0a2eae61543122095266e1fff1e6abd2d53e6f4609574ab", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "c94ec8fc50a4e003b4e4cd3ac3106b9cea0709dcd9d7729f72499744d875fa10", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "e8cf05fa4f01186b6e1810c0e5f8c3f6e5c7efe88cbf2efb6e9d6e4fed2692d9", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "70688ef9098dda4c2c0acb06a4edcf7457ccf5f6ae509edcad89ce1eb9b33fe6", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-illumos.tar.gz": "4ee1f9699c22200beb40523976617b32e097c443bae1201fc64ad3235c8f58ea", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-illumos.tar.xz": "988079564d076c2c49f8eae77069a0636945a980389ae06ed09a90326ddf9f76", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "0897b02e38e01b0c47075c9f2ebe1e8d127193890be499acec84c56e7a04c036", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "746317cab5b1c8676191287077e4a93877c545fbde577c3cc96149aaaec80afb", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "8130a54368f699c26108314690745dc69bcdc572ccedfcb5799728fb902b2ec7", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "c7493f1d747cbd893195a548f23ec9e713694057a15caa86d121fd981cf50ab6", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "6eec43a326e3c26a5f64c0aea25bcef1f890bbd4ec7bdfe9e32ea47641fb5820", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "1bca9c3dafa477ce34e2f58f6625bd3b461ae188468759921db591ec065cd3f6", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "bbb87aabd230f4209df5f63fdb88fb9f7a2f6d0b4e9cd9f9770e2a60881d4442", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "b235872c8041c38321d3e9d9ff3b4fce3ace96493c61af46e47b531bfab0eade", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-none.tar.gz": "d20e50343834f77e39043ab23fe5591bff07bf913bbffcfbc9e618a920fb2043", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-none.tar.xz": "495a4e236f92d2c9ec0ffaee4792e356ee15de447093538f9a34e85c94fd3ddf", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-redox.tar.gz": "de46554c25acc2b3571063da2d63d32337a5c60f71afff96ead0339dedcb7f3d", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-redox.tar.xz": "dea31f24ddd5c5bac73c6bc731f5356232be331fc8cdff80f4fa460266f1f5b5", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-uefi.tar.gz": "7a1f61d37a132fe288652e7679f78c8f36d51a0724102ae39ccf81f0bc9e88bd", - "dist/2023-10-04/rust-std-beta-x86_64-unknown-uefi.tar.xz": "c452f747af508bfa76f27a3ecfdd333c50e9168ced7738fda38ea4e7f1ea904e", - "dist/2023-10-04/rustc-beta-aarch64-apple-darwin.tar.gz": "68aa57ce1a40d955bbc110bbcf1a9a433ef8492d91961658f163eea0f1917de6", - "dist/2023-10-04/rustc-beta-aarch64-apple-darwin.tar.xz": "30063d4818173bd302eecbe204942fc7c7a908a4294cfd3b5670de6a91c5937c", - "dist/2023-10-04/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "e91ae34b35404fd9466b3c4210c4859489b726df6bd1c6b5deda2f54f8243662", - "dist/2023-10-04/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "f5f62ccb98f5340a02ce4ad73cf370692eafb722d89a7dc18d411216dc62d082", - "dist/2023-10-04/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "b9dd02920bcd80f7bf58e5545ec8cfed0763eea657c2903cd21526b6f9ad3891", - "dist/2023-10-04/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "9ac274cd2078ddba5c856e3258862d45b61375f98d326a32505267c4856fa21f", - "dist/2023-10-04/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "ca1accabfd224bcefc1e9726cbb19066e42b3f5eff349c1be837e6adc4b4c63f", - "dist/2023-10-04/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "cd53dd9d96dff348f45ba28ffe68dcdb0fa90b372acc18e3edff9748e0ef6bed", - "dist/2023-10-04/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "3ca0229603110cb4492c2c399da2b57e5084791d8ec84b4cf9557498134362ce", - "dist/2023-10-04/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "f7950c38c09c37a8fb3d521b62185316e85cefcee13ecf6cf86238c03854aec9", - "dist/2023-10-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "332e1f2d816e878bcef183485ededaca830f72265c676af2df92e359df608fcc", - "dist/2023-10-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "0b88d3083b62f3e212bb2c823c7c2f5491eaed0baed99a031220f6ca115d4b17", - "dist/2023-10-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "0b4854c6290e97b4539f55973ccc9f9a4941a07c5b559f94b79490635913cf0f", - "dist/2023-10-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "fac86fc193852246947b648e2c725a4e9973d67a8129e66e9df88a91e7403ffa", - "dist/2023-10-04/rustc-beta-i686-pc-windows-gnu.tar.gz": "1ab3eecffe819ee2b4057a06998fce122931f1989dfab260272fc238f5672592", - "dist/2023-10-04/rustc-beta-i686-pc-windows-gnu.tar.xz": "8af88f78bbe66d35013a9b51606c570ade03c10c3e01115340ac62a99ad28ef8", - "dist/2023-10-04/rustc-beta-i686-pc-windows-msvc.tar.gz": "1d9c70146764cce221cc3e8144395541fc0f3b4af1cc4178342cc6c54e9adb6f", - "dist/2023-10-04/rustc-beta-i686-pc-windows-msvc.tar.xz": "5599aec7ac269dd2a03f5c549a50eca656a309cfe4178e097b64f6357f1d38e5", - "dist/2023-10-04/rustc-beta-i686-unknown-linux-gnu.tar.gz": "7b2b59a9e5acaa56d614c68fbe3b9f0e792f75a32e5f7c27b1ffb6d74508a433", - "dist/2023-10-04/rustc-beta-i686-unknown-linux-gnu.tar.xz": "2ed53af655d58300f88bae54967f964959c01f7d39e7198b14ad835392826dae", - "dist/2023-10-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "720e53352f5388ce0880b3f51b9941c4d7db86a549ae4c624238808438b02ecf", - "dist/2023-10-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "9fe3dc9d520284e4004c712fd328d86b6e4601283efe0bf519c3386906dd460f", - "dist/2023-10-04/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "d479a5254d2707ddf725b7400ae04c8c68c138a54aa65861ee5f8e6ef107c4a9", - "dist/2023-10-04/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "bf1756fc7b439b338defd1cbdcc1127c364a5ce4248c73f9a5881c39dd6a7bff", - "dist/2023-10-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "691e59ad96392bd1b61538fe2bcd8665470d9243a09c372bad93c115092aa5b7", - "dist/2023-10-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "3597d20828b23e94934ea8bbd4aafc51e06bd006ff993e95d1106822131403b7", - "dist/2023-10-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "24d283898ca2ce98b2ba38a9ac2fd2fb039da21badbe7c2e0c15660cd622a7e4", - "dist/2023-10-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "5c927ce64da0e898c03b56677047f087f88eab5c0777b6f07fb5356fb7dfd913", - "dist/2023-10-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "e10ef3fafa1dd6bf2c935853bb9289e1fbf85cfb092683b99107f986a2ba0b9c", - "dist/2023-10-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "d0fa4adb60babd26da08c8e141f1ce472c0c3111b1c361bb1a28cc65cd83afa7", - "dist/2023-10-04/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "65020cdd2b30795f3a8771fe41176e747bd13f3b948860aefed5675b89c55257", - "dist/2023-10-04/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "233890aaf235832448dbf05f7ac547cc74c53490fd6c9818d7ea673bb6391d35", - "dist/2023-10-04/rustc-beta-x86_64-apple-darwin.tar.gz": "745e29cf4127d5f67c1a663e47755a8cb200a14cbb44a33e5da6d25e11c145a3", - "dist/2023-10-04/rustc-beta-x86_64-apple-darwin.tar.xz": "609f55c6c784caf6978c176ddfe1b2675bd7f23a4ce4ebff98147f0ce58c0cac", - "dist/2023-10-04/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "78e37a161d41f1012896efb345b1e53febc11943e003c3e848106828e2b9337c", - "dist/2023-10-04/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "58baad93c3fd4a9c25472bfb10cea890efc94cc7c7b131d8dbca727bae79491e", - "dist/2023-10-04/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "3e5497aa975297ad9abae5913ab7ffe8a77a40a37cf26d7fbf18410993731ddf", - "dist/2023-10-04/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "157877278bb6b5af2676a61377e4a2b637470c89971e649b3476ec33d2f84987", - "dist/2023-10-04/rustc-beta-x86_64-unknown-freebsd.tar.gz": "923235f207f5477e455e82c1f516fcb1f9281f67c2f4fefdcb8b4a64b651d7eb", - "dist/2023-10-04/rustc-beta-x86_64-unknown-freebsd.tar.xz": "8e298f4524ee23f9f9b7ca00ce8c45c9e1a16d85c19acb4897fcf24ae1e40d8a", - "dist/2023-10-04/rustc-beta-x86_64-unknown-illumos.tar.gz": "e443cd9be3b531b645ad8ef32bb7f91f25fd17bdbd9439f1f77cd8345c13cc03", - "dist/2023-10-04/rustc-beta-x86_64-unknown-illumos.tar.xz": "682f11962582237689f9b8bc75c5a42b7492a26957909d15e919e0871b33b030", - "dist/2023-10-04/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "60faf9e993a2e2ebec1922a485fa63a47a1c4ad9e282928be8c21dd6397efe9e", - "dist/2023-10-04/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "e0a5cee0346f2ec96d14c5aa6b9d26d8d6d8ac80ea852b2df89d2df999c965e9", - "dist/2023-10-04/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "62ad39e3d0ee9eee3d88f3e2e0b151fc9eed8475e2e4b601dea37b8c6990a9c6", - "dist/2023-10-04/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "8946e23ee7e0eec9b519c0a7c0428592c30a605efb6b58109936300b59ac3074", - "dist/2023-10-04/rustc-beta-x86_64-unknown-netbsd.tar.gz": "651b08daca5f9de5c24ff465ee8f93beaa77477b6b54af8f7929d54876ca08e2", - "dist/2023-10-04/rustc-beta-x86_64-unknown-netbsd.tar.xz": "443bc94ae5274c8f42961bd2a297a32ee1d543ee1014d0f6cfce45febfc19c18", - "dist/2023-10-04/rustc-nightly-aarch64-apple-darwin.tar.gz": "2932fbd7dbe55d1bdfe33788d9aae9e40e42e5fc81841b605873cd118a769947", - "dist/2023-10-04/rustc-nightly-aarch64-apple-darwin.tar.xz": "c9bb124d9b5433d0a5fbfe8728fe4db5314b07f6f38617e6c8fa0b263f02b813", - "dist/2023-10-04/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "8b9a4eea2d57230d6dcc867b0564ac7c5b557e4eadfe8198ac253c523e72c00a", - "dist/2023-10-04/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "993f2afb93e5736973eba557ff5e14cebf4836ec02cfbdf2b652f06fce39cce5", - "dist/2023-10-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "0e10e13a02462859451cddcb429af9453ac3ba11dbe896d49b008905ec3b0fec", - "dist/2023-10-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "be81aa143335be4d36c01ca557128cbff380cdcea72d9df20260ac6d91ac79fe", - "dist/2023-10-04/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "f4300af316cc86ea85fb9775ad488e22e1f36fc10a2c40a55bea26fd1d180359", - "dist/2023-10-04/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "8579fdaf0c89dc6dfb69ef6f9c1c650476c4aa3d6f2664776a453028516366d3", - "dist/2023-10-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "bf6cb4c51f515a63e0ab92904c364238dcb889f21148ceffce0c2110238a7fca", - "dist/2023-10-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "359a9a8ca14829ef6f530631d8b88eda2fbfd9a7d01a3b9c8e98b121c8470056", - "dist/2023-10-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "9508938031c9333accd01cffad43b5ff1c552843cb4d5f5a0f767a3ccf908c01", - "dist/2023-10-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "e5d7638eab37ee18b58d50848398cef79d241939e1330796a7678399d395d1c8", - "dist/2023-10-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "196c7e12591a22f5c354045bb1f8ad18e8f069191b5d234fac3490d4c0782839", - "dist/2023-10-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "d01560008ec3c254b5ec1c4f9b4b707b7e60d4c7eb1560a2e95efd9fd681a63f", - "dist/2023-10-04/rustc-nightly-i686-pc-windows-gnu.tar.gz": "13987991229171f65295f901451bc735d5b38737c012150c7d912a9dbb627136", - "dist/2023-10-04/rustc-nightly-i686-pc-windows-gnu.tar.xz": "de3b82265e5157b0fe36ba0686b4dfaf9b697594ba50c0697d1d261812bddd30", - "dist/2023-10-04/rustc-nightly-i686-pc-windows-msvc.tar.gz": "aa2292fbcd0ea65407e5cf47924616a90762ca4750535c3e980b9057623bd896", - "dist/2023-10-04/rustc-nightly-i686-pc-windows-msvc.tar.xz": "063fcf503b76f1ae1ed7278a01c61e12bef4aa6d5e69ddec751986dfc7038b27", - "dist/2023-10-04/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "cb0a6e9cfbf7a2869818fe16c853127e4d7cafb69cda01d7737d30476f7d9b49", - "dist/2023-10-04/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "0057ecebc5d9e12f6ef8d0c0ea737b7694507b9c7a8ce0e6e0d323acd0a39b3e", - "dist/2023-10-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "b38717c03d77eb019262ea3a82e7d91f620170bcb1f05717f8e5dadfac1df483", - "dist/2023-10-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "4e6a0e9d35101983388772f77ac0fc0714f3025d670c649e6050fb50ca031738", - "dist/2023-10-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "1ea0bd0e5070fa590dc2301b6f41a54b9895b0fd688d9c6f37d77d0b6bbef8ee", - "dist/2023-10-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "6666cc6e04743127cd63ec7c8fe1e9fb7882222778471ea1368bbab4adce903a", - "dist/2023-10-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "60c4c413d85f86de2709e4b9ab4c0e25bb6e99da3e10cc68eb2b3864a5d60e18", - "dist/2023-10-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "8569bba6344da9ceb87d53c3d5664d442a1251621625f7b332c4a6f4cb93643a", - "dist/2023-10-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "016f8daba0a904e185075840c55f477bab7c91a8b6ca1aee936074f01adb2b44", - "dist/2023-10-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "573286e527de43850a25b2c03b61d89fc97437ceacc9f5b3be3a313c9175027e", - "dist/2023-10-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "d03339ef02057584100232a6def4a9b80f13b9d242fe57fa47c0b18e84f3c56f", - "dist/2023-10-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "2e5ceb85b2612164e1727471a775d5ca1924f92327deddce0d1509c5a87e4bb9", - "dist/2023-10-04/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "b991507575a08b993508ee4c7ac065f3f1983278a457c141ffbfb15b46ae25c2", - "dist/2023-10-04/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "155a4e360eeae301379200415820a6f9c53d3923943d791a3e802ef8083494c4", - "dist/2023-10-04/rustc-nightly-x86_64-apple-darwin.tar.gz": "0ae7a68d86c72f42e3a98737abe466ad88a6be92cb17994b26fc2a495abacd2e", - "dist/2023-10-04/rustc-nightly-x86_64-apple-darwin.tar.xz": "5e2b0a191b34e133ca9e0d883714bea46dc0f6381c9e5ee145851bba799bf7db", - "dist/2023-10-04/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "62e5b0dae1aa25488dab73869da8ed2425114b778adc55db6c6c6b9f77c67d7e", - "dist/2023-10-04/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "5494b11d55bb36ae0536b534796870a0ad8e2a427f64a21418d5bcc2d0f27ab9", - "dist/2023-10-04/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "38b8add3755f62016c40ac84ad3b7085b6058e40768b40e2df672ea4c5d3e91d", - "dist/2023-10-04/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "e511c5e3adfffd33e6dd3cd9525409366f3b54ebb1b3a7f2c09cb7444e678006", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "54190bb432f9dbc4fb414ff40a5e8a5668b8aa343599b4e4b28f7a2e9fc0fa3b", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "7c260043c68b31484f3d415d43ad8bd702f642cfc5050e09ea6b9bb7fa108020", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-illumos.tar.gz": "7cc87c2a5f801a1023688cc6bbecfa0c4c072108b4edcf4afea5df059ef1c2cc", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-illumos.tar.xz": "b21f227d6b8c4c8847db2e3299613a86b13c95bff4f17c7055e1c0d46721fbc6", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "52b372926f5f72a711c36da67a09dfd8d4c9e819b76917053865cce5bc603732", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "499a3aa2baff90e710e2aa9d6be421569119ac90b484093ec38717da1fea3142", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "dc43a1ff5639479cef66778baf3a61ccee67b1aba57dc24a81a0d2f35b24b3ad", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "0f953831e44c7084c86f393cfa3a3b3a0ea8aa2de3a0f7701094683f491c4a6b", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "e636cdb58be6fc3d97387121c404d02772c5a7519f0f001f1c9ff282acdaead4", - "dist/2023-10-04/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "79db9632154590294cd0a9f1229b95ec82163a278b3011e25f2fb86c8af6d894", - "dist/2023-10-04/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "0cde181bc0e9af1eb2813aea3ada3333974eaa85227eab12eaeffe026fe7f31b", - "dist/2023-10-04/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "0aa47b92b78591f522c5d5b4109b1a0fcb4489ceeb3a9014d3f71dc76bc00a6e", - "dist/2023-10-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "30ac919cb1eec11a22d96ab32debddf9ee91e776d0edac25fd2c71421145d77c", - "dist/2023-10-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "55d800eab787c0bb1d41def853b1a48ab54c2e6cfd6b118e905ec283cc1814eb", - "dist/2023-10-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "9e3ae2cbc37307c47c78c953cb2703daddd46b6df44cc61c2b3cf43921c5b03c", - "dist/2023-10-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "6812bf2f1ff86bce8bc82cf2ea2f29171fced04b9ca89cfc43121824c4d15eda", - "dist/2023-10-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "99ee18898dde1821751cc06eead4d53208d66d98c7f95e8122c7a1161924aaea", - "dist/2023-10-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "f65c4577aad313101a6b22f55d777a76db31f21c6467f25eb1d8775a484256ba", - "dist/2023-10-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "94b76e626d2460f6701d5c16dc91d633a8c88b0f2583f4996b1173709c29c8cb", - "dist/2023-10-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "d63186fe9980b884f375f8ea44ea2e4e8493529047a7035c49c9007261310d8d", - "dist/2023-10-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "04e20827f34cab6f259686decdec4df335a8bfa2846a46fc83bee1d65b39ee15", - "dist/2023-10-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "f46798ddac7d5b3cafaba54b0fa561ff618f7b931cba4b59eaf2f38e5a60b720", - "dist/2023-10-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "3d2b5974f820e976c890300755efbcebb4b14558bd9824bc66d9ebf1dc33de7d", - "dist/2023-10-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "ce148b424ce7122fb2330c9911fdb134a67b7365dbd10fff182bd70517ea39e1", - "dist/2023-10-04/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "369278645833248dad11a65a886791134880e26bf0a35ff9462913a355fffb90", - "dist/2023-10-04/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "995727a9213386e7e02d27a3d2f99f5beda5fc0469fccc5736b92ecb4e317ba6", - "dist/2023-10-04/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "92da2162ef18033e68593617613ac11d9ba16bda81a0a685a89fcbd80a815994", - "dist/2023-10-04/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "abca8c7e31afc80ea515c92a7e12a8d6d0af6d41d5f18caeba74a1cd5372876c", - "dist/2023-10-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "e755ab5413fa52013cc00df1d8cda68c5b3ef1e99d1d964259d5b002f293e8b2", - "dist/2023-10-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "1100241ea39bc177140c458a12174b54af5d569000f59c9791ee8c6497fd4fe6", - "dist/2023-10-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "5ac4fe7bb0f596cd8565d1edef6f1696043c698c90f5562f5d4a94fca26021a6", - "dist/2023-10-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "9ecf3bac557d64bd467f9213959e8b1a361041e5a98552a448936fd2903b334d", - "dist/2023-10-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "71bbdb6c608d2cdc60619dc2acd7bc7e35e9a20e5e02a633b224b124438a7cb6", - "dist/2023-10-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "2d3af87b5c6e0ea524cde039a6deb0b014ca103e4183602b47aedb5bfb97ff9d", - "dist/2023-10-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "e3678dc35f3dede5d6fc5e75eec6f19990e4a8b034163c4ef79eb522e654f6f3", - "dist/2023-10-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "da9ed66ae0021c2cc16d70a29151963149a433fd4a2a299a45d7cd23556fc58f", - "dist/2023-10-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "8a08e5a3d5eea3f414e7b8ed939793ce02f843a60dadf0e4d6eb62e8265fa20c", - "dist/2023-10-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "68441252ba1e058023cd480e431e04d755309c1acd7330d49a20c0aeefb1ceac", - "dist/2023-10-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "305f24d9813129ce07117dff8cf0de42aff539c7a89df58c2a11f7056594a702", - "dist/2023-10-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "beca739e374e20d15a3a16240a801662c42ef135eea5311d8bae7335bf27634c", - "dist/2023-10-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "c33dc1b858ad79f2ef89159f40b893d071bd54b1891868064bd210fa2ab1c917", - "dist/2023-10-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "0929169a91b4d66058e251ebf7c8bbeb73e3859600158afeb9fcdedd4de84168", - "dist/2023-10-04/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "13684516018f9c56c504793b4d110610f6f8c4a2a1624c63630a12927a9b5b29", - "dist/2023-10-04/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "50686ab2eeeb73d51830b8f19c76a615eec1b17df8f34ddbcbee6458fc51832d", - "dist/2023-10-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "315a87aa3fbbc7594d64b4771d105961144f9937c9c1b33991de4ff33c186bd6", - "dist/2023-10-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "289c99380cfb2933d5c85b20f7f38e4a61de2c3ce3640ca45a81eb68a7005b72", - "dist/2023-10-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "81f689344b8d0d2312790109c18e206849906bcee5bb167c9a07632c1ba71eaa", - "dist/2023-10-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "6f17e1e8327cb470c00e58acb8f4b076aa8989c98bcbb0c55867dd6ba1f436ae", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "93e0ccbe7484ee679c4cefa80e46d76c0adfe93f0b52b34ba80cefbde69845b9", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "4c9fde270df24fbca4286d42577d454fab9aa3cc7abec2f8eb4fce359162d8ad", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "e6d4e9b727c7c61a28dbfead22492c7503c4b5d05b41e2991eb9e3551365d440", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "30db9362b5f7eb09ba8ac2050cb98599fb352b332bf3e5c94ad6bc182fe9f294", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "348b94f9020c65fec79a36c6044857a7e897164f1b2a4250e807f258efe99e1b", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "2914983968c484e4e74cee620764aeb476445b1e324253c5087354dbb95a0132", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "0ab0a77a8fadc6cc4e21238cb9487bf5e3b6085663351b2b3c429038621ad83d", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "a992de62c67d56889e11dc7c5401729d8658c3e50365037b4bd975624122dec5", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "e9ab091b5bf9d307164b8c774f98912a0a8282f98e6d9528569acb2dcf29a10d", - "dist/2023-10-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "d9421dbbb9b995b6df1144cebf0d6b10fc4a91414b97d66b28335e78b8859d5b" + "dist/2023-11-13/cargo-beta-aarch64-apple-darwin.tar.gz": "747e7a7b31217abef7f5e6e451669cbada43ccaecf6e58df2dabb2b059256406", + "dist/2023-11-13/cargo-beta-aarch64-apple-darwin.tar.xz": "4ab42395708f3d2b495217c08f96a80ad5a6415edb226391e0f010927b206b88", + "dist/2023-11-13/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "96a5f6d7d5fb25cb749b4f20405d7eb1aee296ea58915032f589943faaa87819", + "dist/2023-11-13/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "0f350bb1a28c7d822782137d80f0664c7906cdfce050e303559ea98891a0e3c8", + "dist/2023-11-13/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "a02bafa141d71877c806aa7bd9ad6831c4cf99bb62503ec4a7046e2e8a8a7885", + "dist/2023-11-13/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "26b16d1805b6424109dc1586146fec72ad370eb7d6be0e746b627884a17f8ab7", + "dist/2023-11-13/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "b8cfc7a38693863a8b8b2928654a86347c07b8da14356a424dc86a4451e2201f", + "dist/2023-11-13/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "579c0fe919fe22221a545bd75152d7cfdac9f1b6529f9eacf397c0bb4d4db63c", + "dist/2023-11-13/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "a4fa076f7512a74fd3c4cb6f3ae12322049197ba5e719801fc4d72fcf33b5837", + "dist/2023-11-13/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "4574101b1cc23cb87abc038f342a73fb3b46a5a8d18f660ff4ce047a30a507e4", + "dist/2023-11-13/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "cafa333ea302e7066ad642994eb92811b85f41da5f2d8da83bb9c380eef44a77", + "dist/2023-11-13/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "9fb8b43ae9c7c18cee03403cd5b01cd246d5a0ab542e4eb19bbd03fda0e611cb", + "dist/2023-11-13/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "d3f6f85bba4b890fae52c593d8d57ccccaf86dd2d2545afe49d1dc924e7a72b0", + "dist/2023-11-13/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7380fd4af83d9caad6f9a7d5d03f9ca33fe770fd35cec2e7ff78bd39f5a1e417", + "dist/2023-11-13/cargo-beta-i686-pc-windows-gnu.tar.gz": "15673b84641058cc0a91fedfad9f74c284d87231905980182e535ad7ccd9b31e", + "dist/2023-11-13/cargo-beta-i686-pc-windows-gnu.tar.xz": "2661610cb774326a04fdea7011ffa10a5635ff679ba744c05eb3abc56b8fc8da", + "dist/2023-11-13/cargo-beta-i686-pc-windows-msvc.tar.gz": "e1aee3221f3f17d129cd06f506a9cc384e91d211cc3ac09b927e3c7f069c74df", + "dist/2023-11-13/cargo-beta-i686-pc-windows-msvc.tar.xz": "d2f18bc8e07711ccc9723be50cd8bf42bc710efc50f12ef72921d12af7d2b9f1", + "dist/2023-11-13/cargo-beta-i686-unknown-linux-gnu.tar.gz": "0aac1acdb7cd73b19b9581f2262a22ab43378ad17c68e7b8133d34ab8b56ad6c", + "dist/2023-11-13/cargo-beta-i686-unknown-linux-gnu.tar.xz": "e592ec051931d944f2cbe23d42e3b59ec4b077f6122dca928d065cfab333d91c", + "dist/2023-11-13/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "b5905ac53e476ecf1e0ea7d6625c1306cf8de27a2f1ff6b904e58bebfd87d384", + "dist/2023-11-13/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "3ee0542b6dec61ae9839f838aa229e13ad8e5ccbc659d6cff5c30f5cc8da1b7e", + "dist/2023-11-13/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "dc469696bbb2c80105c615dbd1e404de4e2552db295c20840f8253fac58b494f", + "dist/2023-11-13/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "0d162454c64f09c54f55c177d1b9f73cef27f399065095830ede9f3879395bcf", + "dist/2023-11-13/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "1c5a563db7c53e639823b56251efdd755c052c4cbc83956c84cd1f6af880ccf6", + "dist/2023-11-13/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "1302079a10c98b469effdda4de7bf8489cc577497c125f609b72f2f8257419fb", + "dist/2023-11-13/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c739f65c2e06c5843bf619b1028fe6f2c82cbe48e922d1bb30d2379fbe74317d", + "dist/2023-11-13/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "83e25573d9c4713e095e3f2f253228ea558c5826b00319c9622fd47be5787351", + "dist/2023-11-13/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "04bb36ec9d2e636f11f7c5573f4749e3c767dc371fb7dd7e5fb7bc5497a9f02a", + "dist/2023-11-13/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "4d79803c2f04a69f02bfbf9e300b8d48baf381a4fadc9f665f748b81f1c2b126", + "dist/2023-11-13/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "49354596eb8d6be2afd40022504987ccf0e54c205d74ee5b8352260f2e95f9b7", + "dist/2023-11-13/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "1df49a605408c0b72c95f5f1fadc6da14f847622617a70d4ae0df6437505896b", + "dist/2023-11-13/cargo-beta-x86_64-apple-darwin.tar.gz": "3ac3c0170016d6ca3fa18902a1c8714820ce8c743e7dd3674c54dd69f1f84645", + "dist/2023-11-13/cargo-beta-x86_64-apple-darwin.tar.xz": "d403d08162ecf41d53190ea5a3a945c1fc5bd0e2c380dbaac764d03ad8377f0d", + "dist/2023-11-13/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "1003fe8288c982459ee4379a5746d825ff0b6c5d0bebb2b269903da9432b712b", + "dist/2023-11-13/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "07a364faf47204c92d021fbbae57b369ad82ba64fad2173189aea3764568eaa8", + "dist/2023-11-13/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "1a7213217869ffb3c48b557dc8c172be61eee258f7bf34bb2b5f8c9ad96f8521", + "dist/2023-11-13/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "64966d116575a18354d6e884317a6400941994462e305269f25f17ef17605417", + "dist/2023-11-13/cargo-beta-x86_64-unknown-freebsd.tar.gz": "7a1e553ef97d3d88d532060a8dd64234742df04ada95f5d13536b21d380a9d1e", + "dist/2023-11-13/cargo-beta-x86_64-unknown-freebsd.tar.xz": "67f1bb5008080c00f4f22be794b1fa63a88c1503187dc3396260aa73d52a1f7c", + "dist/2023-11-13/cargo-beta-x86_64-unknown-illumos.tar.gz": "436959c6da9c1c4bc49c4df51747729c0cc31b68c5a4dbf0e1875f3535dd1d26", + "dist/2023-11-13/cargo-beta-x86_64-unknown-illumos.tar.xz": "fbe0068c48b9b90467fe22e61d7c0707dbc8b113f07966f6c796821d283fe113", + "dist/2023-11-13/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "aea309719c709ba1a8663dcfd8f4ac379695d65b69115641e6adb57cd24819f0", + "dist/2023-11-13/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "cb0fcf1a9804d106f4168f6f8d2a071bddbfaa55430f3284696982bc6bc6c4f8", + "dist/2023-11-13/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "03062f953a10777d1a26ab13190a5493c989ab560b182c5968cca3df97fd2b48", + "dist/2023-11-13/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "790a859eaf49da5fdef1ea1ebf8b7f1f001bdaa62798a745d791bc915d886094", + "dist/2023-11-13/cargo-beta-x86_64-unknown-netbsd.tar.gz": "f14395b57c0eca7c8ac9012b303c3781e16a2287698f68705fcbbc5c7c5916c9", + "dist/2023-11-13/cargo-beta-x86_64-unknown-netbsd.tar.xz": "2c759c8bfc9cc556eb3464ac7e5589b573c46bd3938ac288ba52549121d3333d", + "dist/2023-11-13/clippy-beta-aarch64-apple-darwin.tar.gz": "258b55f0db78c93f14952fc3e2d9fc49f1121de5268ec49d03d4f197bd7c9773", + "dist/2023-11-13/clippy-beta-aarch64-apple-darwin.tar.xz": "554bd9488a9887c4acfb7c24775365108aef049feb15c93926128f805183f5e1", + "dist/2023-11-13/clippy-beta-aarch64-pc-windows-msvc.tar.gz": "d120adaec65b5f44f40fba38fa10a0cda33769756ac7fc2878d64154acc7e06c", + "dist/2023-11-13/clippy-beta-aarch64-pc-windows-msvc.tar.xz": "1dd23152a87fb8fa60569c304a3bbfd93f97c52d533fe53c8d9a5a4a72912938", + "dist/2023-11-13/clippy-beta-aarch64-unknown-linux-gnu.tar.gz": "41198264d015ccf624e0fca876bee16f8c3cbb07596f5f4d4f271b9843b10e30", + "dist/2023-11-13/clippy-beta-aarch64-unknown-linux-gnu.tar.xz": "1c889aad06c73dd2212403ff2aa5f256eba490cb8f1c81d7c75199a267052648", + "dist/2023-11-13/clippy-beta-aarch64-unknown-linux-musl.tar.gz": "db784d117c156d0e8854518a5df6e9adbf0b2d24f3504358b1a371b8e7954eef", + "dist/2023-11-13/clippy-beta-aarch64-unknown-linux-musl.tar.xz": "a946d40d32be1c5477f1740648e18af5792ceed38fe255e8cf09160acb27d02f", + "dist/2023-11-13/clippy-beta-arm-unknown-linux-gnueabi.tar.gz": "1b760fadecb9f4c4c1780b36d9bd651fa6c8a8fb6b48dc0dfbfb2ecd9359ca92", + "dist/2023-11-13/clippy-beta-arm-unknown-linux-gnueabi.tar.xz": "9e21f778eee57b067f411faa15425317158abd22f7c60dd4fc24214536ff7415", + "dist/2023-11-13/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz": "fbe3d7776b9353782d2690ff1c98a0ce5d8d23de2381ecd3d4eff4ce165b66d5", + "dist/2023-11-13/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz": "bfabf9e2419065173bf709166b0c81db66e1b2514003b28d08ec4410e04525a3", + "dist/2023-11-13/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz": "5371c798687aece2b98e22cf5bca02e568913011393a86a1aa3b0ff79eeabb57", + "dist/2023-11-13/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz": "82723066f2ec52fb5854a397f71df79db54976f4c03113034627c1a5c92ceffb", + "dist/2023-11-13/clippy-beta-i686-pc-windows-gnu.tar.gz": "0214eee5dc37f3a780ca62f1e7a66c5e19d583542dbfca047e383dfacca604b3", + "dist/2023-11-13/clippy-beta-i686-pc-windows-gnu.tar.xz": "cee7d7039b1ee909fa4a188d7fd0bae14d718bad98209d8df2dc087cc28d7a9c", + "dist/2023-11-13/clippy-beta-i686-pc-windows-msvc.tar.gz": "b6f1042f0d4652e941d975af8aeb4a61e335c585c1cd6dad7f85ba5b03c6face", + "dist/2023-11-13/clippy-beta-i686-pc-windows-msvc.tar.xz": "a31c1951abdff06c3709472acede08cd000b940a7a65f9afd664ca276fc724c1", + "dist/2023-11-13/clippy-beta-i686-unknown-linux-gnu.tar.gz": "1e0f2f2ea38988cd0012ceedacfa9828b4b6c6dfd3dca9eee5a98483fd90f439", + "dist/2023-11-13/clippy-beta-i686-unknown-linux-gnu.tar.xz": "f19b56068a40af2aee7c828a4688289a8142f98a81b80d66d12ddc6725209628", + "dist/2023-11-13/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz": "e0f02e3ba303bef68a7cd1ea5effaa126eedbdc892b01dac85f4b3e6d4b2f522", + "dist/2023-11-13/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz": "17a01e484f238bff790ad6cfededa8d9c7df0f6f36af336a1e8a7414a43271f5", + "dist/2023-11-13/clippy-beta-powerpc-unknown-linux-gnu.tar.gz": "ea4bc3aed8739bcecaa97f01972bbbba45e838c811ca0c408824b1409f9ac7c6", + "dist/2023-11-13/clippy-beta-powerpc-unknown-linux-gnu.tar.xz": "9ddb71b1f35f6953aedc6a1f93dde4a9b014255b5bd7d4448e4dd9b1a65c7f5a", + "dist/2023-11-13/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz": "ccb95c3ce3dd4ee2776201ce1bd79122e97916c555126393f1839d301824e746", + "dist/2023-11-13/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz": "9aad65fcefe5789670bc85cd177bd72eac469eb0a33db54685132a7ce5115a83", + "dist/2023-11-13/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz": "eb50e6349423c963fdce3193f361572a47e4d7fe5b90f8a297471c0a5df31feb", + "dist/2023-11-13/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz": "aa72d573b344953b9224ceb6eff484b6f012febfc009bc7773d398a3ffa69ea0", + "dist/2023-11-13/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8546ac9a9e5081384d7ef889254e41998f60c04bbdca319128039e8a4e7cbc68", + "dist/2023-11-13/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz": "15fa574f7f7de2d8fcd124f44b1880a78bdd6a2ba77fe6b392299dd746ea9c63", + "dist/2023-11-13/clippy-beta-s390x-unknown-linux-gnu.tar.gz": "ee27937b85c142ebf46bb59ad9e113414cc9d631179a2f8df2b32980aa57b515", + "dist/2023-11-13/clippy-beta-s390x-unknown-linux-gnu.tar.xz": "e6e99e486418cb23a0cb80a2b145413bfeb62746b60fd9a0ff3959424b7ee07e", + "dist/2023-11-13/clippy-beta-x86_64-apple-darwin.tar.gz": "8a37545cef25abdd3c722a21385b843cb9d8d06fed8f302880beecbcb9373f98", + "dist/2023-11-13/clippy-beta-x86_64-apple-darwin.tar.xz": "f572586fc28bb5b2b77464d89b41c374de4002b453c297a8fc1468cee10db972", + "dist/2023-11-13/clippy-beta-x86_64-pc-windows-gnu.tar.gz": "5add2dab913488a482be6849887d9fa8c3cd197d3c423595a7133b511efcefca", + "dist/2023-11-13/clippy-beta-x86_64-pc-windows-gnu.tar.xz": "1d0d97a6b8703166616b6ae56d2b344e85dfa1db36976585d21cda65362cfff8", + "dist/2023-11-13/clippy-beta-x86_64-pc-windows-msvc.tar.gz": "4069dc9296cdc54af7e14d4ba5fc12ee5e6445be74f39c39526e4ed77378112f", + "dist/2023-11-13/clippy-beta-x86_64-pc-windows-msvc.tar.xz": "fdf4dfaef5f8fb24075bf8b24bdbd71804a49acda40921de84c61bc2250ade6c", + "dist/2023-11-13/clippy-beta-x86_64-unknown-freebsd.tar.gz": "4554eee1b1bd7e5575eaf5e7a815686da88fb395a80084c7a0fad3f338ac83b1", + "dist/2023-11-13/clippy-beta-x86_64-unknown-freebsd.tar.xz": "b0f1718df2a1e88ff4aa239bf4b9dc7a971fbc64cfa1ef8f399760fe09117097", + "dist/2023-11-13/clippy-beta-x86_64-unknown-illumos.tar.gz": "035400e01edb1a91ddcac72fe3ca1ea94465c4fe9047546d057f6867d8b068d1", + "dist/2023-11-13/clippy-beta-x86_64-unknown-illumos.tar.xz": "3ad1b06c3bc1e327ea7a3b30908b48bf6b59b7222101e5a30fb054b1be579087", + "dist/2023-11-13/clippy-beta-x86_64-unknown-linux-gnu.tar.gz": "88d611c40a30922515d09425ecd1a8b87f46131ab61f3c4bf841a41f281134b3", + "dist/2023-11-13/clippy-beta-x86_64-unknown-linux-gnu.tar.xz": "9908227c8a684aa5c24f3272997fc9688044580f792375ec9fc8f775e394953f", + "dist/2023-11-13/clippy-beta-x86_64-unknown-linux-musl.tar.gz": "10a7b2427ee8a4e83d271023e6bd00573266f317789cff3b75e68d7bddc41cbc", + "dist/2023-11-13/clippy-beta-x86_64-unknown-linux-musl.tar.xz": "cb1f3c2be55e11920340344d2f2f796098b7f13c9ddd2fb8a38ac1b29c5d6925", + "dist/2023-11-13/clippy-beta-x86_64-unknown-netbsd.tar.gz": "2b29461b085f0af1bb50d10ef8bf6448550c9b5867a364da3d921daea8e0a13d", + "dist/2023-11-13/clippy-beta-x86_64-unknown-netbsd.tar.xz": "e9d2ff4c8c63a9cfb7d8b12df4942f5b90c33c4fa3f755bbdc3c5df1b2b877fe", + "dist/2023-11-13/rust-std-beta-aarch64-apple-darwin.tar.gz": "818e3554a6bd82c3533e68f8597c09563af1dc08d6b23bbd2323b8ebcce251f6", + "dist/2023-11-13/rust-std-beta-aarch64-apple-darwin.tar.xz": "6f9333c281859e40b1c1c20e9f07ac1633ca2c99e86268b521945b8ed6cf6a50", + "dist/2023-11-13/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "fa4bb7a5d4dcecb2dfd8596e3ad442a5fe05468c939de3b36e44a43e10ea9d30", + "dist/2023-11-13/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "4a8e8ffb4658162c3bbd7b1c819f50181ca88c6afbb61c689c621ee4d29a66c7", + "dist/2023-11-13/rust-std-beta-aarch64-apple-ios.tar.gz": "42d37c57380ea2b97c1ba62d50d49db5e674387b0953f2bdcb323f4383f5f456", + "dist/2023-11-13/rust-std-beta-aarch64-apple-ios.tar.xz": "699f2f3c386f4bde50cc59616339abb95d95f292650b4b1f04cf8d923fccb03a", + "dist/2023-11-13/rust-std-beta-aarch64-linux-android.tar.gz": "b872dd2e1f7af33d327033ee602bcc62a5e49cd6178d0974a0f0ffcba86b457c", + "dist/2023-11-13/rust-std-beta-aarch64-linux-android.tar.xz": "ef121a3a4db77c3935d23887ead6c6399dbe45c739566c8bd66ad4fbf6adef2f", + "dist/2023-11-13/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "055043974520b270fdfa63074e5f44d2881052542549ae215e5701c1d476235a", + "dist/2023-11-13/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "6c320b375bb029c144eebfb01127ac0f1f2e4567df3ea505ad5f48d144115272", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "9aedfe4d4186d26878ffa73f6562a88e5123a54fc81293315c4e62c9e559b6cf", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "7f623ca49e51ad78caf64221581e96eb95a489532cea22d91f98794f5a6819eb", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "07bc11565052f5a417f650451f2ff0aa6f0aadd506b664e77789006429746d9e", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "d4bbc5dc49a1f6d53c1928807531679836aa69a4b3715295472e3df4a40da27a", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "493f4f196274a1141904e1aeb9cd32dcc6d4a06283395012d257e2a8d545d7ef", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "594529eb5be03d6f376c75d04260700205f815e33697e6cabd5449754704c748", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "5b9a95cccb9179fe2b62998292a40ec05137ca9423b103392fe4d7a6e6d03402", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "aeab81bc3066bdb94227a31473ded8a623d9bad924a39bb6db6e7d6f4fcb77b2", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-none.tar.gz": "24a9a76b4a2a24c9388d55ff95dc100436ed7047f95c0d6476d66cb9266f6c03", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-none.tar.xz": "0052dac98cec080b2bc15955f7ac93c11db351d32c7f5a1b46e00eef9ca39f81", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-uefi.tar.gz": "3bf855413ee4c57ffa54eebb00b819e57014977bd85c69dd5ec35ec0b64d1b1b", + "dist/2023-11-13/rust-std-beta-aarch64-unknown-uefi.tar.xz": "0dc3b0d4f1cf927b1e1a53755b1f2da81bd4e43c172e446426ce70db6ba22802", + "dist/2023-11-13/rust-std-beta-arm-linux-androideabi.tar.gz": "9f6d485b3e53a3604f80f48149742e22820d64fa4e4bdba0b0206b6d6be78486", + "dist/2023-11-13/rust-std-beta-arm-linux-androideabi.tar.xz": "52efc21d5c92a8bb3eaedfaf87fda75b5b19bf0c65538b718f1fabc3b14e0582", + "dist/2023-11-13/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "5c5089e88d841aeabd4ba279a696a687cb68850185da92b61afbd3739c0a409d", + "dist/2023-11-13/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "55ee23f7747ecfd8c8c6678372109c7068d3363d710519bc607135fe8b5fc46c", + "dist/2023-11-13/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "08afb933ce18021e8bc6a016dcc63f8001bf94f201618b8e004c2f4c4c9bafd8", + "dist/2023-11-13/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "1b16c956b8b05fbbd0d3adf0356dddc64be1a8f099d99f6d8d7f76a0b07d19ba", + "dist/2023-11-13/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "ac49dee872f3cf6d74abb60c6a717a2e8fc8994e8a2a4cf2e89eab7808f9013f", + "dist/2023-11-13/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "5852f7f9f08574a351f5094a5268cddc27afc4b9933c998d0757a838504e9959", + "dist/2023-11-13/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "c9b806a780d1cb75f7892b2d1adca343fcbfc626fd4c364af42c13d8f8e71e82", + "dist/2023-11-13/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "d81d26a77da1d034caafd194e2d36de5be1d4c4f99095d39a378b661dd20f28e", + "dist/2023-11-13/rust-std-beta-armebv7r-none-eabi.tar.gz": "be2105b20ecfd7103613a4e2924e6057806535f467a5aadacdf8f458eff9866f", + "dist/2023-11-13/rust-std-beta-armebv7r-none-eabi.tar.xz": "f130958a449aaeb7fb81864eae5e25e5f1b30c4b59c438e15783eb501ec01e80", + "dist/2023-11-13/rust-std-beta-armebv7r-none-eabihf.tar.gz": "68e2ae2d1d6bb4eadfea2e1baccbe2984c38c13d9b492390ea897cf828976fc0", + "dist/2023-11-13/rust-std-beta-armebv7r-none-eabihf.tar.xz": "08858898e6b3c4855e8dfb015353a76ae5afa056208de6110135967fd752e6ed", + "dist/2023-11-13/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "06726cce8e9d1106443ef1d34fc9ff960cc8bfe7b4553ddd8e8c455360fb7a3b", + "dist/2023-11-13/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "b582686035b5ab0b855886feaa11a6b978cd0b9a1cbefe4afe9083e726c17916", + "dist/2023-11-13/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "2bcbccb51e5d10a766103d132cc10176e0747801a6fc1e3fcdc68b55f8970273", + "dist/2023-11-13/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "979f9c7c3a804552f41836a152fdfd8a68db2c144ff37bba3a85c99c4c7d21c3", + "dist/2023-11-13/rust-std-beta-armv7-linux-androideabi.tar.gz": "e5a563a023c4c90b2908c7de6535e208b412cf8ef67bc870d5a5079d7a2c4ab6", + "dist/2023-11-13/rust-std-beta-armv7-linux-androideabi.tar.xz": "88c84f7196f86a1e20400e9addbf1051ca90c1f6fae06ea711a0f49f5ba3ff1d", + "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "2a164112ad94b3729b39c2dcb5e6e1ac756e2f30bb0730db679a9aa59ad2cc26", + "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "c0eb6162b48266df4747833613ecf2a0234a4a7bf75331459bc230e7b868b676", + "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "2340f23434b411fa3da490cff5a41752d4f557324b3ee28bee2b089030f2e53f", + "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "fa34f4a1dbd757aebcbdd4e3e3de5053ef268b0a9fba7efa47607596f03b9e70", + "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "a9c3505a537f119a261dc882c0979c262efe68a5a798ee860924d0a0ad9ac359", + "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "3cb01b367a700d8ac8df14b6b87a81ff308fa9e4efaa08156ce3ea51b515c2ea", + "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "a57268eeb2308841c947b26c1492c3d9a36fb47408bb5b7909f0c3d4ab84f27c", + "dist/2023-11-13/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "38d8c2a2c7b8770c517f1cf17bba625dbe2f13c6899f61f3156d769a34515fbc", + "dist/2023-11-13/rust-std-beta-armv7a-none-eabi.tar.gz": "2e2d0f38992ef60701d1ea6ff647f72039e6a7fb483bf9ee4b341120e1d6df43", + "dist/2023-11-13/rust-std-beta-armv7a-none-eabi.tar.xz": "5a3115daef7c1d7138baa27e7bdc9ec3834fcab9e910ae2cbaec47ea833b8318", + "dist/2023-11-13/rust-std-beta-armv7r-none-eabi.tar.gz": "bb61701c8cdc26851b3939db5d9f965bb8167be3d681e006a1a9f0ae21e5a293", + "dist/2023-11-13/rust-std-beta-armv7r-none-eabi.tar.xz": "ca5264eaa211f9fe9fb2a61bb6c7efe9b2ad63a84976ce1a1d0742278003d484", + "dist/2023-11-13/rust-std-beta-armv7r-none-eabihf.tar.gz": "f399d12314de408001e925042b464052809c57c533dafa4694c16e4a4ae1d874", + "dist/2023-11-13/rust-std-beta-armv7r-none-eabihf.tar.xz": "50dd55169e78b93428c19c8dad61e037a019de50cb91ff559c29069de63d8e66", + "dist/2023-11-13/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "e2e512e6a1d5d86ed040c22d7a1fe504ba6f5de30c24065f19c23763cb4c8743", + "dist/2023-11-13/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "3ae3afdae7a52e933e75564476a8b080e414905436fe0e9706932d69900b1fc0", + "dist/2023-11-13/rust-std-beta-i586-pc-windows-msvc.tar.gz": "b06d0dc821d3d67ef20fe1987411b57cdfeb29e6f330d6b9922fd3b854cff28d", + "dist/2023-11-13/rust-std-beta-i586-pc-windows-msvc.tar.xz": "3c22775d9760be3699bfb1f4a0379cbd6838c03e2f8205a85d90c7a476664414", + "dist/2023-11-13/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "cdc0219c4ab66986f4de668b2c7cebd90ccde6958b50ce0dadee81518e67de34", + "dist/2023-11-13/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "09e838ae1922f7170e85c5b95d032f9feae9876f5e11bfc3693624b62b5a358f", + "dist/2023-11-13/rust-std-beta-i586-unknown-linux-musl.tar.gz": "e8b92575033950392e252dd68a0f8da310909bda23b4e40d6323d54211ee2604", + "dist/2023-11-13/rust-std-beta-i586-unknown-linux-musl.tar.xz": "584f829d6f324705c783ad97f67acdb34fe475fed8c4b91817978335d922ba1a", + "dist/2023-11-13/rust-std-beta-i686-linux-android.tar.gz": "0ef6e63ce3999c3035f0fb76bdc314966c4892a0ff7023941b1dc193e5c37a6b", + "dist/2023-11-13/rust-std-beta-i686-linux-android.tar.xz": "67d8dc585cec56aade8fcda986512fefd2c6346f446ab4df0764deb12cee5567", + "dist/2023-11-13/rust-std-beta-i686-pc-windows-gnu.tar.gz": "af77f489643aaf9b38681f038d7b6841122469841f68e1826525849e99081f69", + "dist/2023-11-13/rust-std-beta-i686-pc-windows-gnu.tar.xz": "5456f998f86146cb9a522734eb32ccc75155a10e28f26728909bc5e53e7c7b8b", + "dist/2023-11-13/rust-std-beta-i686-pc-windows-msvc.tar.gz": "2d770b47791453dacf349942b97c9fc8f4cf1c38130a37de6b698663194e6112", + "dist/2023-11-13/rust-std-beta-i686-pc-windows-msvc.tar.xz": "502623d29afe9167e2266b42a89b4224fb232fce73676da71502ca015daf8964", + "dist/2023-11-13/rust-std-beta-i686-unknown-freebsd.tar.gz": "d87ff9aea045e2414e3986227a78b75ac543200063d55022ae08e26e02f62819", + "dist/2023-11-13/rust-std-beta-i686-unknown-freebsd.tar.xz": "3c50e2ac1823ad810c360ff754984d5fa85d108ca38d83158059e95876127d97", + "dist/2023-11-13/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "233e5fac1a76ba28d23a5173e703bd24455307a78ff767dbb049192892dfce0c", + "dist/2023-11-13/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "f307359373a6dc48f5e18f3fff52326cb473c6b17db458c78a640bb488f294ef", + "dist/2023-11-13/rust-std-beta-i686-unknown-linux-musl.tar.gz": "360cecf2a1cd51f88c4da401f27b24f3a6395247b112428df3191990781f4e5b", + "dist/2023-11-13/rust-std-beta-i686-unknown-linux-musl.tar.xz": "d8246447e17987bdb19c6bd500eb575bf9041537fbfef8a6d82c1c98693ce63a", + "dist/2023-11-13/rust-std-beta-i686-unknown-uefi.tar.gz": "b5735aa3bf0c111c5bd652aca5bd8a2249d6a5d8b6152b404cd4f34b82bcd46f", + "dist/2023-11-13/rust-std-beta-i686-unknown-uefi.tar.xz": "f9a8e850c9a72948f31ba398037b389eea987b81213a2d743a04d4b818000e14", + "dist/2023-11-13/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "2eb39cd50a93749af784c634ea757e72c4e24347b7258642481aef73829ab87a", + "dist/2023-11-13/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "f01b91ea400ec0b9e565e2de689ab6ba48c78ef2f91ebccc2cfaf45c1b8cefbe", + "dist/2023-11-13/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "6b141c0f56a27540186a6cc880c3330a5bce099ff002f3681c680c1221a3b1c1", + "dist/2023-11-13/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "8f95e17e81d1b3dd039826f3ca483a570c9086b36c5523c277eaf302d0d6ff38", + "dist/2023-11-13/rust-std-beta-loongarch64-unknown-none.tar.gz": "78526ba4e1e78cdbb6943d8406a5bbc5fb8df2e1890d50d613b33bdc701b1c99", + "dist/2023-11-13/rust-std-beta-loongarch64-unknown-none.tar.xz": "bfb7baf432d1fba29933a55498764a4e563dbb75f444a4ef3e2bce71e25b8f84", + "dist/2023-11-13/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "9216385a85d7085474ce36bfc961b84e6a48ded07017ff5a057f502f6b0c7eec", + "dist/2023-11-13/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "f5501192af94ff399de9e74bd8d87ff37a986d369d3a6ed40fff85ab11d93676", + "dist/2023-11-13/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "2350b2f1bebda9335750671e6716dc6b7cee4897507e828fb8a65cc88a057b03", + "dist/2023-11-13/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "f31c185d7532fdaf4a358ef7ead703623fa3c2196f354eabdc7923f6da44db0f", + "dist/2023-11-13/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "22a03f008b066e0667bea31c0b1702d04c3eb57c34f19b2da6410e15eebb6872", + "dist/2023-11-13/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "8016d83a15e9ea72dc3f453671ae85dfcebfb518d1b306da96ae1a870997b337", + "dist/2023-11-13/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "3b166df751af8d54f4555d70407b2da6ade6972c07400a462680a8a40972691a", + "dist/2023-11-13/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "863da3831b4c6990f68a83cf3067b490e383ff1a33f7113a845a1ab8c2e2b714", + "dist/2023-11-13/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "8b571f65ec378563147a64a18fe202ac76a2c13a6ca2987976edbaa358a0e797", + "dist/2023-11-13/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "79d82bc4dc99af74ddebfc72305b32c1c819d9105c59359bb86b9b07d68db515", + "dist/2023-11-13/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "2ab118b25f237453d3aa68b9288c317e4474a469f4ed5e2f0fa10d85495a7c8f", + "dist/2023-11-13/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "25b9e9f41cfd797ffd25c2f5bfaf4ecb295de95db81e72a265e9d54bd5f41406", + "dist/2023-11-13/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "d6b3e8d853108716a2a9c6779a0ec2e7a496b58f98a27e95a5cfcc4c1acde7c4", + "dist/2023-11-13/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "e0f93c480e505d241ba00f4846d94a667df425800c204fdc0a30db2384012a13", + "dist/2023-11-13/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8cf3de56808a9222c0b59f15616ccfc0c311a6c01c889be0f208ec48c3f92471", + "dist/2023-11-13/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "b46efcf1348f1f718355cfdb4a196001af55248a4c4f4cadf72a159c0369b30d", + "dist/2023-11-13/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "445a73b9646aa7e1bd02789db0c2486ef5b40ae76ba8f79fb7752e8a6e21e251", + "dist/2023-11-13/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "5afe29968b96ea83bb5e9e76b508ba3f51cae9da7c1d5635943b3d5dd00f1340", + "dist/2023-11-13/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "bab78b1672ca3b76a15cd151e9a63941dc226b7a64308290faa21eec777fada5", + "dist/2023-11-13/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "955965774ce971cdcb6b168604e110c7a1226059671d001f551aa1330783f909", + "dist/2023-11-13/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "f0eca14f82d86753444ac617789d4fd922437e62616123d0cdf3593fc2886e25", + "dist/2023-11-13/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "0d4ef0c263c798c5d636519d8893af46eee02339704bdc9c50d04e2029d48f47", + "dist/2023-11-13/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "fb652a85e83ca307eacfbd3155d46ec355bdcd46b2d9c94ae839c6cdbc78c4e3", + "dist/2023-11-13/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "1b8cfaeaf1d5d47760f9ee671b32ebbe81bfaa34074ad7c437602af65e91b1d8", + "dist/2023-11-13/rust-std-beta-sparcv9-sun-solaris.tar.gz": "5e5363302fee2567c27bfbe59a874b9d47c8dd27da502f7b5dda093a8327b936", + "dist/2023-11-13/rust-std-beta-sparcv9-sun-solaris.tar.xz": "fcd48e58e9ef18401d86482636f1bf2dd645e03e3d12896f5ac082ab5dc1990f", + "dist/2023-11-13/rust-std-beta-thumbv6m-none-eabi.tar.gz": "4b7e449d6d81ad8042506d617c27cf3fb3980299cf17a3b6b084f9253c95dfd0", + "dist/2023-11-13/rust-std-beta-thumbv6m-none-eabi.tar.xz": "b5f0cace5ec3a46e5cec31444e9d6340df5ae43584579d1b6171c7c22a925050", + "dist/2023-11-13/rust-std-beta-thumbv7em-none-eabi.tar.gz": "ebbe4cb796fbe017d0ceea0be022c1a6e6166e66eff943ac9aac548474ba774d", + "dist/2023-11-13/rust-std-beta-thumbv7em-none-eabi.tar.xz": "416e127948af40411b0063e677f2b212a46f784c9a15db9e4f762a487692ba07", + "dist/2023-11-13/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "5737d11a1a1ddb39dbef8f7f3feb752e396cda780180ebbf8d27be015a0ad2b1", + "dist/2023-11-13/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "616c5ffc3410720a3b4fbdbfca8399750bdccc5dfdb9e2a5eac52400186baddc", + "dist/2023-11-13/rust-std-beta-thumbv7m-none-eabi.tar.gz": "57f785f8ded6d3cfdf63658474f3ac65e80cdb00dae57f83a2d40f2c676491c1", + "dist/2023-11-13/rust-std-beta-thumbv7m-none-eabi.tar.xz": "5bed08004eac3bd3fb77bc47035ea3ae2095122f3fe4b83eb1401ed77d6fbc97", + "dist/2023-11-13/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "698e3213fc2e8a3b1fd2609a7bfe31549166f67768e7db6f0f3b8f462dfdb0f7", + "dist/2023-11-13/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "fabc41d905c2594bfddb7e789ca9ff42039ae43219ad70da73ddde5f3903110b", + "dist/2023-11-13/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "87eed169aeec1e8b3adefd3b3765e563a32fa355202e3110f115460198cd67be", + "dist/2023-11-13/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "f6b9bc666d0ada37ca8e9fb695d971e254ab1487d16923a413297d364f0a7827", + "dist/2023-11-13/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "b2ee2d569a0f4cc9f00d476b6197869bd46e6a25054f910bc997d4a47cd216c6", + "dist/2023-11-13/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "04e619d6cc94478bd474f97402ef0147e02078c5f24b4f9c3ab2d904a09cad62", + "dist/2023-11-13/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "49e2121df0ea56468be58522fc74c047b3bee7390242900575dfbe65edb96f54", + "dist/2023-11-13/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "ee743c99bfccb84fca2a1ffb569f1674b5e1710d7b670e3e62cc184c12bd61a6", + "dist/2023-11-13/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "cb9f8fd4fc4f2b27be37ec3777cd64bc638584b1744292b10af969bfb1b50f78", + "dist/2023-11-13/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "d62839e513f8a1fa57b97453d7bf6b15f85616828049a36d74d4de553e5b9856", + "dist/2023-11-13/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "ef29dbc48b483b4e8264e03d9869a87eb5f60f7f7f28dcca1361fadb54b79cdb", + "dist/2023-11-13/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "155f3844de6b49f5db34265320f4f94e45ac0f12f12000589d3a17cddef3ccce", + "dist/2023-11-13/rust-std-beta-wasm32-unknown-unknown.tar.gz": "e8a74c1a40b9bbe0d062d57d7169931d6d32b17ad0c82bc007cae16d400851f3", + "dist/2023-11-13/rust-std-beta-wasm32-unknown-unknown.tar.xz": "20521840fd7d292aece540525ccd11f9179700d3bc5c3be5403b032867e87afc", + "dist/2023-11-13/rust-std-beta-wasm32-wasi-preview1-threads.tar.gz": "7c090f46555efca8a60cf028321756b44ce7a27555204d114fc2661e64f2aa9a", + "dist/2023-11-13/rust-std-beta-wasm32-wasi-preview1-threads.tar.xz": "07b638d2f77fbb4286dd26537a8123fcf4a66f3bd065e541dc736536507127bd", + "dist/2023-11-13/rust-std-beta-wasm32-wasi.tar.gz": "089a845111c76efda5f50d84f3ab796f7e00a6710031a8a3d077d00414823637", + "dist/2023-11-13/rust-std-beta-wasm32-wasi.tar.xz": "1017d96927a3b65d8425e0c79320960b763ff9af3d31ebf71bf6ebcdcc7180d6", + "dist/2023-11-13/rust-std-beta-x86_64-apple-darwin.tar.gz": "98ce9ca7ff9a5d31006196bda22710f4a476b50f1e18759465c6026dec85fd08", + "dist/2023-11-13/rust-std-beta-x86_64-apple-darwin.tar.xz": "52d3637b78762c064e0548850e1ec5854fc0e98d339d7ae7d301ea9bb254ca3c", + "dist/2023-11-13/rust-std-beta-x86_64-apple-ios.tar.gz": "459b9e2b063afbb3c3014c9b6259ee5b3f774c4592393c22090dc1764b2a4eb4", + "dist/2023-11-13/rust-std-beta-x86_64-apple-ios.tar.xz": "3f8125a3565ff9f1bc4e528d6b23c4edc5bb12568418d88ca27ae4a0772dd6fd", + "dist/2023-11-13/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "8d35128421e601daab5fb5bbf2e3f5f23b18453efb39b71d54b36a15ba54c3f6", + "dist/2023-11-13/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "0f6b3cabefb9bc82eb4d8438524b3030a26053cc9b340f2aed4e68270c832c71", + "dist/2023-11-13/rust-std-beta-x86_64-linux-android.tar.gz": "5816f58ee8cbb0832357220ae4d25b87fde5090305a2298f3804faf1d0c87e85", + "dist/2023-11-13/rust-std-beta-x86_64-linux-android.tar.xz": "c0df3bc87d839b95bc1a5f69e2211020c183922a6d65508df90d60371f10e4a4", + "dist/2023-11-13/rust-std-beta-x86_64-pc-solaris.tar.gz": "d4a929235c25fdff8331e359612c6e2158b9984ed5b1a2d22d135c9ff714ad52", + "dist/2023-11-13/rust-std-beta-x86_64-pc-solaris.tar.xz": "d807cf6b57c12c9ab9baa703d2c38fb8817a185c0f1a3d846173d46c83f591ea", + "dist/2023-11-13/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "01e0338a3d36292ad73490c29e8ef11694dbbbc43eeb42faef2b4a824fd2f82e", + "dist/2023-11-13/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "5ebf0b26f4ece70aea9146c48eb2733fc517f387919842d5ec7caede5a7b4295", + "dist/2023-11-13/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "799e830f3151d8227e4c2a2c9c7f68706459b6d39fd9cb1041b3a87628cd7c58", + "dist/2023-11-13/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "4cd37d3f6214d120855ca215baadb9483218317dfc345bd390c86082d9801dfb", + "dist/2023-11-13/rust-std-beta-x86_64-sun-solaris.tar.gz": "b573908c72c8a11c879fc9b97d956f599e5642d38aed8a0a7dac68f988e0ac7a", + "dist/2023-11-13/rust-std-beta-x86_64-sun-solaris.tar.xz": "6493f17b04ea8817693a85268cb21e0b47f95edd4fd00561e104dccdae66812f", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "5dcedf3a1a8c12602932bc6683987a75db68a381019bad8207414843c35552d0", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "28c43fb5b7bf4c254ef61c5bc39da09e81881e01261a8a3346968170c8774581", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "85f5052ba7d38dc951bbfbfa6f0d932866a8b49f54457ca1611804b1d9014ce6", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "fbac8d59fd510bd5e4978fcd8e56a1e73de7140726df9c3106784496e744848c", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-illumos.tar.gz": "289dfdbd7607d2275b0ac57ceadbda7ea4c060636f007685e66d7a7170494ad7", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-illumos.tar.xz": "7d3a1849998b3212f226bd9c0a3193c0abca814d73edd0ff3c041d6b2338bc18", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "4d9e48adce6450cd114bf7509694c5ab7bedbf06210a9abd5461412617934133", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "f96c3b0bd75f15b8b6b9a6326c03ff5b4ee9aa16eaf426fdeb2e2213297854a4", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "6c4c00e554ff08bf6fc79df4790e3315c703bd789634f0dab01901a3527ced74", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "7f94911e59d0e7ca49f810124358d6ba8247df2136db1415216b90817200e91e", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "6408769d5540cc5a8cf741886ab9079184ff5562c6761d40b19874dbbc137e0a", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "a6b25bc4020a9f3ed59b16ee8e26ba8deab3d32dc3f771452e21301d1e9e905e", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "ad01d75532a0a05890e69c2d3a77b0c871a5aa50acda7cefce0654a2b634ad27", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "7eeb9cdaba6ffabd6f1aceb6c2eac354bb237b606582f6c88a754bedf5987735", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-none.tar.gz": "2e3292d36d8ce3b383b220106513a5e7cd7e90160c9326dd6d0960678b4b961c", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-none.tar.xz": "078cae8dae258af5fccde5efb2ce3599f5c1cb4a0aac05a9bb7e215e85d19cf7", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-redox.tar.gz": "7f6f2e63a6ef9501630dc02c8a66e805a1d8cae3e457d163cf02c65d3be213aa", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-redox.tar.xz": "0174212e92efc759ae9c75f9a32743a03029b7292f5b6b604b57ed8be9c58304", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-uefi.tar.gz": "228fe781f4206dd1cd22210c22404087eeb5a56b3a56adb9fda90100cea87efc", + "dist/2023-11-13/rust-std-beta-x86_64-unknown-uefi.tar.xz": "4515744a3dcbc08ce672efaf4589874597e0feae691d14d6ba9050c56c8098df", + "dist/2023-11-13/rustc-beta-aarch64-apple-darwin.tar.gz": "4bdddcb1c681df3203a723dc31e683ca0b517d8fec2e98cfde24550c375b3d79", + "dist/2023-11-13/rustc-beta-aarch64-apple-darwin.tar.xz": "28e922e7c6b08c6a33e25038fb86773948c5131a4360a000b488d1be9cf14fba", + "dist/2023-11-13/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "8a10a25a15e933d9807859e58bc1dabe1d3cce515148a91ccf767369b385e6c3", + "dist/2023-11-13/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "8a842f833c006b361bf10e6b68c54a86744c4dde9248d7a2240cef6a46761548", + "dist/2023-11-13/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "f8cf7a5a8ce11f260eb73b2d2fa06714263e3d5355e7dc1288e2bbc2407cf64b", + "dist/2023-11-13/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "4426e7b5da73ff357094f07f0f5dfafa7a627daa3c73101d9424a174acad4794", + "dist/2023-11-13/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "21d8b92246382c25630fd0bc462a485becb309027414311d64268babcbfaaa63", + "dist/2023-11-13/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "221d51e77fbc6af202563fdf557631f75064e5ecd7750cfdf03a9dab6e7748a5", + "dist/2023-11-13/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "659197905941615e7cd8e2c41a09699b0df9ff4540b514e942e66b0e0acb02cd", + "dist/2023-11-13/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "5624af4e8f4f2cb0c11d504d4d1514a75a2c5e35a5fee9e2888e12d6dfd5fa76", + "dist/2023-11-13/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "27bb3004bc4dd6822b67de5f05c90850b1b8b0f0702f1685a572fcf416dd04ab", + "dist/2023-11-13/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "5102179b53fbaa0c416d5305c8b76be4e7ee707d840ab5ccc0a76335debc236a", + "dist/2023-11-13/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "493076756274e9c588700821abf39193c7d7ee51f41034db773f649ceeceb530", + "dist/2023-11-13/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c487bdb531c75d273026c256a4e5d126aa68ebeb40e2eb602b7b232719e76ada", + "dist/2023-11-13/rustc-beta-i686-pc-windows-gnu.tar.gz": "158a1e8b326c5077c335cac2d031d266d7d5db04a1b2e9d76c9081730166a6de", + "dist/2023-11-13/rustc-beta-i686-pc-windows-gnu.tar.xz": "ba0306b06819ee34b62edb40c9e78a60ab58d6de0493af1bf2dd72ba2d31ae38", + "dist/2023-11-13/rustc-beta-i686-pc-windows-msvc.tar.gz": "0188d1e4f66dc89611b9567356b9fcbe633a857140ebba83ba43c99c22353c6c", + "dist/2023-11-13/rustc-beta-i686-pc-windows-msvc.tar.xz": "1f66b7976350cb06ea1d7e8869c0276676dc82ebf1d23c57adf37c2b36da1c93", + "dist/2023-11-13/rustc-beta-i686-unknown-linux-gnu.tar.gz": "6646a59d419a19aa9fadb55c12faa93524a85e3e1d7f0e7e20ad8007757fbff9", + "dist/2023-11-13/rustc-beta-i686-unknown-linux-gnu.tar.xz": "7fa6483a4bb592ea4e86b7ddbb9e938aceb2fee0ad7a4106f415eed66699bf97", + "dist/2023-11-13/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "965c3f1a939386134e563f8c6fd5399221b8bf47f52d62fd640276762ff94dba", + "dist/2023-11-13/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "a956879fc43f02d6f3558494c59fbdd67a93d0a51f44a85247cbb0f69a9793dc", + "dist/2023-11-13/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "4474c8e5d3b1931c5330f7b337dfe093110d006466a846bc8b7e06abb9497e67", + "dist/2023-11-13/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "a7dded69245f0b007f6ed5c803cc886d04fdff68884c44e426df3bccc00d9dd3", + "dist/2023-11-13/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "c35144e8205a84e48ff5b32fb7c363d8a18d42f873b47b0a54189f32a422c462", + "dist/2023-11-13/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "22f8c6f103806968ec4dac5a53581cb862cda6b291864e555a93f908971f87bb", + "dist/2023-11-13/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "5eb310b5a54135e443fd7aa571815e289a1bd0f96f2bca1ad719cf156f382531", + "dist/2023-11-13/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "7fdbc3fedaa77d12b04dc9b9602a44d45eea72d29642f1112a839cc90d72c262", + "dist/2023-11-13/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "7e936ba6928cd7116045f9c0dad358661fa867fe32c62c0815a8b392b64ea9fa", + "dist/2023-11-13/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "dd41b7b468837fd8a96dc37c99ad5a29edf185df38b0f82e5582a6200aabc564", + "dist/2023-11-13/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "3bc91d1003d07f9378317cf38eadcba4c69c65c34cf73016ab524f63b5ae77c2", + "dist/2023-11-13/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "30022ac67369c112725c8e327a76100d438ffb3cab27bbe3fd62316de60af5f7", + "dist/2023-11-13/rustc-beta-x86_64-apple-darwin.tar.gz": "848549ae18928e8c2ceafa986fe99d3d103a5a97348f4ed9cf9825096e44d6f8", + "dist/2023-11-13/rustc-beta-x86_64-apple-darwin.tar.xz": "00f5ea9ee85bfb85ff66b1b2ce9b04207334cc731e33b7250d1593f92abb9b63", + "dist/2023-11-13/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "0fe8320e4c07636743156943851a17c606d32f79a773a394983021f987bf33ad", + "dist/2023-11-13/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "b61d7f52522f0576e71ebb1d83b995085b020bc00b3423078210239ebcf2f954", + "dist/2023-11-13/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "e2da8e7a2d7f9a558bdbb4f56273e139ea26dd6778d4006479890163c52dbf9d", + "dist/2023-11-13/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "4ea59ac07b85078514af502538535c1ef98799eb574d2036752ed608353266b2", + "dist/2023-11-13/rustc-beta-x86_64-unknown-freebsd.tar.gz": "5870b4f26a3f47ecc8cf5eaf0e5f062087f71dcd94cedb420e402724a5d340c3", + "dist/2023-11-13/rustc-beta-x86_64-unknown-freebsd.tar.xz": "c2094e3b40e602ab804e875ec1b1ab7e91f0ff499bc6c1e4b2a957ed4d136ab8", + "dist/2023-11-13/rustc-beta-x86_64-unknown-illumos.tar.gz": "ef47a9f5bb410eeb8361db7a71bb3faed4f71024ad0659c359a20346e75fc7b6", + "dist/2023-11-13/rustc-beta-x86_64-unknown-illumos.tar.xz": "444e9b6a42b3219bc2c556b9c2b1c20d8ab6411662fc55d76ee0b1775321cbd8", + "dist/2023-11-13/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "f492e76a0ad4182607d27145ad45bb8ba6f41fa194dc7a2dec121cdb7fafd918", + "dist/2023-11-13/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "898c58f43f6bc8f259a87dfa7f57c88f1069883604e927f4e1f4808ac8969838", + "dist/2023-11-13/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "fdf79b4d8aeb5b846caeb19ba7bb4b7e614cc4cb48d3d129470ee2c914afcc85", + "dist/2023-11-13/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "17666599cd367e20a1439b91ae19e3d3214c6aed5ae36016efe34938e9e6ddde", + "dist/2023-11-13/rustc-beta-x86_64-unknown-netbsd.tar.gz": "e3085637e043c5bf132411cea9421fbb6f062fa6dca6b73592512dd739d94cc0", + "dist/2023-11-13/rustc-beta-x86_64-unknown-netbsd.tar.xz": "ac4d1228639906c873f5ab4c12b770ea2c053380e68e46d0afa70bac48cdf16b", + "dist/2023-11-13/rustc-nightly-aarch64-apple-darwin.tar.gz": "1b113b6dc4c3bb4997be30a939f3ef1d699c5052d7387da92a7d17a5bbb3de98", + "dist/2023-11-13/rustc-nightly-aarch64-apple-darwin.tar.xz": "2ae2b64171c7ad6fe7c769a3507900ff024cfc6f621b4d566022000ba1d0febf", + "dist/2023-11-13/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "b7617099a6409b869f0b186acf775df723c11d0c625db9bdedfa2ef45cefe5db", + "dist/2023-11-13/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "e73652ac663242b0e10abdec32234ad6fb6c899bb5251488d7b19b17c8ccdff9", + "dist/2023-11-13/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "6569fab33d672526354484ec648a7e3287b3c1e43420e11a8e15fe9d5b3d6bc4", + "dist/2023-11-13/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "215070976901d265554415ee06df6f377691fbf9287548379a31dcb4beb52042", + "dist/2023-11-13/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "d3b0eec2524ae12b5c62f3d8e7ec924063e5a867975bea3048b14af2e04a60e9", + "dist/2023-11-13/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "222e74a5a6d0564d81d97a2c95e9aeeb0f17201505f18f6a073f6ed7d6167148", + "dist/2023-11-13/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "20de495b3f5140777d268fcfb17031ef0ee6b28ba483612f8d8544922d42c1eb", + "dist/2023-11-13/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "2eb1a8ba2d86fd43a3276e676524a2d34bfff9b12c8531308e5c9ef3a47400a6", + "dist/2023-11-13/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "7e3b4243ada8f8d2b95c8e3920dbb92c5712a14033128bb3b5ce65ff83998d7e", + "dist/2023-11-13/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "bc6261b5cfc43a2f5d308dd086cad7d4c983cb4b8e57843789fb6271c2221d07", + "dist/2023-11-13/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "366dbc3bd8290cbd17cf831dca5e75a6b92c8b2e256c4cdbf98f6cb13d857538", + "dist/2023-11-13/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "a6584f803d16b4338c1d2535d1ba359932e4d7b539953b579c39c5171f902ea7", + "dist/2023-11-13/rustc-nightly-i686-pc-windows-gnu.tar.gz": "095b37bf7bb69726ff58296da5b597478a5af64682d8e69b7076154123c758cb", + "dist/2023-11-13/rustc-nightly-i686-pc-windows-gnu.tar.xz": "5d5727b6b7c52b7d46a161e31c2637f8de33080ff92424edf1a287d4499b33e2", + "dist/2023-11-13/rustc-nightly-i686-pc-windows-msvc.tar.gz": "06b287a308d728c990c1f7e63dc33e90823a2e74fed57cde8e6c1de1e265a26e", + "dist/2023-11-13/rustc-nightly-i686-pc-windows-msvc.tar.xz": "4f5a923e4193280cd5acbb81e6d578d55b119085963a7915e89a2c9c324ad550", + "dist/2023-11-13/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "2a9b18c971ddd81ce45162d224f3d83954f47d2e4f20c9259aa2f03840b4c42d", + "dist/2023-11-13/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "40769cf6e32903769166a1d47a99de93052c820e53770b7d253452c0f5122e1f", + "dist/2023-11-13/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "67eb782c10ce7abc56124f789023cebc5772a01f1ef1adf107a90120a4f065c5", + "dist/2023-11-13/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "eca35c310f253e95aa324ab8772f1ab6335020e609f632162707222bd9a0de35", + "dist/2023-11-13/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "218a990d7d01b093e59bcfaed89eb3b53d4a50d5e3a82f53e079df11660ed2a4", + "dist/2023-11-13/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "007cb6841bcecbe98bbff8b3542cd39afec275fad5d2eb45af733409b6b4802b", + "dist/2023-11-13/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "765aa9f6aaed661607ad4a54015df14b67da611a99efcf080036116467c2ca0d", + "dist/2023-11-13/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "8d3ff5b8df0befe504be38d8dfb0807980e2be4673f244c4633e3c5d118ce4d9", + "dist/2023-11-13/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "0e74f7782fb99fc29e663634dd2f08cc47b50f714e04a8544eef4eb4defa4db8", + "dist/2023-11-13/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "b1381bc7ecb0c08e65ff32152681c0007a55117df2f52f8cb33cb4abea7f14d7", + "dist/2023-11-13/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "69318b9a4f6e1da3e6751e6e4e089a2180cd4068f54a4e965f9fae8a45bf9c89", + "dist/2023-11-13/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "7c64b2d0a8a9d24ed41235e17e45e75668dca40ef32cca47a9ce428de94a2922", + "dist/2023-11-13/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "44fd98bb055b90813a346592b7dbc40633b339de09fa1184cc177968f08efcd4", + "dist/2023-11-13/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "c968ae5d316b3783af6449fbabbf034743711175cdce7922734034b7916ad251", + "dist/2023-11-13/rustc-nightly-x86_64-apple-darwin.tar.gz": "e0540ab928f55092b8e70426bb7d098e74cabbedcebe6ff77ab485262cfedb5b", + "dist/2023-11-13/rustc-nightly-x86_64-apple-darwin.tar.xz": "c37789b8a4f187492506e340a679cfc047332ebf5694ae764cb2474afd1281bc", + "dist/2023-11-13/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "e0980059f71c1af5388c65f6f8f317bb55c5788a7bfbfaf472358f30faefb14f", + "dist/2023-11-13/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "39a13cf1d38638bdd98355f2494221304fd9928558719a2dc36e06699a97dc68", + "dist/2023-11-13/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "6e22b7936652eec3ac0c1da277ba9ef89d805defc4fc3abea61f2ce68bcf784f", + "dist/2023-11-13/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "464cf4f724210a72cff14a6924ffd896cf160bc7ab8831e3580593a2f7e54a31", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "c3a0ef4295a245c46e39c6a644a9a237e81dc95443930ec4230227b8bbdf2927", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "6cf9e31f4e5a5276c426b3a3ba6d9ba1f9c7b253d30fb2dacea92c9dba19c53d", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-illumos.tar.gz": "15cc5b822d9fa3d832899a07f5a373c6705907f26a5d90c97cad472eb6fbb383", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-illumos.tar.xz": "5cf0eb4e4dc8cf25c02fa8cb9bb60c27212a77088a6fde5a97a6dd11d21b9c5c", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "dbdbe9ad1b19a9f746d1831fb20be9581dbe7701544bedccb08458fb89719c33", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "e1d08f9cb45c86de3217d8c3bb7fa6f7ef201ac826b19b2750aa770f6b665cac", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "2b30ecd41818e8e39b286bf1ea69353416bf79b38f3119bdb98c2ac4594a5f76", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "ad42102fab1902fc1273e776345cdda9e40a5a39574421397405b7657741128a", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "a7b7dcf01dedf0c88443ca2baa49b84ff2027b8bc68502af0f53647fe2005bdf", + "dist/2023-11-13/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "27410cfafe573d12e7fe5c2649cfbb6487a8df172867bf665bf3b3d67dfd44ef", + "dist/2023-11-13/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "fe2710bc7ab0f0a5e4797b011ea47ae797ae3824bd03d59d8c5a92222f750703", + "dist/2023-11-13/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "3cc0c843aa31d9262aff93b597673fe5c0a78bc9fc66a92899c498f566dca806", + "dist/2023-11-13/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "31d23f4bb53bdc6b93a07e50de1a8b5398c5f8e747f4da6b6bafa499a6ef9b83", + "dist/2023-11-13/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "b4d8b84c9fbe2635fb88c9d26a6f86b51651f07a2f8f139d332b49749e364525", + "dist/2023-11-13/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "dd24bd46bf4c24678d7bbee6f7b8e3bb6417131acb3f19c8293b84658e259d37", + "dist/2023-11-13/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "77cfd74f88a8266e3540bec0a4ea669694cb171145ee368158953d47ca74106d", + "dist/2023-11-13/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "63c3c7d5e72813514df27bed4d9daa2d3eefbc50176dba2ae48cc1aa85bd58d0", + "dist/2023-11-13/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "d01d0ce2aa536d635f3d69f6ca7c15b351a2dbace08a1c2aaf8718e6ea07829d", + "dist/2023-11-13/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "8eb1391c5657980cc8a810c1d5b14a28421b4bf81511e4a6e31a3aef15f2c689", + "dist/2023-11-13/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "9eac418607a5f9b1818439a608179ab907a0c2333ec05b18fcf6a36c0d1f67d9", + "dist/2023-11-13/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "d1221f9a330abfd4ffaec357d589148e0484200328cbc1db3224096be012ab30", + "dist/2023-11-13/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "51b2891e0296ce41fa57468cb97b9bb4a3e0a251ba7a5095ad828e5aa175d8e4", + "dist/2023-11-13/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "0d1c59d8947b77f2078122a3fc9c53b3179ba87caea53fa9156d3af913ac42fb", + "dist/2023-11-13/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "607811fe589646c251f14ea1981465000259605e9ddff8ffccdfd0936f851d16", + "dist/2023-11-13/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "044e8b5bff3a8d3259023706c0ef03c8068704534dd8f804c4f53466e35807eb", + "dist/2023-11-13/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "a27ea67409922132ab294a734828980a279ab5cd8a3d8c26b590e313e7da2ed5", + "dist/2023-11-13/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "0bd3c933ed3345fee541549127e20dd63f52a533f2f22523d1db096132ce0aaa", + "dist/2023-11-13/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "4334d49822f9a85d43fbfa463b55d4b9c424ef058c4146852a252162fdbc198e", + "dist/2023-11-13/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "5015ca31e974c16050e44c6ac6dffcbfa82b7532951842dd2745139463c5edb6", + "dist/2023-11-13/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "40380de3945ea3dee9dd05e4dc2d2c12a7d621d9bdfa59233faa2437e80db915", + "dist/2023-11-13/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "478ebf6629bf890c8d3726f090b8fcbc9cc5d5d828ec3554287668491e2bbf8e", + "dist/2023-11-13/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "3a130b2b7e06f6c16325bf36b8f5c702335c745471bf946a9d0ac2202af65fbb", + "dist/2023-11-13/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "002db7233067339672abc2e210d98897a3870842cbf1e487ae5c111d5bc949cc", + "dist/2023-11-13/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "a514b43eb0c1d8e2d20b6ff77b611e126d06522758f6d31b6fbd94639a6f04aa", + "dist/2023-11-13/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "7d21d10b85ec4f720ffca74184758eb568050776f1d3592dc65075b9c83c9f8a", + "dist/2023-11-13/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "2a335532b528ca936903bcaacfec2f34ecb37ddc88bc8c0762fb12c1bdd71d9c", + "dist/2023-11-13/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "73f983755c3f413abb0be9112776ee4ea3a6a122abc37e4f0aa81021dc7dd67a", + "dist/2023-11-13/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "dc164f3dcc898851265f3353f0400953637ea7b5684e91cac6961c2dedb50d03", + "dist/2023-11-13/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "b81877958bad0de48add2148ced0cbee5a66233386d0b50e9fef6ea844ac808d", + "dist/2023-11-13/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "4f755394b456a00a929d89aaa7814e70882f7ffd62489a833be4707ae687c465", + "dist/2023-11-13/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "8d1a9321201939ae453f21fdfe9498e1edcad176b9490531655f47fe7c3c9269", + "dist/2023-11-13/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "1fa1f0161620cd73e1a0bf39ab5225c77e9f3e0888cc0d59b71dab260f7cca9a", + "dist/2023-11-13/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "b6bd3c9eacbb7d10d16e82a9946a77442495259951705dd7c9685f02919c1c0c", + "dist/2023-11-13/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "777f05162f4c6396cf0ca75fed5ff37539534f179a399e3032f0b1b327cf53fe", + "dist/2023-11-13/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "dd5c0eccf137eb8c92211c062057b7fd4a8c49d60953498d3b123d91e1359e29", + "dist/2023-11-13/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "9d90e65fd32c86c77e96b0c46d47d1c2a04090f22d1ba3934bd0507fb8fc09c6", + "dist/2023-11-13/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "a33338f00147ee970b14cd24be361216d3f9ffb963952aa8c5b6731fb6cb3505", + "dist/2023-11-13/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "399cb9ff66482ec0200b4c8750d344ee77900972838b11895f9b542a43e75931", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "46ff40a2afdd62b0b9e3d39ba1ca7ba43a9719ac23cb7b8ec324f0a60859805b", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "c14de41967e9b30a166516944c399f490be89cb9217255e9d22d33fb03489d9a", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "df917224a72d311e8e26632413507dce4e4d3203c049545959c481905939da37", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "1f19725221ec719718a5836bd911f0f04e4a604e71d2557ff28713e5cc58b8e8", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "cb50baa37637b79cda8e7f7fd6a77fedde6ede21063fc3c01c7c61558998df4f", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "a1bf9051bdd85fa33041b84378af684ed974671f17694e00d6f370a27b0563d9", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "5a2df248d0586d4ea49dceaa9400ee9ac4b0cb1a97076b6ec366a9b55217fee9", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "06d4e6d2a909cefef0988d4ef35cd9ae6ed6d87b83a08a91ef2966ebe5989803", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "aba0a7d2d67413990bf0ae9b8f4fd580a43f708b01ae8403fce0c4eff1f35b54", + "dist/2023-11-13/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "53891c1cbf7ff0f648188a655a6dd7c253997f230f4bd7eaa1881bce54128be7" } } diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 2c795ebb21487..9ac97236f19c8 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -50,7 +50,9 @@ static HOSTS: &[&str] = &[ static TARGETS: &[&str] = &[ "aarch64-apple-darwin", + "arm64e-apple-darwin", "aarch64-apple-ios", + "arm64e-apple-ios", "aarch64-apple-ios-sim", "aarch64-unknown-fuchsia", "aarch64-linux-android", @@ -82,7 +84,6 @@ static TARGETS: &[&str] = &[ "armv7r-none-eabi", "armv7r-none-eabihf", "armv7s-apple-ios", - "asmjs-unknown-emscripten", "bpfeb-unknown-none", "bpfel-unknown-none", "i386-apple-ios", @@ -123,6 +124,7 @@ static TARGETS: &[&str] = &[ "riscv32im-unknown-none-elf", "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf", + "riscv32imafc-unknown-none-elf", "riscv32gc-unknown-linux-gnu", "riscv64imac-unknown-none-elf", "riscv64gc-unknown-hermit", @@ -150,7 +152,6 @@ static TARGETS: &[&str] = &[ "x86_64-linux-android", "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", - "x86_64-sun-solaris", "x86_64-pc-solaris", "x86_64-unikraft-linux-musl", "x86_64-unknown-freebsd", @@ -266,6 +267,29 @@ impl Builder { // channel-rust-1.XX.toml let major_minor = rust_version.split('.').take(2).collect::>().join("."); self.write_channel_files(&major_minor, &manifest); + } else if channel == "beta" { + // channel-rust-1.XX.YY-beta.Z.toml + let rust_version = self + .versions + .version(&PkgType::Rust) + .expect("missing Rust tarball") + .version + .expect("missing Rust version") + .split(' ') + .next() + .unwrap() + .to_string(); + self.write_channel_files(&rust_version, &manifest); + + // channel-rust-1.XX.YY-beta.toml + let major_minor_patch_beta = + rust_version.split('.').take(3).collect::>().join("."); + self.write_channel_files(&major_minor_patch_beta, &manifest); + + // channel-rust-1.XX-beta.toml + let major_minor_beta = + format!("{}-beta", rust_version.split('.').take(2).collect::>().join(".")); + self.write_channel_files(&major_minor_beta, &manifest); } if let Some(path) = std::env::var_os("BUILD_MANIFEST_SHIPPED_FILES_PATH") { diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index f20b7a2b4d729..b91dc38e9248f 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,6 +1,11 @@ use std::process::Stdio; use std::{path::Path, process::Command}; +pub struct GitConfig<'a> { + pub git_repository: &'a str, + pub nightly_branch: &'a str, +} + /// Runs a command and returns the output fn output_result(cmd: &mut Command) -> Result { let output = match cmd.stderr(Stdio::inherit()).output() { @@ -27,7 +32,10 @@ fn output_result(cmd: &mut Command) -> Result { /// upstream https://github.com/rust-lang/rust (fetch) /// upstream https://github.com/rust-lang/rust (push) /// ``` -pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result { +pub fn get_rust_lang_rust_remote( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { let mut git = Command::new("git"); if let Some(git_dir) = git_dir { git.current_dir(git_dir); @@ -37,8 +45,8 @@ pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result) -> Result { /// This could be because the user is updating their forked master branch using the GitHub UI /// and therefore doesn't need an upstream master branch checked out. /// We will then fall back to origin/master in the hope that at least this exists. -pub fn updated_master_branch(git_dir: Option<&Path>) -> Result { - let upstream_remote = get_rust_lang_rust_remote(git_dir)?; - for upstream_master in [format!("{upstream_remote}/master"), format!("origin/master")] { +pub fn updated_master_branch( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { + let upstream_remote = get_rust_lang_rust_remote(config, git_dir)?; + let branch = config.nightly_branch; + for upstream_master in [format!("{upstream_remote}/{branch}"), format!("origin/{branch}")] { if rev_exists(&upstream_master, git_dir)? { return Ok(upstream_master); } @@ -87,8 +99,11 @@ pub fn updated_master_branch(git_dir: Option<&Path>) -> Result { Err(format!("Cannot find any suitable upstream master branch")) } -pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result { - let updated_master = updated_master_branch(git_dir)?; +pub fn get_git_merge_base( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { + let updated_master = updated_master_branch(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { git.current_dir(git_dir); @@ -100,10 +115,11 @@ pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result { /// The `extensions` parameter can be used to filter the files by their extension. /// If `extensions` is empty, all files will be returned. pub fn get_git_modified_files( + config: &GitConfig<'_>, git_dir: Option<&Path>, extensions: &Vec<&str>, ) -> Result>, String> { - let merge_base = get_git_merge_base(git_dir)?; + let merge_base = get_git_merge_base(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { @@ -122,8 +138,11 @@ pub fn get_git_modified_files( } /// Returns the files that haven't been added to git yet. -pub fn get_git_untracked_files(git_dir: Option<&Path>) -> Result>, String> { - let Ok(_updated_master) = updated_master_branch(git_dir) else { +pub fn get_git_untracked_files( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result>, String> { + let Ok(_updated_master) = updated_master_branch(config, git_dir) else { return Ok(None); }; let mut git = Command::new("git"); diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs index b007f9a22c36f..bd97b4eaa3e4d 100644 --- a/src/tools/bump-stage0/src/main.rs +++ b/src/tools/bump-stage0/src/main.rs @@ -4,7 +4,7 @@ use indexmap::IndexMap; use std::collections::HashMap; const PATH: &str = "src/stage0.json"; -const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo"]; +const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo", "clippy-preview"]; const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview", "rustc"]; struct Tool { diff --git a/src/tools/cargo b/src/tools/cargo index 65e297d1ec0de..9787229614b27 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 65e297d1ec0dee1a74800efe600b8dc163bcf5db +Subproject commit 9787229614b27854cf73d57ffae430d7c1e6caa4 diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 7044cb8928694..a5d2ffb157238 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -140,7 +140,7 @@ fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf { let status = Command::new("git") .arg("fetch") .arg(test.repo) - .arg("master") + .arg(test.sha) .arg(&format!("--depth={}", depth)) .current_dir(&out_dir) .status() diff --git a/src/tools/clippy/.github/workflows/deploy.yml b/src/tools/clippy/.github/workflows/deploy.yml index f42928c2cd116..999ee7acfe761 100644 --- a/src/tools/clippy/.github/workflows/deploy.yml +++ b/src/tools/clippy/.github/workflows/deploy.yml @@ -52,7 +52,9 @@ jobs: run: cargo generate-lockfile - name: Cache - uses: Swatinem/rust-cache@v1.3.0 + uses: Swatinem/rust-cache@v2.7.0 + with: + save-if: ${{ github.ref == 'refs/heads/master' }} - name: cargo collect-metadata run: cargo collect-metadata diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 87a96bdeba65f..2e9b755caa05e 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,70 @@ document. ## Unreleased / Beta / In Rust Nightly -[1e8fdf49...master](https://github.com/rust-lang/rust-clippy/compare/1e8fdf49...master) +[7671c283...master](https://github.com/rust-lang/rust-clippy/compare/7671c283...master) + +## Rust 1.74 + +Current stable, released 2023-11-16 + +[View all 94 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-08-11T15%3A29%3A18Z..2023-09-25T08%3A48%3A22Z+base%3Amaster) + +### New Lints + +* [`redundant_as_str`] + [#11526](https://github.com/rust-lang/rust-clippy/pull/11526) +* [`needless_borrows_for_generic_args`] + [#11511](https://github.com/rust-lang/rust-clippy/pull/11511) +* [`path_ends_with_ext`] + [#11483](https://github.com/rust-lang/rust-clippy/pull/11483) +* [`unnecessary_map_on_constructor`] + [#11413](https://github.com/rust-lang/rust-clippy/pull/11413) +* [`missing_asserts_for_indexing`] + [#10692](https://github.com/rust-lang/rust-clippy/pull/10692) +* [`iter_out_of_bounds`] + [#11396](https://github.com/rust-lang/rust-clippy/pull/11396) +* [`implied_bounds_in_impls`] + [#11362](https://github.com/rust-lang/rust-clippy/pull/11362) +* [`reserve_after_initialization`] + [#11373](https://github.com/rust-lang/rust-clippy/pull/11373) +* [`should_panic_without_expect`] + [#11204](https://github.com/rust-lang/rust-clippy/pull/11204) + +### Moves and Deprecations + +* Renamed `incorrect_clone_impl_on_copy_type` to [`non_canonical_clone_impl`] + [#11358](https://github.com/rust-lang/rust-clippy/pull/11358) +* Renamed `incorrect_partial_ord_impl_on_ord_type` to [`non_canonical_partial_ord_impl`] + [#11358](https://github.com/rust-lang/rust-clippy/pull/11358) +* Moved [`non_canonical_clone_impl`] to `suspicious` (Now warn-by-default) + [#11358](https://github.com/rust-lang/rust-clippy/pull/11358) +* Moved [`non_canonical_partial_ord_impl`] to `suspicious` (Now warn-by-default) + [#11358](https://github.com/rust-lang/rust-clippy/pull/11358) +* Moved [`needless_pass_by_ref_mut`] to `nursery` (Now allow-by-default) + [#11596](https://github.com/rust-lang/rust-clippy/pull/11596) + +### Enhancements + +* [`undocumented_unsafe_blocks`]: The config values [`accept-comment-above-statement`] and + [`accept-comment-above-attributes`] to `true` by default + [#11170](https://github.com/rust-lang/rust-clippy/pull/11170) +* [`explicit_iter_loop`]: Added [`enforce-iter-loop-reborrow`] to disable reborrow linting by default + [#11418](https://github.com/rust-lang/rust-clippy/pull/11418) + +### ICE Fixes + +* [`enum_variant_names`]: No longer crashes if the threshold is 0 and the enum has no variants + [#11552](https://github.com/rust-lang/rust-clippy/pull/11552) +* [`cast_possible_truncation`]: No longer crashes on values larger than `u64::MAX` + [#11517](https://github.com/rust-lang/rust-clippy/pull/11517) +* [`tuple_array_conversions`]: No longer crashes if the array length is not usize + [#11379](https://github.com/rust-lang/rust-clippy/pull/11379) +* [`useless_conversion`]: No longer crashes, when the receiver is a non-fn item + [#11070](https://github.com/rust-lang/rust-clippy/pull/11070) ## Rust 1.73 -Current stable, released 2023-10-05 +Released 2023-10-05 [View all 103 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-07-02T12%3A24%3A40Z..2023-08-11T11%3A09%3A56Z+base%3Amaster) @@ -5069,6 +5128,7 @@ Released 2018-09-13 [`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond [`ignored_unit_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns +[`impl_hash_borrow_with_str_and_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_hash_borrow_with_str_and_bytes [`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params [`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher @@ -5123,12 +5183,14 @@ Released 2018-09-13 [`iter_on_empty_collections`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_empty_collections [`iter_on_single_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_single_items [`iter_out_of_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_out_of_bounds +[`iter_over_hash_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_over_hash_type [`iter_overeager_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_overeager_cloned [`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next [`iter_skip_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_zero [`iter_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_with_drain [`iter_without_into_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_without_into_iter [`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iterator_step_by_zero +[`join_absolute_paths`]: https://rust-lang.github.io/rust-clippy/master/index.html#join_absolute_paths [`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits [`large_const_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays [`large_digit_groups`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_digit_groups @@ -5320,6 +5382,7 @@ Released 2018-09-13 [`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used [`option_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_filter_map [`option_if_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else +[`option_map_or_err_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_err_ok [`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none [`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn [`option_map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or @@ -5482,6 +5545,7 @@ Released 2018-09-13 [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr +[`test_attr_in_doctest`]: https://rust-lang.github.io/rust-clippy/master/index.html#test_attr_in_doctest [`tests_outside_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#tests_outside_test_module [`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some [`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display @@ -5678,4 +5742,5 @@ Released 2018-09-13 [`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles [`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow +[`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md index 04af1b98b556e..b1a59238c8266 100644 --- a/src/tools/clippy/CONTRIBUTING.md +++ b/src/tools/clippy/CONTRIBUTING.md @@ -146,16 +146,10 @@ For example, the [`else_if_without_else`][else_if_without_else] lint is register pub mod else_if_without_else; // ... -pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) { +pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { // ... store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse)); // ... - - store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ - // ... - LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE), - // ... - ]); } ``` diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 4b6688a76b467..f6084a4627266 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.75" +version = "0.1.76" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -37,7 +37,7 @@ toml = "0.7.3" walkdir = "2.3" # This is used by the `collect-metadata` alias. filetime = "0.2" -itertools = "0.10.1" +itertools = "0.11" # UI test dependencies clippy_utils = { path = "clippy_utils" } diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md index 55c0e105b307a..e30a5f9fe10b0 100644 --- a/src/tools/clippy/book/src/development/adding_lints.md +++ b/src/tools/clippy/book/src/development/adding_lints.md @@ -202,7 +202,7 @@ is. This file has already imported some initial things we will need: ```rust use rustc_lint::{EarlyLintPass, EarlyContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_ast::ast::*; ``` @@ -270,7 +270,7 @@ When using `cargo dev new_lint`, the lint is automatically registered and nothing more has to be done. When declaring a new lint by hand and `cargo dev update_lints` is used, the lint -pass may have to be registered manually in the `register_plugins` function in +pass may have to be registered manually in the `register_lints` function in `clippy_lints/src/lib.rs`: ```rust,ignore @@ -436,7 +436,7 @@ need to ensure that the MSRV configured for the project is >= the MSRV of the required Rust feature. If multiple features are required, just use the one with a lower MSRV. -First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`]. +First, add an MSRV alias for the required feature in [`clippy_config::msrvs`]. This can be accessed later as `msrvs::STR_STRIP_PREFIX`, for example. ```rust @@ -506,7 +506,7 @@ fn msrv_1_45() { ``` As a last step, the lint should be added to the lint documentation. This is done -in `clippy_lints/src/utils/conf.rs`: +in `clippy_config/src/conf.rs`: ```rust define_Conf! { @@ -516,7 +516,9 @@ define_Conf! { } ``` -[`clippy_utils::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/msrvs/index.html +[`clippy_config::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_config/msrvs/index.html + +Afterwards update the documentation for the book as described in [Adding configuration to a lint](#adding-configuration-to-a-lint). ## Author lint @@ -657,7 +659,7 @@ Adding a configuration to a lint can be useful for thresholds or to constrain some behavior that can be seen as a false positive for some users. Adding a configuration is done in the following steps: -1. Adding a new configuration entry to [`clippy_lints::utils::conf`] like this: +1. Adding a new configuration entry to [`clippy_config::conf`] like this: ```rust,ignore /// Lint: LINT_NAME. @@ -736,7 +738,7 @@ for some users. Adding a configuration is done in the following steps: Run `cargo collect-metadata` to generate documentation changes for the book. -[`clippy_lints::utils::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/conf.rs +[`clippy_config::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_config/src/conf.rs [`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs [`tests/ui`]: https://github.com/rust-lang/rust-clippy/blob/master/tests/ui [`tests/ui-toml`]: https://github.com/rust-lang/rust-clippy/blob/master/tests/ui-toml diff --git a/src/tools/clippy/book/src/development/defining_lints.md b/src/tools/clippy/book/src/development/defining_lints.md index 7c4aa5d45239f..54f77b00190be 100644 --- a/src/tools/clippy/book/src/development/defining_lints.md +++ b/src/tools/clippy/book/src/development/defining_lints.md @@ -186,7 +186,7 @@ However, sometimes we might want to declare a new lint by hand. In this case, we'd use `cargo dev update_lints` command afterwards. When a lint is manually declared, we might need to register the lint pass -manually in the `register_plugins` function in `clippy_lints/src/lib.rs`: +manually in the `register_lints` function in `clippy_lints/src/lib.rs`: ```rust store.register_late_pass(|_| Box::new(foo_functions::FooFunctions)); diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md index d7c2775b89690..a8c9660da4c85 100644 --- a/src/tools/clippy/book/src/development/type_checking.md +++ b/src/tools/clippy/book/src/development/type_checking.md @@ -119,7 +119,7 @@ an `u32`. As far as `hir::Ty` is concerned those might be different types. But a understands that they're the same type, in-depth lifetimes, etc... To get from a `hir::Ty` to a `ty::Ty`, you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function outside of bodies or -outside of bodies the [`TypeckResults::node_type()`][node_type] method. +the [`TypeckResults::node_type()`][node_type] method inside of bodies. > **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs. diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 841a5b6d00778..2bb89321cefe6 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -150,6 +150,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) * [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) * [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) +* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) ## `cognitive-complexity-threshold` @@ -791,3 +792,16 @@ for _ in &mut *rmvec {} * [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop) +## `check-private-items` + + +**Default Value:** `false` + +--- +**Affected lints:** +* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc) +* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc) +* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc) +* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc) + + diff --git a/src/tools/clippy/clippy.toml b/src/tools/clippy/clippy.toml index cda8d17eed44c..4a1805f75235e 100644 --- a/src/tools/clippy/clippy.toml +++ b/src/tools/clippy/clippy.toml @@ -1 +1,7 @@ avoid-breaking-exported-api = false + +# use the various `span_lint_*` methods instead, which also add a link to the docs +disallowed-methods = [ + "rustc_lint::context::LintContext::struct_span_lint", + "rustc_middle::ty::context::TyCtxt::struct_span_lint_hir" +] diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml index 2d41087b51d1d..20f313201276b 100644 --- a/src/tools/clippy/clippy_config/Cargo.toml +++ b/src/tools/clippy/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.75" +version = "0.1.76" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 47259776921b7..88611eb70878e 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -249,7 +249,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP. /// /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = ""] @@ -543,6 +543,10 @@ define_Conf! { /// for _ in &mut *rmvec {} /// ``` (enforce_iter_loop_reborrow: bool = false), + /// Lint: MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC, MISSING_PANICS_DOC, MISSING_ERRORS_DOC + /// + /// Whether to also run the listed lints on private items. + (check_private_items: bool = false), } /// Search for the configuration file. diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index 011d54629d41e..b3ef666e3063c 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -23,6 +23,7 @@ msrv_aliases! { 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY } 1,55,0 { SEEK_REWIND } + 1,54,0 { INTO_KEYS } 1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR } 1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST } 1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS } diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs index e898221ffa776..df48cc3f5e391 100644 --- a/src/tools/clippy/clippy_config/src/types.rs +++ b/src/tools/clippy/clippy_config/src/types.rs @@ -1,7 +1,6 @@ use serde::de::{self, Deserializer, Visitor}; use serde::{ser, Deserialize, Serialize}; use std::fmt; -use std::hash::{Hash, Hasher}; #[derive(Clone, Debug, Deserialize)] pub struct Rename { @@ -33,32 +32,19 @@ impl DisallowedPath { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)] pub enum MatchLintBehaviour { AllTypes, WellKnownTypes, Never, } -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct MacroMatcher { pub name: String, - pub braces: (String, String), + pub braces: (char, char), } -impl Hash for MacroMatcher { - fn hash(&self, state: &mut H) { - self.name.hash(state); - } -} - -impl PartialEq for MacroMatcher { - fn eq(&self, other: &Self) -> bool { - self.name == other.name - } -} -impl Eq for MacroMatcher {} - impl<'de> Deserialize<'de> for MacroMatcher { fn deserialize(deser: D) -> Result where @@ -83,7 +69,7 @@ impl<'de> Deserialize<'de> for MacroMatcher { V: de::MapAccess<'de>, { let mut name = None; - let mut brace: Option = None; + let mut brace: Option = None; while let Some(key) = map.next_key()? { match key { Field::Name => { @@ -104,7 +90,7 @@ impl<'de> Deserialize<'de> for MacroMatcher { let brace = brace.ok_or_else(|| de::Error::missing_field("brace"))?; Ok(MacroMatcher { name, - braces: [("(", ")"), ("{", "}"), ("[", "]")] + braces: [('(', ')'), ('{', '}'), ('[', ']')] .into_iter() .find(|b| b.0 == brace) .map(|(o, c)| (o.to_owned(), c.to_owned())) diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index c3f8a782d273a..ce738e3f4ec7c 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" aho-corasick = "0.7" clap = "4.1.4" indoc = "1.0" -itertools = "0.10.1" +itertools = "0.11" opener = "0.5" shell-escape = "0.1" walkdir = "2.3" diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index eeea53ce46f8c..31a42734c1310 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -283,7 +283,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { use clippy_utils::msrvs::{{self, Msrv}}; {pass_import} use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; - use rustc_session::{{declare_tool_lint, impl_lint_pass}}; + use rustc_session::impl_lint_pass; "# ) @@ -292,7 +292,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { r#" {pass_import} use rustc_lint::{{{context_import}, {pass_type}}}; - use rustc_session::{{declare_lint_pass, declare_tool_lint}}; + use rustc_session::declare_lint_pass; "# ) @@ -320,8 +320,8 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { extract_msrv_attr!({context_import}); }} - // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed. - // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs` + // TODO: Add MSRV level to `clippy_config/src/msrvs.rs` if needed. + // TODO: Update msrv config comment in `clippy_config/src/conf.rs` "# ) } else { diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 4bc27fd48e2f4..a9375214be446 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.75" +version = "0.1.76" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -14,8 +14,7 @@ cargo_metadata = "0.15.3" clippy_config = { path = "../clippy_config" } clippy_utils = { path = "../clippy_utils" } declare_clippy_lint = { path = "../declare_clippy_lint" } -if_chain = "1.0" -itertools = "0.10.1" +itertools = "0.11" quine-mc_cluskey = "0.2" regex-syntax = "0.7" serde = { version = "1.0", features = ["derive"] } diff --git a/src/tools/clippy/clippy_lints/src/absolute_paths.rs b/src/tools/clippy/clippy_lints/src/absolute_paths.rs index 582423603eb19..83d15c0c42520 100644 --- a/src/tools/clippy/clippy_lints/src/absolute_paths.rs +++ b/src/tools/clippy/clippy_lints/src/absolute_paths.rs @@ -5,7 +5,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{HirId, ItemKind, Node, Path}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/allow_attributes.rs index e3f4cf79d315c..39fc49dee377d 100644 --- a/src/tools/clippy/clippy_lints/src/allow_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/allow_attributes.rs @@ -5,7 +5,7 @@ use rustc_ast as ast; use rustc_errors::Applicability; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -52,24 +52,22 @@ declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]); impl LateLintPass<'_> for AllowAttribute { // Separate each crate's features. fn check_attribute<'cx>(&mut self, cx: &LateContext<'cx>, attr: &'cx Attribute) { - if_chain! { - if !in_external_macro(cx.sess(), attr.span); - if cx.tcx.features().lint_reasons; - if let AttrStyle::Outer = attr.style; - if let Some(ident) = attr.ident(); - if ident.name == rustc_span::symbol::sym::allow; - if !is_from_proc_macro(cx, &attr); - then { - span_lint_and_sugg( - cx, - ALLOW_ATTRIBUTES, - ident.span, - "#[allow] attribute found", - "replace it with", - "expect".into(), - Applicability::MachineApplicable, - ); - } + if !in_external_macro(cx.sess(), attr.span) + && cx.tcx.features().lint_reasons + && let AttrStyle::Outer = attr.style + && let Some(ident) = attr.ident() + && ident.name == rustc_span::symbol::sym::allow + && !is_from_proc_macro(cx, &attr) + { + span_lint_and_sugg( + cx, + ALLOW_ATTRIBUTES, + ident.span, + "#[allow] attribute found", + "replace it with", + "expect".into(), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs index e85878eb57094..57a5cd8fba818 100644 --- a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs +++ b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs @@ -5,7 +5,7 @@ use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimit use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs index b4f778f12b93b..409ae0c85acfc 100644 --- a/src/tools/clippy/clippy_lints/src/approx_const.rs +++ b/src/tools/clippy/clippy_lints/src/approx_const.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_semver::RustcVersion; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol; use std::f64::consts as f64; diff --git a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs index 192bc7d9ddce1..657d52d0e9e17 100644 --- a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs +++ b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs @@ -6,7 +6,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::GenericArgKind; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -14,7 +14,9 @@ declare_clippy_lint! { /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`. /// /// ### Why is this bad? - /// `Arc` is only `Send`/`Sync` when `T` is [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E), + /// `Arc` is an Atomic `RC` and guarantees that updates to the reference counter are + /// Atomic. This is useful in multiprocessing scenarios. To send an `Arc` across processes + /// and make use of the atomic ref counter, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E), /// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc` /// /// ### Example @@ -34,7 +36,7 @@ declare_clippy_lint! { #[clippy::version = "1.72.0"] pub ARC_WITH_NON_SEND_SYNC, suspicious, - "using `Arc` with a type that does not implement `Send` or `Sync`" + "using `Arc` with a type that does not implement `Send` and `Sync`" } declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]); @@ -61,19 +63,25 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync { cx, ARC_WITH_NON_SEND_SYNC, expr.span, - "usage of an `Arc` that is not `Send` or `Sync`", + "usage of an `Arc` that is not `Send` and `Sync`", |diag| { with_forced_trimmed_paths!({ + diag.note(format!("`Arc<{arg_ty}>` is not `Send` and `Sync` as:")); + if !is_send { - diag.note(format!("the trait `Send` is not implemented for `{arg_ty}`")); + diag.note(format!("- the trait `Send` is not implemented for `{arg_ty}`")); } if !is_sync { - diag.note(format!("the trait `Sync` is not implemented for `{arg_ty}`")); + diag.note(format!("- the trait `Sync` is not implemented for `{arg_ty}`")); } - diag.note(format!("required for `{ty}` to implement `Send` and `Sync`")); + diag.help("consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types"); + + diag.note("if you intend to use `Arc` with `Send` and `Sync` traits"); - diag.help("consider using an `Rc` instead or wrapping the inner type with a `Mutex`"); + diag.note(format!( + "wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `{arg_ty}`" + )); }); }, ); diff --git a/src/tools/clippy/clippy_lints/src/as_conversions.rs b/src/tools/clippy/clippy_lints/src/as_conversions.rs index b9dda49ca4124..e052d36f1155d 100644 --- a/src/tools/clippy/clippy_lints/src/as_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/as_conversions.rs @@ -3,7 +3,7 @@ use clippy_utils::is_from_proc_macro; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/asm_syntax.rs b/src/tools/clippy/clippy_lints/src/asm_syntax.rs index 9717aa9e981fb..feb6437ee26ac 100644 --- a/src/tools/clippy/clippy_lints/src/asm_syntax.rs +++ b/src/tools/clippy/clippy_lints/src/asm_syntax.rs @@ -3,7 +3,7 @@ use std::fmt; use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions}; use rustc_lint::{EarlyContext, EarlyLintPass, Lint}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; #[derive(Clone, Copy, PartialEq, Eq)] enum AsmStyle { diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs index b90914e936a8a..a15ec199a28a9 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn}; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs index 71ec87a88741c..aec22965b1b0b 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs @@ -9,7 +9,7 @@ use rustc_hir::def::Res; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs index ec2447dae965a..3e5a01c45df1d 100644 --- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs +++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs @@ -4,7 +4,7 @@ use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::{Body, BodyId, CoroutineKind, CoroutineSource, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 38364af27c7f4..da38422874b44 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -5,7 +5,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sug use clippy_utils::is_from_proc_macro; use clippy_utils::macros::{is_panic, macro_backtrace}; use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; -use if_chain::if_chain; use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::TokenTree; use rustc_ast::{ @@ -18,9 +17,9 @@ use rustc_hir::{ use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; +use rustc_session::{declare_lint_pass, impl_lint_pass}; use rustc_span::symbol::Symbol; -use rustc_span::{sym, DUMMY_SP, Span}; +use rustc_span::{sym, Span, DUMMY_SP}; use semver::Version; static UNIX_SYSTEMS: &[&str] = &[ @@ -121,7 +120,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Checks for `#[deprecated]` annotations with a `since` - /// field that is not a valid semantic version. + /// field that is not a valid semantic version. Also allows "TBD" to signal + /// future deprecation. /// /// ### Why is this bad? /// For checking the version of the deprecation, it must be @@ -371,7 +371,7 @@ declare_clippy_lint! { /// let _ = 1 / random(); /// } /// ``` - #[clippy::version = "1.73.0"] + #[clippy::version = "1.74.0"] pub SHOULD_PANIC_WITHOUT_EXPECT, pedantic, "ensures that all `should_panic` attributes specify its expected panic message" @@ -406,20 +406,26 @@ declare_clippy_lint! { /// Checks for `#[cfg(features = "...")]` and suggests to replace it with /// `#[cfg(feature = "...")]`. /// + /// It also checks if `cfg(test)` was misspelled. + /// /// ### Why is this bad? - /// Misspelling `feature` as `features` can be sometimes hard to spot. It + /// Misspelling `feature` as `features` or `test` as `tests` can be sometimes hard to spot. It /// may cause conditional compilation not work quietly. /// /// ### Example /// ```no_run /// #[cfg(features = "some-feature")] /// fn conditional() { } + /// #[cfg(tests)] + /// mod tests { } /// ``` /// /// Use instead: /// ```no_run /// #[cfg(feature = "some-feature")] /// fn conditional() { } + /// #[cfg(test)] + /// mod tests { } /// ``` #[clippy::version = "1.69.0"] pub MAYBE_MISUSED_CFG, @@ -470,13 +476,11 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { return; } for item in items { - if_chain! { - if let NestedMetaItem::MetaItem(mi) = &item; - if let MetaItemKind::NameValue(lit) = &mi.kind; - if mi.has_name(sym::since); - then { - check_semver(cx, item.span(), lit); - } + if let NestedMetaItem::MetaItem(mi) = &item + && let MetaItemKind::NameValue(lit) = &mi.kind + && mi.has_name(sym::since) + { + check_deprecated_since(cx, item.span(), lit); } } } @@ -579,15 +583,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { /// Returns the lint name if it is clippy lint. fn extract_clippy_lint(lint: &NestedMetaItem) -> Option { - if_chain! { - if let Some(meta_item) = lint.meta_item(); - if meta_item.path.segments.len() > 1; - if let tool_name = meta_item.path.segments[0].ident; - if tool_name.name == sym::clippy; - then { - let lint_name = meta_item.path.segments.last().unwrap().ident.name; - return Some(lint_name); - } + if let Some(meta_item) = lint.meta_item() + && meta_item.path.segments.len() > 1 + && let tool_name = meta_item.path.segments[0].ident + && tool_name.name == sym::clippy + { + let lint_name = meta_item.path.segments.last().unwrap().ident.name; + return Some(lint_name); } None } @@ -759,9 +761,9 @@ fn check_attrs(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribut } } -fn check_semver(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) { +fn check_deprecated_since(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) { if let LitKind::Str(is, _) = lit.kind { - if Version::parse(is.as_str()).is_ok() { + if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() { return; } } @@ -856,18 +858,17 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It } fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) { - if_chain! { - if msrv.meets(msrvs::TOOL_ATTRIBUTES); + if msrv.meets(msrvs::TOOL_ATTRIBUTES) // check cfg_attr - if attr.has_name(sym::cfg_attr); - if let Some(items) = attr.meta_item_list(); - if items.len() == 2; + && attr.has_name(sym::cfg_attr) + && let Some(items) = attr.meta_item_list() + && items.len() == 2 // check for `rustfmt` - if let Some(feature_item) = items[0].meta_item(); - if feature_item.has_name(sym::rustfmt); + && let Some(feature_item) = items[0].meta_item() + && feature_item.has_name(sym::rustfmt) // check for `rustfmt_skip` and `rustfmt::skip` - if let Some(skip_item) = &items[1].meta_item(); - if skip_item.has_name(sym!(rustfmt_skip)) + && let Some(skip_item) = &items[1].meta_item() + && (skip_item.has_name(sym!(rustfmt_skip)) || skip_item .path .segments @@ -875,21 +876,20 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr .expect("empty path in attribute") .ident .name - == sym::skip; + == sym::skip) // Only lint outer attributes, because custom inner attributes are unstable // Tracking issue: https://github.com/rust-lang/rust/issues/54726 - if attr.style == AttrStyle::Outer; - then { - span_lint_and_sugg( - cx, - DEPRECATED_CFG_ATTR, - attr.span, - "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes", - "use", - "#[rustfmt::skip]".to_string(), - Applicability::MachineApplicable, - ); - } + && attr.style == AttrStyle::Outer + { + span_lint_and_sugg( + cx, + DEPRECATED_CFG_ATTR, + attr.span, + "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes", + "use", + "#[rustfmt::skip]".to_string(), + Applicability::MachineApplicable, + ); } } @@ -930,21 +930,35 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { for item in items { if let NestedMetaItem::MetaItem(meta) = item { - if meta.has_name(sym!(features)) + if let Some(ident) = meta.ident() + && ident.name.as_str() == "features" && let Some(val) = meta.value_str() { span_lint_and_sugg( cx, MAYBE_MISUSED_CFG, meta.span, - "feature may misspelled as features", - "use", + "'feature' may be misspelled as 'features'", + "did you mean", format!("feature = \"{val}\""), Applicability::MaybeIncorrect, ); } if let MetaItemKind::List(list) = &meta.kind { check_nested_misused_cfg(cx, list); + // If this is not a list, then we check for `cfg(test)`. + } else if let Some(ident) = meta.ident() + && matches!(ident.name.as_str(), "tests" | "Test") + { + span_lint_and_sugg( + cx, + MAYBE_MISUSED_CFG, + meta.span, + &format!("'test' may be misspelled as '{}'", ident.name.as_str()), + "did you mean", + "test".to_string(), + Applicability::MaybeIncorrect, + ); } } } @@ -989,12 +1003,10 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { mismatched.extend(find_mismatched_target_os(list)); }, MetaItemKind::Word => { - if_chain! { - if let Some(ident) = meta.ident(); - if let Some(os) = find_os(ident.name.as_str()); - then { - mismatched.push((os, ident.span)); - } + if let Some(ident) = meta.ident() + && let Some(os) = find_os(ident.name.as_str()) + { + mismatched.push((os, ident.span)); } }, MetaItemKind::NameValue(..) => {}, @@ -1005,30 +1017,28 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) { mismatched } - if_chain! { - if attr.has_name(sym::cfg); - if let Some(list) = attr.meta_item_list(); - let mismatched = find_mismatched_target_os(&list); - if !mismatched.is_empty(); - then { - let mess = "operating system used in target family position"; - - span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| { - // Avoid showing the unix suggestion multiple times in case - // we have more than one mismatch for unix-like systems - let mut unix_suggested = false; - - for (os, span) in mismatched { - let sugg = format!("target_os = \"{os}\""); - diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect); - - if !unix_suggested && is_unix(os) { - diag.help("did you mean `unix`?"); - unix_suggested = true; - } + if attr.has_name(sym::cfg) + && let Some(list) = attr.meta_item_list() + && let mismatched = find_mismatched_target_os(&list) + && !mismatched.is_empty() + { + let mess = "operating system used in target family position"; + + span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| { + // Avoid showing the unix suggestion multiple times in case + // we have more than one mismatch for unix-like systems + let mut unix_suggested = false; + + for (os, span) in mismatched { + let sugg = format!("target_os = \"{os}\""); + diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect); + + if !unix_suggested && is_unix(os) { + diag.help("did you mean `unix`?"); + unix_suggested = true; } - }); - } + } + }); } } diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs index 06b74b972b701..9894a1639618d 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Body, CoroutineKind, CoroutineSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::CoroutineLayout; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs index 04bf541a5bdcf..692309629b79e 100644 --- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs +++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs @@ -4,12 +4,11 @@ use clippy_utils::ty::implements_trait; use clippy_utils::visitors::{for_each_expr, Descend}; use clippy_utils::{get_parent_expr, higher}; use core::ops::ControlFlow; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BlockCheckMode, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -114,15 +113,13 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions { let _: Option = for_each_expr(cond, |e| { if let ExprKind::Closure(closure) = e.kind { // do not lint if the closure is called using an iterator (see #1141) - if_chain! { - if let Some(parent) = get_parent_expr(cx, e); - if let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind; - let caller = cx.typeck_results().expr_ty(self_arg); - if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); - if implements_trait(cx, caller, iter_id, &[]); - then { - return ControlFlow::Continue(Descend::No); - } + if let Some(parent) = get_parent_expr(cx, e) + && let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind + && let caller = cx.typeck_results().expr_ty(self_arg) + && let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator) + && implements_trait(cx, caller, iter_id, &[]) + { + return ControlFlow::Continue(Descend::No); } let body = cx.tcx.hir().body(closure.body); diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index 665dbd6f708c6..74201e9cc304d 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Lit}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::Ident; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs index 156cb34df9cde..cfb76cab6dc23 100644 --- a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs +++ b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs @@ -2,7 +2,7 @@ use clippy_utils::higher::If; use rustc_ast::LitKind; use rustc_hir::{Block, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::Sugg; diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 0e0d229e877b7..e11f83f226034 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -2,13 +2,12 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::eq_expr_value; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp}; use rustc_lint::{LateContext, LateLintPass, Level}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -151,17 +150,15 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { return Ok(Bool::Term(n as u8)); } - if_chain! { - if let ExprKind::Binary(e_binop, e_lhs, e_rhs) = &e.kind; - if implements_ord(self.cx, e_lhs); - if let ExprKind::Binary(expr_binop, expr_lhs, expr_rhs) = &expr.kind; - if negate(e_binop.node) == Some(expr_binop.node); - if eq_expr_value(self.cx, e_lhs, expr_lhs); - if eq_expr_value(self.cx, e_rhs, expr_rhs); - then { - #[expect(clippy::cast_possible_truncation)] - return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); - } + if let ExprKind::Binary(e_binop, e_lhs, e_rhs) = &e.kind + && implements_ord(self.cx, e_lhs) + && let ExprKind::Binary(expr_binop, expr_lhs, expr_rhs) = &expr.kind + && negate(e_binop.node) == Some(expr_binop.node) + && eq_expr_value(self.cx, e_lhs, expr_lhs) + && eq_expr_value(self.cx, e_rhs, expr_rhs) + { + #[expect(clippy::cast_possible_truncation)] + return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); } } let n = self.terminals.len(); @@ -427,8 +424,9 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { improvements.push(suggestion); } } - let nonminimal_bool_lint = |suggestions: Vec<_>| { + let nonminimal_bool_lint = |mut suggestions: Vec<_>| { if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).0 != Level::Allow { + suggestions.sort(); span_lint_hir_and_then( self.cx, NONMINIMAL_BOOL, diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs index 739ce8f67c236..d3d4f3c41c85d 100644 --- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs +++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs @@ -8,7 +8,7 @@ use rustc_hir::{ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::Mutability; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -49,69 +49,62 @@ declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]); impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) { - if_chain! { - if !e.span.from_expansion(); - if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind; - if !addrof_target.span.from_expansion(); - if let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind; - if !deref_target.span.from_expansion(); - if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) ); - let ref_ty = cx.typeck_results().expr_ty(deref_target); - if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind(); - if !is_from_proc_macro(cx, e); - then{ - - if let Some(parent_expr) = get_parent_expr(cx, e){ - if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) && - !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) { - return; - } + if !e.span.from_expansion() + && let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind + && !addrof_target.span.from_expansion() + && let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind + && !deref_target.span.from_expansion() + && !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..)) + && let ref_ty = cx.typeck_results().expr_ty(deref_target) + && let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind() + && !is_from_proc_macro(cx, e) + { + if let Some(parent_expr) = get_parent_expr(cx, e) { + if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) + && !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) + { + return; + } - // modification to `&mut &*x` is different from `&mut x` - if matches!(deref_target.kind, ExprKind::Path(..) - | ExprKind::Field(..) - | ExprKind::Index(..) - | ExprKind::Unary(UnOp::Deref, ..)) - && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) { - return; - } + // modification to `&mut &*x` is different from `&mut x` + if matches!( + deref_target.kind, + ExprKind::Path(..) | ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, ..) + ) && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) + { + return; } + } - span_lint_and_then( - cx, - BORROW_DEREF_REF, - e.span, - "deref on an immutable reference", - |diag| { - diag.span_suggestion( - e.span, - "if you would like to reborrow, try removing `&*`", - snippet_opt(cx, deref_target.span).unwrap(), - Applicability::MachineApplicable - ); + span_lint_and_then( + cx, + BORROW_DEREF_REF, + e.span, + "deref on an immutable reference", + |diag| { + diag.span_suggestion( + e.span, + "if you would like to reborrow, try removing `&*`", + snippet_opt(cx, deref_target.span).unwrap(), + Applicability::MachineApplicable, + ); - // has deref trait -> give 2 help - // doesn't have deref trait -> give 1 help - if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait(){ - if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) { - return; - } + // has deref trait -> give 2 help + // doesn't have deref trait -> give 1 help + if let Some(deref_trait_id) = cx.tcx.lang_items().deref_trait() { + if !implements_trait(cx, *inner_ty, deref_trait_id, &[]) { + return; } - - diag.span_suggestion( - e.span, - "if you would like to deref, try using `&**`", - format!( - "&**{}", - &snippet_opt(cx, deref_target.span).unwrap(), - ), - Applicability::MaybeIncorrect - ); - } - ); - } + diag.span_suggestion( + e.span, + "if you would like to deref, try using `&**`", + format!("&**{}", &snippet_opt(cx, deref_target.span).unwrap()), + Applicability::MaybeIncorrect, + ); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs index 9c78c6e532d3c..ef12fe344e409 100644 --- a/src/tools/clippy/clippy_lints/src/box_default.rs +++ b/src/tools/clippy/clippy_lints/src/box_default.rs @@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::IsSuggestable; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -45,7 +45,7 @@ impl LateLintPass<'_> for BoxDefault { && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_new.kind && let ExprKind::Call(arg_path, ..) = arg.kind && !in_external_macro(cx.sess(), expr.span) - && (expr.span.eq_ctxt(arg.span) || is_vec_expn(cx, arg)) + && (expr.span.eq_ctxt(arg.span) || is_local_vec_expn(cx, arg, expr)) && seg.ident.name == sym::new && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box()) && is_default_equivalent(cx, arg) @@ -81,10 +81,10 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool { } } -fn is_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - macro_backtrace(expr.span) - .next() - .map_or(false, |call| cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id)) +fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) -> bool { + macro_backtrace(expr.span).next().map_or(false, |call| { + cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span) + }) } #[derive(Default)] diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs index 3a872e54c9a2b..fea6924d89e91 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs @@ -8,7 +8,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::is_lint_allowed; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_lint::{LateContext, LateLintPass, Lint}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::DUMMY_SP; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs index f7a5b1857be27..ec681adb7aef2 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -2,7 +2,6 @@ use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId}; use clippy_utils::diagnostics::span_lint; -use if_chain::if_chain; use itertools::Itertools; use rustc_hir::def_id::LOCAL_CRATE; use rustc_lint::LateContext; @@ -15,31 +14,33 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { let mut packages = metadata.packages.clone(); packages.sort_by(|a, b| a.name.cmp(&b.name)); - if_chain! { - if let Some(resolve) = &metadata.resolve; - if let Some(local_id) = packages - .iter() - .find_map(|p| if p.name == local_name.as_str() { Some(&p.id) } else { None }); - then { - for (name, group) in &packages.iter().group_by(|p| p.name.clone()) { - let group: Vec<&Package> = group.collect(); - - if group.len() <= 1 { - continue; - } - - if group.iter().all(|p| is_normal_dep(&resolve.nodes, local_id, &p.id)) { - let mut versions: Vec<_> = group.into_iter().map(|p| &p.version).collect(); - versions.sort(); - let versions = versions.iter().join(", "); - - span_lint( - cx, - MULTIPLE_CRATE_VERSIONS, - DUMMY_SP, - &format!("multiple versions for dependency `{name}`: {versions}"), - ); - } + if let Some(resolve) = &metadata.resolve + && let Some(local_id) = packages.iter().find_map(|p| { + if p.name == local_name.as_str() { + Some(&p.id) + } else { + None + } + }) + { + for (name, group) in &packages.iter().group_by(|p| p.name.clone()) { + let group: Vec<&Package> = group.collect(); + + if group.len() <= 1 { + continue; + } + + if group.iter().all(|p| is_normal_dep(&resolve.nodes, local_id, &p.id)) { + let mut versions: Vec<_> = group.into_iter().map(|p| &p.version).collect(); + versions.sort(); + let versions = versions.iter().join(", "); + + span_lint( + cx, + MULTIPLE_CRATE_VERSIONS, + DUMMY_SP, + &format!("multiple versions for dependency `{name}`: {versions}"), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/cargo/wildcard_dependencies.rs b/src/tools/clippy/clippy_lints/src/cargo/wildcard_dependencies.rs index 4dcc9cbe3a755..244e98eb66662 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/wildcard_dependencies.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/wildcard_dependencies.rs @@ -1,6 +1,5 @@ use cargo_metadata::Metadata; use clippy_utils::diagnostics::span_lint; -use if_chain::if_chain; use rustc_lint::LateContext; use rustc_span::DUMMY_SP; @@ -9,19 +8,17 @@ use super::WILDCARD_DEPENDENCIES; pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) { for dep in &metadata.packages[0].dependencies { // VersionReq::any() does not work - if_chain! { - if let Ok(wildcard_ver) = semver::VersionReq::parse("*"); - if let Some(ref source) = dep.source; - if !source.starts_with("git"); - if dep.req == wildcard_ver; - then { - span_lint( - cx, - WILDCARD_DEPENDENCIES, - DUMMY_SP, - &format!("wildcard dependency for `{}`", dep.name), - ); - } + if let Ok(wildcard_ver) = semver::VersionReq::parse("*") + && let Some(ref source) = dep.source + && !source.starts_with("git") + && dep.req == wildcard_ver + { + span_lint( + cx, + WILDCARD_DEPENDENCIES, + DUMMY_SP, + &format!("wildcard dependency for `{}`", dep.name), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs index ffa571abb3910..2ddb0f00ecdd5 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs @@ -1,5 +1,6 @@ +use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir::Expr; -use rustc_lint::{LateContext, LintContext}; +use rustc_lint::LateContext; use rustc_middle::ty::Ty; use super::{utils, CAST_POSSIBLE_WRAP}; @@ -78,13 +79,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca ), }; - cx.struct_span_lint(CAST_POSSIBLE_WRAP, expr.span, message, |diag| { + span_lint_and_then(cx, CAST_POSSIBLE_WRAP, expr.span, &message, |diag| { if let EmitState::LintOnPtrSize(16) = should_lint { diag - .note("`usize` and `isize` may be as small as 16 bits on some platforms") - .note("for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types") - } else { - diag - } + .note("`usize` and `isize` may be as small as 16 bits on some platforms") + .note("for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types"); + }; }); } diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs index a83dfd94dc226..bd12ee406284b 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs @@ -1,7 +1,6 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::{method_chain_args, sext}; -use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; @@ -28,13 +27,11 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast // Don't lint for positive constants. let const_val = constant(cx, cx.typeck_results(), cast_op); - if_chain! { - if let Some(Constant::Int(n)) = const_val; - if let ty::Int(ity) = *cast_from.kind(); - if sext(cx.tcx, n, ity) >= 0; - then { - return false; - } + if let Some(Constant::Int(n)) = const_val + && let ty::Int(ity) = *cast_from.kind() + && sext(cx.tcx, n, ity) >= 0 + { + return false; } // Don't lint for the result of methods that always return non-negative values. @@ -42,13 +39,11 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast let mut method_name = path.ident.name.as_str(); let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"]; - if_chain! { - if method_name == "unwrap"; - if let Some(arglist) = method_chain_args(cast_op, &["unwrap"]); - if let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind; - then { - method_name = inner_path.ident.name.as_str(); - } + if method_name == "unwrap" + && let Some(arglist) = method_chain_args(cast_op, &["unwrap"]) + && let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind + { + method_name = inner_path.ident.name.as_str(); } if allowed_methods.iter().any(|&name| method_name == name) { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs index d141040291372..2a9f7fec1722f 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -1,7 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source; -use if_chain::if_chain; use rustc_ast::Mutability; use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::LateContext; @@ -69,26 +68,24 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let map = cx.tcx.hir(); - if_chain! { - if let Some(parent_id) = map.opt_parent_id(expr.hir_id); - if let Some(parent) = map.find(parent_id); - then { - let expr = match parent { - Node::Block(block) => { - if let Some(parent_expr) = block.expr { - parent_expr - } else { - return false; - } - }, - Node::Expr(expr) => expr, - _ => return false, - }; + if let Some(parent_id) = map.opt_parent_id(expr.hir_id) + && let Some(parent) = map.find(parent_id) + { + let expr = match parent { + Node::Block(block) => { + if let Some(parent_expr) = block.expr { + parent_expr + } else { + return false; + } + }, + Node::Expr(expr) => expr, + _ => return false, + }; - matches!(expr.kind, ExprKind::Cast(..)) - } else { - false - } + matches!(expr.kind, ExprKind::Cast(..)) + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs index badadf2c9f659..3db1e3e6d97e5 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -1,7 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind}; @@ -25,34 +24,32 @@ fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option { } pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>, msrv: &Msrv) { - if_chain! { - if msrv.meets(msrvs::PTR_SLICE_RAW_PARTS); - if let ty::RawPtr(ptrty) = cast_to.kind(); - if let ty::Slice(_) = ptrty.ty.kind(); - if let ExprKind::Call(fun, [ptr_arg, len_arg]) = cast_expr.peel_blocks().kind; - if let ExprKind::Path(ref qpath) = fun.kind; - if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); - if let Some(rpk) = raw_parts_kind(cx, fun_def_id); - let ctxt = expr.span.ctxt(); - if cast_expr.span.ctxt() == ctxt; - then { - let func = match rpk { - RawPartsKind::Immutable => "from_raw_parts", - RawPartsKind::Mutable => "from_raw_parts_mut" - }; - let span = expr.span; - let mut applicability = Applicability::MachineApplicable; - let ptr = snippet_with_context(cx, ptr_arg.span, ctxt, "ptr", &mut applicability).0; - let len = snippet_with_context(cx, len_arg.span, ctxt, "len", &mut applicability).0; - span_lint_and_sugg( - cx, - CAST_SLICE_FROM_RAW_PARTS, - span, - &format!("casting the result of `{func}` to {cast_to}"), - "replace with", - format!("core::ptr::slice_{func}({ptr}, {len})"), - applicability - ); - } + if msrv.meets(msrvs::PTR_SLICE_RAW_PARTS) + && let ty::RawPtr(ptrty) = cast_to.kind() + && let ty::Slice(_) = ptrty.ty.kind() + && let ExprKind::Call(fun, [ptr_arg, len_arg]) = cast_expr.peel_blocks().kind + && let ExprKind::Path(ref qpath) = fun.kind + && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() + && let Some(rpk) = raw_parts_kind(cx, fun_def_id) + && let ctxt = expr.span.ctxt() + && cast_expr.span.ctxt() == ctxt + { + let func = match rpk { + RawPartsKind::Immutable => "from_raw_parts", + RawPartsKind::Mutable => "from_raw_parts_mut", + }; + let span = expr.span; + let mut applicability = Applicability::MachineApplicable; + let ptr = snippet_with_context(cx, ptr_arg.span, ctxt, "ptr", &mut applicability).0; + let len = snippet_with_context(cx, len_arg.span, ctxt, "len", &mut applicability).0; + span_lint_and_sugg( + cx, + CAST_SLICE_FROM_RAW_PARTS, + span, + &format!("casting the result of `{func}` to {cast_to}"), + "replace with", + format!("core::ptr::slice_{func}({ptr}, {len})"), + applicability, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs index 82e07c98a7e01..a7d3868f76c60 100644 --- a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs +++ b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; -use if_chain::if_chain; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; @@ -10,32 +9,31 @@ use rustc_middle::ty::{self, UintTy}; use super::CHAR_LIT_AS_U8; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if let ExprKind::Cast(e, _) = &expr.kind; - if let ExprKind::Lit(l) = &e.kind; - if let LitKind::Char(c) = l.node; - if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(expr).kind(); - then { - let mut applicability = Applicability::MachineApplicable; - let snippet = snippet_with_applicability(cx, e.span, "'x'", &mut applicability); + if let ExprKind::Cast(e, _) = &expr.kind + && let ExprKind::Lit(l) = &e.kind + && let LitKind::Char(c) = l.node + && ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(expr).kind() + { + let mut applicability = Applicability::MachineApplicable; + let snippet = snippet_with_applicability(cx, e.span, "'x'", &mut applicability); - span_lint_and_then( - cx, - CHAR_LIT_AS_U8, - expr.span, - "casting a character literal to `u8` truncates", - |diag| { - diag.note("`char` is four bytes wide, but `u8` is a single byte"); + span_lint_and_then( + cx, + CHAR_LIT_AS_U8, + expr.span, + "casting a character literal to `u8` truncates", + |diag| { + diag.note("`char` is four bytes wide, but `u8` is a single byte"); - if c.is_ascii() { - diag.span_suggestion( - expr.span, - "use a byte literal instead", - format!("b{snippet}"), - applicability, - ); - } - }); - } + if c.is_ascii() { + diag.span_suggestion( + expr.span, + "use a byte literal instead", + format!("b{snippet}"), + applicability, + ); + } + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index 49a90a2f3c228..e05b8f66d8618 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -27,7 +27,7 @@ use clippy_utils::is_hir_ty_cfg_dependant; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs index 0172e9336494b..ff069860a116e 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs @@ -1,7 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; @@ -17,29 +16,35 @@ pub(super) fn check<'tcx>( cast_to: Ty<'tcx>, msrv: &Msrv, ) { - if_chain! { - if msrv.meets(msrvs::POINTER_CAST_CONSTNESS); - if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, ty: from_ty }) = cast_from.kind(); - if let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, ty: to_ty }) = cast_to.kind(); - if matches!((from_mutbl, to_mutbl), - (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not)); - if from_ty == to_ty; - then { - let sugg = Sugg::hir(cx, cast_expr, "_"); - let constness = match *to_mutbl { - Mutability::Not => "const", - Mutability::Mut => "mut", - }; + if msrv.meets(msrvs::POINTER_CAST_CONSTNESS) + && let ty::RawPtr(TypeAndMut { + mutbl: from_mutbl, + ty: from_ty, + }) = cast_from.kind() + && let ty::RawPtr(TypeAndMut { + mutbl: to_mutbl, + ty: to_ty, + }) = cast_to.kind() + && matches!( + (from_mutbl, to_mutbl), + (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not) + ) + && from_ty == to_ty + { + let sugg = Sugg::hir(cx, cast_expr, "_"); + let constness = match *to_mutbl { + Mutability::Not => "const", + Mutability::Mut => "mut", + }; - span_lint_and_sugg( - cx, - PTR_CAST_CONSTNESS, - expr.span, - "`as` casting between raw pointers while changing only its constness", - &format!("try `pointer::cast_{constness}`, a safer alternative"), - format!("{}.cast_{constness}()", sugg.maybe_par()), - Applicability::MachineApplicable, - ); - } + span_lint_and_sugg( + cx, + PTR_CAST_CONSTNESS, + expr.span, + "`as` casting between raw pointers while changing only its constness", + &format!("try `pointer::cast_{constness}`, a safer alternative"), + format!("{}.cast_{constness}()", sugg.maybe_par()), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index 61bfce07e1a00..849920bb76d51 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -3,7 +3,6 @@ use clippy_utils::numeric_literal::NumericLiteral; use clippy_utils::source::snippet_opt; use clippy_utils::visitors::{for_each_expr, Visitable}; use clippy_utils::{get_parent_expr, get_parent_node, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; -use if_chain::if_chain; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -25,40 +24,40 @@ pub(super) fn check<'tcx>( ) -> bool { let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default(); - if_chain! { - if let ty::RawPtr(..) = cast_from.kind(); + if let ty::RawPtr(..) = cast_from.kind() // check both mutability and type are the same - if cast_from.kind() == cast_to.kind(); - if let ExprKind::Cast(_, cast_to_hir) = expr.kind; + && cast_from.kind() == cast_to.kind() + && let ExprKind::Cast(_, cast_to_hir) = expr.kind // Ignore casts to e.g. type aliases and infer types // - p as pointer_alias // - p as _ - if let TyKind::Ptr(to_pointee) = cast_to_hir.kind; - then { - match to_pointee.ty.kind { - // Ignore casts to pointers that are aliases or cfg dependant, e.g. - // - p as *const std::ffi::c_char (alias) - // - p as *const std::os::raw::c_char (cfg dependant) - TyKind::Path(qpath) => { - if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) { - return false; - } - }, - // Ignore `p as *const _` - TyKind::Infer => return false, - _ => {}, - } - - span_lint_and_sugg( - cx, - UNNECESSARY_CAST, - expr.span, - &format!("casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"), - "try", - cast_str.clone(), - Applicability::MaybeIncorrect, - ); + && let TyKind::Ptr(to_pointee) = cast_to_hir.kind + { + match to_pointee.ty.kind { + // Ignore casts to pointers that are aliases or cfg dependant, e.g. + // - p as *const std::ffi::c_char (alias) + // - p as *const std::os::raw::c_char (cfg dependant) + TyKind::Path(qpath) => { + if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) { + return false; + } + }, + // Ignore `p as *const _` + TyKind::Infer => return false, + _ => {}, } + + span_lint_and_sugg( + cx, + UNNECESSARY_CAST, + expr.span, + &format!( + "casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)" + ), + "try", + cast_str.clone(), + Applicability::MaybeIncorrect, + ); } // skip cast of local that is a type alias @@ -86,14 +85,12 @@ pub(super) fn check<'tcx>( } // skip cast to non-primitive type - if_chain! { - if let ExprKind::Cast(_, cast_to) = expr.kind; - if let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind; - if let Res::PrimTy(_) = path.res; - then {} - else { - return false; - } + if let ExprKind::Cast(_, cast_to) = expr.kind + && let TyKind::Path(QPath::Resolved(_, path)) = &cast_to.kind + && let Res::PrimTy(_) = path.res + { + } else { + return false; } // skip cast of fn call that returns type alias @@ -106,18 +103,19 @@ pub(super) fn check<'tcx>( if let Some(lit) = get_numeric_literal(cast_expr) { let literal_str = &cast_str; - if_chain! { - if let LitKind::Int(n, _) = lit.node; - if let Some(src) = snippet_opt(cx, cast_expr.span); - if cast_to.is_floating_point(); - if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node); - let from_nbits = 128 - n.leading_zeros(); - let to_nbits = fp_ty_mantissa_nbits(cast_to); - if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit.is_decimal(); - then { - lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to); - return true - } + if let LitKind::Int(n, _) = lit.node + && let Some(src) = snippet_opt(cx, cast_expr.span) + && cast_to.is_floating_point() + && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) + && let from_nbits = 128 - n.leading_zeros() + && let to_nbits = fp_ty_mantissa_nbits(cast_to) + && from_nbits != 0 + && to_nbits != 0 + && from_nbits <= to_nbits + && num_lit.is_decimal() + { + lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to); + return true; } match lit.node { diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index d31c2268a657a..92810ea2aa0ff 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -4,12 +4,11 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{in_constant, is_integer_literal, SpanlessEq}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does @@ -55,20 +54,17 @@ impl<'tcx> LateLintPass<'tcx> for CheckedConversions { return; } - let result = if_chain! { - if !in_constant(cx, item.hir_id); - if !in_external_macro(cx.sess(), item.span); - if let ExprKind::Binary(op, left, right) = &item.kind; - - then { - match op.node { - BinOpKind::Ge | BinOpKind::Le => single_check(item), - BinOpKind::And => double_check(cx, left, right), - _ => None, - } - } else { - None + let result = if !in_constant(cx, item.hir_id) + && !in_external_macro(cx.sess(), item.span) + && let ExprKind::Binary(op, left, right) = &item.kind + { + match op.node { + BinOpKind::Ge | BinOpKind::Le => single_check(item), + BinOpKind::And => double_check(cx, left, right), + _ => None, } + } else { + None }; if let Some(cv) = result { @@ -193,16 +189,13 @@ impl ConversionType { /// Check for `expr <= (to_type::MAX as from_type)` fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option> { - if_chain! { - if let ExprKind::Binary(ref op, left, right) = &expr.kind; - if let Some((candidate, check)) = normalize_le_ge(op, left, right); - if let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX"); - - then { - Conversion::try_new(candidate, from, to) - } else { - None - } + if let ExprKind::Binary(ref op, left, right) = &expr.kind + && let Some((candidate, check)) = normalize_le_ge(op, left, right) + && let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX") + { + Conversion::try_new(candidate, from, to) + } else { + None } } @@ -243,33 +236,27 @@ fn get_types_from_cast<'a>( ) -> Option<(&'a str, &'a str)> { // `to_type::max_value() as from_type` // or `to_type::MAX as from_type` - let call_from_cast: Option<(&Expr<'_>, &str)> = if_chain! { + let call_from_cast: Option<(&Expr<'_>, &str)> = if let ExprKind::Cast(limit, from_type) = &expr.kind // to_type::max_value(), from_type - if let ExprKind::Cast(limit, from_type) = &expr.kind; - if let TyKind::Path(ref from_type_path) = &from_type.kind; - if let Some(from_sym) = int_ty_to_sym(from_type_path); - - then { - Some((limit, from_sym)) - } else { - None - } + && let TyKind::Path(ref from_type_path) = &from_type.kind + && let Some(from_sym) = int_ty_to_sym(from_type_path) + { + Some((limit, from_sym)) + } else { + None }; // `from_type::from(to_type::max_value())` let limit_from: Option<(&Expr<'_>, &str)> = call_from_cast.or_else(|| { - if_chain! { + if let ExprKind::Call(from_func, [limit]) = &expr.kind // `from_type::from, to_type::max_value()` - if let ExprKind::Call(from_func, [limit]) = &expr.kind; // `from_type::from` - if let ExprKind::Path(ref path) = &from_func.kind; - if let Some(from_sym) = get_implementing_type(path, INTS, "from"); - - then { - Some((limit, from_sym)) - } else { - None - } + && let ExprKind::Path(ref path) = &from_func.kind + && let Some(from_sym) = get_implementing_type(path, INTS, "from") + { + Some((limit, from_sym)) + } else { + None } }); @@ -298,31 +285,27 @@ fn get_types_from_cast<'a>( /// Gets the type which implements the called function fn get_implementing_type<'a>(path: &QPath<'_>, candidates: &'a [&str], function: &str) -> Option<&'a str> { - if_chain! { - if let QPath::TypeRelative(ty, path) = &path; - if path.ident.name.as_str() == function; - if let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind; - if let [int] = tp.segments; - then { - let name = int.ident.name.as_str(); - candidates.iter().find(|c| &name == *c).copied() - } else { - None - } + if let QPath::TypeRelative(ty, path) = &path + && path.ident.name.as_str() == function + && let TyKind::Path(QPath::Resolved(None, tp)) = &ty.kind + && let [int] = tp.segments + { + let name = int.ident.name.as_str(); + candidates.iter().find(|c| &name == *c).copied() + } else { + None } } /// Gets the type as a string, if it is a supported integer fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> { - if_chain! { - if let QPath::Resolved(_, path) = *path; - if let [ty] = path.segments; - then { - let name = ty.ident.name.as_str(); - INTS.iter().find(|c| &name == *c).copied() - } else { - None - } + if let QPath::Resolved(_, path) = *path + && let [ty] = path.segments + { + let name = ty.ident.name.as_str(); + INTS.iter().find(|c| &name == *c).copied() + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs index 74ecaa60c7ca5..60f436dc5d2be 100644 --- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs @@ -10,7 +10,7 @@ use rustc_ast::ast::Attribute; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Expr, ExprKind, FnDecl}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, BytePos, Span}; diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs index d21ef195d9b71..07b02c98df151 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs @@ -15,11 +15,10 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability}; use clippy_utils::sugg::Sugg; -use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -121,49 +120,55 @@ fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool { } fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, then_span: Span, else_: &ast::Expr) { - if_chain! { - if let ast::ExprKind::Block(ref block, _) = else_.kind; - if !block_starts_with_comment(cx, block); - if let Some(else_) = expr_block(block); - if else_.attrs.is_empty(); - if !else_.span.from_expansion(); - if let ast::ExprKind::If(..) = else_.kind; - then { - // Prevent "elseif" - // Check that the "else" is followed by whitespace - let up_to_else = then_span.between(block.span); - let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() { !c.is_whitespace() } else { false }; + if let ast::ExprKind::Block(ref block, _) = else_.kind + && !block_starts_with_comment(cx, block) + && let Some(else_) = expr_block(block) + && else_.attrs.is_empty() + && !else_.span.from_expansion() + && let ast::ExprKind::If(..) = else_.kind + { + // Prevent "elseif" + // Check that the "else" is followed by whitespace + let up_to_else = then_span.between(block.span); + let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() { + !c.is_whitespace() + } else { + false + }; - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - COLLAPSIBLE_ELSE_IF, - block.span, - "this `else { if .. }` block can be collapsed", - "collapse nested if block", - format!( - "{}{}", - if requires_space { " " } else { "" }, - snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability) - ), - applicability, - ); - } + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + COLLAPSIBLE_ELSE_IF, + block.span, + "this `else { if .. }` block can be collapsed", + "collapse nested if block", + format!( + "{}{}", + if requires_space { " " } else { "" }, + snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability) + ), + applicability, + ); } } fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) { - if_chain! { - if !block_starts_with_comment(cx, then); - if let Some(inner) = expr_block(then); - if inner.attrs.is_empty(); - if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.kind; + if !block_starts_with_comment(cx, then) + && let Some(inner) = expr_block(then) + && inner.attrs.is_empty() + && let ast::ExprKind::If(ref check_inner, ref content, None) = inner.kind // Prevent triggering on `if c { if let a = b { .. } }`. - if !matches!(check_inner.kind, ast::ExprKind::Let(..)); - let ctxt = expr.span.ctxt(); - if inner.span.ctxt() == ctxt; - then { - span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this `if` statement can be collapsed", |diag| { + && !matches!(check_inner.kind, ast::ExprKind::Let(..)) + && let ctxt = expr.span.ctxt() + && inner.span.ctxt() == ctxt + { + span_lint_and_then( + cx, + COLLAPSIBLE_IF, + expr.span, + "this `if` statement can be collapsed", + |diag| { let mut app = Applicability::MachineApplicable; let lhs = Sugg::ast(cx, check, "..", ctxt, &mut app); let rhs = Sugg::ast(cx, check_inner, "..", ctxt, &mut app); @@ -177,8 +182,8 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: & ), app, // snippet ); - }); - } + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs index 1dfc2e251d9fe..d0c989cfff304 100644 --- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs +++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs @@ -5,7 +5,7 @@ use clippy_utils::{get_enclosing_block, get_parent_node, path_to_local_id}; use core::ops::ControlFlow; use rustc_hir::{Block, ExprKind, HirId, LangItem, Local, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; use rustc_span::Symbol; diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs index 0fe973b49a355..2c23c0b4f154c 100644 --- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs +++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::implements_trait; use clippy_utils::{if_sequence, in_constant, is_else_clause, SpanlessEq}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index e3a09636e2496..d91af76f5e0d9 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -13,7 +13,7 @@ use rustc_hir::def_id::DefIdSet; use rustc_hir::{intravisit, BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::query::Key; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::hygiene::walk_chain; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Span, Symbol}; @@ -117,7 +117,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "pre 1.29.0"] pub IF_SAME_THEN_ELSE, - correctness, + style, "`if` with the same `then` and `else` blocks" } diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs index 5d04ad0112d50..50fd76a3a4774 100644 --- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs @@ -2,11 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::ty::is_copy; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; -use if_chain::if_chain; - declare_clippy_lint! { /// ### What it does /// Checks for types that implement `Copy` as well as @@ -38,25 +36,23 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]); impl<'tcx> LateLintPass<'tcx> for CopyIterator { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if_chain! { - if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), - .. - }) = item.kind; - let ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); - if is_copy(cx, ty); - if let Some(trait_id) = trait_ref.trait_def_id(); - if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id); - then { - span_lint_and_note( - cx, - COPY_ITERATOR, - item.span, - "you are implementing `Iterator` on a `Copy` type", - None, - "consider implementing `IntoIterator` instead", - ); - } + if let ItemKind::Impl(Impl { + of_trait: Some(ref trait_ref), + .. + }) = item.kind + && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() + && is_copy(cx, ty) + && let Some(trait_id) = trait_ref.trait_def_id() + && cx.tcx.is_diagnostic_item(sym::Iterator, trait_id) + { + span_lint_and_note( + cx, + COPY_ITERATOR, + item.span, + "you are implementing `Iterator` on a `Copy` type", + None, + "consider implementing `IntoIterator` instead", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs index a2005638d247f..d4828778be28e 100644 --- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs +++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs @@ -4,7 +4,7 @@ use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; use rustc_span::Span; @@ -53,35 +53,31 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]); impl EarlyLintPass for CrateInMacroDef { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if_chain! { - if item.attrs.iter().any(is_macro_export); - if let ItemKind::MacroDef(macro_def) = &item.kind; - let tts = macro_def.body.tokens.clone(); - if let Some(span) = contains_unhygienic_crate_reference(&tts); - then { - span_lint_and_sugg( - cx, - CRATE_IN_MACRO_DEF, - span, - "`crate` references the macro call's crate", - "to reference the macro definition's crate, use", - String::from("$crate"), - Applicability::MachineApplicable, - ); - } + if item.attrs.iter().any(is_macro_export) + && let ItemKind::MacroDef(macro_def) = &item.kind + && let tts = macro_def.body.tokens.clone() + && let Some(span) = contains_unhygienic_crate_reference(&tts) + { + span_lint_and_sugg( + cx, + CRATE_IN_MACRO_DEF, + span, + "`crate` references the macro call's crate", + "to reference the macro definition's crate, use", + String::from("$crate"), + Applicability::MachineApplicable, + ); } } } fn is_macro_export(attr: &Attribute) -> bool { - if_chain! { - if let AttrKind::Normal(normal) = &attr.kind; - if let [segment] = normal.item.path.segments.as_slice(); - then { - segment.ident.name == sym::macro_export - } else { - false - } + if let AttrKind::Normal(normal) = &attr.kind + && let [segment] = normal.item.path.segments.as_slice() + { + segment.ident.name == sym::macro_export + } else { + false } } @@ -89,14 +85,12 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option { let mut prev_is_dollar = false; let mut cursor = tts.trees(); while let Some(curr) = cursor.next() { - if_chain! { - if !prev_is_dollar; - if let Some(span) = is_crate_keyword(curr); - if let Some(next) = cursor.look_ahead(0); - if is_token(next, &TokenKind::ModSep); - then { - return Some(span); - } + if !prev_is_dollar + && let Some(span) = is_crate_keyword(curr) + && let Some(next) = cursor.look_ahead(0) + && is_token(next, &TokenKind::ModSep) + { + return Some(span); } if let TokenTree::Delimited(_, _, tts) = &curr { let span = contains_unhygienic_crate_reference(tts); @@ -110,10 +104,18 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option { } fn is_crate_keyword(tt: &TokenTree) -> Option { - if_chain! { - if let TokenTree::Token(Token { kind: TokenKind::Ident(symbol, _), span }, _) = tt; - if symbol.as_str() == "crate"; - then { Some(*span) } else { None } + if let TokenTree::Token( + Token { + kind: TokenKind::Ident(symbol, _), + span, + }, + _, + ) = tt + && symbol.as_str() == "crate" + { + Some(*span) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/create_dir.rs b/src/tools/clippy/clippy_lints/src/create_dir.rs index 2bca695c43b15..7a3d5a0709127 100644 --- a/src/tools/clippy/clippy_lints/src/create_dir.rs +++ b/src/tools/clippy/clippy_lints/src/create_dir.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -33,22 +32,20 @@ declare_lint_pass!(CreateDir => [CREATE_DIR]); impl LateLintPass<'_> for CreateDir { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if let ExprKind::Call(func, [arg, ..]) = expr.kind; - if let ExprKind::Path(ref path) = func.kind; - if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id); - then { - span_lint_and_sugg( - cx, - CREATE_DIR, - expr.span, - "calling `std::fs::create_dir` where there may be a better way", - "consider calling `std::fs::create_dir_all` instead", - format!("create_dir_all({})", snippet(cx, arg.span, "..")), - Applicability::MaybeIncorrect, - ) - } + if let ExprKind::Call(func, [arg, ..]) = expr.kind + && let ExprKind::Path(ref path) = func.kind + && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id) + { + span_lint_and_sugg( + cx, + CREATE_DIR, + expr.span, + "calling `std::fs::create_dir` where there may be a better way", + "consider calling `std::fs::create_dir_all` instead", + format!("create_dir_all({})", snippet(cx, arg.span, "..")), + Applicability::MaybeIncorrect, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs index 49452136d6f0c..9424a9103db83 100644 --- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs +++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs @@ -5,8 +5,8 @@ use clippy_utils::{is_in_cfg_test, is_in_test_function}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{sym, BytePos, Pos, Span}; +use rustc_session::impl_lint_pass; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -31,31 +31,6 @@ declare_clippy_lint! { "`dbg!` macro is intended as a debugging tool" } -/// Gets the span of the statement up to the next semicolon, if and only if the next -/// non-whitespace character actually is a semicolon. -/// E.g. -/// ```rust,ignore -/// -/// dbg!(); -/// ^^^^^^^ this span is returned -/// -/// foo!(dbg!()); -/// no span is returned -/// ``` -fn span_including_semi(cx: &LateContext<'_>, span: Span) -> Option { - let sm = cx.sess().source_map(); - let sf = sm.lookup_source_file(span.hi()); - let src = sf.src.as_ref()?.get(span.hi().to_usize()..)?; - let first_non_whitespace = src.find(|c: char| !c.is_whitespace())?; - - if src.as_bytes()[first_non_whitespace] == b';' { - let hi = span.hi() + BytePos::from_usize(first_non_whitespace + 1); - Some(span.with_hi(hi)) - } else { - None - } -} - #[derive(Copy, Clone)] pub struct DbgMacro { allow_dbg_in_tests: bool, @@ -88,10 +63,10 @@ impl LateLintPass<'_> for DbgMacro { ExprKind::Block(..) => { // If the `dbg!` macro is a "free" statement and not contained within other expressions, // remove the whole statement. - if let Some(Node::Stmt(stmt)) = cx.tcx.hir().find_parent(expr.hir_id) - && let Some(span) = span_including_semi(cx, stmt.span.source_callsite()) + if let Some(Node::Stmt(_)) = cx.tcx.hir().find_parent(expr.hir_id) + && let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span) { - (span, String::new()) + (macro_call.span.to(semi_span), String::new()) } else { (macro_call.span, String::from("()")) } diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 1a646ba38c35a..b440e267efe34 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -10,8 +10,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ #[cfg(feature = "internal")] crate::utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS_INFO, #[cfg(feature = "internal")] - crate::utils::internal_lints::if_chain_style::IF_CHAIN_STYLE_INFO, - #[cfg(feature = "internal")] crate::utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL_INFO, #[cfg(feature = "internal")] crate::utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR_INFO, @@ -141,6 +139,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::doc::MISSING_PANICS_DOC_INFO, crate::doc::MISSING_SAFETY_DOC_INFO, crate::doc::NEEDLESS_DOCTEST_MAIN_INFO, + crate::doc::SUSPICIOUS_DOC_COMMENTS_INFO, + crate::doc::TEST_ATTR_IN_DOCTEST_INFO, crate::doc::UNNECESSARY_SAFETY_DOC_INFO, crate::double_parens::DOUBLE_PARENS_INFO, crate::drop_forget_ref::DROP_NON_DROP_INFO, @@ -205,6 +205,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::if_not_else::IF_NOT_ELSE_INFO, crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO, crate::ignored_unit_patterns::IGNORED_UNIT_PATTERNS_INFO, + crate::impl_hash_with_borrow_str_and_bytes::IMPL_HASH_BORROW_WITH_STR_AND_BYTES_INFO, crate::implicit_hasher::IMPLICIT_HASHER_INFO, crate::implicit_return::IMPLICIT_RETURN_INFO, crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO, @@ -232,6 +233,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO, crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO, crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO, + crate::iter_over_hash_type::ITER_OVER_HASH_TYPE_INFO, crate::iter_without_into_iter::INTO_ITER_WITHOUT_ITER_INFO, crate::iter_without_into_iter::ITER_WITHOUT_INTO_ITER_INFO, crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO, @@ -376,6 +378,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::ITER_SKIP_NEXT_INFO, crate::methods::ITER_SKIP_ZERO_INFO, crate::methods::ITER_WITH_DRAIN_INFO, + crate::methods::JOIN_ABSOLUTE_PATHS_INFO, crate::methods::MANUAL_FILTER_MAP_INFO, crate::methods::MANUAL_FIND_MAP_INFO, crate::methods::MANUAL_NEXT_BACK_INFO, @@ -403,6 +406,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::OK_EXPECT_INFO, crate::methods::OPTION_AS_REF_DEREF_INFO, crate::methods::OPTION_FILTER_MAP_INFO, + crate::methods::OPTION_MAP_OR_ERR_OK_INFO, crate::methods::OPTION_MAP_OR_NONE_INFO, crate::methods::OR_FUN_CALL_INFO, crate::methods::OR_THEN_UNWRAP_INFO, @@ -628,7 +632,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::strings::STR_TO_STRING_INFO, crate::strings::TRIM_SPLIT_WHITESPACE_INFO, crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO, - crate::suspicious_doc_comments::SUSPICIOUS_DOC_COMMENTS_INFO, crate::suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS_INFO, crate::suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL_INFO, crate::suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL_INFO, diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index c74b2b8831ec5..d8a070b785d5d 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{has_drop, is_copy}; use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro}; -use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -10,7 +9,7 @@ use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_middle::ty::print::with_forced_trimmed_paths; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{sym, Span}; @@ -81,33 +80,31 @@ impl_lint_pass!(Default => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]); impl<'tcx> LateLintPass<'tcx> for Default { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if !expr.span.from_expansion(); + if !expr.span.from_expansion() // Avoid cases already linted by `field_reassign_with_default` - if !self.reassigned_linted.contains(&expr.span); - if let ExprKind::Call(path, ..) = expr.kind; - if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); - if let ExprKind::Path(ref qpath) = path.kind; - if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::default_fn, def_id); - if !is_update_syntax_base(cx, expr); + && !self.reassigned_linted.contains(&expr.span) + && let ExprKind::Call(path, ..) = expr.kind + && !any_parent_is_automatically_derived(cx.tcx, expr.hir_id) + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::default_fn, def_id) + && !is_update_syntax_base(cx, expr) // Detect and ignore ::default() because these calls do explicitly name the type. - if let QPath::Resolved(None, _path) = qpath; - let expr_ty = cx.typeck_results().expr_ty(expr); - if let ty::Adt(def, ..) = expr_ty.kind(); - if !is_from_proc_macro(cx, expr); - then { - let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did()))); - span_lint_and_sugg( - cx, - DEFAULT_TRAIT_ACCESS, - expr.span, - &format!("calling `{replacement}` is more clear than this expression"), - "try", - replacement, - Applicability::Unspecified, // First resolve the TODO above - ); - } + && let QPath::Resolved(None, _path) = qpath + && let expr_ty = cx.typeck_results().expr_ty(expr) + && let ty::Adt(def, ..) = expr_ty.kind() + && !is_from_proc_macro(cx, expr) + { + let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did()))); + span_lint_and_sugg( + cx, + DEFAULT_TRAIT_ACCESS, + expr.span, + &format!("calling `{replacement}` is more clear than this expression"), + "try", + replacement, + Applicability::Unspecified, // First resolve the TODO above + ); } } @@ -124,38 +121,36 @@ impl<'tcx> LateLintPass<'tcx> for Default { // find all binding statements like `let mut _ = T::default()` where `T::default()` is the // `default` method of the `Default` trait, and store statement index in current block being // checked and the name of the bound variable - let (local, variant, binding_name, binding_type, span) = if_chain! { + let (local, variant, binding_name, binding_type, span) = if let StmtKind::Local(local) = stmt.kind // only take `let ...` statements - if let StmtKind::Local(local) = stmt.kind; - if let Some(expr) = local.init; - if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id); - if !expr.span.from_expansion(); + && let Some(expr) = local.init + && !any_parent_is_automatically_derived(cx.tcx, expr.hir_id) + && !expr.span.from_expansion() // only take bindings to identifiers - if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind; + && let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind // only when assigning `... = Default::default()` - if is_expr_default(expr, cx); - let binding_type = cx.typeck_results().node_type(binding_id); - if let Some(adt) = binding_type.ty_adt_def(); - if adt.is_struct(); - let variant = adt.non_enum_variant(); - if adt.did().is_local() || !variant.is_field_list_non_exhaustive(); - let module_did = cx.tcx.parent_module(stmt.hir_id); - if variant + && is_expr_default(expr, cx) + && let binding_type = cx.typeck_results().node_type(binding_id) + && let Some(adt) = binding_type.ty_adt_def() + && adt.is_struct() + && let variant = adt.non_enum_variant() + && (adt.did().is_local() || !variant.is_field_list_non_exhaustive()) + && let module_did = cx.tcx.parent_module(stmt.hir_id) + && variant .fields .iter() - .all(|field| field.vis.is_accessible_from(module_did, cx.tcx)); - let all_fields_are_copy = variant + .all(|field| field.vis.is_accessible_from(module_did, cx.tcx)) + && let all_fields_are_copy = variant .fields .iter() .all(|field| { is_copy(cx, cx.tcx.type_of(field.did).instantiate_identity()) - }); - if !has_drop(cx, binding_type) || all_fields_are_copy; - then { - (local, variant, ident.name, binding_type, expr.span) - } else { - continue; - } + }) + && (!has_drop(cx, binding_type) || all_fields_are_copy) + { + (local, variant, ident.name, binding_type, expr.span) + } else { + continue; }; let init_ctxt = local.span.ctxt(); @@ -216,21 +211,19 @@ impl<'tcx> LateLintPass<'tcx> for Default { .join(", "); // give correct suggestion if generics are involved (see #6944) - let binding_type = if_chain! { - if let ty::Adt(adt_def, args) = binding_type.kind(); - if !args.is_empty(); - then { - let adt_def_ty_name = cx.tcx.item_name(adt_def.did()); - let generic_args = args.iter().collect::>(); - let tys_str = generic_args - .iter() - .map(ToString::to_string) - .collect::>() - .join(", "); - format!("{adt_def_ty_name}::<{}>", &tys_str) - } else { - binding_type.to_string() - } + let binding_type = if let ty::Adt(adt_def, args) = binding_type.kind() + && !args.is_empty() + { + let adt_def_ty_name = cx.tcx.item_name(adt_def.did()); + let generic_args = args.iter().collect::>(); + let tys_str = generic_args + .iter() + .map(ToString::to_string) + .collect::>() + .join(", "); + format!("{adt_def_ty_name}::<{}>", &tys_str) + } else { + binding_type.to_string() }; let sugg = if ext_with_default { @@ -260,48 +253,42 @@ impl<'tcx> LateLintPass<'tcx> for Default { /// Checks if the given expression is the `default` method belonging to the `Default` trait. fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool { - if_chain! { - if let ExprKind::Call(fn_expr, _) = &expr.kind; - if let ExprKind::Path(qpath) = &fn_expr.kind; - if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); - then { - // right hand side of assignment is `Default::default` - cx.tcx.is_diagnostic_item(sym::default_fn, def_id) - } else { - false - } + if let ExprKind::Call(fn_expr, _) = &expr.kind + && let ExprKind::Path(qpath) = &fn_expr.kind + && let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id) + { + // right hand side of assignment is `Default::default` + cx.tcx.is_diagnostic_item(sym::default_fn, def_id) + } else { + false } } /// Returns the reassigned field and the assigning expression (right-hand side of assign). fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> { - if_chain! { + if let StmtKind::Semi(later_expr) = this.kind // only take assignments - if let StmtKind::Semi(later_expr) = this.kind; - if let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind; + && let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind // only take assignments to fields where the left-hand side field is a field of // the same binding as the previous statement - if let ExprKind::Field(binding, field_ident) = assign_lhs.kind; - if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind; - if let Some(second_binding_name) = path.segments.last(); - if second_binding_name.ident.name == binding_name; - then { - Some((field_ident, assign_rhs)) - } else { - None - } + && let ExprKind::Field(binding, field_ident) = assign_lhs.kind + && let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind + && let Some(second_binding_name) = path.segments.last() + && second_binding_name.ident.name == binding_name + { + Some((field_ident, assign_rhs)) + } else { + None } } /// Returns whether `expr` is the update syntax base: `Foo { a: 1, .. base }` fn is_update_syntax_base<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool { - if_chain! { - if let Some(parent) = get_parent_expr(cx, expr); - if let ExprKind::Struct(_, _, Some(base)) = parent.kind; - then { - base.hir_id == expr.hir_id - } else { - false - } + if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::Struct(_, _, Some(base)) = parent.kind + { + base.hir_id == expr.hir_id + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs index bf070432ef99c..9ce5acfbcc212 100644 --- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs +++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -56,32 +56,30 @@ fn is_alias(ty: hir::Ty<'_>) -> bool { impl LateLintPass<'_> for DefaultConstructedUnitStructs { fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if_chain!( + if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind // make sure we have a call to `Default::default` - if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind; - if let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind; + && let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind // make sure this isn't a type alias: // `::Assoc` cannot be used as a constructor - if !is_alias(*base); - if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); - if cx.tcx.is_diagnostic_item(sym::default_fn, def_id); + && !is_alias(*base) + && let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id) + && cx.tcx.is_diagnostic_item(sym::default_fn, def_id) // make sure we have a struct with no fields (unit struct) - if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind(); - if def.is_struct(); - if let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant(); - if !var.is_field_list_non_exhaustive(); - if !expr.span.from_expansion() && !qpath.span().from_expansion(); - then { - span_lint_and_sugg( - cx, - DEFAULT_CONSTRUCTED_UNIT_STRUCTS, - expr.span.with_lo(qpath.qself_span().hi()), - "use of `default` to create a unit struct", - "remove this call to `default`", - String::new(), - Applicability::MachineApplicable, - ) - } - ); + && let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind() + && def.is_struct() + && let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant() + && !var.is_field_list_non_exhaustive() + && !expr.span.from_expansion() && !qpath.span().from_expansion() + { + span_lint_and_sugg( + cx, + DEFAULT_CONSTRUCTED_UNIT_STRUCTS, + expr.span.with_lo(qpath.qself_span().hi()), + "use of `default` to create a unit struct", + "remove this call to `default`", + String::new(), + Applicability::MachineApplicable, + ); + }; } } diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs index 553b670fdb705..2472e2ee76f93 100644 --- a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs +++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, SyntaxContext}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index b296ea20f9c50..64a924a776a65 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::{get_parent_node, numeric_literal}; -use if_chain::if_chain; use rustc_ast::ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor}; @@ -9,7 +8,7 @@ use rustc_hir::{Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use std::iter; declare_clippy_lint! { @@ -82,40 +81,40 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> { /// Check whether a passed literal has potential to cause fallback or not. fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) { - if_chain! { - if !in_external_macro(self.cx.sess(), lit.span); - if matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false))); - if matches!(lit.node, - LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed)); - then { - let (suffix, is_float) = match lit_ty.kind() { - ty::Int(IntTy::I32) => ("i32", false), - ty::Float(FloatTy::F64) => ("f64", true), - // Default numeric fallback never results in other types. - _ => return, - }; - - let src = if let Some(src) = snippet_opt(self.cx, lit.span) { - src - } else { - match lit.node { - LitKind::Int(src, _) => format!("{src}"), - LitKind::Float(src, _) => format!("{src}"), - _ => return, - } - }; - let sugg = numeric_literal::format(&src, Some(suffix), is_float); - span_lint_hir_and_then( - self.cx, - DEFAULT_NUMERIC_FALLBACK, - emit_hir_id, - lit.span, - "default numeric fallback might occur", - |diag| { - diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect); - } - ); + if !in_external_macro(self.cx.sess(), lit.span) + && matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false))) + && matches!( + lit.node, + LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) + ) + { + let (suffix, is_float) = match lit_ty.kind() { + ty::Int(IntTy::I32) => ("i32", false), + ty::Float(FloatTy::F64) => ("f64", true), + // Default numeric fallback never results in other types. + _ => return, + }; + + let src = if let Some(src) = snippet_opt(self.cx, lit.span) { + src + } else { + match lit.node { + LitKind::Int(src, _) => format!("{src}"), + LitKind::Float(src, _) => format!("{src}"), + _ => return, } + }; + let sugg = numeric_literal::format(&src, Some(suffix), is_float); + span_lint_hir_and_then( + self.cx, + DEFAULT_NUMERIC_FALLBACK, + emit_hir_id, + lit.span, + "default numeric fallback might occur", + |diag| { + diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect); + }, + ); } } } @@ -149,36 +148,33 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { ExprKind::Struct(_, fields, base) => { let ty = self.cx.typeck_results().expr_ty(expr); - if_chain! { - if let Some(adt_def) = ty.ty_adt_def(); - if adt_def.is_struct(); - if let Some(variant) = adt_def.variants().iter().next(); - then { - let fields_def = &variant.fields; - - // Push field type then visit each field expr. - for field in *fields { - let bound = - fields_def - .iter() - .find_map(|f_def| { - if f_def.ident(self.cx.tcx) == field.ident - { Some(self.cx.tcx.type_of(f_def.did).instantiate_identity()) } - else { None } - }); - self.ty_bounds.push(bound.into()); - self.visit_expr(field.expr); - self.ty_bounds.pop(); - } - - // Visit base with no bound. - if let Some(base) = base { - self.ty_bounds.push(ExplicitTyBound(false)); - self.visit_expr(base); - self.ty_bounds.pop(); - } - return; + if let Some(adt_def) = ty.ty_adt_def() + && adt_def.is_struct() + && let Some(variant) = adt_def.variants().iter().next() + { + let fields_def = &variant.fields; + + // Push field type then visit each field expr. + for field in *fields { + let bound = fields_def.iter().find_map(|f_def| { + if f_def.ident(self.cx.tcx) == field.ident { + Some(self.cx.tcx.type_of(f_def.did).instantiate_identity()) + } else { + None + } + }); + self.ty_bounds.push(bound.into()); + self.visit_expr(field.expr); + self.ty_bounds.pop(); + } + + // Visit base with no bound. + if let Some(base) = base { + self.ty_bounds.push(ExplicitTyBound(false)); + self.visit_expr(base); + self.ty_bounds.pop(); } + return; } }, diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs index 8c6749a95fafd..db01ff2cd2205 100644 --- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs +++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs @@ -3,7 +3,7 @@ use rustc_hir::{HirId, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, FieldDef, GenericArg, List}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 6c109a51f83be..854324f845b43 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1,10 +1,11 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; -use clippy_utils::ty::{implements_trait, peel_mid_ty_refs}; +use clippy_utils::ty::{implements_trait, is_manually_drop, peel_mid_ty_refs}; use clippy_utils::{ expr_use_ctxt, get_parent_expr, get_parent_node, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode, }; +use core::mem; use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; @@ -16,7 +17,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -170,9 +171,7 @@ pub struct Dereferencing<'tcx> { #[derive(Debug)] struct StateData<'tcx> { - /// Span of the top level expression - span: Span, - hir_id: HirId, + first_expr: &'tcx Expr<'tcx>, adjusted_ty: Ty<'tcx>, } @@ -198,6 +197,7 @@ enum State { }, ExplicitDerefField { name: Symbol, + derefs_manually_drop: bool, }, Reborrow { mutability: Mutability, @@ -242,7 +242,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { // Stop processing sub expressions when a macro call is seen if expr.span.from_expansion() { if let Some((state, data)) = self.state.take() { - report(cx, expr, state, data); + report(cx, expr, state, data, cx.typeck_results()); } return; } @@ -251,7 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { let Some((kind, sub_expr)) = try_parse_ref_op(cx.tcx, typeck, expr) else { // The whole chain of reference operations has been seen if let Some((state, data)) = self.state.take() { - report(cx, expr, state, data); + report(cx, expr, state, data, typeck); } return; }; @@ -272,14 +272,16 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { (Some(use_cx), RefOp::Deref) => { let sub_ty = typeck.expr_ty(sub_expr); if let ExprUseNode::FieldAccess(name) = use_cx.node - && adjusted_ty.ty_adt_def().map_or(true, |adt| !adt.is_union()) + && !use_cx.moved_before_use && !ty_contains_field(sub_ty, name.name) { self.state = Some(( - State::ExplicitDerefField { name: name.name }, + State::ExplicitDerefField { + name: name.name, + derefs_manually_drop: is_manually_drop(sub_ty), + }, StateData { - span: expr.span, - hir_id: expr.hir_id, + first_expr: expr, adjusted_ty, }, )); @@ -293,8 +295,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { self.state = Some(( State::ExplicitDeref { mutability: None }, StateData { - span: expr.span, - hir_id: expr.hir_id, + first_expr: expr, adjusted_ty, }, )); @@ -313,8 +314,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { mutbl, }, StateData { - span: expr.span, - hir_id: expr.hir_id, + first_expr: expr, adjusted_ty, }, )); @@ -342,8 +342,18 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { TyCoercionStability::for_defined_ty(cx, ty, use_cx.node.is_return()) }); let can_auto_borrow = match use_cx.node { - ExprUseNode::Callee => true, - ExprUseNode::FieldAccess(_) => adjusted_ty.ty_adt_def().map_or(true, |adt| !adt.is_union()), + ExprUseNode::FieldAccess(_) + if !use_cx.moved_before_use && matches!(sub_expr.kind, ExprKind::Field(..)) => + { + // `DerefMut` will not be automatically applied to `ManuallyDrop<_>` + // field expressions when the base type is a union and the parent + // expression is also a field access. + // + // e.g. `&mut x.y.z` where `x` is a union, and accessing `z` requires a + // deref through `ManuallyDrop<_>` will not compile. + !adjust_derefs_manually_drop(use_cx.adjustments, expr_ty) + }, + ExprUseNode::Callee | ExprUseNode::FieldAccess(_) => true, ExprUseNode::MethodArg(hir_id, _, 0) if !use_cx.moved_before_use => { // Check for calls to trait methods where the trait is implemented // on a reference. @@ -357,11 +367,8 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { .tcx .erase_regions(use_cx.adjustments.last().map_or(expr_ty, |a| a.target)) && let ty::Ref(_, sub_ty, _) = *arg_ty.kind() - && let args = cx - .typeck_results() - .node_args_opt(hir_id) - .map(|args| &args[1..]) - .unwrap_or_default() + && let args = + typeck.node_args_opt(hir_id).map(|args| &args[1..]).unwrap_or_default() && let impl_ty = if cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder().inputs()[0] .is_ref() @@ -436,14 +443,16 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { count: deref_count - required_refs, msg, stability, - for_field_access: match use_cx.node { - ExprUseNode::FieldAccess(name) => Some(name.name), - _ => None, + for_field_access: if let ExprUseNode::FieldAccess(name) = use_cx.node + && !use_cx.moved_before_use + { + Some(name.name) + } else { + None }, }), StateData { - span: expr.span, - hir_id: expr.hir_id, + first_expr: expr, adjusted_ty: use_cx.adjustments.last().map_or(expr_ty, |a| a.target), }, )); @@ -455,8 +464,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { self.state = Some(( State::Borrow { mutability }, StateData { - span: expr.span, - hir_id: expr.hir_id, + first_expr: expr, adjusted_ty: use_cx.adjustments.last().map_or(expr_ty, |a| a.target), }, )); @@ -501,13 +509,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf(mutability)) => { let adjusted_ty = data.adjusted_ty; let stability = state.stability; - report(cx, expr, State::DerefedBorrow(state), data); + report(cx, expr, State::DerefedBorrow(state), data, typeck); if stability.is_deref_stable() { self.state = Some(( State::Borrow { mutability }, StateData { - span: expr.span, - hir_id: expr.hir_id, + first_expr: expr, adjusted_ty, }, )); @@ -517,15 +524,18 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { let adjusted_ty = data.adjusted_ty; let stability = state.stability; let for_field_access = state.for_field_access; - report(cx, expr, State::DerefedBorrow(state), data); + report(cx, expr, State::DerefedBorrow(state), data, typeck); if let Some(name) = for_field_access - && !ty_contains_field(typeck.expr_ty(sub_expr), name) + && let sub_expr_ty = typeck.expr_ty(sub_expr) + && !ty_contains_field(sub_expr_ty, name) { self.state = Some(( - State::ExplicitDerefField { name }, + State::ExplicitDerefField { + name, + derefs_manually_drop: is_manually_drop(sub_expr_ty), + }, StateData { - span: expr.span, - hir_id: expr.hir_id, + first_expr: expr, adjusted_ty, }, )); @@ -535,8 +545,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { self.state = Some(( State::ExplicitDeref { mutability: None }, StateData { - span: parent.span, - hir_id: parent.hir_id, + first_expr: parent, adjusted_ty, }, )); @@ -566,13 +575,28 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { (state @ Some((State::ExplicitDeref { .. }, _)), RefOp::Deref) => { self.state = state; }, - (Some((State::ExplicitDerefField { name }, data)), RefOp::Deref) - if !ty_contains_field(typeck.expr_ty(sub_expr), name) => + ( + Some(( + State::ExplicitDerefField { + name, + derefs_manually_drop, + }, + data, + )), + RefOp::Deref, + ) if let sub_expr_ty = typeck.expr_ty(sub_expr) + && !ty_contains_field(sub_expr_ty, name) => { - self.state = Some((State::ExplicitDerefField { name }, data)); + self.state = Some(( + State::ExplicitDerefField { + name, + derefs_manually_drop: derefs_manually_drop || is_manually_drop(sub_expr_ty), + }, + data, + )); }, - (Some((state, data)), _) => report(cx, expr, state, data), + (Some((state, data)), _) => report(cx, expr, state, data, typeck), } } @@ -597,26 +621,24 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { return; } - if_chain! { - if !pat.span.from_expansion(); - if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind(); + if !pat.span.from_expansion() + && let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind() // only lint immutable refs, because borrowed `&mut T` cannot be moved out - if let ty::Ref(_, _, Mutability::Not) = *tam.kind(); - then { - let mut app = Applicability::MachineApplicable; - let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0; - self.current_body = self.current_body.or(cx.enclosing_body); - self.ref_locals.insert( - id, - Some(RefPat { - always_deref: true, - spans: vec![pat.span], - app, - replacements: vec![(pat.span, snip.into())], - hir_id: pat.hir_id, - }), - ); - } + && let ty::Ref(_, _, Mutability::Not) = *tam.kind() + { + let mut app = Applicability::MachineApplicable; + let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0; + self.current_body = self.current_body.or(cx.enclosing_body); + self.ref_locals.insert( + id, + Some(RefPat { + always_deref: true, + spans: vec![pat.span], + app, + replacements: vec![(pat.span, snip.into())], + hir_id: pat.hir_id, + }), + ); } } } @@ -689,6 +711,14 @@ fn try_parse_ref_op<'tcx>( } } +// Checks if the adjustments contains a deref of `ManuallyDrop<_>` +fn adjust_derefs_manually_drop<'tcx>(adjustments: &'tcx [Adjustment<'tcx>], mut ty: Ty<'tcx>) -> bool { + adjustments.iter().any(|a| { + let ty = mem::replace(&mut ty, a.target); + matches!(a.kind, Adjust::Deref(Some(ref op)) if op.mutbl == Mutability::Mut) && is_manually_drop(ty) + }) +} + // Checks whether the type for a deref call actually changed the type, not just the mutability of // the reference. fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool { @@ -741,7 +771,7 @@ impl TyCoercionStability { DefinedTy::Mir(ty) => Self::for_mir_ty( cx.tcx, ty.param_env, - cx.tcx.erase_late_bound_regions(ty.value), + cx.tcx.instantiate_bound_regions_with_erased(ty.value), for_return, ), } @@ -898,7 +928,13 @@ fn ty_contains_field(ty: Ty<'_>, name: Symbol) -> bool { } #[expect(clippy::needless_pass_by_value, clippy::too_many_lines)] -fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData<'tcx>) { +fn report<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + state: State, + data: StateData<'tcx>, + typeck: &'tcx TypeckResults<'tcx>, +) { match state { State::DerefMethod { ty_changed_count, @@ -906,8 +942,9 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data mutbl, } => { let mut app = Applicability::MachineApplicable; - let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); - let ty = cx.typeck_results().expr_ty(expr); + let (expr_str, _expr_is_macro_call) = + snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); + let ty = typeck.expr_ty(expr); let (_, ref_count) = peel_mid_ty_refs(ty); let deref_str = if ty_changed_count >= ref_count && ref_count != 0 { // a deref call changing &T -> &U requires two deref operators the first time @@ -947,7 +984,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data span_lint_and_sugg( cx, EXPLICIT_DEREF_METHODS, - data.span, + data.first_expr.span, match mutbl { Mutability::Not => "explicit `deref` method call", Mutability::Mut => "explicit `deref_mut` method call", @@ -959,26 +996,34 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data }, State::DerefedBorrow(state) => { let mut app = Applicability::MachineApplicable; - let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); - span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, state.msg, |diag| { - let (precedence, calls_field) = match get_parent_node(cx.tcx, data.hir_id) { - Some(Node::Expr(e)) => match e.kind { - ExprKind::Call(callee, _) if callee.hir_id != data.hir_id => (0, false), - ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))), - _ => (e.precedence().order(), false), - }, - _ => (0, false), - }; - let sugg = if !snip_is_macro - && (calls_field || expr.precedence().order() < precedence) - && !has_enclosing_paren(&snip) - { - format!("({snip})") - } else { - snip.into() - }; - diag.span_suggestion(data.span, "change this to", sugg, app); - }); + let (snip, snip_is_macro) = + snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); + span_lint_hir_and_then( + cx, + NEEDLESS_BORROW, + data.first_expr.hir_id, + data.first_expr.span, + state.msg, + |diag| { + let (precedence, calls_field) = match get_parent_node(cx.tcx, data.first_expr.hir_id) { + Some(Node::Expr(e)) => match e.kind { + ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false), + ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))), + _ => (e.precedence().order(), false), + }, + _ => (0, false), + }; + let sugg = if !snip_is_macro + && (calls_field || expr.precedence().order() < precedence) + && !has_enclosing_paren(&snip) + { + format!("({snip})") + } else { + snip.into() + }; + diag.span_suggestion(data.first_expr.span, "change this to", sugg, app); + }, + ); }, State::ExplicitDeref { mutability } => { if matches!( @@ -996,7 +1041,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data } let (prefix, precedence) = if let Some(mutability) = mutability - && !cx.typeck_results().expr_ty(expr).is_ref() + && !typeck.expr_ty(expr).is_ref() { let prefix = match mutability { Mutability::Not => "&", @@ -1009,53 +1054,61 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data span_lint_hir_and_then( cx, EXPLICIT_AUTO_DEREF, - data.hir_id, - data.span, + data.first_expr.hir_id, + data.first_expr.span, "deref which would be done by auto-deref", |diag| { let mut app = Applicability::MachineApplicable; - let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); + let (snip, snip_is_macro) = + snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); let sugg = if !snip_is_macro && expr.precedence().order() < precedence && !has_enclosing_paren(&snip) { format!("{prefix}({snip})") } else { format!("{prefix}{snip}") }; - diag.span_suggestion(data.span, "try", sugg, app); + diag.span_suggestion(data.first_expr.span, "try", sugg, app); }, ); }, - State::ExplicitDerefField { .. } => { - if matches!( - expr.kind, - ExprKind::Block(..) - | ExprKind::ConstBlock(_) - | ExprKind::If(..) - | ExprKind::Loop(..) - | ExprKind::Match(..) - ) && data.adjusted_ty.is_sized(cx.tcx, cx.param_env) - { - // Rustc bug: auto deref doesn't work on block expression when targeting sized types. - return; - } - - if let ExprKind::Field(parent_expr, _) = expr.kind - && let ty::Adt(adt, _) = cx.typeck_results().expr_ty(parent_expr).kind() - && adt.is_union() - { - // Auto deref does not apply on union field - return; - } + State::ExplicitDerefField { + derefs_manually_drop, .. + } => { + let (snip_span, needs_parens) = if matches!(expr.kind, ExprKind::Field(..)) + && (derefs_manually_drop + || adjust_derefs_manually_drop( + typeck.expr_adjustments(data.first_expr), + typeck.expr_ty(data.first_expr), + )) { + // `DerefMut` will not be automatically applied to `ManuallyDrop<_>` + // field expressions when the base type is a union and the parent + // expression is also a field access. + // + // e.g. `&mut x.y.z` where `x` is a union, and accessing `z` requires a + // deref through `ManuallyDrop<_>` will not compile. + let parent_id = cx.tcx.hir().parent_id(expr.hir_id); + if parent_id == data.first_expr.hir_id { + return; + } + (cx.tcx.hir().get(parent_id).expect_expr().span, true) + } else { + (expr.span, false) + }; span_lint_hir_and_then( cx, EXPLICIT_AUTO_DEREF, - data.hir_id, - data.span, + data.first_expr.hir_id, + data.first_expr.span, "deref which would be done by auto-deref", |diag| { let mut app = Applicability::MachineApplicable; - let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0; - diag.span_suggestion(data.span, "try", snip.into_owned(), app); + let snip = snippet_with_context(cx, snip_span, data.first_expr.span.ctxt(), "..", &mut app).0; + let sugg = if needs_parens { + format!("({snip})") + } else { + snip.into_owned() + }; + diag.span_suggestion(data.first_expr.span, "try", sugg, app); }, ); }, diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index a450becc647f3..53ef6d7e387e4 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -10,7 +10,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::{self, Adt, AdtDef, GenericArgsRef, Ty, TypeckResults}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -148,83 +148,65 @@ fn check_struct<'tcx>( } fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>) { - if_chain! { - if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind; - if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res; - if let variant_id = cx.tcx.parent(id); - if let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id); - if variant_def.fields.is_empty(); - if !variant_def.is_field_list_non_exhaustive(); - - then { - let enum_span = cx.tcx.def_span(adt_def.did()); - let indent_enum = indent_of(cx, enum_span).unwrap_or(0); - let variant_span = cx.tcx.def_span(variant_def.def_id); - let indent_variant = indent_of(cx, variant_span).unwrap_or(0); - span_lint_and_then( - cx, - DERIVABLE_IMPLS, + if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind + && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res + && let variant_id = cx.tcx.parent(id) + && let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id) + && variant_def.fields.is_empty() + && !variant_def.is_field_list_non_exhaustive() + { + let enum_span = cx.tcx.def_span(adt_def.did()); + let indent_enum = indent_of(cx, enum_span).unwrap_or(0); + let variant_span = cx.tcx.def_span(variant_def.def_id); + let indent_variant = indent_of(cx, variant_span).unwrap_or(0); + span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| { + diag.span_suggestion_hidden( item.span, - "this `impl` can be derived", - |diag| { - diag.span_suggestion_hidden( - item.span, - "remove the manual implementation...", - String::new(), - Applicability::MachineApplicable - ); - diag.span_suggestion( - enum_span.shrink_to_lo(), - "...and instead derive it...", - format!( - "#[derive(Default)]\n{indent}", - indent = " ".repeat(indent_enum), - ), - Applicability::MachineApplicable - ); - diag.span_suggestion( - variant_span.shrink_to_lo(), - "...and mark the default variant", - format!( - "#[default]\n{indent}", - indent = " ".repeat(indent_variant), - ), - Applicability::MachineApplicable - ); - } + "remove the manual implementation...", + String::new(), + Applicability::MachineApplicable, ); - } + diag.span_suggestion( + enum_span.shrink_to_lo(), + "...and instead derive it...", + format!("#[derive(Default)]\n{indent}", indent = " ".repeat(indent_enum),), + Applicability::MachineApplicable, + ); + diag.span_suggestion( + variant_span.shrink_to_lo(), + "...and mark the default variant", + format!("#[default]\n{indent}", indent = " ".repeat(indent_variant),), + Applicability::MachineApplicable, + ); + }); } } impl<'tcx> LateLintPass<'tcx> for DerivableImpls { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if_chain! { - if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), - items: [child], - self_ty, - .. - }) = item.kind; - if !cx.tcx.has_attr(item.owner_id, sym::automatically_derived); - if !item.span.from_expansion(); - if let Some(def_id) = trait_ref.trait_def_id(); - if cx.tcx.is_diagnostic_item(sym::Default, def_id); - if let impl_item_hir = child.id.hir_id(); - if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir); - if let ImplItemKind::Fn(_, b) = &impl_item.kind; - if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b); - if let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind(); - if let attrs = cx.tcx.hir().attrs(item.hir_id()); - if !attrs.iter().any(|attr| attr.doc_str().is_some()); - if cx.tcx.hir().attrs(impl_item_hir).is_empty(); - - then { - if adt_def.is_struct() { - check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b)); - } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) { - check_enum(cx, item, func_expr, adt_def); - } + if let ItemKind::Impl(Impl { + of_trait: Some(ref trait_ref), + items: [child], + self_ty, + .. + }) = item.kind + && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) + && !item.span.from_expansion() + && let Some(def_id) = trait_ref.trait_def_id() + && cx.tcx.is_diagnostic_item(sym::Default, def_id) + && let impl_item_hir = child.id.hir_id() + && let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir) + && let ImplItemKind::Fn(_, b) = &impl_item.kind + && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b) + && let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() + && let attrs = cx.tcx.hir().attrs(item.hir_id()) + && !attrs.iter().any(|attr| attr.doc_str().is_some()) + && cx.tcx.hir().attrs(impl_item_hir).is_empty() + { + if adt_def.is_struct() { + check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b)); + } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) { + check_enum(cx, item, func_expr, adt_def); } } } diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 3a331564db970..61faaa10b8a43 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy}; use clippy_utils::{is_lint_allowed, match_def_path, paths}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor}; @@ -15,7 +14,7 @@ use rustc_middle::ty::{ self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, Ty, TyCtxt, }; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -232,42 +231,37 @@ fn check_hash_peq<'tcx>( ty: Ty<'tcx>, hash_is_automatically_derived: bool, ) { - if_chain! { - if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait(); - if let Some(def_id) = trait_ref.trait_def_id(); - if cx.tcx.is_diagnostic_item(sym::Hash, def_id); - then { - // Look for the PartialEq implementations for `ty` - cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { - let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived); - - if !hash_is_automatically_derived || peq_is_automatically_derived { - return; - } - - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); - - // Only care about `impl PartialEq for Foo` - // For `impl PartialEq for A, input_types is [A, B] - if trait_ref.instantiate_identity().args.type_at(1) == ty { - span_lint_and_then( - cx, - DERIVED_HASH_WITH_MANUAL_EQ, - span, - "you are deriving `Hash` but have implemented `PartialEq` explicitly", - |diag| { - if let Some(local_def_id) = impl_id.as_local() { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id); - diag.span_note( - cx.tcx.hir().span(hir_id), - "`PartialEq` implemented here" - ); - } + if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait() + && let Some(def_id) = trait_ref.trait_def_id() + && cx.tcx.is_diagnostic_item(sym::Hash, def_id) + { + // Look for the PartialEq implementations for `ty` + cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { + let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived); + + if !hash_is_automatically_derived || peq_is_automatically_derived { + return; + } + + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + + // Only care about `impl PartialEq for Foo` + // For `impl PartialEq for A, input_types is [A, B] + if trait_ref.instantiate_identity().args.type_at(1) == ty { + span_lint_and_then( + cx, + DERIVED_HASH_WITH_MANUAL_EQ, + span, + "you are deriving `Hash` but have implemented `PartialEq` explicitly", + |diag| { + if let Some(local_def_id) = impl_id.as_local() { + let hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id); + diag.span_note(cx.tcx.hir().span(hir_id), "`PartialEq` implemented here"); } - ); - } - }); - } + }, + ); + } + }); } } @@ -279,49 +273,38 @@ fn check_ord_partial_ord<'tcx>( ty: Ty<'tcx>, ord_is_automatically_derived: bool, ) { - if_chain! { - if let Some(ord_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Ord); - if let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); - if let Some(def_id) = &trait_ref.trait_def_id(); - if *def_id == ord_trait_def_id; - then { - // Look for the PartialOrd implementations for `ty` - cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| { - let partial_ord_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived); - - if partial_ord_is_automatically_derived == ord_is_automatically_derived { - return; - } - - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); - - // Only care about `impl PartialOrd for Foo` - // For `impl PartialOrd for A, input_types is [A, B] - if trait_ref.instantiate_identity().args.type_at(1) == ty { - let mess = if partial_ord_is_automatically_derived { - "you are implementing `Ord` explicitly but have derived `PartialOrd`" - } else { - "you are deriving `Ord` but have implemented `PartialOrd` explicitly" - }; - - span_lint_and_then( - cx, - DERIVE_ORD_XOR_PARTIAL_ORD, - span, - mess, - |diag| { - if let Some(local_def_id) = impl_id.as_local() { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id); - diag.span_note( - cx.tcx.hir().span(hir_id), - "`PartialOrd` implemented here" - ); - } - } - ); - } - }); - } + if let Some(ord_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Ord) + && let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait() + && let Some(def_id) = &trait_ref.trait_def_id() + && *def_id == ord_trait_def_id + { + // Look for the PartialOrd implementations for `ty` + cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| { + let partial_ord_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived); + + if partial_ord_is_automatically_derived == ord_is_automatically_derived { + return; + } + + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + + // Only care about `impl PartialOrd for Foo` + // For `impl PartialOrd for A, input_types is [A, B] + if trait_ref.instantiate_identity().args.type_at(1) == ty { + let mess = if partial_ord_is_automatically_derived { + "you are implementing `Ord` explicitly but have derived `PartialOrd`" + } else { + "you are deriving `Ord` but have implemented `PartialOrd` explicitly" + }; + + span_lint_and_then(cx, DERIVE_ORD_XOR_PARTIAL_ORD, span, mess, |diag| { + if let Some(local_def_id) = impl_id.as_local() { + let hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id); + diag.span_note(cx.tcx.hir().span(hir_id), "`PartialOrd` implemented here"); + } + }); + } + }); } } @@ -394,27 +377,27 @@ fn check_unsafe_derive_deserialize<'tcx>( visitor.has_unsafe } - if_chain! { - if let Some(trait_def_id) = trait_ref.trait_def_id(); - if match_def_path(cx, trait_def_id, &paths::SERDE_DESERIALIZE); - if let ty::Adt(def, _) = ty.kind(); - if let Some(local_def_id) = def.did().as_local(); - let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id); - if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id); - if cx.tcx.inherent_impls(def.did()) + if let Some(trait_def_id) = trait_ref.trait_def_id() + && match_def_path(cx, trait_def_id, &paths::SERDE_DESERIALIZE) + && let ty::Adt(def, _) = ty.kind() + && let Some(local_def_id) = def.did().as_local() + && let adt_hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id) + && !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id) + && cx + .tcx + .inherent_impls(def.did()) .iter() .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local())) - .any(|imp| has_unsafe(cx, imp)); - then { - span_lint_and_help( - cx, - UNSAFE_DERIVE_DESERIALIZE, - item.span, - "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`", - None, - "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html" - ); - } + .any(|imp| has_unsafe(cx, imp)) + { + span_lint_and_help( + cx, + UNSAFE_DERIVE_DESERIALIZE, + item.span, + "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`", + None, + "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html", + ); } } @@ -431,12 +414,10 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { return; } - if_chain! { - if let Some(header) = kind.header(); - if header.unsafety == Unsafety::Unsafe; - then { - self.has_unsafe = true; - } + if let Some(header) = kind.header() + && header.unsafety == Unsafety::Unsafe + { + self.has_unsafe = true; } walk_fn(self, kind, decl, body_id, id); @@ -463,30 +444,28 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { /// Implementation of the `DERIVE_PARTIAL_EQ_WITHOUT_EQ` lint. fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) { - if_chain! { - if let ty::Adt(adt, args) = ty.kind(); - if cx.tcx.visibility(adt.did()).is_public(); - if let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq); - if let Some(def_id) = trait_ref.trait_def_id(); - if cx.tcx.is_diagnostic_item(sym::PartialEq, def_id); - let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id); - if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]); + if let ty::Adt(adt, args) = ty.kind() + && cx.tcx.visibility(adt.did()).is_public() + && let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq) + && let Some(def_id) = trait_ref.trait_def_id() + && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) + && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) + && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]) // If all of our fields implement `Eq`, we can implement `Eq` too - if adt + && adt .all_fields() .map(|f| f.ty(cx.tcx, args)) - .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[])); - then { - span_lint_and_sugg( - cx, - DERIVE_PARTIAL_EQ_WITHOUT_EQ, - span.ctxt().outer_expn_data().call_site, - "you are deriving `PartialEq` and can implement `Eq`", - "consider deriving `Eq` as well", - "PartialEq, Eq".to_string(), - Applicability::MachineApplicable, - ) - } + .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[])) + { + span_lint_and_sugg( + cx, + DERIVE_PARTIAL_EQ_WITHOUT_EQ, + span.ctxt().outer_expn_data().call_site, + "you are deriving `PartialEq` and can implement `Eq`", + "consider deriving `Eq` as well", + "PartialEq, Eq".to_string(), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs index 324b5e0798edd..656b3d9bfaf1b 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefIdMap; use rustc_hir::{Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, Pat, Path, Stmt, TraitItem, Ty}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{ExpnId, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs index d23aeebb5a8a0..1868d3cd39156 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs @@ -4,7 +4,7 @@ use clippy_utils::{fn_def_id, get_parent_expr, path_def_id}; use rustc_hir::def_id::DefIdMap; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/disallowed_names.rs b/src/tools/clippy/clippy_lints/src/disallowed_names.rs index 5e46b29b63972..09dad5554ad73 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_names.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_names.rs @@ -3,7 +3,7 @@ use clippy_utils::is_test_module_or_function; use rustc_data_structures::fx::FxHashSet; use rustc_hir::{Item, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does @@ -31,9 +31,9 @@ pub struct DisallowedNames { } impl DisallowedNames { - pub fn new(disallow: FxHashSet) -> Self { + pub fn new(disallowed_names: &[String]) -> Self { Self { - disallow, + disallow: disallowed_names.iter().cloned().collect(), test_modules_deep: 0, } } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs index 96a7f0e4fde17..d5205e65cef3a 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use unicode_script::{Script, UnicodeScript}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs index 3578fb640fc47..130f56b698ffc 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs @@ -5,7 +5,7 @@ use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::{Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/doc/link_with_quotes.rs b/src/tools/clippy/clippy_lints/src/doc/link_with_quotes.rs new file mode 100644 index 0000000000000..01191e811b003 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/link_with_quotes.rs @@ -0,0 +1,20 @@ +use std::ops::Range; + +use clippy_utils::diagnostics::span_lint; +use rustc_lint::LateContext; + +use super::{Fragments, DOC_LINK_WITH_QUOTES}; + +pub fn check(cx: &LateContext<'_>, trimmed_text: &str, range: Range, fragments: Fragments<'_>) { + if ((trimmed_text.starts_with('\'') && trimmed_text.ends_with('\'')) + || (trimmed_text.starts_with('"') && trimmed_text.ends_with('"'))) + && let Some(span) = fragments.span(cx, range) + { + span_lint( + cx, + DOC_LINK_WITH_QUOTES, + span, + "possible intra-doc link using quotes instead of backticks", + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs new file mode 100644 index 0000000000000..c0b11eb0dd16e --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs @@ -0,0 +1,109 @@ +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::source::snippet_with_applicability; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_lint::LateContext; +use rustc_span::{BytePos, Pos, Span}; +use url::Url; + +use crate::doc::DOC_MARKDOWN; + +pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet, text: &str, span: Span) { + for word in text.split(|c: char| c.is_whitespace() || c == '\'') { + // Trim punctuation as in `some comment (see foo::bar).` + // ^^ + // Or even as in `_foo bar_` which is emphasized. Also preserve `::` as a prefix/suffix. + let mut word = word.trim_matches(|c: char| !c.is_alphanumeric() && c != ':'); + + // Remove leading or trailing single `:` which may be part of a sentence. + if word.starts_with(':') && !word.starts_with("::") { + word = word.trim_start_matches(':'); + } + if word.ends_with(':') && !word.ends_with("::") { + word = word.trim_end_matches(':'); + } + + if valid_idents.contains(word) || word.chars().all(|c| c == ':') { + continue; + } + + // Adjust for the current word + let offset = word.as_ptr() as usize - text.as_ptr() as usize; + let span = Span::new( + span.lo() + BytePos::from_usize(offset), + span.lo() + BytePos::from_usize(offset + word.len()), + span.ctxt(), + span.parent(), + ); + + check_word(cx, word, span); + } +} + +fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { + /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and + /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case + /// letter (`NASA` is ok). + /// Plurals are also excluded (`IDs` is ok). + fn is_camel_case(s: &str) -> bool { + if s.starts_with(|c: char| c.is_ascii_digit() | c.is_ascii_lowercase()) { + return false; + } + + let s = s.strip_suffix('s').unwrap_or(s); + + s.chars().all(char::is_alphanumeric) + && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 + && s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 + } + + fn has_underscore(s: &str) -> bool { + s != "_" && !s.contains("\\_") && s.contains('_') + } + + fn has_hyphen(s: &str) -> bool { + s != "-" && s.contains('-') + } + + if let Ok(url) = Url::parse(word) { + // try to get around the fact that `foo::bar` parses as a valid URL + if !url.cannot_be_a_base() { + span_lint( + cx, + DOC_MARKDOWN, + span, + "you should put bare URLs between `<`/`>` or make a proper Markdown link", + ); + + return; + } + } + + // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343) + if has_underscore(word) && has_hyphen(word) { + return; + } + + if has_underscore(word) || word.contains("::") || is_camel_case(word) { + let mut applicability = Applicability::MachineApplicable; + + span_lint_and_then( + cx, + DOC_MARKDOWN, + span, + "item in documentation is missing backticks", + |diag| { + let snippet = snippet_with_applicability(cx, span, "..", &mut applicability); + diag.span_suggestion_with_style( + span, + "try", + format!("`{snippet}`"), + applicability, + // always show the suggestion in a separate line, since the + // inline presentation adds another pair of backticks + SuggestionStyle::ShowAlways, + ); + }, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs new file mode 100644 index 0000000000000..4cbfa97a8a35f --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs @@ -0,0 +1,86 @@ +use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use clippy_utils::{is_doc_hidden, return_ty}; +use rustc_hir::{BodyId, FnSig, OwnerId, Unsafety}; +use rustc_lint::LateContext; +use rustc_middle::ty; +use rustc_span::{sym, Span}; + +use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC}; + +pub fn check( + cx: &LateContext<'_>, + owner_id: OwnerId, + sig: &FnSig<'_>, + headers: DocHeaders, + body_id: Option, + panic_span: Option, + check_private_items: bool, +) { + if !check_private_items && !cx.effective_visibilities.is_exported(owner_id.def_id) { + return; // Private functions do not require doc comments + } + + // do not lint if any parent has `#[doc(hidden)]` attribute (#7347) + if !check_private_items + && cx + .tcx + .hir() + .parent_iter(owner_id.into()) + .any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id))) + { + return; + } + + let span = cx.tcx.def_span(owner_id); + match (headers.safety, sig.header.unsafety) { + (false, Unsafety::Unsafe) => span_lint( + cx, + MISSING_SAFETY_DOC, + span, + "unsafe function's docs miss `# Safety` section", + ), + (true, Unsafety::Normal) => span_lint( + cx, + UNNECESSARY_SAFETY_DOC, + span, + "safe function's docs have unnecessary `# Safety` section", + ), + _ => (), + } + if !headers.panics && panic_span.is_some() { + span_lint_and_note( + cx, + MISSING_PANICS_DOC, + span, + "docs for function which may panic missing `# Panics` section", + panic_span, + "first possible panic found here", + ); + } + if !headers.errors { + if is_type_diagnostic_item(cx, return_ty(cx, owner_id), sym::Result) { + span_lint( + cx, + MISSING_ERRORS_DOC, + span, + "docs for function returning `Result` missing `# Errors` section", + ); + } else if let Some(body_id) = body_id + && let Some(future) = cx.tcx.lang_items().future_trait() + && let typeck = cx.tcx.typeck_body(body_id) + && let body = cx.tcx.hir().body(body_id) + && let ret_ty = typeck.expr_ty(body.value) + && implements_trait(cx, ret_ty, future, &[]) + && let ty::Coroutine(_, subs, _) = ret_ty.kind() + && is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result) + { + span_lint( + cx, + MISSING_ERRORS_DOC, + span, + "docs for function returning `Result` missing `# Errors` section", + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs similarity index 60% rename from src/tools/clippy/clippy_lints/src/doc.rs rename to src/tools/clippy/clippy_lints/src/doc/mod.rs index 8982fca6e89be..ba452775015dd 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -1,20 +1,16 @@ use clippy_utils::attrs::is_doc_hidden; -use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; -use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; -use clippy_utils::{is_entrypoint_fn, method_chain_args, return_ty}; -use if_chain::if_chain; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::visitors::Visitable; +use clippy_utils::{is_entrypoint_fn, method_chain_args}; use pulldown_cmark::Event::{ Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text, }; use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph}; use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options}; -use rustc_ast::ast::{Async, Attribute, Fn, FnRetTy, ItemKind}; +use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::Lrc; -use rustc_errors::emitter::EmitterWriter; -use rustc_errors::{Applicability, Handler, SuggestionStyle}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AnonConst, Expr}; @@ -22,20 +18,21 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_parse::maybe_new_parser_from_source_str; -use rustc_parse::parser::ForceCollect; use rustc_resolve::rustdoc::{ add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, DocFragment, }; -use rustc_session::parse::ParseSess; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::edition::Edition; -use rustc_span::{sym, BytePos, FileName, Pos, Span}; -use rustc_span::source_map::{FilePathMapping, SourceMap}; +use rustc_span::{sym, Span}; use std::ops::Range; -use std::{io, thread}; use url::Url; +mod link_with_quotes; +mod markdown; +mod missing_headers; +mod needless_doctest_main; +mod suspicious_doc_comments; + declare_clippy_lint! { /// ### What it does /// Checks for the presence of `_`, `::` or camel-case words @@ -202,6 +199,39 @@ declare_clippy_lint! { "presence of `fn main() {` in code examples" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[test]` in doctests unless they are marked with + /// either `ignore`, `no_run` or `compile_fail`. + /// + /// ### Why is this bad? + /// Code in examples marked as `#[test]` will somewhat + /// surprisingly not be run by `cargo test`. If you really want + /// to show how to test stuff in an example, mark it `no_run` to + /// make the intent clear. + /// + /// ### Examples + /// ```no_run + /// /// An example of a doctest with a `main()` function + /// /// + /// /// # Examples + /// /// + /// /// ``` + /// /// #[test] + /// /// fn equality_works() { + /// /// assert_eq!(1_u8, 1); + /// /// } + /// /// ``` + /// fn test_attr_in_doctest() { + /// unimplemented!(); + /// } + /// ``` + #[clippy::version = "1.40.0"] + pub TEST_ATTR_IN_DOCTEST, + suspicious, + "presence of `#[test]` in code examples" +} + declare_clippy_lint! { /// ### What it does /// Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks) @@ -261,33 +291,83 @@ declare_clippy_lint! { "`pub fn` or `pub trait` with `# Safety` docs" } -#[expect(clippy::module_name_repetitions)] +declare_clippy_lint! { + /// ### What it does + /// Detects the use of outer doc comments (`///`, `/**`) followed by a bang (`!`): `///!` + /// + /// ### Why is this bad? + /// Triple-slash comments (known as "outer doc comments") apply to items that follow it. + /// An outer doc comment followed by a bang (i.e. `///!`) has no specific meaning. + /// + /// The user most likely meant to write an inner doc comment (`//!`, `/*!`), which + /// applies to the parent item (i.e. the item that the comment is contained in, + /// usually a module or crate). + /// + /// ### Known problems + /// Inner doc comments can only appear before items, so there are certain cases where the suggestion + /// made by this lint is not valid code. For example: + /// ```rs + /// fn foo() {} + /// ///! + /// fn bar() {} + /// ``` + /// This lint detects the doc comment and suggests changing it to `//!`, but an inner doc comment + /// is not valid at that position. + /// + /// ### Example + /// In this example, the doc comment is attached to the *function*, rather than the *module*. + /// ```no_run + /// pub mod util { + /// ///! This module contains utility functions. + /// + /// pub fn dummy() {} + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// pub mod util { + /// //! This module contains utility functions. + /// + /// pub fn dummy() {} + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub SUSPICIOUS_DOC_COMMENTS, + suspicious, + "suspicious usage of (outer) doc comments" +} + #[derive(Clone)] -pub struct DocMarkdown { +pub struct Documentation { valid_idents: FxHashSet, in_trait_impl: bool, + check_private_items: bool, } -impl DocMarkdown { - pub fn new(valid_idents: FxHashSet) -> Self { +impl Documentation { + pub fn new(valid_idents: &[String], check_private_items: bool) -> Self { Self { - valid_idents, + valid_idents: valid_idents.iter().cloned().collect(), in_trait_impl: false, + check_private_items, } } } -impl_lint_pass!(DocMarkdown => [ +impl_lint_pass!(Documentation => [ DOC_LINK_WITH_QUOTES, DOC_MARKDOWN, MISSING_SAFETY_DOC, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, NEEDLESS_DOCTEST_MAIN, + TEST_ATTR_IN_DOCTEST, UNNECESSARY_SAFETY_DOC, + SUSPICIOUS_DOC_COMMENTS ]); -impl<'tcx> LateLintPass<'tcx> for DocMarkdown { +impl<'tcx> LateLintPass<'tcx> for Documentation { fn check_crate(&mut self, cx: &LateContext<'tcx>) { let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID); check_attrs(cx, &self.valid_idents, attrs); @@ -302,13 +382,17 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { hir::ItemKind::Fn(ref sig, _, body_id) => { if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) { let body = cx.tcx.hir().body(body_id); - let mut fpu = FindPanicUnwrap { + + let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); + missing_headers::check( cx, - typeck_results: cx.tcx.typeck(item.owner_id.def_id), - panic_span: None, - }; - fpu.visit_expr(body.value); - lint_for_missing_headers(cx, item.owner_id, sig, headers, Some(body_id), fpu.panic_span); + item.owner_id, + sig, + headers, + Some(body_id), + panic_span, + self.check_private_items, + ); } }, hir::ItemKind::Impl(impl_) => { @@ -346,7 +430,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { }; if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { if !in_external_macro(cx.tcx.sess, item.span) { - lint_for_missing_headers(cx, item.owner_id, sig, headers, None, None); + missing_headers::check(cx, item.owner_id, sig, headers, None, None, self.check_private_items); } } } @@ -361,92 +445,17 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { } if let hir::ImplItemKind::Fn(ref sig, body_id) = item.kind { let body = cx.tcx.hir().body(body_id); - let mut fpu = FindPanicUnwrap { - cx, - typeck_results: cx.tcx.typeck(item.owner_id.def_id), - panic_span: None, - }; - fpu.visit_expr(body.value); - lint_for_missing_headers(cx, item.owner_id, sig, headers, Some(body_id), fpu.panic_span); - } - } -} - -fn lint_for_missing_headers( - cx: &LateContext<'_>, - owner_id: hir::OwnerId, - sig: &hir::FnSig<'_>, - headers: DocHeaders, - body_id: Option, - panic_span: Option, -) { - if !cx.effective_visibilities.is_exported(owner_id.def_id) { - return; // Private functions do not require doc comments - } - - // do not lint if any parent has `#[doc(hidden)]` attribute (#7347) - if cx - .tcx - .hir() - .parent_iter(owner_id.into()) - .any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id))) - { - return; - } - let span = cx.tcx.def_span(owner_id); - match (headers.safety, sig.header.unsafety) { - (false, hir::Unsafety::Unsafe) => span_lint( - cx, - MISSING_SAFETY_DOC, - span, - "unsafe function's docs miss `# Safety` section", - ), - (true, hir::Unsafety::Normal) => span_lint( - cx, - UNNECESSARY_SAFETY_DOC, - span, - "safe function's docs have unnecessary `# Safety` section", - ), - _ => (), - } - if !headers.panics && panic_span.is_some() { - span_lint_and_note( - cx, - MISSING_PANICS_DOC, - span, - "docs for function which may panic missing `# Panics` section", - panic_span, - "first possible panic found here", - ); - } - if !headers.errors { - if is_type_diagnostic_item(cx, return_ty(cx, owner_id), sym::Result) { - span_lint( + let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); + missing_headers::check( cx, - MISSING_ERRORS_DOC, - span, - "docs for function returning `Result` missing `# Errors` section", + item.owner_id, + sig, + headers, + Some(body_id), + panic_span, + self.check_private_items, ); - } else { - if_chain! { - if let Some(body_id) = body_id; - if let Some(future) = cx.tcx.lang_items().future_trait(); - let typeck = cx.tcx.typeck_body(body_id); - let body = cx.tcx.hir().body(body_id); - let ret_ty = typeck.expr_ty(body.value); - if implements_trait(cx, ret_ty, future, &[]); - if let ty::Coroutine(_, subs, _) = ret_ty.kind(); - if is_type_diagnostic_item(cx, subs.as_coroutine().return_ty(), sym::Result); - then { - span_lint( - cx, - MISSING_ERRORS_DOC, - span, - "docs for function returning `Result` missing `# Errors` section", - ); - } - } } } } @@ -470,6 +479,13 @@ struct DocHeaders { panics: bool, } +/// Does some pre-processing on raw, desugared `#[doc]` attributes such as parsing them and +/// then delegates to `check_doc`. +/// Some lints are already checked here if they can work with attributes directly and don't need +/// to work with markdown. +/// Others are checked elsewhere, e.g. in `check_doc` if they need access to markdown, or +/// back in the various late lint pass methods if they need the final doc headers, like "Safety" or +/// "Panics" sections. fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[Attribute]) -> Option { /// We don't want the parser to choke on intra doc links. Since we don't /// actually care about rendering them, just pretend that all broken links @@ -483,6 +499,8 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ return None; } + suspicious_doc_comments::check(cx, attrs); + let (fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true); let mut doc = String::new(); for fragment in &fragments { @@ -513,6 +531,10 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail"]; +/// Checks parsed documentation. +/// This walks the "events" (think sections of markdown) produced by `pulldown_cmark`, +/// so lints here will generally access that information. +/// Returns documentation headers -- whether a "Safety", "Errors", "Panic" section was found #[allow(clippy::too_many_lines)] // Only a big match statement fn check_doc<'a, Events: Iterator, Range)>>( cx: &LateContext<'_>, @@ -527,6 +549,7 @@ fn check_doc<'a, Events: Iterator, Range, Range)> = Vec::new(); @@ -542,6 +565,8 @@ fn check_doc<'a, Events: Iterator, Range, Range { in_code = false; is_rust = false; + ignore = false; }, Start(Link(_, url, _)) => in_link = Some(url), End(Link(..)) => in_link = None, @@ -581,7 +607,7 @@ fn check_doc<'a, Events: Iterator, Range, Range, Range, trimmed_text: &str, range: Range, fragments: Fragments<'_>) { - if trimmed_text.starts_with('\'') - && trimmed_text.ends_with('\'') - && let Some(span) = fragments.span(cx, range) - { - span_lint( - cx, - DOC_LINK_WITH_QUOTES, - span, - "possible intra-doc link using quotes instead of backticks", - ); - } -} - -fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, range: Range, fragments: Fragments<'_>) { - fn has_needless_main(code: String, edition: Edition) -> bool { - rustc_driver::catch_fatal_errors(|| { - rustc_span::create_session_globals_then(edition, || { - let filename = FileName::anon_source_code(&code); - - let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let fallback_bundle = - rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false); - let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); - let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); - let sess = ParseSess::with_span_handler(handler, sm); - - let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) { - Ok(p) => p, - Err(errs) => { - drop(errs); - return false; - }, - }; - - let mut relevant_main_found = false; - loop { - match parser.parse_item(ForceCollect::No) { - Ok(Some(item)) => match &item.kind { - ItemKind::Fn(box Fn { - sig, body: Some(block), .. - }) if item.ident.name == sym::main => { - let is_async = matches!(sig.header.asyncness, Async::Yes { .. }); - let returns_nothing = match &sig.decl.output { - FnRetTy::Default(..) => true, - FnRetTy::Ty(ty) if ty.kind.is_unit() => true, - FnRetTy::Ty(_) => false, - }; - - if returns_nothing && !is_async && !block.stmts.is_empty() { - // This main function should be linted, but only if there are no other functions - relevant_main_found = true; - } else { - // This main function should not be linted, we're done - return false; - } - }, - // Tests with one of these items are ignored - ItemKind::Static(..) - | ItemKind::Const(..) - | ItemKind::ExternCrate(..) - | ItemKind::ForeignMod(..) - // Another function was found; this case is ignored - | ItemKind::Fn(..) => return false, - _ => {}, - }, - Ok(None) => break, - Err(e) => { - e.cancel(); - return false; - }, - } - } - - relevant_main_found - }) - }) - .ok() - .unwrap_or_default() - } - - let trailing_whitespace = text.len() - text.trim_end().len(); - - // Because of the global session, we need to create a new session in a different thread with - // the edition we need. - let text = text.to_owned(); - if thread::spawn(move || has_needless_main(text, edition)) - .join() - .expect("thread::spawn failed") - && let Some(span) = fragments.span(cx, range.start..range.end - trailing_whitespace) - { - span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); - } -} - -fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet, text: &str, span: Span) { - for word in text.split(|c: char| c.is_whitespace() || c == '\'') { - // Trim punctuation as in `some comment (see foo::bar).` - // ^^ - // Or even as in `_foo bar_` which is emphasized. Also preserve `::` as a prefix/suffix. - let mut word = word.trim_matches(|c: char| !c.is_alphanumeric() && c != ':'); - - // Remove leading or trailing single `:` which may be part of a sentence. - if word.starts_with(':') && !word.starts_with("::") { - word = word.trim_start_matches(':'); - } - if word.ends_with(':') && !word.ends_with("::") { - word = word.trim_end_matches(':'); - } - - if valid_idents.contains(word) || word.chars().all(|c| c == ':') { - continue; - } - - // Adjust for the current word - let offset = word.as_ptr() as usize - text.as_ptr() as usize; - let span = Span::new( - span.lo() + BytePos::from_usize(offset), - span.lo() + BytePos::from_usize(offset + word.len()), - span.ctxt(), - span.parent(), - ); - - check_word(cx, word, span); - } -} - -fn check_word(cx: &LateContext<'_>, word: &str, span: Span) { - /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and - /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case - /// letter (`NASA` is ok). - /// Plurals are also excluded (`IDs` is ok). - fn is_camel_case(s: &str) -> bool { - if s.starts_with(|c: char| c.is_ascii_digit() | c.is_ascii_lowercase()) { - return false; - } - - let s = s.strip_suffix('s').unwrap_or(s); - - s.chars().all(char::is_alphanumeric) - && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1 - && s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0 - } - - fn has_underscore(s: &str) -> bool { - s != "_" && !s.contains("\\_") && s.contains('_') - } - - fn has_hyphen(s: &str) -> bool { - s != "-" && s.contains('-') - } - - if let Ok(url) = Url::parse(word) { - // try to get around the fact that `foo::bar` parses as a valid URL - if !url.cannot_be_a_base() { - span_lint( - cx, - DOC_MARKDOWN, - span, - "you should put bare URLs between `<`/`>` or make a proper Markdown link", - ); - - return; - } - } - - // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343) - if has_underscore(word) && has_hyphen(word) { - return; - } - - if has_underscore(word) || word.contains("::") || is_camel_case(word) { - let mut applicability = Applicability::MachineApplicable; - - span_lint_and_then( - cx, - DOC_MARKDOWN, - span, - "item in documentation is missing backticks", - |diag| { - let snippet = snippet_with_applicability(cx, span, "..", &mut applicability); - diag.span_suggestion_with_style( - span, - "try", - format!("`{snippet}`"), - applicability, - // always show the suggestion in a separate line, since the - // inline presentation adds another pair of backticks - SuggestionStyle::ShowAlways, - ); - }, - ); - } -} - struct FindPanicUnwrap<'a, 'tcx> { cx: &'a LateContext<'tcx>, panic_span: Option, typeck_results: &'tcx ty::TypeckResults<'tcx>, } +impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> { + pub fn find_span( + cx: &'a LateContext<'tcx>, + typeck_results: &'tcx ty::TypeckResults<'tcx>, + body: impl Visitable<'tcx>, + ) -> Option { + let mut vis = Self { + cx, + panic_span: None, + typeck_results, + }; + body.visit(&mut vis); + vis.panic_span + } +} + impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs new file mode 100644 index 0000000000000..640d4a069ec78 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -0,0 +1,135 @@ +use std::ops::Range; +use std::{io, thread}; + +use crate::doc::{NEEDLESS_DOCTEST_MAIN, TEST_ATTR_IN_DOCTEST}; +use clippy_utils::diagnostics::span_lint; +use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind}; +use rustc_data_structures::sync::Lrc; +use rustc_errors::emitter::EmitterWriter; +use rustc_errors::Handler; +use rustc_lint::LateContext; +use rustc_parse::maybe_new_parser_from_source_str; +use rustc_parse::parser::ForceCollect; +use rustc_session::parse::ParseSess; +use rustc_span::edition::Edition; +use rustc_span::source_map::{FilePathMapping, SourceMap}; +use rustc_span::{sym, FileName, Pos}; + +use super::Fragments; + +fn get_test_spans(item: &Item, test_attr_spans: &mut Vec>) { + test_attr_spans.extend( + item.attrs + .iter() + .find(|attr| attr.has_name(sym::test)) + .map(|attr| attr.span.lo().to_usize()..item.ident.span.hi().to_usize()), + ); +} + +pub fn check( + cx: &LateContext<'_>, + text: &str, + edition: Edition, + range: Range, + fragments: Fragments<'_>, + ignore: bool, +) { + // return whether the code contains a needless `fn main` plus a vector of byte position ranges + // of all `#[test]` attributes in not ignored code examples + fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec>) { + rustc_driver::catch_fatal_errors(|| { + rustc_span::create_session_globals_then(edition, || { + let mut test_attr_spans = vec![]; + let filename = FileName::anon_source_code(&code); + + let fallback_bundle = + rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false); + let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); + let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); + #[expect(clippy::arc_with_non_send_sync)] // `Lrc` is expected by with_span_handler + let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let sess = ParseSess::with_span_handler(handler, sm); + + let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) { + Ok(p) => p, + Err(errs) => { + drop(errs); + return (false, test_attr_spans); + }, + }; + + let mut relevant_main_found = false; + let mut eligible = true; + loop { + match parser.parse_item(ForceCollect::No) { + Ok(Some(item)) => match &item.kind { + ItemKind::Fn(box Fn { + sig, body: Some(block), .. + }) if item.ident.name == sym::main => { + if !ignore { + get_test_spans(&item, &mut test_attr_spans); + } + let is_async = matches!(sig.header.coro_kind, Some(CoroutineKind::Async { .. })); + let returns_nothing = match &sig.decl.output { + FnRetTy::Default(..) => true, + FnRetTy::Ty(ty) if ty.kind.is_unit() => true, + FnRetTy::Ty(_) => false, + }; + + if returns_nothing && !is_async && !block.stmts.is_empty() { + // This main function should be linted, but only if there are no other functions + relevant_main_found = true; + } else { + // This main function should not be linted, we're done + eligible = false; + } + }, + // Another function was found; this case is ignored for needless_doctest_main + ItemKind::Fn(box Fn { .. }) => { + eligible = false; + if !ignore { + get_test_spans(&item, &mut test_attr_spans); + } + }, + // Tests with one of these items are ignored + ItemKind::Static(..) + | ItemKind::Const(..) + | ItemKind::ExternCrate(..) + | ItemKind::ForeignMod(..) => { + eligible = false; + }, + _ => {}, + }, + Ok(None) => break, + Err(e) => { + e.cancel(); + return (false, test_attr_spans); + }, + } + } + + (relevant_main_found & eligible, test_attr_spans) + }) + }) + .ok() + .unwrap_or_default() + } + + let trailing_whitespace = text.len() - text.trim_end().len(); + + // Because of the global session, we need to create a new session in a different thread with + // the edition we need. + let text = text.to_owned(); + let (has_main, test_attr_spans) = thread::spawn(move || check_code_sample(text, edition, ignore)) + .join() + .expect("thread::spawn failed"); + if has_main && let Some(span) = fragments.span(cx, range.start..range.end - trailing_whitespace) { + span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); + } + for span in test_attr_spans { + let span = (range.start + span.start)..(range.start + span.end); + if let Some(span) = fragments.span(cx, span) { + span_lint(cx, TEST_ATTR_IN_DOCTEST, span, "unit tests in doctest are not executed"); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs new file mode 100644 index 0000000000000..d7ad30efec3c6 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs @@ -0,0 +1,48 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_ast::token::CommentKind; +use rustc_ast::{AttrKind, AttrStyle, Attribute}; +use rustc_errors::Applicability; +use rustc_lint::LateContext; +use rustc_span::Span; + +use super::SUSPICIOUS_DOC_COMMENTS; + +pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { + let replacements: Vec<_> = collect_doc_replacements(attrs); + + if let Some((&(lo_span, _), &(hi_span, _))) = replacements.first().zip(replacements.last()) { + span_lint_and_then( + cx, + SUSPICIOUS_DOC_COMMENTS, + lo_span.to(hi_span), + "this is an outer doc comment and does not apply to the parent module or crate", + |diag| { + diag.multipart_suggestion( + "use an inner doc comment to document the parent module or crate", + replacements, + Applicability::MaybeIncorrect, + ); + }, + ); + } +} + +fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> { + attrs + .iter() + .filter_map(|attr| { + if let AttrKind::DocComment(com_kind, sym) = attr.kind + && let AttrStyle::Outer = attr.style + && let Some(com) = sym.as_str().strip_prefix('!') + { + let sugg = match com_kind { + CommentKind::Line => format!("//!{com}"), + CommentKind::Block => format!("/*!{com}*/"), + }; + Some((attr.span, sugg)) + } else { + None + } + }) + .collect() +} diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs index 63f32173b05eb..b51bb7951b741 100644 --- a/src/tools/clippy/clippy_lints/src/double_parens.rs +++ b/src/tools/clippy/clippy_lints/src/double_parens.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs index 177e04dfa6b16..124d78fc4ffdc 100644 --- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs +++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item}; use clippy_utils::{get_parent_node, is_must_use_func_call}; use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; use std::borrow::Cow; diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index 7ff7068f0b05e..471335c098fc4 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Crate, Inline, Item, ItemKind, ModKind}; use rustc_errors::MultiSpan; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{FileName, Span}; use std::collections::BTreeMap; use std::path::PathBuf; diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs index 61db1c1abd163..47780cab9ede8 100644 --- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs +++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs @@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/empty_drop.rs b/src/tools/clippy/clippy_lints/src/empty_drop.rs index 5fcdca7cf362f..e97030cc8b631 100644 --- a/src/tools/clippy/clippy_lints/src/empty_drop.rs +++ b/src/tools/clippy/clippy_lints/src/empty_drop.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::peel_blocks; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -36,31 +35,30 @@ declare_lint_pass!(EmptyDrop => [EMPTY_DROP]); impl LateLintPass<'_> for EmptyDrop { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if_chain! { - if let ItemKind::Impl(Impl { - of_trait: Some(ref trait_ref), - items: [child], - .. - }) = item.kind; - if trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait(); - if let impl_item_hir = child.id.hir_id(); - if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir); - if let ImplItemKind::Fn(_, b) = &impl_item.kind; - if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b); - let func_expr = peel_blocks(func_expr); - if let ExprKind::Block(block, _) = func_expr.kind; - if block.stmts.is_empty() && block.expr.is_none(); - then { - span_lint_and_sugg( - cx, - EMPTY_DROP, - item.span, - "empty drop implementation", - "try removing this impl", - String::new(), - Applicability::MaybeIncorrect - ); - } + if let ItemKind::Impl(Impl { + of_trait: Some(ref trait_ref), + items: [child], + .. + }) = item.kind + && trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait() + && let impl_item_hir = child.id.hir_id() + && let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir) + && let ImplItemKind::Fn(_, b) = &impl_item.kind + && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b) + && let func_expr = peel_blocks(func_expr) + && let ExprKind::Block(block, _) = func_expr.kind + && block.stmts.is_empty() + && block.expr.is_none() + { + span_lint_and_sugg( + cx, + EMPTY_DROP, + item.span, + "empty drop implementation", + "try removing this impl", + String::new(), + Applicability::MaybeIncorrect, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs index a5699727b5be3..420888b6ccb35 100644 --- a/src/tools/clippy/clippy_lints/src/empty_enum.rs +++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs index 4e2a8b73c0ab4..3cf67b3ecbfa4 100644 --- a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs +++ b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{Item, ItemKind, VariantData}; use rustc_errors::Applicability; use rustc_lexer::TokenKind; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/endian_bytes.rs b/src/tools/clippy/clippy_lints/src/endian_bytes.rs index affd082212064..b8a817e21b148 100644 --- a/src/tools/clippy/clippy_lints/src/endian_bytes.rs +++ b/src/tools/clippy/clippy_lints/src/endian_bytes.rs @@ -5,7 +5,7 @@ use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Symbol; use std::borrow::Cow; @@ -114,27 +114,23 @@ impl LateLintPass<'_> for EndianBytes { return; } - if_chain! { - if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind; - if args.is_empty(); - let ty = cx.typeck_results().expr_ty(receiver); - if ty.is_primitive_ty(); - if maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty); - then { - return; - } + if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind + && args.is_empty() + && let ty = cx.typeck_results().expr_ty(receiver) + && ty.is_primitive_ty() + && maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty) + { + return; } - if_chain! { - if let ExprKind::Call(function, ..) = expr.kind; - if let ExprKind::Path(qpath) = function.kind; - if let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id(); - if let Some(function_name) = cx.get_def_path(def_id).last(); - let ty = cx.typeck_results().expr_ty(expr); - if ty.is_primitive_ty(); - then { - maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty); - } + if let ExprKind::Call(function, ..) = expr.kind + && let ExprKind::Path(qpath) = function.kind + && let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id() + && let Some(function_name) = cx.get_def_path(def_id).last() + && let ty = cx.typeck_results().expr_ty(expr) + && ty.is_primitive_ty() + { + maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty); } } } diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index 3e3c62e85d019..ce0a1dfdc61f2 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -10,7 +10,7 @@ use rustc_hir::hir_id::HirIdSet; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{Block, Expr, ExprKind, Guard, HirId, Let, Pat, Stmt, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{Span, SyntaxContext, DUMMY_SP}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 003b5fc7261df..30eb643c42ece 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -7,7 +7,7 @@ use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, IntTy, UintTy}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 575fead5bf3e4..3c43529425265 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -6,7 +6,7 @@ use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -46,9 +46,12 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { pats.iter().all(unary_pattern) } match &pat.kind { - PatKind::Slice(_, _, _) | PatKind::Range(_, _, _) | PatKind::Binding(..) | PatKind::Wild | PatKind::Or(_) => { - false - }, + PatKind::Slice(_, _, _) + | PatKind::Range(_, _, _) + | PatKind::Binding(..) + | PatKind::Wild + | PatKind::Never + | PatKind::Or(_) => false, PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x), diff --git a/src/tools/clippy/clippy_lints/src/error_impl_error.rs b/src/tools/clippy/clippy_lints/src/error_impl_error.rs index bc878555c66dd..8dbb47fadc5da 100644 --- a/src/tools/clippy/clippy_lints/src/error_impl_error.rs +++ b/src/tools/clippy/clippy_lints/src/error_impl_error.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Visibility; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError { if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id()) && error_def_id == trait_def_id && let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local) - && let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id) + && let hir_id = cx.tcx.local_def_id_to_hir_id(def_id) && let Some(ident) = cx.tcx.opt_item_ident(def_id.to_def_id()) && ident.name == sym::Error && is_visible_outside_module(cx, def_id) => diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 3d0ddca19c9f9..ae1e69a4f2325 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -6,10 +6,10 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, TraitRef, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; -use rustc_span::Span; use rustc_span::symbol::kw; +use rustc_span::Span; use rustc_target::spec::abi::Abi; #[derive(Copy, Clone)] @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { let parent_id = cx .tcx .hir() - .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(fn_def_id)) + .get_parent_item(cx.tcx.local_def_id_to_hir_id(fn_def_id)) .def_id; let parent_node = cx.tcx.hir().find_by_def_id(parent_id); diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index fad8fbf04497c..450cee4007c72 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::{ self, Binder, ClosureArgs, ClosureKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, GenericArgsRef, ImplPolarity, List, Region, RegionKind, Ty, TypeVisitableExt, TypeckResults, }; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; @@ -220,7 +220,8 @@ fn check_inputs( params.len() == self_arg.map_or(0, |_| 1) + args.len() && params.iter().zip(self_arg.into_iter().chain(args)).all(|(p, arg)| { matches!( - p.pat.kind,PatKind::Binding(BindingAnnotation::NONE, id, _, None) + p.pat.kind, + PatKind::Binding(BindingAnnotation::NONE, id, _, None) if path_to_local_id(arg, id) ) // Only allow adjustments which change regions (i.e. re-borrowing). @@ -247,8 +248,7 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<'tcx>, call_sig: /// This is needed because rustc is unable to late bind early-bound regions in a function signature. fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<'_>) -> bool { fn check_region(from_region: Region<'_>, to_region: Region<'_>) -> bool { - matches!(from_region.kind(), RegionKind::ReLateBound(..)) - && !matches!(to_region.kind(), RegionKind::ReLateBound(..)) + matches!(from_region.kind(), RegionKind::ReBound(..)) && !matches!(to_region.kind(), RegionKind::ReBound(..)) } fn check_subs(from_subs: &[GenericArg<'_>], to_subs: &[GenericArg<'_>]) -> bool { @@ -290,7 +290,7 @@ fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<' .zip(to_tys) .any(|(from_ty, to_ty)| check_ty(from_ty, to_ty)) }, - _ => from_ty.has_late_bound_regions(), + _ => from_ty.has_bound_regions(), } } diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index 1d18e194d15c6..c5f7212c4c081 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -3,7 +3,7 @@ use clippy_utils::{get_parent_as_impl, has_repr_attr, is_bool}; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::Span; use rustc_target::spec::abi::Abi; @@ -171,7 +171,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools { span: Span, def_id: LocalDefId, ) { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(def_id); if let Some(fn_header) = fn_kind.header() && fn_header.abi == Abi::Rust && get_parent_as_impl(cx.tcx, hir_id).map_or(true, |impl_item| impl_item.of_trait.is_none()) diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs index 83480fc5eebed..4b0d11c5d1bea 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs @@ -5,7 +5,7 @@ use rustc_ast::visit::{walk_block, walk_item, Visitor}; use rustc_ast::{Block, Crate, Inline, Item, ItemKind, ModKind, NodeId}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index f976cfd3f2255..3a621d967f43f 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::indent_of; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -71,40 +70,31 @@ declare_lint_pass!(ExhaustiveItems => [EXHAUSTIVE_ENUMS, EXHAUSTIVE_STRUCTS]); impl LateLintPass<'_> for ExhaustiveItems { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if_chain! { - if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind; - if cx.effective_visibilities.is_exported(item.owner_id.def_id); - let attrs = cx.tcx.hir().attrs(item.hir_id()); - if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)); - then { - let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind { - if v.fields().iter().any(|f| { - !cx.tcx.visibility(f.def_id).is_public() - }) { - // skip structs with private fields - return; - } - (EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive") - } else { - (EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive") - }; - let suggestion_span = item.span.shrink_to_lo(); - let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0)); - span_lint_and_then( - cx, - lint, - item.span, - msg, - |diag| { - let sugg = format!("#[non_exhaustive]\n{indent}"); - diag.span_suggestion(suggestion_span, - "try adding #[non_exhaustive]", - sugg, - Applicability::MaybeIncorrect); - } + if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind + && cx.effective_visibilities.is_exported(item.owner_id.def_id) + && let attrs = cx.tcx.hir().attrs(item.hir_id()) + && !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)) + { + let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind { + if v.fields().iter().any(|f| !cx.tcx.visibility(f.def_id).is_public()) { + // skip structs with private fields + return; + } + (EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive") + } else { + (EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive") + }; + let suggestion_span = item.span.shrink_to_lo(); + let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0)); + span_lint_and_then(cx, lint, item.span, msg, |diag| { + let sugg = format!("#[non_exhaustive]\n{indent}"); + diag.span_suggestion( + suggestion_span, + "try adding #[non_exhaustive]", + sugg, + Applicability::MaybeIncorrect, ); - - } + }); } } } diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index e14b1c556ecca..a974c10bc7dc9 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::is_entrypoint_fn; -use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -42,19 +41,17 @@ declare_lint_pass!(Exit => [EXIT]); impl<'tcx> LateLintPass<'tcx> for Exit { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(path_expr, _args) = e.kind; - if let ExprKind::Path(ref path) = path_expr.kind; - if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::process_exit, def_id); - let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id; - if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent); + if let ExprKind::Call(path_expr, _args) = e.kind + && let ExprKind::Path(ref path) = path_expr.kind + && let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::process_exit, def_id) + && let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id + && let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent) // If the next item up is a function we check if it is an entry point // and only then emit a linter warning - if !is_entrypoint_fn(cx, parent.to_def_id()); - then { - span_lint(cx, EXIT, e.span, "usage of `process::exit`"); - } + && !is_entrypoint_fn(cx, parent.to_def_id()) + { + span_lint(cx, EXIT, e.span, "usage of `process::exit`"); } } } diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index 4b5bcb06a1e8d..4e2e1d1724a58 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -2,12 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::{find_format_args, format_args_inputs_span}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_expn_of, path_def_id}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{BindingAnnotation, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, ExpnId}; declare_clippy_lint! { @@ -101,30 +100,28 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { /// If `kind` is a block that looks like `{ let result = $expr; result }` then /// returns $expr. Otherwise returns `kind`. fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) -> &'tcx ExprKind<'hir> { - if_chain! { - if let ExprKind::Block(block, _label @ None) = kind; - if let Block { + if let ExprKind::Block(block, _label @ None) = kind + && let Block { stmts: [Stmt { kind: StmtKind::Local(local), .. }], expr: Some(expr_end_of_block), rules: BlockCheckMode::DefaultBlock, .. - } = block; + } = block // Find id of the local that expr_end_of_block resolves to - if let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind; - if let Res::Local(expr_res) = expr_path.res; - if let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res); + && let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind + && let Res::Local(expr_res) = expr_path.res + && let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res) // Find id of the local we found in the block - if let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind; + && let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind // If those two are the same hir id - if res_pat.hir_id == local_hir_id; + && res_pat.hir_id == local_hir_id - if let Some(init) = local.init; - then { - return &init.kind; - } + && let Some(init) = local.init + { + return &init.kind; } kind } diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs index d6c746901fc72..538d29eb43dca 100644 --- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs +++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs @@ -10,7 +10,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index efb69476b94a6..0446943321aa9 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -2,11 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::method_chain_args; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -53,13 +52,13 @@ declare_lint_pass!(FallibleImplFrom => [FALLIBLE_IMPL_FROM]); impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { // check for `impl From for ..` - if_chain! { - if let hir::ItemKind::Impl(impl_) = &item.kind; - if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); - if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id); - then { - lint_impl_body(cx, item.span, impl_.items); - } + if let hir::ItemKind::Impl(impl_) = &item.kind + && let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) + && cx + .tcx + .is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id) + { + lint_impl_body(cx, item.span, impl_.items); } } } @@ -98,34 +97,33 @@ fn lint_impl_body(cx: &LateContext<'_>, impl_span: Span, impl_items: &[hir::Impl } for impl_item in impl_items { - if_chain! { - if impl_item.ident.name == sym::from; - if let ImplItemKind::Fn(_, body_id) = - cx.tcx.hir().impl_item(impl_item.id).kind; - then { - // check the body for `begin_panic` or `unwrap` - let body = cx.tcx.hir().body(body_id); - let mut fpu = FindPanicUnwrap { - lcx: cx, - typeck_results: cx.tcx.typeck(impl_item.id.owner_id.def_id), - result: Vec::new(), - }; - fpu.visit_expr(body.value); + if impl_item.ident.name == sym::from + && let ImplItemKind::Fn(_, body_id) = cx.tcx.hir().impl_item(impl_item.id).kind + { + // check the body for `begin_panic` or `unwrap` + let body = cx.tcx.hir().body(body_id); + let mut fpu = FindPanicUnwrap { + lcx: cx, + typeck_results: cx.tcx.typeck(impl_item.id.owner_id.def_id), + result: Vec::new(), + }; + fpu.visit_expr(body.value); - // if we've found one, lint - if !fpu.result.is_empty() { - span_lint_and_then( - cx, - FALLIBLE_IMPL_FROM, - impl_span, - "consider implementing `TryFrom` instead", - move |diag| { - diag.help( - "`From` is intended for infallible conversions only. \ - Use `TryFrom` if there's a possibility for the conversion to fail"); - diag.span_note(fpu.result, "potential failure(s)"); - }); - } + // if we've found one, lint + if !fpu.result.is_empty() { + span_lint_and_then( + cx, + FALLIBLE_IMPL_FROM, + impl_span, + "consider implementing `TryFrom` instead", + move |diag| { + diag.help( + "`From` is intended for infallible conversions only. \ + Use `TryFrom` if there's a possibility for the conversion to fail", + ); + diag.span_note(fpu.result, "potential failure(s)"); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index 506a1191747f5..38a16c5c8b0b7 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal; -use if_chain::if_chain; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, FloatTy}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use std::fmt; declare_clippy_lint! { @@ -64,73 +63,70 @@ declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]); impl<'tcx> LateLintPass<'tcx> for FloatLiteral { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { let ty = cx.typeck_results().expr_ty(expr); - if_chain! { - if let ty::Float(fty) = *ty.kind(); - if let hir::ExprKind::Lit(lit) = expr.kind; - if let LitKind::Float(sym, lit_float_ty) = lit.node; - then { - let sym_str = sym.as_str(); - let formatter = FloatFormat::new(sym_str); - // Try to bail out if the float is for sure fine. - // If its within the 2 decimal digits of being out of precision we - // check if the parsed representation is the same as the string - // since we'll need the truncated string anyway. - let digits = count_digits(sym_str); - let max = max_digits(fty); - let type_suffix = match lit_float_ty { - LitFloatType::Suffixed(ast::FloatTy::F32) => Some("f32"), - LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"), - LitFloatType::Unsuffixed => None - }; - let (is_whole, is_inf, mut float_str) = match fty { - FloatTy::F32 => { - let value = sym_str.parse::().unwrap(); + if let ty::Float(fty) = *ty.kind() + && let hir::ExprKind::Lit(lit) = expr.kind + && let LitKind::Float(sym, lit_float_ty) = lit.node + { + let sym_str = sym.as_str(); + let formatter = FloatFormat::new(sym_str); + // Try to bail out if the float is for sure fine. + // If its within the 2 decimal digits of being out of precision we + // check if the parsed representation is the same as the string + // since we'll need the truncated string anyway. + let digits = count_digits(sym_str); + let max = max_digits(fty); + let type_suffix = match lit_float_ty { + LitFloatType::Suffixed(ast::FloatTy::F32) => Some("f32"), + LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"), + LitFloatType::Unsuffixed => None, + }; + let (is_whole, is_inf, mut float_str) = match fty { + FloatTy::F32 => { + let value = sym_str.parse::().unwrap(); - (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) - }, - FloatTy::F64 => { - let value = sym_str.parse::().unwrap(); + (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) + }, + FloatTy::F64 => { + let value = sym_str.parse::().unwrap(); + (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) + }, + }; - (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) - }, - }; - - if is_inf { - return; - } - - if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') { - // Normalize the literal by stripping the fractional portion - if sym_str.split('.').next().unwrap() != float_str { - // If the type suffix is missing the suggestion would be - // incorrectly interpreted as an integer so adding a `.0` - // suffix to prevent that. - if type_suffix.is_none() { - float_str.push_str(".0"); - } + if is_inf { + return; + } - span_lint_and_sugg( - cx, - LOSSY_FLOAT_LITERAL, - expr.span, - "literal cannot be represented as the underlying type without loss of precision", - "consider changing the type or replacing it with", - numeric_literal::format(&float_str, type_suffix, true), - Applicability::MachineApplicable, - ); + if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') { + // Normalize the literal by stripping the fractional portion + if sym_str.split('.').next().unwrap() != float_str { + // If the type suffix is missing the suggestion would be + // incorrectly interpreted as an integer so adding a `.0` + // suffix to prevent that. + if type_suffix.is_none() { + float_str.push_str(".0"); } - } else if digits > max as usize && float_str.len() < sym_str.len() { + span_lint_and_sugg( cx, - EXCESSIVE_PRECISION, + LOSSY_FLOAT_LITERAL, expr.span, - "float has excessive precision", - "consider changing the type or truncating it to", + "literal cannot be represented as the underlying type without loss of precision", + "consider changing the type or replacing it with", numeric_literal::format(&float_str, type_suffix, true), Applicability::MachineApplicable, ); } + } else if digits > max as usize && float_str.len() < sym_str.len() { + span_lint_and_sugg( + cx, + EXCESSIVE_PRECISION, + expr.span, + "float has excessive precision", + "consider changing the type or truncating it to", + numeric_literal::format(&float_str, type_suffix, true), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs index 09a9d9924de33..c8b87e510ed68 100644 --- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs @@ -4,12 +4,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::{ eq_expr_value, get_parent_expr, higher, in_constant, is_no_std_crate, numeric_literal, peel_blocks, sugg, }; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_ast::ast; @@ -133,30 +132,25 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su expr = inner_expr; } - if_chain! { + if let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind() // if the expression is a float literal and it is unsuffixed then // add a suffix so the suggestion is valid and unambiguous - if let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind(); - if let ExprKind::Lit(lit) = &expr.kind; - if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node; - then { - let op = format!( - "{suggestion}{}{}", - // Check for float literals without numbers following the decimal - // separator such as `2.` and adds a trailing zero - if sym.as_str().ends_with('.') { - "0" - } else { - "" - }, - float_ty.name_str() - ).into(); - - suggestion = match suggestion { - Sugg::MaybeParen(_) => Sugg::MaybeParen(op), - _ => Sugg::NonParen(op) - }; - } + && let ExprKind::Lit(lit) = &expr.kind + && let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node + { + let op = format!( + "{suggestion}{}{}", + // Check for float literals without numbers following the decimal + // separator such as `2.` and adds a trailing zero + if sym.as_str().ends_with('.') { "0" } else { "" }, + float_ty.name_str() + ) + .into(); + + suggestion = match suggestion { + Sugg::MaybeParen(_) => Sugg::MaybeParen(op), + _ => Sugg::NonParen(op), + }; } suggestion.maybe_par() @@ -359,35 +353,59 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option { ) = receiver.kind { // check if expression of the form x * x + y * y - if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lmul_lhs, lmul_rhs) = add_lhs.kind; - if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, rmul_lhs, rmul_rhs) = add_rhs.kind; - if eq_expr_value(cx, lmul_lhs, lmul_rhs); - if eq_expr_value(cx, rmul_lhs, rmul_rhs); - then { - return Some(format!("{}.hypot({})", Sugg::hir(cx, lmul_lhs, "..").maybe_par(), Sugg::hir(cx, rmul_lhs, ".."))); - } + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + lmul_lhs, + lmul_rhs, + ) = add_lhs.kind + && let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + rmul_lhs, + rmul_rhs, + ) = add_rhs.kind + && eq_expr_value(cx, lmul_lhs, lmul_rhs) + && eq_expr_value(cx, rmul_lhs, rmul_rhs) + { + return Some(format!( + "{}.hypot({})", + Sugg::hir(cx, lmul_lhs, "..").maybe_par(), + Sugg::hir(cx, rmul_lhs, "..") + )); } // check if expression of the form x.powi(2) + y.powi(2) - if_chain! { - if let ExprKind::MethodCall( - PathSegment { ident: lmethod_name, .. }, - largs_0, [largs_1, ..], - _ - ) = &add_lhs.kind; - if let ExprKind::MethodCall( - PathSegment { ident: rmethod_name, .. }, - rargs_0, [rargs_1, ..], - _ - ) = &add_rhs.kind; - if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi"; - if let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1); - if let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1); - if Int(2) == lvalue && Int(2) == rvalue; - then { - return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, "..").maybe_par(), Sugg::hir(cx, rargs_0, ".."))); - } + if let ExprKind::MethodCall( + PathSegment { + ident: lmethod_name, .. + }, + largs_0, + [largs_1, ..], + _, + ) = &add_lhs.kind + && let ExprKind::MethodCall( + PathSegment { + ident: rmethod_name, .. + }, + rargs_0, + [rargs_1, ..], + _, + ) = &add_rhs.kind + && lmethod_name.as_str() == "powi" + && rmethod_name.as_str() == "powi" + && let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1) + && let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1) + && Int(2) == lvalue + && Int(2) == rvalue + { + return Some(format!( + "{}.hypot({})", + Sugg::hir(cx, largs_0, "..").maybe_par(), + Sugg::hir(cx, rargs_0, "..") + )); } } @@ -411,39 +429,44 @@ fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { // TODO: Lint expressions of the form `x.exp() - y` where y > 1 // and suggest usage of `x.exp_m1() - (y - 1)` instead fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind; - if cx.typeck_results().expr_ty(lhs).is_floating_point(); - if let Some(value) = constant(cx, cx.typeck_results(), rhs); - if F32(1.0) == value || F64(1.0) == value; - if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind; - if cx.typeck_results().expr_ty(self_arg).is_floating_point(); - if path.ident.name.as_str() == "exp"; - then { - span_lint_and_sugg( - cx, - IMPRECISE_FLOPS, - expr.span, - "(e.pow(x) - 1) can be computed more accurately", - "consider using", - format!( - "{}.exp_m1()", - Sugg::hir(cx, self_arg, "..").maybe_par() - ), - Applicability::MachineApplicable, - ); - } + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Sub, .. + }, + lhs, + rhs, + ) = expr.kind + && cx.typeck_results().expr_ty(lhs).is_floating_point() + && let Some(value) = constant(cx, cx.typeck_results(), rhs) + && (F32(1.0) == value || F64(1.0) == value) + && let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind + && cx.typeck_results().expr_ty(self_arg).is_floating_point() + && path.ident.name.as_str() == "exp" + { + span_lint_and_sugg( + cx, + IMPRECISE_FLOPS, + expr.span, + "(e.pow(x) - 1) can be computed more accurately", + "consider using", + format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_par()), + Applicability::MachineApplicable, + ); } } fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { - if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, lhs, rhs) = &expr.kind; - if cx.typeck_results().expr_ty(lhs).is_floating_point(); - if cx.typeck_results().expr_ty(rhs).is_floating_point(); - then { - return Some((lhs, rhs)); - } + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + lhs, + rhs, + ) = &expr.kind + && cx.typeck_results().expr_ty(lhs).is_floating_point() + && cx.typeck_results().expr_ty(rhs).is_floating_point() + { + return Some((lhs, rhs)); } None @@ -473,9 +496,13 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { if let BinOpKind::Sub = op { -sugg } else { sugg } }; - let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) { + let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) + && cx.typeck_results().expr_ty(rhs).is_floating_point() + { (inner_lhs, Sugg::hir(cx, inner_rhs, ".."), maybe_neg_sugg(rhs)) - } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) { + } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) + && cx.typeck_results().expr_ty(lhs).is_floating_point() + { (inner_lhs, maybe_neg_sugg(inner_rhs), Sugg::hir(cx, lhs, "..")) } else { return; @@ -553,60 +580,72 @@ fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a } fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if let Some(higher::If { cond, then, r#else: Some(r#else) }) = higher::If::hir(expr); - let if_body_expr = peel_blocks(then); - let else_body_expr = peel_blocks(r#else); - if let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr); - then { - let positive_abs_sugg = ( - "manual implementation of `abs` method", - format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_par()), - ); - let negative_abs_sugg = ( - "manual implementation of negation of `abs` method", - format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_par()), - ); - let sugg = if is_testing_positive(cx, cond, body) { - if if_expr_positive { - positive_abs_sugg - } else { - negative_abs_sugg - } - } else if is_testing_negative(cx, cond, body) { - if if_expr_positive { - negative_abs_sugg - } else { - positive_abs_sugg - } + if let Some(higher::If { + cond, + then, + r#else: Some(r#else), + }) = higher::If::hir(expr) + && let if_body_expr = peel_blocks(then) + && let else_body_expr = peel_blocks(r#else) + && let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr) + { + let positive_abs_sugg = ( + "manual implementation of `abs` method", + format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_par()), + ); + let negative_abs_sugg = ( + "manual implementation of negation of `abs` method", + format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_par()), + ); + let sugg = if is_testing_positive(cx, cond, body) { + if if_expr_positive { + positive_abs_sugg } else { - return; - }; - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - sugg.0, - "try", - sugg.1, - Applicability::MachineApplicable, - ); - } + negative_abs_sugg + } + } else if is_testing_negative(cx, cond, body) { + if if_expr_positive { + negative_abs_sugg + } else { + positive_abs_sugg + } + } else { + return; + }; + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + sugg.0, + "try", + sugg.1, + Applicability::MachineApplicable, + ); } } fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { - if_chain! { - if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, args_a, _) = expr_a.kind; - if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, args_b, _) = expr_b.kind; - then { - return method_name_a.as_str() == method_name_b.as_str() && - args_a.len() == args_b.len() && - ( - ["ln", "log2", "log10"].contains(&method_name_a.as_str()) || - method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0]) - ); - } + if let ExprKind::MethodCall( + PathSegment { + ident: method_name_a, .. + }, + _, + args_a, + _, + ) = expr_a.kind + && let ExprKind::MethodCall( + PathSegment { + ident: method_name_b, .. + }, + _, + args_b, + _, + ) = expr_b.kind + { + return method_name_a.as_str() == method_name_b.as_str() + && args_a.len() == args_b.len() + && (["ln", "log2", "log10"].contains(&method_name_a.as_str()) + || method_name_a.as_str() == "log" && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])); } false @@ -614,103 +653,98 @@ fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_> fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { // check if expression of the form x.logN() / y.logN() - if_chain! { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Div, .. - }, - lhs, - rhs, - ) = &expr.kind; - if are_same_base_logs(cx, lhs, rhs); - if let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind; - if let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind; - then { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "log base can be expressed more clearly", - "consider using", - format!("{}.log({})", Sugg::hir(cx, largs_self, "..").maybe_par(), Sugg::hir(cx, rargs_self, ".."),), - Applicability::MachineApplicable, - ); - } + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Div, .. + }, + lhs, + rhs, + ) = &expr.kind + && are_same_base_logs(cx, lhs, rhs) + && let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind + && let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind + { + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "log base can be expressed more clearly", + "consider using", + format!( + "{}.log({})", + Sugg::hir(cx, largs_self, "..").maybe_par(), + Sugg::hir(cx, rargs_self, ".."), + ), + Applicability::MachineApplicable, + ); } } fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Div, .. - }, - div_lhs, - div_rhs, - ) = &expr.kind; - if let ExprKind::Binary( + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Div, .. + }, + div_lhs, + div_rhs, + ) = &expr.kind + && let ExprKind::Binary( Spanned { node: BinOpKind::Mul, .. }, mul_lhs, mul_rhs, - ) = &div_lhs.kind; - if let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs); - if let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs); - then { - // TODO: also check for constant values near PI/180 or 180/PI - if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) && - (F32(180_f32) == lvalue || F64(180_f64) == lvalue) + ) = &div_lhs.kind + && let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs) + && let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs) + { + // TODO: also check for constant values near PI/180 or 180/PI + if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) + && (F32(180_f32) == lvalue || F64(180_f64) == lvalue) + { + let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_par()); + if let ExprKind::Lit(literal) = mul_lhs.kind + && let ast::LitKind::Float(ref value, float_type) = literal.node + && float_type == ast::LitFloatType::Unsuffixed { - let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_par()); - if_chain! { - if let ExprKind::Lit(literal) = mul_lhs.kind; - if let ast::LitKind::Float(ref value, float_type) = literal.node; - if float_type == ast::LitFloatType::Unsuffixed; - then { - if value.as_str().ends_with('.') { - proposal = format!("{}0_f64.to_degrees()", Sugg::hir(cx, mul_lhs, "..")); - } else { - proposal = format!("{}_f64.to_degrees()", Sugg::hir(cx, mul_lhs, "..")); - } - } + if value.as_str().ends_with('.') { + proposal = format!("{}0_f64.to_degrees()", Sugg::hir(cx, mul_lhs, "..")); + } else { + proposal = format!("{}_f64.to_degrees()", Sugg::hir(cx, mul_lhs, "..")); } - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "conversion to degrees can be done more accurately", - "consider using", - proposal, - Applicability::MachineApplicable, - ); - } else if - (F32(180_f32) == rvalue || F64(180_f64) == rvalue) && - (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue) + } + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "conversion to degrees can be done more accurately", + "consider using", + proposal, + Applicability::MachineApplicable, + ); + } else if (F32(180_f32) == rvalue || F64(180_f64) == rvalue) + && (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue) + { + let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_par()); + if let ExprKind::Lit(literal) = mul_lhs.kind + && let ast::LitKind::Float(ref value, float_type) = literal.node + && float_type == ast::LitFloatType::Unsuffixed { - let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_par()); - if_chain! { - if let ExprKind::Lit(literal) = mul_lhs.kind; - if let ast::LitKind::Float(ref value, float_type) = literal.node; - if float_type == ast::LitFloatType::Unsuffixed; - then { - if value.as_str().ends_with('.') { - proposal = format!("{}0_f64.to_radians()", Sugg::hir(cx, mul_lhs, "..")); - } else { - proposal = format!("{}_f64.to_radians()", Sugg::hir(cx, mul_lhs, "..")); - } - } + if value.as_str().ends_with('.') { + proposal = format!("{}0_f64.to_radians()", Sugg::hir(cx, mul_lhs, "..")); + } else { + proposal = format!("{}_f64.to_radians()", Sugg::hir(cx, mul_lhs, "..")); } - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "conversion to radians can be done more accurately", - "consider using", - proposal, - Applicability::MachineApplicable, - ); } + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "conversion to radians can be done more accurately", + "consider using", + proposal, + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index 18ed05c1ca621..8a0cd155d211c 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 3c1f2d9d5dcd5..8af321e4d553b 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -8,7 +8,6 @@ use clippy_utils::macros::{ }; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; -use if_chain::if_chain; use itertools::Itertools; use rustc_ast::{ FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions, @@ -20,7 +19,7 @@ use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; use rustc_middle::ty::Ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::DefId; use rustc_span::edition::Edition::Edition2021; use rustc_span::{sym, Span, Symbol}; @@ -404,49 +403,43 @@ fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symb } fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Expr<'_>) { - if_chain! { - if !value.span.from_expansion(); - if let ExprKind::MethodCall(_, receiver, [], to_string_span) = value.kind; - if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id); - if is_diag_trait_item(cx, method_def_id, sym::ToString); - let receiver_ty = cx.typeck_results().expr_ty(receiver); - if let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display); - let (n_needed_derefs, target) = - count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter()); - if implements_trait(cx, target, display_trait_id, &[]); - if let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait(); - if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); - then { - let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]); - if n_needed_derefs == 0 && !needs_ref { - span_lint_and_sugg( - cx, - TO_STRING_IN_FORMAT_ARGS, - to_string_span.with_lo(receiver.span.hi()), - &format!( - "`to_string` applied to a type that implements `Display` in `{name}!` args" - ), - "remove this", - String::new(), - Applicability::MachineApplicable, - ); - } else { - span_lint_and_sugg( - cx, - TO_STRING_IN_FORMAT_ARGS, - value.span, - &format!( - "`to_string` applied to a type that implements `Display` in `{name}!` args" - ), - "use this", - format!( - "{}{:*>n_needed_derefs$}{receiver_snippet}", - if needs_ref { "&" } else { "" }, - "" - ), - Applicability::MachineApplicable, - ); - } + if !value.span.from_expansion() + && let ExprKind::MethodCall(_, receiver, [], to_string_span) = value.kind + && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id) + && is_diag_trait_item(cx, method_def_id, sym::ToString) + && let receiver_ty = cx.typeck_results().expr_ty(receiver) + && let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display) + && let (n_needed_derefs, target) = + count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter()) + && implements_trait(cx, target, display_trait_id, &[]) + && let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait() + && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + { + let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]); + if n_needed_derefs == 0 && !needs_ref { + span_lint_and_sugg( + cx, + TO_STRING_IN_FORMAT_ARGS, + to_string_span.with_lo(receiver.span.hi()), + &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), + "remove this", + String::new(), + Applicability::MachineApplicable, + ); + } else { + span_lint_and_sugg( + cx, + TO_STRING_IN_FORMAT_ARGS, + value.span, + &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), + "use this", + format!( + "{}{:*>n_needed_derefs$}{receiver_snippet}", + if needs_ref { "&" } else { "" }, + "" + ), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs index 08ee7032c0918..9360eb1fa91ad 100644 --- a/src/tools/clippy/clippy_lints/src/format_impl.rs +++ b/src/tools/clippy/clippy_lints/src/format_impl.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::macros::{find_format_arg_expr, find_format_args, is_format_macro, root_macro_call_first_node}; use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators}; -use if_chain::if_chain; use rustc_ast::{FormatArgsPiece, FormatTrait}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; use rustc_span::{sym, Span, Symbol}; @@ -141,27 +140,25 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl { } fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { + if let ExprKind::MethodCall(path, self_arg, ..) = expr.kind // Get the hir_id of the object we are calling the method on - if let ExprKind::MethodCall(path, self_arg, ..) = expr.kind; // Is the method to_string() ? - if path.ident.name == sym::to_string; + && path.ident.name == sym::to_string // Is the method a part of the ToString trait? (i.e. not to_string() implemented // separately) - if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if is_diag_trait_item(cx, expr_def_id, sym::ToString); + && let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && is_diag_trait_item(cx, expr_def_id, sym::ToString) // Is the method is called on self - if let ExprKind::Path(QPath::Resolved(_, path)) = self_arg.kind; - if let [segment] = path.segments; - if segment.ident.name == kw::SelfLower; - then { - span_lint( - cx, - RECURSIVE_FORMAT_IMPL, - expr.span, - "using `self.to_string` in `fmt::Display` implementation will cause infinite recursion", - ); - } + && let ExprKind::Path(QPath::Resolved(_, path)) = self_arg.kind + && let [segment] = path.segments + && segment.ident.name == kw::SelfLower + { + span_lint( + cx, + RECURSIVE_FORMAT_IMPL, + expr.span, + "using `self.to_string` in `fmt::Display` implementation will cause infinite recursion", + ); } } @@ -215,55 +212,53 @@ fn check_format_arg_self(cx: &LateContext<'_>, span: Span, arg: &Expr<'_>, impl_ } fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTraitNames) { - if_chain! { - if let Some(macro_call) = root_macro_call_first_node(cx, expr); - if let Some(name) = cx.tcx.get_diagnostic_name(macro_call.def_id); - then { - let replacement = match name { - sym::print_macro | sym::eprint_macro => "write", - sym::println_macro | sym::eprintln_macro => "writeln", - _ => return, - }; + if let Some(macro_call) = root_macro_call_first_node(cx, expr) + && let Some(name) = cx.tcx.get_diagnostic_name(macro_call.def_id) + { + let replacement = match name { + sym::print_macro | sym::eprint_macro => "write", + sym::println_macro | sym::eprintln_macro => "writeln", + _ => return, + }; - let name = name.as_str().strip_suffix("_macro").unwrap(); + let name = name.as_str().strip_suffix("_macro").unwrap(); - span_lint_and_sugg( - cx, - PRINT_IN_FORMAT_IMPL, - macro_call.span, - &format!("use of `{name}!` in `{}` impl", impl_trait.name), - "replace with", - if let Some(formatter_name) = impl_trait.formatter_name { - format!("{replacement}!({formatter_name}, ..)") - } else { - format!("{replacement}!(..)") - }, - Applicability::HasPlaceholders, - ); - } + span_lint_and_sugg( + cx, + PRINT_IN_FORMAT_IMPL, + macro_call.span, + &format!("use of `{name}!` in `{}` impl", impl_trait.name), + "replace with", + if let Some(formatter_name) = impl_trait.formatter_name { + format!("{replacement}!({formatter_name}, ..)") + } else { + format!("{replacement}!(..)") + }, + Applicability::HasPlaceholders, + ); } } fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option { - if_chain! { - if impl_item.ident.name == sym::fmt; - if let ImplItemKind::Fn(_, body_id) = impl_item.kind; - if let Some(Impl { of_trait: Some(trait_ref),..}) = get_parent_as_impl(cx.tcx, impl_item.hir_id()); - if let Some(did) = trait_ref.trait_def_id(); - if let Some(name) = cx.tcx.get_diagnostic_name(did); - if matches!(name, sym::Debug | sym::Display); - then { - let body = cx.tcx.hir().body(body_id); - let formatter_name = body.params.get(1) - .and_then(|param| param.pat.simple_ident()) - .map(|ident| ident.name); + if impl_item.ident.name == sym::fmt + && let ImplItemKind::Fn(_, body_id) = impl_item.kind + && let Some(Impl { + of_trait: Some(trait_ref), + .. + }) = get_parent_as_impl(cx.tcx, impl_item.hir_id()) + && let Some(did) = trait_ref.trait_def_id() + && let Some(name) = cx.tcx.get_diagnostic_name(did) + && matches!(name, sym::Debug | sym::Display) + { + let body = cx.tcx.hir().body(body_id); + let formatter_name = body + .params + .get(1) + .and_then(|param| param.pat.simple_ident()) + .map(|ident| ident.name); - Some(FormatTraitNames { - name, - formatter_name, - }) - } else { - None - } + Some(FormatTraitNames { name, formatter_name }) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs index ac45f5aedfa46..3901dd984f9d6 100644 --- a/src/tools/clippy/clippy_lints/src/format_push_string.rs +++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::is_type_lang_item; use clippy_utils::{higher, match_def_path, paths}; use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs index 2c9c43d3ea7a8..c3ef6f180c9fa 100644 --- a/src/tools/clippy/clippy_lints/src/formatting.rs +++ b/src/tools/clippy/clippy_lints/src/formatting.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note}; use clippy_utils::is_span_if; use clippy_utils::source::snippet_opt; -use if_chain::if_chain; -use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; +use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -145,7 +144,7 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) { let eq_span = lhs.span.between(rhs.span); if let ExprKind::Unary(op, ref sub_rhs) = rhs.kind { if let Some(eq_snippet) = snippet_opt(cx, eq_span) { - let op = UnOp::to_string(op); + let op = op.as_str(); let eqop_span = lhs.span.between(sub_rhs.span); if eq_snippet.ends_with('=') { span_lint_and_note( @@ -168,93 +167,84 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) { /// Implementation of the `SUSPICIOUS_UNARY_OP_FORMATTING` lint. fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) { - if_chain! { - if let ExprKind::Binary(ref binop, ref lhs, ref rhs) = expr.kind; - if !lhs.span.from_expansion() && !rhs.span.from_expansion(); + if let ExprKind::Binary(ref binop, ref lhs, ref rhs) = expr.kind + && !lhs.span.from_expansion() && !rhs.span.from_expansion() // span between BinOp LHS and RHS - let binop_span = lhs.span.between(rhs.span); + && let binop_span = lhs.span.between(rhs.span) // if RHS is an UnOp - if let ExprKind::Unary(op, ref un_rhs) = rhs.kind; + && let ExprKind::Unary(op, ref un_rhs) = rhs.kind // from UnOp operator to UnOp operand - let unop_operand_span = rhs.span.until(un_rhs.span); - if let Some(binop_snippet) = snippet_opt(cx, binop_span); - if let Some(unop_operand_snippet) = snippet_opt(cx, unop_operand_span); - let binop_str = BinOpKind::to_string(&binop.node); + && let unop_operand_span = rhs.span.until(un_rhs.span) + && let Some(binop_snippet) = snippet_opt(cx, binop_span) + && let Some(unop_operand_snippet) = snippet_opt(cx, unop_operand_span) + && let binop_str = binop.node.as_str() // no space after BinOp operator and space after UnOp operator - if binop_snippet.ends_with(binop_str) && unop_operand_snippet.ends_with(' '); - then { - let unop_str = UnOp::to_string(op); - let eqop_span = lhs.span.between(un_rhs.span); - span_lint_and_help( - cx, - SUSPICIOUS_UNARY_OP_FORMATTING, - eqop_span, - &format!( - "by not having a space between `{binop_str}` and `{unop_str}` it looks like \ - `{binop_str}{unop_str}` is a single operator" - ), - None, - &format!( - "put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`" - ), - ); - } + && binop_snippet.ends_with(binop_str) && unop_operand_snippet.ends_with(' ') + { + let unop_str = op.as_str(); + let eqop_span = lhs.span.between(un_rhs.span); + span_lint_and_help( + cx, + SUSPICIOUS_UNARY_OP_FORMATTING, + eqop_span, + &format!( + "by not having a space between `{binop_str}` and `{unop_str}` it looks like \ + `{binop_str}{unop_str}` is a single operator" + ), + None, + &format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"), + ); } } /// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else`. fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { - if_chain! { - if let ExprKind::If(_, then, Some(else_)) = &expr.kind; - if is_block(else_) || is_if(else_); - if !then.span.from_expansion() && !else_.span.from_expansion(); - if !in_external_macro(cx.sess(), expr.span); + if let ExprKind::If(_, then, Some(else_)) = &expr.kind + && (is_block(else_) || is_if(else_)) + && !then.span.from_expansion() && !else_.span.from_expansion() + && !in_external_macro(cx.sess(), expr.span) // workaround for rust-lang/rust#43081 - if expr.span.lo().0 != 0 && expr.span.hi().0 != 0; + && expr.span.lo().0 != 0 && expr.span.hi().0 != 0 // this will be a span from the closing ‘}’ of the “then” block (excluding) to // the “if” of the “else if” block (excluding) - let else_span = then.span.between(else_.span); + && let else_span = then.span.between(else_.span) // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” - if let Some(else_snippet) = snippet_opt(cx, else_span); - if let Some((pre_else, post_else)) = else_snippet.split_once("else"); - if let Some((_, post_else_post_eol)) = post_else.split_once('\n'); - - then { - // Allow allman style braces `} \n else \n {` - if_chain! { - if is_block(else_); - if let Some((_, pre_else_post_eol)) = pre_else.split_once('\n'); - // Exactly one eol before and after the else - if !pre_else_post_eol.contains('\n'); - if !post_else_post_eol.contains('\n'); - then { - return; - } - } - - // Don't warn if the only thing inside post_else_post_eol is a comment block. - let trimmed_post_else_post_eol = post_else_post_eol.trim(); - if trimmed_post_else_post_eol.starts_with("/*") && trimmed_post_else_post_eol.ends_with("*/") { - return - } + && let Some(else_snippet) = snippet_opt(cx, else_span) + && let Some((pre_else, post_else)) = else_snippet.split_once("else") + && let Some((_, post_else_post_eol)) = post_else.split_once('\n') + { + // Allow allman style braces `} \n else \n {` + if is_block(else_) + && let Some((_, pre_else_post_eol)) = pre_else.split_once('\n') + // Exactly one eol before and after the else + && !pre_else_post_eol.contains('\n') + && !post_else_post_eol.contains('\n') + { + return; + } - let else_desc = if is_if(else_) { "if" } else { "{..}" }; - span_lint_and_note( - cx, - SUSPICIOUS_ELSE_FORMATTING, - else_span, - &format!("this is an `else {else_desc}` but the formatting might hide it"), - None, - &format!( - "to remove this lint, remove the `else` or remove the new line between \ - `else` and `{else_desc}`", - ), - ); + // Don't warn if the only thing inside post_else_post_eol is a comment block. + let trimmed_post_else_post_eol = post_else_post_eol.trim(); + if trimmed_post_else_post_eol.starts_with("/*") && trimmed_post_else_post_eol.ends_with("*/") { + return; } + + let else_desc = if is_if(else_) { "if" } else { "{..}" }; + span_lint_and_note( + cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + &format!("this is an `else {else_desc}` but the formatting might hide it"), + None, + &format!( + "to remove this lint, remove the `else` or remove the new line between \ + `else` and `{else_desc}`", + ), + ); } } @@ -272,61 +262,56 @@ fn indentation(cx: &EarlyContext<'_>, span: Span) -> usize { fn check_array(cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::Array(ref array) = expr.kind { for element in array { - if_chain! { - if let ExprKind::Binary(ref op, ref lhs, _) = element.kind; - if has_unary_equivalent(op.node) && lhs.span.eq_ctxt(op.span); - let space_span = lhs.span.between(op.span); - if let Some(space_snippet) = snippet_opt(cx, space_span); - let lint_span = lhs.span.with_lo(lhs.span.hi()); - if space_snippet.contains('\n'); - if indentation(cx, op.span) <= indentation(cx, lhs.span); - then { - span_lint_and_note( - cx, - POSSIBLE_MISSING_COMMA, - lint_span, - "possibly missing a comma here", - None, - "to remove this lint, add a comma or write the expr in a single line", - ); - } + if let ExprKind::Binary(ref op, ref lhs, _) = element.kind + && has_unary_equivalent(op.node) + && lhs.span.eq_ctxt(op.span) + && let space_span = lhs.span.between(op.span) + && let Some(space_snippet) = snippet_opt(cx, space_span) + && let lint_span = lhs.span.with_lo(lhs.span.hi()) + && space_snippet.contains('\n') + && indentation(cx, op.span) <= indentation(cx, lhs.span) + { + span_lint_and_note( + cx, + POSSIBLE_MISSING_COMMA, + lint_span, + "possibly missing a comma here", + None, + "to remove this lint, add a comma or write the expr in a single line", + ); } } } } fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) { - if_chain! { - if !first.span.from_expansion() && !second.span.from_expansion(); - if matches!(first.kind, ExprKind::If(..)); - if is_block(second) || is_if(second); + if !first.span.from_expansion() && !second.span.from_expansion() + && matches!(first.kind, ExprKind::If(..)) + && (is_block(second) || is_if(second)) // Proc-macros can give weird spans. Make sure this is actually an `if`. - if is_span_if(cx, first.span); + && is_span_if(cx, first.span) // If there is a line break between the two expressions, don't lint. // If there is a non-whitespace character, this span came from a proc-macro. - let else_span = first.span.between(second.span); - if let Some(else_snippet) = snippet_opt(cx, else_span); - if !else_snippet.chars().any(|c| c == '\n' || !c.is_whitespace()); - then { - let (looks_like, next_thing) = if is_if(second) { - ("an `else if`", "the second `if`") - } else { - ("an `else {..}`", "the next block") - }; + && let else_span = first.span.between(second.span) + && let Some(else_snippet) = snippet_opt(cx, else_span) + && !else_snippet.chars().any(|c| c == '\n' || !c.is_whitespace()) + { + let (looks_like, next_thing) = if is_if(second) { + ("an `else if`", "the second `if`") + } else { + ("an `else {..}`", "the next block") + }; - span_lint_and_note( - cx, - SUSPICIOUS_ELSE_FORMATTING, - else_span, - &format!("this looks like {looks_like} but the `else` is missing"), - None, - &format!( - "to remove this lint, add the missing `else` or add a new line before {next_thing}", - ), - ); - } + span_lint_and_note( + cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + &format!("this looks like {looks_like} but the `else` is missing"), + None, + &format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",), + ); } } diff --git a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs index 69bc0b726fcce..0599e08e6c0af 100644 --- a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs +++ b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::Item; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 5477532bb9588..fa1f98ba01343 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -12,7 +12,7 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::{kw, sym}; use rustc_span::{Span, Symbol}; diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs index d9138d48b2ca1..c8d10dc4b9298 100644 --- a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{RawPtr, TypeAndMut}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs index 74a60b6a0d24b..633ed96d6a6d5 100644 --- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs +++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs @@ -2,12 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_integer_literal; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -46,52 +45,41 @@ declare_lint_pass!(FromStrRadix10 => [FROM_STR_RADIX_10]); impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 { fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) { - if_chain! { - if let ExprKind::Call(maybe_path, [src, radix]) = &exp.kind; - if let ExprKind::Path(QPath::TypeRelative(ty, pathseg)) = &maybe_path.kind; + if let ExprKind::Call(maybe_path, [src, radix]) = &exp.kind + && let ExprKind::Path(QPath::TypeRelative(ty, pathseg)) = &maybe_path.kind // check if the first part of the path is some integer primitive - if let TyKind::Path(ty_qpath) = &ty.kind; - let ty_res = cx.qpath_res(ty_qpath, ty.hir_id); - if let def::Res::PrimTy(prim_ty) = ty_res; - if matches!(prim_ty, PrimTy::Int(_) | PrimTy::Uint(_)); + && let TyKind::Path(ty_qpath) = &ty.kind + && let ty_res = cx.qpath_res(ty_qpath, ty.hir_id) + && let def::Res::PrimTy(prim_ty) = ty_res + && matches!(prim_ty, PrimTy::Int(_) | PrimTy::Uint(_)) // check if the second part of the path indeed calls the associated // function `from_str_radix` - if pathseg.ident.name.as_str() == "from_str_radix"; + && pathseg.ident.name.as_str() == "from_str_radix" // check if the second argument is a primitive `10` - if is_integer_literal(radix, 10); + && is_integer_literal(radix, 10) + { + let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind { + let ty = cx.typeck_results().expr_ty(expr); + if is_ty_stringish(cx, ty) { expr } else { &src } + } else { + &src + }; - then { - let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind { - let ty = cx.typeck_results().expr_ty(expr); - if is_ty_stringish(cx, ty) { - expr - } else { - &src - } - } else { - &src - }; + let sugg = + Sugg::hir_with_applicability(cx, expr, "", &mut Applicability::MachineApplicable).maybe_par(); - let sugg = Sugg::hir_with_applicability( - cx, - expr, - "", - &mut Applicability::MachineApplicable - ).maybe_par(); - - span_lint_and_sugg( - cx, - FROM_STR_RADIX_10, - exp.span, - "this call to `from_str_radix` can be replaced with a call to `str::parse`", - "try", - format!("{sugg}.parse::<{}>()", prim_ty.name_str()), - Applicability::MaybeIncorrect - ); - } + span_lint_and_sugg( + cx, + FROM_STR_RADIX_10, + exp.span, + "this call to `from_str_radix` can be replaced with a call to `str::parse`", + "try", + format!("{sugg}.parse::<{}>()", prim_ty.name_str()), + Applicability::MaybeIncorrect, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs index ee66c841ed25c..8fba41c0e24d5 100644 --- a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs @@ -5,18 +5,10 @@ use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind}; use rustc_lint::LateContext; -use rustc_span::symbol::Ident; -use rustc_span::{BytePos, Span}; use super::IMPL_TRAIT_IN_PARAMS; -fn report( - cx: &LateContext<'_>, - param: &GenericParam<'_>, - ident: &Ident, - generics: &Generics<'_>, - first_param_span: Span, -) { +fn report(cx: &LateContext<'_>, param: &GenericParam<'_>, generics: &Generics<'_>) { // No generics with nested generics, and no generics like FnMut(x) span_lint_and_then( cx, @@ -35,12 +27,7 @@ fn report( ); } else { diag.span_suggestion_with_style( - Span::new( - first_param_span.lo() - rustc_span::BytePos(1), - ident.span.hi(), - ident.span.ctxt(), - ident.span.parent(), - ), + generics.span, "add a type parameter", format!("<{{ /* Generic name */ }}: {}>", ¶m.name.ident().as_str()[5..]), rustc_errors::Applicability::HasPlaceholders, @@ -52,54 +39,47 @@ fn report( } pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) { - if_chain! { - if let FnKind::ItemFn(ident, generics, _) = kind; - if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public(); - if !is_in_test_function(cx.tcx, hir_id); - then { - for param in generics.params { - if param.is_impl_trait() { - report(cx, param, ident, generics, body.params[0].span); - }; - } + if let FnKind::ItemFn(_, generics, _) = kind + && cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public() + && !is_in_test_function(cx.tcx, hir_id) + { + for param in generics.params { + if param.is_impl_trait() { + report(cx, param, generics); + }; } } } pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { - if_chain! { - if let ImplItemKind::Fn(_, body_id) = impl_item.kind; - if let hir::Node::Item(item) = cx.tcx.hir().get_parent(impl_item.hir_id()); - if let hir::ItemKind::Impl(impl_) = item.kind; - if let hir::Impl { of_trait, .. } = *impl_; - if of_trait.is_none(); - let body = cx.tcx.hir().body(body_id); - if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public(); - if !is_in_test_function(cx.tcx, impl_item.hir_id()); - then { - for param in impl_item.generics.params { - if param.is_impl_trait() { - report(cx, param, &impl_item.ident, impl_item.generics, body.params[0].span); - } + if let ImplItemKind::Fn(_, body_id) = impl_item.kind + && let hir::Node::Item(item) = cx.tcx.hir().get_parent(impl_item.hir_id()) + && let hir::ItemKind::Impl(impl_) = item.kind + && let hir::Impl { of_trait, .. } = *impl_ + && of_trait.is_none() + && let body = cx.tcx.hir().body(body_id) + && cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public() + && !is_in_test_function(cx.tcx, impl_item.hir_id()) + { + for param in impl_item.generics.params { + if param.is_impl_trait() { + report(cx, param, impl_item.generics); } } } } pub(super) fn check_trait_item(cx: &LateContext<'_>, trait_item: &TraitItem<'_>, avoid_breaking_exported_api: bool) { - if_chain! { - if !avoid_breaking_exported_api; - if let TraitItemKind::Fn(_, _) = trait_item.kind; - if let hir::Node::Item(item) = cx.tcx.hir().get_parent(trait_item.hir_id()); + if !avoid_breaking_exported_api + && let TraitItemKind::Fn(_, _) = trait_item.kind + && let hir::Node::Item(item) = cx.tcx.hir().get_parent(trait_item.hir_id()) // ^^ (Will always be a trait) - if !item.vis_span.is_empty(); // Is public - if !is_in_test_function(cx.tcx, trait_item.hir_id()); - then { - for param in trait_item.generics.params { - if param.is_impl_trait() { - let sp = trait_item.ident.span.with_hi(trait_item.ident.span.hi() + BytePos(1)); - report(cx, param, &trait_item.ident, trait_item.generics, sp.shrink_to_hi()); - } + && !item.vis_span.is_empty() // Is public + && !is_in_test_function(cx.tcx, trait_item.hir_id()) + { + for param in trait_item.generics.params { + if param.is_impl_trait() { + report(cx, param, trait_item.generics); } } } diff --git a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs index 18f7368dafb75..bf96c0d62b05a 100644 --- a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs +++ b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs @@ -43,15 +43,13 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: // Body must be &(mut) .name // self_data is not necessarily self, to also lint sub-getters, etc… - let block_expr = if_chain! { - if let ExprKind::Block(block,_) = body.value.kind; - if block.stmts.is_empty(); - if let Some(block_expr) = block.expr; - then { - block_expr - } else { - return; - } + let block_expr = if let ExprKind::Block(block, _) = body.value.kind + && block.stmts.is_empty() + && let Some(block_expr) = block.expr + { + block_expr + } else { + return; }; let expr_span = block_expr.span; @@ -61,14 +59,12 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: } else { block_expr }; - let (self_data, used_ident) = if_chain! { - if let ExprKind::Field(self_data, ident) = expr.kind; - if ident.name.as_str() != name; - then { - (self_data, ident) - } else { - return; - } + let (self_data, used_ident) = if let ExprKind::Field(self_data, ident) = expr.kind + && ident.name.as_str() != name + { + (self_data, ident) + } else { + return; }; let mut used_field = None; diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs index 3f5cceec70ed6..96da2ec2a1a8b 100644 --- a/src/tools/clippy/clippy_lints/src/functions/mod.rs +++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs @@ -9,7 +9,7 @@ mod too_many_lines; use rustc_hir as hir; use rustc_hir::intravisit; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::Span; @@ -407,7 +407,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions { span: Span, def_id: LocalDefId, ) { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(def_id); too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold); too_many_lines::check_fn(cx, kind, span, body, self.too_many_lines_threshold); not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, def_id); diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index 485235514dedb..5e90fcd72ebea 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -23,7 +23,7 @@ fn result_err_ty<'tcx>( && let hir::FnRetTy::Return(hir_ty) = decl.output && let ty = cx .tcx - .erase_late_bound_regions(cx.tcx.fn_sig(id).instantiate_identity().output()) + .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().output()) && is_type_diagnostic_item(cx, ty, sym::Result) && let ty::Adt(_, args) = ty.kind() { @@ -86,59 +86,60 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S } fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) { - if_chain! { - if let Adt(adt, subst) = err_ty.kind(); - if let Some(local_def_id) = err_ty.ty_adt_def().expect("already checked this is adt").did().as_local(); - if let Some(hir::Node::Item(item)) = cx - .tcx - .hir() - .find_by_def_id(local_def_id); - if let hir::ItemKind::Enum(ref def, _) = item.kind; - then { - let variants_size = AdtVariantInfo::new(cx, *adt, subst); - if let Some((first_variant, variants)) = variants_size.split_first() - && first_variant.size >= large_err_threshold - { - span_lint_and_then( - cx, - RESULT_LARGE_ERR, - hir_ty_span, - "the `Err`-variant returned from this function is very large", - |diag| { - diag.span_label( - def.variants[first_variant.ind].span, - format!("the largest variant contains at least {} bytes", variants_size[0].size), - ); + if let Adt(adt, subst) = err_ty.kind() + && let Some(local_def_id) = err_ty + .ty_adt_def() + .expect("already checked this is adt") + .did() + .as_local() + && let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(local_def_id) + && let hir::ItemKind::Enum(ref def, _) = item.kind + { + let variants_size = AdtVariantInfo::new(cx, *adt, subst); + if let Some((first_variant, variants)) = variants_size.split_first() + && first_variant.size >= large_err_threshold + { + span_lint_and_then( + cx, + RESULT_LARGE_ERR, + hir_ty_span, + "the `Err`-variant returned from this function is very large", + |diag| { + diag.span_label( + def.variants[first_variant.ind].span, + format!("the largest variant contains at least {} bytes", variants_size[0].size), + ); - for variant in variants { - if variant.size >= large_err_threshold { - let variant_def = &def.variants[variant.ind]; - diag.span_label( - variant_def.span, - format!("the variant `{}` contains at least {} bytes", variant_def.ident, variant.size), - ); - } + for variant in variants { + if variant.size >= large_err_threshold { + let variant_def = &def.variants[variant.ind]; + diag.span_label( + variant_def.span, + format!( + "the variant `{}` contains at least {} bytes", + variant_def.ident, variant.size + ), + ); } - - diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`")); } - ); - } + + diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`")); + }, + ); } - else { - let ty_size = approx_ty_size(cx, err_ty); - if ty_size >= large_err_threshold { - span_lint_and_then( - cx, - RESULT_LARGE_ERR, - hir_ty_span, - "the `Err`-variant returned from this function is very large", - |diag: &mut Diagnostic| { - diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes")); - diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`")); - }, - ); - } + } else { + let ty_size = approx_ty_size(cx, err_ty); + if ty_size >= large_err_threshold { + span_lint_and_then( + cx, + RESULT_LARGE_ERR, + hir_ty_span, + "the `Err`-variant returned from this function is very large", + |diag: &mut Diagnostic| { + diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes")); + diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`")); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index eee5b7540ba7e..9fb59a320d488 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -5,7 +5,7 @@ use rustc_hir::{Body, FnDecl}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt; @@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { if let FnKind::Closure = kind { return; } - let ret_ty = return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(fn_def_id).expect_owner()); + let ret_ty = return_ty(cx, cx.tcx.local_def_id_to_hir_id(fn_def_id).expect_owner()); if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind() { let preds = cx.tcx.explicit_item_bounds(def_id); let mut is_future = false; diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs index e614a8f694fb7..5e354209cbfc2 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{higher, SpanlessEq}; -use if_chain::if_chain; use rustc_errors::Diagnostic; use rustc_hir::intravisit::{self as visit, Visitor}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -127,15 +126,13 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { } fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if_chain! { - if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind; - if path.ident.as_str() == "lock"; - let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); - if is_type_diagnostic_item(cx, ty, sym::Mutex); - then { - Some(self_arg) - } else { - None - } + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind + && path.ident.as_str() == "lock" + && let ty = cx.typeck_results().expr_ty(self_arg).peel_refs() + && is_type_diagnostic_item(cx, ty, sym::Mutex) + { + Some(self_arg) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/if_not_else.rs b/src/tools/clippy/clippy_lints/src/if_not_else.rs index cae561f7802e4..4dc1ff8377110 100644 --- a/src/tools/clippy/clippy_lints/src/if_not_else.rs +++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs @@ -6,7 +6,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_else_clause; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs index 66c10ab228f4b..cd6c46a71a8e1 100644 --- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs +++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs @@ -9,7 +9,7 @@ use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs index 76bdfb94eb85d..0a2fd0c663e54 100644 --- a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs @@ -3,7 +3,7 @@ use hir::{Node, PatKind}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs b/src/tools/clippy/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs new file mode 100644 index 0000000000000..940adbae428e8 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs @@ -0,0 +1,106 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::implements_trait; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{Item, ItemKind, Path, TraitRef}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; +use rustc_session::declare_lint_pass; +use rustc_span::symbol::sym; + +declare_clippy_lint! { + /// ### What it does + /// + /// This lint is concerned with the semantics of `Borrow` and `Hash` for a + /// type that implements all three of `Hash`, `Borrow` and `Borrow<[u8]>` + /// as it is impossible to satisfy the semantics of Borrow and `Hash` for + /// both `Borrow` and `Borrow<[u8]>`. + /// + /// ### Why is this bad? + /// + /// When providing implementations for `Borrow`, one should consider whether the different + /// implementations should act as facets or representations of the underlying type. Generic code + /// typically uses `Borrow` when it relies on the identical behavior of these additional trait + /// implementations. These traits will likely appear as additional trait bounds. + /// + /// In particular `Eq`, `Ord` and `Hash` must be equivalent for borrowed and owned values: + /// `x.borrow() == y.borrow()` should give the same result as `x == y`. + /// It follows then that the following equivalence must hold: + /// `hash(x) == hash((x as Borrow<[u8]>).borrow()) == hash((x as Borrow).borrow())` + /// + /// Unfortunately it doesn't hold as `hash("abc") != hash("abc".as_bytes())`. + /// This happens because the `Hash` impl for str passes an additional `0xFF` byte to + /// the hasher to avoid collisions. For example, given the tuples `("a", "bc")`, and `("ab", "c")`, + /// the two tuples would have the same hash value if the `0xFF` byte was not added. + /// + /// ### Example + /// + /// ``` + /// use std::borrow::Borrow; + /// use std::hash::{Hash, Hasher}; + /// + /// struct ExampleType { + /// data: String + /// } + /// + /// impl Hash for ExampleType { + /// fn hash(&self, state: &mut H) { + /// self.data.hash(state); + /// } + /// } + /// + /// impl Borrow for ExampleType { + /// fn borrow(&self) -> &str { + /// &self.data + /// } + /// } + /// + /// impl Borrow<[u8]> for ExampleType { + /// fn borrow(&self) -> &[u8] { + /// self.data.as_bytes() + /// } + /// } + /// ``` + /// As a consequence, hashing a `&ExampleType` and hashing the result of the two + /// borrows will result in different values. + /// + #[clippy::version = "1.76.0"] + pub IMPL_HASH_BORROW_WITH_STR_AND_BYTES, + correctness, + "ensures that the semantics of `Borrow` for `Hash` are satisfied when `Borrow` and `Borrow<[u8]>` are implemented" +} + +declare_lint_pass!(ImplHashWithBorrowStrBytes => [IMPL_HASH_BORROW_WITH_STR_AND_BYTES]); + +impl LateLintPass<'_> for ImplHashWithBorrowStrBytes { + /// We are emitting this lint at the Hash impl of a type that implements all + /// three of `Hash`, `Borrow` and `Borrow<[u8]>`. + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if let ItemKind::Impl(imp) = item.kind + && let Some(TraitRef {path: Path {span, res, ..}, ..}) = imp.of_trait + && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() + && let Some(hash_id) = cx.tcx.get_diagnostic_item(sym::Hash) + && Res::Def(DefKind::Trait, hash_id) == *res + && let Some(borrow_id) = cx.tcx.get_diagnostic_item(sym::Borrow) + // since we are in the `Hash` impl, we don't need to check for that. + // we need only to check for `Borrow` and `Borrow<[u8]>` + && implements_trait(cx, ty, borrow_id, &[cx.tcx.types.str_.into()]) + && implements_trait(cx, ty, borrow_id, &[Ty::new_slice(cx.tcx, cx.tcx.types.u8).into()]) + { + span_lint_and_then( + cx, + IMPL_HASH_BORROW_WITH_STR_AND_BYTES, + *span, + "the semantics of `Borrow` around `Hash` can't be satisfied when both `Borrow` and `Borrow<[u8]>` are implemented", + |diag| { + diag.note("the `Borrow` semantics require that `Hash` must behave the same for all implementations of Borrow"); + diag.note( + "however, the hash implementations of a string (`str`) and the bytes of a string `[u8]` do not behave the same ..." + ); + diag.note("... as (`hash(\"abc\") != hash(\"abc\".as_bytes())`"); + diag.help("consider either removing one of the `Borrow` implementations (`Borrow` or `Borrow<[u8]>`) ..."); + diag.help("... or not implementing `Hash` for this type"); + }, + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index eaf80de385727..43eb6a9b8386a 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -9,11 +9,9 @@ use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{Ty, TypeckResults}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; - -use if_chain::if_chain; +use rustc_span::Span; use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_opt}; @@ -337,42 +335,38 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't } fn visit_expr(&mut self, e: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(fun, args) = e.kind; - if let ExprKind::Path(QPath::TypeRelative(ty, method)) = fun.kind; - if let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind; - if let Some(ty_did) = ty_path.res.opt_def_id(); - then { - if self.target.ty() != self.maybe_typeck_results.unwrap().expr_ty(e) { - return; - } + if let ExprKind::Call(fun, args) = e.kind + && let ExprKind::Path(QPath::TypeRelative(ty, method)) = fun.kind + && let TyKind::Path(QPath::Resolved(None, ty_path)) = ty.kind + && let Some(ty_did) = ty_path.res.opt_def_id() + { + if self.target.ty() != self.maybe_typeck_results.unwrap().expr_ty(e) { + return; + } - if self.cx.tcx.is_diagnostic_item(sym::HashMap, ty_did) { - if method.ident.name == sym::new { - self.suggestions - .insert(e.span, "HashMap::default()".to_string()); - } else if method.ident.name == sym!(with_capacity) { - self.suggestions.insert( - e.span, - format!( - "HashMap::with_capacity_and_hasher({}, Default::default())", - snippet(self.cx, args[0].span, "capacity"), - ), - ); - } - } else if self.cx.tcx.is_diagnostic_item(sym::HashSet, ty_did) { - if method.ident.name == sym::new { - self.suggestions - .insert(e.span, "HashSet::default()".to_string()); - } else if method.ident.name == sym!(with_capacity) { - self.suggestions.insert( - e.span, - format!( - "HashSet::with_capacity_and_hasher({}, Default::default())", - snippet(self.cx, args[0].span, "capacity"), - ), - ); - } + if self.cx.tcx.is_diagnostic_item(sym::HashMap, ty_did) { + if method.ident.name == sym::new { + self.suggestions.insert(e.span, "HashMap::default()".to_string()); + } else if method.ident.name == sym!(with_capacity) { + self.suggestions.insert( + e.span, + format!( + "HashMap::with_capacity_and_hasher({}, Default::default())", + snippet(self.cx, args[0].span, "capacity"), + ), + ); + } + } else if self.cx.tcx.is_diagnostic_item(sym::HashSet, ty_did) { + if method.ident.name == sym::new { + self.suggestions.insert(e.span, "HashSet::default()".to_string()); + } else if method.ident.name == sym!(with_capacity) { + self.suggestions.insert( + e.span, + format!( + "HashSet::with_capacity_and_hasher({}, Default::default())", + snippet(self.cx, args[0].span, "capacity"), + ), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index c6bcf3ba40c54..d68c5c4bac68b 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -8,7 +8,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, SyntaxContext}; diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs index 24f62490f967f..cc74844f29427 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs @@ -2,13 +2,12 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_context; -use if_chain::if_chain; use rustc_ast::ast::{LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{Int, IntTy, Ty, Uint, UintTy}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -40,42 +39,58 @@ declare_lint_pass!(ImplicitSaturatingAdd => [IMPLICIT_SATURATING_ADD]); impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if_chain! { - if let ExprKind::If(cond, then, None) = expr.kind; - if let ExprKind::DropTemps(expr1) = cond.kind; - if let Some((c, op_node, l)) = get_const(cx, expr1); - if let BinOpKind::Ne | BinOpKind::Lt = op_node; - if let ExprKind::Block(block, None) = then.kind; - if let Block { + if let ExprKind::If(cond, then, None) = expr.kind + && let ExprKind::DropTemps(expr1) = cond.kind + && let Some((c, op_node, l)) = get_const(cx, expr1) + && let BinOpKind::Ne | BinOpKind::Lt = op_node + && let ExprKind::Block(block, None) = then.kind + && let Block { stmts: - [Stmt - { kind: StmtKind::Expr(ex) | StmtKind::Semi(ex), .. }], - expr: None, ..} | - Block { stmts: [], expr: Some(ex), ..} = block; - if let ExprKind::AssignOp(op1, target, value) = ex.kind; - let ty = cx.typeck_results().expr_ty(target); - if Some(c) == get_int_max(ty); - let ctxt = expr.span.ctxt(); - if ex.span.ctxt() == ctxt; - if expr1.span.ctxt() == ctxt; - if clippy_utils::SpanlessEq::new(cx).eq_expr(l, target); - if BinOpKind::Add == op1.node; - if let ExprKind::Lit(lit) = value.kind; - if let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node; - if block.expr.is_none(); - then { - let mut app = Applicability::MachineApplicable; - let code = snippet_with_context(cx, target.span, ctxt, "_", &mut app).0; - let sugg = if let Some(parent) = get_parent_expr(cx, expr) - && let ExprKind::If(_cond, _then, Some(else_)) = parent.kind - && else_.hir_id == expr.hir_id - { - format!("{{{code} = {code}.saturating_add(1); }}") - } else { - format!("{code} = {code}.saturating_add(1);") - }; - span_lint_and_sugg(cx, IMPLICIT_SATURATING_ADD, expr.span, "manual saturating add detected", "use instead", sugg, app); + [ + Stmt { + kind: StmtKind::Expr(ex) | StmtKind::Semi(ex), + .. + }, + ], + expr: None, + .. } + | Block { + stmts: [], + expr: Some(ex), + .. + } = block + && let ExprKind::AssignOp(op1, target, value) = ex.kind + && let ty = cx.typeck_results().expr_ty(target) + && Some(c) == get_int_max(ty) + && let ctxt = expr.span.ctxt() + && ex.span.ctxt() == ctxt + && expr1.span.ctxt() == ctxt + && clippy_utils::SpanlessEq::new(cx).eq_expr(l, target) + && BinOpKind::Add == op1.node + && let ExprKind::Lit(lit) = value.kind + && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node + && block.expr.is_none() + { + let mut app = Applicability::MachineApplicable; + let code = snippet_with_context(cx, target.span, ctxt, "_", &mut app).0; + let sugg = if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::If(_cond, _then, Some(else_)) = parent.kind + && else_.hir_id == expr.hir_id + { + format!("{{{code} = {code}.saturating_add(1); }}") + } else { + format!("{code} = {code}.saturating_add(1);") + }; + span_lint_and_sugg( + cx, + IMPLICIT_SATURATING_ADD, + expr.span, + "manual saturating add detected", + "use instead", + sugg, + app, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 859404289d97c..81df1a889c789 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq}; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -46,83 +45,76 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if expr.span.from_expansion() { return; } - if_chain! { - if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr); + if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr) // Check if the conditional expression is a binary operation - if let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind; + && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind // Ensure that the binary operator is >, !=, or < - if BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node; + && (BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node) // Check if assign operation is done - if let Some(target) = subtracts_one(cx, then); + && let Some(target) = subtracts_one(cx, then) // Extracting out the variable name - if let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind; - - then { - // Handle symmetric conditions in the if statement - let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) { - if BinOpKind::Gt == cond_op.node || BinOpKind::Ne == cond_op.node { - (cond_left, cond_right) - } else { - return; - } - } else if SpanlessEq::new(cx).eq_expr(cond_right, target) { - if BinOpKind::Lt == cond_op.node || BinOpKind::Ne == cond_op.node { - (cond_right, cond_left) - } else { - return; - } + && let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind + { + // Handle symmetric conditions in the if statement + let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) { + if BinOpKind::Gt == cond_op.node || BinOpKind::Ne == cond_op.node { + (cond_left, cond_right) } else { return; - }; - - // Check if the variable in the condition statement is an integer - if !cx.typeck_results().expr_ty(cond_var).is_integral() { + } + } else if SpanlessEq::new(cx).eq_expr(cond_right, target) { + if BinOpKind::Lt == cond_op.node || BinOpKind::Ne == cond_op.node { + (cond_right, cond_left) + } else { return; } + } else { + return; + }; - // Get the variable name - let var_name = ares_path.segments[0].ident.name.as_str(); - match cond_num_val.kind { - ExprKind::Lit(cond_lit) => { - // Check if the constant is zero - if let LitKind::Int(0, _) = cond_lit.node { - if cx.typeck_results().expr_ty(cond_left).is_signed() { - } else { - print_lint_and_sugg(cx, var_name, expr); - }; - } - }, - ExprKind::Path(QPath::TypeRelative(_, name)) => { - if_chain! { - if name.ident.as_str() == "MIN"; - if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(const_id); - if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl - if cx.tcx.type_of(impl_id).instantiate_identity().is_integral(); - then { - print_lint_and_sugg(cx, var_name, expr) - } - } - }, - ExprKind::Call(func, []) => { - if_chain! { - if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind; - if name.ident.as_str() == "min_value"; - if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(func_id); - if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl - if cx.tcx.type_of(impl_id).instantiate_identity().is_integral(); - then { - print_lint_and_sugg(cx, var_name, expr) - } - } - }, - _ => (), - } + // Check if the variable in the condition statement is an integer + if !cx.typeck_results().expr_ty(cond_var).is_integral() { + return; + } + + // Get the variable name + let var_name = ares_path.segments[0].ident.name.as_str(); + match cond_num_val.kind { + ExprKind::Lit(cond_lit) => { + // Check if the constant is zero + if let LitKind::Int(0, _) = cond_lit.node { + if cx.typeck_results().expr_ty(cond_left).is_signed() { + } else { + print_lint_and_sugg(cx, var_name, expr); + }; + } + }, + ExprKind::Path(QPath::TypeRelative(_, name)) => { + if name.ident.as_str() == "MIN" + && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(const_id) + && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl + && cx.tcx.type_of(impl_id).instantiate_identity().is_integral() + { + print_lint_and_sugg(cx, var_name, expr); + } + }, + ExprKind::Call(func, []) => { + if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind + && name.ident.as_str() == "min_value" + && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(func_id) + && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl + && cx.tcx.type_of(impl_id).instantiate_identity().is_integral() + { + print_lint_and_sugg(cx, var_name, expr); + } + }, + _ => (), } } } @@ -135,18 +127,14 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Exp (BinOpKind::Sub == op1.node && is_integer_literal(value, 1)).then_some(target) }, ExprKind::Assign(target, value, _) => { - if_chain! { - if let ExprKind::Binary(ref op1, left1, right1) = value.kind; - if BinOpKind::Sub == op1.node; - - if SpanlessEq::new(cx).eq_expr(left1, target); - - if is_integer_literal(right1, 1); - then { - Some(target) - } else { - None - } + if let ExprKind::Binary(ref op1, left1, right1) = value.kind + && BinOpKind::Sub == op1.node + && SpanlessEq::new(cx).eq_expr(left1, target) + && is_integer_literal(right1, 1) + { + Some(target) + } else { + None } }, _ => None, diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index ff27a5d666d35..9a66cbde53c0f 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -10,7 +10,7 @@ use rustc_hir::{ use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, ClauseKind, Generics, Ty, TyCtxt}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -43,9 +43,9 @@ declare_clippy_lint! { /// Box::new(123) /// } /// ``` - #[clippy::version = "1.73.0"] + #[clippy::version = "1.74.0"] pub IMPLIED_BOUNDS_IN_IMPLS, - nursery, + complexity, "specifying bounds that are implied by other bounds in `impl Trait` type" } declare_lint_pass!(ImpliedBoundsInImpls => [IMPLIED_BOUNDS_IN_IMPLS]); diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs index a84f7351ad66a..1075975f0a21e 100644 --- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::{self as hir, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::Symbol; use std::fmt::{self, Write as _}; @@ -66,54 +65,53 @@ declare_lint_pass!(InconsistentStructConstructor => [INCONSISTENT_STRUCT_CONSTRU impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if_chain! { - if !expr.span.from_expansion(); - if let ExprKind::Struct(qpath, fields, base) = expr.kind; - let ty = cx.typeck_results().expr_ty(expr); - if let Some(adt_def) = ty.ty_adt_def(); - if adt_def.is_struct(); - if let Some(variant) = adt_def.variants().iter().next(); - if fields.iter().all(|f| f.is_shorthand); - then { - let mut def_order_map = FxHashMap::default(); - for (idx, field) in variant.fields.iter().enumerate() { - def_order_map.insert(field.name, idx); - } + if !expr.span.from_expansion() + && let ExprKind::Struct(qpath, fields, base) = expr.kind + && let ty = cx.typeck_results().expr_ty(expr) + && let Some(adt_def) = ty.ty_adt_def() + && adt_def.is_struct() + && let Some(variant) = adt_def.variants().iter().next() + && fields.iter().all(|f| f.is_shorthand) + { + let mut def_order_map = FxHashMap::default(); + for (idx, field) in variant.fields.iter().enumerate() { + def_order_map.insert(field.name, idx); + } - if is_consistent_order(fields, &def_order_map) { - return; - } + if is_consistent_order(fields, &def_order_map) { + return; + } - let mut ordered_fields: Vec<_> = fields.iter().map(|f| f.ident.name).collect(); - ordered_fields.sort_unstable_by_key(|id| def_order_map[id]); + let mut ordered_fields: Vec<_> = fields.iter().map(|f| f.ident.name).collect(); + ordered_fields.sort_unstable_by_key(|id| def_order_map[id]); - let mut fields_snippet = String::new(); - let (last_ident, idents) = ordered_fields.split_last().unwrap(); - for ident in idents { - let _: fmt::Result = write!(fields_snippet, "{ident}, "); - } - fields_snippet.push_str(&last_ident.to_string()); + let mut fields_snippet = String::new(); + let (last_ident, idents) = ordered_fields.split_last().unwrap(); + for ident in idents { + let _: fmt::Result = write!(fields_snippet, "{ident}, "); + } + fields_snippet.push_str(&last_ident.to_string()); - let base_snippet = if let Some(base) = base { - format!(", ..{}", snippet(cx, base.span, "..")) - } else { - String::new() - }; + let base_snippet = if let Some(base) = base { + format!(", ..{}", snippet(cx, base.span, "..")) + } else { + String::new() + }; - let sugg = format!("{} {{ {fields_snippet}{base_snippet} }}", - snippet(cx, qpath.span(), ".."), - ); + let sugg = format!( + "{} {{ {fields_snippet}{base_snippet} }}", + snippet(cx, qpath.span(), ".."), + ); - span_lint_and_sugg( - cx, - INCONSISTENT_STRUCT_CONSTRUCTOR, - expr.span, - "struct constructor field order is inconsistent with struct definition field order", - "try", - sugg, - Applicability::MachineApplicable, - ) - } + span_lint_and_sugg( + cx, + INCONSISTENT_STRUCT_CONSTRUCTOR, + expr.span, + "struct constructor field order is inconsistent with struct definition field order", + "try", + sugg, + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index c2f1f18e39d10..b6f9d8b81f821 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -4,7 +4,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLet; use clippy_utils::ty::is_copy; use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local}; -use if_chain::if_chain; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::Applicability; use rustc_hir as hir; @@ -12,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -70,20 +69,17 @@ impl_lint_pass!(IndexRefutableSlice => [INDEX_REFUTABLE_SLICE]); impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if_chain! { - if !expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some(); - if let Some(IfLet {let_pat, if_then, ..}) = IfLet::hir(cx, expr); - if !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id); - if self.msrv.meets(msrvs::SLICE_PATTERNS); - - let found_slices = find_slice_values(cx, let_pat); - if !found_slices.is_empty(); - let filtered_slices = filter_lintable_slices(cx, found_slices, self.max_suggested_slice, if_then); - if !filtered_slices.is_empty(); - then { - for slice in filtered_slices.values() { - lint_slice(cx, slice); - } + if (!expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some()) + && let Some(IfLet { let_pat, if_then, .. }) = IfLet::hir(cx, expr) + && !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id) + && self.msrv.meets(msrvs::SLICE_PATTERNS) + && let found_slices = find_slice_values(cx, let_pat) + && !found_slices.is_empty() + && let filtered_slices = filter_lintable_slices(cx, found_slices, self.max_suggested_slice, if_then) + && !filtered_slices.is_empty() + { + for slice in filtered_slices.values() { + lint_slice(cx, slice); } } } @@ -245,28 +241,26 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { max_suggested_slice, } = *self; - if_chain! { + if let Some(use_info) = slice_lint_info.get_mut(&local_id) // Check if this is even a local we're interested in - if let Some(use_info) = slice_lint_info.get_mut(&local_id); - let map = cx.tcx.hir(); + && let map = cx.tcx.hir() // Checking for slice indexing - let parent_id = map.parent_id(expr.hir_id); - if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id); - if let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind; - if let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr); - if let Ok(index_value) = index_value.try_into(); - if index_value < max_suggested_slice; + && let parent_id = map.parent_id(expr.hir_id) + && let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id) + && let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind + && let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr) + && let Ok(index_value) = index_value.try_into() + && index_value < max_suggested_slice // Make sure that this slice index is read only - let maybe_addrof_id = map.parent_id(parent_id); - if let Some(hir::Node::Expr(maybe_addrof_expr)) = map.find(maybe_addrof_id); - if let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind; - then { - use_info.index_use.push((index_value, map.span(parent_expr.hir_id))); - return; - } + && let maybe_addrof_id = map.parent_id(parent_id) + && let Some(hir::Node::Expr(maybe_addrof_expr)) = map.find(maybe_addrof_id) + && let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind + { + use_info.index_use.push((index_value, map.span(parent_expr.hir_id))); + return; } // The slice was used for something other than indexing diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index 1ce7d85d3828f..0ae03d101ab58 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -7,7 +7,7 @@ use rustc_ast::ast::RangeLimits; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index e9c53671a9322..9ad02735878a4 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -3,7 +3,7 @@ use clippy_utils::higher; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use rustc_hir::{BorrowKind, Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::{sym, Symbol}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index a61a64161930c..5c926133c427b 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; use rustc_hir::{Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; use std::collections::hash_map::Entry; @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { && !is_lint_allowed( cx, MULTIPLE_INHERENT_IMPL, - cx.tcx.hir().local_def_id_to_hir_id(id), + cx.tcx.local_def_id_to_hir_id(id), ) }) { for impl_id in impl_ids.iter().map(|id| id.expect_local()) { @@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { /// Gets the span for the given impl block unless it's not being considered by the lint. fn get_impl_span(cx: &LateContext<'_>, id: LocalDefId) -> Option { - let id = cx.tcx.hir().local_def_id_to_hir_id(id); + let id = cx.tcx.local_def_id_to_hir_id(id); if let Node::Item(&Item { kind: ItemKind::Impl(impl_item), span, diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs index fe5eb5ccac528..ca2ac60306b3d 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::{implements_trait, is_type_lang_item}; use clippy_utils::{return_ty, trait_ref_of_method}; use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem, Unsafety}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; use rustc_target::spec::abi::Abi; diff --git a/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs b/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs index 269311a67d64c..e486563808a5d 100644 --- a/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs +++ b/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use std::borrow::Cow; use std::cmp::Reverse; use std::collections::BinaryHeap; diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs index 899126565f791..bc236c5c71fd8 100644 --- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs +++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs @@ -6,7 +6,7 @@ use rustc_ast::ast::Attribute; use rustc_errors::Applicability; use rustc_hir::{TraitFn, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Symbol}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs index 32b2cb4385f85..655f4b82aa4f1 100644 --- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs +++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs @@ -6,7 +6,7 @@ use clippy_utils::ty; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -89,27 +89,17 @@ impl LateLintPass<'_> for InstantSubtraction { rhs, ) = expr.kind { - if_chain! { - if is_instant_now_call(cx, lhs); - - if is_an_instant(cx, rhs); - if let Some(sugg) = Sugg::hir_opt(cx, rhs); - - then { - print_manual_instant_elapsed_sugg(cx, expr, sugg) - } else { - if_chain! { - if !expr.span.from_expansion(); - if self.msrv.meets(msrvs::TRY_FROM); - - if is_an_instant(cx, lhs); - if is_a_duration(cx, rhs); - - then { - print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr) - } - } - } + if is_instant_now_call(cx, lhs) + && is_an_instant(cx, rhs) + && let Some(sugg) = Sugg::hir_opt(cx, rhs) + { + print_manual_instant_elapsed_sugg(cx, expr, sugg); + } else if !expr.span.from_expansion() + && self.msrv.meets(msrvs::TRY_FROM) + && is_an_instant(cx, lhs) + && is_a_duration(cx, rhs) + { + print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr); } } } diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs index 9ffcee07d287a..b8e0eef7c7e9e 100644 --- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs +++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs @@ -6,7 +6,7 @@ use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind}; use rustc_ast::token; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs index de82935e66b65..8bcd9b532bd10 100644 --- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs @@ -2,7 +2,7 @@ use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, IntTy, UintTy}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; use clippy_utils::comparisons; diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 90048d96c9c68..b6aacba2517a1 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -6,9 +6,9 @@ use clippy_utils::source::is_present_in_source; use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case}; use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::Span; +use rustc_session::impl_lint_pass; use rustc_span::symbol::Symbol; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs index 9605d76fbf00d..39223c20470b5 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs @@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_hir; use rustc_hir::{Block, ItemKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs index 35e01862cee89..3614fb8cc963b 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs @@ -4,7 +4,7 @@ use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro}; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir::{HirId, Item, ItemKind, Mod}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::hygiene::AstPass; use rustc_span::{sym, ExpnKind}; diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs index 505aadd1a1106..b9fad726511c5 100644 --- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -4,7 +4,7 @@ use clippy_utils::ty::implements_trait; use rustc_hir::def_id::LocalDefId; use rustc_hir::{FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -71,7 +71,7 @@ fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefI if sig.decl.implicit_self.has_implicit_self() { let ret_ty = cx .tcx - .erase_late_bound_regions(cx.tcx.fn_sig(fn_id).instantiate_identity().output()); + .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(fn_id).instantiate_identity().output()); let ret_ty = cx .tcx .try_normalize_erasing_regions(cx.param_env, ret_ty) diff --git a/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs b/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs new file mode 100644 index 0000000000000..8110c1970d9b1 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs @@ -0,0 +1,78 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::higher::ForLoop; +use clippy_utils::match_any_def_paths; +use clippy_utils::paths::{ + HASHMAP_DRAIN, HASHMAP_ITER, HASHMAP_ITER_MUT, HASHMAP_KEYS, HASHMAP_VALUES, HASHMAP_VALUES_MUT, HASHSET_DRAIN, + HASHSET_ITER_TY, +}; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// This is a restriction lint which prevents the use of hash types (i.e., `HashSet` and `HashMap`) in for loops. + /// + /// ### Why is this bad? + /// Because hash types are unordered, when iterated through such as in a for loop, the values are returned in + /// an undefined order. As a result, on redundant systems this may cause inconsistencies and anomalies. + /// In addition, the unknown order of the elements may reduce readability or introduce other undesired + /// side effects. + /// + /// ### Example + /// ```no_run + /// let my_map = std::collections::HashMap::::new(); + /// for (key, value) in my_map { /* ... */ } + /// ``` + /// Use instead: + /// ```no_run + /// let my_map = std::collections::HashMap::::new(); + /// let mut keys = my_map.keys().clone().collect::>(); + /// keys.sort(); + /// for key in keys { + /// let value = &my_map[key]; + /// } + /// ``` + #[clippy::version = "1.75.0"] + pub ITER_OVER_HASH_TYPE, + restriction, + "iterating over unordered hash-based types (`HashMap` and `HashSet`)" +} + +declare_lint_pass!(IterOverHashType => [ITER_OVER_HASH_TYPE]); + +impl LateLintPass<'_> for IterOverHashType { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) { + if let Some(for_loop) = ForLoop::hir(expr) + && !for_loop.body.span.from_expansion() + && let ty = cx.typeck_results().expr_ty(for_loop.arg).peel_refs() + && let Some(adt) = ty.ty_adt_def() + && let did = adt.did() + && (match_any_def_paths( + cx, + did, + &[ + &HASHMAP_KEYS, + &HASHMAP_VALUES, + &HASHMAP_VALUES_MUT, + &HASHMAP_ITER, + &HASHMAP_ITER_MUT, + &HASHMAP_DRAIN, + &HASHSET_ITER_TY, + &HASHSET_DRAIN, + ], + ) + .is_some() + || is_type_diagnostic_item(cx, ty, sym::HashMap) + || is_type_diagnostic_item(cx, ty, sym::HashSet)) + { + span_lint( + cx, + ITER_OVER_HASH_TYPE, + expr.span, + "iteration over unordered hash-based type", + ); + }; + } +} diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 3c291f25590d4..3a5756482a125 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Symbol}; use std::iter; diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index a4f3d49834531..b561054b58240 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ConstKind}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, Span}; declare_clippy_lint! { @@ -47,43 +46,40 @@ impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]); impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if_chain! { - if !item.span.from_expansion(); - if let ItemKind::Const(_, generics, _) = &item.kind; + if !item.span.from_expansion() + && let ItemKind::Const(_, generics, _) = &item.kind // Since static items may not have generics, skip generic const items. // FIXME(generic_const_items): I don't think checking `generics.hwcp` suffices as it // doesn't account for empty where-clauses that only consist of keyword `where` IINM. - if generics.params.is_empty() && !generics.has_where_clause_predicates; - let ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); - if let ty::Array(element_type, cst) = ty.kind(); - if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind(); - if let Ok(element_count) = element_count.try_to_target_usize(cx.tcx); - if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()); - if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size); - - then { - let hi_pos = item.ident.span.lo() - BytePos::from_usize(1); - let sugg_span = Span::new( - hi_pos - BytePos::from_usize("const".len()), - hi_pos, - item.span.ctxt(), - item.span.parent(), - ); - span_lint_and_then( - cx, - LARGE_CONST_ARRAYS, - item.span, - "large array defined as const", - |diag| { - diag.span_suggestion( - sugg_span, - "make this a static item", - "static", - Applicability::MachineApplicable, - ); - } - ); - } + && generics.params.is_empty() && !generics.has_where_clause_predicates + && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() + && let ty::Array(element_type, cst) = ty.kind() + && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind() + && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx) + && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) + && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size) + { + let hi_pos = item.ident.span.lo() - BytePos::from_usize(1); + let sugg_span = Span::new( + hi_pos - BytePos::from_usize("const".len()), + hi_pos, + item.span.ctxt(), + item.span.parent(), + ); + span_lint_and_then( + cx, + LARGE_CONST_ARRAYS, + item.span, + "large array defined as const", + |diag| { + diag.span_suggestion( + sugg_span, + "make this a static item", + "static", + Applicability::MachineApplicable, + ); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index 0bf9b8718cd05..6feb188557643 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -8,7 +8,7 @@ use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{Adt, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs index 26a7278524e11..eb7570e9b44eb 100644 --- a/src/tools/clippy/clippy_lints/src/large_futures.rs +++ b/src/tools/clippy/clippy_lints/src/large_futures.rs @@ -4,7 +4,7 @@ use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_target::abi::Size; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs index 566901de34754..1b5981ecc281a 100644 --- a/src/tools/clippy/clippy_lints/src/large_include_file.rs +++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs @@ -4,7 +4,7 @@ use clippy_utils::macros::root_macro_call_first_node; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -50,37 +50,35 @@ impl_lint_pass!(LargeIncludeFile => [LARGE_INCLUDE_FILE]); impl LateLintPass<'_> for LargeIncludeFile { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { - if_chain! { - if let Some(macro_call) = root_macro_call_first_node(cx, expr); - if !is_lint_allowed(cx, LARGE_INCLUDE_FILE, expr.hir_id); - if cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id) - || cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id); - if let ExprKind::Lit(lit) = &expr.kind; - then { - let len = match &lit.node { - // include_bytes - LitKind::ByteStr(bstr, _) => bstr.len(), - // include_str - LitKind::Str(sym, _) => sym.as_str().len(), - _ => return, - }; + if let Some(macro_call) = root_macro_call_first_node(cx, expr) + && !is_lint_allowed(cx, LARGE_INCLUDE_FILE, expr.hir_id) + && (cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id) + || cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id)) + && let ExprKind::Lit(lit) = &expr.kind + { + let len = match &lit.node { + // include_bytes + LitKind::ByteStr(bstr, _) => bstr.len(), + // include_str + LitKind::Str(sym, _) => sym.as_str().len(), + _ => return, + }; - if len as u64 <= self.max_file_size { - return; - } - - span_lint_and_note( - cx, - LARGE_INCLUDE_FILE, - expr.span, - "attempted to include a large file", - None, - &format!( - "the configuration allows a maximum size of {} bytes", - self.max_file_size - ), - ); + if len as u64 <= self.max_file_size { + return; } + + span_lint_and_note( + cx, + LARGE_INCLUDE_FILE, + expr.span, + "attempted to include a large file", + None, + &format!( + "the configuration allows a maximum size of {} bytes", + self.max_file_size + ), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 5e312ab724020..fd33ba91bfd76 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -4,7 +4,7 @@ use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ConstKind}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs index 33636eb687f36..b397180a69c55 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 0f17d26764c98..e121da776b21e 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::Sugg; use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators}; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -14,10 +13,10 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{Span, Symbol}; +use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; +use rustc_span::{Span, Symbol}; declare_clippy_lint! { /// ### What it does @@ -132,37 +131,33 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { - if_chain! { - if item.ident.name == sym::len; - if let ImplItemKind::Fn(sig, _) = &item.kind; - if sig.decl.implicit_self.has_implicit_self(); - if sig.decl.inputs.len() == 1; - if cx.effective_visibilities.is_exported(item.owner_id.def_id); - if matches!(sig.decl.output, FnRetTy::Return(_)); - if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()); - if imp.of_trait.is_none(); - if let TyKind::Path(ty_path) = &imp.self_ty.kind; - if let Some(ty_id) = cx.qpath_res(ty_path, imp.self_ty.hir_id).opt_def_id(); - if let Some(local_id) = ty_id.as_local(); - let ty_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id); - if !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id); - if let Some(output) = parse_len_output( - cx, - cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder() - ); - then { - let (name, kind) = match cx.tcx.hir().find(ty_hir_id) { - Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"), - Some(Node::Item(x)) => match x.kind { - ItemKind::Struct(..) => (x.ident.name, "struct"), - ItemKind::Enum(..) => (x.ident.name, "enum"), - ItemKind::Union(..) => (x.ident.name, "union"), - _ => (x.ident.name, "type"), - } - _ => return, - }; - check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind) - } + if item.ident.name == sym::len + && let ImplItemKind::Fn(sig, _) = &item.kind + && sig.decl.implicit_self.has_implicit_self() + && sig.decl.inputs.len() == 1 + && cx.effective_visibilities.is_exported(item.owner_id.def_id) + && matches!(sig.decl.output, FnRetTy::Return(_)) + && let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()) + && imp.of_trait.is_none() + && let TyKind::Path(ty_path) = &imp.self_ty.kind + && let Some(ty_id) = cx.qpath_res(ty_path, imp.self_ty.hir_id).opt_def_id() + && let Some(local_id) = ty_id.as_local() + && let ty_hir_id = cx.tcx.local_def_id_to_hir_id(local_id) + && !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id) + && let Some(output) = + parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder()) + { + let (name, kind) = match cx.tcx.hir().find(ty_hir_id) { + Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"), + Some(Node::Item(x)) => match x.kind { + ItemKind::Struct(..) => (x.ident.name, "struct"), + ItemKind::Enum(..) => (x.ident.name, "enum"), + ItemKind::Union(..) => (x.ident.name, "union"), + _ => (x.ident.name, "type"), + }, + _ => return, + }; + check_for_is_empty(cx, sig.span, sig.decl.implicit_self, output, ty_id, name, kind); } } diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 2f6f36c396044..270162ae7717f 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -2,12 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::path_to_local_id; use clippy_utils::source::snippet; use clippy_utils::visitors::is_local_used; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{BindingAnnotation, Mutability}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -61,76 +60,85 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { let mut it = block.stmts.iter().peekable(); while let Some(stmt) = it.next() { - if_chain! { - if let Some(expr) = it.peek(); - if let hir::StmtKind::Local(local) = stmt.kind; - if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind; - if let hir::StmtKind::Expr(if_) = expr.kind; - if let hir::ExprKind::If(hir::Expr { kind: hir::ExprKind::DropTemps(cond), ..}, then, else_) = if_.kind; - if !is_local_used(cx, *cond, canonical_id); - if let hir::ExprKind::Block(then, _) = then.kind; - if let Some(value) = check_assign(cx, canonical_id, then); - if !is_local_used(cx, value, canonical_id); - then { - let span = stmt.span.to(if_.span); + if let Some(expr) = it.peek() + && let hir::StmtKind::Local(local) = stmt.kind + && let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind + && let hir::StmtKind::Expr(if_) = expr.kind + && let hir::ExprKind::If( + hir::Expr { + kind: hir::ExprKind::DropTemps(cond), + .. + }, + then, + else_, + ) = if_.kind + && !is_local_used(cx, *cond, canonical_id) + && let hir::ExprKind::Block(then, _) = then.kind + && let Some(value) = check_assign(cx, canonical_id, then) + && !is_local_used(cx, value, canonical_id) + { + let span = stmt.span.to(if_.span); - let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze( - cx.tcx, - cx.param_env, - ); - if has_interior_mutability { return; } + let has_interior_mutability = !cx + .typeck_results() + .node_type(canonical_id) + .is_freeze(cx.tcx, cx.param_env); + if has_interior_mutability { + return; + } - let (default_multi_stmts, default) = if let Some(else_) = else_ { - if let hir::ExprKind::Block(else_, _) = else_.kind { - if let Some(default) = check_assign(cx, canonical_id, else_) { - (else_.stmts.len() > 1, default) - } else if let Some(default) = local.init { - (true, default) - } else { - continue; - } + let (default_multi_stmts, default) = if let Some(else_) = else_ { + if let hir::ExprKind::Block(else_, _) = else_.kind { + if let Some(default) = check_assign(cx, canonical_id, else_) { + (else_.stmts.len() > 1, default) + } else if let Some(default) = local.init { + (true, default) } else { continue; } - } else if let Some(default) = local.init { - (false, default) } else { continue; - }; + } + } else if let Some(default) = local.init { + (false, default) + } else { + continue; + }; - let mutability = match mode { - BindingAnnotation(_, Mutability::Mut) => " ", - _ => "", - }; + let mutability = match mode { + BindingAnnotation(_, Mutability::Mut) => " ", + _ => "", + }; - // FIXME: this should not suggest `mut` if we can detect that the variable is not - // use mutably after the `if` + // FIXME: this should not suggest `mut` if we can detect that the variable is not + // use mutably after the `if` - let sug = format!( - "let {mutability}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};", - name=ident.name, - cond=snippet(cx, cond.span, "_"), - then=if then.stmts.len() > 1 { " ..;" } else { "" }, - else=if default_multi_stmts { " ..;" } else { "" }, - value=snippet(cx, value.span, ""), - default=snippet(cx, default.span, ""), - ); - span_lint_and_then(cx, - USELESS_LET_IF_SEQ, - span, - "`if _ { .. } else { .. }` is an expression", - |diag| { - diag.span_suggestion( - span, - "it is more idiomatic to write", - sug, - Applicability::HasPlaceholders, - ); - if !mutability.is_empty() { - diag.note("you might not need `mut` at all"); - } - }); - } + let sug = format!( + "let {mutability}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};", + name=ident.name, + cond=snippet(cx, cond.span, "_"), + then=if then.stmts.len() > 1 { " ..;" } else { "" }, + else=if default_multi_stmts { " ..;" } else { "" }, + value=snippet(cx, value.span, ""), + default=snippet(cx, default.span, ""), + ); + span_lint_and_then( + cx, + USELESS_LET_IF_SEQ, + span, + "`if _ { .. } else { .. }` is an expression", + |diag| { + diag.span_suggestion( + span, + "it is more idiomatic to write", + sug, + Applicability::HasPlaceholders, + ); + if !mutability.is_empty() { + diag.note("you might not need `mut` at all"); + } + }, + ); } } } @@ -141,20 +149,23 @@ fn check_assign<'tcx>( decl: hir::HirId, block: &'tcx hir::Block<'_>, ) -> Option<&'tcx hir::Expr<'tcx>> { - if_chain! { - if block.expr.is_none(); - if let Some(expr) = block.stmts.iter().last(); - if let hir::StmtKind::Semi(expr) = expr.kind; - if let hir::ExprKind::Assign(var, value, _) = expr.kind; - if path_to_local_id(var, decl); - then { - if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| is_local_used(cx, stmt, decl)) { - None - } else { - Some(value) - } - } else { + if block.expr.is_none() + && let Some(expr) = block.stmts.iter().last() + && let hir::StmtKind::Semi(expr) = expr.kind + && let hir::ExprKind::Assign(var, value, _) = expr.kind + && path_to_local_id(var, decl) + { + if block + .stmts + .iter() + .take(block.stmts.len() - 1) + .any(|stmt| is_local_used(cx, stmt, decl)) + { None + } else { + Some(value) } + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index 04f23a213f2bc..606c2ed72becc 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -5,7 +5,7 @@ use rustc_hir::{Local, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{GenericArgKind, IsSuggestable}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs index 79d728a021c3c..5f3f9b43f4580 100644 --- a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet; use rustc_hir::{Local, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -27,27 +27,25 @@ declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]); impl LateLintPass<'_> for UnderscoreTyped { fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) { - if_chain! { - if !in_external_macro(cx.tcx.sess, local.span); - if let Some(ty) = local.ty; // Ensure that it has a type defined - if let TyKind::Infer = &ty.kind; // that type is '_' - if local.span.eq_ctxt(ty.span); - then { - // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized, - // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty` - if snippet(cx, ty.span, "_").trim() != "_" { - return; - } - - span_lint_and_help( - cx, - LET_WITH_TYPE_UNDERSCORE, - local.span, - "variable declared with type underscore", - Some(ty.span.with_lo(local.pat.span.hi())), - "remove the explicit type `_` declaration" - ) + if !in_external_macro(cx.tcx.sess, local.span) + && let Some(ty) = local.ty // Ensure that it has a type defined + && let TyKind::Infer = &ty.kind // that type is '_' + && local.span.eq_ctxt(ty.span) + { + // NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized, + // this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty` + if snippet(cx, ty.span, "_").trim() != "_" { + return; } + + span_lint_and_help( + cx, + LET_WITH_TYPE_UNDERSCORE, + local.span, + "variable declared with type underscore", + Some(ty.span.with_lo(local.pat.span.hi())), + "remove the explicit type `_` declaration", + ); }; } } diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index ab978a677c236..1c59b2df853ba 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -52,7 +52,6 @@ extern crate declare_clippy_lint; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; -use rustc_session::Session; #[cfg(feature = "internal")] pub mod deprecated_lints; @@ -145,6 +144,7 @@ mod if_let_mutex; mod if_not_else; mod if_then_some_else_none; mod ignored_unit_patterns; +mod impl_hash_with_borrow_str_and_bytes; mod implicit_hasher; mod implicit_return; mod implicit_saturating_add; @@ -165,6 +165,7 @@ mod item_name_repetitions; mod items_after_statements; mod items_after_test_module; mod iter_not_returning_iterator; +mod iter_over_hash_type; mod iter_without_into_iter; mod large_const_arrays; mod large_enum_variant; @@ -308,7 +309,6 @@ mod slow_vector_initialization; mod std_instead_of_core; mod strings; mod strlen_on_c_strings; -mod suspicious_doc_comments; mod suspicious_operation_groupings; mod suspicious_trait_impl; mod suspicious_xor_used_as_pow; @@ -492,11 +492,84 @@ fn register_categories(store: &mut rustc_lint::LintStore) { groups.register(store); } -/// Register all lints and lint groups with the rustc plugin registry +/// Register all lints and lint groups with the rustc lint store /// /// Used in `./src/driver.rs`. #[expect(clippy::too_many_lines)] -pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &'static Conf) { +pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { + let Conf { + ref absolute_paths_allowed_crates, + absolute_paths_max_segments, + accept_comment_above_attributes, + accept_comment_above_statement, + allow_dbg_in_tests, + allow_expect_in_tests, + allow_mixed_uninlined_format_args, + allow_one_hash_in_raw_strings, + allow_print_in_tests, + allow_private_module_inception, + allow_unwrap_in_tests, + ref allowed_dotfiles, + ref allowed_idents_below_min_chars, + ref allowed_scripts, + ref arithmetic_side_effects_allowed_binary, + ref arithmetic_side_effects_allowed_unary, + ref arithmetic_side_effects_allowed, + array_size_threshold, + avoid_breaking_exported_api, + ref await_holding_invalid_types, + cargo_ignore_publish, + cognitive_complexity_threshold, + ref disallowed_macros, + ref disallowed_methods, + ref disallowed_names, + ref disallowed_types, + ref doc_valid_idents, + enable_raw_pointer_heuristic_for_send, + enforce_iter_loop_reborrow, + ref enforced_import_renames, + enum_variant_name_threshold, + enum_variant_size_threshold, + excessive_nesting_threshold, + future_size_threshold, + ref ignore_interior_mutability, + large_error_threshold, + literal_representation_threshold, + matches_for_let_else, + max_fn_params_bools, + max_include_file_size, + max_struct_bools, + max_suggested_slice_pattern_length, + max_trait_bounds, + min_ident_chars_threshold, + missing_docs_in_crate_items, + ref msrv, + pass_by_value_size_limit, + semicolon_inside_block_ignore_singleline, + semicolon_outside_block_ignore_multiline, + single_char_binding_names_threshold, + stack_size_threshold, + ref standard_macro_braces, + struct_field_name_threshold, + suppress_restriction_lint_in_const, + too_large_for_stack, + too_many_arguments_threshold, + too_many_lines_threshold, + trivial_copy_size_limit, + type_complexity_threshold, + unnecessary_box_size, + unreadable_literal_lint_fractions, + upper_case_acronyms_aggressive, + vec_box_size_threshold, + verbose_bit_mask_threshold, + warn_on_all_wildcard_imports, + check_private_items, + + blacklisted_names: _, + cyclomatic_complexity_threshold: _, + } = *conf; + let msrv = || msrv.clone(); + register_removed_non_tool_lints(store); register_categories(store); @@ -521,7 +594,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| { Box::new(utils::internal_lints::compiler_lint_functions::CompilerLintFunctions::new()) }); - store.register_late_pass(|_| Box::new(utils::internal_lints::if_chain_style::IfChainStyle)); store.register_late_pass(|_| Box::new(utils::internal_lints::invalid_paths::InvalidPaths)); store.register_late_pass(|_| { Box::::default() @@ -537,9 +609,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); } - let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone(); - let arithmetic_side_effects_allowed_binary = conf.arithmetic_side_effects_allowed_binary.clone(); - let arithmetic_side_effects_allowed_unary = conf.arithmetic_side_effects_allowed_unary.clone(); store.register_late_pass(move |_| { Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new( arithmetic_side_effects_allowed @@ -557,16 +626,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::::default()); store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir)); store.register_late_pass(|_| Box::new(utils::author::Author)); - let await_holding_invalid_types = conf.await_holding_invalid_types.clone(); store.register_late_pass(move |_| { Box::new(await_holding_invalid::AwaitHolding::new( await_holding_invalid_types.clone(), )) }); store.register_late_pass(|_| Box::new(serde_api::SerdeApi)); - let vec_box_size_threshold = conf.vec_box_size_threshold; - let type_complexity_threshold = conf.type_complexity_threshold; - let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; store.register_late_pass(move |_| { Box::new(types::Types::new( vec_box_size_threshold, @@ -599,19 +664,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor)); store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports)); - - let msrv = || conf.msrv.clone(); - let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; - let allow_expect_in_tests = conf.allow_expect_in_tests; - let allow_unwrap_in_tests = conf.allow_unwrap_in_tests; - let suppress_restriction_lint_in_const = conf.suppress_restriction_lint_in_const; store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv()))); - let allowed_dotfiles = conf - .allowed_dotfiles - .iter() - .cloned() - .chain(methods::DEFAULT_ALLOWED_DOTFILES.iter().copied().map(ToOwned::to_owned)) - .collect::>(); store.register_late_pass(move |_| { Box::new(methods::Methods::new( avoid_breaking_exported_api, @@ -622,7 +675,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv()))); - let matches_for_let_else = conf.matches_for_let_else; store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv()))); store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv()))); store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv()))); @@ -639,7 +691,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv()))); store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount)); store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod)); - let max_suggested_slice_pattern_length = conf.max_suggested_slice_pattern_length; store.register_late_pass(move |_| { Box::new(index_refutable_slice::IndexRefutableSlice::new( max_suggested_slice_pattern_length, @@ -648,7 +699,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(unit_types::UnitTypes)); - let enforce_iter_loop_reborrow = conf.enforce_iter_loop_reborrow; store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv(), enforce_iter_loop_reborrow))); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(lifetimes::Lifetimes)); @@ -662,13 +712,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(no_effect::NoEffect)); store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment)); store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv()))); - let cognitive_complexity_threshold = conf.cognitive_complexity_threshold; store.register_late_pass(move |_| { Box::new(cognitive_complexity::CognitiveComplexity::new( cognitive_complexity_threshold, )) }); - let too_large_for_stack = conf.too_large_for_stack; store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack })); store.register_late_pass(move |_| { Box::new(vec::UselessVec { @@ -684,18 +732,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum)); store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons)); store.register_late_pass(|_| Box::::default()); - let ignore_interior_mutability = conf.ignore_interior_mutability.clone(); store.register_late_pass(move |_| Box::new(copies::CopyAndPaste::new(ignore_interior_mutability.clone()))); store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator)); store.register_late_pass(|_| Box::new(format::UselessFormat)); store.register_late_pass(|_| Box::new(swap::Swap)); store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional)); store.register_late_pass(|_| Box::::default()); - let disallowed_names = conf.disallowed_names.iter().cloned().collect::>(); - store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone()))); - let too_many_arguments_threshold = conf.too_many_arguments_threshold; - let too_many_lines_threshold = conf.too_many_lines_threshold; - let large_error_threshold = conf.large_error_threshold; + store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names))); store.register_late_pass(move |_| { Box::new(functions::Functions::new( too_many_arguments_threshold, @@ -704,9 +747,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: avoid_breaking_exported_api, )) }); - let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::>(); - let missing_docs_in_crate_items = conf.missing_docs_in_crate_items; - store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); + store.register_late_pass(move |_| Box::new(doc::Documentation::new(doc_valid_idents, check_private_items))); store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply)); store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq)); store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); @@ -716,17 +757,17 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk)); store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl)); store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount)); - let enum_variant_size_threshold = conf.enum_variant_size_threshold; store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold))); store.register_late_pass(|_| Box::new(explicit_write::ExplicitWrite)); store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue)); - let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new( - conf.trivial_copy_size_limit, - conf.pass_by_value_size_limit, - conf.avoid_breaking_exported_api, - &sess.target, - ); - store.register_late_pass(move |_| Box::new(pass_by_ref_or_value)); + store.register_late_pass(move |tcx| { + Box::new(pass_by_ref_or_value::PassByRefOrValue::new( + trivial_copy_size_limit, + pass_by_value_size_limit, + avoid_breaking_exported_api, + tcx.sess.target.pointer_width, + )) + }); store.register_late_pass(|_| Box::new(ref_option_ref::RefOptionRef)); store.register_late_pass(|_| Box::new(infinite_iter::InfiniteIter)); store.register_late_pass(|_| Box::new(inline_fn_without_body::InlineFnWithoutBody)); @@ -746,7 +787,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: suppress_restriction_lint_in_const, )) }); - let ignore_interior_mutability = conf.ignore_interior_mutability.clone(); store.register_late_pass(move |_| Box::new(non_copy_const::NonCopyConst::new(ignore_interior_mutability.clone()))); store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast)); store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone)); @@ -755,10 +795,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(assertions_on_constants::AssertionsOnConstants)); store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates)); store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString)); - let max_trait_bounds = conf.max_trait_bounds; store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds, msrv()))); store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain)); - let ignore_interior_mutability = conf.ignore_interior_mutability.clone(); store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone()))); store.register_early_pass(|| Box::new(reference::DerefAddrOf)); store.register_early_pass(|| Box::new(double_parens::DoubleParens)); @@ -779,21 +817,16 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::new(redundant_else::RedundantElse)); store.register_late_pass(|_| Box::new(create_dir::CreateDir)); store.register_early_pass(|| Box::new(needless_arbitrary_self_type::NeedlessArbitrarySelfType)); - let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions; store.register_early_pass(move || { Box::new(literal_representation::LiteralDigitGrouping::new( - literal_representation_lint_fraction_readability, + unreadable_literal_lint_fractions, )) }); - let literal_representation_threshold = conf.literal_representation_threshold; store.register_early_pass(move || { Box::new(literal_representation::DecimalLiteralRepresentation::new( literal_representation_threshold, )) }); - let enum_variant_name_threshold = conf.enum_variant_name_threshold; - let struct_field_name_threshold = conf.struct_field_name_threshold; - let allow_private_module_inception = conf.allow_private_module_inception; store.register_late_pass(move |_| { Box::new(item_name_repetitions::ItemNameRepetitions::new( enum_variant_name_threshold, @@ -803,7 +836,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments)); - let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive; store.register_late_pass(move |_| { Box::new(upper_case_acronyms::UpperCaseAcronyms::new( avoid_breaking_exported_api, @@ -815,15 +847,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall)); store.register_late_pass(|_| Box::new(exit::Exit)); store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome)); - let array_size_threshold = u128::from(conf.array_size_threshold); - store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold))); - store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold))); + store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold.into()))); + store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold.into()))); store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic)); store.register_late_pass(|_| Box::new(as_conversions::AsConversions)); store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore)); store.register_early_pass(|| Box::::default()); - let max_fn_params_bools = conf.max_fn_params_bools; - let max_struct_bools = conf.max_struct_bools; store.register_late_pass(move |_| { Box::new(excessive_bools::ExcessiveBools::new( max_struct_bools, @@ -831,36 +860,30 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap)); - let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports))); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress)); store.register_late_pass(|_| Box::>::default()); store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); - let future_size_threshold = conf.future_size_threshold; store.register_late_pass(move |_| Box::new(large_futures::LargeFuture::new(future_size_threshold))); store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex)); store.register_late_pass(|_| Box::new(if_not_else::IfNotElse)); store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality)); store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn)); store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn)); - let single_char_binding_names_threshold = conf.single_char_binding_names_threshold; store.register_early_pass(move || { Box::new(non_expressive_names::NonExpressiveNames { single_char_binding_names_threshold, }) }); - let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::>(); - store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(¯o_matcher))); + store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(standard_macro_braces))); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::new(pattern_type_mismatch::PatternTypeMismatch)); store.register_late_pass(|_| Box::new(unwrap_in_result::UnwrapInResult)); store.register_late_pass(|_| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned)); store.register_late_pass(|_| Box::new(async_yields_async::AsyncYieldsAsync)); - let disallowed_macros = conf.disallowed_macros.clone(); store.register_late_pass(move |_| Box::new(disallowed_macros::DisallowedMacros::new(disallowed_macros.clone()))); - let disallowed_methods = conf.disallowed_methods.clone(); store.register_late_pass(move |_| Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone()))); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax)); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax)); @@ -875,36 +898,30 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison)); store.register_early_pass(move || Box::new(module_style::ModStyle)); store.register_late_pass(|_| Box::::default()); - let disallowed_types = conf.disallowed_types.clone(); store.register_late_pass(move |_| Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone()))); - let import_renames = conf.enforced_import_renames.clone(); store.register_late_pass(move |_| { Box::new(missing_enforced_import_rename::ImportRename::new( - import_renames.clone(), + enforced_import_renames.clone(), )) }); - let scripts = conf.allowed_scripts.clone(); - store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(&scripts))); + store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(allowed_scripts))); store.register_late_pass(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings)); store.register_late_pass(move |_| Box::new(self_named_constructors::SelfNamedConstructors)); store.register_late_pass(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator)); store.register_late_pass(move |_| Box::new(manual_assert::ManualAssert)); - let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send; store.register_late_pass(move |_| { Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new( enable_raw_pointer_heuristic_for_send, )) }); - let accept_comment_above_statement = conf.accept_comment_above_statement; - let accept_comment_above_attributes = conf.accept_comment_above_attributes; store.register_late_pass(move |_| { Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new( accept_comment_above_statement, accept_comment_above_attributes, )) }); - let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args; - store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined))); + store + .register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined_format_args))); store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray)); store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes)); store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit)); @@ -914,11 +931,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv()))); store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation)); store.register_late_pass(|_| Box::::default()); - let allow_dbg_in_tests = conf.allow_dbg_in_tests; store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests))); - let allow_print_in_tests = conf.allow_print_in_tests; store.register_late_pass(move |_| Box::new(write::Write::new(allow_print_in_tests))); - let cargo_ignore_publish = conf.cargo_ignore_publish; store.register_late_pass(move |_| { Box::new(cargo::Cargo { ignore_publish: cargo_ignore_publish, @@ -929,7 +943,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings)); store.register_early_pass(|| Box::new(pub_use::PubUse)); store.register_late_pass(|_| Box::new(format_push_string::FormatPushString)); - let max_include_file_size = conf.max_include_file_size; store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size))); store.register_late_pass(|_| Box::new(strings::TrimSplitWhitespace)); store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit)); @@ -942,7 +955,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty)); store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv()))); store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv()))); - let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold; store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold))); store.register_late_pass(|_| Box::::default()); store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv()))); @@ -959,8 +971,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr)); store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow)); store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv()))); - let semicolon_inside_block_ignore_singleline = conf.semicolon_inside_block_ignore_singleline; - let semicolon_outside_block_ignore_multiline = conf.semicolon_outside_block_ignore_multiline; store.register_late_pass(move |_| { Box::new(semicolon_block::SemicolonBlock::new( semicolon_inside_block_ignore_singleline, @@ -983,7 +993,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute)); store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv()))); store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct)); - let unnecessary_box_size = conf.unnecessary_box_size; store.register_late_pass(move |_| { Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new( avoid_breaking_exported_api, @@ -993,8 +1002,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk)); store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule)); store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation)); - store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments)); - let excessive_nesting_threshold = conf.excessive_nesting_threshold; store.register_early_pass(move || { Box::new(excessive_nesting::ExcessiveNesting { excessive_nesting_threshold, @@ -1010,15 +1017,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(redundant_type_annotations::RedundantTypeAnnotations)); store.register_late_pass(|_| Box::new(arc_with_non_send_sync::ArcWithNonSendSync)); store.register_late_pass(|_| Box::new(needless_if::NeedlessIf)); - let allowed_idents_below_min_chars = conf.allowed_idents_below_min_chars.clone(); - let min_ident_chars_threshold = conf.min_ident_chars_threshold; store.register_late_pass(move |_| { Box::new(min_ident_chars::MinIdentChars { allowed_idents_below_min_chars: allowed_idents_below_min_chars.clone(), min_ident_chars_threshold, }) }); - let stack_size_threshold = conf.stack_size_threshold; store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold))); store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit)); store.register_late_pass(move |_| { @@ -1033,10 +1037,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: def_id_to_usage: rustc_data_structures::fx::FxHashMap::default(), }) }); - let needless_raw_string_hashes_allow_one = conf.allow_one_hash_in_raw_strings; store.register_early_pass(move || { Box::new(raw_strings::RawStrings { - needless_raw_string_hashes_allow_one, + allow_one_hash_in_raw_strings, }) }); store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns)); @@ -1045,8 +1048,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(manual_float_methods::ManualFloatMethods)); store.register_late_pass(|_| Box::new(four_forward_slashes::FourForwardSlashes)); store.register_late_pass(|_| Box::new(error_impl_error::ErrorImplError)); - let absolute_paths_max_segments = conf.absolute_paths_max_segments; - let absolute_paths_allowed_crates = conf.absolute_paths_allowed_crates.clone(); store.register_late_pass(move |_| { Box::new(absolute_paths::AbsolutePaths { absolute_paths_max_segments, @@ -1066,6 +1067,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv()))); store.register_late_pass(|_| Box::new(iter_without_into_iter::IterWithoutIntoIter)); + store.register_late_pass(|_| Box::new(iter_over_hash_type::IterOverHashType)); + store.register_late_pass(|_| Box::new(impl_hash_with_borrow_str_and_bytes::ImplHashWithBorrowStrBytes)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 7517003be2301..17ca48683b3c1 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -18,10 +18,10 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter as middle_nested_filter; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; -use rustc_span::Span; use rustc_span::symbol::{kw, Ident, Symbol}; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does @@ -310,20 +310,17 @@ fn elision_suggestions( // elision doesn't work for explicit self types, see rust-lang/rust#69064 fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option) -> bool { - if_chain! { - if let Some(ident) = ident; - if ident.name == kw::SelfLower; - if !func.implicit_self.has_implicit_self(); - - if let Some(self_ty) = func.inputs.first(); - then { - let mut visitor = RefVisitor::new(cx); - visitor.visit_ty(self_ty); - - !visitor.all_lts().is_empty() - } else { - false - } + if let Some(ident) = ident + && ident.name == kw::SelfLower + && !func.implicit_self.has_implicit_self() + && let Some(self_ty) = func.inputs.first() + { + let mut visitor = RefVisitor::new(cx); + visitor.visit_ty(self_ty); + + !visitor.all_lts().is_empty() + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs index 0a5f5a80cb726..8a0955147bb54 100644 --- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs +++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs @@ -4,7 +4,7 @@ use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to use rustc_errors::Applicability; use rustc_hir::{Body, Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -53,18 +53,45 @@ declare_clippy_lint! { #[clippy::version = "1.70.0"] pub LINES_FILTER_MAP_OK, suspicious, - "filtering `std::io::Lines` with `filter_map()` or `flat_map()` might cause an infinite loop" + "filtering `std::io::Lines` with `filter_map()`, `flat_map()`, or `flatten()` might cause an infinite loop" } declare_lint_pass!(LinesFilterMapOk => [LINES_FILTER_MAP_OK]); impl LateLintPass<'_> for LinesFilterMapOk { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::MethodCall(fm_method, fm_receiver, [fm_arg], fm_span) = expr.kind + if let ExprKind::MethodCall(fm_method, fm_receiver, fm_args, fm_span) = expr.kind && is_trait_method(cx, expr, sym::Iterator) - && (fm_method.ident.as_str() == "filter_map" || fm_method.ident.as_str() == "flat_map") + && let fm_method_str = fm_method.ident.as_str() + && matches!(fm_method_str, "filter_map" | "flat_map" | "flatten") && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), sym::IoLines) + && should_lint(cx, fm_args, fm_method_str) { - let lint = match &fm_arg.kind { + span_lint_and_then( + cx, + LINES_FILTER_MAP_OK, + fm_span, + &format!("`{fm_method_str}()` will run forever if the iterator repeatedly produces an `Err`",), + |diag| { + diag.span_note( + fm_receiver.span, + "this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error"); + diag.span_suggestion( + fm_span, + "replace with", + "map_while(Result::ok)", + Applicability::MaybeIncorrect, + ); + }, + ); + } + } +} + +fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_str: &str) -> bool { + match args { + [] => method_str == "flatten", + [fm_arg] => { + match &fm_arg.kind { // Detect `Result::ok` ExprKind::Path(qpath) => cx .qpath_res(qpath, fm_arg.hir_id) @@ -86,29 +113,8 @@ impl LateLintPass<'_> for LinesFilterMapOk { } }, _ => false, - }; - if lint { - span_lint_and_then( - cx, - LINES_FILTER_MAP_OK, - fm_span, - &format!( - "`{}()` will run forever if the iterator repeatedly produces an `Err`", - fm_method.ident - ), - |diag| { - diag.span_note( - fm_receiver.span, - "this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error"); - diag.span_suggestion( - fm_span, - "replace with", - "map_while(Result::ok)", - Applicability::MaybeIncorrect, - ); - }, - ); } - } + }, + _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs index 2c14bb72a9e06..f33151cf4c591 100644 --- a/src/tools/clippy/clippy_lints/src/literal_representation.rs +++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs @@ -4,13 +4,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::{NumericLiteral, Radix}; use clippy_utils::source::snippet_opt; -use if_chain::if_chain; use rustc_ast::ast::{Expr, ExprKind, LitKind}; use rustc_ast::token; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; use std::iter; @@ -255,56 +254,48 @@ impl LiteralDigitGrouping { } fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) { - if_chain! { - if let Some(src) = snippet_opt(cx, span); - if let Ok(lit_kind) = LitKind::from_token_lit(lit); - if let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind); - then { - if !Self::check_for_mistyped_suffix(cx, span, &mut num_lit) { - return; - } + if let Some(src) = snippet_opt(cx, span) + && let Ok(lit_kind) = LitKind::from_token_lit(lit) + && let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind) + { + if !Self::check_for_mistyped_suffix(cx, span, &mut num_lit) { + return; + } + + if Self::is_literal_uuid_formatted(&num_lit) { + return; + } - if Self::is_literal_uuid_formatted(&num_lit) { - return; + let result = (|| { + let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix, true)?; + if let Some(fraction) = num_lit.fraction { + let fractional_group_size = + Self::get_group_size(fraction.rsplit('_'), num_lit.radix, self.lint_fraction_readability)?; + + let consistent = Self::parts_consistent( + integral_group_size, + fractional_group_size, + num_lit.integer.len(), + fraction.len(), + ); + if !consistent { + return Err(WarningType::InconsistentDigitGrouping); + }; } - let result = (|| { - - let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix, true)?; - if let Some(fraction) = num_lit.fraction { - let fractional_group_size = Self::get_group_size( - fraction.rsplit('_'), - num_lit.radix, - self.lint_fraction_readability)?; - - let consistent = Self::parts_consistent(integral_group_size, - fractional_group_size, - num_lit.integer.len(), - fraction.len()); - if !consistent { - return Err(WarningType::InconsistentDigitGrouping); - }; - } + Ok(()) + })(); - Ok(()) - })(); - - - if let Err(warning_type) = result { - let should_warn = match warning_type { - | WarningType::UnreadableLiteral - | WarningType::InconsistentDigitGrouping - | WarningType::UnusualByteGroupings - | WarningType::LargeDigitGroups => { - !span.from_expansion() - } - WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => { - true - } - }; - if should_warn { - warning_type.display(num_lit.format(), cx, span); - } + if let Err(warning_type) = result { + let should_warn = match warning_type { + WarningType::UnreadableLiteral + | WarningType::InconsistentDigitGrouping + | WarningType::UnusualByteGroupings + | WarningType::LargeDigitGroups => !span.from_expansion(), + WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => true, + }; + if should_warn { + warning_type.display(num_lit.format(), cx, span); } } } @@ -478,20 +469,18 @@ impl DecimalLiteralRepresentation { } fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) { // Lint integral literals. - if_chain! { - if let Ok(lit_kind) = LitKind::from_token_lit(lit); - if let LitKind::Int(val, _) = lit_kind; - if let Some(src) = snippet_opt(cx, span); - if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind); - if num_lit.radix == Radix::Decimal; - if val >= u128::from(self.threshold); - then { - let hex = format!("{val:#X}"); - let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false); - let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| { - warning_type.display(num_lit.format(), cx, span); - }); - } + if let Ok(lit_kind) = LitKind::from_token_lit(lit) + && let LitKind::Int(val, _) = lit_kind + && let Some(src) = snippet_opt(cx, span) + && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind) + && num_lit.radix == Radix::Decimal + && val >= u128::from(self.threshold) + { + let hex = format!("{val:#X}"); + let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false); + let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| { + warning_type.display(num_lit.format(), cx, span); + }); } } diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs index 1953ee8a71752..277062a84901c 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs @@ -2,7 +2,6 @@ use super::{make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{get_enclosing_block, is_integer_const}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_block, walk_expr}; use rustc_hir::{Expr, Pat}; @@ -30,59 +29,57 @@ pub(super) fn check<'tcx>( let mut initialize_visitor = InitializeVisitor::new(cx, expr, id); walk_block(&mut initialize_visitor, block); - if_chain! { - if let Some((name, ty, initializer)) = initialize_visitor.get_result(); - if is_integer_const(cx, initializer, 0); - then { - let mut applicability = Applicability::MaybeIncorrect; - let span = expr.span.with_hi(arg.span.hi()); + if let Some((name, ty, initializer)) = initialize_visitor.get_result() + && is_integer_const(cx, initializer, 0) + { + let mut applicability = Applicability::MaybeIncorrect; + let span = expr.span.with_hi(arg.span.hi()); - let int_name = match ty.map(Ty::kind) { - // usize or inferred - Some(ty::Uint(UintTy::Usize)) | None => { - span_lint_and_sugg( - cx, - EXPLICIT_COUNTER_LOOP, - span, - &format!("the variable `{name}` is used as a loop counter"), - "consider using", - format!( - "for ({name}, {}) in {}.enumerate()", - snippet_with_applicability(cx, pat.span, "item", &mut applicability), - make_iterator_snippet(cx, arg, &mut applicability), - ), - applicability, - ); - return; - } - Some(ty::Int(int_ty)) => int_ty.name_str(), - Some(ty::Uint(uint_ty)) => uint_ty.name_str(), - _ => return, - }; + let int_name = match ty.map(Ty::kind) { + // usize or inferred + Some(ty::Uint(UintTy::Usize)) | None => { + span_lint_and_sugg( + cx, + EXPLICIT_COUNTER_LOOP, + span, + &format!("the variable `{name}` is used as a loop counter"), + "consider using", + format!( + "for ({name}, {}) in {}.enumerate()", + snippet_with_applicability(cx, pat.span, "item", &mut applicability), + make_iterator_snippet(cx, arg, &mut applicability), + ), + applicability, + ); + return; + }, + Some(ty::Int(int_ty)) => int_ty.name_str(), + Some(ty::Uint(uint_ty)) => uint_ty.name_str(), + _ => return, + }; - span_lint_and_then( - cx, - EXPLICIT_COUNTER_LOOP, - span, - &format!("the variable `{name}` is used as a loop counter"), - |diag| { - diag.span_suggestion( - span, - "consider using", - format!( - "for ({name}, {}) in (0_{int_name}..).zip({})", - snippet_with_applicability(cx, pat.span, "item", &mut applicability), - make_iterator_snippet(cx, arg, &mut applicability), - ), - applicability, - ); + span_lint_and_then( + cx, + EXPLICIT_COUNTER_LOOP, + span, + &format!("the variable `{name}` is used as a loop counter"), + |diag| { + diag.span_suggestion( + span, + "consider using", + format!( + "for ({name}, {}) in (0_{int_name}..).zip({})", + snippet_with_applicability(cx, pat.span, "item", &mut applicability), + make_iterator_snippet(cx, arg, &mut applicability), + ), + applicability, + ); - diag.note(format!( - "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`" - )); - }, - ); - } + diag.note(format!( + "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`" + )); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs index a9a9058c93f36..d484ce40d785e 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs @@ -4,7 +4,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::implements_trait; use clippy_utils::{higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::lang_items::LangItem; @@ -23,77 +22,79 @@ pub(super) fn check<'tcx>( let inner_expr = peel_blocks_with_stmt(body); // Check for the specific case that the result is returned and optimize suggestion for that (more // cases can be added later) - if_chain! { - if let Some(higher::If { cond, then, r#else: None, }) = higher::If::hir(inner_expr); - if let Some(binding_id) = get_binding(pat); - if let ExprKind::Block(block, _) = then.kind; - if let [stmt] = block.stmts; - if let StmtKind::Semi(semi) = stmt.kind; - if let ExprKind::Ret(Some(ret_value)) = semi.kind; - if let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind; - if is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome); - if path_res(cx, inner_ret) == Res::Local(binding_id); - if let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr); - then { - let mut applicability = Applicability::MachineApplicable; - let mut snippet = make_iterator_snippet(cx, arg, &mut applicability); - // Checks if `pat` is a single reference to a binding (`&x`) - let is_ref_to_binding = - matches!(pat.kind, PatKind::Ref(inner, _) if matches!(inner.kind, PatKind::Binding(..))); - // If `pat` is not a binding or a reference to a binding (`x` or `&x`) - // we need to map it to the binding returned by the function (i.e. `.map(|(x, _)| x)`) - if !(matches!(pat.kind, PatKind::Binding(..)) || is_ref_to_binding) { - snippet.push_str( - &format!( - ".map(|{}| {})", - snippet_with_applicability(cx, pat.span, "..", &mut applicability), - snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), - )[..], - ); - } - let ty = cx.typeck_results().expr_ty(inner_ret); - if cx.tcx.lang_items().copy_trait().map_or(false, |id| implements_trait(cx, ty, id, &[])) { - snippet.push_str( - &format!( - ".find(|{}{}| {})", - "&".repeat(1 + usize::from(is_ref_to_binding)), - snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), - snippet_with_applicability(cx, cond.span, "..", &mut applicability), - )[..], - ); - if is_ref_to_binding { - snippet.push_str(".copied()"); - } - } else { - applicability = Applicability::MaybeIncorrect; - snippet.push_str( - &format!( - ".find(|{}| {})", - snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), - snippet_with_applicability(cx, cond.span, "..", &mut applicability), - )[..], - ); + if let Some(higher::If { + cond, + then, + r#else: None, + }) = higher::If::hir(inner_expr) + && let Some(binding_id) = get_binding(pat) + && let ExprKind::Block(block, _) = then.kind + && let [stmt] = block.stmts + && let StmtKind::Semi(semi) = stmt.kind + && let ExprKind::Ret(Some(ret_value)) = semi.kind + && let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind + && is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome) + && path_res(cx, inner_ret) == Res::Local(binding_id) + && let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr) + { + let mut applicability = Applicability::MachineApplicable; + let mut snippet = make_iterator_snippet(cx, arg, &mut applicability); + // Checks if `pat` is a single reference to a binding (`&x`) + let is_ref_to_binding = + matches!(pat.kind, PatKind::Ref(inner, _) if matches!(inner.kind, PatKind::Binding(..))); + // If `pat` is not a binding or a reference to a binding (`x` or `&x`) + // we need to map it to the binding returned by the function (i.e. `.map(|(x, _)| x)`) + if !(matches!(pat.kind, PatKind::Binding(..)) || is_ref_to_binding) { + snippet.push_str( + &format!( + ".map(|{}| {})", + snippet_with_applicability(cx, pat.span, "..", &mut applicability), + snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), + )[..], + ); + } + let ty = cx.typeck_results().expr_ty(inner_ret); + if cx + .tcx + .lang_items() + .copy_trait() + .map_or(false, |id| implements_trait(cx, ty, id, &[])) + { + snippet.push_str( + &format!( + ".find(|{}{}| {})", + "&".repeat(1 + usize::from(is_ref_to_binding)), + snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), + snippet_with_applicability(cx, cond.span, "..", &mut applicability), + )[..], + ); + if is_ref_to_binding { + snippet.push_str(".copied()"); } - // Extends to `last_stmt` to include semicolon in case of `return None;` - let lint_span = span.to(last_stmt.span).to(last_ret.span); - span_lint_and_then( - cx, - MANUAL_FIND, - lint_span, - "manual implementation of `Iterator::find`", - |diag| { - if applicability == Applicability::MaybeIncorrect { - diag.note("you may need to dereference some variables"); - } - diag.span_suggestion( - lint_span, - "replace with an iterator", - snippet, - applicability, - ); - }, + } else { + applicability = Applicability::MaybeIncorrect; + snippet.push_str( + &format!( + ".find(|{}| {})", + snippet_with_applicability(cx, inner_ret.span, "..", &mut applicability), + snippet_with_applicability(cx, cond.span, "..", &mut applicability), + )[..], ); } + // Extends to `last_stmt` to include semicolon in case of `return None;` + let lint_span = span.to(last_stmt.span).to(last_ret.span); + span_lint_and_then( + cx, + MANUAL_FIND, + lint_span, + "manual implementation of `Iterator::find`", + |diag| { + if applicability == Applicability::MaybeIncorrect { + diag.note("you may need to dereference some variables"); + } + diag.span_suggestion(lint_span, "replace with an iterator", snippet, applicability); + }, + ); } } @@ -124,34 +125,30 @@ fn last_stmt_and_ret<'tcx>( if let Some(ret) = block.expr { return Some((last_stmt, ret)); } - if_chain! { - if let [.., snd_last, _] = block.stmts; - if let StmtKind::Semi(last_expr) = last_stmt.kind; - if let ExprKind::Ret(Some(ret)) = last_expr.kind; - then { - return Some((snd_last, ret)); - } + if let [.., snd_last, _] = block.stmts + && let StmtKind::Semi(last_expr) = last_stmt.kind + && let ExprKind::Ret(Some(ret)) = last_expr.kind + { + return Some((snd_last, ret)); } } None } let mut parent_iter = cx.tcx.hir().parent_iter(expr.hir_id); - if_chain! { + if let Some((node_hir, Node::Stmt(..))) = parent_iter.next() // This should be the loop - if let Some((node_hir, Node::Stmt(..))) = parent_iter.next(); // This should be the function body - if let Some((_, Node::Block(block))) = parent_iter.next(); - if let Some((last_stmt, last_ret)) = extract(block); - if last_stmt.hir_id == node_hir; - if is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone); - if let Some((_, Node::Expr(_block))) = parent_iter.next(); + && let Some((_, Node::Block(block))) = parent_iter.next() + && let Some((last_stmt, last_ret)) = extract(block) + && last_stmt.hir_id == node_hir + && is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone) + && let Some((_, Node::Expr(_block))) = parent_iter.next() // This includes the function header - if let Some((_, func)) = parent_iter.next(); - if func.fn_kind().is_some(); - then { - Some((block.stmts.last().unwrap(), last_ret)) - } else { - None - } + && let Some((_, func)) = parent_iter.next() + && func.fn_kind().is_some() + { + Some((block.stmts.last().unwrap(), last_ret)) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs index 124a35f8f540b..a726b11695637 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs @@ -3,7 +3,6 @@ use super::MANUAL_FLATTEN; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::visitors::is_local_used; use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, Pat, PatKind}; @@ -21,66 +20,51 @@ pub(super) fn check<'tcx>( span: Span, ) { let inner_expr = peel_blocks_with_stmt(body); - if_chain! { - if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None }) - = higher::IfLet::hir(cx, inner_expr); + if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None }) + = higher::IfLet::hir(cx, inner_expr) // Ensure match_expr in `if let` statement is the same as the pat from the for-loop - if let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind; - if path_to_local_id(let_expr, pat_hir_id); + && let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind + && path_to_local_id(let_expr, pat_hir_id) // Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result` - if let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind; - if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id); - if let Some(variant_id) = cx.tcx.opt_parent(ctor_id); - let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id); - let ok_ctor = cx.tcx.lang_items().result_ok_variant() == Some(variant_id); - if some_ctor || ok_ctor; + && let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind + && let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id) + && let Some(variant_id) = cx.tcx.opt_parent(ctor_id) + && let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id) + && let ok_ctor = cx.tcx.lang_items().result_ok_variant() == Some(variant_id) + && (some_ctor || ok_ctor) // Ensure expr in `if let` is not used afterwards - if !is_local_used(cx, if_then, pat_hir_id); - then { - let if_let_type = if some_ctor { "Some" } else { "Ok" }; - // Prepare the error message - let msg = format!("unnecessary `if let` since only the `{if_let_type}` variant of the iterator element is used"); + && !is_local_used(cx, if_then, pat_hir_id) + { + let if_let_type = if some_ctor { "Some" } else { "Ok" }; + // Prepare the error message + let msg = + format!("unnecessary `if let` since only the `{if_let_type}` variant of the iterator element is used"); - // Prepare the help message - let mut applicability = Applicability::MaybeIncorrect; - let arg_snippet = make_iterator_snippet(cx, arg, &mut applicability); - let copied = match cx.typeck_results().expr_ty(let_expr).kind() { - ty::Ref(_, inner, _) => match inner.kind() { - ty::Ref(..) => ".copied()", - _ => "" - } - _ => "" - }; + // Prepare the help message + let mut applicability = Applicability::MaybeIncorrect; + let arg_snippet = make_iterator_snippet(cx, arg, &mut applicability); + let copied = match cx.typeck_results().expr_ty(let_expr).kind() { + ty::Ref(_, inner, _) => match inner.kind() { + ty::Ref(..) => ".copied()", + _ => "", + }, + _ => "", + }; - let sugg = format!("{arg_snippet}{copied}.flatten()"); + let sugg = format!("{arg_snippet}{copied}.flatten()"); - // If suggestion is not a one-liner, it won't be shown inline within the error message. In that case, - // it will be shown in the extra `help` message at the end, which is why the first `help_msg` needs - // to refer to the correct relative position of the suggestion. - let help_msg = if sugg.contains('\n') { - "remove the `if let` statement in the for loop and then..." - } else { - "...and remove the `if let` statement in the for loop" - }; + // If suggestion is not a one-liner, it won't be shown inline within the error message. In that + // case, it will be shown in the extra `help` message at the end, which is why the first + // `help_msg` needs to refer to the correct relative position of the suggestion. + let help_msg = if sugg.contains('\n') { + "remove the `if let` statement in the for loop and then..." + } else { + "...and remove the `if let` statement in the for loop" + }; - span_lint_and_then( - cx, - MANUAL_FLATTEN, - span, - &msg, - |diag| { - diag.span_suggestion( - arg.span, - "try", - sugg, - applicability, - ); - diag.span_help( - inner_expr.span, - help_msg, - ); - } - ); - } + span_lint_and_then(cx, MANUAL_FLATTEN, span, &msg, |diag| { + diag.span_suggestion(arg.span, "try", sugg, applicability); + diag.span_help(inner_expr.span, help_msg); + }); } } diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index d3fd0e8639e97..40d56240b9deb 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -4,7 +4,6 @@ use clippy_utils::source::snippet; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_copy; use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg}; -use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir::intravisit::walk_block; @@ -59,22 +58,31 @@ pub(super) fn check<'tcx>( .map(|o| { o.and_then(|(lhs, rhs)| { let rhs = fetch_cloned_expr(rhs); - if_chain! { - if let ExprKind::Index(base_left, idx_left, _) = lhs.kind; - if let ExprKind::Index(base_right, idx_right, _) = rhs.kind; - if let Some(ty) = get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_left)); - if get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_right)).is_some(); - if let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts); - if let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts); + if let ExprKind::Index(base_left, idx_left, _) = lhs.kind + && let ExprKind::Index(base_right, idx_right, _) = rhs.kind + && let Some(ty) = get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_left)) + && get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_right)).is_some() + && let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts) + && let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts) // Source and destination must be different - if path_to_local(base_left) != path_to_local(base_right); - then { - Some((ty, IndexExpr { base: base_left, idx: start_left, idx_offset: offset_left }, - IndexExpr { base: base_right, idx: start_right, idx_offset: offset_right })) - } else { - None - } + && path_to_local(base_left) != path_to_local(base_right) + { + Some(( + ty, + IndexExpr { + base: base_left, + idx: start_left, + idx_offset: offset_left, + }, + IndexExpr { + base: base_right, + idx: start_right, + idx_offset: offset_right, + }, + )) + } else { + None } }) }) @@ -118,23 +126,19 @@ fn build_manual_memcpy_suggestion<'tcx>( } let print_limit = |end: &Expr<'_>, end_str: &str, base: &Expr<'_>, sugg: MinifyingSugg<'static>| { - if_chain! { - if let ExprKind::MethodCall(method, recv, [], _) = end.kind; - if method.ident.name == sym::len; - if path_to_local(recv) == path_to_local(base); - then { - if sugg.to_string() == end_str { - sugg::EMPTY.into() - } else { - sugg - } + if let ExprKind::MethodCall(method, recv, [], _) = end.kind + && method.ident.name == sym::len + && path_to_local(recv) == path_to_local(base) + { + if sugg.to_string() == end_str { + sugg::EMPTY.into() } else { - match limits { - ast::RangeLimits::Closed => { - sugg + &sugg::ONE.into() - }, - ast::RangeLimits::HalfOpen => sugg, - } + sugg + } + } else { + match limits { + ast::RangeLimits::Closed => sugg + &sugg::ONE.into(), + ast::RangeLimits::HalfOpen => sugg, } } }; @@ -174,7 +178,9 @@ fn build_manual_memcpy_suggestion<'tcx>( let dst_base_str = snippet(cx, dst.base.span, "???"); let src_base_str = snippet(cx, src.base.span, "???"); - let dst = if dst_offset == sugg::EMPTY && dst_limit == sugg::EMPTY { + let dst = if (dst_offset == sugg::EMPTY && dst_limit == sugg::EMPTY) + || is_array_length_equal_to_range(cx, start, end, dst.base) + { dst_base_str } else { format!("{dst_base_str}[{}..{}]", dst_offset.maybe_par(), dst_limit.maybe_par()).into() @@ -186,11 +192,13 @@ fn build_manual_memcpy_suggestion<'tcx>( "clone_from_slice" }; - format!( - "{dst}.{method_str}(&{src_base_str}[{}..{}]);", - src_offset.maybe_par(), - src_limit.maybe_par() - ) + let src = if is_array_length_equal_to_range(cx, start, end, src.base) { + src_base_str + } else { + format!("{src_base_str}[{}..{}]", src_offset.maybe_par(), src_limit.maybe_par()).into() + }; + + format!("{dst}.{method_str}(&{src});") } /// a wrapper of `Sugg`. Besides what `Sugg` do, this removes unnecessary `0`; @@ -331,10 +339,12 @@ fn get_slice_like_element_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Opti } fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { - if_chain! { - if let ExprKind::MethodCall(method, arg, [], _) = expr.kind; - if method.ident.name == sym::clone; - then { arg } else { expr } + if let ExprKind::MethodCall(method, arg, [], _) = expr.kind + && method.ident.name == sym::clone + { + arg + } else { + expr } } @@ -446,3 +456,34 @@ fn get_loop_counters<'a, 'tcx>( .into() }) } + +fn is_array_length_equal_to_range(cx: &LateContext<'_>, start: &Expr<'_>, end: &Expr<'_>, arr: &Expr<'_>) -> bool { + fn extract_lit_value(expr: &Expr<'_>) -> Option { + if let ExprKind::Lit(lit) = expr.kind + && let ast::LitKind::Int(value, _) = lit.node + { + Some(value) + } else { + None + } + } + + let arr_ty = cx.typeck_results().expr_ty(arr).peel_refs(); + + if let ty::Array(_, s) = arr_ty.kind() { + let size: u128 = if let Some(size) = s.try_eval_target_usize(cx.tcx, cx.param_env) { + size.into() + } else { + return false; + }; + + let range = match (extract_lit_value(start), extract_lit_value(end)) { + (Some(start_value), Some(end_value)) => end_value - start_value, + _ => return false, + }; + + size == range + } else { + false + } +} diff --git a/src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs b/src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs index 7b7d19c753feb..e405829b2f4ba 100644 --- a/src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/missing_spin_loop.rs @@ -31,26 +31,30 @@ fn unpack_cond<'tcx>(cond: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { } pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Block(Block { stmts: [], expr: None, ..}, _) = body.kind; - if let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind; - if [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name); - if let ty::Adt(def, _args) = cx.typeck_results().expr_ty(callee).kind(); - if cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did()); - then { - span_lint_and_sugg( - cx, - MISSING_SPIN_LOOP, - body.span, - "busy-waiting loop should at least have a spin loop hint", - "try", - (if is_no_std_crate(cx) { - "{ core::hint::spin_loop() }" - } else { - "{ std::hint::spin_loop() }" - }).into(), - Applicability::MachineApplicable - ); - } + if let ExprKind::Block( + Block { + stmts: [], expr: None, .. + }, + _, + ) = body.kind + && let ExprKind::MethodCall(method, callee, ..) = unpack_cond(cond).kind + && [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name) + && let ty::Adt(def, _args) = cx.typeck_results().expr_ty(callee).kind() + && cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did()) + { + span_lint_and_sugg( + cx, + MISSING_SPIN_LOOP, + body.span, + "busy-waiting loop should at least have a spin loop hint", + "try", + (if is_no_std_crate(cx) { + "{ core::hint::spin_loop() }" + } else { + "{ std::hint::spin_loop() }" + }) + .into(), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index 67c80fb8387f5..892336878c7b3 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -24,7 +24,7 @@ use clippy_config::msrvs::Msrv; use clippy_utils::higher; use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor}; diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index 2c12d9582d638..227096251a550 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -1,7 +1,6 @@ use super::MUT_RANGE_BOUND; use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::{get_enclosing_block, higher, path_to_local}; -use if_chain::if_chain; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; @@ -12,19 +11,17 @@ use rustc_middle::ty; use rustc_span::Span; pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) { - if_chain! { - if let Some(higher::Range { - start: Some(start), - end: Some(end), - .. - }) = higher::Range::hir(arg); - let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end)); - if mut_id_start.is_some() || mut_id_end.is_some(); - then { - let (span_low, span_high) = check_for_mutation(cx, body, mut_id_start, mut_id_end); - mut_warn_with_span(cx, span_low); - mut_warn_with_span(cx, span_high); - } + if let Some(higher::Range { + start: Some(start), + end: Some(end), + .. + }) = higher::Range::hir(arg) + && let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end)) + && (mut_id_start.is_some() || mut_id_end.is_some()) + { + let (span_low, span_high) = check_for_mutation(cx, body, mut_id_start, mut_id_end); + mut_warn_with_span(cx, span_low); + mut_warn_with_span(cx, span_high); } } @@ -42,13 +39,11 @@ fn mut_warn_with_span(cx: &LateContext<'_>, span: Option) { } fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option { - if_chain! { - if let Some(hir_id) = path_to_local(bound); - if let Node::Pat(pat) = cx.tcx.hir().get(hir_id); - if let PatKind::Binding(BindingAnnotation::MUT, ..) = pat.kind; - then { - return Some(hir_id); - } + if let Some(hir_id) = path_to_local(bound) + && let Node::Pat(pat) = cx.tcx.hir().get(hir_id) + && let PatKind::Binding(BindingAnnotation::MUT, ..) = pat.kind + { + return Some(hir_id); } None } diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index c4af46b8fd3a7..e2be861a70890 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -4,7 +4,6 @@ use clippy_utils::source::snippet; use clippy_utils::ty::has_iter_method; use clippy_utils::visitors::is_local_used; use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq}; -use if_chain::if_chain; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::{DefKind, Res}; @@ -187,15 +186,13 @@ pub(super) fn check<'tcx>( } fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool { - if_chain! { - if let ExprKind::MethodCall(method, recv, [], _) = expr.kind; - if method.ident.name == sym::len; - if let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind; - if path.segments.len() == 1; - if path.segments[0].ident.name == var; - then { - return true; - } + if let ExprKind::MethodCall(method, recv, [], _) = expr.kind + && method.ident.name == sym::len + && let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind + && path.segments.len() == 1 + && path.segments[0].ident.name == var + { + return true; } false @@ -207,17 +204,15 @@ fn is_end_eq_array_len<'tcx>( limits: ast::RangeLimits, indexed_ty: Ty<'tcx>, ) -> bool { - if_chain! { - if let ExprKind::Lit(lit) = end.kind; - if let ast::LitKind::Int(end_int, _) = lit.node; - if let ty::Array(_, arr_len_const) = indexed_ty.kind(); - if let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env); - then { - return match limits { - ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(), - ast::RangeLimits::HalfOpen => end_int >= arr_len.into(), - }; - } + if let ExprKind::Lit(lit) = end.kind + && let ast::LitKind::Int(end_int, _) = lit.node + && let ty::Array(_, arr_len_const) = indexed_ty.kind() + && let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env) + { + return match limits { + ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(), + ast::RangeLimits::HalfOpen => end_int >= arr_len.into(), + }; } false @@ -248,51 +243,49 @@ struct VarVisitor<'a, 'tcx> { impl<'a, 'tcx> VarVisitor<'a, 'tcx> { fn check(&mut self, idx: &'tcx Expr<'_>, seqexpr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) -> bool { - if_chain! { + if let ExprKind::Path(ref seqpath) = seqexpr.kind // the indexed container is referenced by a name - if let ExprKind::Path(ref seqpath) = seqexpr.kind; - if let QPath::Resolved(None, seqvar) = *seqpath; - if seqvar.segments.len() == 1; - if is_local_used(self.cx, idx, self.var); - then { - if self.prefer_mutable { - self.indexed_mut.insert(seqvar.segments[0].ident.name); - } - let index_used_directly = matches!(idx.kind, ExprKind::Path(_)); - let res = self.cx.qpath_res(seqpath, seqexpr.hir_id); - match res { - Res::Local(hir_id) => { - let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); - let extent = self - .cx - .tcx - .region_scope_tree(parent_def_id) - .var_scope(hir_id.local_id) - .unwrap(); - if index_used_directly { - self.indexed_directly.insert( - seqvar.segments[0].ident.name, - (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)), - ); - } else { - self.indexed_indirectly - .insert(seqvar.segments[0].ident.name, Some(extent)); - } - return false; // no need to walk further *on the variable* - }, - Res::Def(DefKind::Static(_) | DefKind::Const, ..) => { - if index_used_directly { - self.indexed_directly.insert( - seqvar.segments[0].ident.name, - (None, self.cx.typeck_results().node_type(seqexpr.hir_id)), - ); - } else { - self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); - } - return false; // no need to walk further *on the variable* - }, - _ => (), - } + && let QPath::Resolved(None, seqvar) = *seqpath + && seqvar.segments.len() == 1 + && is_local_used(self.cx, idx, self.var) + { + if self.prefer_mutable { + self.indexed_mut.insert(seqvar.segments[0].ident.name); + } + let index_used_directly = matches!(idx.kind, ExprKind::Path(_)); + let res = self.cx.qpath_res(seqpath, seqexpr.hir_id); + match res { + Res::Local(hir_id) => { + let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); + let extent = self + .cx + .tcx + .region_scope_tree(parent_def_id) + .var_scope(hir_id.local_id) + .unwrap(); + if index_used_directly { + self.indexed_directly.insert( + seqvar.segments[0].ident.name, + (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)), + ); + } else { + self.indexed_indirectly + .insert(seqvar.segments[0].ident.name, Some(extent)); + } + return false; // no need to walk further *on the variable* + }, + Res::Def(DefKind::Static(_) | DefKind::Const, ..) => { + if index_used_directly { + self.indexed_directly.insert( + seqvar.segments[0].ident.name, + (None, self.cx.typeck_results().node_type(seqexpr.hir_id)), + ); + } else { + self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); + } + return false; // no need to walk further *on the variable* + }, + _ => (), } } true @@ -301,42 +294,36 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if_chain! { + if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind // a range index op - if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind; - if let Some(trait_id) = self + && let Some(trait_id) = self .cx .typeck_results() .type_dependent_def_id(expr.hir_id) - .and_then(|def_id| self.cx.tcx.trait_of_item(def_id)); - if (meth.ident.name == sym::index && self.cx.tcx.lang_items().index_trait() == Some(trait_id)) - || (meth.ident.name == sym::index_mut && self.cx.tcx.lang_items().index_mut_trait() == Some(trait_id)); - if !self.check(args_1, args_0, expr); - then { - return; - } + .and_then(|def_id| self.cx.tcx.trait_of_item(def_id)) + && ((meth.ident.name == sym::index && self.cx.tcx.lang_items().index_trait() == Some(trait_id)) + || (meth.ident.name == sym::index_mut && self.cx.tcx.lang_items().index_mut_trait() == Some(trait_id))) + && !self.check(args_1, args_0, expr) + { + return; } - if_chain! { + if let ExprKind::Index(seqexpr, idx, _) = expr.kind // an index op - if let ExprKind::Index(seqexpr, idx, _) = expr.kind; - if !self.check(idx, seqexpr, expr); - then { - return; - } + && !self.check(idx, seqexpr, expr) + { + return; } - if_chain! { + if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind // directly using a variable - if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind; - if let Res::Local(local_id) = path.res; - then { - if local_id == self.var { - self.nonindex = true; - } else { - // not the correct variable, but still a variable - self.referenced.insert(path.segments[0].ident.name); - } + && let Res::Local(local_id) = path.res + { + if local_id == self.var { + self.nonindex = true; + } else { + // not the correct variable, but still a variable + self.referenced.insert(path.segments[0].ident.name); } } diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index 5fffb27cda2f1..15e11fd386cdd 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::path_to_local; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; -use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -44,54 +43,50 @@ pub(super) fn check<'tcx>( // Determine whether it is safe to lint the body let mut same_item_push_visitor = SameItemPushVisitor::new(cx); walk_expr(&mut same_item_push_visitor, body); - if_chain! { - if same_item_push_visitor.should_lint(); - if let Some((vec, pushed_item, ctxt)) = same_item_push_visitor.vec_push; - let vec_ty = cx.typeck_results().expr_ty(vec); - let ty = vec_ty.walk().nth(1).unwrap().expect_ty(); - if cx + if same_item_push_visitor.should_lint() + && let Some((vec, pushed_item, ctxt)) = same_item_push_visitor.vec_push + && let vec_ty = cx.typeck_results().expr_ty(vec) + && let ty = vec_ty.walk().nth(1).unwrap().expect_ty() + && cx .tcx .lang_items() .clone_trait() - .map_or(false, |id| implements_trait(cx, ty, id, &[])); - then { - // Make sure that the push does not involve possibly mutating values - match pushed_item.kind { - ExprKind::Path(ref qpath) => { - match cx.qpath_res(qpath, pushed_item.hir_id) { - // immutable bindings that are initialized with literal or constant - Res::Local(hir_id) => { - let node = cx.tcx.hir().get(hir_id); - if_chain! { - if let Node::Pat(pat) = node; - if let PatKind::Binding(bind_ann, ..) = pat.kind; - if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut)); - let parent_node = cx.tcx.hir().parent_id(hir_id); - if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node); - if let Some(init) = parent_let_expr.init; - then { - match init.kind { - // immutable bindings that are initialized with literal - ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt), - // immutable bindings that are initialized with constant - ExprKind::Path(ref path) => { - if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) { - emit_lint(cx, vec, pushed_item, ctxt); - } - } - _ => {}, + .map_or(false, |id| implements_trait(cx, ty, id, &[])) + { + // Make sure that the push does not involve possibly mutating values + match pushed_item.kind { + ExprKind::Path(ref qpath) => { + match cx.qpath_res(qpath, pushed_item.hir_id) { + // immutable bindings that are initialized with literal or constant + Res::Local(hir_id) => { + let node = cx.tcx.hir().get(hir_id); + if let Node::Pat(pat) = node + && let PatKind::Binding(bind_ann, ..) = pat.kind + && !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut)) + && let parent_node = cx.tcx.hir().parent_id(hir_id) + && let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node) + && let Some(init) = parent_let_expr.init + { + match init.kind { + // immutable bindings that are initialized with literal + ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt), + // immutable bindings that are initialized with constant + ExprKind::Path(ref path) => { + if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) { + emit_lint(cx, vec, pushed_item, ctxt); } - } + }, + _ => {}, } - }, - // constant - Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item, ctxt), - _ => {}, - } - }, - ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt), - _ => {}, - } + } + }, + // constant + Res::Def(DefKind::Const, ..) => emit_lint(cx, vec, pushed_item, ctxt), + _ => {}, + } + }, + ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item, ctxt), + _ => {}, } } } @@ -118,16 +113,14 @@ impl<'a, 'tcx> SameItemPushVisitor<'a, 'tcx> { } fn should_lint(&self) -> bool { - if_chain! { - if !self.non_deterministic_expr; - if !self.multiple_pushes; - if let Some((vec, _, _)) = self.vec_push; - if let Some(hir_id) = path_to_local(vec); - then { - !self.used_locals.contains(&hir_id) - } else { - false - } + if !self.non_deterministic_expr + && !self.multiple_pushes + && let Some((vec, _, _)) = self.vec_push + && let Some(hir_id) = path_to_local(vec) + { + !self.used_locals.contains(&hir_id) + } else { + false } } } @@ -180,18 +173,16 @@ fn get_vec_push<'tcx>( cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>, ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, SyntaxContext)> { - if_chain! { + if let StmtKind::Semi(semi_stmt) = &stmt.kind // Extract method being called - if let StmtKind::Semi(semi_stmt) = &stmt.kind; - if let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind; + && let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind // Figure out the parameters for the method call - if let Some(pushed_item) = args.first(); + && let Some(pushed_item) = args.first() // Check that the method being called is push() on a Vec - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec); - if path.ident.name.as_str() == "push"; - then { - return Some((self_expr, pushed_item, semi_stmt.span.ctxt())) - } + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec) + && path.ident.name.as_str() == "push" + { + return Some((self_expr, pushed_item, semi_stmt.span.ctxt())); } None } diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs index dfb800ccf714d..4773a1454b7a0 100644 --- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs @@ -1,8 +1,7 @@ use super::SINGLE_ELEMENT_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{indent_of, snippet_with_applicability}; +use clippy_utils::source::{indent_of, snippet, snippet_with_applicability}; use clippy_utils::visitors::contains_break_or_continue; -use if_chain::if_chain; use rustc_ast::util::parser::PREC_PREFIX; use rustc_ast::Mutability; use rustc_errors::Applicability; @@ -66,27 +65,42 @@ pub(super) fn check<'tcx>( ExprKind::Array([arg]) if cx.tcx.sess.edition() >= Edition::Edition2021 => (arg, ""), _ => return, }; - if_chain! { - if let ExprKind::Block(block, _) = body.kind; - if !block.stmts.is_empty(); - if !contains_break_or_continue(body); - then { - let mut applicability = Applicability::MachineApplicable; - let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability); - let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability); - let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned(); - block_str.remove(0); - block_str.pop(); - let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0)); + if let ExprKind::Block(block, _) = body.kind + && !block.stmts.is_empty() + && !contains_break_or_continue(body) + { + let mut applicability = Applicability::MachineApplicable; + let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability); + let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability); + let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned(); + block_str.remove(0); + block_str.pop(); + let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0)); - // Reference iterator from `&(mut) []` or `[].iter(_mut)()`. - if !prefix.is_empty() && ( + // Reference iterator from `&(mut) []` or `[].iter(_mut)()`. + if !prefix.is_empty() + && ( // Precedence of internal expression is less than or equal to precedence of `&expr`. arg_expression.precedence().order() <= PREC_PREFIX || is_range_literal(arg_expression) - ) { - arg_snip = format!("({arg_snip})").into(); - } + ) + { + arg_snip = format!("({arg_snip})").into(); + } + if clippy_utils::higher::Range::hir(arg_expression).is_some() { + let range_expr = snippet(cx, arg_expression.span, "?").to_string(); + + let sugg = snippet(cx, arg_expression.span, ".."); + span_lint_and_sugg( + cx, + SINGLE_ELEMENT_LOOP, + arg.span, + format!("this loops only once with `{pat_snip}` being `{range_expr}`").as_str(), + "did you mean to iterate over the range instead?", + sugg.to_string(), + Applicability::Unspecified, + ); + } else { span_lint_and_sugg( cx, SINGLE_ELEMENT_LOOP, @@ -95,7 +109,7 @@ pub(super) fn check<'tcx>( "try", format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"), applicability, - ) + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs index 62a2ab1ccb4c7..dd7fae79d9ba8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs @@ -9,7 +9,7 @@ use rustc_middle::ty; /// Checks for the `UNUSED_ENUMERATE_INDEX` lint. pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { - let PatKind::Tuple(tuple, _) = pat.kind else { + let PatKind::Tuple([index, elem], _) = pat.kind else { return; }; @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx let ty = cx.typeck_results().expr_ty(arg); - if !pat_is_wild(cx, &tuple[0].kind, body) { + if !pat_is_wild(cx, &index.kind, body) { return; } @@ -53,7 +53,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx diag, "remove the `.enumerate()` call", vec![ - (pat.span, snippet(cx, tuple[1].span, "..").into_owned()), + (pat.span, snippet(cx, elem.span, "..").into_owned()), (arg.span, base_iter.to_string()), ], ); diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index 0a2bd89eb3cd3..38fdca573c6b8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -1,6 +1,5 @@ use clippy_utils::ty::{has_iter_method, implements_trait}; use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg}; -use if_chain::if_chain; use rustc_ast::ast::{LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, Visitor}; @@ -145,20 +144,18 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> { fn visit_local(&mut self, l: &'tcx Local<'_>) { // Look for declarations of the variable - if_chain! { - if l.pat.hir_id == self.var_id; - if let PatKind::Binding(.., ident, _) = l.pat.kind; - then { - let ty = l.ty.map(|_| self.cx.typeck_results().pat_ty(l.pat)); + if l.pat.hir_id == self.var_id + && let PatKind::Binding(.., ident, _) = l.pat.kind + { + let ty = l.ty.map(|_| self.cx.typeck_results().pat_ty(l.pat)); - self.state = l.init.map_or(InitializeVisitorState::Declared(ident.name, ty), |init| { - InitializeVisitorState::Initialized { - initializer: init, - ty, - name: ident.name, - } - }) - } + self.state = l.init.map_or(InitializeVisitorState::Declared(ident.name, ty), |init| { + InitializeVisitorState::Initialized { + initializer: init, + ty, + name: ident.name, + } + }); } walk_local(self, l); diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs index 7f24f3c5dc281..9fd9b7a163121 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs @@ -2,7 +2,6 @@ use super::WHILE_IMMUTABLE_CONDITION; use clippy_utils::consts::constant; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::usage::mutated_variables; -use if_chain::if_chain; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefIdMap; use rustc_hir::intravisit::{walk_expr, Visitor}; @@ -95,20 +94,18 @@ struct VarCollectorVisitor<'a, 'tcx> { impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { fn insert_def_id(&mut self, ex: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Path(ref qpath) = ex.kind; - if let QPath::Resolved(None, _) = *qpath; - then { - match self.cx.qpath_res(qpath, ex.hir_id) { - Res::Local(hir_id) => { - self.ids.insert(hir_id); - }, - Res::Def(DefKind::Static(_), def_id) => { - let mutable = self.cx.tcx.is_mutable_static(def_id); - self.def_ids.insert(def_id, mutable); - }, - _ => {}, - } + if let ExprKind::Path(ref qpath) = ex.kind + && let QPath::Resolved(None, _) = *qpath + { + match self.cx.qpath_res(qpath, ex.hir_id) { + Res::Local(hir_id) => { + self.ids.insert(hir_id); + }, + Res::Def(DefKind::Static(_), def_id) => { + let mutable = self.cx.tcx.is_mutable_static(def_id); + self.def_ids.insert(def_id, mutable); + }, + _ => {}, } } } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs index 5153070cfe66b..21b9efba54c7f 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::visitors::is_res_used; use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable, is_res_lang_ctor, is_trait_method}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, Visitor}; @@ -15,59 +14,53 @@ use rustc_span::symbol::sym; use rustc_span::Symbol; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - let (scrutinee_expr, iter_expr_struct, iter_expr, some_pat, loop_expr) = if_chain! { - if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr); + if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr) // check for `Some(..)` pattern - if let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind; - if is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome); + && let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind + && is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome) // check for call to `Iterator::next` - if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind; - if method_name.ident.name == sym::next; - if is_trait_method(cx, let_expr, sym::Iterator); - if let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr); + && let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind + && method_name.ident.name == sym::next + && is_trait_method(cx, let_expr, sym::Iterator) + && let Some(iter_expr_struct) = try_parse_iter_expr(cx, iter_expr) // get the loop containing the match expression - if !uses_iter(cx, &iter_expr_struct, if_then); - then { - (let_expr, iter_expr_struct, iter_expr, some_pat, expr) + && !uses_iter(cx, &iter_expr_struct, if_then) + { + let mut applicability = Applicability::MachineApplicable; + let loop_var = if let Some(some_pat) = some_pat.first() { + if is_refutable(cx, some_pat) { + // Refutable patterns don't work with for loops. + return; + } + snippet_with_applicability(cx, some_pat.span, "..", &mut applicability) } else { - return; - } - }; - - let mut applicability = Applicability::MachineApplicable; - let loop_var = if let Some(some_pat) = some_pat.first() { - if is_refutable(cx, some_pat) { - // Refutable patterns don't work with for loops. - return; - } - snippet_with_applicability(cx, some_pat.span, "..", &mut applicability) - } else { - "_".into() - }; + "_".into() + }; - // If the iterator is a field or the iterator is accessed after the loop is complete it needs to be - // borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used - // afterwards a mutable borrow of a field isn't necessary. - let by_ref = if cx.typeck_results().expr_ty(iter_expr).ref_mutability() == Some(Mutability::Mut) - || !iter_expr_struct.can_move - || !iter_expr_struct.fields.is_empty() - || needs_mutable_borrow(cx, &iter_expr_struct, loop_expr) - { - ".by_ref()" - } else { - "" - }; + // If the iterator is a field or the iterator is accessed after the loop is complete it needs to be + // borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used + // afterwards a mutable borrow of a field isn't necessary. + let by_ref = if cx.typeck_results().expr_ty(iter_expr).ref_mutability() == Some(Mutability::Mut) + || !iter_expr_struct.can_move + || !iter_expr_struct.fields.is_empty() + || needs_mutable_borrow(cx, &iter_expr_struct, expr) + { + ".by_ref()" + } else { + "" + }; - let iterator = snippet_with_applicability(cx, iter_expr.span, "_", &mut applicability); - span_lint_and_sugg( - cx, - WHILE_LET_ON_ITERATOR, - expr.span.with_hi(scrutinee_expr.span.hi()), - "this loop could be written as a `for` loop", - "try", - format!("for {loop_var} in {iterator}{by_ref}"), - applicability, - ); + let iterator = snippet_with_applicability(cx, iter_expr.span, "_", &mut applicability); + span_lint_and_sugg( + cx, + WHILE_LET_ON_ITERATOR, + expr.span.with_hi(let_expr.span.hi()), + "this loop could be written as a `for` loop", + "try", + format!("for {loop_var} in {iterator}{by_ref}"), + applicability, + ); + } } #[derive(Debug)] diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 9b158f18f62c4..8d3e7520a5496 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -1,15 +1,15 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; use hir::def::{DefKind, Res}; -use if_chain::if_chain; use rustc_ast::ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::edition::Edition; use rustc_span::{sym, Span}; +use std::collections::BTreeMap; declare_clippy_lint! { /// ### What it does @@ -89,30 +89,26 @@ impl MacroUseImports { impl<'tcx> LateLintPass<'tcx> for MacroUseImports { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if_chain! { - if cx.sess().opts.edition >= Edition::Edition2018; - if let hir::ItemKind::Use(path, _kind) = &item.kind; - let hir_id = item.hir_id(); - let attrs = cx.tcx.hir().attrs(hir_id); - if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use)); - if let Some(id) = path.res.iter().find_map(|res| match res { + if cx.sess().opts.edition >= Edition::Edition2018 + && let hir::ItemKind::Use(path, _kind) = &item.kind + && let hir_id = item.hir_id() + && let attrs = cx.tcx.hir().attrs(hir_id) + && let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use)) + && let Some(id) = path.res.iter().find_map(|res| match res { Res::Def(DefKind::Mod, id) => Some(id), _ => None, - }); - if !id.is_local(); - then { - for kid in cx.tcx.module_children(id) { - if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { - let span = mac_attr.span; - let def_path = cx.tcx.def_path_str(mac_id); - self.imports.push((def_path, span, hir_id)); - } - } - } else { - if item.span.from_expansion() { - self.push_unique_macro_pat_ty(cx, item.span); + }) + && !id.is_local() + { + for kid in cx.tcx.module_children(id) { + if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { + let span = mac_attr.span; + let def_path = cx.tcx.def_path_str(mac_id); + self.imports.push((def_path, span, hir_id)); } } + } else if item.span.from_expansion() { + self.push_unique_macro_pat_ty(cx, item.span); } } fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { @@ -141,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { } } fn check_crate_post(&mut self, cx: &LateContext<'_>) { - let mut used = FxHashMap::default(); + let mut used = BTreeMap::new(); let mut check_dup = vec![]; for (import, span, hir_id) in &self.imports { let found_idx = self.mac_refs.iter().position(|mac| import.ends_with(&mac.name)); @@ -190,20 +186,16 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { } } - let mut suggestions = vec![]; - for ((root, span, hir_id), path) in used { - if path.len() == 1 { - suggestions.push((span, format!("{root}::{}", path[0]), hir_id)); - } else { - suggestions.push((span, format!("{root}::{{{}}}", path.join(", ")), hir_id)); - } - } - // If mac_refs is not empty we have encountered an import we could not handle // such as `std::prelude::v1::foo` or some other macro that expands to an import. if self.mac_refs.is_empty() { - for (span, import, hir_id) in suggestions { - let help = format!("use {import};"); + for ((root, span, hir_id), path) in used { + let import = if let [single] = &path[..] { + format!("{root}::{single}") + } else { + format!("{root}::{{{}}}", path.join(", ")) + }; + span_lint_hir_and_then( cx, MACRO_USE_IMPORTS, @@ -214,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { diag.span_suggestion( *span, "remove the attribute and import the macro directly, try", - help, + format!("use {import};"), Applicability::MaybeIncorrect, ); }, diff --git a/src/tools/clippy/clippy_lints/src/main_recursion.rs b/src/tools/clippy/clippy_lints/src/main_recursion.rs index 20333c150e3d5..a381b35cf2e27 100644 --- a/src/tools/clippy/clippy_lints/src/main_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/main_recursion.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::snippet; use clippy_utils::{is_entrypoint_fn, is_no_std_crate}; -use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does @@ -43,21 +42,19 @@ impl LateLintPass<'_> for MainRecursion { return; } - if_chain! { - if let ExprKind::Call(func, _) = &expr.kind; - if let ExprKind::Path(QPath::Resolved(_, path)) = &func.kind; - if let Some(def_id) = path.res.opt_def_id(); - if is_entrypoint_fn(cx, def_id); - then { - span_lint_and_help( - cx, - MAIN_RECURSION, - func.span, - &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")), - None, - "consider using another function for this recursion" - ) - } + if let ExprKind::Call(func, _) = &expr.kind + && let ExprKind::Path(QPath::Resolved(_, path)) = &func.kind + && let Some(def_id) = path.res.opt_def_id() + && is_entrypoint_fn(cx, def_id) + { + span_lint_and_help( + cx, + MAIN_RECURSION, + func.span, + &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")), + None, + "consider using another function for this recursion", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs index 9a3da975f83c5..4f6a2cf017ca0 100644 --- a/src/tools/clippy/clippy_lints/src/manual_assert.rs +++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs @@ -5,7 +5,7 @@ use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 998de38a9952a..ee053ffe4ecad 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -8,7 +7,7 @@ use rustc_hir::{ ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -47,61 +46,57 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { span: Span, def_id: LocalDefId, ) { - if_chain! { - if let Some(header) = kind.header(); - if !header.asyncness.is_async(); + if let Some(header) = kind.header() + && !header.asyncness.is_async() // Check that this function returns `impl Future` - if let FnRetTy::Return(ret_ty) = decl.output; - if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty); - if let Some(output) = future_output_ty(trait_ref); - if captures_all_lifetimes(decl.inputs, &output_lifetimes); + && let FnRetTy::Return(ret_ty) = decl.output + && let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty) + && let Some(output) = future_output_ty(trait_ref) + && captures_all_lifetimes(decl.inputs, &output_lifetimes) // Check that the body of the function consists of one async block - if let ExprKind::Block(block, _) = body.value.kind; - if block.stmts.is_empty(); - if let Some(closure_body) = desugared_async_block(cx, block); - if let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) = - cx.tcx.hir().get_by_def_id(def_id); - then { - let header_span = span.with_hi(ret_ty.span.hi()); - - span_lint_and_then( - cx, - MANUAL_ASYNC_FN, - header_span, - "this function can be simplified using the `async fn` syntax", - |diag| { - if_chain! { - if let Some(vis_snip) = snippet_opt(cx, *vis_span); - if let Some(header_snip) = snippet_opt(cx, header_span); - if let Some(ret_pos) = position_before_rarrow(&header_snip); - if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output); - then { - let header_snip = if vis_snip.is_empty() { - format!("async {}", &header_snip[..ret_pos]) - } else { - format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos]) - }; - - let help = format!("make the function `async` and {ret_sugg}"); - diag.span_suggestion( - header_span, - help, - format!("{header_snip}{ret_snip}"), - Applicability::MachineApplicable - ); - - let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span)); - diag.span_suggestion( - block.span, - "move the body of the async block to the enclosing function", - body_snip, - Applicability::MachineApplicable - ); - } - } - }, - ); - } + && let ExprKind::Block(block, _) = body.value.kind + && block.stmts.is_empty() + && let Some(closure_body) = desugared_async_block(cx, block) + && let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) = + cx.tcx.hir().get_by_def_id(def_id) + { + let header_span = span.with_hi(ret_ty.span.hi()); + + span_lint_and_then( + cx, + MANUAL_ASYNC_FN, + header_span, + "this function can be simplified using the `async fn` syntax", + |diag| { + if let Some(vis_snip) = snippet_opt(cx, *vis_span) + && let Some(header_snip) = snippet_opt(cx, header_span) + && let Some(ret_pos) = position_before_rarrow(&header_snip) + && let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output) + { + let header_snip = if vis_snip.is_empty() { + format!("async {}", &header_snip[..ret_pos]) + } else { + format!("{} async {}", vis_snip, &header_snip[vis_snip.len() + 1..ret_pos]) + }; + + let help = format!("make the function `async` and {ret_sugg}"); + diag.span_suggestion( + header_span, + help, + format!("{header_snip}{ret_snip}"), + Applicability::MachineApplicable, + ); + + let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span)); + diag.span_suggestion( + block.span, + "move the body of the async block to the enclosing function", + body_snip, + Applicability::MachineApplicable, + ); + } + }, + ); } } } @@ -110,48 +105,44 @@ fn future_trait_ref<'tcx>( cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>, ) -> Option<(&'tcx TraitRef<'tcx>, Vec)> { - if_chain! { - if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind; - let item = cx.tcx.hir().item(item_id); - if let ItemKind::OpaqueTy(opaque) = &item.kind; - if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { + if let TyKind::OpaqueDef(item_id, bounds, false) = ty.kind + && let item = cx.tcx.hir().item(item_id) + && let ItemKind::OpaqueTy(opaque) = &item.kind + && let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { if let GenericBound::Trait(poly, _) = bound { Some(&poly.trait_ref) } else { None } - }); - if trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait(); - then { - let output_lifetimes = bounds - .iter() - .filter_map(|bound| { - if let GenericArg::Lifetime(lt) = bound { - Some(lt.res) - } else { - None - } - }) - .collect(); - - return Some((trait_ref, output_lifetimes)); - } + }) + && trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait() + { + let output_lifetimes = bounds + .iter() + .filter_map(|bound| { + if let GenericArg::Lifetime(lt) = bound { + Some(lt.res) + } else { + None + } + }) + .collect(); + + return Some((trait_ref, output_lifetimes)); } None } fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> { - if_chain! { - if let Some(segment) = trait_ref.path.segments.last(); - if let Some(args) = segment.args; - if args.bindings.len() == 1; - let binding = &args.bindings[0]; - if binding.ident.name == sym::Output; - if let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind; - then { - return Some(output); - } + if let Some(segment) = trait_ref.path.segments.last() + && let Some(args) = segment.args + && args.bindings.len() == 1 + && let binding = &args.bindings[0] + && binding.ident.name == sym::Output + && let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind + { + return Some(output); } None @@ -181,31 +172,26 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) } fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { - if_chain! { - if let Some(block_expr) = block.expr; - if let Expr { + if let Some(block_expr) = block.expr + && let Expr { kind: ExprKind::Closure(&Closure { body, .. }), .. - } = block_expr; - let closure_body = cx.tcx.hir().body(body); - if closure_body.coroutine_kind == Some(CoroutineKind::Async(CoroutineSource::Block)); - then { - return Some(closure_body); - } + } = block_expr + && let closure_body = cx.tcx.hir().body(body) + && closure_body.coroutine_kind == Some(CoroutineKind::Async(CoroutineSource::Block)) + { + return Some(closure_body); } None } fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str, String)> { - match output.kind { - TyKind::Tup(tys) if tys.is_empty() => { - let sugg = "remove the return type"; - Some((sugg, String::new())) - }, - _ => { - let sugg = "return the output of the future directly"; - snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}"))) - }, + if let TyKind::Tup([]) = output.kind { + let sugg = "remove the return type"; + Some((sugg, String::new())) + } else { + let sugg = "return the output of the future directly"; + snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}"))) } } diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs index cd614c8951c1b..96c652283daa5 100644 --- a/src/tools/clippy/clippy_lints/src/manual_bits.rs +++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs @@ -8,7 +8,7 @@ use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -53,32 +53,30 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { return; } - if_chain! { - if let ExprKind::Binary(bin_op, left_expr, right_expr) = expr.kind; - if let BinOpKind::Mul = &bin_op.node; - if !in_external_macro(cx.sess(), expr.span); - let ctxt = expr.span.ctxt(); - if left_expr.span.ctxt() == ctxt; - if right_expr.span.ctxt() == ctxt; - if let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr); - if matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_)); - if let ExprKind::Lit(lit) = &other_expr.kind; - if let LitKind::Int(8, _) = lit.node; - then { - let mut app = Applicability::MachineApplicable; - let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0; - let sugg = create_sugg(cx, expr, format!("{ty_snip}::BITS")); - - span_lint_and_sugg( - cx, - MANUAL_BITS, - expr.span, - "usage of `mem::size_of::()` to obtain the size of `T` in bits", - "consider using", - sugg, - app, - ); - } + if let ExprKind::Binary(bin_op, left_expr, right_expr) = expr.kind + && let BinOpKind::Mul = &bin_op.node + && !in_external_macro(cx.sess(), expr.span) + && let ctxt = expr.span.ctxt() + && left_expr.span.ctxt() == ctxt + && right_expr.span.ctxt() == ctxt + && let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr) + && matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_)) + && let ExprKind::Lit(lit) = &other_expr.kind + && let LitKind::Int(8, _) = lit.node + { + let mut app = Applicability::MachineApplicable; + let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0; + let sugg = create_sugg(cx, expr, format!("{ty_snip}::BITS")); + + span_lint_and_sugg( + cx, + MANUAL_BITS, + expr.span, + "usage of `mem::size_of::()` to obtain the size of `T` in bits", + "consider using", + sugg, + app, + ); } } @@ -98,22 +96,22 @@ fn get_one_size_of_ty<'tcx>( } fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(&'tcx rustc_hir::Ty<'tcx>, Ty<'tcx>)> { - if_chain! { - if let ExprKind::Call(count_func, _func_args) = expr.kind; - if let ExprKind::Path(ref count_func_qpath) = count_func.kind; - - if let QPath::Resolved(_, count_func_path) = count_func_qpath; - if let Some(segment_zero) = count_func_path.segments.first(); - if let Some(args) = segment_zero.args; - if let Some(GenericArg::Type(real_ty)) = args.args.first(); - - if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id); - then { - cx.typeck_results().node_args(count_func.hir_id).types().next().map(|resolved_ty| (*real_ty, resolved_ty)) - } else { - None - } + if let ExprKind::Call(count_func, _func_args) = expr.kind + && let ExprKind::Path(ref count_func_qpath) = count_func.kind + && let QPath::Resolved(_, count_func_path) = count_func_qpath + && let Some(segment_zero) = count_func_path.segments.first() + && let Some(args) = segment_zero.args + && let Some(GenericArg::Type(real_ty)) = args.args.first() + && let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id) + { + cx.typeck_results() + .node_args(count_func.hir_id) + .types() + .next() + .map(|resolved_ty| (*real_ty, resolved_ty)) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs index 09c90e38e1186..385fe387a314f 100644 --- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs +++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs @@ -14,7 +14,7 @@ use rustc_hir::def::Res; use rustc_hir::{Arm, BinOpKind, Block, Expr, ExprKind, Guard, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_span::Span; use std::ops::Deref; diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index 0c4101ceb6bb3..31cfb41640dd9 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Constness, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs index 472b4eb900665..252b3a83a18f0 100644 --- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs +++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs @@ -6,7 +6,7 @@ use clippy_utils::{is_trait_method, path_to_local_id}; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, ExprKind, Local, Node, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs index 468f4170732d2..e433c5a3b32b6 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs @@ -8,7 +8,7 @@ use rustc_ast::LitKind::{Byte, Char}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, PatKind, RangeEnd}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::DefId; use rustc_span::{sym, Span}; diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 170a040d4ae88..92dc4d57ab146 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -5,18 +5,15 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::visitors::{Descend, Visitable}; -use clippy_utils::{is_lint_allowed, pat_and_expr_can_be_question_mark, peel_blocks}; +use clippy_utils::{is_lint_allowed, is_never_expr, pat_and_expr_can_be_question_mark, peel_blocks}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; -use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty}; +use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::declare_tool_lint; + use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; -use std::ops::ControlFlow; use std::slice; declare_clippy_lint! { @@ -51,7 +48,7 @@ declare_clippy_lint! { } impl<'tcx> QuestionMark { - pub(crate) fn check_manual_let_else(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) { + pub(crate) fn check_manual_let_else(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) { if !self.msrv.meets(msrvs::LET_ELSE) || in_external_macro(cx.sess(), stmt.span) { return; } @@ -67,7 +64,7 @@ impl<'tcx> QuestionMark { IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => { if let Some(ident_map) = expr_simple_identity_map(local.pat, let_pat, if_then) && let Some(if_else) = if_else - && expr_diverges(cx, if_else) + && is_never_expr(cx, if_else).is_some() && let qm_allowed = is_lint_allowed(cx, QUESTION_MARK, stmt.hir_id) && (qm_allowed || pat_and_expr_can_be_question_mark(cx, let_pat, if_else).is_none()) { @@ -91,10 +88,9 @@ impl<'tcx> QuestionMark { return; } let check_types = self.matches_behaviour == MatchLintBehaviour::WellKnownTypes; - let diverging_arm_opt = arms - .iter() - .enumerate() - .find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types)); + let diverging_arm_opt = arms.iter().enumerate().find(|(_, arm)| { + is_never_expr(cx, arm.body).is_some() && pat_allowed_for_else(cx, arm.pat, check_types) + }); let Some((idx, diverging_arm)) = diverging_arm_opt else { return; }; @@ -272,104 +268,6 @@ fn replace_in_pattern( sn_pat.into_owned() } -/// Check whether an expression is divergent. May give false negatives. -fn expr_diverges(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - struct V<'cx, 'tcx> { - cx: &'cx LateContext<'tcx>, - res: ControlFlow<(), Descend>, - } - impl<'tcx> Visitor<'tcx> for V<'_, '_> { - fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) { - fn is_never(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool { - if let Some(ty) = cx.typeck_results().expr_ty_opt(expr) { - return ty.is_never(); - } - false - } - - if self.res.is_break() { - return; - } - - // We can't just call is_never on expr and be done, because the type system - // sometimes coerces the ! type to something different before we can get - // our hands on it. So instead, we do a manual search. We do fall back to - // is_never in some places when there is no better alternative. - self.res = match e.kind { - ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => ControlFlow::Break(()), - ExprKind::Call(call, _) => { - if is_never(self.cx, e) || is_never(self.cx, call) { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(Descend::Yes) - } - }, - ExprKind::MethodCall(..) => { - if is_never(self.cx, e) { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(Descend::Yes) - } - }, - ExprKind::If(if_expr, if_then, if_else) => { - let else_diverges = if_else.map_or(false, |ex| expr_diverges(self.cx, ex)); - let diverges = - expr_diverges(self.cx, if_expr) || (else_diverges && expr_diverges(self.cx, if_then)); - if diverges { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(Descend::No) - } - }, - ExprKind::Match(match_expr, match_arms, _) => { - let diverges = expr_diverges(self.cx, match_expr) - || match_arms.iter().all(|arm| { - let guard_diverges = arm.guard.as_ref().map_or(false, |g| expr_diverges(self.cx, g.body())); - guard_diverges || expr_diverges(self.cx, arm.body) - }); - if diverges { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(Descend::No) - } - }, - - // Don't continue into loops or labeled blocks, as they are breakable, - // and we'd have to start checking labels. - ExprKind::Block(_, Some(_)) | ExprKind::Loop(..) => ControlFlow::Continue(Descend::No), - - // Default: descend - _ => ControlFlow::Continue(Descend::Yes), - }; - if let ControlFlow::Continue(Descend::Yes) = self.res { - walk_expr(self, e); - } - } - - fn visit_local(&mut self, local: &'tcx Local<'_>) { - // Don't visit the else block of a let/else statement as it will not make - // the statement divergent even though the else block is divergent. - if let Some(init) = local.init { - self.visit_expr(init); - } - } - - // Avoid unnecessary `walk_*` calls. - fn visit_ty(&mut self, _: &'tcx Ty<'tcx>) {} - fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {} - fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {} - // Avoid monomorphising all `visit_*` functions. - fn visit_nested_item(&mut self, _: ItemId) {} - } - - let mut v = V { - cx, - res: ControlFlow::Continue(Descend::Yes), - }; - expr.visit(&mut v); - v.res.is_break() -} - fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: bool) -> bool { // Check whether the pattern contains any bindings, as the // binding might potentially be used in the body. diff --git a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs index 23f47c86fcce3..5732bdda7f2cf 100644 --- a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs +++ b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs @@ -6,7 +6,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, Mutability, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index fc8f23630013a..545b122930e5f 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -9,7 +9,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::{self as hir, Expr, ExprKind, QPath}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{sym, Span}; @@ -118,7 +118,6 @@ impl EarlyLintPass for ManualNonExhaustiveStruct { if let Some(Ok(field)) = iter.next() && iter.next().is_none() && field.ty.kind.is_unit() - && field.ident.map_or(true, |name| name.as_str().starts_with('_')) { span_lint_and_then( cx, @@ -158,7 +157,6 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { { let mut iter = def.variants.iter().filter_map(|v| { (matches!(v.data, hir::VariantData::Unit(_, _)) - && v.ident.as_str().starts_with('_') && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)) && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)) .then_some((v.def_id, v.span)) @@ -173,9 +171,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Path(QPath::Resolved(None, p)) = &e.kind - && let [.., name] = p.segments && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res - && name.ident.as_str().starts_with('_') { let variant_id = cx.tcx.parent(id); let enum_id = cx.tcx.parent(variant_id); @@ -192,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { .contains(&(enum_id.to_def_id(), variant_id.to_def_id())) }) { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(enum_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(enum_id); span_lint_hir_and_then( cx, MANUAL_NON_EXHAUSTIVE, diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs index d24bfe1822448..d585290f7773c 100644 --- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{Span, DUMMY_SP}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs index bc8372fbd4185..e006df7d66664 100644 --- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, Node, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs index 2f8682d041816..1fe247dacb932 100644 --- a/src/tools/clippy/clippy_lints/src/manual_retain.rs +++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs @@ -9,7 +9,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::ExprKind::Assign; use rustc_lint::{LateContext, LateLintPass}; use rustc_semver::RustcVersion; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; const ACCEPTABLE_METHODS: [&[&str]; 5] = [ diff --git a/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs b/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs index 3b97d165998e7..1de686dbcb51e 100644 --- a/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs +++ b/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs @@ -5,7 +5,7 @@ use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/manual_string_new.rs b/src/tools/clippy/clippy_lints/src/manual_string_new.rs index f8afae0e1f518..737c70496c2bd 100644 --- a/src/tools/clippy/clippy_lints/src/manual_string_new.rs +++ b/src/tools/clippy/clippy_lints/src/manual_string_new.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability::MachineApplicable; use rustc_hir::{Expr, ExprKind, PathSegment, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, symbol, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index 9a9e6af508499..7b04fd28b896f 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -4,14 +4,13 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::source::snippet; use clippy_utils::usage::mutated_variables; use clippy_utils::{eq_expr_value, higher, match_def_path, paths}; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::Span; @@ -71,55 +70,61 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { return; } - if_chain! { - if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr); - if let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind; - if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id); - if let ExprKind::Path(target_path) = &target_arg.kind; - then { - let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) { - StripKind::Prefix - } else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) { - StripKind::Suffix - } else { - return; - }; - let target_res = cx.qpath_res(target_path, target_arg.hir_id); - if target_res == Res::Err { - return; - }; - - if_chain! { - if let Res::Local(hir_id) = target_res; - if let Some(used_mutably) = mutated_variables(then, cx); - if used_mutably.contains(&hir_id); - then { - return; - } - } - - let strippings = find_stripping(cx, strip_kind, target_res, pattern, then); - if !strippings.is_empty() { + if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr) + && let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind + && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id) + && let ExprKind::Path(target_path) = &target_arg.kind + { + let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) { + StripKind::Prefix + } else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) { + StripKind::Suffix + } else { + return; + }; + let target_res = cx.qpath_res(target_path, target_arg.hir_id); + if target_res == Res::Err { + return; + }; + + if let Res::Local(hir_id) = target_res + && let Some(used_mutably) = mutated_variables(then, cx) + && used_mutably.contains(&hir_id) + { + return; + } - let kind_word = match strip_kind { - StripKind::Prefix => "prefix", - StripKind::Suffix => "suffix", - }; + let strippings = find_stripping(cx, strip_kind, target_res, pattern, then); + if !strippings.is_empty() { + let kind_word = match strip_kind { + StripKind::Prefix => "prefix", + StripKind::Suffix => "suffix", + }; - let test_span = expr.span.until(then.span); - span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| { + let test_span = expr.span.until(then.span); + span_lint_and_then( + cx, + MANUAL_STRIP, + strippings[0], + &format!("stripping a {kind_word} manually"), + |diag| { diag.span_note(test_span, format!("the {kind_word} was tested here")); multispan_sugg( diag, &format!("try using the `strip_{kind_word}` method"), - vec![(test_span, - format!("if let Some() = {}.strip_{kind_word}({}) ", - snippet(cx, target_arg.span, ".."), - snippet(cx, pattern.span, "..")))] - .into_iter().chain(strippings.into_iter().map(|span| (span, "".into()))), + vec![( + test_span, + format!( + "if let Some() = {}.strip_{kind_word}({}) ", + snippet(cx, target_arg.span, ".."), + snippet(cx, pattern.span, "..") + ), + )] + .into_iter() + .chain(strippings.into_iter().map(|span| (span, "".into()))), ); - }); - } + }, + ); } } } @@ -129,15 +134,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { // Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise. fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if_chain! { - if let ExprKind::MethodCall(_, arg, [], _) = expr.kind; - if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if match_def_path(cx, method_def_id, &paths::STR_LEN); - then { - Some(arg) - } else { - None - } + if let ExprKind::MethodCall(_, arg, [], _) = expr.kind + && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && match_def_path(cx, method_def_id, &paths::STR_LEN) + { + Some(arg) + } else { + None } } @@ -201,36 +204,38 @@ fn find_stripping<'tcx>( impl<'a, 'tcx> Visitor<'tcx> for StrippingFinder<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { - if_chain! { - if is_ref_str(self.cx, ex); - let unref = peel_ref(ex); - if let ExprKind::Index(indexed, index, _) = &unref.kind; - if let Some(higher::Range { start, end, .. }) = higher::Range::hir(index); - if let ExprKind::Path(path) = &indexed.kind; - if self.cx.qpath_res(path, ex.hir_id) == self.target; - then { - match (self.strip_kind, start, end) { - (StripKind::Prefix, Some(start), None) => { - if eq_pattern_length(self.cx, self.pattern, start) { - self.results.push(ex.span); - return; - } - }, - (StripKind::Suffix, None, Some(end)) => { - if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, left, right) = end.kind; - if let Some(left_arg) = len_arg(self.cx, left); - if let ExprKind::Path(left_path) = &left_arg.kind; - if self.cx.qpath_res(left_path, left_arg.hir_id) == self.target; - if eq_pattern_length(self.cx, self.pattern, right); - then { - self.results.push(ex.span); - return; - } - } - }, - _ => {} - } + if is_ref_str(self.cx, ex) + && let unref = peel_ref(ex) + && let ExprKind::Index(indexed, index, _) = &unref.kind + && let Some(higher::Range { start, end, .. }) = higher::Range::hir(index) + && let ExprKind::Path(path) = &indexed.kind + && self.cx.qpath_res(path, ex.hir_id) == self.target + { + match (self.strip_kind, start, end) { + (StripKind::Prefix, Some(start), None) => { + if eq_pattern_length(self.cx, self.pattern, start) { + self.results.push(ex.span); + return; + } + }, + (StripKind::Suffix, None, Some(end)) => { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Sub, .. + }, + left, + right, + ) = end.kind + && let Some(left_arg) = len_arg(self.cx, left) + && let ExprKind::Path(left_path) = &left_arg.kind + && self.cx.qpath_res(left_path, left_arg.hir_id) == self.target + && eq_pattern_length(self.cx, self.pattern, right) + { + self.results.push(ex.span); + return; + } + }, + _ => {}, } } diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index 817d072b9b3d0..3b82c50a84e62 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -2,12 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{iter_input_pats, method_chain_args}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -163,16 +162,14 @@ fn unit_closure<'tcx>( cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, ) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> { - if_chain! { - if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = expr.kind; - let body = cx.tcx.hir().body(body); - let body_expr = &body.value; - if fn_decl.inputs.len() == 1; - if is_unit_expression(cx, body_expr); - if let Some(binding) = iter_input_pats(fn_decl, body).next(); - then { - return Some((binding, body_expr)); - } + if let hir::ExprKind::Closure(&hir::Closure { fn_decl, body, .. }) = expr.kind + && let body = cx.tcx.hir().body(body) + && let body_expr = &body.value + && fn_decl.inputs.len() == 1 + && is_unit_expression(cx, body_expr) + && let Some(binding) = iter_input_pats(fn_decl, body).next() + { + return Some((binding, body_expr)); } None } diff --git a/src/tools/clippy/clippy_lints/src/match_result_ok.rs b/src/tools/clippy/clippy_lints/src/match_result_ok.rs index 841c020f2d3de..62cedc8847b24 100644 --- a/src/tools/clippy/clippy_lints/src/match_result_ok.rs +++ b/src/tools/clippy/clippy_lints/src/match_result_ok.rs @@ -2,11 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{higher, is_res_lang_ctor}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -56,33 +55,31 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk { return; }; - if_chain! { - if let ExprKind::MethodCall(ok_path, recv, [], ..) = let_expr.kind; //check is expr.ok() has type Result.ok(, _) - if let PatKind::TupleStruct(ref pat_path, [ok_pat], _) = let_pat.kind; //get operation - if ok_path.ident.as_str() == "ok"; - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); - if is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome); - let ctxt = expr.span.ctxt(); - if let_expr.span.ctxt() == ctxt; - if let_pat.span.ctxt() == ctxt; - then { - let mut applicability = Applicability::MachineApplicable; - let some_expr_string = snippet_with_context(cx, ok_pat.span, ctxt, "", &mut applicability).0; - let trimmed_ok = snippet_with_context(cx, recv.span, ctxt, "", &mut applicability).0; - let sugg = format!( - "{ifwhile} let Ok({some_expr_string}) = {}", - trimmed_ok.trim().trim_end_matches('.'), - ); - span_lint_and_sugg( - cx, - MATCH_RESULT_OK, - expr.span.with_hi(let_expr.span.hi()), - "matching on `Some` with `ok()` is redundant", - &format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"), - sugg, - applicability, - ); - } + if let ExprKind::MethodCall(ok_path, recv, [], ..) = let_expr.kind //check is expr.ok() has type Result.ok(, _) + && let PatKind::TupleStruct(ref pat_path, [ok_pat], _) = let_pat.kind //get operation + && ok_path.ident.as_str() == "ok" + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result) + && is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome) + && let ctxt = expr.span.ctxt() + && let_expr.span.ctxt() == ctxt + && let_pat.span.ctxt() == ctxt + { + let mut applicability = Applicability::MachineApplicable; + let some_expr_string = snippet_with_context(cx, ok_pat.span, ctxt, "", &mut applicability).0; + let trimmed_ok = snippet_with_context(cx, recv.span, ctxt, "", &mut applicability).0; + let sugg = format!( + "{ifwhile} let Ok({some_expr_string}) = {}", + trimmed_ok.trim().trim_end_matches('.'), + ); + span_lint_and_sugg( + cx, + MATCH_RESULT_OK, + expr.span.with_hi(let_expr.span.hi()), + "matching on `Some` with `ok()` is redundant", + &format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"), + sugg, + applicability, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 29b935fb61a8a..48fc5746b3cd0 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -5,7 +5,6 @@ use clippy_utils::visitors::is_local_used; use clippy_utils::{ is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq, }; -use if_chain::if_chain; use rustc_errors::MultiSpan; use rustc_hir::LangItem::OptionNone; use rustc_hir::{Arm, Expr, Guard, HirId, Let, Pat, PatKind}; @@ -40,76 +39,73 @@ fn check_arm<'tcx>( outer_else_body: Option<&'tcx Expr<'tcx>>, ) { let inner_expr = peel_blocks_with_stmt(outer_then_body); - if_chain! { - if let Some(inner) = IfLetOrMatch::parse(cx, inner_expr); - if let Some((inner_scrutinee, inner_then_pat, inner_else_body)) = match inner { + if let Some(inner) = IfLetOrMatch::parse(cx, inner_expr) + && let Some((inner_scrutinee, inner_then_pat, inner_else_body)) = match inner { IfLetOrMatch::IfLet(scrutinee, pat, _, els) => Some((scrutinee, pat, els)), - IfLetOrMatch::Match(scrutinee, arms, ..) => if_chain! { + IfLetOrMatch::Match(scrutinee, arms, ..) => if arms.len() == 2 && arms.iter().all(|a| a.guard.is_none()) // if there are more than two arms, collapsing would be non-trivial - if arms.len() == 2 && arms.iter().all(|a| a.guard.is_none()); // one of the arms must be "wild-like" - if let Some(wild_idx) = arms.iter().rposition(|a| arm_is_wild_like(cx, a)); - then { - let (then, els) = (&arms[1 - wild_idx], &arms[wild_idx]); - Some((scrutinee, then.pat, Some(els.body))) - } else { - None - } + && let Some(wild_idx) = arms.iter().rposition(|a| arm_is_wild_like(cx, a)) + { + let (then, els) = (&arms[1 - wild_idx], &arms[wild_idx]); + Some((scrutinee, then.pat, Some(els.body))) + } else { + None }, - }; - if outer_pat.span.eq_ctxt(inner_scrutinee.span); + } + && outer_pat.span.eq_ctxt(inner_scrutinee.span) // match expression must be a local binding // match { .. } - if let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee)); - if !pat_contains_or(inner_then_pat); + && let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee)) + && !pat_contains_or(inner_then_pat) // the binding must come from the pattern of the containing match arm // .... => match { .. } - if let (Some(binding_span), is_innermost_parent_pat_struct) - = find_pat_binding_and_is_innermost_parent_pat_struct(outer_pat, binding_id); + && let (Some(binding_span), is_innermost_parent_pat_struct) + = find_pat_binding_and_is_innermost_parent_pat_struct(outer_pat, binding_id) // the "else" branches must be equal - if match (outer_else_body, inner_else_body) { + && match (outer_else_body, inner_else_body) { (None, None) => true, (None, Some(e)) | (Some(e), None) => is_unit_expr(e), (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b), - }; + } // the binding must not be used in the if guard - if outer_guard.map_or( + && outer_guard.map_or( true, |(Guard::If(e) | Guard::IfLet(Let { init: e, .. }))| !is_local_used(cx, *e, binding_id) - ); + ) // ...or anywhere in the inner expression - if match inner { + && match inner { IfLetOrMatch::IfLet(_, _, body, els) => { !is_local_used(cx, body, binding_id) && els.map_or(true, |e| !is_local_used(cx, e, binding_id)) }, IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| is_local_used(cx, arm, binding_id)), - }; - then { - let msg = format!( - "this `{}` can be collapsed into the outer `{}`", - if matches!(inner, IfLetOrMatch::Match(..)) { "match" } else { "if let" }, - if outer_is_match { "match" } else { "if let" }, - ); - // collapsing patterns need an explicit field name in struct pattern matching - // ex: Struct {x: Some(1)} - let replace_msg = if is_innermost_parent_pat_struct { - format!(", prefixed by {}:", snippet(cx, binding_span, "their field name")) + } + { + let msg = format!( + "this `{}` can be collapsed into the outer `{}`", + if matches!(inner, IfLetOrMatch::Match(..)) { + "match" } else { - String::new() - }; - span_lint_and_then( - cx, - COLLAPSIBLE_MATCH, - inner_expr.span, - &msg, - |diag| { - let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]); - help_span.push_span_label(binding_span, "replace this binding"); - help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}")); - diag.span_help(help_span, "the outer pattern can be modified to include the inner pattern"); - }, + "if let" + }, + if outer_is_match { "match" } else { "if let" }, + ); + // collapsing patterns need an explicit field name in struct pattern matching + // ex: Struct {x: Some(1)} + let replace_msg = if is_innermost_parent_pat_struct { + format!(", prefixed by {}:", snippet(cx, binding_span, "their field name")) + } else { + String::new() + }; + span_lint_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.span, &msg, |diag| { + let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]); + help_span.push_span_label(binding_span, "replace this binding"); + help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}")); + diag.span_help( + help_span, + "the outer pattern can be modified to include the inner pattern", ); - } + }); } } diff --git a/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs b/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs index 3329f93b73c4a..c8a48246e6766 100644 --- a/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs @@ -8,38 +8,35 @@ use rustc_lint::LateContext; use super::INFALLIBLE_DESTRUCTURING_MATCH; pub(crate) fn check(cx: &LateContext<'_>, local: &Local<'_>) -> bool { - if_chain! { - if !local.span.from_expansion(); - if let Some(expr) = local.init; - if let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind; - if arms.len() == 1 && arms[0].guard.is_none(); - if let PatKind::TupleStruct( - QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind; - if args.len() == 1; - if let PatKind::Binding(binding, arg, ..) = strip_pat_refs(&args[0]).kind; - let body = peel_blocks(arms[0].body); - if path_to_local_id(body, arg); - - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - INFALLIBLE_DESTRUCTURING_MATCH, - local.span, - "you seem to be trying to use `match` to destructure a single infallible pattern. \ - Consider using `let`", - "try", - format!( - "let {}({}{}) = {};", - snippet_with_applicability(cx, variant_name.span, "..", &mut applicability), - if binding.0 == ByRef::Yes { "ref " } else { "" }, - snippet_with_applicability(cx, local.pat.span, "..", &mut applicability), - snippet_with_applicability(cx, target.span, "..", &mut applicability), - ), - applicability, - ); - return true; - } + if !local.span.from_expansion() + && let Some(expr) = local.init + && let ExprKind::Match(target, arms, MatchSource::Normal) = expr.kind + && arms.len() == 1 + && arms[0].guard.is_none() + && let PatKind::TupleStruct(QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind + && args.len() == 1 + && let PatKind::Binding(binding, arg, ..) = strip_pat_refs(&args[0]).kind + && let body = peel_blocks(arms[0].body) + && path_to_local_id(body, arg) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + INFALLIBLE_DESTRUCTURING_MATCH, + local.span, + "you seem to be trying to use `match` to destructure a single infallible pattern. \ + Consider using `let`", + "try", + format!( + "let {}({}{}) = {};", + snippet_with_applicability(cx, variant_name.span, "..", &mut applicability), + if binding.0 == ByRef::Yes { "ref " } else { "" }, + snippet_with_applicability(cx, local.pat.span, "..", &mut applicability), + snippet_with_applicability(cx, target.span, "..", &mut applicability), + ), + applicability, + ); + return true; } false } diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs index cdb51c33aaf10..619ec83127aba 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs @@ -21,19 +21,19 @@ fn get_cond_expr<'tcx>( expr: &'tcx Expr<'_>, ctxt: SyntaxContext, ) -> Option> { - if_chain! { - if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr); - if let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind; - if let PatKind::Binding(_,target, ..) = pat.kind; - if is_some_expr(cx, target, ctxt, then_expr) && is_none_expr(cx, else_expr) - || is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr); // check that one expr resolves to `Some(x)`, the other to `None` - then { - return Some(SomeExpr { - expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()), - needs_unsafe_block: contains_unsafe_block(cx, expr), - needs_negated: is_none_expr(cx, then_expr) // if the `then_expr` resolves to `None`, need to negate the cond - }) - } + if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr) + && let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind + && let PatKind::Binding(_, target, ..) = pat.kind + && (is_some_expr(cx, target, ctxt, then_expr) && is_none_expr(cx, else_expr) + || is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr)) + // check that one expr resolves to `Some(x)`, the other to `None` + { + return Some(SomeExpr { + expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()), + needs_unsafe_block: contains_unsafe_block(cx, expr), + needs_negated: is_none_expr(cx, then_expr), /* if the `then_expr` resolves to `None`, need to negate the + * cond */ + }); }; None } diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs index b94501bf0ad38..3e79cabd795f5 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs @@ -4,7 +4,6 @@ use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::contains_return_break_continue_macro; use clippy_utils::{is_res_lang_ctor, path_to_local_id, sugg}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::LangItem::{OptionNone, ResultErr}; @@ -16,65 +15,57 @@ use super::MANUAL_UNWRAP_OR; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) { let ty = cx.typeck_results().expr_ty(scrutinee); - if_chain! { - if let Some(ty_name) = if is_type_diagnostic_item(cx, ty, sym::Option) { - Some("Option") - } else if is_type_diagnostic_item(cx, ty, sym::Result) { - Some("Result") - } else { - None - }; - if let Some(or_arm) = applicable_or_arm(cx, arms); - if let Some(or_body_snippet) = snippet_opt(cx, or_arm.body.span); - if let Some(indent) = indent_of(cx, expr.span); - if constant_simple(cx, cx.typeck_results(), or_arm.body).is_some(); - then { - let reindented_or_body = - reindent_multiline(or_body_snippet.into(), true, Some(indent)); + if let Some(ty_name) = if is_type_diagnostic_item(cx, ty, sym::Option) { + Some("Option") + } else if is_type_diagnostic_item(cx, ty, sym::Result) { + Some("Result") + } else { + None + } && let Some(or_arm) = applicable_or_arm(cx, arms) + && let Some(or_body_snippet) = snippet_opt(cx, or_arm.body.span) + && let Some(indent) = indent_of(cx, expr.span) + && constant_simple(cx, cx.typeck_results(), or_arm.body).is_some() + { + let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent)); - let mut app = Applicability::MachineApplicable; - let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_par(); - span_lint_and_sugg( - cx, - MANUAL_UNWRAP_OR, expr.span, - &format!("this pattern reimplements `{ty_name}::unwrap_or`"), - "replace with", - format!( - "{suggestion}.unwrap_or({reindented_or_body})", - ), - app, - ); - } + let mut app = Applicability::MachineApplicable; + let suggestion = sugg::Sugg::hir_with_context(cx, scrutinee, expr.span.ctxt(), "..", &mut app).maybe_par(); + span_lint_and_sugg( + cx, + MANUAL_UNWRAP_OR, + expr.span, + &format!("this pattern reimplements `{ty_name}::unwrap_or`"), + "replace with", + format!("{suggestion}.unwrap_or({reindented_or_body})",), + app, + ); } } fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<&'a Arm<'a>> { - if_chain! { - if arms.len() == 2; - if arms.iter().all(|arm| arm.guard.is_none()); - if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| { - match arm.pat.kind { - PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone), - PatKind::TupleStruct(ref qpath, [pat], _) => - matches!(pat.kind, PatKind::Wild) - && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr), - _ => false, - } - }); - let unwrap_arm = &arms[1 - idx]; - if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind; - if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, unwrap_arm.pat.hir_id); - if let Some(variant_id) = cx.tcx.opt_parent(ctor_id); - if cx.tcx.lang_items().option_some_variant() == Some(variant_id) - || cx.tcx.lang_items().result_ok_variant() == Some(variant_id); - if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind; - if path_to_local_id(unwrap_arm.body, binding_hir_id); - if cx.typeck_results().expr_adjustments(unwrap_arm.body).is_empty(); - if !contains_return_break_continue_macro(or_arm.body); - then { - Some(or_arm) - } else { - None - } + if arms.len() == 2 + && arms.iter().all(|arm| arm.guard.is_none()) + && let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| match arm.pat.kind { + PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone), + PatKind::TupleStruct(ref qpath, [pat], _) => { + matches!(pat.kind, PatKind::Wild) + && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr) + }, + _ => false, + }) + && let unwrap_arm = &arms[1 - idx] + && let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind + && let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, unwrap_arm.pat.hir_id) + && let Some(variant_id) = cx.tcx.opt_parent(ctor_id) + && (cx.tcx.lang_items().option_some_variant() == Some(variant_id) + || cx.tcx.lang_items().result_ok_variant() == Some(variant_id)) + && let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind + && path_to_local_id(unwrap_arm.body, binding_hir_id) + && cx.typeck_results().expr_adjustments(unwrap_arm.body).is_empty() + && !contains_return_break_continue_macro(or_arm.body) + { + Some(or_arm) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 781ee138c76f7..0627e458dfe0f 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -127,32 +127,30 @@ where let closure_expr_snip = some_expr.to_snippet_with_context(cx, expr_ctxt, &mut app); let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind { - if_chain! { - if !some_expr.needs_unsafe_block; - if let Some(func) = can_pass_as_func(cx, id, some_expr.expr); - if func.span.eq_ctxt(some_expr.expr.span); - then { - snippet_with_applicability(cx, func.span, "..", &mut app).into_owned() - } else { - if path_to_local_id(some_expr.expr, id) - && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id) - && binding_ref.is_some() - { - return None; - } + if !some_expr.needs_unsafe_block + && let Some(func) = can_pass_as_func(cx, id, some_expr.expr) + && func.span.eq_ctxt(some_expr.expr.span) + { + snippet_with_applicability(cx, func.span, "..", &mut app).into_owned() + } else { + if path_to_local_id(some_expr.expr, id) + && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id) + && binding_ref.is_some() + { + return None; + } - // `ref` and `ref mut` annotations were handled earlier. - let annotation = if matches!(annotation, BindingAnnotation::MUT) { - "mut " - } else { - "" - }; + // `ref` and `ref mut` annotations were handled earlier. + let annotation = if matches!(annotation, BindingAnnotation::MUT) { + "mut " + } else { + "" + }; - if some_expr.needs_unsafe_block { - format!("|{annotation}{some_binding}| unsafe {{ {closure_expr_snip} }}") - } else { - format!("|{annotation}{some_binding}| {closure_expr_snip}") - } + if some_expr.needs_unsafe_block { + format!("|{annotation}{some_binding}| unsafe {{ {closure_expr_snip} }}") + } else { + format!("|{annotation}{some_binding}| {closure_expr_snip}") } } } else if !is_wild_none && explicit_ref.is_none() { diff --git a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs index d51cca040a265..3f737da92c055 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs @@ -26,18 +26,16 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: let output_ty = cx.typeck_results().expr_ty(expr); let input_ty = cx.typeck_results().expr_ty(ex); - let cast = if_chain! { - if let ty::Adt(_, args) = input_ty.kind(); - let input_ty = args.type_at(0); - if let ty::Adt(_, args) = output_ty.kind(); - let output_ty = args.type_at(0); - if let ty::Ref(_, output_ty, _) = *output_ty.kind(); - if input_ty != output_ty; - then { - ".map(|x| x as _)" - } else { - "" - } + let cast = if let ty::Adt(_, args) = input_ty.kind() + && let input_ty = args.type_at(0) + && let ty::Adt(_, args) = output_ty.kind() + && let output_ty = args.type_at(0) + && let ty::Ref(_, output_ty, _) = *output_ty.kind() + && input_ty != output_ty + { + ".map(|x| x as _)" + } else { + "" }; let mut applicability = Applicability::MachineApplicable; @@ -67,17 +65,16 @@ fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`) fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option { - if_chain! { - if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind; - if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome); - if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind; - if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind; - if is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome); - if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind; - if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name; - then { - return Some(mutabl) - } + if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind + && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome) + && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind + && let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind + && is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome) + && let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind + && path2.segments.len() == 1 + && ident.name == path2.segments[0].ident.name + { + return Some(mutabl); } None } diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs index e2ddf11abe2ca..56123326fe4a7 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs @@ -76,79 +76,80 @@ where ), >, { - if_chain! { - if !span_contains_comment(cx.sess().source_map(), expr.span); - if iter.len() >= 2; - if cx.typeck_results().expr_ty(expr).is_bool(); - if let Some((_, last_pat_opt, last_expr, _)) = iter.next_back(); - let iter_without_last = iter.clone(); - if let Some((first_attrs, _, first_expr, first_guard)) = iter.next(); - if let Some(b0) = find_bool_lit(&first_expr.kind); - if let Some(b1) = find_bool_lit(&last_expr.kind); - if b0 != b1; - if first_guard.is_none() || iter.len() == 0; - if first_attrs.is_empty(); - if iter - .all(|arm| { - find_bool_lit(&arm.2.kind).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty() - }); - then { - if let Some(last_pat) = last_pat_opt { - if !is_wild(last_pat) { - return false; - } + if !span_contains_comment(cx.sess().source_map(), expr.span) + && iter.len() >= 2 + && cx.typeck_results().expr_ty(expr).is_bool() + && let Some((_, last_pat_opt, last_expr, _)) = iter.next_back() + && let iter_without_last = iter.clone() + && let Some((first_attrs, _, first_expr, first_guard)) = iter.next() + && let Some(b0) = find_bool_lit(&first_expr.kind) + && let Some(b1) = find_bool_lit(&last_expr.kind) + && b0 != b1 + && (first_guard.is_none() || iter.len() == 0) + && first_attrs.is_empty() + && iter.all(|arm| find_bool_lit(&arm.2.kind).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty()) + { + if let Some(last_pat) = last_pat_opt { + if !is_wild(last_pat) { + return false; } + } - for arm in iter_without_last.clone() { - if let Some(pat) = arm.1 { - if !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) && is_some(pat.kind) { - return false; - } + for arm in iter_without_last.clone() { + if let Some(pat) = arm.1 { + if !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) && is_some(pat.kind) { + return false; } } + } - // The suggestion may be incorrect, because some arms can have `cfg` attributes - // evaluated into `false` and so such arms will be stripped before. - let mut applicability = Applicability::MaybeIncorrect; - let pat = { - use itertools::Itertools as _; - iter_without_last - .filter_map(|arm| { - let pat_span = arm.1?.span; - Some(snippet_with_applicability(cx, pat_span, "..", &mut applicability)) - }) - .join(" | ") - }; - let pat_and_guard = if let Some(Guard::If(g)) = first_guard { - format!("{pat} if {}", snippet_with_applicability(cx, g.span, "..", &mut applicability)) - } else { - pat - }; - - // strip potential borrows (#6503), but only if the type is a reference - let mut ex_new = ex; - if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind { - if let ty::Ref(..) = cx.typeck_results().expr_ty(ex_inner).kind() { - ex_new = ex_inner; - } - }; - span_lint_and_sugg( - cx, - MATCH_LIKE_MATCHES_MACRO, - expr.span, - &format!("{} expression looks like `matches!` macro", if is_if_let { "if let .. else" } else { "match" }), - "try", - format!( - "{}matches!({}, {pat_and_guard})", - if b0 { "" } else { "!" }, - snippet_with_applicability(cx, ex_new.span, "..", &mut applicability), - ), - applicability, - ); - true + // The suggestion may be incorrect, because some arms can have `cfg` attributes + // evaluated into `false` and so such arms will be stripped before. + let mut applicability = Applicability::MaybeIncorrect; + let pat = { + use itertools::Itertools as _; + iter_without_last + .filter_map(|arm| { + let pat_span = arm.1?.span; + Some(snippet_with_applicability(cx, pat_span, "..", &mut applicability)) + }) + .join(" | ") + }; + let pat_and_guard = if let Some(Guard::If(g)) = first_guard { + format!( + "{pat} if {}", + snippet_with_applicability(cx, g.span, "..", &mut applicability) + ) } else { - false - } + pat + }; + + // strip potential borrows (#6503), but only if the type is a reference + let mut ex_new = ex; + if let ExprKind::AddrOf(BorrowKind::Ref, .., ex_inner) = ex.kind { + if let ty::Ref(..) = cx.typeck_results().expr_ty(ex_inner).kind() { + ex_new = ex_inner; + } + }; + span_lint_and_sugg( + cx, + MATCH_LIKE_MATCHES_MACRO, + expr.span, + &format!( + "{} expression looks like `matches!` macro", + if is_if_let { "if let .. else" } else { "match" } + ), + "try", + format!( + "{}matches!({}, {pat_and_guard})", + if b0 { "" } else { "!" }, + snippet_with_applicability(cx, ex_new.span, "..", &mut applicability), + ), + applicability, + ); + true + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs b/src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs index bd53ebd48c887..dd71560e169ea 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_on_vec_items.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::LateContext; @@ -10,39 +9,29 @@ use rustc_span::sym; use super::MATCH_ON_VEC_ITEMS; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>) { - if_chain! { - if let Some(idx_expr) = is_vec_indexing(cx, scrutinee); - if let ExprKind::Index(vec, idx, _) = idx_expr.kind; - - then { - // FIXME: could be improved to suggest surrounding every pattern with Some(_), - // but only when `or_patterns` are stabilized. - span_lint_and_sugg( - cx, - MATCH_ON_VEC_ITEMS, - scrutinee.span, - "indexing into a vector may panic", - "try", - format!( - "{}.get({})", - snippet(cx, vec.span, ".."), - snippet(cx, idx.span, "..") - ), - Applicability::MaybeIncorrect - ); - } + if let Some(idx_expr) = is_vec_indexing(cx, scrutinee) + && let ExprKind::Index(vec, idx, _) = idx_expr.kind + { + // FIXME: could be improved to suggest surrounding every pattern with Some(_), + // but only when `or_patterns` are stabilized. + span_lint_and_sugg( + cx, + MATCH_ON_VEC_ITEMS, + scrutinee.span, + "indexing into a vector may panic", + "try", + format!("{}.get({})", snippet(cx, vec.span, ".."), snippet(cx, idx.span, "..")), + Applicability::MaybeIncorrect, + ); } } fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { - if_chain! { - if let ExprKind::Index(array, index, _) = expr.kind; - if is_vector(cx, array); - if !is_full_range(cx, index); - - then { - return Some(expr); - } + if let ExprKind::Index(array, index, _) = expr.kind + && is_vector(cx, array) + && !is_full_range(cx, index) + { + return Some(expr); } None diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 6fc79faddbee3..c823d07e2bd3d 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash}; use core::cmp::Ordering; @@ -66,25 +66,23 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { let mut local_map: HirIdMap = HirIdMap::default(); let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| { - if_chain! { - if let Some(a_id) = path_to_local(a); - if let Some(b_id) = path_to_local(b); - let entry = match local_map.entry(a_id) { + if let Some(a_id) = path_to_local(a) + && let Some(b_id) = path_to_local(b) + && let entry = match local_map.entry(a_id) { HirIdMapEntry::Vacant(entry) => entry, // check if using the same bindings as before HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id, - }; - // the names technically don't have to match; this makes the lint more conservative - if cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id); - if cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b); - if pat_contains_local(lhs.pat, a_id); - if pat_contains_local(rhs.pat, b_id); - then { - entry.insert(b_id); - true - } else { - false } + // the names technically don't have to match; this makes the lint more conservative + && cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id) + && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b) + && pat_contains_local(lhs.pat, a_id) + && pat_contains_local(rhs.pat, b_id) + { + entry.insert(b_id); + true + } else { + false } }; // Arms with a guard are ignored, those can’t always be merged together @@ -106,9 +104,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { if !cx.tcx.features().non_exhaustive_omitted_patterns_lint || is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id) { - span_lint_and_then( + span_lint_hir_and_then( cx, MATCH_SAME_ARMS, + arm1.hir_id, arm1.span, "this match arm has an identical body to the `_` wildcard arm", |diag| { @@ -126,9 +125,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { (arm2, arm1) }; - span_lint_and_then( + span_lint_hir_and_then( cx, MATCH_SAME_ARMS, + keep_arm.hir_id, keep_arm.span, "this match arm has an identical body to another arm", |diag| { @@ -152,6 +152,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { #[derive(Clone, Copy)] enum NormalizedPat<'a> { Wild, + Never, Struct(Option, &'a [(Symbol, Self)]), Tuple(Option, &'a [Self]), Or(&'a [Self]), @@ -223,7 +224,7 @@ fn iter_matching_struct_fields<'a>( Iter(left.iter(), right.iter()) } -#[expect(clippy::similar_names)] +#[expect(clippy::similar_names, clippy::too_many_lines)] impl<'a> NormalizedPat<'a> { fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self { match pat.kind { @@ -231,6 +232,7 @@ impl<'a> NormalizedPat<'a> { PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) | PatKind::Ref(pat, _) => { Self::from_pat(cx, arena, pat) }, + PatKind::Never => Self::Never, PatKind::Struct(ref path, fields, _) => { let fields = arena.alloc_from_iter(fields.iter().map(|f| (f.ident.name, Self::from_pat(cx, arena, f.pat)))); @@ -334,7 +336,7 @@ impl<'a> NormalizedPat<'a> { /// type. fn has_overlapping_values(&self, other: &Self) -> bool { match (*self, *other) { - (Self::Wild, _) | (_, Self::Wild) => true, + (Self::Wild, _) | (_, Self::Wild) | (Self::Never, Self::Never) => true, (Self::Or(pats), ref other) | (ref other, Self::Or(pats)) => { pats.iter().any(|pat| pat.has_overlapping_values(other)) }, diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs index 675a85ae5553a..bd38648bcf1b6 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -20,21 +20,16 @@ enum CaseMethod { } pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) { - if_chain! { - if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(scrutinee).kind(); - if let ty::Str = ty.kind(); - then { - let mut visitor = MatchExprVisitor { - cx, - case_method: None, - }; - - visitor.visit_expr(scrutinee); - - if let Some(case_method) = visitor.case_method { - if let Some((bad_case_span, bad_case_sym)) = verify_case(&case_method, arms) { - lint(cx, &case_method, bad_case_span, bad_case_sym.as_str()); - } + if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(scrutinee).kind() + && let ty::Str = ty.kind() + { + let mut visitor = MatchExprVisitor { cx, case_method: None }; + + visitor.visit_expr(scrutinee); + + if let Some(case_method) = visitor.case_method { + if let Some((bad_case_span, bad_case_sym)) = verify_case(&case_method, arms) { + lint(cx, &case_method, bad_case_span, bad_case_sym.as_str()); } } } @@ -88,17 +83,15 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<( }; for arm in arms { - if_chain! { - if let PatKind::Lit(Expr { - kind: ExprKind::Lit(lit), - .. - }) = arm.pat.kind; - if let LitKind::Str(symbol, _) = lit.node; - let input = symbol.as_str(); - if !case_check(input); - then { - return Some((lit.span, symbol)); - } + if let PatKind::Lit(Expr { + kind: ExprKind::Lit(lit), + .. + }) = arm.pat.kind + && let LitKind::Str(symbol, _) = lit.node + && let input = symbol.as_str() + && !case_check(input) + { + return Some((lit.span, symbol)); } } diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs index a2903e52ae08d..8a4c0ab906275 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs @@ -34,20 +34,19 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<' } } } - if_chain! { - if matching_wild; - if let Some(macro_call) = root_macro_call(peel_blocks_with_stmt(arm.body).span); - if is_panic(cx, macro_call.def_id); - then { - // `Err(_)` or `Err(_e)` arm with `panic!` found - span_lint_and_note(cx, - MATCH_WILD_ERR_ARM, - arm.pat.span, - &format!("`Err({ident_bind_name})` matches all errors"), - None, - "match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable", - ); - } + if matching_wild + && let Some(macro_call) = root_macro_call(peel_blocks_with_stmt(arm.body).span) + && is_panic(cx, macro_call.def_id) + { + // `Err(_)` or `Err(_e)` arm with `panic!` found + span_lint_and_note( + cx, + MATCH_WILD_ERR_ARM, + arm.pat.span, + &format!("`Err({ident_bind_name})` matches all errors"), + None, + "match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index dea46d4d36073..4c7568f39b45d 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -31,7 +31,7 @@ use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat}; use rustc_lexer::TokenKind; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{Span, SpanData, SyntaxContext}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index 8f0083f812cc2..8199366d175fb 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -150,7 +150,7 @@ where #[test] fn test_overlapping() { - use rustc_span::source_map::DUMMY_SP; + use rustc_span::DUMMY_SP; let sp = |s, e| SpannedRange { span: DUMMY_SP, diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs index 4a44d596a46d4..f57b22374c8e8 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::path_to_local; -use clippy_utils::source::snippet_with_applicability; +use clippy_utils::source::snippet; use clippy_utils::visitors::{for_each_expr, is_local_used}; use rustc_ast::{BorrowKind, LitKind}; use rustc_errors::Applicability; @@ -8,7 +8,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, Guard, MatchSource, Node, Pat, PatKind}; use rustc_lint::LateContext; use rustc_span::symbol::Ident; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; +use std::borrow::Cow; use std::ops::ControlFlow; use super::REDUNDANT_GUARDS; @@ -41,7 +42,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) { (PatKind::Ref(..), None) | (_, Some(_)) => continue, _ => arm.pat.span, }; - emit_redundant_guards(cx, outer_arm, if_expr.span, pat_span, &binding, arm.guard); + emit_redundant_guards( + cx, + outer_arm, + if_expr.span, + snippet(cx, pat_span, ""), + &binding, + arm.guard, + ); } // `Some(x) if let Some(2) = x` else if let Guard::IfLet(let_expr) = guard @@ -52,7 +60,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) { (PatKind::Ref(..), None) | (_, Some(_)) => continue, _ => let_expr.pat.span, }; - emit_redundant_guards(cx, outer_arm, let_expr.span, pat_span, &binding, None); + emit_redundant_guards( + cx, + outer_arm, + let_expr.span, + snippet(cx, pat_span, ""), + &binding, + None, + ); } // `Some(x) if x == Some(2)` // `Some(x) if Some(2) == x` @@ -78,11 +93,76 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) { (ExprKind::AddrOf(..), None) | (_, Some(_)) => continue, _ => pat.span, }; - emit_redundant_guards(cx, outer_arm, if_expr.span, pat_span, &binding, None); + emit_redundant_guards( + cx, + outer_arm, + if_expr.span, + snippet(cx, pat_span, ""), + &binding, + None, + ); + } else if let Guard::If(if_expr) = guard + && let ExprKind::MethodCall(path, recv, args, ..) = if_expr.kind + && let Some(binding) = get_pat_binding(cx, recv, outer_arm) + { + check_method_calls(cx, outer_arm, path.ident.name, recv, args, if_expr, &binding); } } } +fn check_method_calls<'tcx>( + cx: &LateContext<'tcx>, + arm: &Arm<'tcx>, + method: Symbol, + recv: &Expr<'_>, + args: &[Expr<'_>], + if_expr: &Expr<'_>, + binding: &PatBindingInfo, +) { + let ty = cx.typeck_results().expr_ty(recv).peel_refs(); + let slice_like = ty.is_slice() || ty.is_array(); + + let sugg = if method == sym!(is_empty) { + // `s if s.is_empty()` becomes "" + // `arr if arr.is_empty()` becomes [] + + if ty.is_str() { + r#""""#.into() + } else if slice_like { + "[]".into() + } else { + return; + } + } else if slice_like + && let Some(needle) = args.first() + && let ExprKind::AddrOf(.., needle) = needle.kind + && let ExprKind::Array(needles) = needle.kind + && needles.iter().all(|needle| expr_can_be_pat(cx, needle)) + { + // `arr if arr.starts_with(&[123])` becomes [123, ..] + // `arr if arr.ends_with(&[123])` becomes [.., 123] + // `arr if arr.starts_with(&[])` becomes [..] (why would anyone write this?) + + let mut sugg = snippet(cx, needle.span, "").into_owned(); + + if needles.is_empty() { + sugg.insert_str(1, ".."); + } else if method == sym!(starts_with) { + sugg.insert_str(sugg.len() - 1, ", .."); + } else if method == sym!(ends_with) { + sugg.insert_str(1, ".., "); + } else { + return; + } + + sugg.into() + } else { + return; + }; + + emit_redundant_guards(cx, arm, if_expr.span, sugg, binding, None); +} + struct PatBindingInfo { span: Span, byref_ident: Option, @@ -134,19 +214,16 @@ fn emit_redundant_guards<'tcx>( cx: &LateContext<'tcx>, outer_arm: &Arm<'tcx>, guard_span: Span, - pat_span: Span, + binding_replacement: Cow<'static, str>, pat_binding: &PatBindingInfo, inner_guard: Option>, ) { - let mut app = Applicability::MaybeIncorrect; - span_lint_and_then( cx, REDUNDANT_GUARDS, guard_span.source_callsite(), "redundant guard", |diag| { - let binding_replacement = snippet_with_applicability(cx, pat_span, "", &mut app); let suggestion_span = match *pat_binding { PatBindingInfo { span, @@ -170,14 +247,11 @@ fn emit_redundant_guards<'tcx>( Guard::IfLet(l) => ("if let", l.span), }; - format!( - " {prefix} {}", - snippet_with_applicability(cx, span, "", &mut app), - ) + format!(" {prefix} {}", snippet(cx, span, "")) }), ), ], - app, + Applicability::MaybeIncorrect, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index 9a7c00823b670..2582f7edcf66d 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -5,7 +5,6 @@ use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop}; use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr}; use clippy_utils::{higher, is_expn_of, is_trait_method}; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -35,15 +34,13 @@ pub(super) fn check_if_let<'tcx>( // Extract the generic arguments out of a type fn try_get_generic_ty(ty: Ty<'_>, index: usize) -> Option> { - if_chain! { - if let ty::Adt(_, subs) = ty.kind(); - if let Some(sub) = subs.get(index); - if let GenericArgKind::Type(sub_ty) = sub.unpack(); - then { - Some(sub_ty) - } else { - None - } + if let ty::Adt(_, subs) = ty.kind() + && let Some(sub) = subs.get(index) + && let GenericArgKind::Type(sub_ty) = sub.unpack() + { + Some(sub_ty) + } else { + None } } @@ -142,14 +139,12 @@ fn find_sugg_for_if_let<'tcx>( let needs_drop = needs_ordered_drop(cx, check_ty) || any_temporaries_need_ordered_drop(cx, let_expr); // check that `while_let_on_iterator` lint does not trigger - if_chain! { - if keyword == "while"; - if let ExprKind::MethodCall(method_path, ..) = let_expr.kind; - if method_path.ident.name == sym::next; - if is_trait_method(cx, let_expr, sym::Iterator); - then { - return; - } + if keyword == "while" + && let ExprKind::MethodCall(method_path, ..) = let_expr.kind + && method_path.ident.name == sym::next + && is_trait_method(cx, let_expr, sym::Iterator) + { + return; } let result_expr = match &let_expr.kind { diff --git a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs index 4efe93d4b5424..316b2f63e4eaa 100644 --- a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs +++ b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs @@ -6,25 +6,22 @@ use rustc_middle::ty; use super::REST_PAT_IN_FULLY_BOUND_STRUCTS; pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) { - if_chain! { - if !pat.span.from_expansion(); - if let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind; - if let Some(def_id) = path.res.opt_def_id(); - let ty = cx.tcx.type_of(def_id).instantiate_identity(); - if let ty::Adt(def, _) = ty.kind(); - if def.is_struct() || def.is_union(); - if fields.len() == def.non_enum_variant().fields.len(); - if !def.non_enum_variant().is_field_list_non_exhaustive(); - - then { - span_lint_and_help( - cx, - REST_PAT_IN_FULLY_BOUND_STRUCTS, - pat.span, - "unnecessary use of `..` pattern in struct binding. All fields were already bound", - None, - "consider removing `..` from this binding", - ); - } + if !pat.span.from_expansion() + && let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind + && let Some(def_id) = path.res.opt_def_id() + && let ty = cx.tcx.type_of(def_id).instantiate_identity() + && let ty::Adt(def, _) = ty.kind() + && (def.is_struct() || def.is_union()) + && fields.len() == def.non_enum_variant().fields.len() + && !def.non_enum_variant().is_field_list_non_exhaustive() + { + span_lint_and_help( + cx, + REST_PAT_IN_FULLY_BOUND_STRUCTS, + pat.span, + "unnecessary use of `..` pattern in struct binding. All fields were already bound", + None, + "consider removing `..` from this binding", + ); } } diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 48efd02301753..86c414dafccab 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -89,50 +89,52 @@ fn report_single_pattern( }); let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat); - let (msg, sugg) = if_chain! { - if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind; - let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex)); - if let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait(); - if let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait(); - if ty.is_integral() || ty.is_char() || ty.is_str() - || (implements_trait(cx, ty, spe_trait_id, &[]) - && implements_trait(cx, ty, pe_trait_id, &[ty.into()])); - then { - // scrutinee derives PartialEq and the pattern is a constant. - let pat_ref_count = match pat.kind { - // string literals are already a reference. - PatKind::Lit(Expr { kind: ExprKind::Lit(lit), .. }) if lit.node.is_str() => pat_ref_count + 1, - _ => pat_ref_count, - }; - // References are only implicitly added to the pattern, so no overflow here. - // e.g. will work: match &Some(_) { Some(_) => () } - // will not: match Some(_) { &Some(_) => () } - let ref_count_diff = ty_ref_count - pat_ref_count; - - // Try to remove address of expressions first. - let (ex, removed) = peel_n_hir_expr_refs(ex, ref_count_diff); - let ref_count_diff = ref_count_diff - removed; - - let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`"; - let sugg = format!( - "if {} == {}{} {}{els_str}", - snippet(cx, ex.span, ".."), - // PartialEq for different reference counts may not exist. - "&".repeat(ref_count_diff), - snippet(cx, arms[0].pat.span, ".."), - expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app), - ); - (msg, sugg) - } else { - let msg = "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`"; - let sugg = format!( - "if let {} = {} {}{els_str}", - snippet(cx, arms[0].pat.span, ".."), - snippet(cx, ex.span, ".."), - expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app), - ); - (msg, sugg) - } + let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind + && let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex)) + && let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait() + && let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait() + && (ty.is_integral() + || ty.is_char() + || ty.is_str() + || (implements_trait(cx, ty, spe_trait_id, &[]) && implements_trait(cx, ty, pe_trait_id, &[ty.into()]))) + { + // scrutinee derives PartialEq and the pattern is a constant. + let pat_ref_count = match pat.kind { + // string literals are already a reference. + PatKind::Lit(Expr { + kind: ExprKind::Lit(lit), + .. + }) if lit.node.is_str() => pat_ref_count + 1, + _ => pat_ref_count, + }; + // References are only implicitly added to the pattern, so no overflow here. + // e.g. will work: match &Some(_) { Some(_) => () } + // will not: match Some(_) { &Some(_) => () } + let ref_count_diff = ty_ref_count - pat_ref_count; + + // Try to remove address of expressions first. + let (ex, removed) = peel_n_hir_expr_refs(ex, ref_count_diff); + let ref_count_diff = ref_count_diff - removed; + + let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`"; + let sugg = format!( + "if {} == {}{} {}{els_str}", + snippet(cx, ex.span, ".."), + // PartialEq for different reference counts may not exist. + "&".repeat(ref_count_diff), + snippet(cx, arms[0].pat.span, ".."), + expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app), + ); + (msg, sugg) + } else { + let msg = "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`"; + let sugg = format!( + "if let {} = {} {}{els_str}", + snippet(cx, arms[0].pat.span, ".."), + snippet(cx, ex.span, ".."), + expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app), + ); + (msg, sugg) }; span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app); diff --git a/src/tools/clippy/clippy_lints/src/matches/try_err.rs b/src/tools/clippy/clippy_lints/src/matches/try_err.rs index 0fd6f533db0d5..dd489fc250b7b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs +++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::LangItem::ResultErr; use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath}; @@ -22,59 +21,57 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine // #[allow(unreachable_code)] // val, // }; - if_chain! { - if let ExprKind::Call(match_fun, [try_arg, ..]) = scrutinee.kind; - if let ExprKind::Path(ref match_fun_path) = match_fun.kind; - if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..)); - if let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind; - if is_res_lang_ctor(cx, path_res(cx, err_fun), ResultErr); - if let Some(return_ty) = find_return_type(cx, &expr.kind); - then { - let prefix; - let suffix; - let err_ty; + if let ExprKind::Call(match_fun, [try_arg, ..]) = scrutinee.kind + && let ExprKind::Path(ref match_fun_path) = match_fun.kind + && matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..)) + && let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind + && is_res_lang_ctor(cx, path_res(cx, err_fun), ResultErr) + && let Some(return_ty) = find_return_type(cx, &expr.kind) + { + let prefix; + let suffix; + let err_ty; - if let Some(ty) = result_error_type(cx, return_ty) { - prefix = "Err("; - suffix = ")"; - err_ty = ty; - } else if let Some(ty) = poll_result_error_type(cx, return_ty) { - prefix = "Poll::Ready(Err("; - suffix = "))"; - err_ty = ty; - } else if let Some(ty) = poll_option_result_error_type(cx, return_ty) { - prefix = "Poll::Ready(Some(Err("; - suffix = ")))"; - err_ty = ty; - } else { - return; - }; + if let Some(ty) = result_error_type(cx, return_ty) { + prefix = "Err("; + suffix = ")"; + err_ty = ty; + } else if let Some(ty) = poll_result_error_type(cx, return_ty) { + prefix = "Poll::Ready(Err("; + suffix = "))"; + err_ty = ty; + } else if let Some(ty) = poll_option_result_error_type(cx, return_ty) { + prefix = "Poll::Ready(Some(Err("; + suffix = ")))"; + err_ty = ty; + } else { + return; + }; - let expr_err_ty = cx.typeck_results().expr_ty(err_arg); - let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt()); - let mut applicability = Applicability::MachineApplicable; - let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability); - let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) { - "" // already returns - } else { - "return " - }; - let suggestion = if err_ty == expr_err_ty { - format!("{ret_prefix}{prefix}{origin_snippet}{suffix}") - } else { - format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}") - }; + let expr_err_ty = cx.typeck_results().expr_ty(err_arg); + let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt()); + let mut applicability = Applicability::MachineApplicable; + let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability); + let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) { + "" // already returns + } else { + "return " + }; + let suggestion = if err_ty == expr_err_ty { + format!("{ret_prefix}{prefix}{origin_snippet}{suffix}") + } else { + format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}") + }; - span_lint_and_sugg( - cx, - TRY_ERR, - expr.span, - "returning an `Err(_)` with the `?` operator", - "try", - suggestion, - applicability, - ); - } + span_lint_and_sugg( + cx, + TRY_ERR, + expr.span, + "returning an `Err(_)` with the `?` operator", + "try", + suggestion, + applicability, + ); } } @@ -92,51 +89,42 @@ fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> O /// Extracts the error type from Result. fn result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { - if_chain! { - if let ty::Adt(_, subst) = ty.kind(); - if is_type_diagnostic_item(cx, ty, sym::Result); - then { - Some(subst.type_at(1)) - } else { - None - } + if let ty::Adt(_, subst) = ty.kind() + && is_type_diagnostic_item(cx, ty, sym::Result) + { + Some(subst.type_at(1)) + } else { + None } } /// Extracts the error type from Poll>. fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { - if_chain! { - if let ty::Adt(def, subst) = ty.kind(); - if cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did()); - let ready_ty = subst.type_at(0); - - if let ty::Adt(ready_def, ready_subst) = ready_ty.kind(); - if cx.tcx.is_diagnostic_item(sym::Result, ready_def.did()); - then { - Some(ready_subst.type_at(1)) - } else { - None - } + if let ty::Adt(def, subst) = ty.kind() + && cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did()) + && let ready_ty = subst.type_at(0) + && let ty::Adt(ready_def, ready_subst) = ready_ty.kind() + && cx.tcx.is_diagnostic_item(sym::Result, ready_def.did()) + { + Some(ready_subst.type_at(1)) + } else { + None } } /// Extracts the error type from Poll>>. fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { - if_chain! { - if let ty::Adt(def, subst) = ty.kind(); - if cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did()); - let ready_ty = subst.type_at(0); - - if let ty::Adt(ready_def, ready_subst) = ready_ty.kind(); - if cx.tcx.is_diagnostic_item(sym::Option, ready_def.did()); - let some_ty = ready_subst.type_at(0); - - if let ty::Adt(some_def, some_subst) = some_ty.kind(); - if cx.tcx.is_diagnostic_item(sym::Result, some_def.did()); - then { - Some(some_subst.type_at(1)) - } else { - None - } + if let ty::Adt(def, subst) = ty.kind() + && cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did()) + && let ready_ty = subst.type_at(0) + && let ty::Adt(ready_def, ready_subst) = ready_ty.kind() + && cx.tcx.is_diagnostic_item(sym::Option, ready_def.did()) + && let some_ty = ready_subst.type_at(0) + && let ty::Adt(some_def, some_subst) = some_ty.kind() + && cx.tcx.is_diagnostic_item(sym::Result, some_def.did()) + { + Some(some_subst.type_at(1)) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs index 760c8f59cec81..c22f76484d03d 100644 --- a/src/tools/clippy/clippy_lints/src/mem_replace.rs +++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs @@ -4,15 +4,14 @@ use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_non_aggregate_primitive_type; use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::Span; +use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does @@ -125,17 +124,37 @@ fn check_replace_option_with_none(cx: &LateContext<'_>, dest: &Expr<'_>, expr_sp } fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { - if_chain! { + if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(src.hir_id) // check if replacement is mem::MaybeUninit::uninit().assume_init() - if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(src.hir_id); - if cx.tcx.is_diagnostic_item(sym::assume_init, method_def_id); - then { + && cx.tcx.is_diagnostic_item(sym::assume_init, method_def_id) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + MEM_REPLACE_WITH_UNINIT, + expr_span, + "replacing with `mem::MaybeUninit::uninit().assume_init()`", + "consider using", + format!( + "std::ptr::read({})", + snippet_with_applicability(cx, dest.span, "", &mut applicability) + ), + applicability, + ); + return; + } + + if let ExprKind::Call(repl_func, []) = src.kind + && let ExprKind::Path(ref repl_func_qpath) = repl_func.kind + && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id() + { + if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) { let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, MEM_REPLACE_WITH_UNINIT, expr_span, - "replacing with `mem::MaybeUninit::uninit().assume_init()`", + "replacing with `mem::uninitialized()`", "consider using", format!( "std::ptr::read({})", @@ -143,40 +162,17 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' ), applicability, ); - return; - } - } - - if_chain! { - if let ExprKind::Call(repl_func, []) = src.kind; - if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; - if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); - then { - if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - MEM_REPLACE_WITH_UNINIT, - expr_span, - "replacing with `mem::uninitialized()`", - "consider using", - format!( - "std::ptr::read({})", - snippet_with_applicability(cx, dest.span, "", &mut applicability) - ), - applicability, - ); - } else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) && - !cx.typeck_results().expr_ty(src).is_primitive() { - span_lint_and_help( - cx, - MEM_REPLACE_WITH_UNINIT, - expr_span, - "replacing with `mem::zeroed()`", - None, - "consider using a default value or the `take_mut` crate instead", - ); - } + } else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) + && !cx.typeck_results().expr_ty(src).is_primitive() + { + span_lint_and_help( + cx, + MEM_REPLACE_WITH_UNINIT, + expr_span, + "replacing with `mem::zeroed()`", + None, + "consider using a default value or the `take_mut` crate instead", + ); } } } @@ -222,21 +218,19 @@ impl MemReplace { impl<'tcx> LateLintPass<'tcx> for MemReplace { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { + if let ExprKind::Call(func, [dest, src]) = expr.kind // Check that `expr` is a call to `mem::replace()` - if let ExprKind::Call(func, [dest, src]) = expr.kind; - if let ExprKind::Path(ref func_qpath) = func.kind; - if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::mem_replace, def_id); - then { - // Check that second argument is `Option::None` - if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) { - check_replace_option_with_none(cx, dest, expr.span); - } else if self.msrv.meets(msrvs::MEM_TAKE) { - check_replace_with_default(cx, src, dest, expr.span); - } - check_replace_with_uninit(cx, src, dest, expr.span); + && let ExprKind::Path(ref func_qpath) = func.kind + && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::mem_replace, def_id) + { + // Check that second argument is `Option::None` + if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) { + check_replace_option_with_none(cx, dest, expr.span); + } else if self.msrv.meets(msrvs::MEM_TAKE) { + check_replace_with_default(cx, src, dest, expr.span); } + check_replace_with_uninit(cx, src, dest, expr.span); } } extract_msrv_attr!(LateContext); diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs index 3a8cc41748ebf..08bfa2e009b3f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and use clippy_utils::peel_blocks; use clippy_utils::source::{snippet, snippet_with_context}; use clippy_utils::visitors::find_all_ret_expressions; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -70,57 +69,50 @@ pub(crate) trait BindInsteadOfMap { closure_expr: &hir::Expr<'_>, closure_args_span: Span, ) -> bool { - if_chain! { - if let hir::ExprKind::Call(some_expr, [inner_expr]) = closure_expr.kind; - if let hir::ExprKind::Path(QPath::Resolved(_, path)) = some_expr.kind; - if Self::is_variant(cx, path.res); - if !contains_return(inner_expr); - if let Some(msg) = Self::lint_msg(cx); - then { - let mut app = Applicability::MachineApplicable; - let some_inner_snip = snippet_with_context(cx, inner_expr.span, closure_expr.span.ctxt(), "_", &mut app).0; - - let closure_args_snip = snippet(cx, closure_args_span, ".."); - let option_snip = snippet(cx, recv.span, ".."); - let note = format!("{option_snip}.{}({closure_args_snip} {some_inner_snip})", Self::GOOD_METHOD_NAME); - span_lint_and_sugg( - cx, - BIND_INSTEAD_OF_MAP, - expr.span, - &msg, - "try", - note, - app, - ); - true - } else { - false - } + if let hir::ExprKind::Call(some_expr, [inner_expr]) = closure_expr.kind + && let hir::ExprKind::Path(QPath::Resolved(_, path)) = some_expr.kind + && Self::is_variant(cx, path.res) + && !contains_return(inner_expr) + && let Some(msg) = Self::lint_msg(cx) + { + let mut app = Applicability::MachineApplicable; + let some_inner_snip = snippet_with_context(cx, inner_expr.span, closure_expr.span.ctxt(), "_", &mut app).0; + + let closure_args_snip = snippet(cx, closure_args_span, ".."); + let option_snip = snippet(cx, recv.span, ".."); + let note = format!( + "{option_snip}.{}({closure_args_snip} {some_inner_snip})", + Self::GOOD_METHOD_NAME + ); + span_lint_and_sugg(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, "try", note, app); + true + } else { + false } } fn lint_closure(cx: &LateContext<'_>, expr: &hir::Expr<'_>, closure_expr: &hir::Expr<'_>) -> bool { let mut suggs = Vec::new(); let can_sugg: bool = find_all_ret_expressions(cx, closure_expr, |ret_expr| { - if_chain! { - if !ret_expr.span.from_expansion(); - if let hir::ExprKind::Call(func_path, [arg]) = ret_expr.kind; - if let hir::ExprKind::Path(QPath::Resolved(_, path)) = func_path.kind; - if Self::is_variant(cx, path.res); - if !contains_return(arg); - then { - suggs.push((ret_expr.span, arg.span.source_callsite())); - true - } else { - false - } + if !ret_expr.span.from_expansion() + && let hir::ExprKind::Call(func_path, [arg]) = ret_expr.kind + && let hir::ExprKind::Path(QPath::Resolved(_, path)) = func_path.kind + && Self::is_variant(cx, path.res) + && !contains_return(arg) + { + suggs.push((ret_expr.span, arg.span.source_callsite())); + true + } else { + false } }); - let (span, msg) = if_chain! { - if can_sugg; - if let hir::ExprKind::MethodCall(segment, ..) = expr.kind; - if let Some(msg) = Self::lint_msg(cx); - then { (segment.ident.span, msg) } else { return false; } + let (span, msg) = if can_sugg + && let hir::ExprKind::MethodCall(segment, ..) = expr.kind + && let Some(msg) = Self::lint_msg(cx) + { + (segment.ident.span, msg) + } else { + return false; }; span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| { multispan_sugg_with_applicability( @@ -139,11 +131,12 @@ pub(crate) trait BindInsteadOfMap { /// Lint use of `_.and_then(|x| Some(y))` for `Option`s fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool { - if_chain! { - if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def(); - if let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM); - if adt.did() == cx.tcx.parent(vid); - then {} else { return false; } + if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def() + && let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM) + && adt.did() == cx.tcx.parent(vid) + { + } else { + return false; } match arg.kind { diff --git a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs index 35370355f8340..4a2124c74a882 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs @@ -3,7 +3,6 @@ use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::is_local_used; use clippy_utils::{path_to_local_id, peel_blocks, peel_ref_operators, strip_pat_refs}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind}; use rustc_lint::LateContext; @@ -18,53 +17,50 @@ pub(super) fn check<'tcx>( filter_recv: &'tcx Expr<'_>, filter_arg: &'tcx Expr<'_>, ) { - if_chain! { - if let ExprKind::Closure(&Closure { body, .. }) = filter_arg.kind; - let body = cx.tcx.hir().body(body); - if let [param] = body.params; - if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind; - if let ExprKind::Binary(ref op, l, r) = body.value.kind; - if op.node == BinOpKind::Eq; - if is_type_diagnostic_item(cx, - cx.typeck_results().expr_ty(filter_recv).peel_refs(), - sym::SliceIter); - let operand_is_arg = |expr| { + if let ExprKind::Closure(&Closure { body, .. }) = filter_arg.kind + && let body = cx.tcx.hir().body(body) + && let [param] = body.params + && let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind + && let ExprKind::Binary(ref op, l, r) = body.value.kind + && op.node == BinOpKind::Eq + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv).peel_refs(), sym::SliceIter) + && let operand_is_arg = (|expr| { let expr = peel_ref_operators(cx, peel_blocks(expr)); path_to_local_id(expr, arg_id) - }; - let needle = if operand_is_arg(l) { + }) + && let needle = if operand_is_arg(l) { r } else if operand_is_arg(r) { l } else { return; - }; - if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind(); - if !is_local_used(cx, needle, arg_id); - then { - let haystack = if let ExprKind::MethodCall(path, receiver, [], _) = - filter_recv.kind { - let p = path.ident.name; - if p == sym::iter || p == sym::iter_mut { - receiver - } else { - filter_recv - } + } + && ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind() + && !is_local_used(cx, needle, arg_id) + { + let haystack = if let ExprKind::MethodCall(path, receiver, [], _) = filter_recv.kind { + let p = path.ident.name; + if p == sym::iter || p == sym::iter_mut { + receiver } else { filter_recv - }; - let mut applicability = Applicability::MaybeIncorrect; - span_lint_and_sugg( - cx, - NAIVE_BYTECOUNT, - expr.span, - "you appear to be counting bytes the naive way", - "consider using the bytecount crate", - format!("bytecount::count({}, {})", - snippet_with_applicability(cx, haystack.span, "..", &mut applicability), - snippet_with_applicability(cx, needle.span, "..", &mut applicability)), - applicability, - ); - } + } + } else { + filter_recv + }; + let mut applicability = Applicability::MaybeIncorrect; + span_lint_and_sugg( + cx, + NAIVE_BYTECOUNT, + expr.span, + "you appear to be counting bytes the naive way", + "consider using the bytecount crate", + format!( + "bytecount::count({}, {})", + snippet_with_applicability(cx, haystack.span, "..", &mut applicability), + snippet_with_applicability(cx, needle.span, "..", &mut applicability) + ), + applicability, + ); }; } diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs index 649fc46e4adf1..34159f2d150ea 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_lang_item; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -14,23 +13,24 @@ pub(super) fn check<'tcx>( count_recv: &'tcx hir::Expr<'_>, bytes_recv: &'tcx hir::Expr<'_>, ) { - if_chain! { - if let Some(bytes_id) = cx.typeck_results().type_dependent_def_id(count_recv.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(bytes_id); - if cx.tcx.type_of(impl_id).instantiate_identity().is_str(); - let ty = cx.typeck_results().expr_ty(bytes_recv).peel_refs(); - if ty.is_str() || is_type_lang_item(cx, ty, hir::LangItem::String); - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - BYTES_COUNT_TO_LEN, - expr.span, - "using long and hard to read `.bytes().count()`", - "consider calling `.len()` instead", - format!("{}.len()", snippet_with_applicability(cx, bytes_recv.span, "..", &mut applicability)), - applicability - ); - } + if let Some(bytes_id) = cx.typeck_results().type_dependent_def_id(count_recv.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(bytes_id) + && cx.tcx.type_of(impl_id).instantiate_identity().is_str() + && let ty = cx.typeck_results().expr_ty(bytes_recv).peel_refs() + && (ty.is_str() || is_type_lang_item(cx, ty, hir::LangItem::String)) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + BYTES_COUNT_TO_LEN, + expr.span, + "using long and hard to read `.bytes().count()`", + "consider calling `.len()` instead", + format!( + "{}.len()", + snippet_with_applicability(cx, bytes_recv.span, "..", &mut applicability) + ), + applicability, + ); }; } diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index d5897822edaa7..a37087d0abffb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; use clippy_utils::ty::is_type_lang_item; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem}; @@ -27,51 +26,54 @@ pub(super) fn check<'tcx>( } } - if_chain! { - if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(method_id); - if cx.tcx.type_of(impl_id).instantiate_identity().is_str(); - if let ExprKind::Lit(Spanned { node: LitKind::Str(ext_literal, ..), ..}) = arg.kind; - if (2..=6).contains(&ext_literal.as_str().len()); - let ext_str = ext_literal.as_str(); - if ext_str.starts_with('.'); - if ext_str.chars().skip(1).all(|c| c.is_uppercase() || c.is_ascii_digit()) - || ext_str.chars().skip(1).all(|c| c.is_lowercase() || c.is_ascii_digit()); - let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); - if recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String); - then { - span_lint_and_then( - cx, - CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, - recv.span.to(call_span), - "case-sensitive file extension comparison", - |diag| { - diag.help("consider using a case-insensitive comparison instead"); - if let Some(mut recv_source) = snippet_opt(cx, recv.span) { - - if !cx.typeck_results().expr_ty(recv).is_ref() { - recv_source = format!("&{recv_source}"); - } + if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(method_id) + && cx.tcx.type_of(impl_id).instantiate_identity().is_str() + && let ExprKind::Lit(Spanned { + node: LitKind::Str(ext_literal, ..), + .. + }) = arg.kind + && (2..=6).contains(&ext_literal.as_str().len()) + && let ext_str = ext_literal.as_str() + && ext_str.starts_with('.') + && (ext_str.chars().skip(1).all(|c| c.is_uppercase() || c.is_ascii_digit()) + || ext_str.chars().skip(1).all(|c| c.is_lowercase() || c.is_ascii_digit())) + && let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs() + && (recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String)) + { + span_lint_and_then( + cx, + CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, + recv.span.to(call_span), + "case-sensitive file extension comparison", + |diag| { + diag.help("consider using a case-insensitive comparison instead"); + if let Some(mut recv_source) = snippet_opt(cx, recv.span) { + if !cx.typeck_results().expr_ty(recv).is_ref() { + recv_source = format!("&{recv_source}"); + } - let suggestion_source = reindent_multiline( - format!( - "std::path::Path::new({}) - .extension() - .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))", - recv_source, ext_str.strip_prefix('.').unwrap()).into(), - true, - Some(indent_of(cx, call_span).unwrap_or(0) + 4) - ); + let suggestion_source = reindent_multiline( + format!( + "std::path::Path::new({}) + .extension() + .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))", + recv_source, + ext_str.strip_prefix('.').unwrap() + ) + .into(), + true, + Some(indent_of(cx, call_span).unwrap_or(0) + 4), + ); - diag.span_suggestion( - recv.span.to(call_span), - "use std::path::Path", - suggestion_source, - Applicability::MaybeIncorrect, - ); - } + diag.span_suggestion( + recv.span.to(call_span), + "use std::path::Path", + suggestion_source, + Applicability::MaybeIncorrect, + ); } - ); - } + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs index 0e41f3c210769..c99cec067bf11 100644 --- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs +++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{method_chain_args, path_def_id}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, Lint}; @@ -15,34 +14,34 @@ pub(super) fn check( lint: &'static Lint, suggest: &str, ) -> bool { - if_chain! { - if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind; - if let Some(id) = path_def_id(cx, fun).map(|ctor_id| cx.tcx.parent(ctor_id)); - if Some(id) == cx.tcx.lang_items().option_some_variant(); - then { - let mut applicability = Applicability::MachineApplicable; - let self_ty = cx.typeck_results().expr_ty_adjusted(args[0].0).peel_refs(); + if let Some(args) = method_chain_args(info.chain, chain_methods) + && let hir::ExprKind::Call(fun, [arg_char]) = info.other.kind + && let Some(id) = path_def_id(cx, fun).map(|ctor_id| cx.tcx.parent(ctor_id)) + && Some(id) == cx.tcx.lang_items().option_some_variant() + { + let mut applicability = Applicability::MachineApplicable; + let self_ty = cx.typeck_results().expr_ty_adjusted(args[0].0).peel_refs(); - if *self_ty.kind() != ty::Str { - return false; - } + if *self_ty.kind() != ty::Str { + return false; + } - span_lint_and_sugg( - cx, - lint, - info.expr.span, - &format!("you should use the `{suggest}` method"), - "like this", - format!("{}{}.{suggest}({})", - if info.eq { "" } else { "!" }, - snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability), - snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)), - applicability, - ); + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{suggest}` method"), + "like this", + format!( + "{}{}.{suggest}({})", + if info.eq { "" } else { "!" }, + snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability), + snippet_with_applicability(cx, arg_char.span, "..", &mut applicability) + ), + applicability, + ); - return true; - } + return true; } false diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs index c9d50a5b03db6..d07e45434a7c9 100644 --- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::method_chain_args; use clippy_utils::source::snippet_with_applicability; -use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; @@ -15,28 +14,28 @@ pub(super) fn check( lint: &'static Lint, suggest: &str, ) -> bool { - if_chain! { - if let Some(args) = method_chain_args(info.chain, chain_methods); - if let hir::ExprKind::Lit(lit) = info.other.kind; - if let ast::LitKind::Char(c) = lit.node; - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - lint, - info.expr.span, - &format!("you should use the `{suggest}` method"), - "like this", - format!("{}{}.{suggest}('{}')", - if info.eq { "" } else { "!" }, - snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability), - c.escape_default()), - applicability, - ); + if let Some(args) = method_chain_args(info.chain, chain_methods) + && let hir::ExprKind::Lit(lit) = info.other.kind + && let ast::LitKind::Char(c) = lit.node + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + lint, + info.expr.span, + &format!("you should use the `{suggest}` method"), + "like this", + format!( + "{}{}.{suggest}('{}')", + if info.eq { "" } else { "!" }, + snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability), + c.escape_default() + ), + applicability, + ); - true - } else { - false - } + true + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index eb4f003d38ae5..532bbbeaf032e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -61,7 +61,7 @@ pub(super) fn check( // ? is a Call, makes sure not to rec *x?, but rather (*x)? ExprKind::Call(hir_callee, _) => matches!( hir_callee.kind, - ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, _, _)) + ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, ..)) ), ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true, ExprKind::Match(_, _, MatchSource::TryDesugar(_) | MatchSource::AwaitDesugar) diff --git a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs index a8d4dd5e4f312..dc978c8a58456 100644 --- a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs @@ -16,30 +16,27 @@ pub(super) fn check( err_span: Span, msrv: &Msrv, ) { - if_chain! { - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result) // Test the version to make sure the lint can be showed (expect_err has been // introduced in rust 1.17.0 : https://github.com/rust-lang/rust/pull/38982) - if msrv.meets(msrvs::EXPECT_ERR); + && msrv.meets(msrvs::EXPECT_ERR) // Grabs the `Result` type - let result_type = cx.typeck_results().expr_ty(recv); + && let result_type = cx.typeck_results().expr_ty(recv) // Tests if the T type in a `Result` is not None - if let Some(data_type) = get_data_type(cx, result_type); + && let Some(data_type) = get_data_type(cx, result_type) // Tests if the T type in a `Result` implements debug - if has_debug_impl(cx, data_type); - - then { - span_lint_and_sugg( - cx, - ERR_EXPECT, - err_span.to(expect_span), - "called `.err().expect()` on a `Result` value", - "try", - "expect_err".to_string(), - Applicability::MachineApplicable + && has_debug_impl(cx, data_type) + { + span_lint_and_sugg( + cx, + ERR_EXPECT, + err_span.to(expect_span), + "called `.err().expect()` on a `Result` value", + "try", + "expect_err".to_string(), + Applicability::MachineApplicable, ); - } }; } diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs index a49970b5351d8..f0fc925799a35 100644 --- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs @@ -6,8 +6,8 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::Span; use rustc_span::symbol::sym; +use rustc_span::Span; use std::borrow::Cow; use super::EXPECT_FUN_CALL; diff --git a/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs index 495b266529bdc..460ec7b3640a6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs +++ b/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_lint::LateContext; @@ -11,35 +10,33 @@ use super::EXTEND_WITH_DRAIN; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) { let ty = cx.typeck_results().expr_ty(recv).peel_refs(); - if_chain! { - if is_type_diagnostic_item(cx, ty, sym::Vec); + if is_type_diagnostic_item(cx, ty, sym::Vec) //check source object - if let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind; - if src_method.ident.as_str() == "drain"; - let src_ty = cx.typeck_results().expr_ty(drain_vec); + && let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind + && src_method.ident.as_str() == "drain" + && let src_ty = cx.typeck_results().expr_ty(drain_vec) //check if actual src type is mutable for code suggestion - let immutable = src_ty.is_mutable_ptr(); - let src_ty = src_ty.peel_refs(); - if is_type_diagnostic_item(cx, src_ty, sym::Vec); + && let immutable = src_ty.is_mutable_ptr() + && let src_ty = src_ty.peel_refs() + && is_type_diagnostic_item(cx, src_ty, sym::Vec) //check drain range - if let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs(); - if is_type_lang_item(cx, src_ty_range, LangItem::RangeFull); - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - EXTEND_WITH_DRAIN, - expr.span, - "use of `extend` instead of `append` for adding the full range of a second vector", - "try", - format!( - "{}.append({}{})", - snippet_with_applicability(cx, recv.span, "..", &mut applicability), - if immutable { "" } else { "&mut " }, - snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability) - ), - applicability, - ); - } + && let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs() + && is_type_lang_item(cx, src_ty_range, LangItem::RangeFull) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + EXTEND_WITH_DRAIN, + expr.span, + "use of `extend` instead of `append` for adding the full range of a second vector", + "try", + format!( + "{}.append({}{})", + snippet_with_applicability(cx, recv.span, "..", &mut applicability), + if immutable { "" } else { "&mut " }, + snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability) + ), + applicability, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs index 7818be81119bb..b05361ab21204 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::get_parent_expr; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::{sym, Span}; @@ -19,21 +18,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr let verb: &str; let lint_unary: &str; let help_unary: &str; - if_chain! { - if let Some(parent) = get_parent_expr(cx, expr); - if let hir::ExprKind::Unary(op, _) = parent.kind; - if op == hir::UnOp::Not; - then { - lint_unary = "!"; - verb = "denies"; - help_unary = ""; - span = parent.span; - } else { - lint_unary = ""; - verb = "covers"; - help_unary = "!"; - span = expr.span; - } + if let Some(parent) = get_parent_expr(cx, expr) + && let hir::ExprKind::Unary(op, _) = parent.kind + && op == hir::UnOp::Not + { + lint_unary = "!"; + verb = "denies"; + help_unary = ""; + span = parent.span; + } else { + lint_unary = ""; + verb = "covers"; + help_unary = "!"; + span = expr.span; } let lint_msg = format!("`{lint_unary}FileType::is_file()` only {verb} regular files"); let help_msg = format!("use `{help_unary}FileType::is_dir()` instead"); diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index 5bb8c7a6b9488..844ab40cab1a0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -4,15 +4,14 @@ use clippy_utils::source::{indent_of, reindent_multiline, snippet}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{higher, is_trait_method, path_to_local_id, peel_blocks, SpanlessEq}; use hir::{Body, HirId, MatchSource, Pat}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty::adjustment::Adjust; -use rustc_span::Span; use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::Span; use std::borrow::Cow; use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP}; @@ -29,13 +28,11 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> let arg_id = body.params[0].pat.hir_id; match closure_expr.kind { hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => { - if_chain! { - if ident.name == method_name; - if let hir::ExprKind::Path(path) = &receiver.kind; - if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id); - then { - return arg_id == *local - } + if ident.name == method_name + && let hir::ExprKind::Path(path) = &receiver.kind + && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id) + { + return arg_id == *local; } false }, @@ -139,11 +136,9 @@ impl<'tcx> OffendingFilterExpr<'tcx> { && path_to_local_id(map_arg_peeled, map_param_id)) && let eq_fallback = (|a: &Expr<'_>, b: &Expr<'_>| { // in `filter(|x| ..)`, replace `*x` with `x` - let a_path = if_chain! { - if !is_filter_param_ref; - if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind; - then { expr_path } else { a } - }; + let a_path = if !is_filter_param_ref + && let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind + { expr_path } else { a }; // let the filter closure arg and the map closure arg be equal path_to_local_id(a_path, filter_param_id) && path_to_local_id(b, map_param_id) @@ -305,87 +300,98 @@ pub(super) fn check( return; } - if_chain! { - if is_trait_method(cx, map_recv, sym::Iterator); + if is_trait_method(cx, map_recv, sym::Iterator) // filter(|x| ...is_some())... - if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind; - let filter_body = cx.tcx.hir().body(filter_body_id); - if let [filter_param] = filter_body.params; + && let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind + && let filter_body = cx.tcx.hir().body(filter_body_id) + && let [filter_param] = filter_body.params // optional ref pattern: `filter(|&x| ..)` - let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind { + && let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind { (ref_pat, true) } else { (filter_param.pat, false) - }; - - if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind; - if let Some(mut offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id); + } - if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind; - let map_body = cx.tcx.hir().body(map_body_id); - if let [map_param] = map_body.params; - if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind; + && let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind + && let Some(mut offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id) - if let Some(check_result) = - offending_expr.check_map_call(cx, map_body, map_param_id, filter_param_id, is_filter_param_ref); + && let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind + && let map_body = cx.tcx.hir().body(map_body_id) + && let [map_param] = map_body.params + && let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind - then { - let span = filter_span.with_hi(expr.span.hi()); - let (filter_name, lint) = if is_find { - ("find", MANUAL_FIND_MAP) - } else { - ("filter", MANUAL_FILTER_MAP) - }; - let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`"); + && let Some(check_result) = + offending_expr.check_map_call(cx, map_body, map_param_id, filter_param_id, is_filter_param_ref) + { + let span = filter_span.with_hi(expr.span.hi()); + let (filter_name, lint) = if is_find { + ("find", MANUAL_FIND_MAP) + } else { + ("filter", MANUAL_FILTER_MAP) + }; + let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`"); - let (sugg, note_and_span, applicability) = match check_result { - CheckResult::Method { map_arg, method, side_effect_expr_span } => { - let (to_opt, deref) = match method { - CalledMethod::ResultIsOk => (".ok()", String::new()), - CalledMethod::OptionIsSome => { - let derefs = cx.typeck_results() - .expr_adjustments(map_arg) - .iter() - .filter(|adj| matches!(adj.kind, Adjust::Deref(_))) - .count(); + let (sugg, note_and_span, applicability) = match check_result { + CheckResult::Method { + map_arg, + method, + side_effect_expr_span, + } => { + let (to_opt, deref) = match method { + CalledMethod::ResultIsOk => (".ok()", String::new()), + CalledMethod::OptionIsSome => { + let derefs = cx + .typeck_results() + .expr_adjustments(map_arg) + .iter() + .filter(|adj| matches!(adj.kind, Adjust::Deref(_))) + .count(); - ("", "*".repeat(derefs)) - } - }; + ("", "*".repeat(derefs)) + }, + }; - let sugg = format!( - "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})", - snippet(cx, map_arg.span, ".."), - ); - let (note_and_span, applicability) = if let Some(span) = side_effect_expr_span { - let note = "the suggestion might change the behavior of the program when merging `filter` and `map`, \ - because this expression potentially contains side effects and will only execute once"; + let sugg = format!( + "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})", + snippet(cx, map_arg.span, ".."), + ); + let (note_and_span, applicability) = if let Some(span) = side_effect_expr_span { + let note = "the suggestion might change the behavior of the program when merging `filter` and `map`, \ + because this expression potentially contains side effects and will only execute once"; - (Some((note, span)), Applicability::MaybeIncorrect) - } else { - (None, Applicability::MachineApplicable) - }; + (Some((note, span)), Applicability::MaybeIncorrect) + } else { + (None, Applicability::MachineApplicable) + }; - (sugg, note_and_span, applicability) - } - CheckResult::PatternMatching { variant_span, variant_ident } => { - let pat = snippet(cx, variant_span, ""); + (sugg, note_and_span, applicability) + }, + CheckResult::PatternMatching { + variant_span, + variant_ident, + } => { + let pat = snippet(cx, variant_span, ""); - (format!("{filter_name}_map(|{map_param_ident}| match {map_param_ident} {{ \ - {pat} => Some({variant_ident}), \ - _ => None \ - }})"), None, Applicability::MachineApplicable) - } - }; - span_lint_and_then(cx, lint, span, &msg, |diag| { - diag.span_suggestion(span, "try", sugg, applicability); + ( + format!( + "{filter_name}_map(|{map_param_ident}| match {map_param_ident} {{ \ + {pat} => Some({variant_ident}), \ + _ => None \ + }})" + ), + None, + Applicability::MachineApplicable, + ) + }, + }; + span_lint_and_then(cx, lint, span, &msg, |diag| { + diag.span_suggestion(span, "try", sugg, applicability); - if let Some((note, span)) = note_and_span { - diag.span_note(span, note); - } - }); - } + if let Some((note, span)) = note_and_span { + diag.span_note(span, note); + } + }); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs index 9950c44285514..2e43d19a69911 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & closure.def_id.to_def_id(), Binder::bind_with_vars( cx.typeck_results().node_type(param_ty.hir_id), - cx.tcx.late_bound_vars(cx.tcx.hir().local_def_id_to_hir_id(closure.def_id)), + cx.tcx.late_bound_vars(cx.tcx.local_def_id_to_hir_id(closure.def_id)), ), ) && is_copy(cx, param_ty) diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 4040d3a5fe13b..917a8e33eb9fb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; use clippy_utils::{is_path_diagnostic_item, sugg}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -12,28 +11,25 @@ use rustc_span::sym; use super::FROM_ITER_INSTEAD_OF_COLLECT; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func: &hir::Expr<'_>) { - if_chain! { - if is_path_diagnostic_item(cx, func, sym::from_iter_fn); - let ty = cx.typeck_results().expr_ty(expr); - let arg_ty = cx.typeck_results().expr_ty(&args[0]); - if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator); - - if implements_trait(cx, arg_ty, iter_id, &[]); - then { - // `expr` implements `FromIterator` trait - let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par(); - let turbofish = extract_turbofish(cx, expr, ty); - let sugg = format!("{iter_expr}.collect::<{turbofish}>()"); - span_lint_and_sugg( - cx, - FROM_ITER_INSTEAD_OF_COLLECT, - expr.span, - "usage of `FromIterator::from_iter`", - "use `.collect()` instead of `::from_iter()`", - sugg, - Applicability::MaybeIncorrect, - ); - } + if is_path_diagnostic_item(cx, func, sym::from_iter_fn) + && let ty = cx.typeck_results().expr_ty(expr) + && let arg_ty = cx.typeck_results().expr_ty(&args[0]) + && let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator) + && implements_trait(cx, arg_ty, iter_id, &[]) + { + // `expr` implements `FromIterator` trait + let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par(); + let turbofish = extract_turbofish(cx, expr, ty); + let sugg = format!("{iter_expr}.collect::<{turbofish}>()"); + span_lint_and_sugg( + cx, + FROM_ITER_INSTEAD_OF_COLLECT, + expr.span, + "usage of `FromIterator::from_iter`", + "use `.collect()` instead of `::from_iter()`", + sugg, + Applicability::MaybeIncorrect, + ); } } @@ -43,41 +39,43 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) -> } let call_site = expr.span.source_callsite(); - if_chain! { - if let Some(snippet) = snippet_opt(cx, call_site); - let snippet_split = snippet.split("::").collect::>(); - if let Some((_, elements)) = snippet_split.split_last(); - - then { - if_chain! { - if let [type_specifier, _] = snippet_split.as_slice(); - if let Some(type_specifier) = strip_angle_brackets(type_specifier); - if let Some((type_specifier, ..)) = type_specifier.split_once(" as "); - then { - type_specifier.to_string() - } else { - // is there a type specifier? (i.e.: like `` in `collections::BTreeSet::::`) - if let Some(type_specifier) = snippet_split.iter().find(|e| strip_angle_brackets(e).is_some()) { - // remove the type specifier from the path elements - let without_ts = elements.iter().filter_map(|e| { - if e == type_specifier { None } else { Some((*e).to_string()) } - }).collect::>(); - // join and add the type specifier at the end (i.e.: `collections::BTreeSet`) - format!("{}{type_specifier}", without_ts.join("::")) - } else { - // type is not explicitly specified so wildcards are needed - // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>` - let ty_str = ty.to_string(); - let start = ty_str.find('<').unwrap_or(0); - let end = ty_str.find('>').unwrap_or(ty_str.len()); - let nb_wildcard = ty_str[start..end].split(',').count(); - let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1)); - format!("{}<{wildcards}>", elements.join("::")) - } - } - } + if let Some(snippet) = snippet_opt(cx, call_site) + && let snippet_split = snippet.split("::").collect::>() + && let Some((_, elements)) = snippet_split.split_last() + { + if let [type_specifier, _] = snippet_split.as_slice() + && let Some(type_specifier) = strip_angle_brackets(type_specifier) + && let Some((type_specifier, ..)) = type_specifier.split_once(" as ") + { + type_specifier.to_string() } else { - ty.to_string() + // is there a type specifier? (i.e.: like `` in `collections::BTreeSet::::`) + if let Some(type_specifier) = snippet_split.iter().find(|e| strip_angle_brackets(e).is_some()) { + // remove the type specifier from the path elements + let without_ts = elements + .iter() + .filter_map(|e| { + if e == type_specifier { + None + } else { + Some((*e).to_string()) + } + }) + .collect::>(); + // join and add the type specifier at the end (i.e.: `collections::BTreeSet`) + format!("{}{type_specifier}", without_ts.join("::")) + } else { + // type is not explicitly specified so wildcards are needed + // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>` + let ty_str = ty.to_string(); + let start = ty_str.find('<').unwrap_or(0); + let end = ty_str.find('>').unwrap_or(ty_str.len()); + let nb_wildcard = ty_str[start..end].split(',').count(); + let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1)); + format!("{}<{wildcards}>", elements.join("::")) + } } + } else { + ty.to_string() } } diff --git a/src/tools/clippy/clippy_lints/src/methods/get_first.rs b/src/tools/clippy/clippy_lints/src/methods/get_first.rs index 2e1dd3ec649be..e1f1e4893558e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/get_first.rs +++ b/src/tools/clippy/clippy_lints/src/methods/get_first.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir as hir; @@ -17,37 +16,38 @@ pub(super) fn check<'tcx>( recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, ) { - if_chain! { - if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(method_id); - let identity = cx.tcx.type_of(impl_id).instantiate_identity(); - if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind; - then { - if identity.is_slice() { - let mut app = Applicability::MachineApplicable; - let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app); - span_lint_and_sugg( - cx, - GET_FIRST, - expr.span, - &format!("accessing first element with `{slice_name}.get(0)`"), - "try", - format!("{slice_name}.first()"), - app, - ); - } else if is_type_diagnostic_item(cx, identity, sym::VecDeque){ - let mut app = Applicability::MachineApplicable; - let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app); - span_lint_and_sugg( - cx, - GET_FIRST, - expr.span, - &format!("accessing first element with `{slice_name}.get(0)`"), - "try", - format!("{slice_name}.front()"), - app, - ); - } + if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(method_id) + && let identity = cx.tcx.type_of(impl_id).instantiate_identity() + && let hir::ExprKind::Lit(Spanned { + node: LitKind::Int(0, _), + .. + }) = arg.kind + { + if identity.is_slice() { + let mut app = Applicability::MachineApplicable; + let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app); + span_lint_and_sugg( + cx, + GET_FIRST, + expr.span, + &format!("accessing first element with `{slice_name}.get(0)`"), + "try", + format!("{slice_name}.first()"), + app, + ); + } else if is_type_diagnostic_item(cx, identity, sym::VecDeque) { + let mut app = Applicability::MachineApplicable; + let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app); + span_lint_and_sugg( + cx, + GET_FIRST, + expr.span, + &format!("accessing first element with `{slice_name}.get(0)`"), + "try", + format!("{slice_name}.front()"), + app, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs index e91ce64d8c8c8..78a553eb8c0d4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{implements_trait, peel_mid_ty_refs}; use clippy_utils::{is_diag_item_method, is_diag_trait_item}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -11,34 +10,32 @@ use rustc_span::sym; use super::IMPLICIT_CLONE; pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { - if_chain! { - if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if is_clone_like(cx, method_name, method_def_id); - let return_type = cx.typeck_results().expr_ty(expr); - let input_type = cx.typeck_results().expr_ty(recv); - let (input_type, ref_count) = peel_mid_ty_refs(input_type); - if !(ref_count > 0 && is_diag_trait_item(cx, method_def_id, sym::ToOwned)); - if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did())); - if return_type == input_type; - if let Some(clone_trait) = cx.tcx.lang_items().clone_trait(); - if implements_trait(cx, return_type, clone_trait, &[]); - then { - let mut app = Applicability::MachineApplicable; - let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0; - span_lint_and_sugg( - cx, - IMPLICIT_CLONE, - expr.span, - &format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"), - "consider using", - if ref_count > 1 { - format!("({}{recv_snip}).clone()", "*".repeat(ref_count - 1)) - } else { - format!("{recv_snip}.clone()") - }, - app, - ); - } + if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && is_clone_like(cx, method_name, method_def_id) + && let return_type = cx.typeck_results().expr_ty(expr) + && let input_type = cx.typeck_results().expr_ty(recv) + && let (input_type, ref_count) = peel_mid_ty_refs(input_type) + && !(ref_count > 0 && is_diag_trait_item(cx, method_def_id, sym::ToOwned)) + && let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did())) + && return_type == input_type + && let Some(clone_trait) = cx.tcx.lang_items().clone_trait() + && implements_trait(cx, return_type, clone_trait, &[]) + { + let mut app = Applicability::MachineApplicable; + let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0; + span_lint_and_sugg( + cx, + IMPLICIT_CLONE, + expr.span, + &format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"), + "consider using", + if ref_count > 1 { + format!("({}{recv_snip}).clone()", "*".repeat(ref_count - 1)) + } else { + format!("{recv_snip}.clone()") + }, + app, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs index 6686d42c95f83..efc3ddd20b4bd 100644 --- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_type_lang_item, walk_ptrs_ty_depth}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -18,37 +17,36 @@ pub fn check( receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>], ) { - if_chain! { - if args.is_empty() && method_name == sym::to_string; - if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if cx.tcx.is_diagnostic_item(sym::to_string_method, to_string_meth_did); - if let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id); - let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver); - let self_ty = args.type_at(0); - let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty); - if deref_count >= 1; - if specializes_tostring(cx, deref_self_ty); - then { - span_lint_and_then( - cx, - INEFFICIENT_TO_STRING, - expr.span, - &format!("calling `to_string` on `{arg_ty}`"), - |diag| { - diag.help(format!( - "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`" - )); - let mut applicability = Applicability::MachineApplicable; - let arg_snippet = snippet_with_applicability(cx, receiver.span, "..", &mut applicability); - diag.span_suggestion( - expr.span, - "try dereferencing the receiver", - format!("({}{arg_snippet}).to_string()", "*".repeat(deref_count)), - applicability, - ); - }, - ); - } + if args.is_empty() + && method_name == sym::to_string + && let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && cx.tcx.is_diagnostic_item(sym::to_string_method, to_string_meth_did) + && let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id) + && let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver) + && let self_ty = args.type_at(0) + && let (deref_self_ty, deref_count) = walk_ptrs_ty_depth(self_ty) + && deref_count >= 1 + && specializes_tostring(cx, deref_self_ty) + { + span_lint_and_then( + cx, + INEFFICIENT_TO_STRING, + expr.span, + &format!("calling `to_string` on `{arg_ty}`"), + |diag| { + diag.help(format!( + "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`" + )); + let mut applicability = Applicability::MachineApplicable; + let arg_snippet = snippet_with_applicability(cx, receiver.span, "..", &mut applicability); + diag.span_suggestion( + expr.span, + "try dereferencing the receiver", + format!("({}{arg_snippet}).to_string()", "*".repeat(deref_count)), + applicability, + ); + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs index bbd964c10995f..80160d17c82d0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs @@ -1,13 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_trait_method; use clippy_utils::ty::has_iter_method; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; -use rustc_span::Span; use rustc_span::symbol::{sym, Symbol}; +use rustc_span::Span; use super::INTO_ITER_ON_REF; @@ -19,24 +18,20 @@ pub(super) fn check( receiver: &hir::Expr<'_>, ) { let self_ty = cx.typeck_results().expr_ty_adjusted(receiver); - if_chain! { - if let ty::Ref(..) = self_ty.kind(); - if method_name == sym::into_iter; - if is_trait_method(cx, expr, sym::IntoIterator); - if let Some((kind, method_name)) = ty_has_iter_method(cx, self_ty); - then { - span_lint_and_sugg( - cx, - INTO_ITER_ON_REF, - method_span, - &format!( - "this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`", - ), - "call directly", - method_name.to_string(), - Applicability::MachineApplicable, - ); - } + if let ty::Ref(..) = self_ty.kind() + && method_name == sym::into_iter + && is_trait_method(cx, expr, sym::IntoIterator) + && let Some((kind, method_name)) = ty_has_iter_method(cx, self_ty) + { + span_lint_and_sugg( + cx, + INTO_ITER_ON_REF, + method_span, + &format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",), + "call directly", + method_name.to_string(), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs index bde6f92b076eb..dd741cd43f94d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs @@ -1,7 +1,6 @@ use crate::methods::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -10,22 +9,21 @@ use rustc_span::sym; use super::ITER_CLONED_COLLECT; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir::Expr<'_>, recv: &'tcx hir::Expr<'_>) { - if_chain! { - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec); - if let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv)); - if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite()); - - then { - span_lint_and_sugg( - cx, - ITER_CLONED_COLLECT, - to_replace, - &format!("called `iter().{method_name}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ - more readable"), - "try", - ".to_vec()".to_string(), - Applicability::MachineApplicable, - ); - } + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) + && let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv)) + && let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite()) + { + span_lint_and_sugg( + cx, + ITER_CLONED_COLLECT, + to_replace, + &format!( + "called `iter().{method_name}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \ + more readable" + ), + "try", + ".to_vec()".to_string(), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs index 625325d4cf5d4..e1b934d36ea8b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs @@ -1,6 +1,7 @@ #![allow(unused_imports)] use super::ITER_KV_MAP; +use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::ty::is_type_diagnostic_item; @@ -21,65 +22,59 @@ pub(super) fn check<'tcx>( expr: &'tcx Expr<'tcx>, // .iter().map(|(_, v_| v)) recv: &'tcx Expr<'tcx>, // hashmap m_arg: &'tcx Expr<'tcx>, // |(_, v)| v + msrv: &Msrv, ) { - if_chain! { - if !expr.span.from_expansion(); - if let ExprKind::Closure(c) = m_arg.kind; - if let Body {params: [p], value: body_expr, coroutine_kind: _ } = cx.tcx.hir().body(c.body); - if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind; - - let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) { + if map_type == "into_iter" && !msrv.meets(msrvs::INTO_KEYS) { + return; + } + if !expr.span.from_expansion() + && let ExprKind::Closure(c) = m_arg.kind + && let Body { + params: [p], + value: body_expr, + coroutine_kind: _, + } = cx.tcx.hir().body(c.body) + && let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind + && let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) { (key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value), (PatKind::Binding(ann, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", ann, key), _ => return, - }; - - let ty = cx.typeck_results().expr_ty(recv); - if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap); - - then { - let mut applicability = rustc_errors::Applicability::MachineApplicable; - let recv_snippet = snippet_with_applicability(cx, recv.span, "map", &mut applicability); - let into_prefix = if map_type == "into_iter" {"into_"} else {""}; - - if_chain! { - if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind; - if let [local_ident] = path.segments; - if local_ident.ident.as_str() == bound_ident.as_str(); + } + && let ty = cx.typeck_results().expr_ty(recv) + && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap)) + { + let mut applicability = rustc_errors::Applicability::MachineApplicable; + let recv_snippet = snippet_with_applicability(cx, recv.span, "map", &mut applicability); + let into_prefix = if map_type == "into_iter" { "into_" } else { "" }; - then { - span_lint_and_sugg( - cx, - ITER_KV_MAP, - expr.span, - &format!("iterating on a map's {replacement_kind}s"), - "try", - format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"), - applicability, - ); - } else { - let ref_annotation = if annotation.0 == ByRef::Yes { - "ref " - } else { - "" - }; - let mut_annotation = if annotation.1 == Mutability::Mut { - "mut " - } else { - "" - }; - span_lint_and_sugg( - cx, - ITER_KV_MAP, - expr.span, - &format!("iterating on a map's {replacement_kind}s"), - "try", - format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})", - snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)), - applicability, - ); - } - } + if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind + && let [local_ident] = path.segments + && local_ident.ident.as_str() == bound_ident.as_str() + { + span_lint_and_sugg( + cx, + ITER_KV_MAP, + expr.span, + &format!("iterating on a map's {replacement_kind}s"), + "try", + format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"), + applicability, + ); + } else { + let ref_annotation = if annotation.0 == ByRef::Yes { "ref " } else { "" }; + let mut_annotation = if annotation.1 == Mutability::Mut { "mut " } else { "" }; + span_lint_and_sugg( + cx, + ITER_KV_MAP, + expr.span, + &format!("iterating on a map's {replacement_kind}s"), + "try", + format!( + "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})", + snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability) + ), + applicability, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs index 8f885e9f729bb..fd4650e1e45f6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{get_parent_expr, higher}; -use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; @@ -26,29 +25,36 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal if derefs_to_slice(cx, caller_expr, cx.typeck_results().expr_ty(caller_expr)).is_some() { // caller is a Slice - if_chain! { - if let hir::ExprKind::Index(caller_var, index_expr, _) = &caller_expr.kind; - if let Some(higher::Range { start: Some(start_expr), end: None, limits: ast::RangeLimits::HalfOpen }) - = higher::Range::hir(index_expr); - if let hir::ExprKind::Lit(start_lit) = &start_expr.kind; - if let ast::LitKind::Int(start_idx, _) = start_lit.node; - then { - let mut applicability = Applicability::MachineApplicable; - let suggest = if start_idx == 0 { - format!("{}.first()", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability)) - } else { - format!("{}.get({start_idx})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability)) - }; - span_lint_and_sugg( - cx, - ITER_NEXT_SLICE, - expr.span, - "using `.iter().next()` on a Slice without end index", - "try calling", - suggest, - applicability, - ); - } + if let hir::ExprKind::Index(caller_var, index_expr, _) = &caller_expr.kind + && let Some(higher::Range { + start: Some(start_expr), + end: None, + limits: ast::RangeLimits::HalfOpen, + }) = higher::Range::hir(index_expr) + && let hir::ExprKind::Lit(start_lit) = &start_expr.kind + && let ast::LitKind::Int(start_idx, _) = start_lit.node + { + let mut applicability = Applicability::MachineApplicable; + let suggest = if start_idx == 0 { + format!( + "{}.first()", + snippet_with_applicability(cx, caller_var.span, "..", &mut applicability) + ) + } else { + format!( + "{}.get({start_idx})", + snippet_with_applicability(cx, caller_var.span, "..", &mut applicability) + ) + }; + span_lint_and_sugg( + cx, + ITER_NEXT_SLICE, + expr.span, + "using `.iter().next()` on a Slice without end index", + "try calling", + suggest, + applicability, + ); } } else if is_vec_or_array(cx, caller_expr) { // caller is a Vec or an Array diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs index 39af52141bbc8..fbe20dfe54ec8 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs @@ -19,18 +19,16 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr expr.span.trim_start(recv.span).unwrap(), "called `skip(..).next()` on an iterator", |diag| { - if_chain! { - if let Some(id) = path_to_local(recv); - if let Node::Pat(pat) = cx.tcx.hir().get(id); - if let PatKind::Binding(ann, _, _, _) = pat.kind; - if ann != BindingAnnotation::MUT; - then { - application = Applicability::Unspecified; - diag.span_help( - pat.span, - format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")), - ); - } + if let Some(id) = path_to_local(recv) + && let Node::Pat(pat) = cx.tcx.hir().get(id) + && let PatKind::Binding(ann, _, _, _) = pat.kind + && ann != BindingAnnotation::MUT + { + application = Applicability::Unspecified; + diag.span_help( + pat.span, + format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")), + ); } diag.span_suggestion( diff --git a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs new file mode 100644 index 0000000000000..02f28779cf6ee --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs @@ -0,0 +1,52 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::expr_or_init; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_ast::ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; +use rustc_span::Span; + +use super::JOIN_ABSOLUTE_PATHS; + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_arg: &'tcx Expr<'tcx>, expr_span: Span) { + let ty = cx.typeck_results().expr_ty(recv).peel_refs(); + if (is_type_diagnostic_item(cx, ty, sym::Path) || is_type_diagnostic_item(cx, ty, sym::PathBuf)) + && let ExprKind::Lit(spanned) = expr_or_init(cx, join_arg).kind + && let LitKind::Str(symbol, _) = spanned.node + && let sym_str = symbol.as_str() + && sym_str.starts_with(['/', '\\']) + { + span_lint_and_then( + cx, + JOIN_ABSOLUTE_PATHS, + join_arg.span, + "argument to `Path::join` starts with a path separator", + |diag| { + let arg_str = snippet_opt(cx, spanned.span).unwrap_or_else(|| "..".to_string()); + + let no_separator = if sym_str.starts_with('/') { + arg_str.replacen('/', "", 1) + } else { + arg_str.replacen('\\', "", 1) + }; + + diag.note("joining a path starting with separator will replace the path instead") + .span_suggestion( + spanned.span, + "if this is unintentional, try removing the starting separator", + no_separator, + Applicability::Unspecified, + ) + .span_suggestion( + expr_span, + "if this is intentional, try using `Path::new` instead", + format!("PathBuf::from({arg_str})"), + Applicability::Unspecified, + ); + }, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs index 3031193e53122..b1af0083e65a9 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::LangItem::{ResultErr, ResultOk}; use rustc_hir::{Expr, ExprKind, PatKind}; @@ -18,30 +17,26 @@ pub(super) fn check<'tcx>( or_expr: &'tcx Expr<'_>, map_expr: &'tcx Expr<'_>, ) { - if_chain! { - if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(method_id); - if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Option); - if let ExprKind::Call(err_path, [err_arg]) = or_expr.kind; - if is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr); - if is_ok_wrapping(cx, map_expr); - if let Some(recv_snippet) = snippet_opt(cx, recv.span); - if let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span); - if let Some(indent) = indent_of(cx, expr.span); - then { - let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4)); - span_lint_and_sugg( - cx, - MANUAL_OK_OR, - expr.span, - "this pattern reimplements `Option::ok_or`", - "replace with", - format!( - "{recv_snippet}.ok_or({reindented_err_arg_snippet})" - ), - Applicability::MachineApplicable, - ); - } + if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(method_id) + && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Option) + && let ExprKind::Call(err_path, [err_arg]) = or_expr.kind + && is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr) + && is_ok_wrapping(cx, map_expr) + && let Some(recv_snippet) = snippet_opt(cx, recv.span) + && let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span) + && let Some(indent) = indent_of(cx, expr.span) + { + let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4)); + span_lint_and_sugg( + cx, + MANUAL_OK_OR, + expr.span, + "this pattern reimplements `Option::ok_or`", + "replace with", + format!("{recv_snippet}.ok_or({reindented_err_arg_snippet})"), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs index 540425eef8c5e..04bdbc1ea25fe 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{match_def_path, path_def_id}; -use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; @@ -69,16 +68,14 @@ enum MinMax { fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option { // `T::max_value()` `T::min_value()` inherent methods - if_chain! { - if let hir::ExprKind::Call(func, args) = &expr.kind; - if args.is_empty(); - if let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = &func.kind; - then { - match segment.ident.as_str() { - "max_value" => return Some(MinMax::Max), - "min_value" => return Some(MinMax::Min), - _ => {} - } + if let hir::ExprKind::Call(func, args) = &expr.kind + && args.is_empty() + && let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = &func.kind + { + match segment.ident.as_str() { + "max_value" => return Some(MinMax::Max), + "min_value" => return Some(MinMax::Min), + _ => {}, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs index ab13d30d84529..61e74369cb05d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs @@ -3,7 +3,6 @@ use clippy_utils::is_path_diagnostic_item; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; -use if_chain::if_chain; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem}; @@ -55,43 +54,42 @@ pub(super) fn check( take_self_arg: &Expr<'_>, take_arg: &Expr<'_>, ) { - if_chain! { - if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind; - if is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat); - if is_type_lang_item(cx, cx.typeck_results().expr_ty(collect_expr), LangItem::String); - if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id); - if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); - if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id); - if let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg); - let ctxt = collect_expr.span.ctxt(); - if ctxt == take_expr.span.ctxt(); - if ctxt == take_self_arg.span.ctxt(); - then { - let mut app = Applicability::MachineApplicable; - let count_snip = snippet_with_context(cx, take_arg.span, ctxt, "..", &mut app).0; + if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind + && is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat) + && is_type_lang_item(cx, cx.typeck_results().expr_ty(collect_expr), LangItem::String) + && let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id) + && let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator) + && cx.tcx.trait_of_item(take_id) == Some(iter_trait_id) + && let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg) + && let ctxt = collect_expr.span.ctxt() + && ctxt == take_expr.span.ctxt() + && ctxt == take_self_arg.span.ctxt() + { + let mut app = Applicability::MachineApplicable; + let count_snip = snippet_with_context(cx, take_arg.span, ctxt, "..", &mut app).0; - let val_str = match repeat_kind { - RepeatKind::Char(_) if repeat_arg.span.ctxt() != ctxt => return, - RepeatKind::Char('\'') => r#""'""#.into(), - RepeatKind::Char('"') => r#""\"""#.into(), - RepeatKind::Char(_) => - match snippet_with_applicability(cx, repeat_arg.span, "..", &mut app) { - Cow::Owned(s) => Cow::Owned(format!("\"{}\"", &s[1..s.len() - 1])), - s @ Cow::Borrowed(_) => s, - }, - RepeatKind::String => - Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app).maybe_par().to_string().into(), - }; + let val_str = match repeat_kind { + RepeatKind::Char(_) if repeat_arg.span.ctxt() != ctxt => return, + RepeatKind::Char('\'') => r#""'""#.into(), + RepeatKind::Char('"') => r#""\"""#.into(), + RepeatKind::Char(_) => match snippet_with_applicability(cx, repeat_arg.span, "..", &mut app) { + Cow::Owned(s) => Cow::Owned(format!("\"{}\"", &s[1..s.len() - 1])), + s @ Cow::Borrowed(_) => s, + }, + RepeatKind::String => Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app) + .maybe_par() + .to_string() + .into(), + }; - span_lint_and_sugg( - cx, - MANUAL_STR_REPEAT, - collect_expr.span, - "manual implementation of `str::repeat` using iterators", - "try", - format!("{val_str}.repeat({count_snip})"), - app - ) - } + span_lint_and_sugg( + cx, + MANUAL_STR_REPEAT, + collect_expr.span, + "manual implementation of `str::repeat` using iterators", + "try", + format!("{val_str}.repeat({count_snip})"), + app, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs index 51145afda7f47..f93edded729fc 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs @@ -1,14 +1,14 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_from_proc_macro; use clippy_utils::source::snippet_opt; use clippy_utils::ty::implements_trait; +use clippy_utils::{is_from_proc_macro, is_trait_method}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_span::Span; +use rustc_span::{sym, Span}; use super::MANUAL_TRY_FOLD; @@ -22,6 +22,7 @@ pub(super) fn check<'tcx>( ) { if !in_external_macro(cx.sess(), fold_span) && msrv.meets(msrvs::ITERATOR_TRY_FOLD) + && is_trait_method(cx, expr, sym::Iterator) && let init_ty = cx.typeck_results().expr_ty(init) && let Some(try_trait) = cx.tcx.lang_items().try_trait() && implements_trait(cx, init_ty, try_trait, &[]) diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs index e0f8cb1b955fe..cc6eeaa86e5a3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_copy, is_type_diagnostic_item}; use clippy_utils::{is_diag_trait_item, peel_blocks}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -16,57 +15,55 @@ use rustc_span::{sym, Span}; use super::MAP_CLONE; pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, msrv: &Msrv) { - if_chain! { - if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id); - if cx.tcx.impl_of_method(method_id) - .map_or(false, |id| is_type_diagnostic_item(cx, cx.tcx.type_of(id).instantiate_identity(), sym::Option)) - || is_diag_trait_item(cx, method_id, sym::Iterator); - if let hir::ExprKind::Closure(&hir::Closure{ body, .. }) = arg.kind; - then { - let closure_body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(closure_body.value); - match closure_body.params[0].pat.kind { - hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding( - hir::BindingAnnotation::NONE, .., name, None - ) = inner.kind { + if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) + && (cx.tcx.impl_of_method(method_id).map_or(false, |id| { + is_type_diagnostic_item(cx, cx.tcx.type_of(id).instantiate_identity(), sym::Option) + }) || is_diag_trait_item(cx, method_id, sym::Iterator)) + && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind + { + let closure_body = cx.tcx.hir().body(body); + let closure_expr = peel_blocks(closure_body.value); + match closure_body.params[0].pat.kind { + hir::PatKind::Ref(inner, hir::Mutability::Not) => { + if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) = inner.kind { if ident_eq(name, closure_expr) { lint_explicit_closure(cx, e.span, recv.span, true, msrv); } - }, - hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) => { - match closure_expr.kind { - hir::ExprKind::Unary(hir::UnOp::Deref, inner) => { - if ident_eq(name, inner) { - if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() { - lint_explicit_closure(cx, e.span, recv.span, true, msrv); - } + } + }, + hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) => { + match closure_expr.kind { + hir::ExprKind::Unary(hir::UnOp::Deref, inner) => { + if ident_eq(name, inner) { + if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() { + lint_explicit_closure(cx, e.span, recv.span, true, msrv); } - }, - hir::ExprKind::MethodCall(method, obj, [], _) => if_chain! { - if ident_eq(name, obj) && method.ident.name == sym::clone; - if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id); - if let Some(trait_id) = cx.tcx.trait_of_item(fn_id); - if cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id); - // no autoderefs - if !cx.typeck_results().expr_adjustments(obj).iter() - .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))); - then { - let obj_ty = cx.typeck_results().expr_ty(obj); - if let ty::Ref(_, ty, mutability) = obj_ty.kind() { - if matches!(mutability, Mutability::Not) { - let copy = is_copy(cx, *ty); - lint_explicit_closure(cx, e.span, recv.span, copy, msrv); - } - } else { - lint_needless_cloning(cx, e.span, recv.span); + } + }, + hir::ExprKind::MethodCall(method, obj, [], _) => { + if ident_eq(name, obj) && method.ident.name == sym::clone + && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id) + && let Some(trait_id) = cx.tcx.trait_of_item(fn_id) + && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id) + // no autoderefs + && !cx.typeck_results().expr_adjustments(obj).iter() + .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) + { + let obj_ty = cx.typeck_results().expr_ty(obj); + if let ty::Ref(_, ty, mutability) = obj_ty.kind() { + if matches!(mutability, Mutability::Not) { + let copy = is_copy(cx, *ty); + lint_explicit_closure(cx, e.span, recv.span, copy, msrv); } + } else { + lint_needless_cloning(cx, e.span, recv.span); } - }, - _ => {}, - } - }, - _ => {}, - } + } + }, + _ => {}, + } + }, + _ => {}, } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs index 01cdd02e602de..e944eac91e7ae 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -13,26 +12,24 @@ use super::MAP_COLLECT_RESULT_UNIT; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, iter: &hir::Expr<'_>, map_fn: &hir::Expr<'_>) { // return of collect `Result<(),_>` let collect_ret_ty = cx.typeck_results().expr_ty(expr); - if_chain! { - if is_type_diagnostic_item(cx, collect_ret_ty, sym::Result); - if let ty::Adt(_, args) = collect_ret_ty.kind(); - if let Some(result_t) = args.types().next(); - if result_t.is_unit(); - // get parts for snippet - then { - span_lint_and_sugg( - cx, - MAP_COLLECT_RESULT_UNIT, - expr.span, - "`.map().collect()` can be replaced with `.try_for_each()`", - "try", - format!( - "{}.try_for_each({})", - snippet(cx, iter.span, ".."), - snippet(cx, map_fn.span, "..") - ), - Applicability::MachineApplicable, - ); - } + if is_type_diagnostic_item(cx, collect_ret_ty, sym::Result) + && let ty::Adt(_, args) = collect_ret_ty.kind() + && let Some(result_t) = args.types().next() + && result_t.is_unit() + // get parts for snippet + { + span_lint_and_sugg( + cx, + MAP_COLLECT_RESULT_UNIT, + expr.span, + "`.map().collect()` can be replaced with `.try_for_each()`", + "try", + format!( + "{}.try_for_each({})", + snippet(cx, iter.span, ".."), + snippet(cx, map_fn.span, "..") + ), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs index e74a764551c13..26ef0d10fed49 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs @@ -63,7 +63,7 @@ fn is_map_to_option(cx: &LateContext<'_>, map_arg: &Expr<'_>) -> bool { ty::Closure(_, args) => args.as_closure().sig(), _ => map_closure_ty.fn_sig(cx.tcx), }; - let map_closure_return_ty = cx.tcx.erase_late_bound_regions(map_closure_sig.output()); + let map_closure_return_ty = cx.tcx.instantiate_bound_regions_with_erased(map_closure_sig.output()); is_type_diagnostic_item(cx, map_closure_return_ty, sym::Option) }, _ => false, diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs index bcfd0de8efe1f..6da9a87f5eece 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs @@ -18,22 +18,20 @@ pub(super) fn check( ) { let caller_ty = cx.typeck_results().expr_ty(caller); - if_chain! { - if is_trait_method(cx, expr, sym::Iterator) - || is_type_diagnostic_item(cx, caller_ty, sym::Result) - || is_type_diagnostic_item(cx, caller_ty, sym::Option); - if is_expr_untyped_identity_function(cx, map_arg); - if let Some(sugg_span) = expr.span.trim_start(caller.span); - then { - span_lint_and_sugg( - cx, - MAP_IDENTITY, - sugg_span, - "unnecessary map of the identity function", - &format!("remove the call to `{name}`"), - String::new(), - Applicability::MachineApplicable, - ) - } + if (is_trait_method(cx, expr, sym::Iterator) + || is_type_diagnostic_item(cx, caller_ty, sym::Result) + || is_type_diagnostic_item(cx, caller_ty, sym::Option)) + && is_expr_untyped_identity_function(cx, map_arg) + && let Some(sugg_span) = expr.span.trim_start(caller.span) + { + span_lint_and_sugg( + cx, + MAP_IDENTITY, + sugg_span, + "unnecessary map of the identity function", + &format!("remove the call to `{name}`"), + String::new(), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs index cb81b3919bfd2..52ea584a2c8cb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs @@ -44,11 +44,9 @@ pub(super) fn check<'tcx>( // lint message let msg = if is_option { - "called `map().unwrap_or_else()` on an `Option` value. This can be done more directly by calling \ - `map_or_else(, )` instead" + "called `map().unwrap_or_else()` on an `Option` value" } else { - "called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling \ - `.map_or_else(, )` instead" + "called `map().unwrap_or_else()` on a `Result` value" }; // get snippets for args to map() and unwrap_or_else() let map_snippet = snippet(cx, map_arg.span, ".."); diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index a71a136eba574..25c681bb9d966 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -49,6 +49,7 @@ mod iter_skip_next; mod iter_skip_zero; mod iter_with_drain; mod iterator_step_by_zero; +mod join_absolute_paths; mod manual_next_back; mod manual_ok_or; mod manual_saturating_arithmetic; @@ -69,6 +70,7 @@ mod obfuscated_if_else; mod ok_expect; mod open_options; mod option_as_ref_deref; +mod option_map_or_err_ok; mod option_map_or_none; mod option_map_unwrap_or; mod or_fun_call; @@ -80,6 +82,7 @@ mod read_line_without_trim; mod readonly_write_lock; mod redundant_as_str; mod repeat_once; +mod result_map_or_else_none; mod search_is_some; mod seek_from_current; mod seek_to_start_instead_of_rewind; @@ -123,7 +126,6 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty}; -use if_chain::if_chain; pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; @@ -131,7 +133,7 @@ use rustc_hir::{Expr, ExprKind, Node, Stmt, StmtKind, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, TraitRef, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -3610,7 +3612,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `as_str()` on a `String`` chained with a method available on the `String` itself. + /// Checks for usage of `as_str()` on a `String` chained with a method available on the `String` itself. /// /// ### Why is this bad? /// The `as_str()` conversion is pointless and can be removed for simplicity and cleanliness. @@ -3619,14 +3621,16 @@ declare_clippy_lint! { /// ```no_run /// # #![allow(unused)] /// let owned_string = "This is a string".to_owned(); - /// owned_string.as_str().as_bytes(); + /// owned_string.as_str().as_bytes() + /// # ; /// ``` /// /// Use instead: /// ```no_run /// # #![allow(unused)] /// let owned_string = "This is a string".to_owned(); - /// owned_string.as_bytes(); + /// owned_string.as_bytes() + /// # ; /// ``` #[clippy::version = "1.74.0"] pub REDUNDANT_AS_STR, @@ -3683,6 +3687,71 @@ declare_clippy_lint! { "calling the `try_from` and `try_into` trait methods when `From`/`Into` is implemented" } +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to `Path::join` that start with a path separator (`\\` or `/`). + /// + /// ### Why is this bad? + /// If the argument to `Path::join` starts with a separator, it will overwrite + /// the original path. If this is intentional, prefer using `Path::new` instead. + /// + /// Note the behavior is platform dependent. A leading `\\` will be accepted + /// on unix systems as part of the file name + /// + /// See [`Path::join`](https://doc.rust-lang.org/std/path/struct.Path.html#method.join) + /// + /// ### Example + /// ```rust + /// # use std::path::{Path, PathBuf}; + /// let path = Path::new("/bin"); + /// let joined_path = path.join("/sh"); + /// assert_eq!(joined_path, PathBuf::from("/sh")); + /// ``` + /// + /// Use instead; + /// ```rust + /// # use std::path::{Path, PathBuf}; + /// let path = Path::new("/bin"); + /// + /// // If this was unintentional, remove the leading separator + /// let joined_path = path.join("sh"); + /// assert_eq!(joined_path, PathBuf::from("/bin/sh")); + /// + /// // If this was intentional, create a new path instead + /// let new = Path::new("/sh"); + /// assert_eq!(new, PathBuf::from("/sh")); + /// ``` + #[clippy::version = "1.76.0"] + pub JOIN_ABSOLUTE_PATHS, + suspicious, + "calls to `Path::join` which will overwrite the original path" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `_.map_or(Err(_), Ok)`. + /// + /// ### Why is this bad? + /// Readability, this can be written more concisely as + /// `_.ok_or(_)`. + /// + /// ### Example + /// ```no_run + /// # let opt = Some(1); + /// opt.map_or(Err("error"), Ok); + /// ``` + /// + /// Use instead: + /// ```no_run + /// # let opt = Some(1); + /// opt.ok_or("error"); + /// ``` + #[clippy::version = "1.76.0"] + pub OPTION_MAP_OR_ERR_OK, + style, + "using `Option.map_or(Err(_), Ok)`, which is more succinctly expressed as `Option.ok_or(_)`" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -3698,8 +3767,10 @@ impl Methods { msrv: Msrv, allow_expect_in_tests: bool, allow_unwrap_in_tests: bool, - allowed_dotfiles: FxHashSet, + mut allowed_dotfiles: FxHashSet, ) -> Self { + allowed_dotfiles.extend(DEFAULT_ALLOWED_DOTFILES.iter().map(ToString::to_string)); + Self { avoid_breaking_exported_api, msrv, @@ -3830,6 +3901,8 @@ impl_lint_pass!(Methods => [ REDUNDANT_AS_STR, WAKER_CLONE_WAKE, UNNECESSARY_FALLIBLE_CONVERSIONS, + JOIN_ABSOLUTE_PATHS, + OPTION_MAP_OR_ERR_OK, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -3896,7 +3969,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })); if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind { let method_sig = cx.tcx.fn_sig(impl_item.owner_id).instantiate_identity(); - let method_sig = cx.tcx.erase_late_bound_regions(method_sig); + let method_sig = cx.tcx.instantiate_bound_regions_with_erased(method_sig); let first_arg_ty_opt = method_sig.inputs().iter().next().copied(); // if this impl block implements a trait, lint in trait definition instead if !implements_trait && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) { @@ -3977,44 +4050,41 @@ impl<'tcx> LateLintPass<'tcx> for Methods { return; } - if_chain! { - if let TraitItemKind::Fn(ref sig, _) = item.kind; - if sig.decl.implicit_self.has_implicit_self(); - if let Some(first_arg_hir_ty) = sig.decl.inputs.first(); - if let Some(&first_arg_ty) = cx.tcx.fn_sig(item.owner_id) + if let TraitItemKind::Fn(ref sig, _) = item.kind + && sig.decl.implicit_self.has_implicit_self() + && let Some(first_arg_hir_ty) = sig.decl.inputs.first() + && let Some(&first_arg_ty) = cx + .tcx + .fn_sig(item.owner_id) .instantiate_identity() .inputs() .skip_binder() - .first(); - then { - let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty(); - wrong_self_convention::check( - cx, - item.ident.name.as_str(), - self_ty, - first_arg_ty, - first_arg_hir_ty.span, - false, - true, - ); - } - } - - if_chain! { - if item.ident.name == sym::new; - if let TraitItemKind::Fn(_, _) = item.kind; - let ret_ty = return_ty(cx, item.owner_id); + .first() + { let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty(); - if !ret_ty.contains(self_ty); + wrong_self_convention::check( + cx, + item.ident.name.as_str(), + self_ty, + first_arg_ty, + first_arg_hir_ty.span, + false, + true, + ); + } - then { - span_lint( - cx, - NEW_RET_NO_SELF, - item.span, - "methods called `new` usually return `Self`", - ); - } + if item.ident.name == sym::new + && let TraitItemKind::Fn(_, _) = item.kind + && let ret_ty = return_ty(cx, item.owner_id) + && let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()).self_ty() + && !ret_ty.contains(self_ty) + { + span_lint( + cx, + NEW_RET_NO_SELF, + item.span, + "methods called `new` usually return `Self`", + ); } } @@ -4235,6 +4305,8 @@ impl Methods { ("join", [join_arg]) => { if let Some(("collect", _, _, span, _)) = method_call(recv) { unnecessary_join::check(cx, expr, recv, join_arg, span); + } else { + join_absolute_paths::check(cx, recv, join_arg, expr.span); } }, ("last", []) => { @@ -4257,7 +4329,7 @@ impl Methods { map_clone::check(cx, expr, recv, m_arg, &self.msrv); match method_call(recv) { Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) => { - iter_kv_map::check(cx, map_name, expr, recv2, m_arg); + iter_kv_map::check(cx, map_name, expr, recv2, m_arg, &self.msrv); }, Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check( cx, @@ -4290,6 +4362,10 @@ impl Methods { ("map_or", [def, map]) => { option_map_or_none::check(cx, expr, recv, def, map); manual_ok_or::check(cx, expr, recv, def, map); + option_map_or_err_ok::check(cx, expr, recv, def, map); + }, + ("map_or_else", [def, map]) => { + result_map_or_else_none::check(cx, expr, recv, def, map); }, ("next", []) => { if let Some((name2, recv2, args2, _, _)) = method_call(recv) { diff --git a/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs b/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs index 2855e23bf5b6a..1a0fce2876d40 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::expr_custom_deref_adjustment; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; @@ -11,22 +10,20 @@ use rustc_span::{sym, Span}; use super::MUT_MUTEX_LOCK; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>, recv: &'tcx Expr<'tcx>, name_span: Span) { - if_chain! { - if matches!(expr_custom_deref_adjustment(cx, recv), None | Some(Mutability::Mut)); - if let ty::Ref(_, _, Mutability::Mut) = cx.typeck_results().expr_ty(recv).kind(); - if let Some(method_id) = cx.typeck_results().type_dependent_def_id(ex.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(method_id); - if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Mutex); - then { - span_lint_and_sugg( - cx, - MUT_MUTEX_LOCK, - name_span, - "calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference", - "change this to", - "get_mut".to_owned(), - Applicability::MaybeIncorrect, - ); - } + if matches!(expr_custom_deref_adjustment(cx, recv), None | Some(Mutability::Mut)) + && let ty::Ref(_, _, Mutability::Mut) = cx.typeck_results().expr_ty(recv).kind() + && let Some(method_id) = cx.typeck_results().type_dependent_def_id(ex.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(method_id) + && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Mutex) + { + span_lint_and_sugg( + cx, + MUT_MUTEX_LOCK, + name_span, + "calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference", + "change this to", + "get_mut".to_owned(), + Applicability::MaybeIncorrect, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 2ef71be3217f8..293b4981c5575 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -225,7 +225,10 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - && let sig = cx.tcx.fn_sig(id).instantiate_identity() && sig.skip_binder().output().is_bool() && let [_, search_ty] = *sig.skip_binder().inputs() - && let ty::Ref(_, search_ty, Mutability::Not) = *cx.tcx.erase_late_bound_regions(sig.rebind(search_ty)).kind() + && let ty::Ref(_, search_ty, Mutability::Not) = *cx + .tcx + .instantiate_bound_regions_with_erased(sig.rebind(search_ty)) + .kind() && let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) && let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_name_and_kind( cx.tcx, diff --git a/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs b/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs index 01655e860c43f..81df32bdee2bc 100644 --- a/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs +++ b/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::is_type_lang_item; use clippy_utils::SpanlessEq; -use if_chain::if_chain; use rustc_ast::LitKind; use rustc_hir::{ExprKind, LangItem}; use rustc_lint::LateContext; @@ -19,17 +18,13 @@ pub(super) fn check<'tcx>( return; } - if_chain! { - if let ExprKind::Lit(spanned) = &arg1.kind; - if let Some(param1) = lit_string_value(&spanned.node); - - if let ExprKind::Lit(spanned) = &arg2.kind; - if let LitKind::Str(param2, _) = &spanned.node; - if param1 == param2.as_str(); - - then { - span_lint(cx, NO_EFFECT_REPLACE, expr.span, "replacing text with itself"); - } + if let ExprKind::Lit(spanned) = &arg1.kind + && let Some(param1) = lit_string_value(&spanned.node) + && let ExprKind::Lit(spanned) = &arg2.kind + && let LitKind::Str(param2, _) = &spanned.node + && param1 == param2.as_str() + { + span_lint(cx, NO_EFFECT_REPLACE, expr.span, "replacing text with itself"); } if SpanlessEq::new(cx).eq_expr(arg1, arg2) { diff --git a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs index f2ef42933df62..e10bc0216e5fd 100644 --- a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item}; -use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; @@ -10,23 +9,20 @@ use super::OK_EXPECT; /// lint use of `ok().expect()` for `Result`s pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { - if_chain! { + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result) // lint if the caller of `ok()` is a `Result` - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); - let result_type = cx.typeck_results().expr_ty(recv); - if let Some(error_type) = get_error_type(cx, result_type); - if has_debug_impl(cx, error_type); - - then { - span_lint_and_help( - cx, - OK_EXPECT, - expr.span, - "called `ok().expect()` on a `Result` value", - None, - "you can call `expect()` directly on the `Result`", - ); - } + && let result_type = cx.typeck_results().expr_ty(recv) + && let Some(error_type) = get_error_type(cx, result_type) + && has_debug_impl(cx, error_type) + { + span_lint_and_help( + cx, + OK_EXPECT, + expr.span, + "called `ok().expect()` on a `Result` value", + None, + "you can call `expect()` directly on the `Result`", + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs index 7b81d4571b244..756dbe62d84d6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -58,34 +57,30 @@ pub(super) fn check( match &closure_expr.kind { hir::ExprKind::MethodCall(_, receiver, [], _) => { - if_chain! { - if path_to_local_id(receiver, closure_body.params[0].pat.hir_id); - let adj = cx + if path_to_local_id(receiver, closure_body.params[0].pat.hir_id) + && let adj = cx .typeck_results() .expr_adjustments(receiver) .iter() .map(|x| &x.kind) - .collect::>(); - if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj; - then { - let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap(); - cx.tcx.is_diagnostic_item(sym::deref_method, method_did) - || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did) - || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path)) - } else { - false - } + .collect::>() + && let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj + { + let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap(); + cx.tcx.is_diagnostic_item(sym::deref_method, method_did) + || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did) + || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path)) + } else { + false } }, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, inner) if same_mutability(m) => { - if_chain! { - if let hir::ExprKind::Unary(hir::UnOp::Deref, inner1) = inner.kind; - if let hir::ExprKind::Unary(hir::UnOp::Deref, inner2) = inner1.kind; - then { - path_to_local_id(inner2, closure_body.params[0].pat.hir_id) - } else { - false - } + if let hir::ExprKind::Unary(hir::UnOp::Deref, inner1) = inner.kind + && let hir::ExprKind::Unary(hir::UnOp::Deref, inner2) = inner1.kind + { + path_to_local_id(inner2, closure_body.params[0].pat.hir_id) + } else { + false } }, _ => false, @@ -104,10 +99,7 @@ pub(super) fn check( let hint = format!("{}.{method_hint}()", snippet(cx, as_ref_recv.span, "..")); let suggestion = format!("try using {method_hint} instead"); - let msg = format!( - "called `{current_method}` on an Option value. This can be done more directly \ - by calling `{hint}` instead" - ); + let msg = format!("called `{current_method}` on an `Option` value"); span_lint_and_sugg( cx, OPTION_AS_REF_DEREF, diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_err_ok.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_err_ok.rs new file mode 100644 index 0000000000000..91e39d5a1cd27 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_err_ok.rs @@ -0,0 +1,41 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_res_lang_ctor, path_res}; +use rustc_errors::Applicability; +use rustc_hir::LangItem::{ResultErr, ResultOk}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; + +use super::OPTION_MAP_OR_ERR_OK; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + recv: &'tcx Expr<'_>, + or_expr: &'tcx Expr<'_>, + map_expr: &'tcx Expr<'_>, +) { + // We check that it's called on an `Option` type. + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) + // We check that first we pass an `Err`. + && let ExprKind::Call(call, &[arg]) = or_expr.kind + && is_res_lang_ctor(cx, path_res(cx, call), ResultErr) + // And finally we check that it is mapped as `Ok`. + && is_res_lang_ctor(cx, path_res(cx, map_expr), ResultOk) + { + let msg = "called `map_or(Err(_), Ok)` on an `Option` value"; + let self_snippet = snippet(cx, recv.span, ".."); + let err_snippet = snippet(cx, arg.span, ".."); + span_lint_and_sugg( + cx, + OPTION_MAP_OR_ERR_OK, + expr.span, + msg, + "try using `ok_or` instead", + format!("{self_snippet}.ok_or({err_snippet})"), + Applicability::MachineApplicable, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs index cb6a2306857d7..ff4d8cc9e3e1a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs @@ -58,32 +58,28 @@ pub(super) fn check<'tcx>( if is_option { let self_snippet = snippet(cx, recv.span, ".."); - if_chain! { - if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = map_arg.kind; - let arg_snippet = snippet(cx, fn_decl_span, ".."); - let body = cx.tcx.hir().body(body); - if let Some((func, [arg_char])) = reduce_unit_expression(body.value); - if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id)); - if Some(id) == cx.tcx.lang_items().option_some_variant(); - then { - let func_snippet = snippet(cx, arg_char.span, ".."); - let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \ - `map(..)` instead"; - return span_lint_and_sugg( - cx, - OPTION_MAP_OR_NONE, - expr.span, - msg, - "try using `map` instead", - format!("{self_snippet}.map({arg_snippet} {func_snippet})"), - Applicability::MachineApplicable, - ); - } + if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = map_arg.kind + && let arg_snippet = snippet(cx, fn_decl_span, "..") + && let body = cx.tcx.hir().body(body) + && let Some((func, [arg_char])) = reduce_unit_expression(body.value) + && let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id)) + && Some(id) == cx.tcx.lang_items().option_some_variant() + { + let func_snippet = snippet(cx, arg_char.span, ".."); + let msg = "called `map_or(None, ..)` on an `Option` value"; + return span_lint_and_sugg( + cx, + OPTION_MAP_OR_NONE, + expr.span, + msg, + "try using `map` instead", + format!("{self_snippet}.map({arg_snippet} {func_snippet})"), + Applicability::MachineApplicable, + ); } let func_snippet = snippet(cx, map_arg.span, ".."); - let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \ - `and_then(..)` instead"; + let msg = "called `map_or(None, ..)` on an `Option` value"; span_lint_and_sugg( cx, OPTION_MAP_OR_NONE, @@ -94,8 +90,7 @@ pub(super) fn check<'tcx>( Applicability::MachineApplicable, ); } else if f_arg_is_some { - let msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \ - `ok()` instead"; + let msg = "called `map_or(None, Some)` on a `Result` value"; let self_snippet = snippet(cx, recv.span, ".."); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index c78f8b71c789d..575c2d8f1575a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -97,10 +97,7 @@ pub(super) fn check<'tcx>( } else { "map_or(, )" }; - let msg = &format!( - "called `map().unwrap_or({arg})` on an `Option` value. \ - This can be done more directly by calling `{suggest}` instead" - ); + let msg = &format!("called `map().unwrap_or({arg})` on an `Option` value"); span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| { let map_arg_span = map_arg.span; diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index b89c151461cf6..e38c66f6741d2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -3,12 +3,11 @@ use clippy_utils::eager_or_lazy::switch_to_lazy_eval; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{expr_type_is_certain, implements_trait, is_type_diagnostic_item}; use clippy_utils::{contains_return, is_default_equivalent, is_default_equivalent_call, last_path_segment}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_span::Span; use rustc_span::symbol::{self, sym, Symbol}; +use rustc_span::Span; use {rustc_ast as ast, rustc_hir as hir}; use super::{OR_FUN_CALL, UNWRAP_OR_DEFAULT}; @@ -131,54 +130,47 @@ pub(super) fn check<'tcx>( (sym::Result, true, &["or", "unwrap_or"], "else"), ]; - if_chain! { - if KNOW_TYPES.iter().any(|k| k.2.contains(&name)); - - if switch_to_lazy_eval(cx, arg); - if !contains_return(arg); - - let self_ty = cx.typeck_results().expr_ty(self_expr); - - if let Some(&(_, fn_has_arguments, poss, suffix)) = - KNOW_TYPES.iter().find(|&&i| is_type_diagnostic_item(cx, self_ty, i.0)); - - if poss.contains(&name); - - then { - let ctxt = span.ctxt(); - let mut app = Applicability::HasPlaceholders; - let sugg = { - let (snippet_span, use_lambda) = match (fn_has_arguments, fun_span) { - (false, Some(fun_span)) => (fun_span, false), - _ => (arg.span, true), - }; - - let snip = snippet_with_context(cx, snippet_span, ctxt, "..", &mut app).0; - let snip = if use_lambda { - let l_arg = if fn_has_arguments { "_" } else { "" }; - format!("|{l_arg}| {snip}") - } else { - snip.into_owned() - }; - - if let Some(f) = second_arg { - let f = snippet_with_context(cx, f.span, ctxt, "..", &mut app).0; - format!("{snip}, {f}") - } else { - snip - } + if KNOW_TYPES.iter().any(|k| k.2.contains(&name)) + && switch_to_lazy_eval(cx, arg) + && !contains_return(arg) + && let self_ty = cx.typeck_results().expr_ty(self_expr) + && let Some(&(_, fn_has_arguments, poss, suffix)) = + KNOW_TYPES.iter().find(|&&i| is_type_diagnostic_item(cx, self_ty, i.0)) + && poss.contains(&name) + { + let ctxt = span.ctxt(); + let mut app = Applicability::HasPlaceholders; + let sugg = { + let (snippet_span, use_lambda) = match (fn_has_arguments, fun_span) { + (false, Some(fun_span)) => (fun_span, false), + _ => (arg.span, true), + }; + + let snip = snippet_with_context(cx, snippet_span, ctxt, "..", &mut app).0; + let snip = if use_lambda { + let l_arg = if fn_has_arguments { "_" } else { "" }; + format!("|{l_arg}| {snip}") + } else { + snip.into_owned() }; - let span_replace_word = method_span.with_hi(span.hi()); - span_lint_and_sugg( - cx, - OR_FUN_CALL, - span_replace_word, - &format!("use of `{name}` followed by a function call"), - "try", - format!("{name}_{suffix}({sugg})"), - app, - ); - } + + if let Some(f) = second_arg { + let f = snippet_with_context(cx, f.span, ctxt, "..", &mut app).0; + format!("{snip}, {f}") + } else { + snip + } + }; + let span_replace_word = method_span.with_hi(span.hi()); + span_lint_and_sugg( + cx, + OR_FUN_CALL, + span_replace_word, + &format!("use of `{name}` followed by a function call"), + "try", + format!("{name}_{suffix}({sugg})"), + app, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs index 1c07d2a3a59c2..04a27cc98f3c3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs +++ b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; @@ -11,27 +10,25 @@ use std::path::{Component, Path}; use super::PATH_BUF_PUSH_OVERWRITE; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) { - if_chain! { - if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(method_id); - if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::PathBuf); - if let ExprKind::Lit(lit) = arg.kind; - if let LitKind::Str(ref path_lit, _) = lit.node; - if let pushed_path = Path::new(path_lit.as_str()); - if let Some(pushed_path_lit) = pushed_path.to_str(); - if pushed_path.has_root(); - if let Some(root) = pushed_path.components().next(); - if root == Component::RootDir; - then { - span_lint_and_sugg( - cx, - PATH_BUF_PUSH_OVERWRITE, - lit.span, - "calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition", - "try", - format!("\"{}\"", pushed_path_lit.trim_start_matches(|c| c == '/' || c == '\\')), - Applicability::MachineApplicable, - ); - } + if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(method_id) + && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::PathBuf) + && let ExprKind::Lit(lit) = arg.kind + && let LitKind::Str(ref path_lit, _) = lit.node + && let pushed_path = Path::new(path_lit.as_str()) + && let Some(pushed_path_lit) = pushed_path.to_str() + && pushed_path.has_root() + && let Some(root) = pushed_path.components().next() + && root == Component::RootDir + { + span_lint_and_sugg( + cx, + PATH_BUF_PUSH_OVERWRITE, + lit.span, + "calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition", + "try", + format!("\"{}\"", pushed_path_lit.trim_start_matches(|c| c == '/' || c == '\\')), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs b/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs index f253d8de91f9e..1148628b0844b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs +++ b/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::source::snippet; use clippy_utils::{higher, is_integer_const, is_trait_method, SpanlessEq}; -use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; use rustc_span::sym; @@ -9,25 +8,26 @@ use rustc_span::sym; use super::RANGE_ZIP_WITH_LEN; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, zip_arg: &'tcx Expr<'_>) { - if_chain! { - if is_trait_method(cx, expr, sym::Iterator); + if is_trait_method(cx, expr, sym::Iterator) // range expression in `.zip()` call: `0..x.len()` - if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg); - if is_integer_const(cx, start, 0); + && let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::Range::hir(zip_arg) + && is_integer_const(cx, start, 0) // `.len()` call - if let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind; - if len_path.ident.name == sym::len; + && let ExprKind::MethodCall(len_path, len_recv, [], _) = end.kind + && len_path.ident.name == sym::len // `.iter()` and `.len()` called on same `Path` - if let ExprKind::Path(QPath::Resolved(_, iter_path)) = recv.kind; - if let ExprKind::Path(QPath::Resolved(_, len_path)) = len_recv.kind; - if SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments); - then { - span_lint(cx, - RANGE_ZIP_WITH_LEN, - expr.span, - &format!("it is more idiomatic to use `{}.iter().enumerate()`", - snippet(cx, recv.span, "_")) - ); - } + && let ExprKind::Path(QPath::Resolved(_, iter_path)) = recv.kind + && let ExprKind::Path(QPath::Resolved(_, len_path)) = len_recv.kind + && SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments) + { + span_lint( + cx, + RANGE_ZIP_WITH_LEN, + expr.span, + &format!( + "it is more idiomatic to use `{}.iter().enumerate()`", + snippet(cx, recv.span, "_") + ), + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs b/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs new file mode 100644 index 0000000000000..bc16a11281620 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs @@ -0,0 +1,42 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::LangItem::{OptionNone, OptionSome}; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; + +use super::RESULT_MAP_OR_INTO_OPTION; + +/// lint use of `_.map_or_else(|_| None, Some)` for `Result`s +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + recv: &'tcx hir::Expr<'_>, + def_arg: &'tcx hir::Expr<'_>, + map_arg: &'tcx hir::Expr<'_>, +) { + // lint if the caller of `map_or_else()` is a `Result` + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result) + // We check that it is mapped as `Some`. + && is_res_lang_ctor(cx, path_res(cx, map_arg), OptionSome) + && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = def_arg.kind + && let body = cx.tcx.hir().body(body) + // And finally we check that we return a `None` in the "else case". + && is_res_lang_ctor(cx, path_res(cx, peel_blocks(body.value)), OptionNone) + { + let msg = "called `map_or_else(|_| None, Some)` on a `Result` value"; + let self_snippet = snippet(cx, recv.span, ".."); + span_lint_and_sugg( + cx, + RESULT_MAP_OR_INTO_OPTION, + expr.span, + msg, + "try using `ok` instead", + format!("{self_snippet}.ok()"), + Applicability::MachineApplicable, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs index 05a9a06c8c7d5..6339011c92f58 100644 --- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs @@ -3,13 +3,12 @@ use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::deref_closure_args; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{is_trait_method, strip_pat_refs}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::PatKind; use rustc_lint::LateContext; -use rustc_span::Span; use rustc_span::symbol::sym; +use rustc_span::Span; use super::SEARCH_IS_SOME; @@ -35,29 +34,27 @@ pub(super) fn check<'tcx>( // suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()` // suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()` let mut applicability = Applicability::MachineApplicable; - let any_search_snippet = if_chain! { - if search_method == "find"; - if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind; - let closure_body = cx.tcx.hir().body(body); - if let Some(closure_arg) = closure_body.params.first(); - then { - if let hir::PatKind::Ref(..) = closure_arg.pat.kind { - Some(search_snippet.replacen('&', "", 1)) - } else if let PatKind::Binding(..) = strip_pat_refs(closure_arg.pat).kind { - // `find()` provides a reference to the item, but `any` does not, - // so we should fix item usages for suggestion - if let Some(closure_sugg) = deref_closure_args(cx, search_arg) { - applicability = closure_sugg.applicability; - Some(closure_sugg.suggestion) - } else { - Some(search_snippet.to_string()) - } + let any_search_snippet = if search_method == "find" + && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind + && let closure_body = cx.tcx.hir().body(body) + && let Some(closure_arg) = closure_body.params.first() + { + if let hir::PatKind::Ref(..) = closure_arg.pat.kind { + Some(search_snippet.replacen('&', "", 1)) + } else if let PatKind::Binding(..) = strip_pat_refs(closure_arg.pat).kind { + // `find()` provides a reference to the item, but `any` does not, + // so we should fix item usages for suggestion + if let Some(closure_sugg) = deref_closure_args(cx, search_arg) { + applicability = closure_sugg.applicability; + Some(closure_sugg.suggestion) } else { - None + Some(search_snippet.to_string()) } } else { None } + } else { + None }; // add note if not multi-line if is_some { @@ -110,41 +107,37 @@ pub(super) fn check<'tcx>( self_ty.is_str() } }; - if_chain! { - if is_string_or_str_slice(search_recv); - if is_string_or_str_slice(search_arg); - then { - let msg = format!("called `{option_check_method}()` after calling `find()` on a string"); - match option_check_method { - "is_some" => { - let mut applicability = Applicability::MachineApplicable; - let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability); - span_lint_and_sugg( - cx, - SEARCH_IS_SOME, - method_span.with_hi(expr.span.hi()), - &msg, - "use `contains()` instead", - format!("contains({find_arg})"), - applicability, - ); - }, - "is_none" => { - let string = snippet(cx, search_recv.span, ".."); - let mut applicability = Applicability::MachineApplicable; - let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability); - span_lint_and_sugg( - cx, - SEARCH_IS_SOME, - expr.span, - &msg, - "use `!_.contains()` instead", - format!("!{string}.contains({find_arg})"), - applicability, - ); - }, - _ => (), - } + if is_string_or_str_slice(search_recv) && is_string_or_str_slice(search_arg) { + let msg = format!("called `{option_check_method}()` after calling `find()` on a string"); + match option_check_method { + "is_some" => { + let mut applicability = Applicability::MachineApplicable; + let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability); + span_lint_and_sugg( + cx, + SEARCH_IS_SOME, + method_span.with_hi(expr.span.hi()), + &msg, + "use `contains()` instead", + format!("contains({find_arg})"), + applicability, + ); + }, + "is_none" => { + let string = snippet(cx, search_recv.span, ".."); + let mut applicability = Applicability::MachineApplicable; + let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability); + span_lint_and_sugg( + cx, + SEARCH_IS_SOME, + expr.span, + &msg, + "use `!_.contains()` instead", + format!("!{string}.contains({find_arg})"), + applicability, + ); + }, + _ => (), } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs index 4d704ec39ebb1..3983f0c0cabd4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs @@ -1,6 +1,5 @@ use super::utils::get_hint_if_single_char_arg; use clippy_utils::diagnostics::span_lint_and_sugg; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -45,24 +44,23 @@ pub(super) fn check( args: &[hir::Expr<'_>], ) { for &(method, pos) in &PATTERN_METHODS { - if_chain! { - if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind(); - if ty.is_str(); - if method_name.as_str() == method && args.len() > pos; - let arg = &args[pos]; - let mut applicability = Applicability::MachineApplicable; - if let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability); - then { - span_lint_and_sugg( - cx, - SINGLE_CHAR_PATTERN, - arg.span, - "single-character string constant used as pattern", - "try using a `char` instead", - hint, - applicability, - ); - } + if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind() + && ty.is_str() + && method_name.as_str() == method + && args.len() > pos + && let arg = &args[pos] + && let mut applicability = Applicability::MachineApplicable + && let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability) + { + span_lint_and_sugg( + cx, + SINGLE_CHAR_PATTERN, + arg.span, + "single-character string constant used as pattern", + "try using a `char` instead", + hint, + applicability, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 9da61bca52c86..0e7ad8fc996e5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -6,7 +6,6 @@ use clippy_utils::usage::local_used_after_expr; use clippy_utils::visitors::{for_each_expr_with_closures, Descend}; use clippy_utils::{is_diag_item_method, match_def_path, path_to_local_id, paths}; use core::ops::ControlFlow; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ BindingAnnotation, Expr, ExprKind, HirId, LangItem, Local, MatchSource, Node, Pat, PatKind, QPath, Stmt, StmtKind, @@ -286,41 +285,35 @@ fn parse_iter_usage<'tcx>( match (name.ident.as_str(), args) { ("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => (IterUsageKind::Nth(0), e.span), ("next_tuple", []) => { - return if_chain! { - if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE); - if let ty::Adt(adt_def, subs) = cx.typeck_results().expr_ty(e).kind(); - if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did()); - if let ty::Tuple(subs) = subs.type_at(0).kind(); - if subs.len() == 2; - then { - Some(IterUsage { - kind: IterUsageKind::NextTuple, - span: e.span, - unwrap_kind: None - }) - } else { - None - } + return if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE) + && let ty::Adt(adt_def, subs) = cx.typeck_results().expr_ty(e).kind() + && cx.tcx.is_diagnostic_item(sym::Option, adt_def.did()) + && let ty::Tuple(subs) = subs.type_at(0).kind() + && subs.len() == 2 + { + Some(IterUsage { + kind: IterUsageKind::NextTuple, + span: e.span, + unwrap_kind: None, + }) + } else { + None }; }, ("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => { if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) { let span = if name.ident.as_str() == "nth" { e.span + } else if let Some((_, Node::Expr(next_expr))) = iter.next() + && let ExprKind::MethodCall(next_name, _, [], _) = next_expr.kind + && next_name.ident.name == sym::next + && next_expr.span.ctxt() == ctxt + && let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id) + && cx.tcx.trait_of_item(next_id) == Some(iter_id) + { + next_expr.span } else { - if_chain! { - if let Some((_, Node::Expr(next_expr))) = iter.next(); - if let ExprKind::MethodCall(next_name, _, [], _) = next_expr.kind; - if next_name.ident.name == sym::next; - if next_expr.span.ctxt() == ctxt; - if let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id); - if cx.tcx.trait_of_item(next_id) == Some(iter_id); - then { - next_expr.span - } else { - return None; - } - } + return None; }; (IterUsageKind::Nth(idx), span) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs index 0dc7fe2a2c5a3..ed49233acb7f0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::usage::mutated_variables; use clippy_utils::{expr_or_init, is_trait_method}; -use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::sym; @@ -9,26 +8,24 @@ use rustc_span::sym; use super::SUSPICIOUS_MAP; pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) { - if_chain! { - if is_trait_method(cx, count_recv, sym::Iterator); - if let hir::ExprKind::Closure(closure) = expr_or_init(cx, map_arg).kind; - let closure_body = cx.tcx.hir().body(closure.body); - if !cx.typeck_results().expr_ty(closure_body.value).is_unit(); - then { - if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) { - // A variable is used mutably inside of the closure. Suppress the lint. - if !map_mutated_vars.is_empty() { - return; - } + if is_trait_method(cx, count_recv, sym::Iterator) + && let hir::ExprKind::Closure(closure) = expr_or_init(cx, map_arg).kind + && let closure_body = cx.tcx.hir().body(closure.body) + && !cx.typeck_results().expr_ty(closure_body.value).is_unit() + { + if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) { + // A variable is used mutably inside of the closure. Suppress the lint. + if !map_mutated_vars.is_empty() { + return; } - span_lint_and_help( - cx, - SUSPICIOUS_MAP, - expr.span, - "this call to `map()` won't have an effect on the call to `count()`", - None, - "make sure you did not confuse `map` with `filter`, `for_each` or `inspect`", - ); } + span_lint_and_help( + cx, + SUSPICIOUS_MAP, + expr.span, + "this call to `map()` won't have an effect on the call to `count()`", + None, + "make sure you did not confuse `map` with `filter`, `for_each` or `inspect`", + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs index 3cb2719e4a032..c45212581eedb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs @@ -1,5 +1,4 @@ use clippy_utils::diagnostics::span_lint_and_note; -use if_chain::if_chain; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -8,41 +7,36 @@ use rustc_span::source_map::Spanned; use super::SUSPICIOUS_SPLITN; pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_arg: &Expr<'_>, count: u128) { - if_chain! { - if count <= 1; - if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(call_id); - if cx.tcx.impl_trait_ref(impl_id).is_none(); - let self_ty = cx.tcx.type_of(impl_id).instantiate_identity(); - if self_ty.is_slice() || self_ty.is_str(); - then { - // Ignore empty slice and string literals when used with a literal count. - if matches!(self_arg.kind, ExprKind::Array([])) - || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty()) - { - return; - } + if count <= 1 + && let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(call_id) + && cx.tcx.impl_trait_ref(impl_id).is_none() + && let self_ty = cx.tcx.type_of(impl_id).instantiate_identity() + && (self_ty.is_slice() || self_ty.is_str()) + { + // Ignore empty slice and string literals when used with a literal count. + if matches!(self_arg.kind, ExprKind::Array([])) + || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty()) + { + return; + } - let (msg, note_msg) = if count == 0 { - (format!("`{method_name}` called with `0` splits"), - "the resulting iterator will always return `None`") - } else { - (format!("`{method_name}` called with `1` split"), + let (msg, note_msg) = if count == 0 { + ( + format!("`{method_name}` called with `0` splits"), + "the resulting iterator will always return `None`", + ) + } else { + ( + format!("`{method_name}` called with `1` split"), if self_ty.is_slice() { "the resulting iterator will always return the entire slice followed by `None`" } else { "the resulting iterator will always return the entire string followed by `None`" - }) - }; + }, + ) + }; - span_lint_and_note( - cx, - SUSPICIOUS_SPLITN, - expr.span, - &msg, - None, - note_msg, - ); - } + span_lint_and_note(cx, SUSPICIOUS_SPLITN, expr.span, &msg, None, note_msg); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs index 9eb8d6e6e787d..60864902a4890 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_diag_trait_item; use clippy_utils::source::snippet_with_context; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -12,40 +11,37 @@ use rustc_span::sym; use super::SUSPICIOUS_TO_OWNED; pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -> bool { - if_chain! { - if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if is_diag_trait_item(cx, method_def_id, sym::ToOwned); - let input_type = cx.typeck_results().expr_ty(expr); - if let ty::Adt(adt, _) = cx.typeck_results().expr_ty(expr).kind(); - if cx.tcx.is_diagnostic_item(sym::Cow, adt.did()); - - then { - let mut app = Applicability::MaybeIncorrect; - let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0; - span_lint_and_then( - cx, - SUSPICIOUS_TO_OWNED, - expr.span, - &with_forced_trimmed_paths!(format!( - "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned" - )), - |diag| { - diag.span_suggestion( - expr.span, - "depending on intent, either make the Cow an Owned variant", - format!("{recv_snip}.into_owned()"), - app - ); - diag.span_suggestion( - expr.span, - "or clone the Cow itself", - format!("{recv_snip}.clone()"), - app - ); - } - ); - return true; - } + if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && is_diag_trait_item(cx, method_def_id, sym::ToOwned) + && let input_type = cx.typeck_results().expr_ty(expr) + && let ty::Adt(adt, _) = cx.typeck_results().expr_ty(expr).kind() + && cx.tcx.is_diagnostic_item(sym::Cow, adt.did()) + { + let mut app = Applicability::MaybeIncorrect; + let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0; + span_lint_and_then( + cx, + SUSPICIOUS_TO_OWNED, + expr.span, + &with_forced_trimmed_paths!(format!( + "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned" + )), + |diag| { + diag.span_suggestion( + expr.span, + "depending on intent, either make the Cow an Owned variant", + format!("{recv_snip}.into_owned()"), + app, + ); + diag.span_suggestion( + expr.span, + "or clone the Cow itself", + format!("{recv_snip}.clone()"), + app, + ); + }, + ); + return true; } false } diff --git a/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs b/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs index bc9c518dbcf0a..1ee655d61e1d2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs +++ b/src/tools/clippy/clippy_lints/src/methods/uninit_assumed_init.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::is_path_diagnostic_item; use clippy_utils::ty::is_uninit_value_valid_for_ty; -use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::sym; @@ -10,18 +9,16 @@ use super::UNINIT_ASSUMED_INIT; /// lint for `MaybeUninit::uninit().assume_init()` (we already have the latter) pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { - if_chain! { - if let hir::ExprKind::Call(callee, args) = recv.kind; - if args.is_empty(); - if is_path_diagnostic_item(cx, callee, sym::maybe_uninit_uninit); - if !is_uninit_value_valid_for_ty(cx, cx.typeck_results().expr_ty_adjusted(expr)); - then { - span_lint( - cx, - UNINIT_ASSUMED_INIT, - expr.span, - "this call for this type may be undefined behavior" - ); - } + if let hir::ExprKind::Call(callee, args) = recv.kind + && args.is_empty() + && is_path_diagnostic_item(cx, callee, sym::maybe_uninit_uninit) + && !is_uninit_value_valid_for_ty(cx, cx.typeck_results().expr_ty_adjusted(expr)) + { + span_lint( + cx, + UNINIT_ASSUMED_INIT, + expr.span, + "this call for this type may be undefined behavior", + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs index bb32b1bb7fc44..89cf20c14fc6a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs @@ -1,10 +1,11 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::get_parent_expr; use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty; +use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_span::{sym, Span}; use super::UNNECESSARY_FALLIBLE_CONVERSIONS; @@ -42,6 +43,7 @@ fn check<'tcx>( // (else there would be conflicting impls, even with #![feature(spec)]), so we don't even need to check // what `>::Error` is: it's always `Infallible` && implements_trait(cx, self_ty, from_into_trait, &[other_ty]) + && let Some(other_ty) = other_ty.as_type() { let parent_unwrap_call = get_parent_expr(cx, expr).and_then(|parent| { if let ExprKind::MethodCall(path, .., span) = parent.kind @@ -52,8 +54,7 @@ fn check<'tcx>( None } }); - - let (sugg, span, applicability) = match kind { + let (source_ty, target_ty, sugg, span, applicability) = match kind { FunctionKind::TryIntoMethod if let Some(unwrap_span) = parent_unwrap_call => { // Extend the span to include the unwrap/expect call: // `foo.try_into().expect("..")` @@ -63,24 +64,41 @@ fn check<'tcx>( // so that can be machine-applicable ( + self_ty, + other_ty, "into()", primary_span.with_hi(unwrap_span.hi()), Applicability::MachineApplicable, ) }, - FunctionKind::TryFromFunction => ("From::from", primary_span, Applicability::Unspecified), - FunctionKind::TryIntoFunction => ("Into::into", primary_span, Applicability::Unspecified), - FunctionKind::TryIntoMethod => ("into", primary_span, Applicability::Unspecified), + FunctionKind::TryFromFunction => ( + other_ty, + self_ty, + "From::from", + primary_span, + Applicability::Unspecified, + ), + FunctionKind::TryIntoFunction => ( + self_ty, + other_ty, + "Into::into", + primary_span, + Applicability::Unspecified, + ), + FunctionKind::TryIntoMethod => (self_ty, other_ty, "into", primary_span, Applicability::Unspecified), }; - span_lint_and_sugg( + span_lint_and_then( cx, UNNECESSARY_FALLIBLE_CONVERSIONS, span, "use of a fallible conversion when an infallible one could be used", - "use", - sugg.into(), - applicability, + |diag| { + with_forced_trimmed_paths!({ + diag.note(format!("converting `{source_ty}` to `{target_ty}` cannot fail")); + }); + diag.span_suggestion(span, "use", sugg, applicability); + }, ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index 6d51c4ab05446..ebbdde48b450f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_trait_method, path_to_local_id, peel_blocks, strip_pat_refs}; -use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; @@ -60,57 +59,51 @@ fn check_fold_with_op( op: hir::BinOpKind, replacement: Replacement, ) { - if_chain! { + if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind // Extract the body of the closure passed to fold - if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind; - let closure_body = cx.tcx.hir().body(body); - let closure_expr = peel_blocks(closure_body.value); + && let closure_body = cx.tcx.hir().body(body) + && let closure_expr = peel_blocks(closure_body.value) // Check if the closure body is of the form `acc some_expr(x)` - if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind; - if bin_op.node == op; + && let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind + && bin_op.node == op // Extract the names of the two arguments to the closure - if let [param_a, param_b] = closure_body.params; - if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind; - if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind; + && let [param_a, param_b] = closure_body.params + && let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind + && let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind - if path_to_local_id(left_expr, first_arg_id); - if replacement.has_args || path_to_local_id(right_expr, second_arg_id); - - then { - let mut applicability = Applicability::MachineApplicable; - - let turbofish = if replacement.has_generic_return { - format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs()) - } else { - String::new() - }; - - let sugg = if replacement.has_args { - format!( - "{method}{turbofish}(|{second_arg_ident}| {r})", - method = replacement.method_name, - r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability), - ) - } else { - format!( - "{method}{turbofish}()", - method = replacement.method_name, - ) - }; - - span_lint_and_sugg( - cx, - UNNECESSARY_FOLD, - fold_span.with_hi(expr.span.hi()), - // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f) - "this `.fold` can be written more succinctly using another method", - "try", - sugg, - applicability, - ); - } + && path_to_local_id(left_expr, first_arg_id) + && (replacement.has_args || path_to_local_id(right_expr, second_arg_id)) + { + let mut applicability = Applicability::MachineApplicable; + + let turbofish = if replacement.has_generic_return { + format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs()) + } else { + String::new() + }; + + let sugg = if replacement.has_args { + format!( + "{method}{turbofish}(|{second_arg_ident}| {r})", + method = replacement.method_name, + r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability), + ) + } else { + format!("{method}{turbofish}()", method = replacement.method_name,) + }; + + span_lint_and_sugg( + cx, + UNNECESSARY_FOLD, + fold_span.with_hi(expr.span.hi()), + // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f) + "this `.fold` can be written more succinctly using another method", + "try", + sugg, + applicability, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 0c72c13a3caa7..36497d59a5a85 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -13,15 +13,13 @@ use rustc_span::{sym, Symbol}; use super::UNNECESSARY_TO_OWNED; pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, receiver: &Expr<'_>) -> bool { - if_chain! { - if let Some(parent) = get_parent_expr(cx, expr); - if let Some(callee_def_id) = fn_def_id(cx, parent); - if is_into_iter(cx, callee_def_id); - then { - check_for_loop_iter(cx, parent, method_name, receiver, false) - } else { - false - } + if let Some(parent) = get_parent_expr(cx, expr) + && let Some(callee_def_id) = fn_def_id(cx, parent) + && is_into_iter(cx, callee_def_id) + { + check_for_loop_iter(cx, parent, method_name, receiver, false) + } else { + false } } @@ -36,65 +34,58 @@ pub fn check_for_loop_iter( receiver: &Expr<'_>, cloned_before_iter: bool, ) -> bool { - if_chain! { - if let Some(grandparent) = get_parent_expr(cx, expr).and_then(|parent| get_parent_expr(cx, parent)); - if let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent); - let (clone_or_copy_needed, addr_of_exprs) = clone_or_copy_needed(cx, pat, body); - if !clone_or_copy_needed; - if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); - then { - let snippet = if_chain! { - if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind; - if maybe_iter_method_name.ident.name == sym::iter; - - if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); - let receiver_ty = cx.typeck_results().expr_ty(receiver); - if implements_trait(cx, receiver_ty, iterator_trait_id, &[]); - if let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty); - - if let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator); - let collection_ty = cx.typeck_results().expr_ty(collection); - if implements_trait(cx, collection_ty, into_iterator_trait_id, &[]); - if let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item"); - - if iter_item_ty == into_iter_item_ty; - if let Some(collection_snippet) = snippet_opt(cx, collection.span); - then { - collection_snippet + if let Some(grandparent) = get_parent_expr(cx, expr).and_then(|parent| get_parent_expr(cx, parent)) + && let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent) + && let (clone_or_copy_needed, addr_of_exprs) = clone_or_copy_needed(cx, pat, body) + && !clone_or_copy_needed + && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + { + let snippet = if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind + && maybe_iter_method_name.ident.name == sym::iter + && let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator) + && let receiver_ty = cx.typeck_results().expr_ty(receiver) + && implements_trait(cx, receiver_ty, iterator_trait_id, &[]) + && let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty) + && let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) + && let collection_ty = cx.typeck_results().expr_ty(collection) + && implements_trait(cx, collection_ty, into_iterator_trait_id, &[]) + && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item") + && iter_item_ty == into_iter_item_ty + && let Some(collection_snippet) = snippet_opt(cx, collection.span) + { + collection_snippet + } else { + receiver_snippet + }; + span_lint_and_then( + cx, + UNNECESSARY_TO_OWNED, + expr.span, + &format!("unnecessary use of `{method_name}`"), + |diag| { + // If `check_into_iter_call_arg` called `check_for_loop_iter` because a call to + // a `to_owned`-like function was removed, then the next suggestion may be + // incorrect. This is because the iterator that results from the call's removal + // could hold a reference to a resource that is used mutably. See + // https://github.com/rust-lang/rust-clippy/issues/8148. + let applicability = if cloned_before_iter { + Applicability::MaybeIncorrect } else { - receiver_snippet - } - }; - span_lint_and_then( - cx, - UNNECESSARY_TO_OWNED, - expr.span, - &format!("unnecessary use of `{method_name}`"), - |diag| { - // If `check_into_iter_call_arg` called `check_for_loop_iter` because a call to - // a `to_owned`-like function was removed, then the next suggestion may be - // incorrect. This is because the iterator that results from the call's removal - // could hold a reference to a resource that is used mutably. See - // https://github.com/rust-lang/rust-clippy/issues/8148. - let applicability = if cloned_before_iter { - Applicability::MaybeIncorrect - } else { - Applicability::MachineApplicable - }; - diag.span_suggestion(expr.span, "use", snippet, applicability); - for addr_of_expr in addr_of_exprs { - match addr_of_expr.kind { - ExprKind::AddrOf(_, _, referent) => { - let span = addr_of_expr.span.with_hi(referent.span.lo()); - diag.span_suggestion(span, "remove this `&`", "", applicability); - } - _ => unreachable!(), - } + Applicability::MachineApplicable + }; + diag.span_suggestion(expr.span, "use", snippet, applicability); + for addr_of_expr in addr_of_exprs { + match addr_of_expr.kind { + ExprKind::AddrOf(_, _, referent) => { + let span = addr_of_expr.span.with_hi(referent.span.lo()); + diag.span_suggestion(span, "remove this `&`", "", applicability); + }, + _ => unreachable!(), } } - ); - return true; - } + }, + ); + return true; } false } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs index d0c62fb56dc20..e2b389e96dae0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs @@ -18,25 +18,23 @@ pub(super) fn check<'tcx>( ) { let applicability = Applicability::MachineApplicable; let collect_output_adjusted_type = cx.typeck_results().expr_ty_adjusted(join_self_arg); - if_chain! { + if let Ref(_, ref_type, _) = collect_output_adjusted_type.kind() // the turbofish for collect is ::> - if let Ref(_, ref_type, _) = collect_output_adjusted_type.kind(); - if let Slice(slice) = ref_type.kind(); - if is_type_lang_item(cx, *slice, LangItem::String); + && let Slice(slice) = ref_type.kind() + && is_type_lang_item(cx, *slice, LangItem::String) // the argument for join is "" - if let ExprKind::Lit(spanned) = &join_arg.kind; - if let LitKind::Str(symbol, _) = spanned.node; - if symbol.is_empty(); - then { - span_lint_and_sugg( - cx, - UNNECESSARY_JOIN, - span.with_hi(expr.span.hi()), - r#"called `.collect::>().join("")` on an iterator"#, - "try using", - "collect::()".to_owned(), - applicability, - ); - } + && let ExprKind::Lit(spanned) = &join_arg.kind + && let LitKind::Str(symbol, _) = spanned.node + && symbol.is_empty() + { + span_lint_and_sugg( + cx, + UNNECESSARY_JOIN, + span.with_hi(expr.span.hi()), + r#"called `.collect::>().join("")` on an iterator"#, + "try using", + "collect::()".to_owned(), + applicability, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs index e62a65a27125f..696e5e74d60a5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_trait_method; use clippy_utils::sugg::Sugg; use clippy_utils::ty::implements_trait; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath}; use rustc_lint::LateContext; @@ -115,55 +114,72 @@ fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident } fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) -> Option { - if_chain! { - if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(method_id); - if cx.tcx.type_of(impl_id).instantiate_identity().is_slice(); - if let ExprKind::Closure(&Closure { body, .. }) = arg.kind; - if let closure_body = cx.tcx.hir().body(body); - if let &[ - Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..}, - Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. } - ] = &closure_body.params; - if let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind; - if method_path.ident.name == sym::cmp; - if is_trait_method(cx, closure_body.value, sym::Ord); - then { - let (closure_body, closure_arg, reverse) = if mirrored_exprs( - left_expr, - left_ident, - right_expr, - right_ident - ) { - (Sugg::hir(cx, left_expr, "..").to_string(), left_ident.name.to_string(), false) - } else if mirrored_exprs(left_expr, right_ident, right_expr, left_ident) { - (Sugg::hir(cx, left_expr, "..").to_string(), right_ident.name.to_string(), true) - } else { - return None; - }; - let vec_name = Sugg::hir(cx, recv, "..").to_string(); + if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(method_id) + && cx.tcx.type_of(impl_id).instantiate_identity().is_slice() + && let ExprKind::Closure(&Closure { body, .. }) = arg.kind + && let closure_body = cx.tcx.hir().body(body) + && let &[ + Param { + pat: + Pat { + kind: PatKind::Binding(_, _, left_ident, _), + .. + }, + .. + }, + Param { + pat: + Pat { + kind: PatKind::Binding(_, _, right_ident, _), + .. + }, + .. + }, + ] = &closure_body.params + && let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind + && method_path.ident.name == sym::cmp + && is_trait_method(cx, closure_body.value, sym::Ord) + { + let (closure_body, closure_arg, reverse) = if mirrored_exprs(left_expr, left_ident, right_expr, right_ident) { + ( + Sugg::hir(cx, left_expr, "..").to_string(), + left_ident.name.to_string(), + false, + ) + } else if mirrored_exprs(left_expr, right_ident, right_expr, left_ident) { + ( + Sugg::hir(cx, left_expr, "..").to_string(), + right_ident.name.to_string(), + true, + ) + } else { + return None; + }; + let vec_name = Sugg::hir(cx, recv, "..").to_string(); - if_chain! { - if let ExprKind::Path(QPath::Resolved(_, Path { - segments: [PathSegment { ident: left_name, .. }], .. - })) = &left_expr.kind; - if left_name == left_ident; - if cx.tcx.get_diagnostic_item(sym::Ord).map_or(false, |id| { - implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[]) - }); - then { - return Some(LintTrigger::Sort(SortDetection { vec_name })); - } - } + if let ExprKind::Path(QPath::Resolved( + _, + Path { + segments: [PathSegment { ident: left_name, .. }], + .. + }, + )) = &left_expr.kind + && left_name == left_ident + && cx.tcx.get_diagnostic_item(sym::Ord).map_or(false, |id| { + implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[]) + }) + { + return Some(LintTrigger::Sort(SortDetection { vec_name })); + } - if !expr_borrows(cx, left_expr) { - return Some(LintTrigger::SortByKey(SortByKeyDetection { - vec_name, - closure_arg, - closure_body, - reverse, - })); - } + if !expr_borrows(cx, left_expr) { + return Some(LintTrigger::SortByKey(SortByKeyDetection { + vec_name, + closure_arg, + closure_body, + reverse, + })); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 772686d93dd7e..395b22ebc5d88 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -32,25 +32,23 @@ pub fn check<'tcx>( args: &'tcx [Expr<'_>], msrv: &Msrv, ) { - if_chain! { - if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if args.is_empty(); - then { - if is_cloned_or_copied(cx, method_name, method_def_id) { - unnecessary_iter_cloned::check(cx, expr, method_name, receiver); - } else if is_to_owned_like(cx, expr, method_name, method_def_id) { - // At this point, we know the call is of a `to_owned`-like function. The functions - // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary - // based on its context, that is, whether it is a referent in an `AddrOf` expression, an - // argument in a `into_iter` call, or an argument in the call of some other function. - if check_addr_of_expr(cx, expr, method_name, method_def_id, receiver) { - return; - } - if check_into_iter_call_arg(cx, expr, method_name, receiver, msrv) { - return; - } - check_other_call_arg(cx, expr, method_name, receiver); + if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && args.is_empty() + { + if is_cloned_or_copied(cx, method_name, method_def_id) { + unnecessary_iter_cloned::check(cx, expr, method_name, receiver); + } else if is_to_owned_like(cx, expr, method_name, method_def_id) { + // At this point, we know the call is of a `to_owned`-like function. The functions + // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary + // based on its context, that is, whether it is a referent in an `AddrOf` expression, an + // argument in a `into_iter` call, or an argument in the call of some other function. + if check_addr_of_expr(cx, expr, method_name, method_def_id, receiver) { + return; } + if check_into_iter_call_arg(cx, expr, method_name, receiver, msrv) { + return; + } + check_other_call_arg(cx, expr, method_name, receiver); } } } @@ -65,11 +63,10 @@ fn check_addr_of_expr( method_def_id: DefId, receiver: &Expr<'_>, ) -> bool { - if_chain! { - if let Some(parent) = get_parent_expr(cx, expr); - if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) = parent.kind; - let adjustments = cx.typeck_results().expr_adjustments(parent).iter().collect::>(); - if let + if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) = parent.kind + && let adjustments = cx.typeck_results().expr_adjustments(parent).iter().collect::>() + && let // For matching uses of `Cow::from` [ Adjustment { @@ -110,10 +107,10 @@ fn check_addr_of_expr( kind: Adjust::Borrow(_), target: target_ty, }, - ] = adjustments[..]; - let receiver_ty = cx.typeck_results().expr_ty(receiver); - let (target_ty, n_target_refs) = peel_mid_ty_refs(*target_ty); - let (receiver_ty, n_receiver_refs) = peel_mid_ty_refs(receiver_ty); + ] = adjustments[..] + && let receiver_ty = cx.typeck_results().expr_ty(receiver) + && let (target_ty, n_target_refs) = peel_mid_ty_refs(*target_ty) + && let (receiver_ty, n_receiver_refs) = peel_mid_ty_refs(receiver_ty) // Only flag cases satisfying at least one of the following three conditions: // * the referent and receiver types are distinct // * the referent/receiver type is a copyable array @@ -123,77 +120,72 @@ fn check_addr_of_expr( // https://github.com/rust-lang/rust-clippy/issues/8759 // Arrays are a bit of a corner case. Non-copyable arrays are handled by // `redundant_clone`, but copyable arrays are not. - if *referent_ty != receiver_ty + && (*referent_ty != receiver_ty || (matches!(referent_ty.kind(), ty::Array(..)) && is_copy(cx, *referent_ty)) - || is_cow_into_owned(cx, method_name, method_def_id); - if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); - then { - if receiver_ty == target_ty && n_target_refs >= n_receiver_refs { + || is_cow_into_owned(cx, method_name, method_def_id)) + && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + { + if receiver_ty == target_ty && n_target_refs >= n_receiver_refs { + span_lint_and_sugg( + cx, + UNNECESSARY_TO_OWNED, + parent.span, + &format!("unnecessary use of `{method_name}`"), + "use", + format!( + "{:&>width$}{receiver_snippet}", + "", + width = n_target_refs - n_receiver_refs + ), + Applicability::MachineApplicable, + ); + return true; + } + if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) + && implements_trait(cx, receiver_ty, deref_trait_id, &[]) + && cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty) + // Make sure that it's actually calling the right `.to_string()`, (#10033) + // *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow) + // but that's ok for Cow::into_owned specifically) + && (cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() == target_ty + || is_cow_into_owned(cx, method_name, method_def_id)) + { + if n_receiver_refs > 0 { span_lint_and_sugg( cx, UNNECESSARY_TO_OWNED, parent.span, &format!("unnecessary use of `{method_name}`"), "use", - format!( - "{:&>width$}{receiver_snippet}", - "", - width = n_target_refs - n_receiver_refs - ), + receiver_snippet, + Applicability::MachineApplicable, + ); + } else { + span_lint_and_sugg( + cx, + UNNECESSARY_TO_OWNED, + expr.span.with_lo(receiver.span.hi()), + &format!("unnecessary use of `{method_name}`"), + "remove this", + String::new(), Applicability::MachineApplicable, ); - return true; - } - if_chain! { - if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref); - if implements_trait(cx, receiver_ty, deref_trait_id, &[]); - if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty); - // Make sure that it's actually calling the right `.to_string()`, (#10033) - // *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow) - // but that's ok for Cow::into_owned specifically) - if cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() == target_ty - || is_cow_into_owned(cx, method_name, method_def_id); - then { - if n_receiver_refs > 0 { - span_lint_and_sugg( - cx, - UNNECESSARY_TO_OWNED, - parent.span, - &format!("unnecessary use of `{method_name}`"), - "use", - receiver_snippet, - Applicability::MachineApplicable, - ); - } else { - span_lint_and_sugg( - cx, - UNNECESSARY_TO_OWNED, - expr.span.with_lo(receiver.span.hi()), - &format!("unnecessary use of `{method_name}`"), - "remove this", - String::new(), - Applicability::MachineApplicable, - ); - } - return true; - } - } - if_chain! { - if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef); - if implements_trait(cx, receiver_ty, as_ref_trait_id, &[GenericArg::from(target_ty)]); - then { - span_lint_and_sugg( - cx, - UNNECESSARY_TO_OWNED, - parent.span, - &format!("unnecessary use of `{method_name}`"), - "use", - format!("{receiver_snippet}.as_ref()"), - Applicability::MachineApplicable, - ); - return true; - } } + return true; + } + if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef) + && implements_trait(cx, receiver_ty, as_ref_trait_id, &[GenericArg::from(target_ty)]) + { + span_lint_and_sugg( + cx, + UNNECESSARY_TO_OWNED, + parent.span, + &format!("unnecessary use of `{method_name}`"), + "use", + format!("{receiver_snippet}.as_ref()"), + Applicability::MachineApplicable, + ); + return true; } } false @@ -208,38 +200,36 @@ fn check_into_iter_call_arg( receiver: &Expr<'_>, msrv: &Msrv, ) -> bool { - if_chain! { - if let Some(parent) = get_parent_expr(cx, expr); - if let Some(callee_def_id) = fn_def_id(cx, parent); - if is_into_iter(cx, callee_def_id); - if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); - let parent_ty = cx.typeck_results().expr_ty(parent); - if implements_trait(cx, parent_ty, iterator_trait_id, &[]); - if let Some(item_ty) = get_iterator_item_ty(cx, parent_ty); - if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); - then { - if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) { - return true; - } - let cloned_or_copied = if is_copy(cx, item_ty) && msrv.meets(msrvs::ITERATOR_COPIED) { - "copied" - } else { - "cloned" - }; - // The next suggestion may be incorrect because the removal of the `to_owned`-like - // function could cause the iterator to hold a reference to a resource that is used - // mutably. See https://github.com/rust-lang/rust-clippy/issues/8148. - span_lint_and_sugg( - cx, - UNNECESSARY_TO_OWNED, - parent.span, - &format!("unnecessary use of `{method_name}`"), - "use", - format!("{receiver_snippet}.iter().{cloned_or_copied}()"), - Applicability::MaybeIncorrect, - ); + if let Some(parent) = get_parent_expr(cx, expr) + && let Some(callee_def_id) = fn_def_id(cx, parent) + && is_into_iter(cx, callee_def_id) + && let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator) + && let parent_ty = cx.typeck_results().expr_ty(parent) + && implements_trait(cx, parent_ty, iterator_trait_id, &[]) + && let Some(item_ty) = get_iterator_item_ty(cx, parent_ty) + && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + { + if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) { return true; } + let cloned_or_copied = if is_copy(cx, item_ty) && msrv.meets(msrvs::ITERATOR_COPIED) { + "copied" + } else { + "cloned" + }; + // The next suggestion may be incorrect because the removal of the `to_owned`-like + // function could cause the iterator to hold a reference to a resource that is used + // mutably. See https://github.com/rust-lang/rust-clippy/issues/8148. + span_lint_and_sugg( + cx, + UNNECESSARY_TO_OWNED, + parent.span, + &format!("unnecessary use of `{method_name}`"), + "use", + format!("{receiver_snippet}.iter().{cloned_or_copied}()"), + Applicability::MaybeIncorrect, + ); + return true; } false } @@ -252,26 +242,25 @@ fn check_other_call_arg<'tcx>( method_name: Symbol, receiver: &'tcx Expr<'tcx>, ) -> bool { - if_chain! { - if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr); - if let Some((callee_def_id, _, recv, call_args)) = get_callee_generic_args_and_args(cx, maybe_call); - let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder(); - if let Some(i) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == maybe_arg.hir_id); - if let Some(input) = fn_sig.inputs().get(i); - let (input, n_refs) = peel_mid_ty_refs(*input); - if let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input); - if let Some(sized_def_id) = cx.tcx.lang_items().sized_trait(); - if let [trait_predicate] = trait_predicates + if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr) + && let Some((callee_def_id, _, recv, call_args)) = get_callee_generic_args_and_args(cx, maybe_call) + && let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder() + && let Some(i) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == maybe_arg.hir_id) + && let Some(input) = fn_sig.inputs().get(i) + && let (input, n_refs) = peel_mid_ty_refs(*input) + && let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input) + && let Some(sized_def_id) = cx.tcx.lang_items().sized_trait() + && let [trait_predicate] = trait_predicates .iter() .filter(|trait_predicate| trait_predicate.def_id() != sized_def_id) - .collect::>()[..]; - if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref); - if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef); - if trait_predicate.def_id() == deref_trait_id || trait_predicate.def_id() == as_ref_trait_id; - let receiver_ty = cx.typeck_results().expr_ty(receiver); + .collect::>()[..] + && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) + && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef) + && (trait_predicate.def_id() == deref_trait_id || trait_predicate.def_id() == as_ref_trait_id) + && let receiver_ty = cx.typeck_results().expr_ty(receiver) // We can't add an `&` when the trait is `Deref` because `Target = &T` won't match // `Target = T`. - if let Some((n_refs, receiver_ty)) = if n_refs > 0 || is_copy(cx, receiver_ty) { + && let Some((n_refs, receiver_ty)) = if n_refs > 0 || is_copy(cx, receiver_ty) { Some((n_refs, receiver_ty)) } else if trait_predicate.def_id() != deref_trait_id { Some((1, Ty::new_ref(cx.tcx, @@ -283,21 +272,20 @@ fn check_other_call_arg<'tcx>( ))) } else { None - }; - if can_change_type(cx, maybe_arg, receiver_ty); - if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); - then { - span_lint_and_sugg( - cx, - UNNECESSARY_TO_OWNED, - maybe_arg.span, - &format!("unnecessary use of `{method_name}`"), - "use", - format!("{:&>n_refs$}{receiver_snippet}", ""), - Applicability::MachineApplicable, - ); - return true; } + && can_change_type(cx, maybe_arg, receiver_ty) + && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + { + span_lint_and_sugg( + cx, + UNNECESSARY_TO_OWNED, + maybe_arg.span, + &format!("unnecessary use of `{method_name}`"), + "use", + format!("{:&>n_refs$}{receiver_snippet}", ""), + Applicability::MachineApplicable, + ); + return true; } false } @@ -329,22 +317,18 @@ fn get_callee_generic_args_and_args<'tcx>( Option<&'tcx Expr<'tcx>>, &'tcx [Expr<'tcx>], )> { - if_chain! { - if let ExprKind::Call(callee, args) = expr.kind; - let callee_ty = cx.typeck_results().expr_ty(callee); - if let ty::FnDef(callee_def_id, _) = callee_ty.kind(); - then { - let generic_args = cx.typeck_results().node_args(callee.hir_id); - return Some((*callee_def_id, generic_args, None, args)); - } + if let ExprKind::Call(callee, args) = expr.kind + && let callee_ty = cx.typeck_results().expr_ty(callee) + && let ty::FnDef(callee_def_id, _) = callee_ty.kind() + { + let generic_args = cx.typeck_results().node_args(callee.hir_id); + return Some((*callee_def_id, generic_args, None, args)); } - if_chain! { - if let ExprKind::MethodCall(_, recv, args, _) = expr.kind; - if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - then { - let generic_args = cx.typeck_results().node_args(expr.hir_id); - return Some((method_def_id, generic_args, Some(recv), args)); - } + if let ExprKind::MethodCall(_, recv, args, _) = expr.kind + && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + { + let generic_args = cx.typeck_results().node_args(expr.hir_id); + return Some((method_def_id, generic_args, Some(recv), args)); } None } diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs index b5f810eddf4a0..84ee64e88a6a0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::walk_ptrs_ty_depth; use clippy_utils::{get_parent_expr, is_trait_method}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -22,13 +21,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, let (base_rcv_ty, rcv_depth) = walk_ptrs_ty_depth(rcv_ty); if base_rcv_ty == base_res_ty && rcv_depth >= res_depth { // allow the `as_ref` or `as_mut` if it is followed by another method call - if_chain! { - if let Some(parent) = get_parent_expr(cx, expr); - if let hir::ExprKind::MethodCall(segment, ..) = parent.kind; - if segment.ident.span != expr.span; - then { - return; - } + if let Some(parent) = get_parent_expr(cx, expr) + && let hir::ExprKind::MethodCall(segment, ..) = parent.kind + && segment.ident.span != expr.span + { + return; } let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs index 9f1f73e602185..9ad4250a141f0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/utils.rs +++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs @@ -1,7 +1,6 @@ use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{get_parent_expr, path_to_local_id, usage}; -use if_chain::if_chain; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; @@ -55,32 +54,33 @@ pub(super) fn get_hint_if_single_char_arg( arg: &hir::Expr<'_>, applicability: &mut Applicability, ) -> Option { - if_chain! { - if let hir::ExprKind::Lit(lit) = &arg.kind; - if let ast::LitKind::Str(r, style) = lit.node; - let string = r.as_str(); - if string.chars().count() == 1; - then { - let snip = snippet_with_applicability(cx, arg.span, string, applicability); - let ch = if let ast::StrStyle::Raw(nhash) = style { - let nhash = nhash as usize; - // for raw string: r##"a"## - &snip[(nhash + 2)..(snip.len() - 1 - nhash)] - } else { - // for regular string: "a" - &snip[1..(snip.len() - 1)] - }; + if let hir::ExprKind::Lit(lit) = &arg.kind + && let ast::LitKind::Str(r, style) = lit.node + && let string = r.as_str() + && string.chars().count() == 1 + { + let snip = snippet_with_applicability(cx, arg.span, string, applicability); + let ch = if let ast::StrStyle::Raw(nhash) = style { + let nhash = nhash as usize; + // for raw string: r##"a"## + &snip[(nhash + 2)..(snip.len() - 1 - nhash)] + } else { + // for regular string: "a" + &snip[1..(snip.len() - 1)] + }; - let hint = format!("'{}'", match ch { - "'" => "\\'" , + let hint = format!( + "'{}'", + match ch { + "'" => "\\'", r"\" => "\\\\", _ => ch, - }); + } + ); - Some(hint) - } else { - None - } + Some(hint) + } else { + None } } @@ -140,15 +140,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> { return; }, ExprKind::MethodCall(.., args, _) => { - if_chain! { - if args.iter().all(|arg| !self.is_binding(arg)); - if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id); - let method_ty = self.cx.tcx.type_of(method_def_id).instantiate_identity(); - let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder(); - if matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Not)); - then { - return; - } + if args.iter().all(|arg| !self.is_binding(arg)) + && let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id) + && let method_ty = self.cx.tcx.type_of(method_def_id).instantiate_identity() + && let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder() + && matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Not)) + { + return; } }, _ => {}, diff --git a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs index 73072718678eb..9e87fb45aa65a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs +++ b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; @@ -17,29 +16,32 @@ pub(super) fn check<'tcx>( default_arg: &'tcx Expr<'_>, name_span: Span, ) { - if_chain! { - if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); - if let Some(impl_id) = cx.tcx.impl_of_method(method_id); - if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Vec); - if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = count_arg.kind; - if let ExprKind::Lit(Spanned { node: LitKind::Int(..), .. }) = default_arg.kind; - then { - let method_call_span = expr.span.with_lo(name_span.lo()); - span_lint_and_then( - cx, - VEC_RESIZE_TO_ZERO, - expr.span, - "emptying a vector with `resize`", - |db| { - db.help("the arguments may be inverted..."); - db.span_suggestion( - method_call_span, - "...or you can empty the vector with", - "clear()".to_string(), - Applicability::MaybeIncorrect, - ); - }, - ); - } + if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(method_id) + && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Vec) + && let ExprKind::Lit(Spanned { + node: LitKind::Int(0, _), + .. + }) = count_arg.kind + && let ExprKind::Lit(Spanned { + node: LitKind::Int(..), .. + }) = default_arg.kind + { + let method_call_span = expr.span.with_lo(name_span.lo()); + span_lint_and_then( + cx, + VEC_RESIZE_TO_ZERO, + expr.span, + "emptying a vector with `resize`", + |db| { + db.help("the arguments may be inverted..."); + db.span_suggestion( + method_call_span, + "...or you can empty the vector with", + "clear()".to_string(), + Applicability::MaybeIncorrect, + ); + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs index e9f268da69156..0b829d99aef89 100644 --- a/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs +++ b/src/tools/clippy/clippy_lints/src/methods/zst_offset.rs @@ -1,5 +1,4 @@ use clippy_utils::diagnostics::span_lint; -use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty; @@ -7,12 +6,10 @@ use rustc_middle::ty; use super::ZST_OFFSET; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { - if_chain! { - if let ty::RawPtr(ty::TypeAndMut { ty, .. }) = cx.typeck_results().expr_ty(recv).kind(); - if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty)); - if layout.is_zst(); - then { - span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value"); - } + if let ty::RawPtr(ty::TypeAndMut { ty, .. }) = cx.typeck_results().expr_ty(recv).kind() + && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty)) + && layout.is_zst() + { + span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value"); } } diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index 4ad12e899fe2a..f5b749c7f800a 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -6,7 +6,7 @@ use rustc_hir::intravisit::{walk_item, Visitor}; use rustc_hir::{GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; use std::borrow::Cow; diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs index e0904f17b8de0..fca626fa5c35c 100644 --- a/src/tools/clippy/clippy_lints/src/minmax.rs +++ b/src/tools/clippy/clippy_lints/src/minmax.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::is_trait_method; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; use std::cmp::Ordering; diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index f4af5f37bf374..b9784a58596c1 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -5,7 +5,6 @@ use clippy_utils::{ any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, is_lint_allowed, iter_input_pats, last_path_segment, SpanlessEq, }; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::intravisit::FnKind; @@ -14,7 +13,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::Span; @@ -143,73 +142,64 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if_chain! { - if !in_external_macro(cx.tcx.sess, stmt.span); - if let StmtKind::Local(local) = stmt.kind; - if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind; - if let Some(init) = local.init; + if !in_external_macro(cx.tcx.sess, stmt.span) + && let StmtKind::Local(local) = stmt.kind + && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind + && let Some(init) = local.init // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue. - if is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id); - then { - let ctxt = local.span.ctxt(); - let mut app = Applicability::MachineApplicable; - let sugg_init = Sugg::hir_with_context(cx, init, ctxt, "..", &mut app); - let (mutopt, initref) = if mutabl == Mutability::Mut { - ("mut ", sugg_init.mut_addr()) - } else { - ("", sugg_init.addr()) - }; - let tyopt = if let Some(ty) = local.ty { - let ty_snip = snippet_with_context(cx, ty.span, ctxt, "_", &mut app).0; - format!(": &{mutopt}{ty_snip}") - } else { - String::new() - }; - span_lint_hir_and_then( - cx, - TOPLEVEL_REF_ARG, - init.hir_id, - local.pat.span, - "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", - |diag| { - diag.span_suggestion( - stmt.span, - "try", - format!( - "let {name}{tyopt} = {initref};", - name=snippet(cx, name.span, ".."), - ), - app, - ); - } - ); - } + && is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id) + { + let ctxt = local.span.ctxt(); + let mut app = Applicability::MachineApplicable; + let sugg_init = Sugg::hir_with_context(cx, init, ctxt, "..", &mut app); + let (mutopt, initref) = if mutabl == Mutability::Mut { + ("mut ", sugg_init.mut_addr()) + } else { + ("", sugg_init.addr()) + }; + let tyopt = if let Some(ty) = local.ty { + let ty_snip = snippet_with_context(cx, ty.span, ctxt, "_", &mut app).0; + format!(": &{mutopt}{ty_snip}") + } else { + String::new() + }; + span_lint_hir_and_then( + cx, + TOPLEVEL_REF_ARG, + init.hir_id, + local.pat.span, + "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead", + |diag| { + diag.span_suggestion( + stmt.span, + "try", + format!("let {name}{tyopt} = {initref};", name = snippet(cx, name.span, ".."),), + app, + ); + }, + ); }; - if_chain! { - if let StmtKind::Semi(expr) = stmt.kind; - if let ExprKind::Binary(ref binop, a, b) = expr.kind; - if binop.node == BinOpKind::And || binop.node == BinOpKind::Or; - if let Some(sugg) = Sugg::hir_opt(cx, a); - then { - span_lint_hir_and_then( - cx, - SHORT_CIRCUIT_STATEMENT, - expr.hir_id, - stmt.span, - "boolean short circuit operator in statement may be clearer using an explicit test", - |diag| { - let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg }; - diag.span_suggestion( - stmt.span, - "replace it with", - format!( - "if {sugg} {{ {}; }}", - &snippet(cx, b.span, ".."), - ), - Applicability::MachineApplicable, // snippet - ); - }); - } + if let StmtKind::Semi(expr) = stmt.kind + && let ExprKind::Binary(ref binop, a, b) = expr.kind + && (binop.node == BinOpKind::And || binop.node == BinOpKind::Or) + && let Some(sugg) = Sugg::hir_opt(cx, a) + { + span_lint_hir_and_then( + cx, + SHORT_CIRCUIT_STATEMENT, + expr.hir_id, + stmt.span, + "boolean short circuit operator in statement may be clearer using an explicit test", + |diag| { + let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg }; + diag.span_suggestion( + stmt.span, + "replace it with", + format!("if {sugg} {{ {}; }}", &snippet(cx, b.span, ".."),), + Applicability::MachineApplicable, // snippet + ); + }, + ); }; } diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs index df0dd9e4e3986..abe5b00e888a4 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs @@ -16,7 +16,7 @@ use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashMap; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs index 0d79ece087f5f..0739b49fe190e 100644 --- a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs +++ b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs @@ -4,7 +4,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{GenericArg, Item, ItemKind, QPath, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::GenericParamDefKind; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -49,59 +49,59 @@ declare_lint_pass!(TypeParamMismatch => [MISMATCHING_TYPE_PARAM_ORDER]); impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if_chain! { - if !item.span.from_expansion(); - if let ItemKind::Impl(imp) = &item.kind; - if let TyKind::Path(QPath::Resolved(_, path)) = &imp.self_ty.kind; - if let Some(segment) = path.segments.iter().next(); - if let Some(generic_args) = segment.args; - if !generic_args.args.is_empty(); - then { - // get the name and span of the generic parameters in the Impl - let mut impl_params = Vec::new(); - for p in generic_args.args { - match p { - GenericArg::Type(Ty {kind: TyKind::Path(QPath::Resolved(_, path)), ..}) => - impl_params.push((path.segments[0].ident.to_string(), path.span)), - GenericArg::Type(_) => return, - _ => (), - }; - } - - // find the type that the Impl is for - // only lint on struct/enum/union for now - let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, defid) = path.res else { - return + if !item.span.from_expansion() + && let ItemKind::Impl(imp) = &item.kind + && let TyKind::Path(QPath::Resolved(_, path)) = &imp.self_ty.kind + && let Some(segment) = path.segments.iter().next() + && let Some(generic_args) = segment.args + && !generic_args.args.is_empty() + { + // get the name and span of the generic parameters in the Impl + let mut impl_params = Vec::new(); + for p in generic_args.args { + match p { + GenericArg::Type(Ty { + kind: TyKind::Path(QPath::Resolved(_, path)), + .. + }) => impl_params.push((path.segments[0].ident.to_string(), path.span)), + GenericArg::Type(_) => return, + _ => (), }; + } + + // find the type that the Impl is for + // only lint on struct/enum/union for now + let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, defid) = path.res else { + return; + }; - // get the names of the generic parameters in the type - let type_params = &cx.tcx.generics_of(defid).params; - let type_param_names: Vec<_> = type_params.iter() - .filter_map(|p| - match p.kind { - GenericParamDefKind::Type {..} => Some(p.name.to_string()), - _ => None, - } - ).collect(); - // hashmap of name -> index for mismatch_param_name - let type_param_names_hashmap: FxHashMap<&String, usize> = - type_param_names.iter().enumerate().map(|(i, param)| (param, i)).collect(); + // get the names of the generic parameters in the type + let type_params = &cx.tcx.generics_of(defid).params; + let type_param_names: Vec<_> = type_params + .iter() + .filter_map(|p| match p.kind { + GenericParamDefKind::Type { .. } => Some(p.name.to_string()), + _ => None, + }) + .collect(); + // hashmap of name -> index for mismatch_param_name + let type_param_names_hashmap: FxHashMap<&String, usize> = type_param_names + .iter() + .enumerate() + .map(|(i, param)| (param, i)) + .collect(); - let type_name = segment.ident; - for (i, (impl_param_name, impl_param_span)) in impl_params.iter().enumerate() { - if mismatch_param_name(i, impl_param_name, &type_param_names_hashmap) { - let msg = format!("`{type_name}` has a similarly named generic type parameter `{impl_param_name}` in its declaration, but in a different order"); - let help = format!("try `{}`, or a name that does not conflict with `{type_name}`'s generic params", - type_param_names[i]); - span_lint_and_help( - cx, - MISMATCHING_TYPE_PARAM_ORDER, - *impl_param_span, - &msg, - None, - &help - ); - } + let type_name = segment.ident; + for (i, (impl_param_name, impl_param_span)) in impl_params.iter().enumerate() { + if mismatch_param_name(i, impl_param_name, &type_param_names_hashmap) { + let msg = format!( + "`{type_name}` has a similarly named generic type parameter `{impl_param_name}` in its declaration, but in a different order" + ); + let help = format!( + "try `{}`, or a name that does not conflict with `{type_name}`'s generic params", + type_param_names[i] + ); + span_lint_and_help(cx, MISMATCHING_TYPE_PARAM_ORDER, *impl_param_span, &msg, None, &help); } } } diff --git a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs index 4e00215c5cba2..04df7b7a7e5a4 100644 --- a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs +++ b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs @@ -3,7 +3,7 @@ use clippy_utils::macros::{find_assert_args, find_assert_eq_args, root_macro_cal use clippy_utils::{is_in_cfg_test, is_in_test_function}; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index dccf72d3c84c1..8f2a5390781dd 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -9,9 +9,9 @@ use clippy_utils::{eq_expr_value, hash_expr, higher}; use rustc_ast::{LitKind, RangeLimits}; use rustc_data_structures::unhash::UnhashMap; use rustc_errors::{Applicability, Diagnostic}; -use rustc_hir::{BinOp, Block, Expr, ExprKind, UnOp}; +use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::{sym, Span}; @@ -57,7 +57,7 @@ declare_clippy_lint! { /// v[0] + v[1] + v[2] + v[3] /// } /// ``` - #[clippy::version = "1.70.0"] + #[clippy::version = "1.74.0"] pub MISSING_ASSERTS_FOR_INDEXING, restriction, "indexing into a slice multiple times without an `assert`" @@ -390,10 +390,10 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnhashMap> } impl LateLintPass<'_> for MissingAssertsForIndexing { - fn check_block(&mut self, cx: &LateContext<'_>, block: &Block<'_>) { + fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { let mut map = UnhashMap::default(); - for_each_expr(block, |expr| { + for_each_expr(body.value, |expr| { check_index(cx, expr, &mut map); check_assert(cx, expr, &mut map); ControlFlow::::Continue(()) diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index 97522cbe6cea9..5f736898159db 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -9,7 +9,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Constness, FnDecl, GenericParamKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::Span; @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { FnKind::Closure => return, } - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(def_id); // Const fns are not allowed as methods in a trait. { diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 973caa72b772e..bf4af7946f470 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -8,13 +8,12 @@ use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_from_proc_macro; -use if_chain::if_chain; use rustc_ast::ast::{self, MetaItem, MetaItemKind}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::Visibility; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{sym, Span}; @@ -63,16 +62,14 @@ impl MissingDoc { } fn has_include(meta: Option) -> bool { - if_chain! { - if let Some(meta) = meta; - if let MetaItemKind::List(list) = meta.kind; - if let Some(meta) = list.first(); - if let Some(name) = meta.ident(); - then { - name.name == sym::include - } else { - false - } + if let Some(meta) = meta + && let MetaItemKind::List(list) = meta.kind + && let Some(meta) = list.first() + && let Some(name) = meta.ident() + { + name.name == sym::include + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs index 16ff98a5922ca..c1f6c71a63e68 100644 --- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -7,7 +7,7 @@ use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::{Item, ItemKind, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Symbol; declare_clippy_lint! { @@ -72,13 +72,12 @@ impl LateLintPass<'_> for ImportRename { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if let ItemKind::Use(path, UseKind::Single) = &item.kind { for &res in &path.res { - if_chain! { - if let Res::Def(_, id) = res; - if let Some(name) = self.renames.get(&id); + if let Res::Def(_, id) = res + && let Some(name) = self.renames.get(&id) // Remove semicolon since it is not present for nested imports - let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';'); - if let Some(snip) = snippet_opt(cx, span_without_semi); - if let Some(import) = match snip.split_once(" as ") { + && let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';') + && let Some(snip) = snippet_opt(cx, span_without_semi) + && let Some(import) = match snip.split_once(" as ") { None => Some(snip.as_str()), Some((import, rename)) => { if rename.trim() == name.as_str() { @@ -87,20 +86,17 @@ impl LateLintPass<'_> for ImportRename { Some(import.trim()) } }, - }; - then { - span_lint_and_sugg( - cx, - MISSING_ENFORCED_IMPORT_RENAMES, - span_without_semi, - "this import should be renamed", - "try", - format!( - "{import} as {name}", - ), - Applicability::MachineApplicable, - ); } + { + span_lint_and_sugg( + cx, + MISSING_ENFORCED_IMPORT_RENAMES, + span_without_semi, + "this import should be renamed", + "try", + format!("{import} as {name}",), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs index 95f9df4e42a4f..8be45b8c2f352 100644 --- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs +++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs @@ -12,7 +12,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{Ty, TypeckResults}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span, Symbol}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index b815da79b6951..07bcbfc4ff4db 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::{self, LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs index ad5f45a328087..6bbf18d52d11c 100644 --- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs +++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefIdMap; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::AssocItem; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index 215161b04c7c9..cd180754113fe 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id}; -use if_chain::if_chain; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -80,11 +79,13 @@ declare_lint_pass!(EvalOrderDependence => [MIXED_READ_WRITE_IN_EXPRESSION, DIVER impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Find a write to a local variable. - let var = if_chain! { - if let ExprKind::Assign(lhs, ..) | ExprKind::AssignOp(_, lhs, _) = expr.kind; - if let Some(var) = path_to_local(lhs); - if expr.span.desugaring_kind().is_none(); - then { var } else { return; } + let var = if let ExprKind::Assign(lhs, ..) | ExprKind::AssignOp(_, lhs, _) = expr.kind + && let Some(var) = path_to_local(lhs) + && expr.span.desugaring_kind().is_none() + { + var + } else { + return; }; let mut visitor = ReadVisitor { cx, @@ -164,7 +165,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { match typ.kind() { ty::FnDef(..) | ty::FnPtr(_) => { let sig = typ.fn_sig(self.cx.tcx); - if self.cx.tcx.erase_late_bound_regions(sig).output().kind() == &ty::Never { + if self.cx.tcx.instantiate_bound_regions_with_erased(sig).output().kind() == &ty::Never { self.report_diverging_sub_expr(e); } }, diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs index efdc7560ee49c..0226b31dd190d 100644 --- a/src/tools/clippy/clippy_lints/src/module_style.rs +++ b/src/tools/clippy/clippy_lints/src/module_style.rs @@ -1,7 +1,8 @@ +use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{FileName, SourceFile, Span, SyntaxContext}; use std::ffi::OsStr; @@ -124,11 +125,13 @@ impl EarlyLintPass for ModStyle { correct.pop(); correct.push(folder); correct.push("mod.rs"); - cx.struct_span_lint( + span_lint_and_help( + cx, SELF_NAMED_MODULE_FILES, Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), - format!("`mod.rs` files are required, found `{}`", path.display()), - |lint| lint.help(format!("move `{}` to `{}`", path.display(), correct.display(),)), + &format!("`mod.rs` files are required, found `{}`", path.display()), + None, + &format!("move `{}` to `{}`", path.display(), correct.display(),), ); } } @@ -153,17 +156,22 @@ fn process_paths_for_mod_files<'a>( } /// Checks every path for the presence of `mod.rs` files and emits the lint if found. +/// We should not emit a lint for test modules in the presence of `mod.rs`. +/// Using `mod.rs` in integration tests is a [common pattern](https://doc.rust-lang.org/book/ch11-03-test-organization.html#submodules-in-integration-test) +/// for code-sharing between tests. fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &SourceFile) { - if path.ends_with("mod.rs") { + if path.ends_with("mod.rs") && !path.starts_with("tests") { let mut mod_file = path.to_path_buf(); mod_file.pop(); mod_file.set_extension("rs"); - cx.struct_span_lint( + span_lint_and_help( + cx, MOD_MODULE_FILES, Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), - format!("`mod.rs` files are not allowed, found `{}`", path.display()), - |lint| lint.help(format!("move `{}` to `{}`", path.display(), mod_file.display())), + &format!("`mod.rs` files are not allowed, found `{}`", path.display()), + None, + &format!("move `{}` to `{}`", path.display(), mod_file.display()), ); } } diff --git a/src/tools/clippy/clippy_lints/src/multi_assignments.rs b/src/tools/clippy/clippy_lints/src/multi_assignments.rs index b42dce7a13a38..9a6b1dfc52b5c 100644 --- a/src/tools/clippy/clippy_lints/src/multi_assignments.rs +++ b/src/tools/clippy/clippy_lints/src/multi_assignments.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index d4f8008aeced0..049f44f3246f4 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -8,7 +8,7 @@ use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{DesugaringKind, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index ebfd53f1ee9aa..04d2ced6abf81 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -6,10 +6,10 @@ use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::query::Key; use rustc_middle::ty::{Adt, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; -use rustc_span::Span; use rustc_span::symbol::sym; +use rustc_span::Span; use std::iter; declare_clippy_lint! { @@ -143,7 +143,11 @@ impl MutableKeyType { for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) { self.check_ty_(cx, hir_ty.span, *ty); } - self.check_ty_(cx, decl.output.span(), cx.tcx.erase_late_bound_regions(fn_sig.output())); + self.check_ty_( + cx, + decl.output.span(), + cx.tcx.instantiate_bound_regions_with_erased(fn_sig.output()), + ); } // We want to lint 1. sets or maps with 2. not immutable key types and 3. no unerased diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index 6989504a4a9af..72a2cca1e4024 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -5,7 +5,7 @@ use rustc_hir::intravisit; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs index 4f8e244222d8d..f905a4e5b64c6 100644 --- a/src/tools/clippy/clippy_lints/src/mut_reference.rs +++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use std::iter; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs index dea432fdbd505..96cd81ecdf314 100644 --- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs +++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs @@ -5,7 +5,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs index 9d8c06cd07709..a23e12f7a18c2 100644 --- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs +++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs @@ -7,7 +7,7 @@ use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs index 97e8f1c030ad5..2ab83f733cb19 100644 --- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use if_chain::if_chain; use rustc_ast::ast::{BindingAnnotation, ByRef, Lifetime, Mutability, Param, PatKind, Path, TyKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::kw; use rustc_span::Span; @@ -66,48 +65,46 @@ enum Mode { } fn check_param_inner(cx: &EarlyContext<'_>, path: &Path, span: Span, binding_mode: &Mode, mutbl: Mutability) { - if_chain! { - if let [segment] = &path.segments[..]; - if segment.ident.name == kw::SelfUpper; - then { - // In case we have a named lifetime, we check if the name comes from expansion. - // If it does, at this point we know the rest of the parameter was written by the user, - // so let them decide what the name of the lifetime should be. - // See #6089 for more details. - let mut applicability = Applicability::MachineApplicable; - let self_param = match (binding_mode, mutbl) { - (Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(), - (Mode::Ref(Some(lifetime)), Mutability::Mut) => { - if lifetime.ident.span.from_expansion() { - applicability = Applicability::HasPlaceholders; - "&'_ mut self".to_string() - } else { - format!("&{} mut self", &lifetime.ident.name) - } - }, - (Mode::Ref(None), Mutability::Not) => "&self".to_string(), - (Mode::Ref(Some(lifetime)), Mutability::Not) => { - if lifetime.ident.span.from_expansion() { - applicability = Applicability::HasPlaceholders; - "&'_ self".to_string() - } else { - format!("&{} self", &lifetime.ident.name) - } - }, - (Mode::Value, Mutability::Mut) => "mut self".to_string(), - (Mode::Value, Mutability::Not) => "self".to_string(), - }; + if let [segment] = &path.segments[..] + && segment.ident.name == kw::SelfUpper + { + // In case we have a named lifetime, we check if the name comes from expansion. + // If it does, at this point we know the rest of the parameter was written by the user, + // so let them decide what the name of the lifetime should be. + // See #6089 for more details. + let mut applicability = Applicability::MachineApplicable; + let self_param = match (binding_mode, mutbl) { + (Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(), + (Mode::Ref(Some(lifetime)), Mutability::Mut) => { + if lifetime.ident.span.from_expansion() { + applicability = Applicability::HasPlaceholders; + "&'_ mut self".to_string() + } else { + format!("&{} mut self", &lifetime.ident.name) + } + }, + (Mode::Ref(None), Mutability::Not) => "&self".to_string(), + (Mode::Ref(Some(lifetime)), Mutability::Not) => { + if lifetime.ident.span.from_expansion() { + applicability = Applicability::HasPlaceholders; + "&'_ self".to_string() + } else { + format!("&{} self", &lifetime.ident.name) + } + }, + (Mode::Value, Mutability::Mut) => "mut self".to_string(), + (Mode::Value, Mutability::Not) => "self".to_string(), + }; - span_lint_and_sugg( - cx, - NEEDLESS_ARBITRARY_SELF_TYPE, - span, - "the type of the `self` parameter does not need to be arbitrary", - "consider to change this parameter to", - self_param, - applicability, - ) - } + span_lint_and_sugg( + cx, + NEEDLESS_ARBITRARY_SELF_TYPE, + span, + "the type of the `self` parameter does not need to be arbitrary", + "consider to change this parameter to", + self_param, + applicability, + ); } } @@ -125,12 +122,10 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { } }, TyKind::Ref(lifetime, mut_ty) => { - if_chain! { - if let TyKind::Path(None, path) = &mut_ty.ty.kind; - if let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind; - then { - check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl); - } + if let TyKind::Path(None, path) = &mut_ty.ty.kind + && let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind + { + check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl); } }, _ => {}, diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index 02c177c922746..218ca5e80f380 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -13,7 +13,7 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Node, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::Span; diff --git a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs index fdb91f0dc0d66..4710a69443b47 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, Mutability, Node, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index dcfb109a4c49b..85166b0dd95be 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -15,7 +15,7 @@ use rustc_middle::mir::{Rvalue, StatementKind}; use rustc_middle::ty::{ self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, List, ParamTy, ProjectionPredicate, Ty, }; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{Obligation, ObligationCause}; @@ -50,7 +50,7 @@ declare_clippy_lint! { /// let x = "foo"; /// f(x); /// ``` - #[clippy::version = "pre 1.29.0"] + #[clippy::version = "1.74.0"] pub NEEDLESS_BORROWS_FOR_GENERIC_ARGS, style, "taking a reference that is going to be automatically dereferenced" diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs index cb2738947d49d..4b9ab50e4fd77 100644 --- a/src/tools/clippy/clippy_lints/src/needless_continue.rs +++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs @@ -37,7 +37,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::{indent_of, snippet, snippet_block}; use rustc_ast::ast; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -362,21 +362,19 @@ fn suggestion_snippet_for_continue_inside_else(cx: &EarlyContext<'_>, data: &Lin } fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) { - if_chain! { - if let ast::ExprKind::Loop(loop_block, ..) = &expr.kind; - if let Some(last_stmt) = loop_block.stmts.last(); - if let ast::StmtKind::Expr(inner_expr) | ast::StmtKind::Semi(inner_expr) = &last_stmt.kind; - if let ast::ExprKind::Continue(_) = inner_expr.kind; - then { - span_lint_and_help( - cx, - NEEDLESS_CONTINUE, - last_stmt.span, - MSG_REDUNDANT_CONTINUE_EXPRESSION, - None, - DROP_CONTINUE_EXPRESSION_MSG, - ); - } + if let ast::ExprKind::Loop(loop_block, ..) = &expr.kind + && let Some(last_stmt) = loop_block.stmts.last() + && let ast::StmtKind::Expr(inner_expr) | ast::StmtKind::Semi(inner_expr) = &last_stmt.kind + && let ast::ExprKind::Continue(_) = inner_expr.kind + { + span_lint_and_help( + cx, + NEEDLESS_CONTINUE, + last_stmt.span, + MSG_REDUNDANT_CONTINUE_EXPRESSION, + None, + DROP_CONTINUE_EXPRESSION_MSG, + ); } with_loop_block(expr, |loop_block, label| { for (i, stmt) in loop_block.stmts.iter().enumerate() { diff --git a/src/tools/clippy/clippy_lints/src/needless_else.rs b/src/tools/clippy/clippy_lints/src/needless_else.rs index d881c13f84ade..b6aad69d1668c 100644 --- a/src/tools/clippy/clippy_lints/src/needless_else.rs +++ b/src/tools/clippy/clippy_lints/src/needless_else.rs @@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_opt, trim_span}; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs index c71996131db4e..84a07df1bb0ac 100644 --- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs +++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs @@ -2,11 +2,9 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{Closure, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span, Symbol}; -use if_chain::if_chain; - use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_trait_method; use clippy_utils::source::snippet_with_applicability; @@ -51,65 +49,63 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach { return; }; - if_chain! { + if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind // Check the method name is `for_each`. - if let ExprKind::MethodCall(method_name, for_each_recv, [for_each_arg], _) = expr.kind; - if method_name.ident.name == Symbol::intern("for_each"); + && method_name.ident.name == Symbol::intern("for_each") // Check `for_each` is an associated function of `Iterator`. - if is_trait_method(cx, expr, sym::Iterator); + && is_trait_method(cx, expr, sym::Iterator) // Checks the receiver of `for_each` is also a method call. - if let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind; + && let ExprKind::MethodCall(_, iter_recv, [], _) = for_each_recv.kind // Skip the lint if the call chain is too long. e.g. `v.field.iter().for_each()` or // `v.foo().iter().for_each()` must be skipped. - if matches!( + && matches!( iter_recv.kind, ExprKind::Array(..) | ExprKind::Call(..) | ExprKind::Path(..) - ); + ) // Checks the type of the `iter` method receiver is NOT a user defined type. - if has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some(); + && has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some() // Skip the lint if the body is not block because this is simpler than `for` loop. // e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop. - if let ExprKind::Closure(&Closure { body, .. }) = for_each_arg.kind; - let body = cx.tcx.hir().body(body); - if let ExprKind::Block(..) = body.value.kind; - then { - let mut ret_collector = RetCollector::default(); - ret_collector.visit_expr(body.value); - - // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`. - if ret_collector.ret_in_loop { - return; - } - - let (mut applicability, ret_suggs) = if ret_collector.spans.is_empty() { - (Applicability::MachineApplicable, None) - } else { - ( - Applicability::MaybeIncorrect, - Some( - ret_collector - .spans - .into_iter() - .map(|span| (span, "continue".to_string())) - .collect(), - ), - ) - }; + && let ExprKind::Closure(&Closure { body, .. }) = for_each_arg.kind + && let body = cx.tcx.hir().body(body) + && let ExprKind::Block(..) = body.value.kind + { + let mut ret_collector = RetCollector::default(); + ret_collector.visit_expr(body.value); + + // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`. + if ret_collector.ret_in_loop { + return; + } - let sugg = format!( - "for {} in {} {}", - snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability), - snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability), - snippet_with_applicability(cx, body.value.span, "..", &mut applicability), - ); + let (mut applicability, ret_suggs) = if ret_collector.spans.is_empty() { + (Applicability::MachineApplicable, None) + } else { + ( + Applicability::MaybeIncorrect, + Some( + ret_collector + .spans + .into_iter() + .map(|span| (span, "continue".to_string())) + .collect(), + ), + ) + }; + + let sugg = format!( + "for {} in {} {}", + snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability), + snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability), + snippet_with_applicability(cx, body.value.span, "..", &mut applicability), + ); - span_lint_and_then(cx, NEEDLESS_FOR_EACH, stmt.span, "needless use of `for_each`", |diag| { - diag.span_suggestion(stmt.span, "try", sugg, applicability); - if let Some(ret_suggs) = ret_suggs { - diag.multipart_suggestion("...and replace `return` with `continue`", ret_suggs, applicability); - } - }) - } + span_lint_and_then(cx, NEEDLESS_FOR_EACH, stmt.span, "needless use of `for_each`", |diag| { + diag.span_suggestion(stmt.span, "try", sugg, applicability); + if let Some(ret_suggs) = ret_suggs { + diag.multipart_suggestion("...and replace `return` with `continue`", ret_suggs, applicability); + } + }); } } } diff --git a/src/tools/clippy/clippy_lints/src/needless_if.rs b/src/tools/clippy/clippy_lints/src/needless_if.rs index 1ed7ea6b32554..41d05d7228492 100644 --- a/src/tools/clippy/clippy_lints/src/needless_if.rs +++ b/src/tools/clippy/clippy_lints/src/needless_if.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::{ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index c8888c744b667..3e63c0a1d36e7 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -10,7 +10,7 @@ use rustc_hir::{ StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -128,21 +128,18 @@ impl LocalAssign { let assign = match expr.kind { ExprKind::Block(Block { expr: Some(expr), .. }, _) => Self::from_expr(expr, expr.span), ExprKind::Block(block, _) => { - if_chain! { - if let Some((last, other_stmts)) = block.stmts.split_last(); - if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = last.kind; + if let Some((last, other_stmts)) = block.stmts.split_last() + && let StmtKind::Expr(expr) | StmtKind::Semi(expr) = last.kind - let assign = Self::from_expr(expr, last.span)?; + && let assign = Self::from_expr(expr, last.span)? // avoid visiting if not needed - if assign.lhs_id == binding_id; - if other_stmts.iter().all(|stmt| !contains_assign_expr(cx, stmt)); - - then { - Some(assign) - } else { - None - } + && assign.lhs_id == binding_id + && other_stmts.iter().all(|stmt| !contains_assign_expr(cx, stmt)) + { + Some(assign) + } else { + None } }, ExprKind::Assign(..) => Self::from_expr(expr, expr.span), @@ -368,22 +365,20 @@ fn check<'tcx>( impl<'tcx> LateLintPass<'tcx> for NeedlessLateInit { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { let mut parents = cx.tcx.hir().parent_iter(local.hir_id); - if_chain! { - if let Local { - init: None, - pat: &Pat { + if let Local { + init: None, + pat: + &Pat { kind: PatKind::Binding(BindingAnnotation::NONE, binding_id, _, None), .. }, - source: LocalSource::Normal, - .. - } = local; - if let Some((_, Node::Stmt(local_stmt))) = parents.next(); - if let Some((_, Node::Block(block))) = parents.next(); - - then { - check(cx, local, local_stmt, block, binding_id); - } + source: LocalSource::Normal, + .. + } = local + && let Some((_, Node::Stmt(local_stmt))) = parents.next() + && let Some((_, Node::Block(block))) = parents.next() + { + check(cx, local, local_stmt, block, binding_id); } } } diff --git a/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs b/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs index 7bbf1fb4cd9a8..8a62106377c54 100644 --- a/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs +++ b/src/tools/clippy/clippy_lints/src/needless_parens_on_range_literals.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -53,21 +53,23 @@ fn check_for_parens(cx: &LateContext<'_>, e: &Expr<'_>, is_start: bool) { // don't check floating point literals on the start expression of a range return; } - if_chain! { - if let ExprKind::Lit(literal) = e.kind; + if let ExprKind::Lit(literal) = e.kind // the indicator that parenthesis surround the literal is that the span of the expression and the literal differ - if (literal.span.data().hi - literal.span.data().lo) != (e.span.data().hi - e.span.data().lo); + && (literal.span.data().hi - literal.span.data().lo) != (e.span.data().hi - e.span.data().lo) // inspect the source code of the expression for parenthesis - if snippet_enclosed_in_parenthesis(&snippet(cx, e.span, "")); - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_then(cx, NEEDLESS_PARENS_ON_RANGE_LITERALS, e.span, - "needless parenthesis on range literals can be removed", - |diag| { - let suggestion = snippet_with_applicability(cx, literal.span, "_", &mut applicability); - diag.span_suggestion(e.span, "try", suggestion, applicability); - }); - } + && snippet_enclosed_in_parenthesis(&snippet(cx, e.span, "")) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_then( + cx, + NEEDLESS_PARENS_ON_RANGE_LITERALS, + e.span, + "needless parenthesis on range literals can be removed", + |diag| { + let suggestion = snippet_with_applicability(cx, literal.span, "_", &mut applicability); + diag.span_suggestion(e.span, "try", suggestion, applicability); + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index d610ba520a48f..13b736cd9ad8a 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -17,7 +17,7 @@ use rustc_middle::hir::map::associated_body; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::kw; use rustc_span::Span; @@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { return; } - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(fn_def_id); let is_async = match kind { FnKind::ItemFn(.., header) => { if header.is_unsafe() { @@ -256,7 +256,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { span_lint_hir_and_then( cx, NEEDLESS_PASS_BY_REF_MUT, - cx.tcx.hir().local_def_id_to_hir_id(*fn_def_id), + cx.tcx.local_def_id_to_hir_id(*fn_def_id), sp, "this argument is a mutable reference, but not used mutably", |diag| { diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 8fa461ac12c7e..27da44812eb1a 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -5,7 +5,6 @@ use clippy_utils::source::{snippet, snippet_opt}; use clippy_utils::ty::{ implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, }; -use if_chain::if_chain; use rustc_ast::ast::Attribute; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir::intravisit::FnKind; @@ -18,7 +17,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::kw; use rustc_span::{sym, Span}; @@ -87,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { return; } - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(fn_def_id); match kind { FnKind::ItemFn(.., header) => { @@ -177,118 +176,119 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { ) }; - if_chain! { - if !is_self(arg); - if !ty.is_mutable_ptr(); - if !is_copy(cx, ty); - if ty.is_sized(cx.tcx, cx.param_env); - if !allowed_traits.iter().any(|&t| implements_trait_with_env_from_iter( - cx.tcx, - cx.param_env, - ty, - t, - [Option::>::None], - )); - if !implements_borrow_trait; - if !all_borrowable_trait; - - if let PatKind::Binding(BindingAnnotation(_, Mutability::Not), canonical_id, ..) = arg.pat.kind; - if !moved_vars.contains(&canonical_id); - then { - // Dereference suggestion - let sugg = |diag: &mut Diagnostic| { - if let ty::Adt(def, ..) = ty.kind() { - if let Some(span) = cx.tcx.hir().span_if_local(def.did()) { - if type_allowed_to_implement_copy( - cx.tcx, - cx.param_env, - ty, - traits::ObligationCause::dummy_with_span(span), - ).is_ok() { - diag.span_help(span, "consider marking this type as `Copy`"); - } + if !is_self(arg) + && !ty.is_mutable_ptr() + && !is_copy(cx, ty) + && ty.is_sized(cx.tcx, cx.param_env) + && !allowed_traits.iter().any(|&t| { + implements_trait_with_env_from_iter( + cx.tcx, + cx.param_env, + ty, + t, + [Option::>::None], + ) + }) + && !implements_borrow_trait + && !all_borrowable_trait + && let PatKind::Binding(BindingAnnotation(_, Mutability::Not), canonical_id, ..) = arg.pat.kind + && !moved_vars.contains(&canonical_id) + { + // Dereference suggestion + let sugg = |diag: &mut Diagnostic| { + if let ty::Adt(def, ..) = ty.kind() { + if let Some(span) = cx.tcx.hir().span_if_local(def.did()) { + if type_allowed_to_implement_copy( + cx.tcx, + cx.param_env, + ty, + traits::ObligationCause::dummy_with_span(span), + ) + .is_ok() + { + diag.span_help(span, "consider marking this type as `Copy`"); } } + } - if_chain! { - if is_type_diagnostic_item(cx, ty, sym::Vec); - if let Some(clone_spans) = - get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]); - if let TyKind::Path(QPath::Resolved(_, path)) = input.kind; - if let Some(elem_ty) = path.segments.iter() - .find(|seg| seg.ident.name == sym::Vec) - .and_then(|ps| ps.args.as_ref()) - .map(|params| params.args.iter().find_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }).unwrap()); - then { - let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); - diag.span_suggestion( - input.span, - "consider changing the type to", - slice_ty, - Applicability::Unspecified, - ); - - for (span, suggestion) in clone_spans { - diag.span_suggestion( - span, - snippet_opt(cx, span) - .map_or( - "change the call to".into(), - |x| format!("change `{x}` to"), - ), - suggestion, - Applicability::Unspecified, - ); - } - - // cannot be destructured, no need for `*` suggestion - return; - } + if is_type_diagnostic_item(cx, ty, sym::Vec) + && let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]) + && let TyKind::Path(QPath::Resolved(_, path)) = input.kind + && let Some(elem_ty) = path + .segments + .iter() + .find(|seg| seg.ident.name == sym::Vec) + .and_then(|ps| ps.args.as_ref()) + .map(|params| { + params + .args + .iter() + .find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }) + .unwrap() + }) + { + let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_")); + diag.span_suggestion( + input.span, + "consider changing the type to", + slice_ty, + Applicability::Unspecified, + ); + + for (span, suggestion) in clone_spans { + diag.span_suggestion( + span, + snippet_opt(cx, span) + .map_or("change the call to".into(), |x| format!("change `{x}` to")), + suggestion, + Applicability::Unspecified, + ); } - if is_type_lang_item(cx, ty, LangItem::String) { - if let Some(clone_spans) = - get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { + // cannot be destructured, no need for `*` suggestion + return; + } + + if is_type_lang_item(cx, ty, LangItem::String) { + if let Some(clone_spans) = + get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) + { + diag.span_suggestion( + input.span, + "consider changing the type to", + "&str", + Applicability::Unspecified, + ); + + for (span, suggestion) in clone_spans { diag.span_suggestion( - input.span, - "consider changing the type to", - "&str", + span, + snippet_opt(cx, span) + .map_or("change the call to".into(), |x| format!("change `{x}` to")), + suggestion, Applicability::Unspecified, ); - - for (span, suggestion) in clone_spans { - diag.span_suggestion( - span, - snippet_opt(cx, span) - .map_or( - "change the call to".into(), - |x| format!("change `{x}` to") - ), - suggestion, - Applicability::Unspecified, - ); - } - - return; } + + return; } + } - let spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; + let spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))]; - multispan_sugg(diag, "consider taking a reference instead", spans); - }; + multispan_sugg(diag, "consider taking a reference instead", spans); + }; - span_lint_and_then( - cx, - NEEDLESS_PASS_BY_VALUE, - input.span, - "this argument is passed by value, but not consumed in the function body", - sugg, - ); - } + span_lint_and_then( + cx, + NEEDLESS_PASS_BY_VALUE, + input.span, + "this argument is passed by value, but not consumed in the function body", + sugg, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index 074c9fef1b2d5..a4d3aaf0de988 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::path_res; use clippy_utils::source::snippet; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Block, Body, CoroutineKind, CoroutineSource, Expr, ExprKind, LangItem, MatchSource, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -111,34 +110,32 @@ impl LateLintPass<'_> for NeedlessQuestionMark { } fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if let ExprKind::Call(path, [arg]) = expr.kind; - if let Res::Def(DefKind::Ctor(..), ctor_id) = path_res(cx, path); - if let Some(variant_id) = cx.tcx.opt_parent(ctor_id); - let sugg_remove = if cx.tcx.lang_items().option_some_variant() == Some(variant_id) { + if let ExprKind::Call(path, [arg]) = expr.kind + && let Res::Def(DefKind::Ctor(..), ctor_id) = path_res(cx, path) + && let Some(variant_id) = cx.tcx.opt_parent(ctor_id) + && let sugg_remove = if cx.tcx.lang_items().option_some_variant() == Some(variant_id) { "Some()" } else if cx.tcx.lang_items().result_ok_variant() == Some(variant_id) { "Ok()" } else { return; - }; - if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind; - if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind; - if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind; - if expr.span.eq_ctxt(inner_expr.span); - let expr_ty = cx.typeck_results().expr_ty(expr); - let inner_ty = cx.typeck_results().expr_ty(inner_expr); - if expr_ty == inner_ty; - then { - span_lint_and_sugg( - cx, - NEEDLESS_QUESTION_MARK, - expr.span, - "question mark operator is useless here", - &format!("try removing question mark and `{sugg_remove}`"), - format!("{}", snippet(cx, inner_expr.span, r#""...""#)), - Applicability::MachineApplicable, - ); } + && let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind + && let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind + && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind + && expr.span.eq_ctxt(inner_expr.span) + && let expr_ty = cx.typeck_results().expr_ty(expr) + && let inner_ty = cx.typeck_results().expr_ty(inner_expr) + && expr_ty == inner_ty + { + span_lint_and_sugg( + cx, + NEEDLESS_QUESTION_MARK, + expr.span, + "question mark operator is useless here", + &format!("try removing question mark and `{sugg_remove}`"), + format!("{}", snippet(cx, inner_expr.span, r#""...""#)), + Applicability::MachineApplicable, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/needless_update.rs b/src/tools/clippy/clippy_lints/src/needless_update.rs index f8888d3687888..6a2893cefbd5b 100644 --- a/src/tools/clippy/clippy_lints/src/needless_update.rs +++ b/src/tools/clippy/clippy_lints/src/needless_update.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 56c67406d6fd7..f7621822b66c4 100644 --- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::implements_trait; -use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -46,42 +45,39 @@ declare_lint_pass!(NoNegCompOpForPartialOrd => [NEG_CMP_OP_ON_PARTIAL_ORD]); impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if !in_external_macro(cx.sess(), expr.span); - if let ExprKind::Unary(UnOp::Not, inner) = expr.kind; - if let ExprKind::Binary(ref op, left, _) = inner.kind; - if let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node; + if !in_external_macro(cx.sess(), expr.span) + && let ExprKind::Unary(UnOp::Not, inner) = expr.kind + && let ExprKind::Binary(ref op, left, _) = inner.kind + && let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node + { + let ty = cx.typeck_results().expr_ty(left); - then { - let ty = cx.typeck_results().expr_ty(left); - - let implements_ord = { - if let Some(id) = cx.tcx.get_diagnostic_item(sym::Ord) { - implements_trait(cx, ty, id, &[]) - } else { - return; - } - }; - - let implements_partial_ord = { - if let Some(id) = cx.tcx.lang_items().partial_ord_trait() { - implements_trait(cx, ty, id, &[ty.into()]) - } else { - return; - } - }; + let implements_ord = { + if let Some(id) = cx.tcx.get_diagnostic_item(sym::Ord) { + implements_trait(cx, ty, id, &[]) + } else { + return; + } + }; - if implements_partial_ord && !implements_ord { - span_lint( - cx, - NEG_CMP_OP_ON_PARTIAL_ORD, - expr.span, - "the use of negated comparison operators on partially ordered \ - types produces code that is hard to read and refactor, please \ - consider using the `partial_cmp` method instead, to make it \ - clear that the two values could be incomparable", - ); + let implements_partial_ord = { + if let Some(id) = cx.tcx.lang_items().partial_ord_trait() { + implements_trait(cx, ty, id, &[ty.into()]) + } else { + return; } + }; + + if implements_partial_ord && !implements_ord { + span_lint( + cx, + NEG_CMP_OP_ON_PARTIAL_ORD, + expr.span, + "the use of negated comparison operators on partially ordered \ + types produces code that is hard to read and refactor, please \ + consider using the `partial_cmp` method instead, to make it \ + clear that the two values could be incomparable", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index 8b69f94cbba2e..f84d9fadb85c5 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -2,12 +2,11 @@ use clippy_utils::consts::{self, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::has_enclosing_paren; -use if_chain::if_chain; use rustc_ast::util::parser::PREC_PREFIX; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -53,28 +52,25 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply { } fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { - if_chain! { - if let ExprKind::Lit(l) = lit.kind; - if consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1); - if cx.typeck_results().expr_ty(exp).is_integral(); - - then { - let mut applicability = Applicability::MachineApplicable; - let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability); - let suggestion = if !from_macro && exp.precedence().order() < PREC_PREFIX && !has_enclosing_paren(&snip) { - format!("-({snip})") - } else { - format!("-{snip}") - }; - span_lint_and_sugg( - cx, - NEG_MULTIPLY, - span, - "this multiplication by -1 can be written more succinctly", - "consider using", - suggestion, - applicability, - ); - } + if let ExprKind::Lit(l) = lit.kind + && consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1) + && cx.typeck_results().expr_ty(exp).is_integral() + { + let mut applicability = Applicability::MachineApplicable; + let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability); + let suggestion = if !from_macro && exp.precedence().order() < PREC_PREFIX && !has_enclosing_paren(&snip) { + format!("-({snip})") + } else { + format!("-{snip}") + }; + span_lint_and_sugg( + cx, + NEG_MULTIPLY, + span, + "this multiplication by -1 can be written more succinctly", + "consider using", + suggestion, + applicability, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index f7f9dccfbceb4..9de6ad4213755 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -2,13 +2,12 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::return_ty; use clippy_utils::source::snippet; use clippy_utils::sugg::DiagnosticExt; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::HirIdSet; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -93,73 +92,69 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { // an impl of `Default` return; } - if_chain! { - if sig.decl.inputs.is_empty(); - if name == sym::new; - if cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id); - let self_def_id = cx.tcx.hir().get_parent_item(id.into()); - let self_ty = cx.tcx.type_of(self_def_id).instantiate_identity(); - if self_ty == return_ty(cx, id); - if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default); - then { - if self.impling_types.is_none() { - let mut impls = HirIdSet::default(); - cx.tcx.for_each_impl(default_trait_id, |d| { - let ty = cx.tcx.type_of(d).instantiate_identity(); - if let Some(ty_def) = ty.ty_adt_def() { - if let Some(local_def_id) = ty_def.did().as_local() { - impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id)); - } + if sig.decl.inputs.is_empty() + && name == sym::new + && cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id) + && let self_def_id = cx.tcx.hir().get_parent_item(id.into()) + && let self_ty = cx.tcx.type_of(self_def_id).instantiate_identity() + && self_ty == return_ty(cx, id) + && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) + { + if self.impling_types.is_none() { + let mut impls = HirIdSet::default(); + cx.tcx.for_each_impl(default_trait_id, |d| { + let ty = cx.tcx.type_of(d).instantiate_identity(); + if let Some(ty_def) = ty.ty_adt_def() { + if let Some(local_def_id) = ty_def.did().as_local() { + impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id)); } - }); - self.impling_types = Some(impls); - } - - // Check if a Default implementation exists for the Self type, regardless of - // generics - if_chain! { - if let Some(ref impling_types) = self.impling_types; - let self_def = cx.tcx.type_of(self_def_id).instantiate_identity(); - if let Some(self_def) = self_def.ty_adt_def(); - if let Some(self_local_did) = self_def.did().as_local(); - let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did); - if impling_types.contains(&self_id); - then { - return; } - } + }); + self.impling_types = Some(impls); + } - let generics_sugg = snippet(cx, generics.span, ""); - let where_clause_sugg = if generics.has_where_clause_predicates { - format!("\n{}\n", snippet(cx, generics.where_clause_span, "")) - } else { - String::new() - }; - let self_ty_fmt = self_ty.to_string(); - let self_type_snip = snippet(cx, impl_self_ty.span, &self_ty_fmt); - span_lint_hir_and_then( - cx, - NEW_WITHOUT_DEFAULT, - id.into(), - impl_item.span, - &format!( - "you should consider adding a `Default` implementation for `{self_type_snip}`" - ), - |diag| { - diag.suggest_prepend_item( - cx, - item.span, - "try adding this", - &create_new_without_default_suggest_msg( - &self_type_snip, - &generics_sugg, - &where_clause_sugg - ), - Applicability::MachineApplicable, - ); - }, - ); + // Check if a Default implementation exists for the Self type, regardless of + // generics + if let Some(ref impling_types) = self.impling_types + && let self_def = cx.tcx.type_of(self_def_id).instantiate_identity() + && let Some(self_def) = self_def.ty_adt_def() + && let Some(self_local_did) = self_def.did().as_local() + && let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did) + && impling_types.contains(&self_id) + { + return; } + + let generics_sugg = snippet(cx, generics.span, ""); + let where_clause_sugg = if generics.has_where_clause_predicates { + format!("\n{}\n", snippet(cx, generics.where_clause_span, "")) + } else { + String::new() + }; + let self_ty_fmt = self_ty.to_string(); + let self_type_snip = snippet(cx, impl_self_ty.span, &self_ty_fmt); + span_lint_hir_and_then( + cx, + NEW_WITHOUT_DEFAULT, + id.into(), + impl_item.span, + &format!( + "you should consider adding a `Default` implementation for `{self_type_snip}`" + ), + |diag| { + diag.suggest_prepend_item( + cx, + item.span, + "try adding this", + &create_new_without_default_suggest_msg( + &self_type_snip, + &generics_sugg, + &where_clause_sugg, + ), + Applicability::MachineApplicable, + ); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 3a28e511fdda7..6e65dd628a447 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -10,7 +10,7 @@ use rustc_hir::{ use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use std::ops::Deref; declare_clippy_lint! { @@ -132,24 +132,22 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { return true; } } else if let StmtKind::Local(local) = stmt.kind { - if_chain! { - if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id); - if let Some(init) = local.init; - if local.els.is_none(); - if !local.pat.span.from_expansion(); - if has_no_effect(cx, init); - if let PatKind::Binding(_, _, ident, _) = local.pat.kind; - if ident.name.to_ident_string().starts_with('_'); - then { - span_lint_hir( - cx, - NO_EFFECT_UNDERSCORE_BINDING, - init.hir_id, - stmt.span, - "binding to `_` prefixed variable with no side-effect" - ); - return true; - } + if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) + && let Some(init) = local.init + && local.els.is_none() + && !local.pat.span.from_expansion() + && has_no_effect(cx, init) + && let PatKind::Binding(_, _, ident, _) = local.pat.kind + && ident.name.to_ident_string().starts_with('_') + { + span_lint_hir( + cx, + NO_EFFECT_UNDERSCORE_BINDING, + init.hir_id, + stmt.span, + "binding to `_` prefixed variable with no side-effect", + ); + return true; } } false @@ -199,63 +197,60 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) { - if_chain! { - if let StmtKind::Semi(expr) = stmt.kind; - let ctxt = stmt.span.ctxt(); - if expr.span.ctxt() == ctxt; - if let Some(reduced) = reduce_expression(cx, expr); - if !in_external_macro(cx.sess(), stmt.span); - if reduced.iter().all(|e| e.span.ctxt() == ctxt); - then { - if let ExprKind::Index(..) = &expr.kind { - let snippet = if let (Some(arr), Some(func)) = - (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) - { + if let StmtKind::Semi(expr) = stmt.kind + && let ctxt = stmt.span.ctxt() + && expr.span.ctxt() == ctxt + && let Some(reduced) = reduce_expression(cx, expr) + && !in_external_macro(cx.sess(), stmt.span) + && reduced.iter().all(|e| e.span.ctxt() == ctxt) + { + if let ExprKind::Index(..) = &expr.kind { + let snippet = + if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) { format!("assert!({}.len() > {});", &arr, &func) } else { return; }; - span_lint_hir_and_then( - cx, - UNNECESSARY_OPERATION, - expr.hir_id, - stmt.span, - "unnecessary operation", - |diag| { - diag.span_suggestion( - stmt.span, - "statement can be written as", - snippet, - Applicability::MaybeIncorrect, - ); - }, - ); - } else { - let mut snippet = String::new(); - for e in reduced { - if let Some(snip) = snippet_opt(cx, e.span) { - snippet.push_str(&snip); - snippet.push(';'); - } else { - return; - } + span_lint_hir_and_then( + cx, + UNNECESSARY_OPERATION, + expr.hir_id, + stmt.span, + "unnecessary operation", + |diag| { + diag.span_suggestion( + stmt.span, + "statement can be written as", + snippet, + Applicability::MaybeIncorrect, + ); + }, + ); + } else { + let mut snippet = String::new(); + for e in reduced { + if let Some(snip) = snippet_opt(cx, e.span) { + snippet.push_str(&snip); + snippet.push(';'); + } else { + return; } - span_lint_hir_and_then( - cx, - UNNECESSARY_OPERATION, - expr.hir_id, - stmt.span, - "unnecessary operation", - |diag| { - diag.span_suggestion( - stmt.span, - "statement can be reduced to", - snippet, - Applicability::MachineApplicable, - ); - }, - ); } + span_lint_hir_and_then( + cx, + UNNECESSARY_OPERATION, + expr.hir_id, + stmt.span, + "unnecessary operation", + |diag| { + diag.span_suggestion( + stmt.span, + "statement can be reduced to", + snippet, + Applicability::MachineApplicable, + ); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs index 04d750148921e..8d5a523fd8f6a 100644 --- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Pos}; use rustc_target::spec::abi::Abi; diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs index 9689f63a01358..63050080ac6d5 100644 --- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs +++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, LangItem, Node, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::EarlyBinder; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; use rustc_span::symbol::kw; diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 54cec066ba10c..4f8922aea1787 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -7,7 +7,6 @@ use std::ptr; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::macro_backtrace; use clippy_utils::{def_path_def_ids, in_constant}; -use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -19,7 +18,7 @@ use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId}; use rustc_middle::query::Key; use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{sym, InnerSpan, Span}; use rustc_target::abi::VariantIdx; @@ -386,15 +385,14 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { of_trait: Some(of_trait_ref), .. }) => { - if_chain! { + if let Some(of_trait_def_id) = of_trait_ref.trait_def_id() // Lint a trait impl item only when the definition is a generic type, // assuming an assoc const is not meant to be an interior mutable type. - if let Some(of_trait_def_id) = of_trait_ref.trait_def_id(); - if let Some(of_assoc_item) = cx + && let Some(of_assoc_item) = cx .tcx .associated_item(impl_item.owner_id) - .trait_item_def_id; - if cx + .trait_item_def_id + && cx .tcx .layout_of(cx.tcx.param_env(of_trait_def_id).and( // Normalize assoc types because ones originated from generic params @@ -405,23 +403,17 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { cx.tcx.type_of(of_assoc_item).instantiate_identity(), ), )) - .is_err(); + .is_err() // If there were a function like `has_frozen_variant` described above, // we should use here as a frozen variant is a potential to be frozen // similar to unknown layouts. // e.g. `layout_of(...).is_err() || has_frozen_variant(...);` - let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity(); - let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); - if !self.is_ty_ignored(ty) && Self::is_unfrozen(cx, normalized); - if self.is_value_unfrozen_poly(cx, *body_id, normalized); - then { - lint( - cx, - Source::Assoc { - item: impl_item.span, - }, - ); - } + && let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity() + && let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty) + && !self.is_ty_ignored(ty) && Self::is_unfrozen(cx, normalized) + && self.is_value_unfrozen_poly(cx, *body_id, normalized) + { + lint(cx, Source::Assoc { item: impl_item.span }); } }, ItemKind::Impl(Impl { of_trait: None, .. }) => { diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs index 61622034d1aad..ba9230dab7aee 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -5,9 +5,9 @@ use rustc_ast::ast::{ use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::{sym, Span}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::{sym, Span}; use std::cmp::Ordering; declare_clippy_lint! { @@ -341,7 +341,9 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { self.apply(|this| { SimilarNamesNameVisitor(this).visit_pat(&arm.pat); - this.apply(|this| walk_expr(this, &arm.body)); + if let Some(body) = &arm.body { + this.apply(|this| walk_expr(this, body)); + } }); self.check_single_char_names(); diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs index e94e458996601..49e9e2c00ccb0 100644 --- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs +++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{snippet_opt, snippet_with_applicability}; use clippy_utils::{match_def_path, paths}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -44,38 +43,36 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { match &expr.kind { ExprKind::MethodCall(path, func, [param], _) => { - if_chain! { - if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def(); - if (path.ident.name == sym!(mode) - && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::FsOpenOptions | sym::DirBuilder))) + if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def() + && ((path.ident.name == sym!(mode) + && matches!( + cx.tcx.get_diagnostic_name(adt.did()), + Some(sym::FsOpenOptions | sym::DirBuilder) + )) || (path.ident.name == sym!(set_mode) - && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did())); - if let ExprKind::Lit(_) = param.kind; - if param.span.eq_ctxt(expr.span); + && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did()))) + && let ExprKind::Lit(_) = param.kind + && param.span.eq_ctxt(expr.span) + { + let Some(snip) = snippet_opt(cx, param.span) else { + return; + }; - then { - let Some(snip) = snippet_opt(cx, param.span) else { - return - }; - - if !snip.starts_with("0o") { - show_error(cx, param); - } + if !snip.starts_with("0o") { + show_error(cx, param); } } }, ExprKind::Call(func, [param]) => { - if_chain! { - if let ExprKind::Path(ref path) = func.kind; - if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id(); - if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE); - if let ExprKind::Lit(_) = param.kind; - if param.span.eq_ctxt(expr.span); - if let Some(snip) = snippet_opt(cx, param.span); - if !snip.starts_with("0o"); - then { - show_error(cx, param); - } + if let ExprKind::Path(ref path) = func.kind + && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id() + && match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE) + && let ExprKind::Lit(_) = param.kind + && param.span.eq_ctxt(expr.span) + && let Some(snip) = snippet_opt(cx, param.span) + && !snip.starts_with("0o") + { + show_error(cx, param); } }, _ => {}, diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index 62ef48c8a90cc..352540d70b52c 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -8,7 +8,7 @@ use rustc_hir::{FieldDef, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, GenericArgKind, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -81,73 +81,74 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { // We start from `Send` impl instead of `check_field_def()` because // single `AdtDef` may have multiple `Send` impls due to generic // parameters, and the lint is much easier to implement in this way. - if_chain! { - if !in_external_macro(cx.tcx.sess, item.span); - if let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send); - if let ItemKind::Impl(hir_impl) = &item.kind; - if let Some(trait_ref) = &hir_impl.of_trait; - if let Some(trait_id) = trait_ref.trait_def_id(); - if send_trait == trait_id; - if hir_impl.polarity == ImplPolarity::Positive; - if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); - if let self_ty = ty_trait_ref.instantiate_identity().self_ty(); - if let ty::Adt(adt_def, impl_trait_args) = self_ty.kind(); - then { - let mut non_send_fields = Vec::new(); - - let hir_map = cx.tcx.hir(); - for variant in adt_def.variants() { - for field in &variant.fields { - if_chain! { - if let Some(field_hir_id) = field - .did - .as_local() - .map(|local_def_id| hir_map.local_def_id_to_hir_id(local_def_id)); - if !is_lint_allowed(cx, NON_SEND_FIELDS_IN_SEND_TY, field_hir_id); - if let field_ty = field.ty(cx.tcx, impl_trait_args); - if !ty_allowed_in_send(cx, field_ty, send_trait); - if let Node::Field(field_def) = hir_map.get(field_hir_id); - then { - non_send_fields.push(NonSendField { - def: field_def, - ty: field_ty, - generic_params: collect_generic_params(field_ty), - }) - } - } + if !in_external_macro(cx.tcx.sess, item.span) + && let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send) + && let ItemKind::Impl(hir_impl) = &item.kind + && let Some(trait_ref) = &hir_impl.of_trait + && let Some(trait_id) = trait_ref.trait_def_id() + && send_trait == trait_id + && hir_impl.polarity == ImplPolarity::Positive + && let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) + && let self_ty = ty_trait_ref.instantiate_identity().self_ty() + && let ty::Adt(adt_def, impl_trait_args) = self_ty.kind() + { + let mut non_send_fields = Vec::new(); + + let hir_map = cx.tcx.hir(); + for variant in adt_def.variants() { + for field in &variant.fields { + if let Some(field_hir_id) = field + .did + .as_local() + .map(|local_def_id| cx.tcx.local_def_id_to_hir_id(local_def_id)) + && !is_lint_allowed(cx, NON_SEND_FIELDS_IN_SEND_TY, field_hir_id) + && let field_ty = field.ty(cx.tcx, impl_trait_args) + && !ty_allowed_in_send(cx, field_ty, send_trait) + && let Node::Field(field_def) = hir_map.get(field_hir_id) + { + non_send_fields.push(NonSendField { + def: field_def, + ty: field_ty, + generic_params: collect_generic_params(field_ty), + }); } } + } - if !non_send_fields.is_empty() { - span_lint_and_then( - cx, - NON_SEND_FIELDS_IN_SEND_TY, - item.span, - &format!( - "some fields in `{}` are not safe to be sent to another thread", - snippet(cx, hir_impl.self_ty.span, "Unknown") - ), - |diag| { - for field in non_send_fields { - diag.span_note( - field.def.span, - format!("it is not safe to send field `{}` to another thread", field.def.ident.name), - ); - - match field.generic_params.len() { - 0 => diag.help("use a thread-safe type that implements `Send`"), - 1 if is_ty_param(field.ty) => diag.help(format!("add `{}: Send` bound in `Send` impl", field.ty)), - _ => diag.help(format!( - "add bounds on type parameter{} `{}` that satisfy `{}: Send`", - if field.generic_params.len() > 1 { "s" } else { "" }, - field.generic_params_string(), - snippet(cx, field.def.ty.span, "Unknown"), - )), - }; - } - }, - ); - } + if !non_send_fields.is_empty() { + span_lint_and_then( + cx, + NON_SEND_FIELDS_IN_SEND_TY, + item.span, + &format!( + "some fields in `{}` are not safe to be sent to another thread", + snippet(cx, hir_impl.self_ty.span, "Unknown") + ), + |diag| { + for field in non_send_fields { + diag.span_note( + field.def.span, + format!( + "it is not safe to send field `{}` to another thread", + field.def.ident.name + ), + ); + + match field.generic_params.len() { + 0 => diag.help("use a thread-safe type that implements `Send`"), + 1 if is_ty_param(field.ty) => { + diag.help(format!("add `{}: Send` bound in `Send` impl", field.ty)) + }, + _ => diag.help(format!( + "add bounds on type parameter{} `{}` that satisfy `{}: Send`", + if field.generic_params.len() > 1 { "s" } else { "" }, + field.generic_params_string(), + snippet(cx, field.def.ty.span, "Unknown"), + )), + }; + } + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs index 11c3a5417b556..1c6069e9c6507 100644 --- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs +++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs @@ -1,13 +1,12 @@ use clippy_config::types::MacroMatcher; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; -use if_chain::if_chain; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::Span; @@ -34,17 +33,17 @@ declare_clippy_lint! { } /// The (callsite span, (open brace, close brace), source snippet) -type MacroInfo<'a> = (Span, &'a (String, String), String); +type MacroInfo = (Span, (char, char), String); -#[derive(Clone, Debug, Default)] +#[derive(Debug)] pub struct MacroBraces { - macro_braces: FxHashMap, + macro_braces: FxHashMap, done: FxHashSet, } impl MacroBraces { - pub fn new(conf: &FxHashSet) -> Self { - let macro_braces = macro_braces(conf.clone()); + pub fn new(conf: &[MacroMatcher]) -> Self { + let macro_braces = macro_braces(conf); Self { macro_braces, done: FxHashSet::default(), @@ -84,7 +83,7 @@ impl EarlyLintPass for MacroBraces { } } -fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a MacroBraces) -> Option> { +fn is_offending_macro(cx: &EarlyContext<'_>, span: Span, mac_braces: &MacroBraces) -> Option { let unnested_or_local = || { !span.ctxt().outer_expn_data().call_site.from_expansion() || span @@ -93,28 +92,26 @@ fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a Mac .map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local)) }; let span_call_site = span.ctxt().outer_expn_data().call_site; - if_chain! { - if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind; - let name = mac_name.as_str(); - if let Some(braces) = mac_braces.macro_braces.get(name); - if let Some(snip) = snippet_opt(cx, span_call_site); + if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind + && let name = mac_name.as_str() + && let Some(&braces) = mac_braces.macro_braces.get(name) + && let Some(snip) = snippet_opt(cx, span_call_site) // we must check only invocation sites // https://github.com/rust-lang/rust-clippy/issues/7422 - if snip.starts_with(&format!("{name}!")); - if unnested_or_local(); + && snip.starts_with(&format!("{name}!")) + && unnested_or_local() // make formatting consistent - let c = snip.replace(' ', ""); - if !c.starts_with(&format!("{name}!{}", braces.0)); - if !mac_braces.done.contains(&span_call_site); - then { - Some((span_call_site, braces, snip)) - } else { - None - } + && let c = snip.replace(' ', "") + && !c.starts_with(&format!("{name}!{}", braces.0)) + && !mac_braces.done.contains(&span_call_site) + { + Some((span_call_site, braces, snip)) + } else { + None } } -fn emit_help(cx: &EarlyContext<'_>, snip: &str, braces: &(String, String), span: Span) { +fn emit_help(cx: &EarlyContext<'_>, snip: &str, (open, close): (char, char), span: Span) { if let Some((macro_name, macro_args_str)) = snip.split_once('!') { let mut macro_args = macro_args_str.trim().to_string(); // now remove the wrong braces @@ -126,67 +123,31 @@ fn emit_help(cx: &EarlyContext<'_>, snip: &str, braces: &(String, String), span: span, &format!("use of irregular braces for `{macro_name}!` macro"), "consider writing", - format!("{macro_name}!{}{macro_args}{}", braces.0, braces.1), + format!("{macro_name}!{open}{macro_args}{close}"), Applicability::MachineApplicable, ); } } -fn macro_braces(conf: FxHashSet) -> FxHashMap { - let mut braces = vec![ - macro_matcher!( - name: "print", - braces: ("(", ")"), - ), - macro_matcher!( - name: "println", - braces: ("(", ")"), - ), - macro_matcher!( - name: "eprint", - braces: ("(", ")"), - ), - macro_matcher!( - name: "eprintln", - braces: ("(", ")"), - ), - macro_matcher!( - name: "write", - braces: ("(", ")"), - ), - macro_matcher!( - name: "writeln", - braces: ("(", ")"), - ), - macro_matcher!( - name: "format", - braces: ("(", ")"), - ), - macro_matcher!( - name: "format_args", - braces: ("(", ")"), - ), - macro_matcher!( - name: "vec", - braces: ("[", "]"), - ), - macro_matcher!( - name: "matches", - braces: ("(", ")"), - ), - ] - .into_iter() - .collect::>(); +fn macro_braces(conf: &[MacroMatcher]) -> FxHashMap { + let mut braces = FxHashMap::from_iter( + [ + ("print", ('(', ')')), + ("println", ('(', ')')), + ("eprint", ('(', ')')), + ("eprintln", ('(', ')')), + ("write", ('(', ')')), + ("writeln", ('(', ')')), + ("format", ('(', ')')), + ("format_args", ('(', ')')), + ("vec", ('[', ']')), + ("matches", ('(', ')')), + ] + .map(|(k, v)| (k.to_string(), v)), + ); // We want users items to override any existing items for it in conf { - braces.insert(it.name, it.braces); + braces.insert(it.name.clone(), it.braces); } braces } - -macro_rules! macro_matcher { - (name: $name:expr, braces: ($open:expr, $close:expr) $(,)?) => { - ($name.to_owned(), ($open.to_owned(), $close.to_owned())) - }; -} -pub(crate) use macro_matcher; diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs index 0faf4ce3d3e61..8822dfeedddb7 100644 --- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs +++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs @@ -4,7 +4,7 @@ use rustc_ast::token::{Lit, LitKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; use std::fmt::Write; diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index ef7b367649f82..d621051ef1653 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -8,7 +8,7 @@ use rustc_hir::hir_id::HirIdMap; use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Node, PatKind, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, ConstKind, EarlyBinder, GenericArgKind, GenericArgsRef}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; use std::iter; diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index f7d9650b2f8db..1a2b20bf43877 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -7,9 +7,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::impl_lint_pass; -use rustc_span::{Span, Symbol}; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; +use rustc_span::{Span, Symbol}; use {rustc_ast as ast, rustc_hir as hir}; const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[["f32", "f32"], ["f64", "f64"], ["std::string::String", "str"]]; diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs index c4572a09db619..2f85130fba118 100644 --- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -4,7 +4,6 @@ use clippy_utils::ty::implements_trait; use clippy_utils::visitors::for_each_expr; use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method}; use core::ops::ControlFlow; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; @@ -25,43 +24,40 @@ pub(super) fn check<'tcx>( let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| { let ty = cx.typeck_results().expr_ty(assignee); let rty = cx.typeck_results().expr_ty(rhs); - if_chain! { - if let Some((_, lang_item)) = binop_traits(op.node); - if let Some(trait_id) = cx.tcx.lang_items().get(lang_item); - let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id; - if trait_ref_of_method(cx, parent_fn) - .map_or(true, |t| t.path.res.def_id() != trait_id); - if implements_trait(cx, ty, trait_id, &[rty.into()]); - then { - // Primitive types execute assign-ops right-to-left. Every other type is left-to-right. - if !(ty.is_primitive() && rty.is_primitive()) { - // TODO: This will have false negatives as it doesn't check if the borrows are - // actually live at the end of their respective expressions. - let mut_borrows = mut_borrows_in_expr(cx, assignee); - let imm_borrows = imm_borrows_in_expr(cx, rhs); - if mut_borrows.iter().any(|id| imm_borrows.contains(id)) { - return; - } + if let Some((_, lang_item)) = binop_traits(op.node) + && let Some(trait_id) = cx.tcx.lang_items().get(lang_item) + && let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id + && trait_ref_of_method(cx, parent_fn).map_or(true, |t| t.path.res.def_id() != trait_id) + && implements_trait(cx, ty, trait_id, &[rty.into()]) + { + // Primitive types execute assign-ops right-to-left. Every other type is left-to-right. + if !(ty.is_primitive() && rty.is_primitive()) { + // TODO: This will have false negatives as it doesn't check if the borrows are + // actually live at the end of their respective expressions. + let mut_borrows = mut_borrows_in_expr(cx, assignee); + let imm_borrows = imm_borrows_in_expr(cx, rhs); + if mut_borrows.iter().any(|id| imm_borrows.contains(id)) { + return; } - span_lint_and_then( - cx, - ASSIGN_OP_PATTERN, - expr.span, - "manual implementation of an assign operation", - |diag| { - if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) - { - diag.span_suggestion( - expr.span, - "replace it with", - format!("{snip_a} {}= {snip_r}", op.node.as_str()), - Applicability::MachineApplicable, - ); - } - }, - ); } + span_lint_and_then( + cx, + ASSIGN_OP_PATTERN, + expr.span, + "manual implementation of an assign operation", + |diag| { + if let (Some(snip_a), Some(snip_r)) = + (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + { + diag.span_suggestion( + expr.span, + "replace it with", + format!("{snip_a} {}= {snip_r}", op.node.as_str()), + Applicability::MachineApplicable, + ); + } + }, + ); } }; diff --git a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs index ec2bb869973f1..e278cf9835a90 100644 --- a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs @@ -3,13 +3,12 @@ use std::cmp::Ordering; use clippy_utils::consts::{constant, Constant}; -use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{Ty, TypeckResults}; -use rustc_span::Span; use rustc_span::source_map::Spanned; +use rustc_span::Span; use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::source::snippet; @@ -24,19 +23,17 @@ fn comparison_to_const<'tcx>( typeck: &TypeckResults<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Option<(CmpOp, &'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Constant<'tcx>, Ty<'tcx>)> { - if_chain! { - if let ExprKind::Binary(operator, left, right) = expr.kind; - if let Ok(cmp_op) = CmpOp::try_from(operator.node); - then { - match (constant(cx, typeck, left), constant(cx, typeck, right)) { - (Some(_), Some(_)) => None, - (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))), - (Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))), - _ => None, - } - } else { - None + if let ExprKind::Binary(operator, left, right) = expr.kind + && let Ok(cmp_op) = CmpOp::try_from(operator.node) + { + match (constant(cx, typeck, left), constant(cx, typeck, right)) { + (Some(_), Some(_)) => None, + (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))), + (Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))), + _ => None, } + } else { + None } } @@ -47,87 +44,89 @@ pub(super) fn check<'tcx>( right_cond: &'tcx Expr<'tcx>, span: Span, ) { - if_chain! { + if and_op.node == BinOpKind::And // Ensure that the binary operator is && - if and_op.node == BinOpKind::And; // Check that both operands to '&&' are themselves a binary operation // The `comparison_to_const` step also checks this, so this step is just an optimization - if let ExprKind::Binary(_, _, _) = left_cond.kind; - if let ExprKind::Binary(_, _, _) = right_cond.kind; + && let ExprKind::Binary(_, _, _) = left_cond.kind + && let ExprKind::Binary(_, _, _) = right_cond.kind - let typeck = cx.typeck_results(); + && let typeck = cx.typeck_results() // Check that both operands to '&&' compare a non-literal to a literal - if let Some((left_cmp_op, left_expr, left_const_expr, left_const, left_type)) = - comparison_to_const(cx, typeck, left_cond); - if let Some((right_cmp_op, right_expr, right_const_expr, right_const, right_type)) = - comparison_to_const(cx, typeck, right_cond); + && let Some((left_cmp_op, left_expr, left_const_expr, left_const, left_type)) = + comparison_to_const(cx, typeck, left_cond) + && let Some((right_cmp_op, right_expr, right_const_expr, right_const, right_type)) = + comparison_to_const(cx, typeck, right_cond) - if left_type == right_type; + && left_type == right_type // Check that the same expression is compared in both comparisons - if SpanlessEq::new(cx).eq_expr(left_expr, right_expr); + && SpanlessEq::new(cx).eq_expr(left_expr, right_expr) - if !left_expr.can_have_side_effects(); + && !left_expr.can_have_side_effects() // Compare the two constant expressions - if let Some(ordering) = Constant::partial_cmp(cx.tcx(), left_type, &left_const, &right_const); + && let Some(ordering) = Constant::partial_cmp(cx.tcx(), left_type, &left_const, &right_const) // Rule out the `x >= 42 && x <= 42` corner case immediately // Mostly to simplify the implementation, but it is also covered by `clippy::double_comparisons` - if !matches!( + && !matches!( (&left_cmp_op, &right_cmp_op, ordering), (CmpOp::Le | CmpOp::Ge, CmpOp::Le | CmpOp::Ge, Ordering::Equal) - ); - - then { - if left_cmp_op.direction() == right_cmp_op.direction() { - let lhs_str = snippet(cx, left_cond.span, ""); - let rhs_str = snippet(cx, right_cond.span, ""); - // We already know that either side of `&&` has no effect, - // but emit a different error message depending on which side it is - if left_side_is_useless(left_cmp_op, ordering) { - span_lint_and_note( - cx, - REDUNDANT_COMPARISONS, - span, - "left-hand side of `&&` operator has no effect", - Some(left_cond.span.until(right_cond.span)), - &format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"), - ); - } else { - span_lint_and_note( - cx, - REDUNDANT_COMPARISONS, - span, - "right-hand side of `&&` operator has no effect", - Some(and_op.span.to(right_cond.span)), - &format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"), - ); - } - // We could autofix this error but choose not to, - // because code triggering this lint probably not behaving correctly in the first place - } - else if !comparison_is_possible(left_cmp_op.direction(), ordering) { - let expr_str = snippet(cx, left_expr.span, ".."); - let lhs_str = snippet(cx, left_const_expr.span, ""); - let rhs_str = snippet(cx, right_const_expr.span, ""); - let note = match ordering { - Ordering::Less => format!("since `{lhs_str}` < `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"), - Ordering::Equal => format!("`{expr_str}` cannot simultaneously be greater than and less than `{lhs_str}`"), - Ordering::Greater => format!("since `{lhs_str}` > `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"), - }; + ) + { + if left_cmp_op.direction() == right_cmp_op.direction() { + let lhs_str = snippet(cx, left_cond.span, ""); + let rhs_str = snippet(cx, right_cond.span, ""); + // We already know that either side of `&&` has no effect, + // but emit a different error message depending on which side it is + if left_side_is_useless(left_cmp_op, ordering) { span_lint_and_note( cx, - IMPOSSIBLE_COMPARISONS, + REDUNDANT_COMPARISONS, span, - "boolean expression will never evaluate to 'true'", - None, - ¬e, + "left-hand side of `&&` operator has no effect", + Some(left_cond.span.until(right_cond.span)), + &format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"), ); + } else { + span_lint_and_note( + cx, + REDUNDANT_COMPARISONS, + span, + "right-hand side of `&&` operator has no effect", + Some(and_op.span.to(right_cond.span)), + &format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"), + ); + } + // We could autofix this error but choose not to, + // because code triggering this lint probably not behaving correctly in the first place + } else if !comparison_is_possible(left_cmp_op.direction(), ordering) { + let expr_str = snippet(cx, left_expr.span, ".."); + let lhs_str = snippet(cx, left_const_expr.span, ""); + let rhs_str = snippet(cx, right_const_expr.span, ""); + let note = match ordering { + Ordering::Less => format!( + "since `{lhs_str}` < `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`" + ), + Ordering::Equal => { + format!("`{expr_str}` cannot simultaneously be greater than and less than `{lhs_str}`") + }, + Ordering::Greater => format!( + "since `{lhs_str}` > `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`" + ), }; - } + span_lint_and_note( + cx, + IMPOSSIBLE_COMPARISONS, + span, + "boolean expression will never evaluate to 'true'", + None, + ¬e, + ); + }; } } diff --git a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs index fd3502ad878cc..01dd418c38be3 100644 --- a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs @@ -36,7 +36,7 @@ pub(crate) fn check<'tcx>( left: &'tcx Expr<'_>, right: &'tcx Expr<'_>, ) { - if is_useless_with_eq_exprs(op.into()) && eq_expr_value(cx, left, right) && !is_in_test_function(cx.tcx, e.hir_id) { + if is_useless_with_eq_exprs(op) && eq_expr_value(cx, left, right) && !is_in_test_function(cx.tcx, e.hir_id) { span_lint_and_then( cx, EQ_OP, diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs index bce6bdcaf61cd..0561739d160f8 100644 --- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs +++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs @@ -2,7 +2,6 @@ use clippy_utils::consts::{constant_with_source, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::get_item_name; use clippy_utils::sugg::Sugg; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::LateContext; @@ -105,14 +104,12 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { return is_signum(cx, child_expr); } - if_chain! { - if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind; - if sym!(signum) == method_name.ident.name; - // Check that the receiver of the signum() is a float (expressions[0] is the receiver of - // the method call) - then { - return is_float(cx, self_arg); - } + if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind + && sym!(signum) == method_name.ident.name + // Check that the receiver of the signum() is a float (expressions[0] is the receiver of + // the method call) + { + return is_float(cx, self_arg); } false } diff --git a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs index a0a8b6aabd9e3..cace85a245139 100644 --- a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs +++ b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{match_def_path, paths, sugg}; -use if_chain::if_chain; use rustc_ast::util::parser::AssocOp; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -24,48 +23,43 @@ pub(crate) fn check<'tcx>( _ => return, }; - if_chain! { + if let ExprKind::Binary( // left hand side is a subtraction - if let ExprKind::Binary( Spanned { node: BinOpKind::Sub, .. }, val_l, val_r, - ) = lhs.kind; + ) = lhs.kind // right hand side matches either f32::EPSILON or f64::EPSILON - if let ExprKind::Path(ref epsilon_path) = rhs.kind; - if let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id); - if match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON); + && let ExprKind::Path(ref epsilon_path) = rhs.kind + && let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id) + && (match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON)) // values of the subtractions on the left hand side are of the type float - let t_val_l = cx.typeck_results().expr_ty(val_l); - let t_val_r = cx.typeck_results().expr_ty(val_r); - if let ty::Float(_) = t_val_l.kind(); - if let ty::Float(_) = t_val_r.kind(); - - then { - let sug_l = sugg::Sugg::hir(cx, val_l, ".."); - let sug_r = sugg::Sugg::hir(cx, val_r, ".."); - // format the suggestion - let suggestion = format!("{}.abs()", sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()); - // spans the lint - span_lint_and_then( - cx, - FLOAT_EQUALITY_WITHOUT_ABS, - expr.span, - "float equality check without `.abs()`", - | diag | { - diag.span_suggestion( - lhs.span, - "add `.abs()`", - suggestion, - Applicability::MaybeIncorrect, - ); - } - ); - } + && let t_val_l = cx.typeck_results().expr_ty(val_l) + && let t_val_r = cx.typeck_results().expr_ty(val_r) + && let ty::Float(_) = t_val_l.kind() + && let ty::Float(_) = t_val_r.kind() + { + let sug_l = sugg::Sugg::hir(cx, val_l, ".."); + let sug_r = sugg::Sugg::hir(cx, val_r, ".."); + // format the suggestion + let suggestion = format!( + "{}.abs()", + sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par() + ); + // spans the lint + span_lint_and_then( + cx, + FLOAT_EQUALITY_WITHOUT_ABS, + expr.span, + "float equality check without `.abs()`", + |diag| { + diag.span_suggestion(lhs.span, "add `.abs()`", suggestion, Applicability::MaybeIncorrect); + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs index 5eabb349ec107..fecc5a8578ed2 100644 --- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs @@ -46,7 +46,7 @@ fn lint_misrefactored_assign_op( if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) { let a = &sugg::Sugg::hir(cx, assignee, ".."); let r = &sugg::Sugg::hir(cx, rhs, ".."); - let long = format!("{snip_a} = {}", sugg::make_binop(op.into(), a, r)); + let long = format!("{snip_a} = {}", sugg::make_binop(op, a, r)); diag.span_suggestion( expr.span, format!( diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index ee79ea2768929..4c09c4eea581f 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -25,7 +25,7 @@ pub(crate) mod arithmetic_side_effects; use rustc_hir::{Body, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs index a2c3a4d8ba775..cb3916484c1d5 100644 --- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs @@ -1,7 +1,6 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sext; -use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; @@ -19,15 +18,12 @@ pub(super) fn check<'tcx>( if op == BinOpKind::Rem { let lhs_operand = analyze_operand(lhs, cx, e); let rhs_operand = analyze_operand(rhs, cx, e); - if_chain! { - if let Some(lhs_operand) = lhs_operand; - if let Some(rhs_operand) = rhs_operand; - then { - check_const_operands(cx, e, &lhs_operand, &rhs_operand); - } - else { - check_non_const_operands(cx, e, lhs); - } + if let Some(lhs_operand) = lhs_operand + && let Some(rhs_operand) = rhs_operand + { + check_const_operands(cx, e, &lhs_operand, &rhs_operand); + } else { + check_non_const_operands(cx, e, lhs); } }; } diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs index 932dd470f9ebd..7d8aa3f56fed2 100644 --- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs +++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::get_enclosing_block; use clippy_utils::source::snippet; use clippy_utils::ty::{implements_trait, is_copy}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; @@ -180,41 +179,33 @@ fn in_impl<'tcx>( e: &'tcx Expr<'_>, bin_op: DefId, ) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> { - if_chain! { - if let Some(block) = get_enclosing_block(cx, e.hir_id); - if let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id()); - let item = cx.tcx.hir().expect_item(impl_def_id.expect_local()); - if let ItemKind::Impl(item) = &item.kind; - if let Some(of_trait) = &item.of_trait; - if let Some(seg) = of_trait.path.segments.last(); - if let Res::Def(_, trait_id) = seg.res; - if trait_id == bin_op; - if let Some(generic_args) = seg.args; - if let Some(GenericArg::Type(other_ty)) = generic_args.args.last(); - - then { - Some((item.self_ty, other_ty)) - } - else { - None - } + if let Some(block) = get_enclosing_block(cx, e.hir_id) + && let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id()) + && let item = cx.tcx.hir().expect_item(impl_def_id.expect_local()) + && let ItemKind::Impl(item) = &item.kind + && let Some(of_trait) = &item.of_trait + && let Some(seg) = of_trait.path.segments.last() + && let Res::Def(_, trait_id) = seg.res + && trait_id == bin_op + && let Some(generic_args) = seg.args + && let Some(GenericArg::Type(other_ty)) = generic_args.args.last() + { + Some((item.self_ty, other_ty)) + } else { + None } } fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool { - if_chain! { - if let ty::Adt(adt_def, _) = middle_ty.kind(); - if let Some(local_did) = adt_def.did().as_local(); - let item = cx.tcx.hir().expect_item(local_did); - let middle_ty_id = item.owner_id.to_def_id(); - if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind; - if let Res::Def(_, hir_ty_id) = path.res; - - then { - hir_ty_id == middle_ty_id - } - else { - false - } + if let ty::Adt(adt_def, _) = middle_ty.kind() + && let Some(local_did) = adt_def.did().as_local() + && let item = cx.tcx.hir().expect_item(local_did) + && let middle_ty_id = item.owner_id.to_def_id() + && let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind + && let Res::Def(_, hir_ty_id) = path.res + { + hir_ty_id == middle_ty_id + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs index 1229c202f5a09..9db2e24630aac 100644 --- a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs +++ b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -22,22 +21,20 @@ pub(super) fn check<'tcx>( _ => (left, right), }; - if_chain! { - if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left); - if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right); - if let Some(left_snip) = snippet_opt(cx, left_var.span); - if let Some(right_snip) = snippet_opt(cx, right_var.span); - then { - span_lint_and_sugg( - cx, - PTR_EQ, - expr.span, - LINT_MSG, - "try", - format!("std::ptr::eq({left_snip}, {right_snip})"), - Applicability::MachineApplicable, - ); - } + if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left) + && let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right) + && let Some(left_snip) = snippet_opt(cx, left_var.span) + && let Some(right_snip) = snippet_opt(cx, right_var.span) + { + span_lint_and_sugg( + cx, + PTR_EQ, + expr.span, + LINT_MSG, + "try", + format!("std::ptr::eq({left_snip}, {right_snip})"), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs index 7792efe6acd0a..4bfb26209d21d 100644 --- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_direct_expn_of; use rustc_ast::ast::{Expr, ExprKind, MethodCall}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs index d7cbbe13a2611..89e4e3c740d5e 100644 --- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs @@ -4,13 +4,12 @@ use clippy_utils::{ can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_res_lang_ctor, peel_blocks, peel_hir_expr_while, CaptureKind, }; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::SyntaxContext; declare_clippy_lint! { @@ -122,73 +121,97 @@ fn try_get_option_occurrence<'tcx>( _ => expr, }; let (inner_pat, is_result) = try_get_inner_pat_and_is_result(cx, pat)?; - if_chain! { - if let PatKind::Binding(bind_annotation, _, id, None) = inner_pat.kind; - if let Some(some_captures) = can_move_expr_to_closure(cx, if_then); - if let Some(none_captures) = can_move_expr_to_closure(cx, if_else); - if some_captures + if let PatKind::Binding(bind_annotation, _, id, None) = inner_pat.kind + && let Some(some_captures) = can_move_expr_to_closure(cx, if_then) + && let Some(none_captures) = can_move_expr_to_closure(cx, if_else) + && some_captures .iter() .filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2))) - .all(|(x, y)| x.is_imm_ref() && y.is_imm_ref()); - then { - let capture_mut = if bind_annotation == BindingAnnotation::MUT { "mut " } else { "" }; - let some_body = peel_blocks(if_then); - let none_body = peel_blocks(if_else); - let method_sugg = if eager_or_lazy::switch_to_eager_eval(cx, none_body) { "map_or" } else { "map_or_else" }; - let capture_name = id.name.to_ident_string(); - let (as_ref, as_mut) = match &expr.kind { - ExprKind::AddrOf(_, Mutability::Not, _) => (true, false), - ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true), - _ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => { - (mutb == Mutability::Not, mutb == Mutability::Mut) - } - _ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT), - }; + .all(|(x, y)| x.is_imm_ref() && y.is_imm_ref()) + { + let capture_mut = if bind_annotation == BindingAnnotation::MUT { + "mut " + } else { + "" + }; + let some_body = peel_blocks(if_then); + let none_body = peel_blocks(if_else); + let method_sugg = if eager_or_lazy::switch_to_eager_eval(cx, none_body) { + "map_or" + } else { + "map_or_else" + }; + let capture_name = id.name.to_ident_string(); + let (as_ref, as_mut) = match &expr.kind { + ExprKind::AddrOf(_, Mutability::Not, _) => (true, false), + ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true), + _ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => { + (mutb == Mutability::Not, mutb == Mutability::Mut) + }, + _ => ( + bind_annotation == BindingAnnotation::REF, + bind_annotation == BindingAnnotation::REF_MUT, + ), + }; - // Check if captures the closure will need conflict with borrows made in the scrutinee. - // TODO: check all the references made in the scrutinee expression. This will require interacting - // with the borrow checker. Currently only `[.]*` is checked for. - if as_ref || as_mut { - let e = peel_hir_expr_while(cond_expr, |e| match e.kind { - ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e), - _ => None, - }); - if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind { - match some_captures.get(local_id) - .or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|()| none_captures.get(local_id))) - { - Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None, - Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None, - Some(CaptureKind::Ref(Mutability::Not)) | None => (), - } + // Check if captures the closure will need conflict with borrows made in the scrutinee. + // TODO: check all the references made in the scrutinee expression. This will require interacting + // with the borrow checker. Currently only `[.]*` is checked for. + if as_ref || as_mut { + let e = peel_hir_expr_while(cond_expr, |e| match e.kind { + ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e), + _ => None, + }); + if let ExprKind::Path(QPath::Resolved( + None, + Path { + res: Res::Local(local_id), + .. + }, + )) = e.kind + { + match some_captures.get(local_id).or_else(|| { + (method_sugg == "map_or_else") + .then_some(()) + .and_then(|()| none_captures.get(local_id)) + }) { + Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None, + Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None, + Some(CaptureKind::Ref(Mutability::Not)) | None => (), } } + } - let mut app = Applicability::Unspecified; + let mut app = Applicability::Unspecified; - let (none_body, is_argless_call) = match none_body.kind { - ExprKind::Call(call_expr, []) if !none_body.span.from_expansion() => (call_expr, true), - _ => (none_body, false), - }; + let (none_body, is_argless_call) = match none_body.kind { + ExprKind::Call(call_expr, []) if !none_body.span.from_expansion() => (call_expr, true), + _ => (none_body, false), + }; - return Some(OptionOccurrence { - option: format_option_in_sugg( - Sugg::hir_with_context(cx, cond_expr, ctxt, "..", &mut app), - as_ref, - as_mut, - ), - method_sugg: method_sugg.to_string(), - some_expr: format!( - "|{capture_mut}{capture_name}| {}", - Sugg::hir_with_context(cx, some_body, ctxt, "..", &mut app), - ), - none_expr: format!( - "{}{}", - if method_sugg == "map_or" || is_argless_call { "" } else if is_result { "|_| " } else { "|| "}, - Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app), - ), - }); - } + return Some(OptionOccurrence { + option: format_option_in_sugg( + Sugg::hir_with_context(cx, cond_expr, ctxt, "..", &mut app), + as_ref, + as_mut, + ), + method_sugg: method_sugg.to_string(), + some_expr: format!( + "|{capture_mut}{capture_name}| {}", + Sugg::hir_with_context(cx, some_body, ctxt, "..", &mut app), + ), + none_expr: format!( + "{}{}", + if method_sugg == "map_or" || is_argless_call { + "" + } else if is_result { + "|_| " + } else { + "|| " + }, + Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app), + ), + }); } None @@ -216,21 +239,24 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> if_then, if_else: Some(if_else), }) = higher::IfLet::hir(cx, expr) + && !cx.typeck_results().expr_ty(expr).is_unit() + && !is_else_clause(cx.tcx, expr) { - if !is_else_clause(cx.tcx, expr) { - return try_get_option_occurrence(cx, expr.span.ctxt(), let_pat, let_expr, if_then, if_else); - } + try_get_option_occurrence(cx, expr.span.ctxt(), let_pat, let_expr, if_then, if_else) + } else { + None } - None } fn detect_option_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option { - if let ExprKind::Match(ex, arms, MatchSource::Normal) = expr.kind { - if let Some((let_pat, if_then, if_else)) = try_convert_match(cx, arms) { - return try_get_option_occurrence(cx, expr.span.ctxt(), let_pat, ex, if_then, if_else); - } + if let ExprKind::Match(ex, arms, MatchSource::Normal) = expr.kind + && !cx.typeck_results().expr_ty(expr).is_unit() + && let Some((let_pat, if_then, if_else)) = try_convert_match(cx, arms) + { + try_get_option_occurrence(cx, expr.span.ctxt(), let_pat, ex, if_then, if_else) + } else { + None } - None } fn try_convert_match<'tcx>( diff --git a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs index 38cd5043adc7b..de78987933108 100644 --- a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs +++ b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::SpanlessEq; -use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -34,41 +33,37 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { // a + b < a, a > a + b, a < a - b, a - b > a fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r); - if_chain! { - if let ExprKind::Binary(ref op, first, second) = expr.kind; - if let ExprKind::Binary(ref op2, ident1, ident2) = first.kind; - if let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind; - if let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind; - if let ExprKind::Path(QPath::Resolved(_, path3)) = second.kind; - if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]); - if cx.typeck_results().expr_ty(ident1).is_integral(); - if cx.typeck_results().expr_ty(ident2).is_integral(); - then { - if op.node == BinOpKind::Lt && op2.node == BinOpKind::Add { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG); - } - if op.node == BinOpKind::Gt && op2.node == BinOpKind::Sub { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG); - } + if let ExprKind::Binary(ref op, first, second) = expr.kind + && let ExprKind::Binary(ref op2, ident1, ident2) = first.kind + && let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind + && let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind + && let ExprKind::Path(QPath::Resolved(_, path3)) = second.kind + && (eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0])) + && cx.typeck_results().expr_ty(ident1).is_integral() + && cx.typeck_results().expr_ty(ident2).is_integral() + { + if op.node == BinOpKind::Lt && op2.node == BinOpKind::Add { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG); + } + if op.node == BinOpKind::Gt && op2.node == BinOpKind::Sub { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG); } } - if_chain! { - if let ExprKind::Binary(ref op, first, second) = expr.kind; - if let ExprKind::Binary(ref op2, ident1, ident2) = second.kind; - if let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind; - if let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind; - if let ExprKind::Path(QPath::Resolved(_, path3)) = first.kind; - if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]); - if cx.typeck_results().expr_ty(ident1).is_integral(); - if cx.typeck_results().expr_ty(ident2).is_integral(); - then { - if op.node == BinOpKind::Gt && op2.node == BinOpKind::Add { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG); - } - if op.node == BinOpKind::Lt && op2.node == BinOpKind::Sub { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG); - } + if let ExprKind::Binary(ref op, first, second) = expr.kind + && let ExprKind::Binary(ref op2, ident1, ident2) = second.kind + && let ExprKind::Path(QPath::Resolved(_, path1)) = ident1.kind + && let ExprKind::Path(QPath::Resolved(_, path2)) = ident2.kind + && let ExprKind::Path(QPath::Resolved(_, path3)) = first.kind + && (eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0])) + && cx.typeck_results().expr_ty(ident1).is_integral() + && cx.typeck_results().expr_ty(ident2).is_integral() + { + if op.node == BinOpKind::Gt && op2.node == BinOpKind::Add { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG); + } + if op.node == BinOpKind::Lt && op2.node == BinOpKind::Sub { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG); } } } diff --git a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs index 6a760f9fe64a1..f821a4efee7b2 100644 --- a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs +++ b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs @@ -7,7 +7,7 @@ use core::ops::ControlFlow; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn { if matches!(fn_kind, FnKind::Closure) { return; } - let owner = cx.tcx.hir().local_def_id_to_hir_id(def_id).expect_owner(); + let owner = cx.tcx.local_def_id_to_hir_id(def_id).expect_owner(); if is_type_diagnostic_item(cx, return_ty(cx, owner), sym::Result) { lint_impl_body(cx, span, body); } diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs index f4f1f6ddb3f20..ef51a9a9a1c8a 100644 --- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs +++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs index 99ba55b6b3103..ffa403e27ca30 100644 --- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs +++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Item, ItemKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs index 68d3d00ac16d0..18e6aad9c9a08 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs @@ -1,8 +1,7 @@ use clippy_utils::diagnostics::span_lint_hir; -use if_chain::if_chain; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -34,22 +33,24 @@ declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]); impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if_chain! { - if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind; - if !cx.tcx.has_attr(item.owner_id, sym::automatically_derived); - if let Some(eq_trait) = cx.tcx.lang_items().eq_trait(); - if trait_ref.path.res.def_id() == eq_trait; - then { - for impl_item in *impl_items { - if impl_item.ident.name == sym::ne { - span_lint_hir( - cx, - PARTIALEQ_NE_IMPL, - impl_item.id.hir_id(), - impl_item.span, - "re-implementing `PartialEq::ne` is unnecessary", - ); - } + if let ItemKind::Impl(Impl { + of_trait: Some(ref trait_ref), + items: impl_items, + .. + }) = item.kind + && !cx.tcx.has_attr(item.owner_id, sym::automatically_derived) + && let Some(eq_trait) = cx.tcx.lang_items().eq_trait() + && trait_ref.path.res.def_id() == eq_trait + { + for impl_item in *impl_items { + if impl_item.ident.name == sym::ne { + span_lint_hir( + cx, + PARTIALEQ_NE_IMPL, + impl_item.id.hir_id(), + impl_item.span, + "re-implementing `PartialEq::ne` is unnecessary", + ); } } }; diff --git a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs index 11e9a2bc39462..6d4216970cc4d 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs @@ -4,7 +4,7 @@ use clippy_utils::{is_res_lang_ctor, path_res, peel_hir_expr_refs, peel_ref_oper use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 4d7a055dae173..57d37067e8f98 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -5,7 +5,6 @@ use clippy_utils::source::snippet; use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy}; use clippy_utils::{is_self, is_self_ty}; use core::ops::ControlFlow; -use if_chain::if_chain; use rustc_ast::attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -16,11 +15,10 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, RegionKind}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; use rustc_target::spec::abi::Abi; -use rustc_target::spec::Target; declare_clippy_lint! { /// ### What it does @@ -117,10 +115,10 @@ impl<'tcx> PassByRefOrValue { ref_min_size: Option, value_max_size: u64, avoid_breaking_exported_api: bool, - target: &Target, + pointer_width: u32, ) -> Self { let ref_min_size = ref_min_size.unwrap_or_else(|| { - let bit_width = u64::from(target.pointer_width); + let bit_width = u64::from(pointer_width); // Cap the calculated bit width at 32-bits to reduce // portability problems between 32 and 64-bit targets let bit_width = cmp::min(bit_width, 32); @@ -168,18 +166,18 @@ impl<'tcx> PassByRefOrValue { match *ty.skip_binder().kind() { ty::Ref(lt, ty, Mutability::Not) => { match lt.kind() { - RegionKind::ReLateBound(index, region) + RegionKind::ReBound(index, region) if index.as_u32() == 0 && output_regions.contains(®ion) => { continue; }, // Early bound regions on functions are either from the containing item, are bounded by another // lifetime, or are used as a bound for a type or lifetime. - RegionKind::ReEarlyBound(..) => continue, + RegionKind::ReEarlyParam(..) => continue, _ => (), } - let ty = cx.tcx.erase_late_bound_regions(fn_sig.rebind(ty)); + let ty = cx.tcx.instantiate_bound_regions_with_erased(fn_sig.rebind(ty)); if is_copy(cx, ty) && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) && size <= self.ref_min_size @@ -227,24 +225,25 @@ impl<'tcx> PassByRefOrValue { _ => continue, } } - let ty = cx.tcx.erase_late_bound_regions(ty); + let ty = cx.tcx.instantiate_bound_regions_with_erased(ty); - if_chain! { - if is_copy(cx, ty); - if !is_self_ty(input); - if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()); - if size > self.value_max_size; - then { - span_lint_and_sugg( - cx, - LARGE_TYPES_PASSED_BY_VALUE, - input.span, - &format!("this argument ({size} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)", self.value_max_size), - "consider passing by reference instead", - format!("&{}", snippet(cx, input.span, "_")), - Applicability::MaybeIncorrect, - ); - } + if is_copy(cx, ty) + && !is_self_ty(input) + && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) + && size > self.value_max_size + { + span_lint_and_sugg( + cx, + LARGE_TYPES_PASSED_BY_VALUE, + input.span, + &format!( + "this argument ({size} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)", + self.value_max_size + ), + "consider passing by reference instead", + format!("&{}", snippet(cx, input.span, "_")), + Applicability::MaybeIncorrect, + ); } }, @@ -280,7 +279,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { return; } - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(def_id); match kind { FnKind::ItemFn(.., header) => { if header.abi != Abi::Rust { diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index dcd1e7af0c2ca..60ced9c12082d 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -3,7 +3,7 @@ use rustc_hir::{intravisit, Body, Expr, ExprKind, FnDecl, Let, LocalSource, Muta use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::Span; diff --git a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs index b98005d592249..704acdc103e84 100644 --- a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs +++ b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs index 057b7e30642ec..ff83725da6913 100644 --- a/src/tools/clippy/clippy_lints/src/precedence.rs +++ b/src/tools/clippy/clippy_lints/src/precedence.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use if_chain::if_chain; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp}; use rustc_ast::token; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; const ALLOWED_ODD_FUNCTIONS: [&str; 14] = [ @@ -79,7 +78,7 @@ impl EarlyLintPass for Precedence { let sugg = format!( "({}) {} ({})", snippet_with_applicability(cx, left.span, "..", &mut applicability), - op.to_string(), + op.as_str(), snippet_with_applicability(cx, right.span, "..", &mut applicability) ); span_sugg(expr, sugg, applicability); @@ -88,7 +87,7 @@ impl EarlyLintPass for Precedence { let sugg = format!( "({}) {} {}", snippet_with_applicability(cx, left.span, "..", &mut applicability), - op.to_string(), + op.as_str(), snippet_with_applicability(cx, right.span, "..", &mut applicability) ); span_sugg(expr, sugg, applicability); @@ -97,7 +96,7 @@ impl EarlyLintPass for Precedence { let sugg = format!( "{} {} ({})", snippet_with_applicability(cx, left.span, "..", &mut applicability), - op.to_string(), + op.as_str(), snippet_with_applicability(cx, right.span, "..", &mut applicability) ); span_sugg(expr, sugg, applicability); @@ -118,25 +117,23 @@ impl EarlyLintPass for Precedence { arg = receiver; } - if_chain! { - if !all_odd; - if let ExprKind::Lit(lit) = &arg.kind; - if let token::LitKind::Integer | token::LitKind::Float = &lit.kind; - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - PRECEDENCE, - expr.span, - "unary minus has lower precedence than method call", - "consider adding parentheses to clarify your intent", - format!( - "-({})", - snippet_with_applicability(cx, operand.span, "..", &mut applicability) - ), - applicability, - ); - } + if !all_odd + && let ExprKind::Lit(lit) = &arg.kind + && let token::LitKind::Integer | token::LitKind::Float = &lit.kind + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + PRECEDENCE, + expr.span, + "unary minus has lower precedence than method call", + "consider adding parentheses to clarify your intent", + format!( + "-({})", + snippet_with_applicability(cx, operand.span, "..", &mut applicability) + ), + applicability, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 83863b92caffa..2587b3881bbfa 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -20,14 +20,16 @@ use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Binder, ClauseKind, ExistentialPredicate, List, PredicateKind, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{sym, Span}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::Symbol; +use rustc_span::{sym, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use std::{fmt, iter}; +use crate::vec::is_allowed_vec_method; + declare_clippy_lint! { /// ### What it does /// This lint checks for function arguments of type `&String`, `&Vec`, @@ -465,9 +467,9 @@ fn check_fn_args<'cx, 'tcx: 'cx>( .walk() .filter_map(|arg| { arg.as_region().and_then(|lifetime| match lifetime.kind() { - ty::ReEarlyBound(r) => Some(r.def_id), - ty::ReLateBound(_, r) => r.kind.get_id(), - ty::ReFree(r) => r.bound_region.get_id(), + ty::ReEarlyParam(r) => Some(r.def_id), + ty::ReBound(_, r) => r.kind.get_id(), + ty::ReLateParam(r) => r.bound_region.get_id(), ty::ReStatic | ty::ReVar(_) | ty::RePlaceholder(_) @@ -660,7 +662,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: }, // If the types match check for methods which exist on both types. e.g. `Vec::len` and // `slice::len` - ty::Adt(def, _) if def.did() == args.ty_did => { + ty::Adt(def, _) if def.did() == args.ty_did && !is_allowed_vec_method(self.cx, e) => { set_skip_flag(); }, _ => (), @@ -712,23 +714,25 @@ fn matches_preds<'tcx>( preds: &'tcx [ty::PolyExistentialPredicate<'tcx>], ) -> bool { let infcx = cx.tcx.infer_ctxt().build(); - preds.iter().all(|&p| match cx.tcx.erase_late_bound_regions(p) { - ExistentialPredicate::Trait(p) => infcx - .type_implements_trait(p.def_id, [ty.into()].into_iter().chain(p.args.iter()), cx.param_env) - .must_apply_modulo_regions(), - ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new( - cx.tcx, - ObligationCause::dummy(), - cx.param_env, - cx.tcx - .mk_predicate(Binder::dummy(PredicateKind::Clause(ClauseKind::Projection( - p.with_self_ty(cx.tcx, ty), - )))), - )), - ExistentialPredicate::AutoTrait(p) => infcx - .type_implements_trait(p, [ty], cx.param_env) - .must_apply_modulo_regions(), - }) + preds + .iter() + .all(|&p| match cx.tcx.instantiate_bound_regions_with_erased(p) { + ExistentialPredicate::Trait(p) => infcx + .type_implements_trait(p.def_id, [ty.into()].into_iter().chain(p.args.iter()), cx.param_env) + .must_apply_modulo_regions(), + ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new( + cx.tcx, + ObligationCause::dummy(), + cx.param_env, + cx.tcx + .mk_predicate(Binder::dummy(PredicateKind::Clause(ClauseKind::Projection( + p.with_self_ty(cx.tcx, ty), + )))), + )), + ExistentialPredicate::AutoTrait(p) => infcx + .type_implements_trait(p, [ty], cx.param_env) + .must_apply_modulo_regions(), + }) } fn get_ref_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> { diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs index 66d869bc45a06..ff8ec2ad57c39 100644 --- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs +++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet_opt; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; use std::fmt; diff --git a/src/tools/clippy/clippy_lints/src/pub_use.rs b/src/tools/clippy/clippy_lints/src/pub_use.rs index 316a72988aab0..c0e999e76ef2f 100644 --- a/src/tools/clippy/clippy_lints/src/pub_use.rs +++ b/src/tools/clippy/clippy_lints/src/pub_use.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Item, ItemKind, VisibilityKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index b133635e88354..fc5835408a92a 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -10,7 +10,6 @@ use clippy_utils::{ is_res_lang_ctor, pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt, }; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; @@ -19,7 +18,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; use rustc_span::symbol::Symbol; @@ -179,17 +178,15 @@ fn expr_return_none_or_err( _ => false, }, ExprKind::Call(call_expr, args_expr) => { - if_chain! { - if smbl == sym::Result; - if let ExprKind::Path(QPath::Resolved(_, path)) = &call_expr.kind; - if let Some(segment) = path.segments.first(); - if let Some(err_sym) = err_sym; - if let Some(arg) = args_expr.first(); - if let ExprKind::Path(QPath::Resolved(_, arg_path)) = &arg.kind; - if let Some(PathSegment { ident, .. }) = arg_path.segments.first(); - then { - return segment.ident.name == sym::Err && err_sym == ident.name; - } + if smbl == sym::Result + && let ExprKind::Path(QPath::Resolved(_, path)) = &call_expr.kind + && let Some(segment) = path.segments.first() + && let Some(err_sym) = err_sym + && let Some(arg) = args_expr.first() + && let ExprKind::Path(QPath::Resolved(_, arg_path)) = &arg.kind + && let Some(PathSegment { ident, .. }) = arg_path.segments.first() + { + return segment.ident.name == sym::Err && err_sym == ident.name; } false }, @@ -218,81 +215,85 @@ impl QuestionMark { /// /// If it matches, it will suggest to use the question mark operator instead fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if_chain! { - if !self.inside_try_block(); - if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr); - if !is_else_clause(cx.tcx, expr); - if let ExprKind::MethodCall(segment, caller, ..) = &cond.kind; - let caller_ty = cx.typeck_results().expr_ty(caller); - let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else); - if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block); - then { - let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) && - !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); - let sugg = if let Some(else_inner) = r#else { - if eq_expr_value(cx, caller, peel_blocks(else_inner)) { - format!("Some({receiver_str}?)") - } else { - return; - } + if !self.inside_try_block() + && let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr) + && !is_else_clause(cx.tcx, expr) + && let ExprKind::MethodCall(segment, caller, ..) = &cond.kind + && let caller_ty = cx.typeck_results().expr_ty(caller) + && let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else) + && (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block)) + { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); + let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) + && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); + let sugg = if let Some(else_inner) = r#else { + if eq_expr_value(cx, caller, peel_blocks(else_inner)) { + format!("Some({receiver_str}?)") } else { - format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" }) - }; + return; + } + } else { + format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" }) + }; - span_lint_and_sugg( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - "replace it with", - sugg, - applicability, - ); - } + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, + ); } } fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if_chain! { - if !self.inside_try_block(); - if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr); - if !is_else_clause(cx.tcx, expr); - if let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind; - if ddpos.as_opt_usize().is_none(); - if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind; - let caller_ty = cx.typeck_results().expr_ty(let_expr); - let if_block = IfBlockType::IfLet( + if !self.inside_try_block() + && let Some(higher::IfLet { + let_pat, + let_expr, + if_then, + if_else, + }) = higher::IfLet::hir(cx, expr) + && !is_else_clause(cx.tcx, expr) + && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind + && ddpos.as_opt_usize().is_none() + && let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind + && let caller_ty = cx.typeck_results().expr_ty(let_expr) + && let if_block = IfBlockType::IfLet( cx.qpath_res(path1, let_pat.hir_id), caller_ty, ident.name, let_expr, if_then, - if_else + if_else, + ) + && ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) + || is_early_return(sym::Result, cx, &if_block)) + && if_else + .map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))) + .filter(|e| *e) + .is_none() + { + let mut applicability = Applicability::MachineApplicable; + let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); + let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_))); + let sugg = format!( + "{receiver_str}{}?{}", + if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, + if requires_semi { ";" } else { "" } + ); + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this block may be rewritten with the `?` operator", + "replace it with", + sugg, + applicability, ); - if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id)) - || is_early_return(sym::Result, cx, &if_block); - if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none(); - then { - let mut applicability = Applicability::MachineApplicable; - let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); - let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_))); - let sugg = format!( - "{receiver_str}{}?{}", - if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, - if requires_semi { ";" } else { "" } - ); - span_lint_and_sugg( - cx, - QUESTION_MARK, - expr.span, - "this block may be rewritten with the `?` operator", - "replace it with", - sugg, - applicability, - ); - } } } } diff --git a/src/tools/clippy/clippy_lints/src/question_mark_used.rs b/src/tools/clippy/clippy_lints/src/question_mark_used.rs index d0de33e3c4f14..ddfc53083c461 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark_used.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark_used.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::macros::span_is_local; use rustc_hir::{Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs index 1b3081abc13ce..6b54258dd617d 100644 --- a/src/tools/clippy/clippy_lints/src/ranges.rs +++ b/src/tools/clippy/clippy_lints/src/ranges.rs @@ -4,15 +4,14 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::{get_parent_expr, higher, in_constant, is_integer_const, path_to_local}; -use if_chain::if_chain; use rustc_ast::ast::RangeLimits; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::Span; +use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; +use rustc_span::Span; use std::cmp::Ordering; declare_clippy_lint! { @@ -283,16 +282,14 @@ fn check_possible_range_contains( // If the LHS is the same operator, we have to recurse to get the "real" RHS, since they have // the same operator precedence - if_chain! { - if let ExprKind::Binary(ref lhs_op, _left, new_lhs) = left.kind; - if op == lhs_op.node; - let new_span = Span::new(new_lhs.span.lo(), right.span.hi(), expr.span.ctxt(), expr.span.parent()); - if let Some(snip) = &snippet_opt(cx, new_span); + if let ExprKind::Binary(ref lhs_op, _left, new_lhs) = left.kind + && op == lhs_op.node + && let new_span = Span::new(new_lhs.span.lo(), right.span.hi(), expr.span.ctxt(), expr.span.parent()) + && let Some(snip) = &snippet_opt(cx, new_span) // Do not continue if we have mismatched number of parens, otherwise the suggestion is wrong - if snip.matches('(').count() == snip.matches(')').count(); - then { - check_possible_range_contains(cx, op, new_lhs, right, expr, new_span); - } + && snip.matches('(').count() == snip.matches(')').count() + { + check_possible_range_contains(cx, op, new_lhs, right, expr, new_span); } } @@ -349,71 +346,66 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) -> // exclusive range plus one: `x..(y+1)` fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if expr.span.can_be_used_for_suggestions(); - if let Some(higher::Range { + if expr.span.can_be_used_for_suggestions() + && let Some(higher::Range { start, end: Some(end), - limits: RangeLimits::HalfOpen - }) = higher::Range::hir(expr); - if let Some(y) = y_plus_one(cx, end); - then { - let span = expr.span; - span_lint_and_then( - cx, - RANGE_PLUS_ONE, - span, - "an inclusive range would be more readable", - |diag| { - let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string()); - let end = Sugg::hir(cx, y, "y").maybe_par(); - if let Some(is_wrapped) = &snippet_opt(cx, span) { - if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') { - diag.span_suggestion( - span, - "use", - format!("({start}..={end})"), - Applicability::MaybeIncorrect, - ); - } else { - diag.span_suggestion( - span, - "use", - format!("{start}..={end}"), - Applicability::MachineApplicable, // snippet - ); - } + limits: RangeLimits::HalfOpen, + }) = higher::Range::hir(expr) + && let Some(y) = y_plus_one(cx, end) + { + let span = expr.span; + span_lint_and_then( + cx, + RANGE_PLUS_ONE, + span, + "an inclusive range would be more readable", + |diag| { + let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string()); + let end = Sugg::hir(cx, y, "y").maybe_par(); + if let Some(is_wrapped) = &snippet_opt(cx, span) { + if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') { + diag.span_suggestion(span, "use", format!("({start}..={end})"), Applicability::MaybeIncorrect); + } else { + diag.span_suggestion( + span, + "use", + format!("{start}..={end}"), + Applicability::MachineApplicable, // snippet + ); } - }, - ); - } + } + }, + ); } } // inclusive range minus one: `x..=(y-1)` fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if expr.span.can_be_used_for_suggestions(); - if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::Range::hir(expr); - if let Some(y) = y_minus_one(cx, end); - then { - span_lint_and_then( - cx, - RANGE_MINUS_ONE, - expr.span, - "an exclusive range would be more readable", - |diag| { - let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string()); - let end = Sugg::hir(cx, y, "y").maybe_par(); - diag.span_suggestion( - expr.span, - "use", - format!("{start}..{end}"), - Applicability::MachineApplicable, // snippet - ); - }, - ); - } + if expr.span.can_be_used_for_suggestions() + && let Some(higher::Range { + start, + end: Some(end), + limits: RangeLimits::Closed, + }) = higher::Range::hir(expr) + && let Some(y) = y_minus_one(cx, end) + { + span_lint_and_then( + cx, + RANGE_MINUS_ONE, + expr.span, + "an exclusive range would be more readable", + |diag| { + let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string()); + let end = Sugg::hir(cx, y, "y").maybe_par(); + diag.span_suggestion( + expr.span, + "use", + format!("{start}..{end}"), + Applicability::MachineApplicable, // snippet + ); + }, + ); } } @@ -447,52 +439,54 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) { } } - if_chain! { - if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::Range::hir(expr); - let ty = cx.typeck_results().expr_ty(start); - if let ty::Int(_) | ty::Uint(_) = ty.kind(); - if let Some(start_idx) = constant(cx, cx.typeck_results(), start); - if let Some(end_idx) = constant(cx, cx.typeck_results(), end); - if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx); - if is_empty_range(limits, ordering); - then { - if inside_indexing_expr(cx, expr) { - // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ... - if ordering != Ordering::Equal { - span_lint( - cx, - REVERSED_EMPTY_RANGES, - expr.span, - "this range is reversed and using it to index a slice will panic at run-time", - ); - } - // ... except in for loop arguments for backwards compatibility with `reverse_range_loop` - } else if ordering != Ordering::Equal || is_for_loop_arg(cx, expr) { - span_lint_and_then( + if let Some(higher::Range { + start: Some(start), + end: Some(end), + limits, + }) = higher::Range::hir(expr) + && let ty = cx.typeck_results().expr_ty(start) + && let ty::Int(_) | ty::Uint(_) = ty.kind() + && let Some(start_idx) = constant(cx, cx.typeck_results(), start) + && let Some(end_idx) = constant(cx, cx.typeck_results(), end) + && let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx) + && is_empty_range(limits, ordering) + { + if inside_indexing_expr(cx, expr) { + // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ... + if ordering != Ordering::Equal { + span_lint( cx, REVERSED_EMPTY_RANGES, expr.span, - "this range is empty so it will yield no values", - |diag| { - if ordering != Ordering::Equal { - let start_snippet = snippet(cx, start.span, "_"); - let end_snippet = snippet(cx, end.span, "_"); - let dots = match limits { - RangeLimits::HalfOpen => "..", - RangeLimits::Closed => "..=" - }; - - diag.span_suggestion( - expr.span, - "consider using the following if you are attempting to iterate over this \ - range in reverse", - format!("({end_snippet}{dots}{start_snippet}).rev()"), - Applicability::MaybeIncorrect, - ); - } - }, + "this range is reversed and using it to index a slice will panic at run-time", ); } + // ... except in for loop arguments for backwards compatibility with `reverse_range_loop` + } else if ordering != Ordering::Equal || is_for_loop_arg(cx, expr) { + span_lint_and_then( + cx, + REVERSED_EMPTY_RANGES, + expr.span, + "this range is empty so it will yield no values", + |diag| { + if ordering != Ordering::Equal { + let start_snippet = snippet(cx, start.span, "_"); + let end_snippet = snippet(cx, end.span, "_"); + let dots = match limits { + RangeLimits::HalfOpen => "..", + RangeLimits::Closed => "..=", + }; + + diag.span_suggestion( + expr.span, + "consider using the following if you are attempting to iterate over this \ + range in reverse", + format!("({end_snippet}{dots}{start_snippet}).rev()"), + Applicability::MaybeIncorrect, + ); + } + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs index 391c77dbf902f..ac29d27303c8b 100644 --- a/src/tools/clippy/clippy_lints/src/raw_strings.rs +++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs @@ -8,7 +8,7 @@ use rustc_ast::token::LitKind; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, Span}; declare_clippy_lint! { @@ -56,7 +56,7 @@ declare_clippy_lint! { impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRINGS, NEEDLESS_RAW_STRING_HASHES]); pub struct RawStrings { - pub needless_raw_string_hashes_allow_one: bool, + pub allow_one_hash_in_raw_strings: bool, } impl EarlyLintPass for RawStrings { diff --git a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs index 59ce289e7d2b5..d0b45b59526fc 100644 --- a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs +++ b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span, Symbol}; declare_clippy_lint! { @@ -118,26 +118,24 @@ fn emit_lint(cx: &LateContext<'_>, symbol: Symbol, lint_span: Span, elem: &Expr< /// Checks whether the given `expr` is a call to `Arc::new`, `Rc::new`, or evaluates to a `Weak` fn ref_init(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<(Symbol, Span)> { - if_chain! { - if let ExprKind::Call(func, _args) = expr.kind; - if let ExprKind::Path(ref func_path @ QPath::TypeRelative(ty, _)) = func.kind; - if let TyKind::Path(ref ty_path) = ty.kind; - if let Some(def_id) = cx.qpath_res(ty_path, ty.hir_id).opt_def_id(); - - then { - if last_path_segment(func_path).ident.name == sym::new - && let Some(symbol) = cx - .tcx - .get_diagnostic_name(def_id) - .filter(|symbol| symbol == &sym::Arc || symbol == &sym::Rc) { - return Some((symbol, func.span)); - } + if let ExprKind::Call(func, _args) = expr.kind + && let ExprKind::Path(ref func_path @ QPath::TypeRelative(ty, _)) = func.kind + && let TyKind::Path(ref ty_path) = ty.kind + && let Some(def_id) = cx.qpath_res(ty_path, ty.hir_id).opt_def_id() + { + if last_path_segment(func_path).ident.name == sym::new + && let Some(symbol) = cx + .tcx + .get_diagnostic_name(def_id) + .filter(|symbol| symbol == &sym::Arc || symbol == &sym::Rc) + { + return Some((symbol, func.span)); + } - if let ty::Adt(adt, _) = *cx.typeck_results().expr_ty(expr).kind() - && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::RcWeak | sym::ArcWeak)) - { - return Some((Symbol::intern("Weak"), func.span)); - } + if let ty::Adt(adt, _) = *cx.typeck_results().expr_ty(expr).kind() + && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::RcWeak | sym::ArcWeak)) + { + return Some((Symbol::intern("Weak"), func.span)); } } diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs index b27d4cc6e4f8c..62f3c09aa7e26 100644 --- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs +++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs @@ -7,7 +7,7 @@ use hir::{Expr, ExprKind, Local, PatKind, PathSegment, QPath, StmtKind}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index 90297ca8bb612..19d9d64b31e3c 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -9,7 +9,7 @@ use rustc_hir::{Closure, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSo use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::UpvarCapture; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 8daf085a42fc9..c62c351e71670 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -3,14 +3,13 @@ use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth}; use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{def_id, Body, FnDecl, LangItem}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, BytePos, Span}; @@ -145,18 +144,16 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { let pred_terminator = mir[ps[0]].terminator(); // receiver of the `deref()` call - let (pred_arg, deref_clone_ret) = if_chain! { - if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) = - is_call_with_ref_arg(cx, mir, &pred_terminator.kind); - if res == cloned; - if cx.tcx.is_diagnostic_item(sym::deref_method, pred_fn_def_id); - if is_type_diagnostic_item(cx, pred_arg_ty, sym::PathBuf) - || is_type_diagnostic_item(cx, pred_arg_ty, sym::OsString); - then { - (pred_arg, res) - } else { - continue; - } + let (pred_arg, deref_clone_ret) = if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) = + is_call_with_ref_arg(cx, mir, &pred_terminator.kind) + && res == cloned + && cx.tcx.is_diagnostic_item(sym::deref_method, pred_fn_def_id) + && (is_type_diagnostic_item(cx, pred_arg_ty, sym::PathBuf) + || is_type_diagnostic_item(cx, pred_arg_ty, sym::OsString)) + { + (pred_arg, res) + } else { + continue; }; let (local, cannot_move_out) = @@ -211,45 +208,37 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { .assert_crate_local() .lint_root; - if_chain! { - if let Some(snip) = snippet_opt(cx, span); - if let Some(dot) = snip.rfind('.'); - then { - let sugg_span = span.with_lo( - span.lo() + BytePos(u32::try_from(dot).unwrap()) - ); - let mut app = Applicability::MaybeIncorrect; - - let call_snip = &snip[dot + 1..]; - // Machine applicable when `call_snip` looks like `foobar()` - if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) { - if call_snip.as_bytes().iter().all(|b| b.is_ascii_alphabetic() || *b == b'_') { - app = Applicability::MachineApplicable; - } + if let Some(snip) = snippet_opt(cx, span) + && let Some(dot) = snip.rfind('.') + { + let sugg_span = span.with_lo(span.lo() + BytePos(u32::try_from(dot).unwrap())); + let mut app = Applicability::MaybeIncorrect; + + let call_snip = &snip[dot + 1..]; + // Machine applicable when `call_snip` looks like `foobar()` + if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) { + if call_snip + .as_bytes() + .iter() + .all(|b| b.is_ascii_alphabetic() || *b == b'_') + { + app = Applicability::MachineApplicable; } + } - span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| { - diag.span_suggestion( - sugg_span, - "remove this", - "", - app, + span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| { + diag.span_suggestion(sugg_span, "remove this", "", app); + if clone_usage.cloned_used { + diag.span_note(span, "cloned value is neither consumed nor mutated"); + } else { + diag.span_note( + span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())), + "this value is dropped without further use", ); - if clone_usage.cloned_used { - diag.span_note( - span, - "cloned value is neither consumed nor mutated", - ); - } else { - diag.span_note( - span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())), - "this value is dropped without further use", - ); - } - }); - } else { - span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone"); - } + } + }); + } else { + span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone"); } } } @@ -261,18 +250,21 @@ fn is_call_with_ref_arg<'tcx>( mir: &'tcx mir::Body<'tcx>, kind: &'tcx mir::TerminatorKind<'tcx>, ) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, mir::Local)> { - if_chain! { - if let mir::TerminatorKind::Call { func, args, destination, .. } = kind; - if args.len() == 1; - if let mir::Operand::Move(mir::Place { local, .. }) = &args[0]; - if let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind(); - if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx)); - if !is_copy(cx, inner_ty); - then { - Some((def_id, *local, inner_ty, destination.as_local()?)) - } else { - None - } + if let mir::TerminatorKind::Call { + func, + args, + destination, + .. + } = kind + && args.len() == 1 + && let mir::Operand::Move(mir::Place { local, .. }) = &args[0] + && let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind() + && let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx)) + && !is_copy(cx, inner_ty) + { + Some((def_id, *local, inner_ty, destination.as_local()?)) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index e679fab5323d4..8bac2e40e0128 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -2,16 +2,15 @@ use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::get_parent_expr; use clippy_utils::sugg::Sugg; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::intravisit as hir_visit; use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; +use rustc_hir::{intravisit as hir_visit, CoroutineKind, CoroutineSource, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -61,11 +60,14 @@ impl<'tcx> Visitor<'tcx> for ReturnVisitor { } } -/// Checks if the body is owned by an async closure -fn is_async_closure(body: &hir::Body<'_>) -> bool { - if let hir::ExprKind::Closure(closure) = body.value.kind - && let [resume_ty] = closure.fn_decl.inputs - && let hir::TyKind::Path(hir::QPath::LangItem(hir::LangItem::ResumeTy, ..)) = resume_ty.kind +/// Checks if the body is owned by an async closure. +/// Returns true for `async || whatever_expression`, but false for `|| async { whatever_expression +/// }`. +fn is_async_closure(cx: &LateContext<'_>, body: &hir::Body<'_>) -> bool { + if let hir::ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind + && let desugared_inner_closure_body = cx.tcx.hir().body(innermost_closure_generated_by_desugar.body) + // checks whether it is `async || whatever_expression` + && let Some(CoroutineKind::Async(CoroutineSource::Closure)) = desugared_inner_closure_body.coroutine_kind { true } else { @@ -101,7 +103,7 @@ fn find_innermost_closure<'tcx>( data = Some(( body.value, closure.fn_decl, - if is_async_closure(body) { + if is_async_closure(cx, body) { ty::Asyncness::Yes } else { ty::Asyncness::No @@ -141,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { } if let hir::ExprKind::Call(recv, _) = expr.kind - // don't lint if the receiver is a call, too. + // don't lint if the receiver is a call, too. // we do this in order to prevent linting multiple times; consider: // `(|| || 1)()()` // ^^ we only want to lint for this call (but we walk up the calls to consider both calls). @@ -174,12 +176,18 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { hint = hint.asyncify(); } - diag.span_suggestion( - full_expr.span, - "try doing something like", - hint.maybe_par(), - applicability, - ); + let is_in_fn_call_arg = + clippy_utils::get_parent_node(cx.tcx, expr.hir_id).is_some_and(|x| match x { + Node::Expr(expr) => matches!(expr.kind, hir::ExprKind::Call(_, _)), + _ => false, + }); + + // avoid clippy::double_parens + if !is_in_fn_call_arg { + hint = hint.maybe_par(); + }; + + diag.span_suggestion(full_expr.span, "try doing something like", hint, applicability); } }, ); @@ -201,14 +209,12 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { type NestedFilter = nested_filter::OnlyBodies; fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { - if_chain! { - if let hir::ExprKind::Call(closure, _) = expr.kind; - if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind; - if self.path.segments[0].ident == path.segments[0].ident; - if self.path.res == path.res; - then { - self.count += 1; - } + if let hir::ExprKind::Call(closure, _) = expr.kind + && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind + && self.path.segments[0].ident == path.segments[0].ident + && self.path.res == path.res + { + self.count += 1; } hir_visit::walk_expr(self, expr); } @@ -223,25 +229,23 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { } for w in block.stmts.windows(2) { - if_chain! { - if let hir::StmtKind::Local(local) = w[0].kind; - if let Option::Some(t) = local.init; - if let hir::ExprKind::Closure { .. } = t.kind; - if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind; - if let hir::StmtKind::Semi(second) = w[1].kind; - if let hir::ExprKind::Assign(_, call, _) = second.kind; - if let hir::ExprKind::Call(closure, _) = call.kind; - if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind; - if ident == path.segments[0].ident; - if count_closure_usage(cx, block, path) == 1; - then { - span_lint( - cx, - REDUNDANT_CLOSURE_CALL, - second.span, - "closure called just once immediately after it was declared", - ); - } + if let hir::StmtKind::Local(local) = w[0].kind + && let Option::Some(t) = local.init + && let hir::ExprKind::Closure { .. } = t.kind + && let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind + && let hir::StmtKind::Semi(second) = w[1].kind + && let hir::ExprKind::Assign(_, call, _) = second.kind + && let hir::ExprKind::Call(closure, _) = call.kind + && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind + && ident == path.segments[0].ident + && count_closure_usage(cx, block, path) == 1 + { + span_lint( + cx, + REDUNDANT_CLOSURE_CALL, + second.span, + "closure called just once immediately after it was declared", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs index 221aa317e5d49..001686c84f818 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_else.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs @@ -3,7 +3,7 @@ use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_ast::visit::{walk_expr, Visitor}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -105,7 +105,9 @@ impl<'ast> Visitor<'ast> for BreakVisitor { fn visit_expr(&mut self, expr: &'ast Expr) { self.is_break = match expr.kind { ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) => true, - ExprKind::Match(_, ref arms) => arms.iter().all(|arm| self.check_expr(&arm.body)), + ExprKind::Match(_, ref arms) => arms.iter().all(|arm| + arm.body.is_none() || arm.body.as_deref().is_some_and(|body| self.check_expr(body)) + ), ExprKind::If(_, ref then, Some(ref els)) => self.check_block(then) && self.check_expr(els), ExprKind::If(_, _, None) // ignore loops for simplicity diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs index b8e606df737cd..fb000cd7184ec 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs index 6bc0d06183f34..8c374d7d6db75 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs @@ -6,7 +6,7 @@ use rustc_hir::def::Res; use rustc_hir::{BindingAnnotation, ByRef, ExprKind, HirId, Local, Node, Pat, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::Ident; use rustc_span::DesugaringKind; @@ -46,40 +46,38 @@ declare_lint_pass!(RedundantLocals => [REDUNDANT_LOCALS]); impl<'tcx> LateLintPass<'tcx> for RedundantLocals { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { - if_chain! { - if !local.span.is_desugaring(DesugaringKind::Async); + if !local.span.is_desugaring(DesugaringKind::Async) // the pattern is a single by-value binding - if let PatKind::Binding(BindingAnnotation(ByRef::No, mutability), _, ident, None) = local.pat.kind; + && let PatKind::Binding(BindingAnnotation(ByRef::No, mutability), _, ident, None) = local.pat.kind // the binding is not type-ascribed - if local.ty.is_none(); + && local.ty.is_none() // the expression is a resolved path - if let Some(expr) = local.init; - if let ExprKind::Path(qpath @ QPath::Resolved(None, path)) = expr.kind; + && let Some(expr) = local.init + && let ExprKind::Path(qpath @ QPath::Resolved(None, path)) = expr.kind // the path is a single segment equal to the local's name - if let [last_segment] = path.segments; - if last_segment.ident == ident; + && let [last_segment] = path.segments + && last_segment.ident == ident // resolve the path to its defining binding pattern - if let Res::Local(binding_id) = cx.qpath_res(&qpath, expr.hir_id); - if let Node::Pat(binding_pat) = cx.tcx.hir().get(binding_id); + && let Res::Local(binding_id) = cx.qpath_res(&qpath, expr.hir_id) + && let Node::Pat(binding_pat) = cx.tcx.hir().get(binding_id) // the previous binding has the same mutability - if find_binding(binding_pat, ident).is_some_and(|bind| bind.1 == mutability); + && find_binding(binding_pat, ident).is_some_and(|bind| bind.1 == mutability) // the local does not change the effect of assignments to the binding. see #11290 - if !affects_assignments(cx, mutability, binding_id, local.hir_id); + && !affects_assignments(cx, mutability, binding_id, local.hir_id) // the local does not affect the code's drop behavior - if !needs_ordered_drop(cx, cx.typeck_results().expr_ty(expr)); + && !needs_ordered_drop(cx, cx.typeck_results().expr_ty(expr)) // the local is user-controlled - if !in_external_macro(cx.sess(), local.span); - if !is_from_proc_macro(cx, expr); - then { - span_lint_and_help( - cx, - REDUNDANT_LOCALS, - local.span, - &format!("redundant redefinition of a binding `{ident}`"), - Some(binding_pat.span), - &format!("`{ident}` is initially defined here"), - ); - } + && !in_external_macro(cx.sess(), local.span) + && !is_from_proc_macro(cx, expr) + { + span_lint_and_help( + cx, + REDUNDANT_LOCALS, + local.span, + &format!("redundant redefinition of a binding `{ident}`"), + Some(binding_pat.span), + &format!("`{ident}` is initially defined here"), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 03673eb27f8fd..0e43e4a7ee530 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -4,7 +4,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::hygiene::MacroKind; @@ -45,28 +45,27 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]); impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if_chain! { - if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()); - if !cx.effective_visibilities.is_exported(item.owner_id.def_id) && self.is_exported.last() == Some(&false); - if is_not_macro_export(item); - then { - let span = item.span.with_hi(item.ident.span.hi()); - let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id()); - span_lint_and_then( - cx, - REDUNDANT_PUB_CRATE, - span, - &format!("pub(crate) {descr} inside private module"), - |diag| { - diag.span_suggestion( - item.vis_span, - "consider using", - "pub".to_string(), - Applicability::MachineApplicable, - ); - }, - ); - } + if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()) + && !cx.effective_visibilities.is_exported(item.owner_id.def_id) + && self.is_exported.last() == Some(&false) + && is_not_macro_export(item) + { + let span = item.span.with_hi(item.ident.span.hi()); + let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id()); + span_lint_and_then( + cx, + REDUNDANT_PUB_CRATE, + span, + &format!("pub(crate) {descr} inside private module"), + |diag| { + diag.span_suggestion( + item.vis_span, + "consider using", + "pub".to_string(), + Applicability::MachineApplicable, + ); + }, + ); } if let ItemKind::Mod { .. } = item.kind { diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index 7adbd67912c09..c99b657c23a23 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -2,14 +2,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{is_type_lang_item, peel_mid_ty_refs}; -use if_chain::if_chain; use rustc_ast::util::parser::PREC_PREFIX; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{GenericArg, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -78,92 +77,83 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { } let ctxt = expr.span.ctxt(); - if_chain! { - if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind; - if addressee.span.ctxt() == ctxt; - if let ExprKind::Index(indexed, range, _) = addressee.kind; - if is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull); - then { - let (expr_ty, expr_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(expr)); - let (indexed_ty, indexed_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(indexed)); - let parent_expr = get_parent_expr(cx, expr); - let needs_parens_for_prefix = parent_expr.map_or(false, |parent| { - parent.precedence().order() > PREC_PREFIX - }); - let mut app = Applicability::MachineApplicable; + if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind + && addressee.span.ctxt() == ctxt + && let ExprKind::Index(indexed, range, _) = addressee.kind + && is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull) + { + let (expr_ty, expr_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(expr)); + let (indexed_ty, indexed_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(indexed)); + let parent_expr = get_parent_expr(cx, expr); + let needs_parens_for_prefix = parent_expr.map_or(false, |parent| parent.precedence().order() > PREC_PREFIX); + let mut app = Applicability::MachineApplicable; - let ((lint, msg), help, sugg) = if expr_ty == indexed_ty { - if expr_ref_count > indexed_ref_count { - // Indexing takes self by reference and can't return a reference to that - // reference as it's a local variable. The only way this could happen is if - // `self` contains a reference to the `Self` type. If this occurs then the - // lint no longer applies as it's essentially a field access, which is not - // redundant. - return; - } - let deref_count = indexed_ref_count - expr_ref_count; + let ((lint, msg), help, sugg) = if expr_ty == indexed_ty { + if expr_ref_count > indexed_ref_count { + // Indexing takes self by reference and can't return a reference to that + // reference as it's a local variable. The only way this could happen is if + // `self` contains a reference to the `Self` type. If this occurs then the + // lint no longer applies as it's essentially a field access, which is not + // redundant. + return; + } + let deref_count = indexed_ref_count - expr_ref_count; - let (lint, reborrow_str, help_str) = if mutability == Mutability::Mut { - // The slice was used to reborrow the mutable reference. - (DEREF_BY_SLICING_LINT, "&mut *", "reborrow the original value instead") - } else if matches!( - parent_expr, - Some(Expr { - kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _), - .. - }) - ) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| { - matches!(a.kind, Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. }))) - }) { - // The slice was used to make a temporary reference. - (DEREF_BY_SLICING_LINT, "&*", "reborrow the original value instead") - } else if deref_count != 0 { - (DEREF_BY_SLICING_LINT, "", "dereference the original value instead") - } else { - (REDUNDANT_SLICING_LINT, "", "use the original value instead") - }; + let (lint, reborrow_str, help_str) = if mutability == Mutability::Mut { + // The slice was used to reborrow the mutable reference. + (DEREF_BY_SLICING_LINT, "&mut *", "reborrow the original value instead") + } else if matches!( + parent_expr, + Some(Expr { + kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _), + .. + }) + ) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| { + matches!( + a.kind, + Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. })) + ) + }) { + // The slice was used to make a temporary reference. + (DEREF_BY_SLICING_LINT, "&*", "reborrow the original value instead") + } else if deref_count != 0 { + (DEREF_BY_SLICING_LINT, "", "dereference the original value instead") + } else { + (REDUNDANT_SLICING_LINT, "", "use the original value instead") + }; - let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; - let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix { - format!("({reborrow_str}{}{snip})", "*".repeat(deref_count)) - } else { - format!("{reborrow_str}{}{snip}", "*".repeat(deref_count)) - }; + let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; + let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix { + format!("({reborrow_str}{}{snip})", "*".repeat(deref_count)) + } else { + format!("{reborrow_str}{}{snip}", "*".repeat(deref_count)) + }; - (lint, help_str, sugg) - } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { - if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( - cx.param_env, - Ty::new_projection(cx.tcx,target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])), - ) { - if deref_ty == expr_ty { - let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; - let sugg = if needs_parens_for_prefix { - format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count)) - } else { - format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count)) - }; - (DEREF_BY_SLICING_LINT, "dereference the original value instead", sugg) + (lint, help_str, sugg) + } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { + if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( + cx.param_env, + Ty::new_projection(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])), + ) { + if deref_ty == expr_ty { + let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0; + let sugg = if needs_parens_for_prefix { + format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count)) } else { - return; - } + format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count)) + }; + (DEREF_BY_SLICING_LINT, "dereference the original value instead", sugg) } else { return; } } else { return; - }; + } + } else { + return; + }; - span_lint_and_sugg( - cx, - lint, - expr.span, - msg, - help, - sugg, - app, - ); - } + span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg, app); } } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index a70b831a80cf6..07b604f2326ba 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet; use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs index f6af9cac3def6..07fcb69afbc4c 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs index c984a8286eb88..19ce08bde10c9 100644 --- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::last_path_segment; use clippy_utils::source::snippet; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{GenericArg, GenericArgsParentheses, Mutability, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -38,34 +37,30 @@ declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]); impl<'tcx> LateLintPass<'tcx> for RefOptionRef { fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { - if_chain! { - if let TyKind::Ref(_, ref mut_ty) = ty.kind; - if mut_ty.mutbl == Mutability::Not; - if let TyKind::Path(ref qpath) = &mut_ty.ty.kind; - let last = last_path_segment(qpath); - if let Some(def_id) = last.res.opt_def_id(); - - if cx.tcx.is_diagnostic_item(sym::Option, def_id); - if let Some(params) = last_path_segment(qpath).args ; - if params.parenthesized == GenericArgsParentheses::No; - if let Some(inner_ty) = params.args.iter().find_map(|arg| match arg { + if let TyKind::Ref(_, ref mut_ty) = ty.kind + && mut_ty.mutbl == Mutability::Not + && let TyKind::Path(ref qpath) = &mut_ty.ty.kind + && let last = last_path_segment(qpath) + && let Some(def_id) = last.res.opt_def_id() + && cx.tcx.is_diagnostic_item(sym::Option, def_id) + && let Some(params) = last_path_segment(qpath).args + && params.parenthesized == GenericArgsParentheses::No + && let Some(inner_ty) = params.args.iter().find_map(|arg| match arg { GenericArg::Type(inner_ty) => Some(inner_ty), _ => None, - }); - if let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind; - if inner_mut_ty.mutbl == Mutability::Not; - - then { - span_lint_and_sugg( - cx, - REF_OPTION_REF, - ty.span, - "since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>`", - "try", - format!("Option<{}>", &snippet(cx, inner_ty.span, "..")), - Applicability::MaybeIncorrect, - ); - } + }) + && let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind + && inner_mut_ty.mutbl == Mutability::Not + { + span_lint_and_sugg( + cx, + REF_OPTION_REF, + ty.span, + "since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>`", + "try", + format!("Option<{}>", &snippet(cx, inner_ty.span, "..")), + Applicability::MaybeIncorrect, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/ref_patterns.rs b/src/tools/clippy/clippy_lints/src/ref_patterns.rs index 8b3dabde9bee9..a4be78b310b4e 100644 --- a/src/tools/clippy/clippy_lints/src/ref_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/ref_patterns.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{BindingAnnotation, Pat, PatKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs index 12da29f11089c..16086ba6637c3 100644 --- a/src/tools/clippy/clippy_lints/src/reference.rs +++ b/src/tools/clippy/clippy_lints/src/reference.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{snippet_opt, snippet_with_applicability}; -use if_chain::if_chain; use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::BytePos; declare_clippy_lint! { @@ -47,58 +46,62 @@ fn without_parens(mut e: &Expr) -> &Expr { impl EarlyLintPass for DerefAddrOf { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { - if_chain! { - if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind; - if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind; - if deref_target.span.eq_ctxt(e.span); - if !addrof_target.span.from_expansion(); - then { - let mut applicability = Applicability::MachineApplicable; - let sugg = if e.span.from_expansion() { - if let Some(macro_source) = snippet_opt(cx, e.span) { - // Remove leading whitespace from the given span - // e.g: ` $visitor` turns into `$visitor` - let trim_leading_whitespaces = |span| { - snippet_opt(cx, span).and_then(|snip| { + if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind + && let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind + && deref_target.span.eq_ctxt(e.span) + && !addrof_target.span.from_expansion() + { + let mut applicability = Applicability::MachineApplicable; + let sugg = if e.span.from_expansion() { + if let Some(macro_source) = snippet_opt(cx, e.span) { + // Remove leading whitespace from the given span + // e.g: ` $visitor` turns into `$visitor` + let trim_leading_whitespaces = |span| { + snippet_opt(cx, span) + .and_then(|snip| { #[expect(clippy::cast_possible_truncation)] - snip.find(|c: char| !c.is_whitespace()).map(|pos| { - span.lo() + BytePos(pos as u32) - }) - }).map_or(span, |start_no_whitespace| e.span.with_lo(start_no_whitespace)) - }; - - let mut generate_snippet = |pattern: &str| { - #[expect(clippy::cast_possible_truncation)] - macro_source.rfind(pattern).map(|pattern_pos| { - let rpos = pattern_pos + pattern.len(); - let span_after_ref = e.span.with_lo(BytePos(e.span.lo().0 + rpos as u32)); - let span = trim_leading_whitespaces(span_after_ref); - snippet_with_applicability(cx, span, "_", &mut applicability) + snip.find(|c: char| !c.is_whitespace()) + .map(|pos| span.lo() + BytePos(pos as u32)) }) - }; + .map_or(span, |start_no_whitespace| e.span.with_lo(start_no_whitespace)) + }; + + let mut generate_snippet = |pattern: &str| { + #[expect(clippy::cast_possible_truncation)] + macro_source.rfind(pattern).map(|pattern_pos| { + let rpos = pattern_pos + pattern.len(); + let span_after_ref = e.span.with_lo(BytePos(e.span.lo().0 + rpos as u32)); + let span = trim_leading_whitespaces(span_after_ref); + snippet_with_applicability(cx, span, "_", &mut applicability) + }) + }; - if *mutability == Mutability::Mut { - generate_snippet("mut") - } else { - generate_snippet("&") - } + if *mutability == Mutability::Mut { + generate_snippet("mut") } else { - Some(snippet_with_applicability(cx, e.span, "_", &mut applicability)) + generate_snippet("&") } } else { - Some(snippet_with_applicability(cx, addrof_target.span, "_", &mut applicability)) - }; - if let Some(sugg) = sugg { - span_lint_and_sugg( - cx, - DEREF_ADDROF, - e.span, - "immediately dereferencing a reference", - "try", - sugg.to_string(), - applicability, - ); + Some(snippet_with_applicability(cx, e.span, "_", &mut applicability)) } + } else { + Some(snippet_with_applicability( + cx, + addrof_target.span, + "_", + &mut applicability, + )) + }; + if let Some(sugg) = sugg { + span_lint_and_sugg( + cx, + DEREF_ADDROF, + e.span, + "immediately dereferencing a reference", + "try", + sugg.to_string(), + applicability, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs index cb78eec9e8d7b..687bad35a3685 100644 --- a/src/tools/clippy/clippy_lints/src/regex.rs +++ b/src/tools/clippy/clippy_lints/src/regex.rs @@ -8,7 +8,7 @@ use rustc_ast::ast::{LitKind, StrStyle}; use rustc_hir::def_id::DefIdMap; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Span}; declare_clippy_lint! { @@ -191,13 +191,11 @@ fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> { } fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) { - if_chain! { - if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind; - if let ExprKind::Array(exprs) = expr.kind; - then { - for expr in exprs { - check_regex(cx, expr, utf8); - } + if let ExprKind::AddrOf(BorrowKind::Ref, _, expr) = expr.kind + && let ExprKind::Array(exprs) = expr.kind + { + for expr in exprs { + check_regex(cx, expr, utf8); } } } diff --git a/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs b/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs index 1975946c6e6cc..ca7a0c7c87bb9 100644 --- a/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs @@ -7,7 +7,7 @@ use rustc_hir::def::Res; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Local, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -26,7 +26,7 @@ declare_clippy_lint! { /// ```no_run /// let mut v: Vec = Vec::with_capacity(10); /// ``` - #[clippy::version = "1.73.0"] + #[clippy::version = "1.74.0"] pub RESERVE_AFTER_INITIALIZATION, complexity, "`reserve` called immediately after `Vec` creation" diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs index 245029a066dbe..5962e8be9594b 100644 --- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs +++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs @@ -6,7 +6,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -69,35 +69,32 @@ declare_clippy_lint! { declare_lint_pass!(ReturnSelfNotMustUse => [RETURN_SELF_NOT_MUST_USE]); fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, span: Span, owner_id: OwnerId) { - if_chain! { + if !in_external_macro(cx.sess(), span) // If it comes from an external macro, better ignore it. - if !in_external_macro(cx.sess(), span); - if decl.implicit_self.has_implicit_self(); + && decl.implicit_self.has_implicit_self() // We only show this warning for public exported methods. - if cx.effective_visibilities.is_exported(fn_def); + && cx.effective_visibilities.is_exported(fn_def) // We don't want to emit this lint if the `#[must_use]` attribute is already there. - if !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use)); - if cx.tcx.visibility(fn_def.to_def_id()).is_public(); - let ret_ty = return_ty(cx, owner_id); - let self_arg = nth_arg(cx, owner_id, 0); + && !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use)) + && cx.tcx.visibility(fn_def.to_def_id()).is_public() + && let ret_ty = return_ty(cx, owner_id) + && let self_arg = nth_arg(cx, owner_id, 0) // If `Self` has the same type as the returned type, then we want to warn. // // For this check, we don't want to remove the reference on the returned type because if // there is one, we shouldn't emit a warning! - if self_arg.peel_refs() == ret_ty; + && self_arg.peel_refs() == ret_ty // If `Self` is already marked as `#[must_use]`, no need for the attribute here. - if !is_must_use_ty(cx, ret_ty); - - then { - span_lint_and_help( - cx, - RETURN_SELF_NOT_MUST_USE, - span, - "missing `#[must_use]` attribute on a method returning `Self`", - None, - "consider adding the `#[must_use]` attribute to the method or directly to the `Self` type" - ); - } + && !is_must_use_ty(cx, ret_ty) + { + span_lint_and_help( + cx, + RETURN_SELF_NOT_MUST_USE, + span, + "missing `#[must_use]` attribute on a method returning `Self`", + None, + "consider adding the `#[must_use]` attribute to the method or directly to the `Self` type", + ); } } @@ -111,18 +108,15 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse { span: Span, fn_def: LocalDefId, ) { - if_chain! { + if matches!(kind, FnKind::Method(_, _)) // We are only interested in methods, not in functions or associated functions. - if matches!(kind, FnKind::Method(_, _)); - if let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id()); + && let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id()) // We don't want this method to be te implementation of a trait because the // `#[must_use]` should be put on the trait definition directly. - if cx.tcx.trait_id_of_impl(impl_def).is_none(); - - then { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def); - check_method(cx, decl, fn_def, span, hir_id.expect_owner()); - } + && cx.tcx.trait_id_of_impl(impl_def).is_none() + { + let hir_id = cx.tcx.local_def_id_to_hir_id(fn_def); + check_method(cx, decl, fn_def, span, hir_id.expect_owner()); } } diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index f2a3dc5099dc3..2293b53b42b91 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -2,18 +2,19 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then, span_lin use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::visitors::{for_each_expr_with_closures, Descend}; -use clippy_utils::{fn_def_id, is_from_proc_macro, path_to_local_id, span_find_starting_semi}; +use clippy_utils::{fn_def_id, is_from_proc_macro, is_inside_let_else, path_to_local_id, span_find_starting_semi}; use core::ops::ControlFlow; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Block, Body, Expr, ExprKind, FnDecl, ItemKind, LangItem, MatchSource, OwnerNode, PatKind, QPath, Stmt, StmtKind, + Block, Body, Expr, ExprKind, FnDecl, HirId, ItemKind, LangItem, MatchSource, Node, OwnerNode, PatKind, QPath, Stmt, + StmtKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, GenericArgKind, Ty}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{BytePos, Pos, Span}; use std::borrow::Cow; @@ -159,6 +160,22 @@ impl<'tcx> ToString for RetReplacement<'tcx> { declare_lint_pass!(Return => [LET_AND_RETURN, NEEDLESS_RETURN, NEEDLESS_RETURN_WITH_QUESTION_MARK]); +/// Checks if a return statement is "needed" in the middle of a block, or if it can be removed. This +/// is the case when the enclosing block expression is coerced to some other type, which only works +/// because of the never-ness of `return` expressions +fn stmt_needs_never_type(cx: &LateContext<'_>, stmt_hir_id: HirId) -> bool { + cx.tcx + .hir() + .parent_iter(stmt_hir_id) + .find_map(|(_, node)| if let Node::Expr(expr) = node { Some(expr) } else { None }) + .is_some_and(|e| { + cx.typeck_results() + .expr_adjustments(e) + .iter() + .any(|adjust| adjust.target != cx.tcx.types.unit && matches!(adjust.kind, Adjust::NeverToAny)) + }) +} + impl<'tcx> LateLintPass<'tcx> for Return { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if !in_external_macro(cx.sess(), stmt.span) @@ -170,9 +187,11 @@ impl<'tcx> LateLintPass<'tcx> for Return { && let ItemKind::Fn(_, _, body) = item.kind && let block = cx.tcx.hir().body(body).value && let ExprKind::Block(block, _) = block.kind + && !is_inside_let_else(cx.tcx, expr) && let [.., final_stmt] = block.stmts && final_stmt.hir_id != stmt.hir_id && !is_from_proc_macro(cx, expr) + && !stmt_needs_never_type(cx, stmt.hir_id) { span_lint_and_sugg( cx, @@ -188,50 +207,45 @@ impl<'tcx> LateLintPass<'tcx> for Return { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { // we need both a let-binding stmt and an expr - if_chain! { - if let Some(retexpr) = block.expr; - if let Some(stmt) = block.stmts.iter().last(); - if let StmtKind::Local(local) = &stmt.kind; - if local.ty.is_none(); - if cx.tcx.hir().attrs(local.hir_id).is_empty(); - if let Some(initexpr) = &local.init; - if let PatKind::Binding(_, local_id, _, _) = local.pat.kind; - if path_to_local_id(retexpr, local_id); - if !last_statement_borrows(cx, initexpr); - if !in_external_macro(cx.sess(), initexpr.span); - if !in_external_macro(cx.sess(), retexpr.span); - if !local.span.from_expansion(); - then { - span_lint_hir_and_then( - cx, - LET_AND_RETURN, - retexpr.hir_id, - retexpr.span, - "returning the result of a `let` binding from a block", - |err| { - err.span_label(local.span, "unnecessary `let` binding"); + if let Some(retexpr) = block.expr + && let Some(stmt) = block.stmts.iter().last() + && let StmtKind::Local(local) = &stmt.kind + && local.ty.is_none() + && cx.tcx.hir().attrs(local.hir_id).is_empty() + && let Some(initexpr) = &local.init + && let PatKind::Binding(_, local_id, _, _) = local.pat.kind + && path_to_local_id(retexpr, local_id) + && !last_statement_borrows(cx, initexpr) + && !in_external_macro(cx.sess(), initexpr.span) + && !in_external_macro(cx.sess(), retexpr.span) + && !local.span.from_expansion() + { + span_lint_hir_and_then( + cx, + LET_AND_RETURN, + retexpr.hir_id, + retexpr.span, + "returning the result of a `let` binding from a block", + |err| { + err.span_label(local.span, "unnecessary `let` binding"); - if let Some(mut snippet) = snippet_opt(cx, initexpr.span) { - if !cx.typeck_results().expr_adjustments(retexpr).is_empty() { - if !has_enclosing_paren(&snippet) { - snippet = format!("({snippet})"); - } - snippet.push_str(" as _"); + if let Some(mut snippet) = snippet_opt(cx, initexpr.span) { + if !cx.typeck_results().expr_adjustments(retexpr).is_empty() { + if !has_enclosing_paren(&snippet) { + snippet = format!("({snippet})"); } - err.multipart_suggestion( - "return the expression directly", - vec![ - (local.span, String::new()), - (retexpr.span, snippet), - ], - Applicability::MachineApplicable, - ); - } else { - err.span_help(initexpr.span, "this expression can be directly returned"); + snippet.push_str(" as _"); } - }, - ); - } + err.multipart_suggestion( + "return the expression directly", + vec![(local.span, String::new()), (retexpr.span, snippet)], + Applicability::MachineApplicable, + ); + } else { + err.span_help(initexpr.span, "this expression can be directly returned"); + } + }, + ); } } @@ -314,7 +328,7 @@ fn check_final_expr<'tcx>( let replacement = if let Some(inner_expr) = inner { // if desugar of `do yeet`, don't lint if let ExprKind::Call(path_expr, _) = inner_expr.kind - && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind + && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, ..)) = path_expr.kind { return; } diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index fd1f3d3903ac9..74193e0199f3f 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -4,7 +4,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{HirId, Impl, ItemKind, Node, Path, QPath, TraitRef, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::AssocKind; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::Symbol; use rustc_span::Span; use std::collections::{BTreeMap, BTreeSet}; @@ -75,26 +75,23 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { match of_trait { Some(trait_ref) => { - let mut methods_in_trait: BTreeSet = if_chain! { - if let Some(Node::TraitRef(TraitRef { path, .. })) = - cx.tcx.hir().find(trait_ref.hir_ref_id); - if let Res::Def(DefKind::Trait, did) = path.res; - then{ - // FIXME: if - // `rustc_middle::ty::assoc::AssocItems::items` is public, - // we can iterate its keys instead of `in_definition_order`, - // which's more efficient - cx.tcx - .associated_items(did) - .in_definition_order() - .filter(|assoc_item| { - matches!(assoc_item.kind, AssocKind::Fn) - }) - .map(|assoc_item| assoc_item.name) - .collect() - }else{ - BTreeSet::new() - } + let mut methods_in_trait: BTreeSet = if let Some(Node::TraitRef(TraitRef { + path, .. + })) = cx.tcx.hir().find(trait_ref.hir_ref_id) + && let Res::Def(DefKind::Trait, did) = path.res + { + // FIXME: if + // `rustc_middle::ty::assoc::AssocItems::items` is public, + // we can iterate its keys instead of `in_definition_order`, + // which's more efficient + cx.tcx + .associated_items(did) + .in_definition_order() + .filter(|assoc_item| matches!(assoc_item.kind, AssocKind::Fn)) + .map(|assoc_item| assoc_item.name) + .collect() + } else { + BTreeSet::new() }; let mut check_trait_method = |method_name: Symbol, trait_method_span: Span| { diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index b92014f68b396..935dd4a3630f5 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -3,7 +3,7 @@ use clippy_utils::return_ty; use clippy_utils::ty::contains_adt_constructor; use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -70,22 +70,20 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { return; } - if_chain! { - if let Some(self_def) = self_ty.ty_adt_def(); - if let Some(self_local_did) = self_def.did().as_local(); - let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did); - if let Some(Node::Item(x)) = cx.tcx.hir().find(self_id); - let type_name = x.ident.name.as_str().to_lowercase(); - if impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace('_', "") == type_name; - - then { - span_lint( - cx, - SELF_NAMED_CONSTRUCTORS, - impl_item.span, - &format!("constructor `{}` has the same name as the type", impl_item.ident.name), - ); - } + if let Some(self_def) = self_ty.ty_adt_def() + && let Some(self_local_did) = self_def.did().as_local() + && let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did) + && let Some(Node::Item(x)) = cx.tcx.hir().find(self_id) + && let type_name = x.ident.name.as_str().to_lowercase() + && (impl_item.ident.name.as_str() == type_name + || impl_item.ident.name.as_str().replace('_', "") == type_name) + { + span_lint( + cx, + SELF_NAMED_CONSTRUCTORS, + impl_item.span, + &format!("constructor `{}` has the same name as the type", impl_item.ident.name), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs index b0601bba4aff3..0b3adfb7a4b8d 100644 --- a/src/tools/clippy/clippy_lints/src/semicolon_block.rs +++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and use rustc_errors::Applicability; use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs index ccf8b99770562..2cd3e57f885a2 100644 --- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs @@ -1,11 +1,10 @@ use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Block, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -38,30 +37,29 @@ declare_lint_pass!(SemicolonIfNothingReturned => [SEMICOLON_IF_NOTHING_RETURNED] impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { - if_chain! { - if !block.span.from_expansion(); - if let Some(expr) = block.expr; - let t_expr = cx.typeck_results().expr_ty(expr); - if t_expr.is_unit(); - let mut app = Applicability::MachineApplicable; - if let snippet = snippet_with_context(cx, expr.span, block.span.ctxt(), "}", &mut app).0; - if !snippet.ends_with('}') && !snippet.ends_with(';'); - if cx.sess().source_map().is_multiline(block.span); - then { - // filter out the desugared `for` loop - if let ExprKind::DropTemps(..) = &expr.kind { - return; - } - span_lint_and_sugg( - cx, - SEMICOLON_IF_NOTHING_RETURNED, - expr.span.source_callsite(), - "consider adding a `;` to the last statement for consistent formatting", - "add a `;` here", - format!("{snippet};"), - app, - ); + if !block.span.from_expansion() + && let Some(expr) = block.expr + && let t_expr = cx.typeck_results().expr_ty(expr) + && t_expr.is_unit() + && let mut app = Applicability::MachineApplicable + && let snippet = snippet_with_context(cx, expr.span, block.span.ctxt(), "}", &mut app).0 + && !snippet.ends_with('}') + && !snippet.ends_with(';') + && cx.sess().source_map().is_multiline(block.span) + { + // filter out the desugared `for` loop + if let ExprKind::DropTemps(..) = &expr.kind { + return; } + span_lint_and_sugg( + cx, + SEMICOLON_IF_NOTHING_RETURNED, + expr.span.source_callsite(), + "consider adding a `;` to the last statement for consistent formatting", + "add a `;` here", + format!("{snippet};"), + app, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs index fc1c2af9257bf..90834d784a57a 100644 --- a/src/tools/clippy/clippy_lints/src/serde_api.rs +++ b/src/tools/clippy/clippy_lints/src/serde_api.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::{get_trait_def_id, paths}; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 41c10b34a4248..c74364d89d61b 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::hir_id::ItemLocalId; use rustc_hir::{Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, Let, Node, Pat, PatKind, QPath, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{Span, Symbol}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index 57bcee1a87196..6c99ccda7ea73 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -8,7 +8,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{self as hir}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::{GenericArgKind, Ty, TypeAndMut}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, DUMMY_SP}; use std::borrow::Cow; diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs index ae81e1198af26..396d2717a13fa 100644 --- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs +++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs @@ -7,7 +7,7 @@ use rustc_hir::{Body, Expr, ExprKind, FnDecl}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs b/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs index 74ee8ce2de725..42f1564db353a 100644 --- a/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs +++ b/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{GenericParam, GenericParamKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs index 9c21d70c82cc3..18fbbdb407911 100644 --- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs +++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs @@ -5,7 +5,7 @@ use rustc_ast::visit::{walk_expr, Visitor}; use rustc_ast::{Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::edition::Edition; use rustc_span::symbol::kw; use rustc_span::{Span, Symbol}; diff --git a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs index 099743d229d1f..95b4a11a78347 100644 --- a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs +++ b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs @@ -8,7 +8,7 @@ use rustc_ast::{LitIntType, LitKind, UintTy}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, LangItem, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use std::fmt::{self, Display, Formatter}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs index b940cac6047be..756e47cbdf0a4 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs @@ -2,11 +2,10 @@ //! expecting a count of T use clippy_utils::diagnostics::span_lint_and_help; -use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty, TypeAndMut}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -39,16 +38,17 @@ declare_lint_pass!(SizeOfInElementCount => [SIZE_OF_IN_ELEMENT_COUNT]); fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, inverted: bool) -> Option> { match expr.kind { ExprKind::Call(count_func, _func_args) => { - if_chain! { - if !inverted; - if let ExprKind::Path(ref count_func_qpath) = count_func.kind; - if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id(); - if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::mem_size_of | sym::mem_size_of_val)); - then { - cx.typeck_results().node_args(count_func.hir_id).types().next() - } else { - None - } + if !inverted + && let ExprKind::Path(ref count_func_qpath) = count_func.kind + && let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id() + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::mem_size_of | sym::mem_size_of_val) + ) + { + cx.typeck_results().node_args(count_func.hir_id).types().next() + } else { + None } }, ExprKind::Binary(op, left, right) if BinOpKind::Mul == op.node => { @@ -80,13 +80,12 @@ fn get_pointee_ty_and_count_expr<'tcx>( "wrapping_offset", ]; - if_chain! { + if let ExprKind::Call(func, [.., count]) = expr.kind // Find calls to ptr::{copy, copy_nonoverlapping} // and ptr::{swap_nonoverlapping, write_bytes}, - if let ExprKind::Call(func, [.., count]) = expr.kind; - if let ExprKind::Path(ref func_qpath) = func.kind; - if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if matches!(cx.tcx.get_diagnostic_name(def_id), Some( + && let ExprKind::Path(ref func_qpath) = func.kind + && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id() + && matches!(cx.tcx.get_diagnostic_name(def_id), Some( sym::ptr_copy | sym::ptr_copy_nonoverlapping | sym::ptr_slice_from_raw_parts @@ -95,26 +94,23 @@ fn get_pointee_ty_and_count_expr<'tcx>( | sym::ptr_write_bytes | sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut - )); + )) // Get the pointee type - if let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next(); - then { - return Some((pointee_ty, count)); - } + && let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next() + { + return Some((pointee_ty, count)); }; - if_chain! { + if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods - if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind; - let method_ident = method_path.ident.as_str(); - if METHODS.iter().any(|m| *m == method_ident); + && let method_ident = method_path.ident.as_str() + && METHODS.iter().any(|m| *m == method_ident) // Get the pointee type - if let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) = - cx.typeck_results().expr_ty(ptr_self).kind(); - then { - return Some((*pointee_ty, count)); - } + && let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) = + cx.typeck_results().expr_ty(ptr_self).kind() + { + return Some((*pointee_ty, count)); }; None } @@ -127,25 +123,16 @@ impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount { const LINT_MSG: &str = "found a count of bytes \ instead of a count of elements of `T`"; - if_chain! { + if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr) // Find calls to functions with an element count parameter and get // the pointee type and count parameter expression - if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr); // Find a size_of call in the count parameter expression and // check that it's the same type - if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr, false); - if pointee_ty == ty_used_for_size_of; - then { - span_lint_and_help( - cx, - SIZE_OF_IN_ELEMENT_COUNT, - count_expr.span, - LINT_MSG, - None, - HELP_MSG - ); - } + && let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr, false) + && pointee_ty == ty_used_for_size_of + { + span_lint_and_help(cx, SIZE_OF_IN_ELEMENT_COUNT, count_expr.span, LINT_MSG, None, HELP_MSG); }; } } diff --git a/src/tools/clippy/clippy_lints/src/size_of_ref.rs b/src/tools/clippy/clippy_lints/src/size_of_ref.rs index 7de029b7b9425..14ca7a3f0042e 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_ref.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_ref.rs @@ -3,7 +3,7 @@ use clippy_utils::path_def_id; use clippy_utils::ty::peel_mid_ty_refs; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 2244eab96ca88..c4a5e48e855e6 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -5,12 +5,11 @@ use clippy_utils::{ get_enclosing_block, is_expr_path_def_path, is_integer_literal, is_path_diagnostic_item, path_to_local, path_to_local_id, paths, SpanlessEq, }; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -103,41 +102,35 @@ enum InitializationType<'tcx> { impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // Matches initialization on reassignments. For example: `vec = Vec::with_capacity(100)` - if_chain! { - if let ExprKind::Assign(left, right, _) = expr.kind; - if let Some(local_id) = path_to_local(left); - if let Some(size_expr) = Self::as_vec_initializer(cx, right); - - then { - let vi = VecAllocation { - local_id, - allocation_expr: right, - size_expr, - }; - - Self::search_initialization(cx, vi, expr.hir_id); - } + if let ExprKind::Assign(left, right, _) = expr.kind + && let Some(local_id) = path_to_local(left) + && let Some(size_expr) = Self::as_vec_initializer(cx, right) + { + let vi = VecAllocation { + local_id, + allocation_expr: right, + size_expr, + }; + + Self::search_initialization(cx, vi, expr.hir_id); } } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` // or `Vec::new()` - if_chain! { - if let StmtKind::Local(local) = stmt.kind; - if let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind; - if let Some(init) = local.init; - if let Some(size_expr) = Self::as_vec_initializer(cx, init); - - then { - let vi = VecAllocation { - local_id, - allocation_expr: init, - size_expr, - }; - - Self::search_initialization(cx, vi, stmt.hir_id); - } + if let StmtKind::Local(local) = stmt.kind + && let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind + && let Some(init) = local.init + && let Some(size_expr) = Self::as_vec_initializer(cx, init) + { + let vi = VecAllocation { + local_id, + allocation_expr: init, + size_expr, + }; + + Self::search_initialization(cx, vi, stmt.hir_id); } } } @@ -242,16 +235,13 @@ struct VectorInitializationVisitor<'a, 'tcx> { impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Checks if the given expression is extending a vector with `repeat(0).take(..)` fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) { - if_chain! { - if self.initialization_found; - if let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind; - if path_to_local_id(self_arg, self.vec_alloc.local_id); - if path.ident.name == sym!(extend); - if self.is_repeat_take(extend_arg); - - then { - self.slow_expression = Some(InitializationType::Extend(expr)); - } + if self.initialization_found + && let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind + && path_to_local_id(self_arg, self.vec_alloc.local_id) + && path.ident.name == sym!(extend) + && self.is_repeat_take(extend_arg) + { + self.slow_expression = Some(InitializationType::Extend(expr)); } } @@ -281,21 +271,19 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Returns `true` if give expression is `repeat(0).take(...)` fn is_repeat_take(&mut self, expr: &'tcx Expr<'tcx>) -> bool { - if_chain! { - if let ExprKind::MethodCall(take_path, recv, [len_arg, ..], _) = expr.kind; - if take_path.ident.name == sym!(take); + if let ExprKind::MethodCall(take_path, recv, [len_arg, ..], _) = expr.kind + && take_path.ident.name == sym!(take) // Check that take is applied to `repeat(0)` - if self.is_repeat_zero(recv); - then { - if let InitializedSize::Initialized(size_expr) = self.vec_alloc.size_expr { - // Check that len expression is equals to `with_capacity` expression - return SpanlessEq::new(self.cx).eq_expr(len_arg, size_expr) - || matches!(len_arg.kind, ExprKind::MethodCall(path, ..) if path.ident.as_str() == "capacity") - } - - self.vec_alloc.size_expr = InitializedSize::Initialized(len_arg); - return true; + && self.is_repeat_zero(recv) + { + if let InitializedSize::Initialized(size_expr) = self.vec_alloc.size_expr { + // Check that len expression is equals to `with_capacity` expression + return SpanlessEq::new(self.cx).eq_expr(len_arg, size_expr) + || matches!(len_arg.kind, ExprKind::MethodCall(path, ..) if path.ident.as_str() == "capacity"); } + + self.vec_alloc.size_expr = InitializedSize::Initialized(len_arg); + return true; } false @@ -303,15 +291,13 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Returns `true` if given expression is `repeat(0)` fn is_repeat_zero(&self, expr: &Expr<'_>) -> bool { - if_chain! { - if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind; - if is_path_diagnostic_item(self.cx, fn_expr, sym::iter_repeat); - if is_integer_literal(repeat_arg, 0); - then { - true - } else { - false - } + if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind + && is_path_diagnostic_item(self.cx, fn_expr, sym::iter_repeat) + && is_integer_literal(repeat_arg, 0) + { + true + } else { + false } } } diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index d07a44770cc75..38fd54a0f1e0c 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{HirId, Path, PathSegment}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; use rustc_span::{sym, Span}; diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index a44adc938559f..13ae1ff52ddfe 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -5,14 +5,13 @@ use clippy_utils::{ get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls, peel_blocks, SpanlessEq, }; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::sym; @@ -251,128 +250,115 @@ const MAX_LENGTH_BYTE_STRING_LIT: usize = 32; declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS_BYTES]); impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { - #[expect(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use rustc_ast::LitKind; - if_chain! { + if let ExprKind::Call(fun, args) = e.kind // Find std::str::converts::from_utf8 - if let ExprKind::Call(fun, args) = e.kind; - if is_path_diagnostic_item(cx, fun, sym::str_from_utf8); + && is_path_diagnostic_item(cx, fun, sym::str_from_utf8) // Find string::as_bytes - if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind; - if let ExprKind::Index(left, right, _) = args.kind; - let (method_names, expressions, _) = method_calls(left, 1); - if method_names.len() == 1; - if expressions.len() == 1; - if expressions[0].1.is_empty(); - if method_names[0] == sym!(as_bytes); + && let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args[0].kind + && let ExprKind::Index(left, right, _) = args.kind + && let (method_names, expressions, _) = method_calls(left, 1) + && method_names.len() == 1 + && expressions.len() == 1 + && expressions[0].1.is_empty() + && method_names[0] == sym!(as_bytes) // Check for slicer - if let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), _, _) = right.kind; + && let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), _, _) = right.kind + { + let mut applicability = Applicability::MachineApplicable; + let string_expression = &expressions[0].0; - then { - let mut applicability = Applicability::MachineApplicable; - let string_expression = &expressions[0].0; + let snippet_app = snippet_with_applicability(cx, string_expression.span, "..", &mut applicability); - let snippet_app = snippet_with_applicability( - cx, - string_expression.span, "..", - &mut applicability, - ); + span_lint_and_sugg( + cx, + STRING_FROM_UTF8_AS_BYTES, + e.span, + "calling a slice of `as_bytes()` with `from_utf8` should be not necessary", + "try", + format!("Some(&{snippet_app}[{}])", snippet(cx, right.span, "..")), + applicability, + ); + } + if !in_external_macro(cx.sess(), e.span) + && let ExprKind::MethodCall(path, receiver, ..) = &e.kind + && path.ident.name == sym!(as_bytes) + && let ExprKind::Lit(lit) = &receiver.kind + && let LitKind::Str(lit_content, _) = &lit.node + { + let callsite = snippet(cx, receiver.span.source_callsite(), r#""foo""#); + let mut applicability = Applicability::MachineApplicable; + if callsite.starts_with("include_str!") { span_lint_and_sugg( cx, - STRING_FROM_UTF8_AS_BYTES, + STRING_LIT_AS_BYTES, e.span, - "calling a slice of `as_bytes()` with `from_utf8` should be not necessary", - "try", - format!("Some(&{snippet_app}[{}])", snippet(cx, right.span, "..")), - applicability - ) - } - } - - if_chain! { - if !in_external_macro(cx.sess(), e.span); - if let ExprKind::MethodCall(path, receiver, ..) = &e.kind; - if path.ident.name == sym!(as_bytes); - if let ExprKind::Lit(lit) = &receiver.kind; - if let LitKind::Str(lit_content, _) = &lit.node; - then { - let callsite = snippet(cx, receiver.span.source_callsite(), r#""foo""#); - let mut applicability = Applicability::MachineApplicable; - if callsite.starts_with("include_str!") { + "calling `as_bytes()` on `include_str!(..)`", + "consider using `include_bytes!(..)` instead", + snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability).replacen( + "include_str", + "include_bytes", + 1, + ), + applicability, + ); + } else if lit_content.as_str().is_ascii() + && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT + && !receiver.span.from_expansion() + { + if let Some((parent, id)) = get_expr_use_or_unification_node(cx.tcx, e) + && let Node::Expr(parent) = parent + && let ExprKind::Match(scrutinee, ..) = parent.kind + && scrutinee.hir_id == id + { + // Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces + // `&[u8]`. This change would prevent matching with different sized slices. + } else if !callsite.starts_with("env!") { span_lint_and_sugg( cx, STRING_LIT_AS_BYTES, e.span, - "calling `as_bytes()` on `include_str!(..)`", - "consider using `include_bytes!(..)` instead", - snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability).replacen( - "include_str", - "include_bytes", - 1, + "calling `as_bytes()` on a string literal", + "consider using a byte string literal instead", + format!( + "b{}", + snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability) ), applicability, ); - } else if lit_content.as_str().is_ascii() - && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT - && !receiver.span.from_expansion() - { - if let Some((parent, id)) = get_expr_use_or_unification_node(cx.tcx, e) - && let Node::Expr(parent) = parent - && let ExprKind::Match(scrutinee, ..) = parent.kind - && scrutinee.hir_id == id - { - // Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces - // `&[u8]`. This change would prevent matching with different sized slices. - } else if !callsite.starts_with("env!") { - span_lint_and_sugg( - cx, - STRING_LIT_AS_BYTES, - e.span, - "calling `as_bytes()` on a string literal", - "consider using a byte string literal instead", - format!( - "b{}", - snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability) - ), - applicability, - ); - } } } } - if_chain! { - if let ExprKind::MethodCall(path, recv, [], _) = &e.kind; - if path.ident.name == sym!(into_bytes); - if let ExprKind::MethodCall(path, recv, [], _) = &recv.kind; - if matches!(path.ident.name.as_str(), "to_owned" | "to_string"); - if let ExprKind::Lit(lit) = &recv.kind; - if let LitKind::Str(lit_content, _) = &lit.node; - - if lit_content.as_str().is_ascii(); - if lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT; - if !recv.span.from_expansion(); - then { - let mut applicability = Applicability::MachineApplicable; + if let ExprKind::MethodCall(path, recv, [], _) = &e.kind + && path.ident.name == sym!(into_bytes) + && let ExprKind::MethodCall(path, recv, [], _) = &recv.kind + && matches!(path.ident.name.as_str(), "to_owned" | "to_string") + && let ExprKind::Lit(lit) = &recv.kind + && let LitKind::Str(lit_content, _) = &lit.node + && lit_content.as_str().is_ascii() + && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT + && !recv.span.from_expansion() + { + let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - STRING_LIT_AS_BYTES, - e.span, - "calling `into_bytes()` on a string literal", - "consider using a byte string literal instead", - format!( - "b{}.to_vec()", - snippet_with_applicability(cx, recv.span, r#""..""#, &mut applicability) - ), - applicability, - ); - } + span_lint_and_sugg( + cx, + STRING_LIT_AS_BYTES, + e.span, + "calling `into_bytes()` on a string literal", + "consider using a byte string literal instead", + format!( + "b{}.to_vec()", + snippet_with_applicability(cx, recv.span, r#""..""#, &mut applicability) + ), + applicability, + ); } } } @@ -406,22 +392,20 @@ declare_lint_pass!(StrToString => [STR_TO_STRING]); impl<'tcx> LateLintPass<'tcx> for StrToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { - if_chain! { - if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind; - if path.ident.name == sym::to_string; - let ty = cx.typeck_results().expr_ty(self_arg); - if let ty::Ref(_, ty, ..) = ty.kind(); - if ty.is_str(); - then { - span_lint_and_help( - cx, - STR_TO_STRING, - expr.span, - "`to_string()` called on a `&str`", - None, - "consider using `.to_owned()`", - ); - } + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind + && path.ident.name == sym::to_string + && let ty = cx.typeck_results().expr_ty(self_arg) + && let ty::Ref(_, ty, ..) = ty.kind() + && ty.is_str() + { + span_lint_and_help( + cx, + STR_TO_STRING, + expr.span, + "`to_string()` called on a `&str`", + None, + "consider using `.to_owned()`", + ); } } } @@ -456,21 +440,19 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]); impl<'tcx> LateLintPass<'tcx> for StringToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { - if_chain! { - if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind; - if path.ident.name == sym::to_string; - let ty = cx.typeck_results().expr_ty(self_arg); - if is_type_lang_item(cx, ty, LangItem::String); - then { - span_lint_and_help( - cx, - STRING_TO_STRING, - expr.span, - "`to_string()` called on a `String`", - None, - "consider using `.clone()`", - ); - } + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind + && path.ident.name == sym::to_string + && let ty = cx.typeck_results().expr_ty(self_arg) + && is_type_lang_item(cx, ty, LangItem::String) + { + span_lint_and_help( + cx, + STRING_TO_STRING, + expr.span, + "`to_string()` called on a `String`", + None, + "consider using `.clone()`", + ); } } } @@ -500,26 +482,24 @@ declare_lint_pass!(TrimSplitWhitespace => [TRIM_SPLIT_WHITESPACE]); impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { let tyckres = cx.typeck_results(); - if_chain! { - if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind; - if path.ident.name == sym!(split_whitespace); - if let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id); - if cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id); - if let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind; - if let trim_fn_name @ ("trim" | "trim_start" | "trim_end") = path.ident.name.as_str(); - if let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id); - if is_one_of_trim_diagnostic_items(cx, trim_def_id); - then { - span_lint_and_sugg( - cx, - TRIM_SPLIT_WHITESPACE, - trim_span.with_hi(split_ws_span.lo()), - &format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"), - &format!("remove `{trim_fn_name}()`"), - String::new(), - Applicability::MachineApplicable, - ); - } + if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind + && path.ident.name == sym!(split_whitespace) + && let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id) + && cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id) + && let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind + && let trim_fn_name @ ("trim" | "trim_start" | "trim_end") = path.ident.name.as_str() + && let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id) + && is_one_of_trim_diagnostic_items(cx, trim_def_id) + { + span_lint_and_sugg( + cx, + TRIM_SPLIT_WHITESPACE, + trim_span.with_hi(split_ws_span.lo()), + &format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"), + &format!("remove `{trim_fn_name}()`"), + String::new(), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs index b3db5e9a42214..8cf4715eeb89c 100644 --- a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs +++ b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs @@ -3,11 +3,10 @@ use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::is_expr_unsafe; use clippy_utils::{get_parent_node, match_libc_symbol}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, LangItem, Node, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -41,48 +40,45 @@ declare_lint_pass!(StrlenOnCStrings => [STRLEN_ON_C_STRINGS]); impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if !expr.span.from_expansion(); - if let ExprKind::Call(func, [recv]) = expr.kind; - if let ExprKind::Path(path) = &func.kind; - if let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id(); - if match_libc_symbol(cx, did, "strlen"); - if let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind; - if !recv.span.from_expansion(); - if path.ident.name == sym::as_ptr; - then { - let ctxt = expr.span.ctxt(); - let span = match get_parent_node(cx.tcx, expr.hir_id) { - Some(Node::Block(&Block { - rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), span, .. - })) - if span.ctxt() == ctxt && !is_expr_unsafe(cx, self_arg) => { - span - } - _ => expr.span, - }; + if !expr.span.from_expansion() + && let ExprKind::Call(func, [recv]) = expr.kind + && let ExprKind::Path(path) = &func.kind + && let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id() + && match_libc_symbol(cx, did, "strlen") + && let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind + && !recv.span.from_expansion() + && path.ident.name == sym::as_ptr + { + let ctxt = expr.span.ctxt(); + let span = match get_parent_node(cx.tcx, expr.hir_id) { + Some(Node::Block(&Block { + rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), + span, + .. + })) if span.ctxt() == ctxt && !is_expr_unsafe(cx, self_arg) => span, + _ => expr.span, + }; - let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); - let mut app = Applicability::MachineApplicable; - let val_name = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0; - let method_name = if is_type_diagnostic_item(cx, ty, sym::cstring_type) { - "as_bytes" - } else if is_type_lang_item(cx, ty, LangItem::CStr) { - "to_bytes" - } else { - return; - }; + let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); + let mut app = Applicability::MachineApplicable; + let val_name = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0; + let method_name = if is_type_diagnostic_item(cx, ty, sym::cstring_type) { + "as_bytes" + } else if is_type_lang_item(cx, ty, LangItem::CStr) { + "to_bytes" + } else { + return; + }; - span_lint_and_sugg( - cx, - STRLEN_ON_C_STRINGS, - span, - "using `libc::strlen` on a `CString` or `CStr` value", - "try", - format!("{val_name}.{method_name}().len()"), - app, - ); - } + span_lint_and_sugg( + cx, + STRLEN_ON_C_STRINGS, + span, + "using `libc::strlen` on a `CString` or `CStr` value", + "try", + format!("{val_name}.{method_name}().len()"), + app, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/suspicious_doc_comments.rs b/src/tools/clippy/clippy_lints/src/suspicious_doc_comments.rs deleted file mode 100644 index 0abc199da1646..0000000000000 --- a/src/tools/clippy/clippy_lints/src/suspicious_doc_comments.rs +++ /dev/null @@ -1,95 +0,0 @@ -use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}; -use if_chain::if_chain; -use rustc_ast::token::CommentKind; -use rustc_ast::{AttrKind, AttrStyle, Attribute, Item}; -use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; - -declare_clippy_lint! { - /// ### What it does - /// Detects the use of outer doc comments (`///`, `/**`) followed by a bang (`!`): `///!` - /// - /// ### Why is this bad? - /// Triple-slash comments (known as "outer doc comments") apply to items that follow it. - /// An outer doc comment followed by a bang (i.e. `///!`) has no specific meaning. - /// - /// The user most likely meant to write an inner doc comment (`//!`, `/*!`), which - /// applies to the parent item (i.e. the item that the comment is contained in, - /// usually a module or crate). - /// - /// ### Known problems - /// Inner doc comments can only appear before items, so there are certain cases where the suggestion - /// made by this lint is not valid code. For example: - /// ```rs - /// fn foo() {} - /// ///! - /// fn bar() {} - /// ``` - /// This lint detects the doc comment and suggests changing it to `//!`, but an inner doc comment - /// is not valid at that position. - /// - /// ### Example - /// In this example, the doc comment is attached to the *function*, rather than the *module*. - /// ```no_run - /// pub mod util { - /// ///! This module contains utility functions. - /// - /// pub fn dummy() {} - /// } - /// ``` - /// - /// Use instead: - /// ```no_run - /// pub mod util { - /// //! This module contains utility functions. - /// - /// pub fn dummy() {} - /// } - /// ``` - #[clippy::version = "1.70.0"] - pub SUSPICIOUS_DOC_COMMENTS, - suspicious, - "suspicious usage of (outer) doc comments" -} -declare_lint_pass!(SuspiciousDocComments => [SUSPICIOUS_DOC_COMMENTS]); - -const WARNING: &str = "this is an outer doc comment and does not apply to the parent module or crate"; -const HELP: &str = "use an inner doc comment to document the parent module or crate"; - -impl EarlyLintPass for SuspiciousDocComments { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let replacements = collect_doc_comment_replacements(&item.attrs); - - if let Some(((lo_span, _), (hi_span, _))) = replacements.first().zip(replacements.last()) { - let span = lo_span.to(*hi_span); - - span_lint_and_then(cx, SUSPICIOUS_DOC_COMMENTS, span, WARNING, |diag| { - multispan_sugg_with_applicability(diag, HELP, Applicability::MaybeIncorrect, replacements); - }); - } - } -} - -fn collect_doc_comment_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> { - attrs - .iter() - .filter_map(|attr| { - if_chain! { - if let AttrKind::DocComment(com_kind, sym) = attr.kind; - if let AttrStyle::Outer = attr.style; - if let Some(com) = sym.as_str().strip_prefix('!'); - then { - let sugg = match com_kind { - CommentKind::Line => format!("//!{com}"), - CommentKind::Block => format!("/*!{com}*/") - }; - Some((attr.span, sugg)) - } else { - None - } - } - }) - .collect() -} diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index bb8cde5b94d16..8b9d9bade915f 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -2,12 +2,11 @@ use clippy_utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use core::ops::{Add, AddAssign}; -use if_chain::if_chain; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, StmtKind}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -155,34 +154,22 @@ fn check_binops(cx: &EarlyContext<'_>, binops: &[&BinaryOp<'_>]) { match (no_difference_info, double_difference_info) { (Some(i), None) => attempt_to_emit_no_difference_lint(cx, binops, i, expected_loc), (None, Some((double_difference_index, ident_loc1, ident_loc2))) => { - if_chain! { - if one_ident_difference_count == binop_count - 1; - if let Some(binop) = binops.get(double_difference_index); - then { - let changed_loc = if ident_loc1 == expected_loc { - ident_loc2 - } else if ident_loc2 == expected_loc { - ident_loc1 - } else { - // This expression doesn't match the form we're - // looking for. - return; - }; - - if let Some(sugg) = ident_swap_sugg( - cx, - &paired_identifiers, - binop, - changed_loc, - &mut applicability, - ) { - emit_suggestion( - cx, - binop.span, - sugg, - applicability, - ); - } + if one_ident_difference_count == binop_count - 1 + && let Some(binop) = binops.get(double_difference_index) + { + let changed_loc = if ident_loc1 == expected_loc { + ident_loc2 + } else if ident_loc2 == expected_loc { + ident_loc1 + } else { + // This expression doesn't match the form we're + // looking for. + return; + }; + + if let Some(sugg) = ident_swap_sugg(cx, &paired_identifiers, binop, changed_loc, &mut applicability) + { + emit_suggestion(cx, binop.span, sugg, applicability); } } }, @@ -212,48 +199,32 @@ fn attempt_to_emit_no_difference_lint( let old_right_ident = get_ident(binop.right, expected_loc); for b in skip_index(binops.iter(), i) { - if_chain! { - if let (Some(old_ident), Some(new_ident)) = - (old_left_ident, get_ident(b.left, expected_loc)); - if old_ident != new_ident; - if let Some(sugg) = suggestion_with_swapped_ident( + if let (Some(old_ident), Some(new_ident)) = (old_left_ident, get_ident(b.left, expected_loc)) + && old_ident != new_ident + && let Some(sugg) = + suggestion_with_swapped_ident(cx, binop.left, expected_loc, new_ident, &mut applicability) + { + emit_suggestion( cx, - binop.left, - expected_loc, - new_ident, - &mut applicability, + binop.span, + replace_left_sugg(cx, binop, &sugg, &mut applicability), + applicability, ); - then { - emit_suggestion( - cx, - binop.span, - replace_left_sugg(cx, binop, &sugg, &mut applicability), - applicability, - ); - return; - } + return; } - if_chain! { - if let (Some(old_ident), Some(new_ident)) = - (old_right_ident, get_ident(b.right, expected_loc)); - if old_ident != new_ident; - if let Some(sugg) = suggestion_with_swapped_ident( + if let (Some(old_ident), Some(new_ident)) = (old_right_ident, get_ident(b.right, expected_loc)) + && old_ident != new_ident + && let Some(sugg) = + suggestion_with_swapped_ident(cx, binop.right, expected_loc, new_ident, &mut applicability) + { + emit_suggestion( cx, - binop.right, - expected_loc, - new_ident, - &mut applicability, + binop.span, + replace_right_sugg(cx, binop, &sugg, &mut applicability), + applicability, ); - then { - emit_suggestion( - cx, - binop.span, - replace_right_sugg(cx, binop, &sugg, &mut applicability), - applicability, - ); - return; - } + return; } } } @@ -327,7 +298,7 @@ fn replace_left_sugg( ) -> String { format!( "{left_suggestion} {} {}", - binop.op.to_string(), + binop.op.as_str(), snippet_with_applicability(cx, binop.right.span, "..", applicability), ) } @@ -341,7 +312,7 @@ fn replace_right_sugg( format!( "{} {} {right_suggestion}", snippet_with_applicability(cx, binop.left.span, "..", applicability), - binop.op.to_string(), + binop.op.as_str(), ) } diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index 6271ea0273140..268c0c1b2dfc4 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -2,10 +2,9 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::visitors::for_each_expr; use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS}; use core::ops::ControlFlow; -use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -57,37 +56,39 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if_chain! { - if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind; - if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node); - if let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang); - if let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang); + if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind + && let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node) + && let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang) + && let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang) // Check for more than one binary operation in the implemented function // Linting when multiple operations are involved can result in false positives - let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; - if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get_by_def_id(parent_fn); - if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind; - let body = cx.tcx.hir().body(body_id); - let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; - if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn); - let trait_id = trait_ref.path.res.def_id(); - if ![binop_trait_id, op_assign_trait_id].contains(&trait_id); - if let Some(&(_, lint)) = [ + && let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id + && let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get_by_def_id(parent_fn) + && let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind + && let body = cx.tcx.hir().body(body_id) + && let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id + && let Some(trait_ref) = trait_ref_of_method(cx, parent_fn) + && let trait_id = trait_ref.path.res.def_id() + && ![binop_trait_id, op_assign_trait_id].contains(&trait_id) + && let Some(&(_, lint)) = [ (&BINOP_TRAITS, SUSPICIOUS_ARITHMETIC_IMPL), (&OP_ASSIGN_TRAITS, SUSPICIOUS_OP_ASSIGN_IMPL), ] .iter() - .find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t))); - if count_binops(body.value) == 1; - then { - span_lint( - cx, - lint, - binop.span, - &format!("suspicious use of `{}` in `{}` impl", binop.node.as_str(), cx.tcx.item_name(trait_id)), - ); - } + .find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t))) + && count_binops(body.value) == 1 + { + span_lint( + cx, + lint, + binop.span, + &format!( + "suspicious use of `{}` in `{}` impl", + binop.node.as_str(), + cx.tcx.item_name(trait_id) + ), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs index 4340c23f8303a..1cc27670fa8bf 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index 660e6835e46ab..daa6fe8715ca8 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -3,13 +3,12 @@ use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{can_mut_borrow_both, eq_expr_value, in_constant, std_or_core}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, SyntaxContext}; @@ -149,36 +148,33 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { } for [s1, s2, s3] in block.stmts.array_windows::<3>() { - if_chain! { + if let StmtKind::Local(tmp) = s1.kind // let t = foo(); - if let StmtKind::Local(tmp) = s1.kind; - if let Some(tmp_init) = tmp.init; - if let PatKind::Binding(.., ident, None) = tmp.pat.kind; + && let Some(tmp_init) = tmp.init + && let PatKind::Binding(.., ident, None) = tmp.pat.kind // foo() = bar(); - if let StmtKind::Semi(first) = s2.kind; - if let ExprKind::Assign(lhs1, rhs1, _) = first.kind; + && let StmtKind::Semi(first) = s2.kind + && let ExprKind::Assign(lhs1, rhs1, _) = first.kind // bar() = t; - if let StmtKind::Semi(second) = s3.kind; - if let ExprKind::Assign(lhs2, rhs2, _) = second.kind; - if let ExprKind::Path(QPath::Resolved(None, rhs2)) = rhs2.kind; - if rhs2.segments.len() == 1; + && let StmtKind::Semi(second) = s3.kind + && let ExprKind::Assign(lhs2, rhs2, _) = second.kind + && let ExprKind::Path(QPath::Resolved(None, rhs2)) = rhs2.kind + && rhs2.segments.len() == 1 - if ident.name == rhs2.segments[0].ident.name; - if eq_expr_value(cx, tmp_init, lhs1); - if eq_expr_value(cx, rhs1, lhs2); + && ident.name == rhs2.segments[0].ident.name + && eq_expr_value(cx, tmp_init, lhs1) + && eq_expr_value(cx, rhs1, lhs2) - let ctxt = s1.span.ctxt(); - if s2.span.ctxt() == ctxt; - if s3.span.ctxt() == ctxt; - if first.span.ctxt() == ctxt; - if second.span.ctxt() == ctxt; - - then { - let span = s1.span.to(s3.span); - generate_swap_warning(cx, lhs1, lhs2, span, false); - } + && let ctxt = s1.span.ctxt() + && s2.span.ctxt() == ctxt + && s3.span.ctxt() == ctxt + && first.span.ctxt() == ctxt + && second.span.ctxt() == ctxt + { + let span = s1.span.to(s3.span); + generate_swap_warning(cx, lhs1, lhs2, span, false); } } } @@ -261,20 +257,18 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr< fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) { for [s1, s2, s3] in block.stmts.array_windows::<3>() { let ctxt = s1.span.ctxt(); - if_chain! { - if let Some((lhs0, rhs0)) = extract_sides_of_xor_assign(s1, ctxt); - if let Some((lhs1, rhs1)) = extract_sides_of_xor_assign(s2, ctxt); - if let Some((lhs2, rhs2)) = extract_sides_of_xor_assign(s3, ctxt); - if eq_expr_value(cx, lhs0, rhs1); - if eq_expr_value(cx, lhs2, rhs1); - if eq_expr_value(cx, lhs1, rhs0); - if eq_expr_value(cx, lhs1, rhs2); - if s2.span.ctxt() == ctxt; - if s3.span.ctxt() == ctxt; - then { - let span = s1.span.to(s3.span); - generate_swap_warning(cx, lhs0, rhs0, span, true); - } + if let Some((lhs0, rhs0)) = extract_sides_of_xor_assign(s1, ctxt) + && let Some((lhs1, rhs1)) = extract_sides_of_xor_assign(s2, ctxt) + && let Some((lhs2, rhs2)) = extract_sides_of_xor_assign(s3, ctxt) + && eq_expr_value(cx, lhs0, rhs1) + && eq_expr_value(cx, lhs2, rhs1) + && eq_expr_value(cx, lhs1, rhs0) + && eq_expr_value(cx, lhs1, rhs2) + && s2.span.ctxt() == ctxt + && s3.span.ctxt() == ctxt + { + let span = s1.span.to(s3.span); + generate_swap_warning(cx, lhs0, rhs0, span, true); }; } } diff --git a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs index 6a6c94425d1db..20e9608a15dc8 100644 --- a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span, SyntaxContext}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs index dcf1fac023ac7..af9e13dba36ec 100644 --- a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs +++ b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/temporary_assignment.rs b/src/tools/clippy/clippy_lints/src/temporary_assignment.rs index c717ccc35a6b3..8151dd8f2cfec 100644 --- a/src/tools/clippy/clippy_lints/src/temporary_assignment.rs +++ b/src/tools/clippy/clippy_lints/src/temporary_assignment.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::is_adjusted; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs b/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs index 0cfb1c1253c65..da55758264750 100644 --- a/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs +++ b/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs @@ -3,7 +3,7 @@ use clippy_utils::{is_in_cfg_test, is_in_test_function}; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::Span; @@ -55,20 +55,18 @@ impl LateLintPass<'_> for TestsOutsideTestModule { sp: Span, _: LocalDefId, ) { - if_chain! { - if !matches!(kind, FnKind::Closure); - if is_in_test_function(cx.tcx, body.id().hir_id); - if !is_in_cfg_test(cx.tcx, body.id().hir_id); - then { - span_lint_and_note( - cx, - TESTS_OUTSIDE_TEST_MODULE, - sp, - "this function marked with #[test] is outside a #[cfg(test)] module", - None, - "move it to a testing module marked with #[cfg(test)]", - ); - } + if !matches!(kind, FnKind::Closure) + && is_in_test_function(cx.tcx, body.id().hir_id) + && !is_in_cfg_test(cx.tcx, body.id().hir_id) + { + span_lint_and_note( + cx, + TESTS_OUTSIDE_TEST_MODULE, + sp, + "this function marked with #[test] is outside a #[cfg(test)] module", + None, + "move it to a testing module marked with #[cfg(test)]", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs index a171d225f1e48..dafe9e38818f5 100644 --- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::match_def_path; use clippy_utils::source::snippet_with_applicability; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -38,59 +37,57 @@ declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]); impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if_chain! { - if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind; - if is_some_path.ident.name.as_str() == "is_some"; - then { - let match_result = match &to_digit_expr.kind { - hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => { - if_chain! { - if to_digits_path.ident.name.as_str() == "to_digit"; - let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg); - if *char_arg_ty.kind() == ty::Char; - then { - Some((true, *char_arg, radix_arg)) - } else { - None - } - } + if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind + && is_some_path.ident.name.as_str() == "is_some" + { + let match_result = match &to_digit_expr.kind { + hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => { + if to_digits_path.ident.name.as_str() == "to_digit" + && let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg) + && *char_arg_ty.kind() == ty::Char + { + Some((true, *char_arg, radix_arg)) + } else { + None } - hir::ExprKind::Call(to_digits_call, to_digit_args) => { - if_chain! { - if let [char_arg, radix_arg] = *to_digit_args; - if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind; - if let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id); - if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id(); - if match_def_path(cx, to_digits_def_id, &["core", "char", "methods", "", "to_digit"]); - then { - Some((false, char_arg, radix_arg)) - } else { - None - } - } + }, + hir::ExprKind::Call(to_digits_call, to_digit_args) => { + if let [char_arg, radix_arg] = *to_digit_args + && let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind + && let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id) + && let Some(to_digits_def_id) = to_digits_call_res.opt_def_id() + && match_def_path( + cx, + to_digits_def_id, + &["core", "char", "methods", "", "to_digit"], + ) + { + Some((false, char_arg, radix_arg)) + } else { + None } - _ => None - }; + }, + _ => None, + }; - if let Some((is_method_call, char_arg, radix_arg)) = match_result { - let mut applicability = Applicability::MachineApplicable; - let char_arg_snip = snippet_with_applicability(cx, char_arg.span, "_", &mut applicability); - let radix_snip = snippet_with_applicability(cx, radix_arg.span, "_", &mut applicability); + if let Some((is_method_call, char_arg, radix_arg)) = match_result { + let mut applicability = Applicability::MachineApplicable; + let char_arg_snip = snippet_with_applicability(cx, char_arg.span, "_", &mut applicability); + let radix_snip = snippet_with_applicability(cx, radix_arg.span, "_", &mut applicability); - span_lint_and_sugg( - cx, - TO_DIGIT_IS_SOME, - expr.span, - "use of `.to_digit(..).is_some()`", - "try", - if is_method_call { - format!("{char_arg_snip}.is_digit({radix_snip})") - } else { - format!("char::is_digit({char_arg_snip}, {radix_snip})") - }, - applicability, - ); - } + span_lint_and_sugg( + cx, + TO_DIGIT_IS_SOME, + expr.span, + "use of `.to_digit(..).is_some()`", + "try", + if is_method_call { + format!("{char_arg_snip}.is_digit({radix_snip})") + } else { + format!("char::is_digit({char_arg_snip}, {radix_snip})") + }, + applicability, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 87181adc24b08..cbdf31c933647 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -3,7 +3,7 @@ use clippy_utils::has_repr_attr; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Const; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -54,20 +54,18 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { } fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_>) -> bool { - if_chain! { + if let ItemKind::Struct(data, _) = &item.kind // First check if last field is an array - if let ItemKind::Struct(data, _) = &item.kind; - if let Some(last_field) = data.fields().last(); - if let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind; + && let Some(last_field) = data.fields().last() + && let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind // Then check if that array is zero-sized - let length = Const::from_anon_const(cx.tcx, length.def_id); - let length = length.try_eval_target_usize(cx.tcx, cx.param_env); - if let Some(length) = length; - then { - length == 0 - } else { - false - } + && let length = Const::from_anon_const(cx.tcx, length.def_id) + && let length = length.try_eval_target_usize(cx.tcx, cx.param_env) + && let Some(length) = length + { + length == 0 + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index f065d215e4891..e4054393d0ad7 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash}; use core::hash::{Hash, Hasher}; -use if_chain::if_chain; use itertools::Itertools; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unhash::UnhashMap; @@ -14,7 +13,7 @@ use rustc_hir::{ TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Span}; use std::collections::hash_map::Entry; @@ -124,103 +123,100 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { let mut self_bounds_map = FxHashMap::default(); for predicate in item.generics.predicates { - if_chain! { - if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate; - if bound_predicate.origin != PredicateOrigin::ImplTrait; - if !bound_predicate.span.from_expansion(); - if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind; - if let Some(PathSegment { - res: Res::SelfTyParam { trait_: def_id }, .. - }) = segments.first(); - if let Some( - Node::Item( - Item { - kind: ItemKind::Trait(_, _, _, self_bounds, _), - .. } - ) - ) = cx.tcx.hir().get_if_local(*def_id); - then { - if self_bounds_map.is_empty() { - for bound in *self_bounds { - let Some((self_res, self_segments, _)) = get_trait_info_from_bound(bound) else { continue }; - self_bounds_map.insert(self_res, self_segments); - } + if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate + && bound_predicate.origin != PredicateOrigin::ImplTrait + && !bound_predicate.span.from_expansion() + && let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind + && let Some(PathSegment { + res: Res::SelfTyParam { trait_: def_id }, + .. + }) = segments.first() + && let Some(Node::Item(Item { + kind: ItemKind::Trait(_, _, _, self_bounds, _), + .. + })) = cx.tcx.hir().get_if_local(*def_id) + { + if self_bounds_map.is_empty() { + for bound in *self_bounds { + let Some((self_res, self_segments, _)) = get_trait_info_from_bound(bound) else { + continue; + }; + self_bounds_map.insert(self_res, self_segments); } + } - bound_predicate - .bounds - .iter() - .filter_map(get_trait_info_from_bound) - .for_each(|(trait_item_res, trait_item_segments, span)| { - if let Some(self_segments) = self_bounds_map.get(&trait_item_res) { - if SpanlessEq::new(cx).eq_path_segments(self_segments, trait_item_segments) { - span_lint_and_help( - cx, - TRAIT_DUPLICATION_IN_BOUNDS, - span, - "this trait bound is already specified in trait declaration", - None, - "consider removing this trait bound", - ); - } + bound_predicate + .bounds + .iter() + .filter_map(get_trait_info_from_bound) + .for_each(|(trait_item_res, trait_item_segments, span)| { + if let Some(self_segments) = self_bounds_map.get(&trait_item_res) { + if SpanlessEq::new(cx).eq_path_segments(self_segments, trait_item_segments) { + span_lint_and_help( + cx, + TRAIT_DUPLICATION_IN_BOUNDS, + span, + "this trait bound is already specified in trait declaration", + None, + "consider removing this trait bound", + ); } - }); - } + } + }); } } } fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { - if_chain! { - if let TyKind::Ref(.., mut_ty) = &ty.kind; - if let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind; - if bounds.len() > 2; - then { - - // Build up a hash of every trait we've seen - // When we see a trait for the first time, add it to unique_traits - // so we can later use it to build a string of all traits exactly once, without duplicates + if let TyKind::Ref(.., mut_ty) = &ty.kind + && let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind + && bounds.len() > 2 + { + // Build up a hash of every trait we've seen + // When we see a trait for the first time, add it to unique_traits + // so we can later use it to build a string of all traits exactly once, without duplicates - let mut seen_def_ids = FxHashSet::default(); - let mut unique_traits = Vec::new(); + let mut seen_def_ids = FxHashSet::default(); + let mut unique_traits = Vec::new(); - // Iterate the bounds and add them to our seen hash - // If we haven't yet seen it, add it to the fixed traits - for bound in bounds { - let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; }; + // Iterate the bounds and add them to our seen hash + // If we haven't yet seen it, add it to the fixed traits + for bound in bounds { + let Some(def_id) = bound.trait_ref.trait_def_id() else { + continue; + }; - let new_trait = seen_def_ids.insert(def_id); + let new_trait = seen_def_ids.insert(def_id); - if new_trait { - unique_traits.push(bound); - } + if new_trait { + unique_traits.push(bound); } + } - // If the number of unique traits isn't the same as the number of traits in the bounds, - // there must be 1 or more duplicates - if bounds.len() != unique_traits.len() { - let mut bounds_span = bounds[0].span; - - for bound in bounds.iter().skip(1) { - bounds_span = bounds_span.to(bound.span); - } - - let fixed_trait_snippet = unique_traits - .iter() - .filter_map(|b| snippet_opt(cx, b.span)) - .collect::>() - .join(" + "); + // If the number of unique traits isn't the same as the number of traits in the bounds, + // there must be 1 or more duplicates + if bounds.len() != unique_traits.len() { + let mut bounds_span = bounds[0].span; - span_lint_and_sugg( - cx, - TRAIT_DUPLICATION_IN_BOUNDS, - bounds_span, - "this trait bound is already specified in trait declaration", - "try", - fixed_trait_snippet, - Applicability::MaybeIncorrect, - ); + for bound in bounds.iter().skip(1) { + bounds_span = bounds_span.to(bound.span); } + + let fixed_trait_snippet = unique_traits + .iter() + .filter_map(|b| snippet_opt(cx, b.span)) + .collect::>() + .join(" + "); + + span_lint_and_sugg( + cx, + TRAIT_DUPLICATION_IN_BOUNDS, + bounds_span, + "this trait bound is already specified in trait declaration", + "try", + fixed_trait_snippet, + Applicability::MaybeIncorrect, + ); } } } @@ -267,36 +263,38 @@ impl TraitBounds { let mut map: UnhashMap, Vec<&GenericBound<'_>>> = UnhashMap::default(); let mut applicability = Applicability::MaybeIncorrect; for bound in gen.predicates { - if_chain! { - if let WherePredicate::BoundPredicate(ref p) = bound; - if p.origin != PredicateOrigin::ImplTrait; - if p.bounds.len() as u64 <= self.max_trait_bounds; - if !p.span.from_expansion(); - let bounds = p.bounds.iter().filter(|b| !self.cannot_combine_maybe_bound(cx, b)).collect::>(); - if !bounds.is_empty(); - if let Some(ref v) = map.insert(SpanlessTy { ty: p.bounded_ty, cx }, bounds); - if !is_from_proc_macro(cx, p.bounded_ty); - then { - let trait_bounds = v - .iter() - .copied() - .chain(p.bounds.iter()) - .filter_map(get_trait_info_from_bound) - .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability)) - .join(" + "); - let hint_string = format!( - "consider combining the bounds: `{}: {trait_bounds}`", - snippet(cx, p.bounded_ty.span, "_"), - ); - span_lint_and_help( - cx, - TYPE_REPETITION_IN_BOUNDS, - p.span, - "this type has already been used as a bound predicate", - None, - &hint_string, - ); - } + if let WherePredicate::BoundPredicate(ref p) = bound + && p.origin != PredicateOrigin::ImplTrait + && p.bounds.len() as u64 <= self.max_trait_bounds + && !p.span.from_expansion() + && let bounds = p + .bounds + .iter() + .filter(|b| !self.cannot_combine_maybe_bound(cx, b)) + .collect::>() + && !bounds.is_empty() + && let Some(ref v) = map.insert(SpanlessTy { ty: p.bounded_ty, cx }, bounds) + && !is_from_proc_macro(cx, p.bounded_ty) + { + let trait_bounds = v + .iter() + .copied() + .chain(p.bounds.iter()) + .filter_map(get_trait_info_from_bound) + .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability)) + .join(" + "); + let hint_string = format!( + "consider combining the bounds: `{}: {trait_bounds}`", + snippet(cx, p.bounded_ty.span, "_"), + ); + span_lint_and_help( + cx, + TYPE_REPETITION_IN_BOUNDS, + p.span, + "this type has already been used as a bound predicate", + None, + &hint_string, + ); } } } @@ -318,15 +316,19 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { .predicates .iter() .filter_map(|pred| { - if_chain! { - if pred.in_where_clause(); - if let WherePredicate::BoundPredicate(bound_predicate) = pred; - if let TyKind::Path(QPath::Resolved(_, path)) = bound_predicate.bounded_ty.kind; - then { - return Some( - rollup_traits(cx, bound_predicate.bounds, "these where clauses contain repeated elements") - .into_iter().map(|(trait_ref, _)| (path.res, trait_ref))) - } + if pred.in_where_clause() + && let WherePredicate::BoundPredicate(bound_predicate) = pred + && let TyKind::Path(QPath::Resolved(_, path)) = bound_predicate.bounded_ty.kind + { + return Some( + rollup_traits( + cx, + bound_predicate.bounds, + "these where clauses contain repeated elements", + ) + .into_iter() + .map(|(trait_ref, _)| (path.res, trait_ref)), + ); } None }) @@ -340,25 +342,23 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { // compare trait bounds keyed by generic name and comparable trait to collected where // predicates eg. (T, Clone) for predicate in gen.predicates.iter().filter(|pred| !pred.in_where_clause()) { - if_chain! { - if let WherePredicate::BoundPredicate(bound_predicate) = predicate; - if bound_predicate.origin != PredicateOrigin::ImplTrait; - if !bound_predicate.span.from_expansion(); - if let TyKind::Path(QPath::Resolved(_, path)) = bound_predicate.bounded_ty.kind; - then { - let traits = rollup_traits(cx, bound_predicate.bounds, "these bounds contain repeated elements"); - for (trait_ref, span) in traits { - let key = (path.res, trait_ref); - if where_predicates.contains(&key) { - span_lint_and_help( - cx, - TRAIT_DUPLICATION_IN_BOUNDS, - span, - "this trait bound is already specified in the where clause", - None, - "consider removing this trait bound", - ); - } + if let WherePredicate::BoundPredicate(bound_predicate) = predicate + && bound_predicate.origin != PredicateOrigin::ImplTrait + && !bound_predicate.span.from_expansion() + && let TyKind::Path(QPath::Resolved(_, path)) = bound_predicate.bounded_ty.kind + { + let traits = rollup_traits(cx, bound_predicate.bounds, "these bounds contain repeated elements"); + for (trait_ref, span) in traits { + let key = (path.res, trait_ref); + if where_predicates.contains(&key) { + span_lint_and_help( + cx, + TRAIT_DUPLICATION_IN_BOUNDS, + span, + "this trait bound is already specified in the where clause", + None, + "consider removing this trait bound", + ); } } } @@ -401,10 +401,10 @@ fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef { .filter_map(|segment| { // get trait bound type arguments Some(segment.args?.args.iter().filter_map(|arg| { - if_chain! { - if let GenericArg::Type(ty) = arg; - if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind; - then { return Some(path.res) } + if let GenericArg::Type(ty) = arg + && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind + { + return Some(path.res); } None })) @@ -444,27 +444,24 @@ fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) - comparable_bounds[i] = (k, v); } - if_chain! { - if repeated_res; - if let [first_trait, .., last_trait] = bounds; - then { - let all_trait_span = first_trait.span().to(last_trait.span()); - - let traits = comparable_bounds.iter() - .filter_map(|&(_, span)| snippet_opt(cx, span)) - .collect::>(); - let traits = traits.join(" + "); - - span_lint_and_sugg( - cx, - TRAIT_DUPLICATION_IN_BOUNDS, - all_trait_span, - msg, - "try", - traits, - Applicability::MachineApplicable - ); - } + if repeated_res && let [first_trait, .., last_trait] = bounds { + let all_trait_span = first_trait.span().to(last_trait.span()); + + let traits = comparable_bounds + .iter() + .filter_map(|&(_, span)| snippet_opt(cx, span)) + .collect::>(); + let traits = traits.join(" + "); + + span_lint_and_sugg( + cx, + TRAIT_DUPLICATION_IN_BOUNDS, + all_trait_span, + msg, + "try", + traits, + Applicability::MachineApplicable, + ); } comparable_bounds diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 6eec40cb5295c..95a92afea6681 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -19,10 +19,9 @@ mod wrong_transmute; use clippy_config::msrvs::Msrv; use clippy_utils::in_constant; -use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -494,51 +493,47 @@ impl Transmute { } impl<'tcx> LateLintPass<'tcx> for Transmute { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(path_expr, [arg]) = e.kind; - if let ExprKind::Path(QPath::Resolved(None, path)) = path_expr.kind; - if let Some(def_id) = path.res.opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::transmute, def_id); - then { - // Avoid suggesting non-const operations in const contexts: - // - from/to bits (https://github.com/rust-lang/rust/issues/73736) - // - dereferencing raw pointers (https://github.com/rust-lang/rust/issues/51911) - // - char conversions (https://github.com/rust-lang/rust/issues/89259) - let const_context = in_constant(cx, e.hir_id); + if let ExprKind::Call(path_expr, [arg]) = e.kind + && let ExprKind::Path(QPath::Resolved(None, path)) = path_expr.kind + && let Some(def_id) = path.res.opt_def_id() + && cx.tcx.is_diagnostic_item(sym::transmute, def_id) + { + // Avoid suggesting non-const operations in const contexts: + // - from/to bits (https://github.com/rust-lang/rust/issues/73736) + // - dereferencing raw pointers (https://github.com/rust-lang/rust/issues/51911) + // - char conversions (https://github.com/rust-lang/rust/issues/89259) + let const_context = in_constant(cx, e.hir_id); - let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) { - [] => (cx.typeck_results().expr_ty(arg), false), - [.., a] => (a.target, true), - }; - // Adjustments for `to_ty` happen after the call to `transmute`, so don't use them. - let to_ty = cx.typeck_results().expr_ty(e); + let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) { + [] => (cx.typeck_results().expr_ty(arg), false), + [.., a] => (a.target, true), + }; + // Adjustments for `to_ty` happen after the call to `transmute`, so don't use them. + let to_ty = cx.typeck_results().expr_ty(e); - // If useless_transmute is triggered, the other lints can be skipped. - if useless_transmute::check(cx, e, from_ty, to_ty, arg) { - return; - } + // If useless_transmute is triggered, the other lints can be skipped. + if useless_transmute::check(cx, e, from_ty, to_ty, arg) { + return; + } - let linted = wrong_transmute::check(cx, e, from_ty, to_ty) - | crosspointer_transmute::check(cx, e, from_ty, to_ty) - | transmuting_null::check(cx, e, arg, to_ty) - | transmute_null_to_fn::check(cx, e, arg, to_ty) - | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv) - | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) - | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) - | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg) - | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) - | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context) - | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg) - | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context) - | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context) - | ( - unsound_collection_transmute::check(cx, e, from_ty, to_ty) - || transmute_undefined_repr::check(cx, e, from_ty, to_ty) - ); + let linted = wrong_transmute::check(cx, e, from_ty, to_ty) + | crosspointer_transmute::check(cx, e, from_ty, to_ty) + | transmuting_null::check(cx, e, arg, to_ty) + | transmute_null_to_fn::check(cx, e, arg, to_ty) + | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv) + | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg) + | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) + | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg) + | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context) + | (unsound_collection_transmute::check(cx, e, from_ty, to_ty) + || transmute_undefined_repr::check(cx, e, from_ty, to_ty)); - if !linted { - transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg); - } + if !linted { + transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg); } } } diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs index 5ecba512b0fd6..aef520923e477 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -1,7 +1,6 @@ use super::TRANSMUTE_FLOAT_TO_INT; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg; -use if_chain::if_chain; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, UnOp}; @@ -32,17 +31,15 @@ pub(super) fn check<'tcx>( arg = inner_expr; } - if_chain! { + if let ExprKind::Lit(lit) = &arg.kind // if the expression is a float literal and it is unsuffixed then // add a suffix so the suggestion is valid and unambiguous - if let ExprKind::Lit(lit) = &arg.kind; - if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node; - then { - let op = format!("{sugg}{}", float_ty.name_str()).into(); - match sugg { - sugg::Sugg::MaybeParen(_) => sugg = sugg::Sugg::MaybeParen(op), - _ => sugg = sugg::Sugg::NonParen(op) - } + && let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node + { + let op = format!("{sugg}{}", float_ty.name_str()).into(); + match sugg { + sugg::Sugg::MaybeParen(_) => sugg = sugg::Sugg::MaybeParen(op), + _ => sugg = sugg::Sugg::NonParen(op), } } diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs index ea9ad99618abc..98e9ea2d7751f 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs @@ -2,7 +2,6 @@ use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet; use clippy_utils::sugg; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; @@ -21,68 +20,59 @@ pub(super) fn check<'tcx>( let mut triggered = false; if let (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) = (&from_ty.kind(), &to_ty.kind()) { - if_chain! { - if let ty::Slice(slice_ty) = *ty_from.kind(); - if ty_to.is_str(); - if let ty::Uint(ty::UintTy::U8) = slice_ty.kind(); - if from_mutbl == to_mutbl; - then { - let postfix = if *from_mutbl == Mutability::Mut { - "_mut" - } else { - "" - }; + if let ty::Slice(slice_ty) = *ty_from.kind() + && ty_to.is_str() + && let ty::Uint(ty::UintTy::U8) = slice_ty.kind() + && from_mutbl == to_mutbl + { + let postfix = if *from_mutbl == Mutability::Mut { "_mut" } else { "" }; - let snippet = snippet(cx, arg.span, ".."); + let snippet = snippet(cx, arg.span, ".."); - span_lint_and_sugg( - cx, - TRANSMUTE_BYTES_TO_STR, - e.span, - &format!("transmute from a `{from_ty}` to a `{to_ty}`"), - "consider using", - if const_context { - format!("std::str::from_utf8_unchecked{postfix}({snippet})") - } else { - format!("std::str::from_utf8{postfix}({snippet}).unwrap()") - }, - Applicability::MaybeIncorrect, - ); - triggered = true; - } else { - if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty)) - && !const_context { - span_lint_and_then( - cx, - TRANSMUTE_PTR_TO_PTR, - e.span, - "transmute from a reference to a reference", - |diag| if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - let ty_from_and_mut = ty::TypeAndMut { - ty: *ty_from, - mutbl: *from_mutbl - }; - let ty_to_and_mut = ty::TypeAndMut { ty: *ty_to, mutbl: *to_mutbl }; - let sugg_paren = arg - .as_ty(Ty::new_ptr(cx.tcx,ty_from_and_mut)) - .as_ty(Ty::new_ptr(cx.tcx,ty_to_and_mut)); - let sugg = if *to_mutbl == Mutability::Mut { - sugg_paren.mut_addr_deref() - } else { - sugg_paren.addr_deref() - }; - diag.span_suggestion( - e.span, - "try", - sugg, - Applicability::Unspecified, - ); - }, - ); + span_lint_and_sugg( + cx, + TRANSMUTE_BYTES_TO_STR, + e.span, + &format!("transmute from a `{from_ty}` to a `{to_ty}`"), + "consider using", + if const_context { + format!("std::str::from_utf8_unchecked{postfix}({snippet})") + } else { + format!("std::str::from_utf8{postfix}({snippet}).unwrap()") + }, + Applicability::MaybeIncorrect, + ); + triggered = true; + } else if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty)) && !const_context { + span_lint_and_then( + cx, + TRANSMUTE_PTR_TO_PTR, + e.span, + "transmute from a reference to a reference", + |diag| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { + let ty_from_and_mut = ty::TypeAndMut { + ty: *ty_from, + mutbl: *from_mutbl, + }; + let ty_to_and_mut = ty::TypeAndMut { + ty: *ty_to, + mutbl: *to_mutbl, + }; + let sugg_paren = arg + .as_ty(Ty::new_ptr(cx.tcx, ty_from_and_mut)) + .as_ty(Ty::new_ptr(cx.tcx, ty_to_and_mut)); + let sugg = if *to_mutbl == Mutability::Mut { + sugg_paren.mut_addr_deref() + } else { + sugg_paren.addr_deref() + }; + diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); + } + }, + ); - triggered = true; - } - } + triggered = true; } } diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 7c2223ca3ab71..a65bc0ce458b4 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -299,14 +299,12 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> } fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - if_chain! { - if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty); - if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)); - then { - layout.layout.size().bytes() == 0 - } else { - false - } + if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) + && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) + { + layout.layout.size().bytes() == 0 + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs index 642e39e8270ec..e1cd82e18d56d 100644 --- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs @@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use std::iter::once; use std::ops::ControlFlow; diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index 306ca5724da1f..801e886261993 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind, @@ -15,66 +14,64 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m TyKind::Path(ref qpath) => { let hir_id = mut_ty.ty.hir_id; let def = cx.qpath_res(qpath, hir_id); - if_chain! { - if let Some(def_id) = def.opt_def_id(); - if Some(def_id) == cx.tcx.lang_items().owned_box(); - if let QPath::Resolved(None, path) = *qpath; - if let [ref bx] = *path.segments; - if let Some(params) = bx.args; - if params.parenthesized == hir::GenericArgsParentheses::No; - if let Some(inner) = params.args.iter().find_map(|arg| match arg { + if let Some(def_id) = def.opt_def_id() + && Some(def_id) == cx.tcx.lang_items().owned_box() + && let QPath::Resolved(None, path) = *qpath + && let [ref bx] = *path.segments + && let Some(params) = bx.args + && params.parenthesized == hir::GenericArgsParentheses::No + && let Some(inner) = params.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), _ => None, - }); - then { - if is_any_trait(cx, inner) { - // Ignore `Box` types; see issue #1884 for details. - return false; - } - - let ltopt = if lt.is_anonymous() { - String::new() - } else { - format!("{} ", lt.ident.as_str()) - }; + }) + { + if is_any_trait(cx, inner) { + // Ignore `Box` types; see issue #1884 for details. + return false; + } - if mut_ty.mutbl == Mutability::Mut { - // Ignore `&mut Box` types; see issue #2907 for - // details. - return false; - } + let ltopt = if lt.is_anonymous() { + String::new() + } else { + format!("{} ", lt.ident.as_str()) + }; - // When trait objects or opaque types have lifetime or auto-trait bounds, - // we need to add parentheses to avoid a syntax error due to its ambiguity. - // Originally reported as the issue #3128. - let inner_snippet = snippet(cx, inner.span, ".."); - let suggestion = match &inner.kind { - TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => { - format!("&{ltopt}({})", &inner_snippet) - }, - TyKind::Path(qpath) - if get_bounds_if_impl_trait(cx, qpath, inner.hir_id) - .map_or(false, |bounds| bounds.len() > 1) => - { - format!("&{ltopt}({})", &inner_snippet) - }, - _ => format!("&{ltopt}{}", &inner_snippet), - }; - span_lint_and_sugg( - cx, - BORROWED_BOX, - hir_ty.span, - "you seem to be trying to use `&Box`. Consider using just `&T`", - "try", - suggestion, - // To make this `MachineApplicable`, at least one needs to check if it isn't a trait item - // because the trait impls of it will break otherwise; - // and there may be other cases that result in invalid code. - // For example, type coercion doesn't work nicely. - Applicability::Unspecified, - ); - return true; + if mut_ty.mutbl == Mutability::Mut { + // Ignore `&mut Box` types; see issue #2907 for + // details. + return false; } + + // When trait objects or opaque types have lifetime or auto-trait bounds, + // we need to add parentheses to avoid a syntax error due to its ambiguity. + // Originally reported as the issue #3128. + let inner_snippet = snippet(cx, inner.span, ".."); + let suggestion = match &inner.kind { + TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => { + format!("&{ltopt}({})", &inner_snippet) + }, + TyKind::Path(qpath) + if get_bounds_if_impl_trait(cx, qpath, inner.hir_id) + .map_or(false, |bounds| bounds.len() > 1) => + { + format!("&{ltopt}({})", &inner_snippet) + }, + _ => format!("&{ltopt}{}", &inner_snippet), + }; + span_lint_and_sugg( + cx, + BORROWED_BOX, + hir_ty.span, + "you seem to be trying to use `&Box`. Consider using just `&T`", + "try", + suggestion, + // To make this `MachineApplicable`, at least one needs to check if it isn't a trait item + // because the trait impls of it will break otherwise; + // and there may be other cases that result in invalid code. + // For example, type coercion doesn't work nicely. + Applicability::Unspecified, + ); + return true; }; false }, @@ -84,33 +81,29 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m // Returns true if given type is `Any` trait. fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool { - if_chain! { - if let TyKind::TraitObject(traits, ..) = t.kind; - if !traits.is_empty(); - if let Some(trait_did) = traits[0].trait_ref.trait_def_id(); + if let TyKind::TraitObject(traits, ..) = t.kind + && !traits.is_empty() + && let Some(trait_did) = traits[0].trait_ref.trait_def_id() // Only Send/Sync can be used as additional traits, so it is enough to // check only the first trait. - if cx.tcx.is_diagnostic_item(sym::Any, trait_did); - then { - return true; - } + && cx.tcx.is_diagnostic_item(sym::Any, trait_did) + { + return true; } false } fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option> { - if_chain! { - if let Some(did) = cx.qpath_res(qpath, id).opt_def_id(); - if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did); - if let GenericParamKind::Type { synthetic, .. } = generic_param.kind; - if synthetic; - if let Some(generics) = cx.tcx.hir().get_generics(id.owner.def_id); - if let Some(pred) = generics.bounds_for_param(did.expect_local()).next(); - then { - Some(pred.bounds) - } else { - None - } + if let Some(did) = cx.qpath_res(qpath, id).opt_def_id() + && let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did) + && let GenericParamKind::Type { synthetic, .. } = generic_param.kind + && synthetic + && let Some(generics) = cx.tcx.hir().get_generics(id.owner.def_id) + && let Some(pred) = generics.bounds_for_param(did.expect_local()).next() + { + Some(pred.bounds) + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/types/box_collection.rs b/src/tools/clippy/clippy_lints/src/types/box_collection.rs index 4a5a94f26302e..fc3420af02082 100644 --- a/src/tools/clippy/clippy_lints/src/types/box_collection.rs +++ b/src/tools/clippy/clippy_lints/src/types/box_collection.rs @@ -8,30 +8,26 @@ use rustc_span::{sym, Symbol}; use super::BOX_COLLECTION; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { - if_chain! { - if Some(def_id) == cx.tcx.lang_items().owned_box(); - if let Some(item_type) = get_std_collection(cx, qpath); - then { - let generic = match item_type { - sym::String => "", - _ => "<..>", - }; + if Some(def_id) == cx.tcx.lang_items().owned_box() + && let Some(item_type) = get_std_collection(cx, qpath) + { + let generic = match item_type { + sym::String => "", + _ => "<..>", + }; - let box_content = format!("{item_type}{generic}"); - span_lint_and_help( - cx, - BOX_COLLECTION, - hir_ty.span, - &format!( - "you seem to be trying to use `Box<{box_content}>`. Consider using just `{box_content}`"), - None, - &format!( - "`{box_content}` is already on the heap, `Box<{box_content}>` makes an extra allocation") - ); - true - } else { - false - } + let box_content = format!("{item_type}{generic}"); + span_lint_and_help( + cx, + BOX_COLLECTION, + hir_ty.span, + &format!("you seem to be trying to use `Box<{box_content}>`. Consider using just `{box_content}`"), + None, + &format!("`{box_content}` is already on the heap, `Box<{box_content}>` makes an extra allocation"), + ); + true + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 6a6160c4983dd..8e890b4df8894 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -16,7 +16,7 @@ use rustc_hir::{ TraitItemKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::Span; @@ -324,7 +324,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id( cx.tcx .hir() - .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(def_id)) + .get_parent_item(cx.tcx.local_def_id_to_hir_id(def_id)) .def_id, ) { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) @@ -490,7 +490,7 @@ impl Types { // All lints that are being checked in this block are guarded by // the `avoid_breaking_exported_api` configuration. When adding a // new lint, please also add the name to the configuration documentation - // in `clippy_lints::utils::conf.rs` + // in `clippy_config::conf` let mut triggered = false; triggered |= box_collection::check(cx, hir_ty, qpath, def_id); diff --git a/src/tools/clippy/clippy_lints/src/types/option_option.rs b/src/tools/clippy/clippy_lints/src/types/option_option.rs index 60622903af1d6..d12d14f2b1413 100644 --- a/src/tools/clippy/clippy_lints/src/types/option_option.rs +++ b/src/tools/clippy/clippy_lints/src/types/option_option.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::{path_def_id, qpath_generic_tys}; -use if_chain::if_chain; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, QPath}; use rustc_lint::LateContext; @@ -9,21 +8,19 @@ use rustc_span::symbol::sym; use super::OPTION_OPTION; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { - if_chain! { - if cx.tcx.is_diagnostic_item(sym::Option, def_id); - if let Some(arg) = qpath_generic_tys(qpath).next(); - if path_def_id(cx, arg) == Some(def_id); - then { - span_lint( - cx, - OPTION_OPTION, - hir_ty.span, - "consider using `Option` instead of `Option>` or a custom \ - enum if you need to distinguish all 3 cases", - ); - true - } else { - false - } + if cx.tcx.is_diagnostic_item(sym::Option, def_id) + && let Some(arg) = qpath_generic_tys(qpath).next() + && path_def_id(cx, arg) == Some(def_id) + { + span_lint( + cx, + OPTION_OPTION, + hir_ty.span, + "consider using `Option` instead of `Option>` or a custom \ + enum if you need to distinguish all 3 cases", + ); + true + } else { + false } } diff --git a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs index a616c3e4ea831..afc319217042f 100644 --- a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{path_def_id, qpath_generic_tys}; -use if_chain::if_chain; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, QPath}; use rustc_lint::LateContext; @@ -9,22 +8,20 @@ use rustc_span::symbol::sym; use super::RC_MUTEX; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { - if_chain! { - if cx.tcx.is_diagnostic_item(sym::Rc, def_id) ; - if let Some(arg) = qpath_generic_tys(qpath).next(); - if let Some(id) = path_def_id(cx, arg); - if cx.tcx.is_diagnostic_item(sym::Mutex, id); - then { - span_lint_and_help( - cx, - RC_MUTEX, - hir_ty.span, - "usage of `Rc>`", - None, - "consider using `Rc>` or `Arc>` instead", - ); - return true; - } + if cx.tcx.is_diagnostic_item(sym::Rc, def_id) + && let Some(arg) = qpath_generic_tys(qpath).next() + && let Some(id) = path_def_id(cx, arg) + && cx.tcx.is_diagnostic_item(sym::Mutex, id) + { + span_lint_and_help( + cx, + RC_MUTEX, + hir_ty.span, + "usage of `Rc>`", + None, + "consider using `Rc>` or `Arc>` instead", + ); + return true; } false diff --git a/src/tools/clippy/clippy_lints/src/types/utils.rs b/src/tools/clippy/clippy_lints/src/types/utils.rs index 39469841bd404..0bca56b8da78a 100644 --- a/src/tools/clippy/clippy_lints/src/types/utils.rs +++ b/src/tools/clippy/clippy_lints/src/types/utils.rs @@ -1,22 +1,19 @@ use clippy_utils::last_path_segment; -use if_chain::if_chain; use rustc_hir::{GenericArg, GenericArgsParentheses, QPath, TyKind}; use rustc_lint::LateContext; use rustc_span::Span; pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option { let last = last_path_segment(qpath); - if_chain! { - if let Some(params) = last.args; - if params.parenthesized == GenericArgsParentheses::No; - if let Some(ty) = params.args.iter().find_map(|arg| match arg { + if let Some(params) = last.args + && params.parenthesized == GenericArgsParentheses::No + && let Some(ty) = params.args.iter().find_map(|arg| match arg { GenericArg::Type(ty) => Some(ty), _ => None, - }); - if let TyKind::Ref(..) = ty.kind; - then { - return Some(ty.span); - } + }) + && let TyKind::Ref(..) = ty.kind + { + return Some(ty.span); } None } diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index decc183ad9613..9d5066199bde5 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::last_path_segment; +use clippy_utils::paths::ALLOCATOR_GLOBAL; use clippy_utils::source::snippet; -use if_chain::if_chain; +use clippy_utils::{last_path_segment, match_def_path}; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, GenericArg, QPath, TyKind}; @@ -21,43 +21,57 @@ pub(super) fn check( box_size_threshold: u64, ) -> bool { if cx.tcx.is_diagnostic_item(sym::Vec, def_id) { - if_chain! { + if let Some(last) = last_path_segment(qpath).args // Get the _ part of Vec<_> - if let Some(last) = last_path_segment(qpath).args; - if let Some(ty) = last.args.iter().find_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }); + && let Some(GenericArg::Type(ty)) = last.args.first() + // extract allocator from the Vec for later + && let vec_alloc_ty = last.args.get(1) // ty is now _ at this point - if let TyKind::Path(ref ty_qpath) = ty.kind; - let res = cx.qpath_res(ty_qpath, ty.hir_id); - if let Some(def_id) = res.opt_def_id(); - if Some(def_id) == cx.tcx.lang_items().owned_box(); + && let TyKind::Path(ref ty_qpath) = ty.kind + && let res = cx.qpath_res(ty_qpath, ty.hir_id) + && let Some(def_id) = res.opt_def_id() + && Some(def_id) == cx.tcx.lang_items().owned_box() // At this point, we know ty is Box, now get T - if let Some(last) = last_path_segment(ty_qpath).args; - if let Some(boxed_ty) = last.args.iter().find_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }); - let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty); - if !ty_ty.has_escaping_bound_vars(); - if ty_ty.is_sized(cx.tcx, cx.param_env); - if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()); - if ty_ty_size < box_size_threshold; - then { - span_lint_and_sugg( - cx, - VEC_BOX, - hir_ty.span, - "`Vec` is already on the heap, the boxing is unnecessary", - "try", - format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")), - Applicability::MachineApplicable, - ); - true - } else { - false + && let Some(last) = last_path_segment(ty_qpath).args + && let Some(GenericArg::Type(boxed_ty)) = last.args.first() + // extract allocator from the Box for later + && let boxed_alloc_ty = last.args.get(1) + && let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty) + && !ty_ty.has_escaping_bound_vars() + && ty_ty.is_sized(cx.tcx, cx.param_env) + && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()) + && ty_ty_size < box_size_threshold + // https://github.com/rust-lang/rust-clippy/issues/7114 + && match (vec_alloc_ty, boxed_alloc_ty) { + (None, None) => true, + // this is in the event that we have something like + // Vec<_, Global>, in which case is equivalent to + // Vec<_> + (None, Some(GenericArg::Type(inner))) | (Some(GenericArg::Type(inner)), None) => { + if let TyKind::Path(path) = inner.kind + && let Some(did) = cx.qpath_res(&path, inner.hir_id).opt_def_id() { + match_def_path(cx, did, &ALLOCATOR_GLOBAL) + } else { + false + } + }, + (Some(GenericArg::Type(l)), Some(GenericArg::Type(r))) => + hir_ty_to_ty(cx.tcx, l) == hir_ty_to_ty(cx.tcx, r), + _ => false } + { + span_lint_and_sugg( + cx, + VEC_BOX, + hir_ty.span, + "`Vec` is already on the heap, the boxing is unnecessary", + "try", + format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")), + Applicability::Unspecified, + ); + true + } else { + false } } else { false diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 32aebdd8c0f7b..7a6549a7c54a6 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -11,7 +11,7 @@ use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource}; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, RelativeBytePos, Span, SyntaxContext}; declare_clippy_lint! { @@ -349,7 +349,7 @@ fn block_parents_have_safety_comment( span, owner_id, .. - })) => (*span, cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id)), + })) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)), _ => { if is_branchy(expr) { return false; @@ -370,7 +370,7 @@ fn block_parents_have_safety_comment( span, owner_id, .. - }) => (*span, cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id)), + }) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)), _ => return false, }; // if unsafe block is part of a let/const/static statement, diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs index b824deac2c8b5..3d319b9fe767a 100644 --- a/src/tools/clippy/clippy_lints/src/unicode.rs +++ b/src/tools/clippy/clippy_lints/src/unicode.rs @@ -6,7 +6,7 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; use unicode_normalization::UnicodeNormalization; diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs index 72569e10f0581..fc8519d562835 100644 --- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs +++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs @@ -6,7 +6,7 @@ use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKi use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span}; // TODO: add `ReadBuf` (RFC 2930) in "How to fix" once it is available in std @@ -83,41 +83,39 @@ fn handle_uninit_vec_pair<'tcx>( maybe_init_or_reserve: &'tcx Stmt<'tcx>, maybe_set_len: &'tcx Expr<'tcx>, ) { - if_chain! { - if let Some(vec) = extract_init_or_reserve_target(cx, maybe_init_or_reserve); - if let Some((set_len_self, call_span)) = extract_set_len_self(cx, maybe_set_len); - if vec.location.eq_expr(cx, set_len_self); - if let ty::Ref(_, vec_ty, _) = cx.typeck_results().expr_ty_adjusted(set_len_self).kind(); - if let ty::Adt(_, args) = vec_ty.kind(); + if let Some(vec) = extract_init_or_reserve_target(cx, maybe_init_or_reserve) + && let Some((set_len_self, call_span)) = extract_set_len_self(cx, maybe_set_len) + && vec.location.eq_expr(cx, set_len_self) + && let ty::Ref(_, vec_ty, _) = cx.typeck_results().expr_ty_adjusted(set_len_self).kind() + && let ty::Adt(_, args) = vec_ty.kind() // `#[allow(...)]` attribute can be set on enclosing unsafe block of `set_len()` - if !is_lint_allowed(cx, UNINIT_VEC, maybe_set_len.hir_id); - then { - if vec.has_capacity() { - // with_capacity / reserve -> set_len + && !is_lint_allowed(cx, UNINIT_VEC, maybe_set_len.hir_id) + { + if vec.has_capacity() { + // with_capacity / reserve -> set_len - // Check T of Vec - if !is_uninit_value_valid_for_ty(cx, args.type_at(0)) { - // FIXME: #7698, false positive of the internal lints - #[expect(clippy::collapsible_span_lint_calls)] - span_lint_and_then( - cx, - UNINIT_VEC, - vec![call_span, maybe_init_or_reserve.span], - "calling `set_len()` immediately after reserving a buffer creates uninitialized values", - |diag| { - diag.help("initialize the buffer or wrap the content in `MaybeUninit`"); - }, - ); - } - } else { - // new / default -> set_len - span_lint( + // Check T of Vec + if !is_uninit_value_valid_for_ty(cx, args.type_at(0)) { + // FIXME: #7698, false positive of the internal lints + #[expect(clippy::collapsible_span_lint_calls)] + span_lint_and_then( cx, UNINIT_VEC, vec![call_span, maybe_init_or_reserve.span], - "calling `set_len()` on empty `Vec` creates out-of-bound values", + "calling `set_len()` immediately after reserving a buffer creates uninitialized values", + |diag| { + diag.help("initialize the buffer or wrap the content in `MaybeUninit`"); + }, ); } + } else { + // new / default -> set_len + span_lint( + cx, + UNINIT_VEC, + vec![call_span, maybe_init_or_reserve.span], + "calling `set_len()` on empty `Vec` creates out-of-bound values", + ); } } } @@ -156,16 +154,14 @@ impl<'tcx> VecLocation<'tcx> { fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> Option> { match stmt.kind { StmtKind::Local(local) => { - if_chain! { - if let Some(init_expr) = local.init; - if let PatKind::Binding(_, hir_id, _, None) = local.pat.kind; - if let Some(init_kind) = get_vec_init_kind(cx, init_expr); - then { - return Some(TargetVec { - location: VecLocation::Local(hir_id), - init_kind: Some(init_kind), - }) - } + if let Some(init_expr) = local.init + && let PatKind::Binding(_, hir_id, _, None) = local.pat.kind + && let Some(init_kind) = get_vec_init_kind(cx, init_expr) + { + return Some(TargetVec { + location: VecLocation::Local(hir_id), + init_kind: Some(init_kind), + }); } }, StmtKind::Expr(expr) | StmtKind::Semi(expr) => match expr.kind { diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index e76cc65fd46a2..729972de6e6f3 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; -use if_chain::if_chain; use rustc_hir::def_id::DefId; use rustc_hir::{Closure, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, BytePos, Span}; declare_clippy_lint! { @@ -44,14 +43,14 @@ fn get_trait_predicates_for_trait_id<'tcx>( ) -> Vec> { let mut preds = Vec::new(); for (pred, _) in generics.predicates { - if_chain! { - if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder(); - let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred)); - if let Some(trait_def_id) = trait_id; - if trait_def_id == trait_pred.trait_ref.def_id; - then { - preds.push(trait_pred); - } + if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder() + && let trait_pred = cx + .tcx + .instantiate_bound_regions_with_erased(pred.kind().rebind(poly_trait_pred)) + && let Some(trait_def_id) = trait_id + && trait_def_id == trait_pred.trait_ref.def_id + { + preds.push(trait_pred); } } preds @@ -64,7 +63,9 @@ fn get_projection_pred<'tcx>( ) -> Option> { generics.predicates.iter().find_map(|(proj_pred, _)| { if let ClauseKind::Projection(pred) = proj_pred.kind().skip_binder() { - let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred)); + let projection_pred = cx + .tcx + .instantiate_bound_regions_with_erased(proj_pred.kind().rebind(pred)); if projection_pred.projection_ty.args == trait_pred.trait_ref.args { return Some(projection_pred); } @@ -82,10 +83,10 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve let ord_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.get_diagnostic_item(sym::Ord)); let partial_ord_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().partial_ord_trait()); - // Trying to call erase_late_bound_regions on fn_sig.inputs() gives the following error + // Trying to call instantiate_bound_regions_with_erased on fn_sig.inputs() gives the following error // The trait `rustc::ty::TypeFoldable<'_>` is not implemented for // `&[rustc_middle::ty::Ty<'_>]` - let inputs_output = cx.tcx.erase_late_bound_regions(fn_sig.inputs_and_output()); + let inputs_output = cx.tcx.instantiate_bound_regions_with_erased(fn_sig.inputs_and_output()); inputs_output .iter() .rev() @@ -94,21 +95,19 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve .enumerate() .for_each(|(i, inp)| { for trait_pred in &fn_mut_preds { - if_chain! { - if trait_pred.self_ty() == inp; - if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred); - then { - if ord_preds - .iter() - .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty()) - { - args_to_check.push((i, "Ord".to_string())); - } else if partial_ord_preds - .iter() - .any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap()) - { - args_to_check.push((i, "PartialOrd".to_string())); - } + if trait_pred.self_ty() == inp + && let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred) + { + if ord_preds + .iter() + .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty()) + { + args_to_check.push((i, "Ord".to_string())); + } else if partial_ord_preds + .iter() + .any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap()) + { + args_to_check.push((i, "PartialOrd".to_string())); } } } @@ -118,30 +117,26 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve } fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Span, Option)> { - if_chain! { - if let ExprKind::Closure(&Closure { body, fn_decl_span, .. }) = arg.kind; - if let ty::Closure(_def_id, args) = &cx.typeck_results().node_type(arg.hir_id).kind(); - let ret_ty = args.as_closure().sig().output(); - let ty = cx.tcx.erase_late_bound_regions(ret_ty); - if ty.is_unit(); - then { - let body = cx.tcx.hir().body(body); - if_chain! { - if let ExprKind::Block(block, _) = body.value.kind; - if block.expr.is_none(); - if let Some(stmt) = block.stmts.last(); - if let StmtKind::Semi(_) = stmt.kind; - then { - let data = stmt.span.data(); - // Make a span out of the semicolon for the help message - Some((fn_decl_span, Some(data.with_lo(data.hi-BytePos(1))))) - } else { - Some((fn_decl_span, None)) - } - } + if let ExprKind::Closure(&Closure { body, fn_decl_span, .. }) = arg.kind + && let ty::Closure(_def_id, args) = &cx.typeck_results().node_type(arg.hir_id).kind() + && let ret_ty = args.as_closure().sig().output() + && let ty = cx.tcx.instantiate_bound_regions_with_erased(ret_ty) + && ty.is_unit() + { + let body = cx.tcx.hir().body(body); + if let ExprKind::Block(block, _) = body.value.kind + && block.expr.is_none() + && let Some(stmt) = block.stmts.last() + && let StmtKind::Semi(_) = stmt.kind + { + let data = stmt.span.data(); + // Make a span out of the semicolon for the help message + Some((fn_decl_span, Some(data.with_lo(data.hi - BytePos(1))))) } else { - None + Some((fn_decl_span, None)) } + } else { + None } } diff --git a/src/tools/clippy/clippy_lints/src/unit_types/mod.rs b/src/tools/clippy/clippy_lints/src/unit_types/mod.rs index 884c6ca4d313a..0abd48e6423bb 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/mod.rs @@ -5,7 +5,7 @@ mod utils; use rustc_hir::{Expr, Local}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs index 462b1aa8153e7..44cff78a7936d 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{self as hir, Block, Expr, ExprKind, MatchSource, Node, StmtKind}; use rustc_lint::LateContext; @@ -22,12 +21,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { } let map = &cx.tcx.hir(); let opt_parent_node = map.find_parent(expr.hir_id); - if_chain! { - if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; - if is_questionmark_desugar_marked_call(parent_expr); - then { - return; - } + if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node + && is_questionmark_desugar_marked_call(parent_expr) + { + return; } let args: Vec<_> = match expr.kind { @@ -80,21 +77,15 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp args_to_recover .iter() .filter_map(|arg| { - if_chain! { - if let ExprKind::Block(block, _) = arg.kind; - if block.expr.is_none(); - if let Some(last_stmt) = block.stmts.iter().last(); - if let StmtKind::Semi(last_expr) = last_stmt.kind; - if let Some(snip) = snippet_opt(cx, last_expr.span); - then { - Some(( - last_stmt.span, - snip, - )) - } - else { - None - } + if let ExprKind::Block(block, _) = arg.kind + && block.expr.is_none() + && let Some(last_stmt) = block.stmts.iter().last() + && let StmtKind::Semi(last_expr) = last_stmt.kind + && let Some(snip) = snippet_opt(cx, last_expr.span) + { + Some((last_stmt.span, snip)) + } else { + None } }) .for_each(|(span, sugg)| { diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs index e7355f92304da..41e13e13e56c0 100644 --- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs +++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; -use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -76,55 +75,50 @@ impl LateLintPass<'_> for UnnamedAddress { matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..)) } - if_chain! { - if let ExprKind::Binary(binop, left, right) = expr.kind; - if is_comparison(binop.node); - if is_trait_ptr(cx, left) && is_trait_ptr(cx, right); - then { - span_lint_and_help( - cx, - VTABLE_ADDRESS_COMPARISONS, - expr.span, - "comparing trait object pointers compares a non-unique vtable address", - None, - "consider extracting and comparing data pointers only", - ); - } + if let ExprKind::Binary(binop, left, right) = expr.kind + && is_comparison(binop.node) + && is_trait_ptr(cx, left) + && is_trait_ptr(cx, right) + { + span_lint_and_help( + cx, + VTABLE_ADDRESS_COMPARISONS, + expr.span, + "comparing trait object pointers compares a non-unique vtable address", + None, + "consider extracting and comparing data pointers only", + ); } - if_chain! { - if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind; - if let ExprKind::Path(ref func_qpath) = func.kind; - if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::ptr_eq, def_id); - let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0); - if ty_param.is_trait(); - then { - span_lint_and_help( - cx, - VTABLE_ADDRESS_COMPARISONS, - expr.span, - "comparing trait object pointers compares a non-unique vtable address", - None, - "consider extracting and comparing data pointers only", - ); - } + if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind + && let ExprKind::Path(ref func_qpath) = func.kind + && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::ptr_eq, def_id) + && let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0) + && ty_param.is_trait() + { + span_lint_and_help( + cx, + VTABLE_ADDRESS_COMPARISONS, + expr.span, + "comparing trait object pointers compares a non-unique vtable address", + None, + "consider extracting and comparing data pointers only", + ); } - if_chain! { - if let ExprKind::Binary(binop, left, right) = expr.kind; - if is_comparison(binop.node); - if cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr(); - if cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr(); - if is_fn_def(cx, left) || is_fn_def(cx, right); - then { - span_lint( - cx, - FN_ADDRESS_COMPARISONS, - expr.span, - "comparing with a non-unique address of a function item", - ); - } + if let ExprKind::Binary(binop, left, right) = expr.kind + && is_comparison(binop.node) + && cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr() + && cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr() + && (is_fn_def(cx, left) || is_fn_def(cx, right)) + { + span_lint( + cx, + FN_ADDRESS_COMPARISONS, + expr.span, + "comparing with a non-unique address of a function item", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs index ca159eb4d5fd0..f5af540fa1486 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_hir::def_id::LocalDefId; use rustc_hir::{FnDecl, FnRetTy, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Symbol; declare_clippy_lint! { @@ -71,7 +71,7 @@ impl UnnecessaryBoxReturns { let return_ty = cx .tcx - .erase_late_bound_regions(cx.tcx.fn_sig(def_id).skip_binder()) + .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder()) .output(); if !return_ty.is_box() { diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs b/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs index 9107b2b99b88e..9979e02297e92 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_map_on_constructor.rs @@ -4,26 +4,29 @@ use clippy_utils::ty::get_type_diagnostic_name; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { /// ### What it does - /// Suggest removing the use of a may (or map_err) method when an Option or Result is being constructed. + /// Suggests removing the use of a `map()` (or `map_err()`) method when an `Option` or `Result` + /// is being constructed. /// /// ### Why is this bad? - /// It introduces unnecessary complexity. In this case the function can be used directly and - /// construct the Option or Result from the output. + /// It introduces unnecessary complexity. Instead, the function can be called before + /// constructing the `Option` or `Result` from its return value. /// /// ### Example /// ```no_run - /// Some(4).map(i32::swap_bytes); + /// Some(4).map(i32::swap_bytes) + /// # ; /// ``` /// Use instead: /// ```no_run - /// Some(i32::swap_bytes(4)); + /// Some(i32::swap_bytes(4)) + /// # ; /// ``` - #[clippy::version = "1.73.0"] + #[clippy::version = "1.74.0"] pub UNNECESSARY_MAP_ON_CONSTRUCTOR, complexity, "using `map`/`map_err` on `Option` or `Result` constructors" @@ -59,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor { } }, hir::QPath::TypeRelative(_, path) => path.ident.name, - hir::QPath::LangItem(_, _, _) => return, + hir::QPath::LangItem(..) => return, }; match constructor_symbol { sym::Some | sym::Ok if path.ident.name == rustc_span::sym::map => (), diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs index 28ea02e4d9a16..6b5e6c6ab2095 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs @@ -1,13 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{match_def_path, paths}; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; declare_clippy_lint! { @@ -36,46 +35,40 @@ declare_lint_pass!(UnnecessaryOwnedEmptyStrings => [UNNECESSARY_OWNED_EMPTY_STRI impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if_chain! { - if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner_expr) = expr.kind; - if let ExprKind::Call(fun, args) = inner_expr.kind; - if let ExprKind::Path(ref qpath) = fun.kind; - if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); - if let ty::Ref(_, inner_str, _) = cx.typeck_results().expr_ty_adjusted(expr).kind(); - if inner_str.is_str(); - then { - if match_def_path(cx, fun_def_id, &paths::STRING_NEW) { - span_lint_and_sugg( - cx, - UNNECESSARY_OWNED_EMPTY_STRINGS, - expr.span, - "usage of `&String::new()` for a function expecting a `&str` argument", - "try", - "\"\"".to_owned(), - Applicability::MachineApplicable, - ); - } else { - if_chain! { - if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id); - if let [.., last_arg] = args; - if let ExprKind::Lit(spanned) = &last_arg.kind; - if let LitKind::Str(symbol, _) = spanned.node; - if symbol.is_empty(); - let inner_expr_type = cx.typeck_results().expr_ty(inner_expr); - if is_type_lang_item(cx, inner_expr_type, LangItem::String); - then { - span_lint_and_sugg( - cx, - UNNECESSARY_OWNED_EMPTY_STRINGS, - expr.span, - "usage of `&String::from(\"\")` for a function expecting a `&str` argument", - "try", - "\"\"".to_owned(), - Applicability::MachineApplicable, - ); - } - } - } + if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner_expr) = expr.kind + && let ExprKind::Call(fun, args) = inner_expr.kind + && let ExprKind::Path(ref qpath) = fun.kind + && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() + && let ty::Ref(_, inner_str, _) = cx.typeck_results().expr_ty_adjusted(expr).kind() + && inner_str.is_str() + { + if match_def_path(cx, fun_def_id, &paths::STRING_NEW) { + span_lint_and_sugg( + cx, + UNNECESSARY_OWNED_EMPTY_STRINGS, + expr.span, + "usage of `&String::new()` for a function expecting a `&str` argument", + "try", + "\"\"".to_owned(), + Applicability::MachineApplicable, + ); + } else if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id) + && let [.., last_arg] = args + && let ExprKind::Lit(spanned) = &last_arg.kind + && let LitKind::Str(symbol, _) = spanned.node + && symbol.is_empty() + && let inner_expr_type = cx.typeck_results().expr_ty(inner_expr) + && is_type_lang_item(cx, inner_expr_type, LangItem::String) + { + span_lint_and_sugg( + cx, + UNNECESSARY_OWNED_EMPTY_STRINGS, + expr.span, + "usage of `&String::from(\"\")` for a function expecting a `&str` argument", + "try", + "\"\"".to_owned(), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs index a1083a0a68e58..ddee06b59cae1 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; -use if_chain::if_chain; use rustc_ast::{Item, ItemKind, UseTreeKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::kw; declare_clippy_lint! { @@ -36,35 +35,36 @@ declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]); impl EarlyLintPass for UnnecessarySelfImports { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if_chain! { - if let ItemKind::Use(use_tree) = &item.kind; - if let UseTreeKind::Nested(nodes) = &use_tree.kind; - if let [(self_tree, _)] = &**nodes; - if let [self_seg] = &*self_tree.prefix.segments; - if self_seg.ident.name == kw::SelfLower; - if let Some(last_segment) = use_tree.prefix.segments.last(); - - then { - span_lint_and_then( - cx, - UNNECESSARY_SELF_IMPORTS, - item.span, - "import ending with `::{self}`", - |diag| { - diag.span_suggestion( - last_segment.span().with_hi(item.span.hi()), - "consider omitting `::{self}`", - format!( - "{}{};", - last_segment.ident, - if let UseTreeKind::Simple(Some(alias)) = self_tree.kind { format!(" as {alias}") } else { String::new() }, - ), - Applicability::MaybeIncorrect, - ); - diag.note("this will slightly change semantics; any non-module items at the same path will also be imported"); - }, - ); - } + if let ItemKind::Use(use_tree) = &item.kind + && let UseTreeKind::Nested(nodes) = &use_tree.kind + && let [(self_tree, _)] = &**nodes + && let [self_seg] = &*self_tree.prefix.segments + && self_seg.ident.name == kw::SelfLower + && let Some(last_segment) = use_tree.prefix.segments.last() + { + span_lint_and_then( + cx, + UNNECESSARY_SELF_IMPORTS, + item.span, + "import ending with `::{self}`", + |diag| { + diag.span_suggestion( + last_segment.span().with_hi(item.span.hi()), + "consider omitting `::{self}`", + format!( + "{}{};", + last_segment.ident, + if let UseTreeKind::Simple(Some(alias)) = self_tree.kind { + format!(" as {alias}") + } else { + String::new() + }, + ), + Applicability::MaybeIncorrect, + ); + diag.note("this will slightly change semantics; any non-module items at the same path will also be imported"); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs b/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs index c35a2afab48e3..ed4d87ef8f8ae 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs @@ -4,7 +4,7 @@ use clippy_utils::ty::is_copy; use clippy_utils::{get_parent_expr, path_to_local}; use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index ab8de17b091f6..446160f8e0fdc 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -2,14 +2,13 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::LangItem::{OptionSome, ResultOk}; use rustc_hir::{Body, ExprKind, FnDecl, Impl, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::sym; use rustc_span::Span; @@ -92,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { } // Abort if the method is implementing a trait or of it a trait method. - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(def_id); if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) { if matches!( item.kind, @@ -119,28 +118,24 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { // Check if all return expression respect the following condition and collect them. let mut suggs = Vec::new(); let can_sugg = find_all_ret_expressions(cx, body.value, |ret_expr| { - if_chain! { - if !ret_expr.span.from_expansion(); + if !ret_expr.span.from_expansion() // Check if a function call. - if let ExprKind::Call(func, [arg]) = ret_expr.kind; - if is_res_lang_ctor(cx, path_res(cx, func), lang_item); + && let ExprKind::Call(func, [arg]) = ret_expr.kind + && is_res_lang_ctor(cx, path_res(cx, func), lang_item) // Make sure the function argument does not contain a return expression. - if !contains_return(arg); - then { - suggs.push( - ( - ret_expr.span, - if inner_type.is_unit() { - String::new() - } else { - snippet(cx, arg.span.source_callsite(), "..").to_string() - } - ) - ); - true - } else { - false - } + && !contains_return(arg) + { + suggs.push(( + ret_expr.span, + if inner_type.is_unit() { + String::new() + } else { + snippet(cx, arg.span.source_callsite(), "..").to_string() + }, + )); + true + } else { + false } }); diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index 8ff088a208f21..65600009c1d79 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -11,7 +11,7 @@ use rustc_ast::{self as ast, Mutability, Pat, PatKind, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::DUMMY_SP; use std::cell::Cell; use std::mem; @@ -226,7 +226,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, // which we would want to join with other `C(p_j)`s. - Ident(.., None) | Lit(_) | Wild | Path(..) | Range(..) | Rest | MacCall(_) + Ident(.., None) | Lit(_) | Wild | Never | Path(..) | Range(..) | Rest | MacCall(_) // Skip immutable refs, as grouping them saves few characters, // and almost always requires adding parens (increasing noisiness). // In the case of only two patterns, replacement adds net characters. diff --git a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs index c43d5dc94b3e5..3f2f765f75126 100644 --- a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs +++ b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{Item, ItemKind, UseTree, UseTreeKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; +use rustc_session::declare_lint_pass; use rustc_span::symbol::Ident; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs index aea72c798be73..9c8c44c0a16df 100644 --- a/src/tools/clippy/clippy_lints/src/unused_async.rs +++ b/src/tools/clippy/clippy_lints/src/unused_async.rs @@ -5,7 +5,7 @@ use rustc_hir::intravisit::{walk_body, walk_expr, walk_fn, FnKind, Visitor}; use rustc_hir::{Body, Expr, ExprKind, FnDecl, Node, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::{LocalDefId, LocalDefIdSet}; use rustc_span::Span; @@ -148,7 +148,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { // statements, so don't lint at all if there are any such paths. if let Some(def_id) = path.res.opt_def_id() && let Some(local_def_id) = def_id.as_local() - && let Some(DefKind::Fn) = cx.tcx.opt_def_kind(def_id) + && cx.tcx.def_kind(def_id) == DefKind::Fn && cx.tcx.asyncness(def_id).is_async() && !is_node_func_call(cx.tcx.hir().get_parent(hir_id), path.span) { diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 0fcb62017c687..1de9adfcb963a 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::{is_trait_method, is_try, match_trait_method, paths}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs index 0473ecaabeb53..ba72b3450b933 100644 --- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs +++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs @@ -6,7 +6,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter::OnlyBodies; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/unused_rounding.rs b/src/tools/clippy/clippy_lints/src/unused_rounding.rs index fbb36bea06825..d5ca844b9e24b 100644 --- a/src/tools/clippy/clippy_lints/src/unused_rounding.rs +++ b/src/tools/clippy/clippy_lints/src/unused_rounding.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet; use rustc_ast::ast::{Expr, ExprKind, MethodCall}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index f864c520302e4..a67f53f00aee7 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -1,10 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::visitors::is_local_used; -use if_chain::if_chain; use rustc_hir::{Body, Impl, ImplItem, ImplItemKind, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use std::ops::ControlFlow; declare_clippy_lint! { @@ -73,25 +72,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { }) .is_some() }; - if_chain! { - if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind; - if assoc_item.fn_has_self_parameter; - if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; - if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api; - let body = cx.tcx.hir().body(*body_id); - if let [self_param, ..] = body.params; - if !is_local_used(cx, body, self_param.pat.hir_id); - if !contains_todo(cx, body); - then { - span_lint_and_help( - cx, - UNUSED_SELF, - self_param.span, - "unused `self` argument", - None, - "consider refactoring to an associated function", - ); - } + if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind + && assoc_item.fn_has_self_parameter + && let ImplItemKind::Fn(.., body_id) = &impl_item.kind + && (!cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api) + && let body = cx.tcx.hir().body(*body_id) + && let [self_param, ..] = body.params + && !is_local_used(cx, body, self_param.pat.hir_id) + && !contains_todo(cx, body) + { + span_lint_and_help( + cx, + UNUSED_SELF, + self_param.span, + "unused `self` argument", + None, + "consider refactoring to an associated function", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs index adbf8281388d1..0a73da202ec6d 100644 --- a/src/tools/clippy/clippy_lints/src/unused_unit.rs +++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{position_before_rarrow, snippet_opt}; -use if_chain::if_chain; use rustc_ast::visit::FnKind; use rustc_ast::{ast, ClosureBinder}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Span}; declare_clippy_lint! { @@ -37,40 +36,39 @@ declare_lint_pass!(UnusedUnit => [UNUSED_UNIT]); impl EarlyLintPass for UnusedUnit { fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, span: Span, _: ast::NodeId) { - if_chain! { - if let ast::FnRetTy::Ty(ref ty) = kind.decl().output; - if let ast::TyKind::Tup(ref vals) = ty.kind; - if vals.is_empty() && !ty.span.from_expansion() && get_def(span) == get_def(ty.span); - then { - // implicit types in closure signatures are forbidden when `for<...>` is present - if let FnKind::Closure(&ClosureBinder::For { .. }, ..) = kind { - return; - } - - lint_unneeded_unit_return(cx, ty, span); + if let ast::FnRetTy::Ty(ref ty) = kind.decl().output + && let ast::TyKind::Tup(ref vals) = ty.kind + && vals.is_empty() + && !ty.span.from_expansion() + && get_def(span) == get_def(ty.span) + { + // implicit types in closure signatures are forbidden when `for<...>` is present + if let FnKind::Closure(&ClosureBinder::For { .. }, ..) = kind { + return; } + + lint_unneeded_unit_return(cx, ty, span); } } fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { - if_chain! { - if let Some(stmt) = block.stmts.last(); - if let ast::StmtKind::Expr(ref expr) = stmt.kind; - if is_unit_expr(expr); - let ctxt = block.span.ctxt(); - if stmt.span.ctxt() == ctxt && expr.span.ctxt() == ctxt; - then { - let sp = expr.span; - span_lint_and_sugg( - cx, - UNUSED_UNIT, - sp, - "unneeded unit expression", - "remove the final `()`", - String::new(), - Applicability::MachineApplicable, - ); - } + if let Some(stmt) = block.stmts.last() + && let ast::StmtKind::Expr(ref expr) = stmt.kind + && is_unit_expr(expr) + && let ctxt = block.span.ctxt() + && stmt.span.ctxt() == ctxt + && expr.span.ctxt() == ctxt + { + let sp = expr.span; + span_lint_and_sugg( + cx, + UNUSED_UNIT, + sp, + "unneeded unit expression", + "remove the final `()`", + String::new(), + Applicability::MachineApplicable, + ); } } @@ -96,16 +94,14 @@ impl EarlyLintPass for UnusedUnit { fn check_poly_trait_ref(&mut self, cx: &EarlyContext<'_>, poly: &ast::PolyTraitRef) { let segments = &poly.trait_ref.path.segments; - if_chain! { - if segments.len() == 1; - if ["Fn", "FnMut", "FnOnce"].contains(&segments[0].ident.name.as_str()); - if let Some(args) = &segments[0].args; - if let ast::GenericArgs::Parenthesized(generic_args) = &**args; - if let ast::FnRetTy::Ty(ty) = &generic_args.output; - if ty.kind.is_unit(); - then { - lint_unneeded_unit_return(cx, ty, generic_args.span); - } + if segments.len() == 1 + && ["Fn", "FnMut", "FnOnce"].contains(&segments[0].ident.name.as_str()) + && let Some(args) = &segments[0].args + && let ast::GenericArgs::Parenthesized(generic_args) = &**args + && let ast::FnRetTy::Ty(ty) = &generic_args.output + && ty.kind.is_unit() + { + lint_unneeded_unit_return(cx, ty, generic_args.span); } } } diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index cdfcb8500c449..ae2ac38cffe1b 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::is_potentially_local_place; use clippy_utils::{higher, path_to_local}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegment, UnOp}; @@ -13,7 +12,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -155,41 +154,35 @@ fn collect_unwrap_info<'tcx>( } } else if let ExprKind::Unary(UnOp::Not, expr) = &expr.kind { return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false); - } else { - if_chain! { - if let ExprKind::MethodCall(method_name, receiver, args, _) = &expr.kind; - if let Some(local_id) = path_to_local(receiver); - let ty = cx.typeck_results().expr_ty(receiver); - let name = method_name.ident.as_str(); - if is_relevant_option_call(cx, ty, name) || is_relevant_result_call(cx, ty, name); - then { - assert!(args.is_empty()); - let unwrappable = match name { - "is_some" | "is_ok" => true, - "is_err" | "is_none" => false, - _ => unreachable!(), - }; - let safe_to_unwrap = unwrappable != invert; - let kind = if is_type_diagnostic_item(cx, ty, sym::Option) { - UnwrappableKind::Option - } else { - UnwrappableKind::Result - }; + } else if let ExprKind::MethodCall(method_name, receiver, args, _) = &expr.kind + && let Some(local_id) = path_to_local(receiver) + && let ty = cx.typeck_results().expr_ty(receiver) + && let name = method_name.ident.as_str() + && (is_relevant_option_call(cx, ty, name) || is_relevant_result_call(cx, ty, name)) + { + assert!(args.is_empty()); + let unwrappable = match name { + "is_some" | "is_ok" => true, + "is_err" | "is_none" => false, + _ => unreachable!(), + }; + let safe_to_unwrap = unwrappable != invert; + let kind = if is_type_diagnostic_item(cx, ty, sym::Option) { + UnwrappableKind::Option + } else { + UnwrappableKind::Result + }; - return vec![ - UnwrapInfo { - local_id, - if_expr, - check: expr, - check_name: method_name, - branch, - safe_to_unwrap, - kind, - is_entire_condition, - } - ] - } - } + return vec![UnwrapInfo { + local_id, + if_expr, + check: expr, + check_name: method_name, + branch, + safe_to_unwrap, + kind, + is_entire_condition, + }]; } Vec::new() } @@ -319,73 +312,72 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } } else { // find `unwrap[_err]()` calls: - if_chain! { - if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind; - let (self_arg, as_ref_kind) = consume_option_as_ref(self_arg); - if let Some(id) = path_to_local(self_arg); - if [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name); - let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name); - if let Some(unwrappable) = self.unwrappables.iter() - .find(|u| u.local_id == id); + if let ExprKind::MethodCall(method_name, self_arg, ..) = expr.kind + && let (self_arg, as_ref_kind) = consume_option_as_ref(self_arg) + && let Some(id) = path_to_local(self_arg) + && [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name) + && let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name) + && let Some(unwrappable) = self.unwrappables.iter() + .find(|u| u.local_id == id) // Span contexts should not differ with the conditional branch - let span_ctxt = expr.span.ctxt(); - if unwrappable.branch.span.ctxt() == span_ctxt; - if unwrappable.check.span.ctxt() == span_ctxt; - then { - if call_to_unwrap == unwrappable.safe_to_unwrap { - let is_entire_condition = unwrappable.is_entire_condition; - let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id); - let suggested_pattern = if call_to_unwrap { - unwrappable.kind.success_variant_pattern() - } else { - unwrappable.kind.error_variant_pattern() - }; - - span_lint_hir_and_then( - self.cx, - UNNECESSARY_UNWRAP, - expr.hir_id, - expr.span, - &format!( - "called `{}` on `{unwrappable_variable_name}` after checking its variant with `{}`", - method_name.ident.name, - unwrappable.check_name.ident.as_str(), - ), - |diag| { - if is_entire_condition { - diag.span_suggestion( - unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()), - "try", - format!( - "if let {suggested_pattern} = {borrow_prefix}{unwrappable_variable_name}", - borrow_prefix = match as_ref_kind { - Some(AsRefKind::AsRef) => "&", - Some(AsRefKind::AsMut) => "&mut ", - None => "", - }, - ), - // We don't track how the unwrapped value is used inside the - // block or suggest deleting the unwrap, so we can't offer a - // fixable solution. - Applicability::Unspecified, - ); - } else { - diag.span_label(unwrappable.check.span, "the check is happening here"); - diag.help("try using `if let` or `match`"); - } - }, - ); + && let span_ctxt = expr.span.ctxt() + && unwrappable.branch.span.ctxt() == span_ctxt + && unwrappable.check.span.ctxt() == span_ctxt + { + if call_to_unwrap == unwrappable.safe_to_unwrap { + let is_entire_condition = unwrappable.is_entire_condition; + let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id); + let suggested_pattern = if call_to_unwrap { + unwrappable.kind.success_variant_pattern() } else { - span_lint_hir_and_then( - self.cx, - PANICKING_UNWRAP, - expr.hir_id, - expr.span, - &format!("this call to `{}()` will always panic", - method_name.ident.name), - |diag| { diag.span_label(unwrappable.check.span, "because of this check"); }, - ); - } + unwrappable.kind.error_variant_pattern() + }; + + span_lint_hir_and_then( + self.cx, + UNNECESSARY_UNWRAP, + expr.hir_id, + expr.span, + &format!( + "called `{}` on `{unwrappable_variable_name}` after checking its variant with `{}`", + method_name.ident.name, + unwrappable.check_name.ident.as_str(), + ), + |diag| { + if is_entire_condition { + diag.span_suggestion( + unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()), + "try", + format!( + "if let {suggested_pattern} = {borrow_prefix}{unwrappable_variable_name}", + borrow_prefix = match as_ref_kind { + Some(AsRefKind::AsRef) => "&", + Some(AsRefKind::AsMut) => "&mut ", + None => "", + }, + ), + // We don't track how the unwrapped value is used inside the + // block or suggest deleting the unwrap, so we can't offer a + // fixable solution. + Applicability::Unspecified, + ); + } else { + diag.span_label(unwrappable.check.span, "the check is happening here"); + diag.help("try using `if let` or `match`"); + } + }, + ); + } else { + span_lint_hir_and_then( + self.cx, + PANICKING_UNWRAP, + expr.hir_id, + expr.span, + &format!("this call to `{}()` will always panic", method_name.ident.name), + |diag| { + diag.span_label(unwrappable.check.span, "because of this check"); + }, + ); } } walk_expr(self, expr); diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs index 21592abbf1686..a615ef116910a 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs @@ -3,11 +3,10 @@ use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::for_each_expr; use clippy_utils::{method_chain_args, return_ty}; use core::ops::ControlFlow; -use if_chain::if_chain; use rustc_hir as hir; use rustc_hir::ImplItemKind; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -60,15 +59,13 @@ declare_lint_pass!(UnwrapInResult=> [UNWRAP_IN_RESULT]); impl<'tcx> LateLintPass<'tcx> for UnwrapInResult { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { - if_chain! { + if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind // first check if it's a method or function - if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind; // checking if its return type is `result` or `option` - if is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Result) - || is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Option); - then { - lint_impl_body(cx, impl_item.span, impl_item); - } + && (is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Result) + || is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Option)) + { + lint_impl_body(cx, impl_item.span, impl_item); } } } diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index de6a75b79fcfd..d2a1d42f27968 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -1,10 +1,10 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_hir_and_then; use itertools::Itertools; use rustc_errors::Applicability; -use rustc_hir::{Item, ItemKind}; +use rustc_hir::{HirId, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::Ident; declare_clippy_lint! { @@ -77,7 +77,7 @@ fn correct_ident(ident: &str) -> String { ident } -fn check_ident(cx: &LateContext<'_>, ident: &Ident, be_aggressive: bool) { +fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive: bool) { let span = ident.span; let ident = ident.as_str(); let corrected = correct_ident(ident); @@ -89,14 +89,20 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, be_aggressive: bool) { // upper-case-acronyms-aggressive config option enabled || (be_aggressive && ident != corrected) { - span_lint_and_sugg( + span_lint_hir_and_then( cx, UPPER_CASE_ACRONYMS, + hir_id, span, &format!("name `{ident}` contains a capitalized acronym"), - "consider making the acronym lowercase, except the initial letter", - corrected, - Applicability::MaybeIncorrect, + |diag| { + diag.span_suggestion( + span, + "consider making the acronym lowercase, except the initial letter", + corrected, + Applicability::MaybeIncorrect, + ); + }, ); } } @@ -111,16 +117,15 @@ impl LateLintPass<'_> for UpperCaseAcronyms { } match it.kind { ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => { - check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive); + check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive); }, ItemKind::Enum(ref enumdef, _) => { - check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive); + check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive); // check enum variants separately because again we only want to lint on private enums and // the fn check_variant does not know about the vis of the enum of its variants - enumdef - .variants - .iter() - .for_each(|variant| check_ident(cx, &variant.ident, self.upper_case_acronyms_aggressive)); + enumdef.variants.iter().for_each(|variant| { + check_ident(cx, &variant.ident, variant.hir_id, self.upper_case_acronyms_aggressive); + }); }, _ => {}, } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index c3fe16ad5c3e2..fa033838ef355 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -2,7 +2,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_from_proc_macro; use clippy_utils::ty::same_type_and_consts; -use if_chain::if_chain; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{CtorOf, DefKind, Res}; @@ -14,7 +13,7 @@ use rustc_hir::{ }; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -93,32 +92,40 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { // relevant for linting, since this is the self type of the `impl` we're currently in. To // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that // we're in an `impl` or nested item, that we don't want to lint - let stack_item = if_chain! { - if let ItemKind::Impl(Impl { self_ty, generics,.. }) = item.kind; - if let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind; - let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; - if parameters.as_ref().map_or(true, |params| { - params.parenthesized == GenericArgsParentheses::No + let stack_item = if let ItemKind::Impl(Impl { self_ty, generics, .. }) = item.kind + && let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind + && let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args + && parameters.as_ref().map_or(true, |params| { + params.parenthesized == GenericArgsParentheses::No && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))) - }); - if !item.span.from_expansion(); - if !is_from_proc_macro(cx, item); // expensive, should be last check - then { - // Self cannot be used inside const generic parameters - let types_to_skip = generics.params.iter().filter_map(|param| { - match param { - GenericParam { kind: GenericParamKind::Const { ty: Ty { hir_id, ..}, ..}, ..} => Some(*hir_id), - _ => None, - } - }).chain(std::iter::once(self_ty.hir_id)).collect(); - StackItem::Check { - impl_id: item.owner_id.def_id, - in_body: 0, - types_to_skip, - } - } else { - StackItem::NoCheck + }) + && !item.span.from_expansion() + && !is_from_proc_macro(cx, item) + // expensive, should be last check + { + // Self cannot be used inside const generic parameters + let types_to_skip = generics + .params + .iter() + .filter_map(|param| match param { + GenericParam { + kind: + GenericParamKind::Const { + ty: Ty { hir_id, .. }, .. + }, + .. + } => Some(*hir_id), + _ => None, + }) + .chain(std::iter::once(self_ty.hir_id)) + .collect(); + StackItem::Check { + impl_id: item.owner_id.def_id, + in_body: 0, + types_to_skip, } + } else { + StackItem::NoCheck }; self.stack.push(stack_item); } @@ -132,56 +139,54 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // We want to skip types in trait `impl`s that aren't declared as `Self` in the trait // declaration. The collection of those types is all this method implementation does. - if_chain! { - if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind; - if let Some(&mut StackItem::Check { + if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind + && let Some(&mut StackItem::Check { impl_id, ref mut types_to_skip, .. - }) = self.stack.last_mut(); - if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id); - then { - // `self_ty` is the semantic self type of `impl for `. This cannot be - // `Self`. - let self_ty = impl_trait_ref.instantiate_identity().self_ty(); + }) = self.stack.last_mut() + && let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id) + { + // `self_ty` is the semantic self type of `impl for `. This cannot be + // `Self`. + let self_ty = impl_trait_ref.instantiate_identity().self_ty(); - // `trait_method_sig` is the signature of the function, how it is declared in the - // trait, not in the impl of the trait. - let trait_method = cx - .tcx - .associated_item(impl_item.owner_id) - .trait_item_def_id - .expect("impl method matches a trait method"); - let trait_method_sig = cx.tcx.fn_sig(trait_method).instantiate_identity(); - let trait_method_sig = cx.tcx.erase_late_bound_regions(trait_method_sig); + // `trait_method_sig` is the signature of the function, how it is declared in the + // trait, not in the impl of the trait. + let trait_method = cx + .tcx + .associated_item(impl_item.owner_id) + .trait_item_def_id + .expect("impl method matches a trait method"); + let trait_method_sig = cx.tcx.fn_sig(trait_method).instantiate_identity(); + let trait_method_sig = cx.tcx.instantiate_bound_regions_with_erased(trait_method_sig); - // `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the - // implementation of the trait. - let output_hir_ty = if let FnRetTy::Return(ty) = &decl.output { - Some(&**ty) - } else { - None - }; - let impl_inputs_outputs = decl.inputs.iter().chain(output_hir_ty); + // `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the + // implementation of the trait. + let output_hir_ty = if let FnRetTy::Return(ty) = &decl.output { + Some(&**ty) + } else { + None + }; + let impl_inputs_outputs = decl.inputs.iter().chain(output_hir_ty); - // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature. - // - // `trait_sem_ty` (of type `ty::Ty`) is the semantic type for the signature in the - // trait declaration. This is used to check if `Self` was used in the trait - // declaration. - // - // If `any`where in the `trait_sem_ty` the `self_ty` was used verbatim (as opposed - // to `Self`), we want to skip linting that type and all subtypes of it. This - // avoids suggestions to e.g. replace `Vec` with `Vec`, in an `impl Trait - // for u8`, when the trait always uses `Vec`. - // - // See also https://github.com/rust-lang/rust-clippy/issues/2894. - for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) { - if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) { - let mut visitor = SkipTyCollector::default(); - visitor.visit_ty(impl_hir_ty); - types_to_skip.extend(visitor.types_to_skip); - } + // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature. + // + // `trait_sem_ty` (of type `ty::Ty`) is the semantic type for the signature in the + // trait declaration. This is used to check if `Self` was used in the trait + // declaration. + // + // If `any`where in the `trait_sem_ty` the `self_ty` was used verbatim (as opposed + // to `Self`), we want to skip linting that type and all subtypes of it. This + // avoids suggestions to e.g. replace `Vec` with `Vec`, in an `impl Trait + // for u8`, when the trait always uses `Vec`. + // + // See also https://github.com/rust-lang/rust-clippy/issues/2894. + for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) { + if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) { + let mut visitor = SkipTyCollector::default(); + visitor.visit_ty(impl_hir_ty); + types_to_skip.extend(visitor.types_to_skip); } } } @@ -203,41 +208,38 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { - if_chain! { - if !hir_ty.span.from_expansion(); - if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS); - if let Some(&StackItem::Check { + if !hir_ty.span.from_expansion() + && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) + && let Some(&StackItem::Check { impl_id, in_body, ref types_to_skip, - }) = self.stack.last(); - if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind; - if !matches!( + }) = self.stack.last() + && let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind + && !matches!( path.res, - Res::SelfTyParam { .. } - | Res::SelfTyAlias { .. } - | Res::Def(DefKind::TyParam, _) - ); - if !types_to_skip.contains(&hir_ty.hir_id); - let ty = if in_body > 0 { + Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _) + ) + && !types_to_skip.contains(&hir_ty.hir_id) + && let ty = if in_body > 0 { cx.typeck_results().node_type(hir_ty.hir_id) } else { hir_ty_to_ty(cx.tcx, hir_ty) - }; - if same_type_and_consts(ty, cx.tcx.type_of(impl_id).instantiate_identity()); - then { - span_lint(cx, hir_ty.span); } + && same_type_and_consts(ty, cx.tcx.type_of(impl_id).instantiate_identity()) + { + span_lint(cx, hir_ty.span); } } fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - if_chain! { - if !expr.span.from_expansion(); - if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS); - if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last(); - if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).instantiate_identity(); - then {} else { return; } + if !expr.span.from_expansion() + && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) + && let Some(&StackItem::Check { impl_id, .. }) = self.stack.last() + && cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).instantiate_identity() + { + } else { + return; } match expr.kind { ExprKind::Struct(QPath::Resolved(_, path), ..) => check_path(cx, path), @@ -252,18 +254,16 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { - if_chain! { - if !pat.span.from_expansion(); - if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS); - if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last(); + if !pat.span.from_expansion() + && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) + && let Some(&StackItem::Check { impl_id, .. }) = self.stack.last() // get the path from the pattern - if let PatKind::Path(QPath::Resolved(_, path)) + && let PatKind::Path(QPath::Resolved(_, path)) | PatKind::TupleStruct(QPath::Resolved(_, path), _, _) - | PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind; - if cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).instantiate_identity(); - then { - check_path(cx, path); - } + | PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind + && cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).instantiate_identity() + { + check_path(cx, path); } } diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 28f1d487eb5f5..2ab24f70ae0b4 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -3,9 +3,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_con use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, path_to_local}; -use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind}; use rustc_infer::infer::TyCtxtInferExt; @@ -13,7 +11,7 @@ use rustc_infer::traits::Obligation; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{sym, Span}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -209,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { && let Some(did) = cx.qpath_res(qpath, recv.hir_id).opt_def_id() // make sure that the path indeed points to a fn-like item, so that // `fn_sig` does not ICE. (see #11065) - && cx.tcx.opt_def_kind(did).is_some_and(DefKind::is_fn_like) => + && cx.tcx.def_kind(did).is_fn_like() => { Some(( did, @@ -311,76 +309,63 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { ); } } - if_chain! { - if is_trait_method(cx, e, sym::TryInto) && name.ident.name == sym::try_into; - let a = cx.typeck_results().expr_ty(e); - let b = cx.typeck_results().expr_ty(recv); - if is_type_diagnostic_item(cx, a, sym::Result); - if let ty::Adt(_, args) = a.kind(); - if let Some(a_type) = args.types().next(); - if same_type_and_consts(a_type, b); + if is_trait_method(cx, e, sym::TryInto) + && name.ident.name == sym::try_into + && let a = cx.typeck_results().expr_ty(e) + && let b = cx.typeck_results().expr_ty(recv) + && is_type_diagnostic_item(cx, a, sym::Result) + && let ty::Adt(_, args) = a.kind() + && let Some(a_type) = args.types().next() + && same_type_and_consts(a_type, b) + { + span_lint_and_help( + cx, + USELESS_CONVERSION, + e.span, + &format!("useless conversion to the same type: `{b}`"), + None, + "consider removing `.try_into()`", + ); + } + }, - then { + ExprKind::Call(path, [arg]) => { + if let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && !is_ty_alias(qpath) + { + let a = cx.typeck_results().expr_ty(e); + let b = cx.typeck_results().expr_ty(arg); + if cx.tcx.is_diagnostic_item(sym::try_from_fn, def_id) + && is_type_diagnostic_item(cx, a, sym::Result) + && let ty::Adt(_, args) = a.kind() + && let Some(a_type) = args.types().next() + && same_type_and_consts(a_type, b) + { + let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from")); span_lint_and_help( cx, USELESS_CONVERSION, e.span, &format!("useless conversion to the same type: `{b}`"), None, - "consider removing `.try_into()`", + &hint, ); } - } - }, - - ExprKind::Call(path, [arg]) => { - if_chain! { - if let ExprKind::Path(ref qpath) = path.kind; - if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); - if !is_ty_alias(qpath); - then { - let a = cx.typeck_results().expr_ty(e); - let b = cx.typeck_results().expr_ty(arg); - if_chain! { - if cx.tcx.is_diagnostic_item(sym::try_from_fn, def_id); - if is_type_diagnostic_item(cx, a, sym::Result); - if let ty::Adt(_, args) = a.kind(); - if let Some(a_type) = args.types().next(); - if same_type_and_consts(a_type, b); - then { - let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from")); - span_lint_and_help( - cx, - USELESS_CONVERSION, - e.span, - &format!("useless conversion to the same type: `{b}`"), - None, - &hint, - ); - } - } - - if_chain! { - if cx.tcx.is_diagnostic_item(sym::from_fn, def_id); - if same_type_and_consts(a, b); - - then { - let mut app = Applicability::MachineApplicable; - let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "", &mut app).maybe_par(); - let sugg_msg = - format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); - span_lint_and_sugg( - cx, - USELESS_CONVERSION, - e.span, - &format!("useless conversion to the same type: `{b}`"), - &sugg_msg, - sugg.to_string(), - app, - ); - } - } + if cx.tcx.is_diagnostic_item(sym::from_fn, def_id) && same_type_and_consts(a, b) { + let mut app = Applicability::MachineApplicable; + let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "", &mut app).maybe_par(); + let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); + span_lint_and_sugg( + cx, + USELESS_CONVERSION, + e.span, + &format!("useless conversion to the same type: `{b}`"), + &sugg_msg, + sugg.to_string(), + app, + ); } } }, diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index ce93aea21360d..e83c04eda2077 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -7,7 +7,7 @@ use rustc_ast::LitIntType; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::{ - ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, + ArrayLen, BindingAnnotation, CaptureBy, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; @@ -479,6 +479,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { movability, .. }) => { + let capture_clause = match capture_clause { + CaptureBy::Value { .. } => "Value { .. }", + CaptureBy::Ref => "Ref", + }; + let movability = OptionPat::new(movability.map(|m| format!("Movability::{m:?}"))); let ret_ty = match fn_decl.output { @@ -487,7 +492,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { }; bind!(self, fn_decl, body_id); - kind!("Closure(CaptureBy::{capture_clause:?}, {fn_decl}, {body_id}, _, {movability})"); + kind!("Closure(CaptureBy::{capture_clause}, {fn_decl}, {body_id}, _, {movability})"); chain!(self, "let {ret_ty} = {fn_decl}.output"); self.body(body_id); }, @@ -624,6 +629,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { match pat.value.kind { PatKind::Wild => kind!("Wild"), + PatKind::Never => kind!("Never"), PatKind::Binding(ann, _, name, sub) => { bind!(self, name); opt_bind!(self, sub); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index ddcb9f27c6c00..877a77fd6d242 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -1,7 +1,6 @@ pub mod almost_standard_lint_formulation; pub mod collapsible_calls; pub mod compiler_lint_functions; -pub mod if_chain_style; pub mod interning_defined_symbol; pub mod invalid_paths; pub mod lint_without_lint_pass; diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs index d78f67c05f007..5ddedb24b15a4 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs @@ -4,7 +4,7 @@ use regex::Regex; use rustc_ast as ast; use rustc_hir::{Item, ItemKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs index d7666b77f6e96..7c70d3f45dba3 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::{is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt, SpanlessEq}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use std::borrow::{Borrow, Cow}; @@ -78,45 +77,43 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { return; } - if_chain! { - if let ExprKind::Call(func, and_then_args) = expr.kind; - if is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"]); - if and_then_args.len() == 5; - if let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].kind; - let body = cx.tcx.hir().body(body); - let only_expr = peel_blocks_with_stmt(body.value); - if let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind; - if let ExprKind::Path(..) = recv.kind; - then { - let and_then_snippets = get_and_then_snippets(cx, and_then_args); - let mut sle = SpanlessEq::new(cx).deny_side_effects(); - match ps.ident.as_str() { - "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { - suggest_suggestion( - cx, - expr, - &and_then_snippets, - &span_suggestion_snippets(cx, span_call_args), - ); - }, - "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { - let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true); - }, - "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { - let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true); - }, - "help" => { - let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#); - suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false); - }, - "note" => { - let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#); - suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false); - }, - _ => (), - } + if let ExprKind::Call(func, and_then_args) = expr.kind + && is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"]) + && and_then_args.len() == 5 + && let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].kind + && let body = cx.tcx.hir().body(body) + && let only_expr = peel_blocks_with_stmt(body.value) + && let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind + && let ExprKind::Path(..) = recv.kind + { + let and_then_snippets = get_and_then_snippets(cx, and_then_args); + let mut sle = SpanlessEq::new(cx).deny_side_effects(); + match ps.ident.as_str() { + "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { + suggest_suggestion( + cx, + expr, + &and_then_snippets, + &span_suggestion_snippets(cx, span_call_args), + ); + }, + "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { + let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); + suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true); + }, + "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => { + let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#); + suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true); + }, + "help" => { + let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#); + suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false); + }, + "note" => { + let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#); + suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false); + }, + _ => (), } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs index cacd05262a215..5059712d69c14 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::match_type; use clippy_utils::{is_lint_allowed, paths}; -use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does @@ -56,22 +55,20 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions { return; } - if_chain! { - if let ExprKind::MethodCall(path, self_arg, _, _) = &expr.kind; - let fn_name = path.ident; - if let Some(sugg) = self.map.get(fn_name.as_str()); - let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); - if match_type(cx, ty, &paths::EARLY_CONTEXT) || match_type(cx, ty, &paths::LATE_CONTEXT); - then { - span_lint_and_help( - cx, - COMPILER_LINT_FUNCTIONS, - path.ident.span, - "usage of a compiler lint function", - None, - &format!("please use the Clippy variant of this function: `{sugg}`"), - ); - } + if let ExprKind::MethodCall(path, self_arg, _, _) = &expr.kind + && let fn_name = path.ident + && let Some(sugg) = self.map.get(fn_name.as_str()) + && let ty = cx.typeck_results().expr_ty(self_arg).peel_refs() + && (match_type(cx, ty, &paths::EARLY_CONTEXT) || match_type(cx, ty, &paths::LATE_CONTEXT)) + { + span_lint_and_help( + cx, + COMPILER_LINT_FUNCTIONS, + path.ident.span, + "usage of a compiler lint function", + None, + &format!("please use the Clippy variant of this function: `{sugg}`"), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs deleted file mode 100644 index 8cdd5ea890371..0000000000000 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs +++ /dev/null @@ -1,166 +0,0 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::{higher, is_else_clause, is_expn_of}; -use if_chain::if_chain; -use rustc_hir as hir; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Local, Node, Stmt, StmtKind}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{BytePos, Span}; - -declare_clippy_lint! { - /// Finds unidiomatic usage of `if_chain!` - pub IF_CHAIN_STYLE, - internal, - "non-idiomatic `if_chain!` usage" -} - -declare_lint_pass!(IfChainStyle => [IF_CHAIN_STYLE]); - -impl<'tcx> LateLintPass<'tcx> for IfChainStyle { - fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { - let (local, after, if_chain_span) = if_chain! { - if let [Stmt { kind: StmtKind::Local(local), .. }, after @ ..] = block.stmts; - if let Some(if_chain_span) = is_expn_of(block.span, "if_chain"); - then { (local, after, if_chain_span) } else { return } - }; - if is_first_if_chain_expr(cx, block.hir_id, if_chain_span) { - span_lint( - cx, - IF_CHAIN_STYLE, - if_chain_local_span(cx, local, if_chain_span), - "`let` expression should be above the `if_chain!`", - ); - } else if local.span.eq_ctxt(block.span) && is_if_chain_then(after, block.expr, if_chain_span) { - span_lint( - cx, - IF_CHAIN_STYLE, - if_chain_local_span(cx, local, if_chain_span), - "`let` expression should be inside `then { .. }`", - ); - } - } - - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - let (cond, then, els) = if let Some(higher::IfOrIfLet { cond, r#else, then }) = higher::IfOrIfLet::hir(expr) { - (cond, then, r#else.is_some()) - } else { - return; - }; - let ExprKind::Block(then_block, _) = then.kind else { - return; - }; - let if_chain_span = is_expn_of(expr.span, "if_chain"); - if !els { - check_nested_if_chains(cx, expr, then_block, if_chain_span); - } - let Some(if_chain_span) = if_chain_span else { return }; - // check for `if a && b;` - if_chain! { - if let ExprKind::Binary(op, _, _) = cond.kind; - if op.node == BinOpKind::And; - if cx.sess().source_map().is_multiline(cond.span); - then { - span_lint(cx, IF_CHAIN_STYLE, cond.span, "`if a && b;` should be `if a; if b;`"); - } - } - if is_first_if_chain_expr(cx, expr.hir_id, if_chain_span) - && is_if_chain_then(then_block.stmts, then_block.expr, if_chain_span) - { - span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`"); - } - } -} - -fn check_nested_if_chains( - cx: &LateContext<'_>, - if_expr: &Expr<'_>, - then_block: &Block<'_>, - if_chain_span: Option, -) { - #[rustfmt::skip] - let (head, tail) = match *then_block { - Block { stmts, expr: Some(tail), .. } => (stmts, tail), - Block { - stmts: &[ - ref head @ .., - Stmt { kind: StmtKind::Expr(tail) | StmtKind::Semi(tail), .. } - ], - .. - } => (head, tail), - _ => return, - }; - if_chain! { - if let Some(higher::IfOrIfLet { r#else: None, .. }) = higher::IfOrIfLet::hir(tail); - let sm = cx.sess().source_map(); - if head - .iter() - .all(|stmt| matches!(stmt.kind, StmtKind::Local(..)) && !sm.is_multiline(stmt.span)); - if if_chain_span.is_some() || !is_else_clause(cx.tcx, if_expr); - then { - } else { - return; - } - } - let (span, msg) = match (if_chain_span, is_expn_of(tail.span, "if_chain")) { - (None, Some(_)) => (if_expr.span, "this `if` can be part of the inner `if_chain!`"), - (Some(_), None) => (tail.span, "this `if` can be part of the outer `if_chain!`"), - (Some(a), Some(b)) if a != b => (b, "this `if_chain!` can be merged with the outer `if_chain!`"), - _ => return, - }; - span_lint_and_then(cx, IF_CHAIN_STYLE, span, msg, |diag| { - let (span, msg) = match head { - [] => return, - [stmt] => (stmt.span, "this `let` statement can also be in the `if_chain!`"), - [a, .., b] => ( - a.span.to(b.span), - "these `let` statements can also be in the `if_chain!`", - ), - }; - diag.span_help(span, msg); - }); -} - -fn is_first_if_chain_expr(cx: &LateContext<'_>, hir_id: HirId, if_chain_span: Span) -> bool { - cx.tcx - .hir() - .parent_iter(hir_id) - .find(|(_, node)| { - #[rustfmt::skip] - !matches!(node, Node::Expr(Expr { kind: ExprKind::Block(..), .. }) | Node::Stmt(_)) - }) - .map_or(false, |(id, _)| { - is_expn_of(cx.tcx.hir().span(id), "if_chain") != Some(if_chain_span) - }) -} - -/// Checks a trailing slice of statements and expression of a `Block` to see if they are part -/// of the `then {..}` portion of an `if_chain!` -fn is_if_chain_then(stmts: &[Stmt<'_>], expr: Option<&Expr<'_>>, if_chain_span: Span) -> bool { - let span = if let [stmt, ..] = stmts { - stmt.span - } else if let Some(expr) = expr { - expr.span - } else { - // empty `then {}` - return true; - }; - is_expn_of(span, "if_chain").map_or(true, |span| span != if_chain_span) -} - -/// Creates a `Span` for `let x = ..;` in an `if_chain!` call. -fn if_chain_local_span(cx: &LateContext<'_>, local: &Local<'_>, if_chain_span: Span) -> Span { - let mut span = local.pat.span; - if let Some(init) = local.init { - span = span.to(init.span); - } - span.adjust(if_chain_span.ctxt().outer_expn()); - let sm = cx.sess().source_map(); - let span = sm.span_extend_to_prev_str(span, "let", false, true).unwrap_or(span); - let span = sm.span_extend_to_next_char(span, ';', false); - Span::new( - span.lo() - BytePos(3), - span.hi() + BytePos(1), - span.ctxt(), - span.parent(), - ) -} diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs index fc9afe5ca8b96..07879e81fc293 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::match_type; use clippy_utils::{def_path_def_ids, is_expn_of, match_def_path, paths}; -use if_chain::if_chain; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -12,7 +11,7 @@ use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::ConstValue; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; use rustc_span::symbol::Symbol; @@ -77,15 +76,13 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol { for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] { for def_id in def_path_def_ids(cx, module) { for item in cx.tcx.module_children(def_id) { - if_chain! { - if let Res::Def(DefKind::Const, item_def_id) = item.res; - let ty = cx.tcx.type_of(item_def_id).instantiate_identity(); - if match_type(cx, ty, &paths::SYMBOL); - if let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id); - if let Ok(value) = value.to_u32(); - then { - self.symbol_map.insert(value, item_def_id); - } + if let Res::Def(DefKind::Const, item_def_id) = item.res + && let ty = cx.tcx.type_of(item_def_id).instantiate_identity() + && match_type(cx, ty, &paths::SYMBOL) + && let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id) + && let Ok(value) = value.to_u32() + { + self.symbol_map.insert(value, item_def_id); } } } @@ -93,24 +90,22 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(func, [arg]) = &expr.kind; - if let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind(); - if match_def_path(cx, *def_id, &paths::SYMBOL_INTERN); - if let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg); - let value = Symbol::intern(&arg).as_u32(); - if let Some(&def_id) = self.symbol_map.get(&value); - then { - span_lint_and_sugg( - cx, - INTERNING_DEFINED_SYMBOL, - is_expn_of(expr.span, "sym").unwrap_or(expr.span), - "interning a defined symbol", - "try", - cx.tcx.def_path_str(def_id), - Applicability::MachineApplicable, - ); - } + if let ExprKind::Call(func, [arg]) = &expr.kind + && let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind() + && match_def_path(cx, *def_id, &paths::SYMBOL_INTERN) + && let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg) + && let value = Symbol::intern(&arg).as_u32() + && let Some(&def_id) = self.symbol_map.get(&value) + { + span_lint_and_sugg( + cx, + INTERNING_DEFINED_SYMBOL, + is_expn_of(expr.span, "sym").unwrap_or(expr.span), + "interning a defined symbol", + "try", + cx.tcx.def_path_str(def_id), + Applicability::MachineApplicable, + ); } if let ExprKind::Binary(op, left, right) = expr.kind { if matches!(op.node, BinOpKind::Eq | BinOpKind::Ne) { @@ -163,27 +158,28 @@ impl InterningDefinedSymbol { fn symbol_str_expr<'tcx>(&self, expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> Option> { static IDENT_STR_PATHS: &[&[&str]] = &[&paths::IDENT_AS_STR]; static SYMBOL_STR_PATHS: &[&[&str]] = &[&paths::SYMBOL_AS_STR, &paths::SYMBOL_TO_IDENT_STRING]; - let call = if_chain! { - if let ExprKind::AddrOf(_, _, e) = expr.kind; - if let ExprKind::Unary(UnOp::Deref, e) = e.kind; - then { e } else { expr } + let call = if let ExprKind::AddrOf(_, _, e) = expr.kind + && let ExprKind::Unary(UnOp::Deref, e) = e.kind + { + e + } else { + expr }; - if_chain! { + if let ExprKind::MethodCall(_, item, [], _) = call.kind // is a method call - if let ExprKind::MethodCall(_, item, [], _) = call.kind; - if let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id); - let ty = cx.typeck_results().expr_ty(item); + && let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id) + && let ty = cx.typeck_results().expr_ty(item) // ...on either an Ident or a Symbol - if let Some(is_ident) = if match_type(cx, ty, &paths::SYMBOL) { + && let Some(is_ident) = if match_type(cx, ty, &paths::SYMBOL) { Some(false) } else if match_type(cx, ty, &paths::IDENT) { Some(true) } else { None - }; + } // ...which converts it to a string - let paths = if is_ident { IDENT_STR_PATHS } else { SYMBOL_STR_PATHS }; - if let Some(is_to_owned) = paths + && let paths = if is_ident { IDENT_STR_PATHS } else { SYMBOL_STR_PATHS } + && let Some(is_to_owned) = paths .iter() .find_map(|path| if match_def_path(cx, did, path) { Some(path == &paths::SYMBOL_TO_IDENT_STRING) @@ -194,14 +190,13 @@ impl InterningDefinedSymbol { Some(true) } else { None - }); - then { - return Some(SymbolStrExpr::Expr { - item, - is_ident, - is_to_owned, - }); - } + }) + { + return Some(SymbolStrExpr::Expr { + item, + is_ident, + is_to_owned, + }); } // is a string constant if let Some(Constant::Str(s)) = constant_simple(cx, cx.typeck_results(), expr) { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs index 250772238853b..4fb615e1d579e 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs @@ -1,14 +1,13 @@ use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::def_path_res; use clippy_utils::diagnostics::span_lint; -use if_chain::if_chain; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::Item; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::FloatTy; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::Symbol; declare_clippy_lint! { @@ -31,13 +30,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { let local_def_id = &cx.tcx.parent_module(item.hir_id()); let mod_name = &cx.tcx.item_name(local_def_id.to_def_id()); - if_chain! { - if mod_name.as_str() == "paths"; - if let hir::ItemKind::Const(.., body_id) = item.kind; - let body = cx.tcx.hir().body(body_id); - let typeck_results = cx.tcx.typeck_body(body_id); - if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value); - if let Some(path) = path + if mod_name.as_str() == "paths" + && let hir::ItemKind::Const(.., body_id) = item.kind + && let body = cx.tcx.hir().body(body_id) + && let typeck_results = cx.tcx.typeck_body(body_id) + && let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value) + && let Some(path) = path .iter() .map(|x| { if let Constant::Str(s) = x { @@ -46,11 +44,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths { None } }) - .collect::>>(); - if !check_path(cx, &path[..]); - then { - span_lint(cx, INVALID_PATHS, item.span, "invalid path"); - } + .collect::>>() + && !check_path(cx, &path[..]) + { + span_lint(cx, INVALID_PATHS, item.span, "invalid path"); } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 00e352961bd3e..370ed430bcfb5 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -2,7 +2,6 @@ use crate::utils::internal_lints::metadata_collector::is_deprecated_lint; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::{is_lint_allowed, match_def_path, paths}; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::{DefKind, Res}; @@ -12,7 +11,7 @@ use rustc_hir::{ExprKind, HirId, Item, MutTy, Mutability, Path, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_semver::RustcVersion; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; use rustc_span::{sym, Span}; @@ -309,14 +308,16 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<' pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option { let attrs = cx.tcx.hir().attrs(item.hir_id()); attrs.iter().find_map(|attr| { - if_chain! { + if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind // Identify attribute - if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind; - if let [tool_name, attr_name] = &attr_kind.item.path.segments[..]; - if tool_name.ident.name == sym::clippy; - if attr_name.ident.name == sym::version; - if let Some(version) = attr.value_str(); - then { Some(version) } else { None } + && let [tool_name, attr_name] = &attr_kind.item.path.segments[..] + && tool_name.ident.name == sym::clippy + && attr_name.ident.name == sym::version + && let Some(version) = attr.value_str() + { + Some(version) + } else { + None } }) } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 51abe0c1dc36d..373b076f92c66 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -14,16 +14,15 @@ use clippy_config::{get_configuration_metadata, ClippyConfiguration}; use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::{match_type, walk_ptrs_ty_depth}; use clippy_utils::{last_path_segment, match_def_path, match_function_call, match_path, paths}; -use if_chain::if_chain; use itertools::Itertools; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, intravisit, Closure, ExprKind, Item, ItemKind, Mutability, QPath}; -use rustc_lint::{CheckLintNameResult, LateContext, LateLintPass, LintContext, LintId}; +use rustc_lint::{unerased_lint_store, CheckLintNameResult, LateContext, LateLintPass, LintContext, LintId}; use rustc_middle::hir::nested_filter; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::Ident; use rustc_span::{sym, Loc, Span, Symbol}; use serde::ser::SerializeStruct; @@ -543,49 +542,45 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector { fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) { if let ItemKind::Static(ty, Mutability::Not, _) = item.kind { // Normal lint - if_chain! { + if is_lint_ref_type(cx, ty) // item validation - if is_lint_ref_type(cx, ty); // disallow check - let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase(); + && let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase() // metadata extraction - if let Some((group, level)) = get_lint_group_and_level_or_lint(cx, &lint_name, item); - if let Some(mut raw_docs) = extract_attr_docs_or_lint(cx, item); - then { - if let Some(configuration_section) = self.get_lint_configs(&lint_name) { - raw_docs.push_str(&configuration_section); - } - let version = get_lint_version(cx, item); - - self.lints.push(LintMetadata::new( - lint_name, - SerializableSpan::from_item(cx, item), - group, - level, - version, - raw_docs, - )); + && let Some((group, level)) = get_lint_group_and_level_or_lint(cx, &lint_name, item) + && let Some(mut raw_docs) = extract_attr_docs_or_lint(cx, item) + { + if let Some(configuration_section) = self.get_lint_configs(&lint_name) { + raw_docs.push_str(&configuration_section); } + let version = get_lint_version(cx, item); + + self.lints.push(LintMetadata::new( + lint_name, + SerializableSpan::from_item(cx, item), + group, + level, + version, + raw_docs, + )); } - if_chain! { - if is_deprecated_lint(cx, ty); + if is_deprecated_lint(cx, ty) // disallow check - let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase(); + && let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase() // Metadata the little we can get from a deprecated lint - if let Some(raw_docs) = extract_attr_docs_or_lint(cx, item); - then { - let version = get_lint_version(cx, item); - - self.lints.push(LintMetadata::new( - lint_name, - SerializableSpan::from_item(cx, item), - DEPRECATED_LINT_GROUP_STR.to_string(), - DEPRECATED_LINT_LEVEL, - version, - raw_docs, - )); - } + && let Some(raw_docs) = extract_attr_docs_or_lint(cx, item) + { + let version = get_lint_version(cx, item); + + self.lints.push(LintMetadata::new( + lint_name, + SerializableSpan::from_item(cx, item), + DEPRECATED_LINT_GROUP_STR.to_string(), + DEPRECATED_LINT_LEVEL, + version, + raw_docs, + )); } } } @@ -719,7 +714,7 @@ fn get_lint_group_and_level_or_lint( lint_name: &str, item: &Item<'_>, ) -> Option<(String, &'static str)> { - let result = cx.lint_store.check_lint_name( + let result = unerased_lint_store(cx.tcx.sess).check_lint_name( lint_name, Some(sym::clippy), &std::iter::once(Ident::with_dummy_span(sym::clippy)).collect(), @@ -751,7 +746,7 @@ fn get_lint_group_and_level_or_lint( } fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option { - for (group_name, lints, _) in cx.lint_store.get_lint_groups() { + for (group_name, lints, _) in unerased_lint_store(cx.tcx.sess).get_lint_groups() { if IGNORED_LINT_GROUPS.contains(&group_name) { continue; } @@ -789,15 +784,13 @@ fn collect_renames(lints: &mut Vec) { loop { if let Some(lint_name) = names.pop() { for (k, v) in RENAMED_LINTS { - if_chain! { - if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX); - if name == lint_name; - if let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX); - then { - lint.former_ids.insert(past_name.to_owned()); - writeln!(collected, "* `{past_name}`").unwrap(); - names.push(past_name.to_string()); - } + if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX) + && name == lint_name + && let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX) + { + lint.former_ids.insert(past_name.to_owned()); + writeln!(collected, "* `{past_name}`").unwrap(); + names.push(past_name.to_string()); } } @@ -927,20 +920,17 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> { } fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - if_chain! { - if let ExprKind::Path(qpath) = &expr.kind; - if let QPath::Resolved(_, path) = qpath; - - let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); - if match_type(self.cx, expr_ty, &paths::LINT); - then { - if let hir::def::Res::Def(DefKind::Static(..), _) = path.res { - let lint_name = last_path_segment(qpath).ident.name; - self.lints.push(sym_to_string(lint_name).to_ascii_lowercase()); - } else if let Some(local) = get_parent_local(self.cx, expr) { - if let Some(local_init) = local.init { - intravisit::walk_expr(self, local_init); - } + if let ExprKind::Path(qpath) = &expr.kind + && let QPath::Resolved(_, path) = qpath + && let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)) + && match_type(self.cx, expr_ty, &paths::LINT) + { + if let hir::def::Res::Def(DefKind::Static(..), _) = path.res { + let lint_name = last_path_segment(qpath).ident.name; + self.lints.push(sym_to_string(lint_name).to_ascii_lowercase()); + } else if let Some(local) = get_parent_local(self.cx, expr) { + if let Some(local_init) = local.init { + intravisit::walk_expr(self, local_init); } } } @@ -992,13 +982,11 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); - if_chain! { - if match_type(self.cx, expr_ty, &paths::APPLICABILITY); - if let Some(local) = get_parent_local(self.cx, expr); - if let Some(local_init) = local.init; - then { - intravisit::walk_expr(self, local_init); - } + if match_type(self.cx, expr_ty, &paths::APPLICABILITY) + && let Some(local) = get_parent_local(self.cx, expr) + && let Some(local_init) = local.init + { + intravisit::walk_expr(self, local_init); }; intravisit::walk_expr(self, expr); diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs index 86b77a77f1730..6d5240db83249 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs @@ -2,12 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::match_type; use clippy_utils::{match_def_path, paths}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::{self, EarlyBinder, GenericArgKind}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -22,40 +21,41 @@ declare_lint_pass!(MsrvAttrImpl => [MISSING_MSRV_ATTR_IMPL]); impl LateLintPass<'_> for MsrvAttrImpl { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if_chain! { - if let hir::ItemKind::Impl(hir::Impl { - of_trait: Some(_), - items, - .. - }) = &item.kind; - if let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::instantiate_identity); - let is_late_pass = match_def_path(cx, trait_ref.def_id, &paths::LATE_LINT_PASS); - if is_late_pass || match_def_path(cx, trait_ref.def_id, &paths::EARLY_LINT_PASS); - if let ty::Adt(self_ty_def, _) = trait_ref.self_ty().kind(); - if self_ty_def.is_struct(); - if self_ty_def.all_fields().any(|f| { + if let hir::ItemKind::Impl(hir::Impl { + of_trait: Some(_), + items, + .. + }) = &item.kind + && let Some(trait_ref) = cx + .tcx + .impl_trait_ref(item.owner_id) + .map(EarlyBinder::instantiate_identity) + && let is_late_pass = match_def_path(cx, trait_ref.def_id, &paths::LATE_LINT_PASS) + && (is_late_pass || match_def_path(cx, trait_ref.def_id, &paths::EARLY_LINT_PASS)) + && let ty::Adt(self_ty_def, _) = trait_ref.self_ty().kind() + && self_ty_def.is_struct() + && self_ty_def.all_fields().any(|f| { cx.tcx .type_of(f.did) .instantiate_identity() .walk() .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_))) .any(|t| match_type(cx, t.expect_ty(), &paths::MSRV)) - }); - if !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs)); - then { - let context = if is_late_pass { "LateContext" } else { "EarlyContext" }; - let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" }; - let span = cx.sess().source_map().span_through_char(item.span, '{'); - span_lint_and_sugg( - cx, - MISSING_MSRV_ATTR_IMPL, - span, - &format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"), - &format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"), - format!("{}\n extract_msrv_attr!({context});", snippet(cx, span, "..")), - Applicability::MachineApplicable, - ); - } + }) + && !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs)) + { + let context = if is_late_pass { "LateContext" } else { "EarlyContext" }; + let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" }; + let span = cx.sess().source_map().span_through_char(item.span, '{'); + span_lint_and_sugg( + cx, + MISSING_MSRV_ATTR_IMPL, + span, + &format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"), + &format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"), + format!("{}\n extract_msrv_attr!({context});", snippet(cx, span, "..")), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs index 2b13fad80665c..326e172146130 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::match_type; use clippy_utils::{is_lint_allowed, method_calls, paths}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::Symbol; declare_clippy_lint! { @@ -40,23 +39,21 @@ impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass { let (method_names, arg_lists, spans) = method_calls(expr, 2); let method_names: Vec<&str> = method_names.iter().map(Symbol::as_str).collect(); - if_chain! { - if let ["expn_data", "outer_expn"] = method_names.as_slice(); - let (self_arg, args) = arg_lists[1]; - if args.is_empty(); - let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); - if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT); - then { - span_lint_and_sugg( - cx, - OUTER_EXPN_EXPN_DATA, - spans[1].with_hi(expr.span.hi()), - "usage of `outer_expn().expn_data()`", - "try", - "outer_expn_data()".to_string(), - Applicability::MachineApplicable, - ); - } + if let ["expn_data", "outer_expn"] = method_names.as_slice() + && let (self_arg, args) = arg_lists[1] + && args.is_empty() + && let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs() + && match_type(cx, self_ty, &paths::SYNTAX_CONTEXT) + { + span_lint_and_sugg( + cx, + OUTER_EXPN_EXPN_DATA, + spans[1].with_hi(expr.span.hi()), + "usage of `outer_expn().expn_data()`", + "try", + "outer_expn_data()".to_string(), + Applicability::MachineApplicable, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs index 5899b94e16ba2..9169e2968eb7d 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs @@ -1,7 +1,7 @@ use rustc_ast::ast::NodeId; use rustc_ast::visit::FnKind; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::Span; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index 81be04659b9fe..70ca1b206b439 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{def_path_def_ids, is_lint_allowed, match_any_def_paths, peel_hir_expr_refs}; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::Applicability; @@ -13,7 +12,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::interpret::{Allocation, GlobalAlloc}; use rustc_middle::mir::ConstValue; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -102,108 +101,106 @@ impl UnnecessaryDefPath { &["clippy_utils", "is_expr_path_def_path"], ]; - if_chain! { - if let [cx_arg, def_arg, args @ ..] = args; - if let ExprKind::Path(path) = &func.kind; - if let Some(id) = cx.qpath_res(path, func.hir_id).opt_def_id(); - if let Some(which_path) = match_any_def_paths(cx, id, PATHS); - let item_arg = if which_path == 4 { &args[1] } else { &args[0] }; + if let [cx_arg, def_arg, args @ ..] = args + && let ExprKind::Path(path) = &func.kind + && let Some(id) = cx.qpath_res(path, func.hir_id).opt_def_id() + && let Some(which_path) = match_any_def_paths(cx, id, PATHS) + && let item_arg = if which_path == 4 { &args[1] } else { &args[0] } // Extract the path to the matched type - if let Some(segments) = path_to_matched_type(cx, item_arg); - let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect(); - if let Some(def_id) = def_path_def_ids(cx, &segments[..]).next(); - then { - // Check if the target item is a diagnostic item or LangItem. - #[rustfmt::skip] - let (msg, item) = if let Some(item_name) - = cx.tcx.diagnostic_items(def_id.krate).id_to_name.get(&def_id) - { - ( - "use of a def path to a diagnostic item", - Item::DiagnosticItem(*item_name), - ) - } else if let Some(item_name) = get_lang_item_name(cx, def_id) { - ( - "use of a def path to a `LangItem`", - Item::LangItem(item_name), - ) - } else { - return; - }; + && let Some(segments) = path_to_matched_type(cx, item_arg) + && let segments = segments.iter().map(|sym| &**sym).collect::>() + && let Some(def_id) = def_path_def_ids(cx, &segments[..]).next() + { + // Check if the target item is a diagnostic item or LangItem. + #[rustfmt::skip] + let (msg, item) = if let Some(item_name) + = cx.tcx.diagnostic_items(def_id.krate).id_to_name.get(&def_id) + { + ( + "use of a def path to a diagnostic item", + Item::DiagnosticItem(*item_name), + ) + } else if let Some(item_name) = get_lang_item_name(cx, def_id) { + ( + "use of a def path to a `LangItem`", + Item::LangItem(item_name), + ) + } else { + return; + }; - let has_ctor = match cx.tcx.def_kind(def_id) { - DefKind::Struct => { - let variant = cx.tcx.adt_def(def_id).non_enum_variant(); - variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public()) - }, - DefKind::Variant => { - let variant = cx.tcx.adt_def(cx.tcx.parent(def_id)).variant_with_id(def_id); - variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public()) - }, - _ => false, - }; + let has_ctor = match cx.tcx.def_kind(def_id) { + DefKind::Struct => { + let variant = cx.tcx.adt_def(def_id).non_enum_variant(); + variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public()) + }, + DefKind::Variant => { + let variant = cx.tcx.adt_def(cx.tcx.parent(def_id)).variant_with_id(def_id); + variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public()) + }, + _ => false, + }; - let mut app = Applicability::MachineApplicable; - let cx_snip = snippet_with_applicability(cx, cx_arg.span, "..", &mut app); - let def_snip = snippet_with_applicability(cx, def_arg.span, "..", &mut app); - let (sugg, with_note) = match (which_path, item) { - // match_def_path - (0, Item::DiagnosticItem(item)) => ( - format!("{cx_snip}.tcx.is_diagnostic_item(sym::{item}, {def_snip})"), - has_ctor, - ), - (0, Item::LangItem(item)) => ( - format!("{cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some({def_snip})"), - has_ctor, - ), - // match_trait_method - (1, Item::DiagnosticItem(item)) => { - (format!("is_trait_method({cx_snip}, {def_snip}, sym::{item})"), false) - }, - // match_type - (2, Item::DiagnosticItem(item)) => ( - format!("is_type_diagnostic_item({cx_snip}, {def_snip}, sym::{item})"), - false, - ), - (2, Item::LangItem(item)) => ( - format!("is_type_lang_item({cx_snip}, {def_snip}, LangItem::{item})"), - false, - ), - // is_expr_path_def_path - (3, Item::DiagnosticItem(item)) if has_ctor => ( - format!("is_res_diag_ctor({cx_snip}, path_res({cx_snip}, {def_snip}), sym::{item})",), - false, - ), - (3, Item::LangItem(item)) if has_ctor => ( - format!("is_res_lang_ctor({cx_snip}, path_res({cx_snip}, {def_snip}), LangItem::{item})",), - false, - ), - (3, Item::DiagnosticItem(item)) => ( - format!("is_path_diagnostic_item({cx_snip}, {def_snip}, sym::{item})"), - false, - ), - (3, Item::LangItem(item)) => ( - format!( - "path_res({cx_snip}, {def_snip}).opt_def_id()\ - .map_or(false, |id| {cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some(id))", - ), - false, + let mut app = Applicability::MachineApplicable; + let cx_snip = snippet_with_applicability(cx, cx_arg.span, "..", &mut app); + let def_snip = snippet_with_applicability(cx, def_arg.span, "..", &mut app); + let (sugg, with_note) = match (which_path, item) { + // match_def_path + (0, Item::DiagnosticItem(item)) => ( + format!("{cx_snip}.tcx.is_diagnostic_item(sym::{item}, {def_snip})"), + has_ctor, + ), + (0, Item::LangItem(item)) => ( + format!("{cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some({def_snip})"), + has_ctor, + ), + // match_trait_method + (1, Item::DiagnosticItem(item)) => { + (format!("is_trait_method({cx_snip}, {def_snip}, sym::{item})"), false) + }, + // match_type + (2, Item::DiagnosticItem(item)) => ( + format!("is_type_diagnostic_item({cx_snip}, {def_snip}, sym::{item})"), + false, + ), + (2, Item::LangItem(item)) => ( + format!("is_type_lang_item({cx_snip}, {def_snip}, LangItem::{item})"), + false, + ), + // is_expr_path_def_path + (3, Item::DiagnosticItem(item)) if has_ctor => ( + format!("is_res_diag_ctor({cx_snip}, path_res({cx_snip}, {def_snip}), sym::{item})",), + false, + ), + (3, Item::LangItem(item)) if has_ctor => ( + format!("is_res_lang_ctor({cx_snip}, path_res({cx_snip}, {def_snip}), LangItem::{item})",), + false, + ), + (3, Item::DiagnosticItem(item)) => ( + format!("is_path_diagnostic_item({cx_snip}, {def_snip}, sym::{item})"), + false, + ), + (3, Item::LangItem(item)) => ( + format!( + "path_res({cx_snip}, {def_snip}).opt_def_id()\ + .map_or(false, |id| {cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some(id))", ), - _ => return, - }; + false, + ), + _ => return, + }; - span_lint_and_then(cx, UNNECESSARY_DEF_PATH, span, msg, |diag| { - diag.span_suggestion(span, "try", sugg, app); - if with_note { - diag.help( - "if this `DefId` came from a constructor expression or pattern then the \ - parent `DefId` should be used instead", - ); - } - }); + span_lint_and_then(cx, UNNECESSARY_DEF_PATH, span, msg, |diag| { + diag.span_suggestion(span, "try", sugg, app); + if with_note { + diag.help( + "if this `DefId` came from a constructor expression or pattern then the \ + parent `DefId` should be used instead", + ); + } + }); - self.linted_def_ids.insert(def_id); - } + self.linted_def_ids.insert(def_id); } } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs index fd51bca9e5be5..a5c4bf474f7aa 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unsorted_clippy_utils_paths.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::ast::{Crate, ItemKind, ModKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index a9a3aaad366e8..ba958c5b3928a 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -7,13 +7,12 @@ use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; use clippy_utils::{get_parent_expr, higher, is_trait_method}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{sym, Span}; #[expect(clippy::module_name_repetitions)] @@ -58,7 +57,7 @@ fn adjusts_to_slice(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { /// Checks if the given expression is a method call to a `Vec` method /// that also exists on slices. If this returns true, it means that /// this expression does not actually require a `Vec` and could just work with an array. -fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { +pub fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { const ALLOWED_METHOD_NAMES: &[&str] = &["len", "as_ptr", "is_empty"]; if let ExprKind::MethodCall(path, ..) = e.kind { @@ -71,21 +70,19 @@ fn is_allowed_vec_method(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { impl<'tcx> LateLintPass<'tcx> for UselessVec { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // search for `&vec![_]` or `vec![_]` expressions where the adjusted type is `&[_]` - if_chain! { - if adjusts_to_slice(cx, expr); - if let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows()); - then { - let (suggest_slice, span) = if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind { - // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.) - (SuggestedType::SliceRef(mutability), expr.span) - } else { - // `expr` is the `vec![_]` expansion, so suggest `[_]` - // and also use the span of the actual `vec![_]` expression - (SuggestedType::Array, expr.span.ctxt().outer_expn_data().call_site) - }; - - self.check_vec_macro(cx, &vec_args, span, suggest_slice); - } + if adjusts_to_slice(cx, expr) + && let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows()) + { + let (suggest_slice, span) = if let ExprKind::AddrOf(BorrowKind::Ref, mutability, _) = expr.kind { + // `expr` is `&vec![_]`, so suggest `&[_]` (or `&mut[_]` resp.) + (SuggestedType::SliceRef(mutability), expr.span) + } else { + // `expr` is the `vec![_]` expansion, so suggest `[_]` + // and also use the span of the actual `vec![_]` expression + (SuggestedType::Array, expr.span.ctxt().outer_expn_data().call_site) + }; + + self.check_vec_macro(cx, &vec_args, span, suggest_slice); } // search for `let foo = vec![_]` expressions where all uses of `foo` @@ -123,15 +120,13 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { } // search for `for _ in vec![…]` - if_chain! { - if let Some(higher::ForLoop { arg, .. }) = higher::ForLoop::hir(expr); - if let Some(vec_args) = higher::VecArgs::hir(cx, arg); - if self.msrv.meets(msrvs::ARRAY_INTO_ITERATOR); - then { - // report the error around the `vec!` not inside `:` - let span = arg.span.ctxt().outer_expn_data().call_site; - self.check_vec_macro(cx, &vec_args, span, SuggestedType::Array); - } + if let Some(higher::ForLoop { arg, .. }) = higher::ForLoop::hir(expr) + && let Some(vec_args) = higher::VecArgs::hir(cx, arg) + && self.msrv.meets(msrvs::ARRAY_INTO_ITERATOR) + { + // report the error around the `vec!` not inside `:` + let span = arg.span.ctxt().outer_expn_data().call_site; + self.check_vec_macro(cx, &vec_args, span, SuggestedType::Array); } } diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs index c8b9402f1ae48..ac3b2bdaf650e 100644 --- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs +++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs @@ -11,7 +11,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{Span, Symbol}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/visibility.rs b/src/tools/clippy/clippy_lints/src/visibility.rs index 8abcc964b890c..83369c66367e7 100644 --- a/src/tools/clippy/clippy_lints/src/visibility.rs +++ b/src/tools/clippy/clippy_lints/src/visibility.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{Item, VisibilityKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::symbol::kw; use rustc_span::Span; diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index d88ede763980d..9b0dac6af2500 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -1,13 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_test_module_or_function; use clippy_utils::source::{snippet, snippet_with_applicability}; -use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Item, ItemKind, PathSegment, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; use rustc_span::{sym, BytePos}; @@ -127,70 +126,55 @@ impl LateLintPass<'_> for WildcardImports { if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) { return; } - if_chain! { - if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; - if self.warn_on_all || !self.check_exceptions(item, use_path.segments); - let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id); - if !used_imports.is_empty(); // Already handled by `unused_imports` - if !used_imports.contains(&kw::Underscore); - then { - let mut applicability = Applicability::MachineApplicable; - let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability); - let (span, braced_glob) = if import_source_snippet.is_empty() { - // This is a `_::{_, *}` import - // In this case `use_path.span` is empty and ends directly in front of the `*`, - // so we need to extend it by one byte. - ( - use_path.span.with_hi(use_path.span.hi() + BytePos(1)), - true, - ) - } else { - // In this case, the `use_path.span` ends right before the `::*`, so we need to - // extend it up to the `*`. Since it is hard to find the `*` in weird - // formattings like `use _ :: *;`, we extend it up to, but not including the - // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we - // can just use the end of the item span - let mut span = use_path.span.with_hi(item.span.hi()); - if snippet(cx, span, "").ends_with(';') { - span = use_path.span.with_hi(item.span.hi() - BytePos(1)); - } - ( - span, false, - ) - }; + if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind + && (self.warn_on_all || !self.check_exceptions(item, use_path.segments)) + && let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id) + && !used_imports.is_empty() // Already handled by `unused_imports` + && !used_imports.contains(&kw::Underscore) + { + let mut applicability = Applicability::MachineApplicable; + let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability); + let (span, braced_glob) = if import_source_snippet.is_empty() { + // This is a `_::{_, *}` import + // In this case `use_path.span` is empty and ends directly in front of the `*`, + // so we need to extend it by one byte. + (use_path.span.with_hi(use_path.span.hi() + BytePos(1)), true) + } else { + // In this case, the `use_path.span` ends right before the `::*`, so we need to + // extend it up to the `*`. Since it is hard to find the `*` in weird + // formattings like `use _ :: *;`, we extend it up to, but not including the + // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we + // can just use the end of the item span + let mut span = use_path.span.with_hi(item.span.hi()); + if snippet(cx, span, "").ends_with(';') { + span = use_path.span.with_hi(item.span.hi() - BytePos(1)); + } + (span, false) + }; - let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(); - let imports_string = if imports.len() == 1 { - imports.pop().unwrap() - } else if braced_glob { - imports.join(", ") - } else { - format!("{{{}}}", imports.join(", ")) - }; + let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(); + let imports_string = if imports.len() == 1 { + imports.pop().unwrap() + } else if braced_glob { + imports.join(", ") + } else { + format!("{{{}}}", imports.join(", ")) + }; - let sugg = if braced_glob { - imports_string - } else { - format!("{import_source_snippet}::{imports_string}") - }; + let sugg = if braced_glob { + imports_string + } else { + format!("{import_source_snippet}::{imports_string}") + }; - // Glob imports always have a single resolution. - let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res[0] { - (ENUM_GLOB_USE, "usage of wildcard import for enum variants") - } else { - (WILDCARD_IMPORTS, "usage of wildcard import") - }; + // Glob imports always have a single resolution. + let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res[0] { + (ENUM_GLOB_USE, "usage of wildcard import for enum variants") + } else { + (WILDCARD_IMPORTS, "usage of wildcard import") + }; - span_lint_and_sugg( - cx, - lint, - span, - message, - "try", - sugg, - applicability, - ); - } + span_lint_and_sugg(cx, lint, span, message, "try", sugg, applicability); } } diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index b6f942a90d3a2..be16d2e5cc301 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -10,7 +10,7 @@ use rustc_ast::{ use rustc_errors::Applicability; use rustc_hir::{Expr, Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::{sym, BytePos, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs index f2f0699ef4892..d3623d6fda442 100644 --- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs +++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs @@ -1,9 +1,8 @@ use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::span_lint_and_help; -use if_chain::if_chain; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does @@ -32,35 +31,30 @@ declare_lint_pass!(ZeroDiv => [ZERO_DIVIDED_BY_ZERO]); impl<'tcx> LateLintPass<'tcx> for ZeroDiv { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // check for instances of 0.0/0.0 - if_chain! { - if let ExprKind::Binary(ref op, left, right) = expr.kind; - if op.node == BinOpKind::Div; + if let ExprKind::Binary(ref op, left, right) = expr.kind + && op.node == BinOpKind::Div // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. - if let Some(lhs_value) = constant_simple(cx, cx.typeck_results(), left); - if let Some(rhs_value) = constant_simple(cx, cx.typeck_results(), right); - if Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value; - if Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value; - then { - // since we're about to suggest a use of f32::NAN or f64::NAN, - // match the precision of the literals that are given. - let float_type = match (lhs_value, rhs_value) { - (Constant::F64(_), _) - | (_, Constant::F64(_)) => "f64", - _ => "f32" - }; - span_lint_and_help( - cx, - ZERO_DIVIDED_BY_ZERO, - expr.span, - "constant division of `0.0` with `0.0` will always result in NaN", - None, - &format!( - "consider using `{float_type}::NAN` if you would like a constant representing NaN", - ), - ); - } + && let Some(lhs_value) = constant_simple(cx, cx.typeck_results(), left) + && let Some(rhs_value) = constant_simple(cx, cx.typeck_results(), right) + && (Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value) + && (Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value) + { + // since we're about to suggest a use of f32::NAN or f64::NAN, + // match the precision of the literals that are given. + let float_type = match (lhs_value, rhs_value) { + (Constant::F64(_), _) | (_, Constant::F64(_)) => "f64", + _ => "f32", + }; + span_lint_and_help( + cx, + ZERO_DIVIDED_BY_ZERO, + expr.span, + "constant division of `0.0` with `0.0` will always result in NaN", + None, + &format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index fee100fe1ead4..fba3808261acf 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item}; -use if_chain::if_chain; use rustc_hir::{self as hir, HirId, ItemKind, Node}; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{Adt, Ty, TypeVisitableExt}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { @@ -46,23 +45,28 @@ declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]); impl LateLintPass<'_> for ZeroSizedMapValues { fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { - if_chain! { - if !hir_ty.span.from_expansion(); - if !in_trait_impl(cx, hir_ty.hir_id); - let ty = ty_from_hir_ty(cx, hir_ty); - if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap); - if let Adt(_, args) = ty.kind(); - let ty = args.type_at(1); + if !hir_ty.span.from_expansion() + && !in_trait_impl(cx, hir_ty.hir_id) + && let ty = ty_from_hir_ty(cx, hir_ty) + && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap)) + && let Adt(_, args) = ty.kind() + && let ty = args.type_at(1) // Fixes https://github.com/rust-lang/rust-clippy/issues/7447 because of // https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/ty/sty.rs#L968 - if !ty.has_escaping_bound_vars(); + && !ty.has_escaping_bound_vars() // Do this to prevent `layout_of` crashing, being unable to fully normalize `ty`. - if is_normalizable(cx, cx.param_env, ty); - if let Ok(layout) = cx.layout_of(ty); - if layout.is_zst(); - then { - span_lint_and_help(cx, ZERO_SIZED_MAP_VALUES, hir_ty.span, "map with zero-sized value type", None, "consider using a set instead"); - } + && is_normalizable(cx, cx.param_env, ty) + && let Ok(layout) = cx.layout_of(ty) + && layout.is_zst() + { + span_lint_and_help( + cx, + ZERO_SIZED_MAP_VALUES, + hir_ty.span, + "map with zero-sized value type", + None, + "consider using a set instead", + ); } } } diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index c9b01a68f42d1..5d23326cec89b 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,14 +1,13 @@ [package] name = "clippy_utils" -version = "0.1.75" +version = "0.1.76" edition = "2021" publish = false [dependencies] clippy_config = { path = "../clippy_config" } arrayvec = { version = "0.7", default-features = false } -if_chain = "1.0" -itertools = "0.10.1" +itertools = "0.11" rustc-semver = "1.1" [features] diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index a2c61e07b70ad..5972278f32fe4 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -188,7 +188,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { Closure(box ast::Closure { binder: lb, capture_clause: lc, - asyncness: la, + coro_kind: la, movability: lm, fn_decl: lf, body: le, @@ -197,7 +197,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { Closure(box ast::Closure { binder: rb, capture_clause: rc, - asyncness: ra, + coro_kind: ra, movability: rm, fn_decl: rf, body: re, @@ -206,7 +206,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { ) => { eq_closure_binder(lb, rb) && lc == rc - && la.is_async() == ra.is_async() + && la.map_or(false, |la| la.is_async()) == ra.map_or(false, |ra| ra.is_async()) && lm == rm && eq_fn_decl(lf, rf) && eq_expr(le, re) @@ -236,7 +236,7 @@ pub fn eq_field(l: &ExprField, r: &ExprField) -> bool { pub fn eq_arm(l: &Arm, r: &Arm) -> bool { l.is_placeholder == r.is_placeholder && eq_pat(&l.pat, &r.pat) - && eq_expr(&l.body, &r.body) + && eq_expr_opt(&l.body, &r.body) && eq_expr_opt(&l.guard, &r.guard) && over(&l.attrs, &r.attrs, eq_attr) } @@ -563,9 +563,18 @@ pub fn eq_fn_sig(l: &FnSig, r: &FnSig) -> bool { eq_fn_decl(&l.decl, &r.decl) && eq_fn_header(&l.header, &r.header) } +fn eq_opt_coro_kind(l: Option, r: Option) -> bool { + match (l, r) { + (Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. })) + | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. })) => true, + (None, None) => true, + _ => false, + } +} + pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool { matches!(l.unsafety, Unsafe::No) == matches!(r.unsafety, Unsafe::No) - && l.asyncness.is_async() == r.asyncness.is_async() + && eq_opt_coro_kind(l.coro_kind, r.coro_kind) && matches!(l.constness, Const::No) == matches!(r.constness, Const::No) && eq_ext(&l.ext, &r.ext) } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index b581a60de6e58..35a8a7920a9dd 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -2,7 +2,7 @@ use crate::source::{get_source_text, walk_span_to_context}; use crate::{clip, is_direct_expn_of, sext, unsext}; -use if_chain::if_chain; + use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; @@ -10,7 +10,7 @@ use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{alloc_range, Scalar}; -use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, List, ScalarInt, Ty, TyCtxt}; +use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ScalarInt, Ty, TyCtxt, UintTy}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::SyntaxContext; @@ -51,6 +51,63 @@ pub enum Constant<'tcx> { Err, } +trait IntTypeBounds: Sized { + type Output: PartialOrd; + + fn min_max(self) -> Option<(Self::Output, Self::Output)>; + fn bits(self) -> Self::Output; + fn ensure_fits(self, val: Self::Output) -> Option { + let (min, max) = self.min_max()?; + (min <= val && val <= max).then_some(val) + } +} +impl IntTypeBounds for UintTy { + type Output = u128; + fn min_max(self) -> Option<(Self::Output, Self::Output)> { + Some(match self { + UintTy::U8 => (u8::MIN.into(), u8::MAX.into()), + UintTy::U16 => (u16::MIN.into(), u16::MAX.into()), + UintTy::U32 => (u32::MIN.into(), u32::MAX.into()), + UintTy::U64 => (u64::MIN.into(), u64::MAX.into()), + UintTy::U128 => (u128::MIN, u128::MAX), + UintTy::Usize => (usize::MIN.try_into().ok()?, usize::MAX.try_into().ok()?), + }) + } + fn bits(self) -> Self::Output { + match self { + UintTy::U8 => 8, + UintTy::U16 => 16, + UintTy::U32 => 32, + UintTy::U64 => 64, + UintTy::U128 => 128, + UintTy::Usize => usize::BITS.into(), + } + } +} +impl IntTypeBounds for IntTy { + type Output = i128; + fn min_max(self) -> Option<(Self::Output, Self::Output)> { + Some(match self { + IntTy::I8 => (i8::MIN.into(), i8::MAX.into()), + IntTy::I16 => (i16::MIN.into(), i16::MAX.into()), + IntTy::I32 => (i32::MIN.into(), i32::MAX.into()), + IntTy::I64 => (i64::MIN.into(), i64::MAX.into()), + IntTy::I128 => (i128::MIN, i128::MAX), + IntTy::Isize => (isize::MIN.try_into().ok()?, isize::MAX.try_into().ok()?), + }) + } + fn bits(self) -> Self::Output { + match self { + IntTy::I8 => 8, + IntTy::I16 => 16, + IntTy::I32 => 32, + IntTy::I64 => 64, + IntTy::I128 => 128, + IntTy::Isize => isize::BITS.into(), + } + } +} + impl<'tcx> PartialEq for Constant<'tcx> { fn eq(&self, other: &Self) -> bool { match (self, other) { @@ -372,27 +429,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { ExprKind::Binary(op, left, right) => self.binop(op, left, right), ExprKind::Call(callee, args) => { // We only handle a few const functions for now. - if_chain! { - if args.is_empty(); - if let ExprKind::Path(qpath) = &callee.kind; - let res = self.typeck_results.qpath_res(qpath, callee.hir_id); - if let Some(def_id) = res.opt_def_id(); - let def_path = self.lcx.get_def_path(def_id); - let def_path: Vec<&str> = def_path.iter().take(4).map(Symbol::as_str).collect(); - if let ["core", "num", int_impl, "max_value"] = *def_path; - then { - let value = match int_impl { - "" => i8::MAX as u128, - "" => i16::MAX as u128, - "" => i32::MAX as u128, - "" => i64::MAX as u128, - "" => i128::MAX as u128, - _ => return None, - }; - Some(Constant::Int(value)) - } else { - None - } + if args.is_empty() + && let ExprKind::Path(qpath) = &callee.kind + && let res = self.typeck_results.qpath_res(qpath, callee.hir_id) + && let Some(def_id) = res.opt_def_id() + && let def_path = self.lcx.get_def_path(def_id) + && let def_path = def_path.iter().take(4).map(Symbol::as_str).collect::>() + && let ["core", "num", int_impl, "max_value"] = *def_path + { + let value = match int_impl { + "" => i8::MAX as u128, + "" => i16::MAX as u128, + "" => i32::MAX as u128, + "" => i64::MAX as u128, + "" => i128::MAX as u128, + _ => return None, + }; + Some(Constant::Int(value)) + } else { + None } }, ExprKind::Index(arr, index, _) => self.index(arr, index), @@ -435,8 +490,15 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { match *o { Int(value) => { let ty::Int(ity) = *ty.kind() else { return None }; + let (min, _) = ity.min_max()?; // sign extend let value = sext(self.lcx.tcx, value, ity); + + // Applying unary - to the most negative value of any signed integer type panics. + if value == min { + return None; + } + let value = value.checked_neg()?; // clear unused bits Some(Int(unsext(self.lcx.tcx, value, ity))) @@ -572,17 +634,33 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { match (l, r) { (Constant::Int(l), Some(Constant::Int(r))) => match *self.typeck_results.expr_ty_opt(left)?.kind() { ty::Int(ity) => { + let (ty_min_value, _) = ity.min_max()?; + let bits = ity.bits(); let l = sext(self.lcx.tcx, l, ity); let r = sext(self.lcx.tcx, r, ity); + + // Using / or %, where the left-hand argument is the smallest integer of a signed integer type and + // the right-hand argument is -1 always panics, even with overflow-checks disabled + if let BinOpKind::Div | BinOpKind::Rem = op.node + && l == ty_min_value + && r == -1 + { + return None; + } + let zext = |n: i128| Constant::Int(unsext(self.lcx.tcx, n, ity)); match op.node { - BinOpKind::Add => l.checked_add(r).map(zext), - BinOpKind::Sub => l.checked_sub(r).map(zext), - BinOpKind::Mul => l.checked_mul(r).map(zext), + // When +, * or binary - create a value greater than the maximum value, or less than + // the minimum value that can be stored, it panics. + BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(zext), + BinOpKind::Sub => l.checked_sub(r).and_then(|n| ity.ensure_fits(n)).map(zext), + BinOpKind::Mul => l.checked_mul(r).and_then(|n| ity.ensure_fits(n)).map(zext), BinOpKind::Div if r != 0 => l.checked_div(r).map(zext), BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext), - BinOpKind::Shr => l.checked_shr(r.try_into().ok()?).map(zext), - BinOpKind::Shl => l.checked_shl(r.try_into().ok()?).map(zext), + // Using << or >> where the right-hand argument is greater than or equal to the number of bits + // in the type of the left-hand argument, or is negative panics. + BinOpKind::Shr if r < bits && !r.is_negative() => l.checked_shr(r.try_into().ok()?).map(zext), + BinOpKind::Shl if r < bits && !r.is_negative() => l.checked_shl(r.try_into().ok()?).map(zext), BinOpKind::BitXor => Some(zext(l ^ r)), BinOpKind::BitOr => Some(zext(l | r)), BinOpKind::BitAnd => Some(zext(l & r)), @@ -595,24 +673,28 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { _ => None, } }, - ty::Uint(_) => match op.node { - BinOpKind::Add => l.checked_add(r).map(Constant::Int), - BinOpKind::Sub => l.checked_sub(r).map(Constant::Int), - BinOpKind::Mul => l.checked_mul(r).map(Constant::Int), - BinOpKind::Div => l.checked_div(r).map(Constant::Int), - BinOpKind::Rem => l.checked_rem(r).map(Constant::Int), - BinOpKind::Shr => l.checked_shr(r.try_into().ok()?).map(Constant::Int), - BinOpKind::Shl => l.checked_shl(r.try_into().ok()?).map(Constant::Int), - BinOpKind::BitXor => Some(Constant::Int(l ^ r)), - BinOpKind::BitOr => Some(Constant::Int(l | r)), - BinOpKind::BitAnd => Some(Constant::Int(l & r)), - BinOpKind::Eq => Some(Constant::Bool(l == r)), - BinOpKind::Ne => Some(Constant::Bool(l != r)), - BinOpKind::Lt => Some(Constant::Bool(l < r)), - BinOpKind::Le => Some(Constant::Bool(l <= r)), - BinOpKind::Ge => Some(Constant::Bool(l >= r)), - BinOpKind::Gt => Some(Constant::Bool(l > r)), - _ => None, + ty::Uint(ity) => { + let bits = ity.bits(); + + match op.node { + BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), + BinOpKind::Sub => l.checked_sub(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), + BinOpKind::Mul => l.checked_mul(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), + BinOpKind::Div => l.checked_div(r).map(Constant::Int), + BinOpKind::Rem => l.checked_rem(r).map(Constant::Int), + BinOpKind::Shr if r < bits => l.checked_shr(r.try_into().ok()?).map(Constant::Int), + BinOpKind::Shl if r < bits => l.checked_shl(r.try_into().ok()?).map(Constant::Int), + BinOpKind::BitXor => Some(Constant::Int(l ^ r)), + BinOpKind::BitOr => Some(Constant::Int(l | r)), + BinOpKind::BitAnd => Some(Constant::Int(l & r)), + BinOpKind::Eq => Some(Constant::Bool(l == r)), + BinOpKind::Ne => Some(Constant::Bool(l != r)), + BinOpKind::Lt => Some(Constant::Bool(l < r)), + BinOpKind::Le => Some(Constant::Bool(l <= r)), + BinOpKind::Ge => Some(Constant::Bool(l >= r)), + BinOpKind::Gt => Some(Constant::Bool(l > r)), + _ => None, + } }, _ => None, }, diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 45c7e3a6e1df7..fa56e5b0ba2bd 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -46,6 +46,7 @@ fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) { /// | ^^^^^^^^^^^^^^^^^^^^^^^ /// ``` pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into, msg: &str) { + #[expect(clippy::disallowed_methods)] cx.struct_span_lint(lint, sp, msg.to_string(), |diag| { docs_link(diag, lint); diag @@ -80,6 +81,7 @@ pub fn span_lint_and_help( help_span: Option, help: &str, ) { + #[expect(clippy::disallowed_methods)] cx.struct_span_lint(lint, span, msg.to_string(), |diag| { let help = help.to_string(); if let Some(help_span) = help_span { @@ -123,6 +125,7 @@ pub fn span_lint_and_note( note_span: Option, note: &str, ) { + #[expect(clippy::disallowed_methods)] cx.struct_span_lint(lint, span, msg.to_string(), |diag| { let note = note.to_string(); if let Some(note_span) = note_span { @@ -145,6 +148,7 @@ where S: Into, F: FnOnce(&mut Diagnostic), { + #[expect(clippy::disallowed_methods)] cx.struct_span_lint(lint, sp, msg.to_string(), |diag| { f(diag); docs_link(diag, lint); @@ -153,6 +157,7 @@ where } pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { + #[expect(clippy::disallowed_methods)] cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| { docs_link(diag, lint); diag @@ -167,6 +172,7 @@ pub fn span_lint_hir_and_then( msg: &str, f: impl FnOnce(&mut Diagnostic), ) { + #[expect(clippy::disallowed_methods)] cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| { f(diag); docs_link(diag, lint); diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index 0bcefba75a7b8..4e71c6483e6aa 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -9,12 +9,13 @@ //! - or-fun-call //! - option-if-let-else +use crate::consts::{constant, FullInt}; use crate::ty::{all_predicates_of, is_copy}; use crate::visitors::is_const_evaluatable; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{Block, Expr, ExprKind, QPath, UnOp}; +use rustc_hir::{BinOpKind, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_middle::ty::adjustment::Adjust; @@ -193,6 +194,12 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS self.eagerness = Lazy; } }, + + // `-i32::MIN` panics with overflow checks + ExprKind::Unary(UnOp::Neg, right) if constant(self.cx, self.cx.typeck_results(), right).is_none() => { + self.eagerness |= NoChange; + }, + // Custom `Deref` impl might have side effects ExprKind::Unary(UnOp::Deref, e) if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() => @@ -207,6 +214,49 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS self.cx.typeck_results().expr_ty(e).kind(), ty::Bool | ty::Int(_) | ty::Uint(_), ) => {}, + + // `>>` and `<<` panic when the right-hand side is greater than or equal to the number of bits in the + // type of the left-hand side, or is negative. + // We intentionally only check if the right-hand isn't a constant, because even if the suggestion would + // overflow with constants, the compiler emits an error for it and the programmer will have to fix it. + // Thus, we would realistically only delay the lint. + ExprKind::Binary(op, _, right) + if matches!(op.node, BinOpKind::Shl | BinOpKind::Shr) + && constant(self.cx, self.cx.typeck_results(), right).is_none() => + { + self.eagerness |= NoChange; + }, + + ExprKind::Binary(op, left, right) + if matches!(op.node, BinOpKind::Div | BinOpKind::Rem) + && let right_ty = self.cx.typeck_results().expr_ty(right) + && let left = constant(self.cx, self.cx.typeck_results(), left) + && let right = constant(self.cx, self.cx.typeck_results(), right) + .and_then(|c| c.int_value(self.cx, right_ty)) + && matches!( + (left, right), + // `1 / x`: x might be zero + (_, None) + // `x / -1`: x might be T::MIN + | (None, Some(FullInt::S(-1))) + ) => + { + self.eagerness |= NoChange; + }, + + // Similar to `>>` and `<<`, we only want to avoid linting entirely if either side is unknown and the + // compiler can't emit an error for an overflowing expression. + // Suggesting eagerness for `true.then(|| i32::MAX + 1)` is okay because the compiler will emit an + // error and it's good to have the eagerness warning up front when the user fixes the logic error. + ExprKind::Binary(op, left, right) + if matches!(op.node, BinOpKind::Add | BinOpKind::Sub | BinOpKind::Mul) + && !self.cx.typeck_results().expr_ty(e).is_floating_point() + && (constant(self.cx, self.cx.typeck_results(), left).is_none() + || constant(self.cx, self.cx.typeck_results(), right).is_none()) => + { + self.eagerness |= NoChange; + }, + ExprKind::Binary(_, lhs, rhs) if self.cx.typeck_results().expr_ty(lhs).is_primitive() && self.cx.typeck_results().expr_ty(rhs).is_primitive() => {}, diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index edea4b3667fed..3135a033648cc 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -5,7 +5,7 @@ use crate::consts::{constant_simple, Constant}; use crate::ty::is_type_diagnostic_item; use crate::{is_expn_of, match_def_path, paths}; -use if_chain::if_chain; + use rustc_ast::ast; use rustc_hir as hir; use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath}; @@ -30,24 +30,22 @@ pub struct ForLoop<'tcx> { impl<'tcx> ForLoop<'tcx> { /// Parses a desugared `for` loop pub fn hir(expr: &Expr<'tcx>) -> Option { - if_chain! { - if let hir::ExprKind::DropTemps(e) = expr.kind; - if let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind; - if let hir::ExprKind::Call(_, [arg]) = iterexpr.kind; - if let hir::ExprKind::Loop(block, ..) = arm.body.kind; - if let [stmt] = block.stmts; - if let hir::StmtKind::Expr(e) = stmt.kind; - if let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind; - if let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind; - then { - return Some(Self { - pat: field.pat, - arg, - body: some_arm.body, - loop_id: arm.body.hir_id, - span: expr.span.ctxt().outer_expn_data().call_site, - }); - } + if let hir::ExprKind::DropTemps(e) = expr.kind + && let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind + && let hir::ExprKind::Call(_, [arg]) = iterexpr.kind + && let hir::ExprKind::Loop(block, ..) = arm.body.kind + && let [stmt] = block.stmts + && let hir::StmtKind::Expr(e) = stmt.kind + && let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind + && let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind + { + return Some(Self { + pat: field.pat, + arg, + body: some_arm.body, + loop_id: arm.body.hir_id, + span: expr.span.ctxt().outer_expn_data().call_site, + }); } None } @@ -277,29 +275,28 @@ impl<'a> VecArgs<'a> { /// Returns the arguments of the `vec!` macro if this expression was expanded /// from `vec!`. pub fn hir(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> Option> { - if_chain! { - if let hir::ExprKind::Call(fun, args) = expr.kind; - if let hir::ExprKind::Path(ref qpath) = fun.kind; - if is_expn_of(fun.span, "vec").is_some(); - if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); - then { - return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 { - // `vec![elem; size]` case - Some(VecArgs::Repeat(&args[0], &args[1])) - } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 { - // `vec![a, b, c]` case - if let hir::ExprKind::Call(_, [arg]) = &args[0].kind - && let hir::ExprKind::Array(args) = arg.kind { - Some(VecArgs::Vec(args)) - } else { - None - } - } else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() { - Some(VecArgs::Vec(&[])) + if let hir::ExprKind::Call(fun, args) = expr.kind + && let hir::ExprKind::Path(ref qpath) = fun.kind + && is_expn_of(fun.span, "vec").is_some() + && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() + { + return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 { + // `vec![elem; size]` case + Some(VecArgs::Repeat(&args[0], &args[1])) + } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 { + // `vec![a, b, c]` case + if let hir::ExprKind::Call(_, [arg]) = &args[0].kind + && let hir::ExprKind::Array(args) = arg.kind + { + Some(VecArgs::Vec(args)) } else { None - }; - } + } + } else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() { + Some(VecArgs::Vec(&[])) + } else { + None + }; } None diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 2a8b2ebd5fbd2..e610ed930505b 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -247,7 +247,7 @@ impl HirEqInterExpr<'_, '_, '_> { res } - #[expect(clippy::similar_names)] + #[expect(clippy::similar_names, clippy::too_many_lines)] pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool { if !self.check_ctxt(left.span.ctxt(), right.span.ctxt()) { return false; @@ -271,9 +271,7 @@ impl HirEqInterExpr<'_, '_, '_> { (&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => { lb == rb && l_mut == r_mut && self.eq_expr(le, re) }, - (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => { - both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name) - }, + (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r), (&ExprKind::Assign(ll, lr, _), &ExprKind::Assign(rl, rr, _)) => { self.inner.allow_side_effects && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }, @@ -294,9 +292,15 @@ impl HirEqInterExpr<'_, '_, '_> { (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => { self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args) }, - (&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) | (&ExprKind::Type(lx, lt), &ExprKind::Type(rx, rt)) => { + (&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) => { self.eq_expr(lx, rx) && self.eq_ty(lt, rt) }, + (&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false, + (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body), + (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => { + both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name) + }, + (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re), (&ExprKind::Field(l_f_exp, ref l_f_ident), &ExprKind::Field(r_f_exp, ref r_f_ident)) => { l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp) }, @@ -329,24 +333,70 @@ impl HirEqInterExpr<'_, '_, '_> { && self.eq_expr(l_receiver, r_receiver) && self.eq_exprs(l_args, r_args) }, + (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => { + self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name) + }, + (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r), (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => { self.eq_expr(le, re) && self.eq_array_length(ll, rl) }, (ExprKind::Ret(l), ExprKind::Ret(r)) => both(l, r, |l, r| self.eq_expr(l, r)), - (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r), (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => { self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && over(lf, rf, |l, r| self.eq_expr_field(l, r)) }, (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup), + (&ExprKind::Type(le, lt), &ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt), (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re), - (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r), - (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re), - (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => { - self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name) - }, - _ => false, + (&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re), + ( + // Else branches for branches above, grouped as per `match_same_arms`. + | &ExprKind::AddrOf(..) + | &ExprKind::Array(..) + | &ExprKind::Assign(..) + | &ExprKind::AssignOp(..) + | &ExprKind::Binary(..) + | &ExprKind::Become(..) + | &ExprKind::Block(..) + | &ExprKind::Break(..) + | &ExprKind::Call(..) + | &ExprKind::Cast(..) + | &ExprKind::ConstBlock(..) + | &ExprKind::Continue(..) + | &ExprKind::DropTemps(..) + | &ExprKind::Field(..) + | &ExprKind::Index(..) + | &ExprKind::If(..) + | &ExprKind::Let(..) + | &ExprKind::Lit(..) + | &ExprKind::Loop(..) + | &ExprKind::Match(..) + | &ExprKind::MethodCall(..) + | &ExprKind::OffsetOf(..) + | &ExprKind::Path(..) + | &ExprKind::Repeat(..) + | &ExprKind::Ret(..) + | &ExprKind::Struct(..) + | &ExprKind::Tup(..) + | &ExprKind::Type(..) + | &ExprKind::Unary(..) + | &ExprKind::Yield(..) + + // --- Special cases that do not have a positive branch. + + // `Err` represents an invalid expression, so let's never assume that + // an invalid expressions is equal to anything. + | &ExprKind::Err(..) + + // For the time being, we always consider that two closures are unequal. + // This behavior may change in the future. + | &ExprKind::Closure(..) + // For the time being, we always consider that two instances of InlineAsm are different. + // This behavior may change in the future. + | &ExprKind::InlineAsm(_) + , _ + ) => false, }; (is_eq && (!self.should_ignore(left) || !self.should_ignore(right))) || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right)) @@ -684,6 +734,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_name(i.ident.name); } }, + ExprKind::Array(v) => { + self.hash_exprs(v); + }, ExprKind::Assign(l, r, _) => { self.hash_expr(l); self.hash_expr(r); @@ -693,6 +746,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(l); self.hash_expr(r); }, + ExprKind::Become(f) => { + self.hash_expr(f); + }, ExprKind::Block(b, _) => { self.hash_block(b); }, @@ -709,9 +765,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(j); } }, - ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => { - self.hash_expr(e); - }, ExprKind::Call(fun, args) => { self.hash_expr(fun); self.hash_exprs(args); @@ -727,6 +780,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { // closures inherit TypeckResults self.hash_expr(self.cx.tcx.hir().body(body).value); }, + ExprKind::ConstBlock(ref l_id) => { + self.hash_body(l_id.body); + }, + ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => { + self.hash_expr(e); + }, ExprKind::Field(e, ref f) => { self.hash_expr(e); self.hash_name(f.name); @@ -788,12 +847,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } }, - ExprKind::OffsetOf(container, fields) => { - self.hash_ty(container); - for field in fields { - self.hash_name(field.name); - } - }, ExprKind::Let(Let { pat, init, ty, .. }) => { self.hash_expr(init); if let Some(ty) = ty { @@ -801,7 +854,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } self.hash_pat(pat); }, - ExprKind::Err(_) => {}, ExprKind::Lit(l) => { l.node.hash(&mut self.s); }, @@ -836,8 +888,14 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(receiver); self.hash_exprs(args); }, - ExprKind::ConstBlock(ref l_id) => { - self.hash_body(l_id.body); + ExprKind::OffsetOf(container, fields) => { + self.hash_ty(container); + for field in fields { + self.hash_name(field.name); + } + }, + ExprKind::Path(ref qpath) => { + self.hash_qpath(qpath); }, ExprKind::Repeat(e, len) => { self.hash_expr(e); @@ -848,12 +906,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } }, - ExprKind::Become(f) => { - self.hash_expr(f); - }, - ExprKind::Path(ref qpath) => { - self.hash_qpath(qpath); - }, ExprKind::Struct(path, fields, ref expr) => { self.hash_qpath(path); @@ -869,13 +921,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { ExprKind::Tup(tup) => { self.hash_exprs(tup); }, - ExprKind::Array(v) => { - self.hash_exprs(v); - }, ExprKind::Unary(lop, le) => { std::mem::discriminant(&lop).hash(&mut self.s); self.hash_expr(le); }, + ExprKind::Err(_) => {}, } } @@ -967,7 +1017,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } e.hash(&mut self.s); }, - PatKind::Wild => {}, + PatKind::Never | PatKind::Wild => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1181dfc0ef95c..f3b63f1cdcf01 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -71,12 +71,12 @@ pub use self::hir_utils::{ both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, HirEqInterExpr, SpanlessEq, SpanlessHash, }; +use core::mem; use core::ops::ControlFlow; use std::collections::hash_map::Entry; use std::hash::BuildHasherDefault; use std::sync::{Mutex, MutexGuard, OnceLock}; -use if_chain::if_chain; use itertools::Itertools; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_data_structures::fx::FxHashMap; @@ -176,14 +176,12 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr /// canonical binding `HirId`. pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { let hir = cx.tcx.hir(); - if_chain! { - if let Some(Node::Pat(pat)) = hir.find(hir_id); - if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..)); - let parent = hir.parent_id(hir_id); - if let Some(Node::Local(local)) = hir.find(parent); - then { - return local.init; - } + if let Some(Node::Pat(pat)) = hir.find(hir_id) + && matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..)) + && let parent = hir.parent_id(hir_id) + && let Some(Node::Local(local)) = hir.find(parent) + { + return local.init; } None } @@ -711,15 +709,13 @@ pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option { /// ``` pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) -> Option<&'tcx TraitRef<'tcx>> { // Get the implemented trait for the current function - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(def_id); let parent_impl = cx.tcx.hir().get_parent_item(hir_id); - if_chain! { - if parent_impl != hir::CRATE_OWNER_ID; - if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl.def_id); - if let hir::ItemKind::Impl(impl_) = &item.kind; - then { - return impl_.of_trait.as_ref(); - } + if parent_impl != hir::CRATE_OWNER_ID + && let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl.def_id) + && let hir::ItemKind::Impl(impl_) = &item.kind + { + return impl_.of_trait.as_ref(); } None } @@ -823,12 +819,14 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath< /// Returns true if the expr is equal to `Default::default` when evaluated. pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> bool { - if_chain! { - if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind; - if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); - if is_diag_trait_item(cx, repl_def_id, sym::Default) - || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath); - then { true } else { false } + if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind + && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id() + && (is_diag_trait_item(cx, repl_def_id, sym::Default) + || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath)) + { + true + } else { + false } } @@ -843,14 +841,14 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { _ => false, }, ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)), - ExprKind::Repeat(x, ArrayLen::Body(len)) => if_chain! { - if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind; - if let LitKind::Int(v, _) = const_lit.node; - if v <= 32 && is_default_equivalent(cx, x); - then { + ExprKind::Repeat(x, ArrayLen::Body(len)) => { + if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind + && let LitKind::Int(v, _) = const_lit.node + && v <= 32 + && is_default_equivalent(cx, x) + { true - } - else { + } else { false } }, @@ -1489,6 +1487,43 @@ pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { } } +/// Checks if the given expression is a part of `let else` +/// returns `true` for both the `init` and the `else` part +pub fn is_inside_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { + let mut child_id = expr.hir_id; + for (parent_id, node) in tcx.hir().parent_iter(child_id) { + if let Node::Local(Local { + init: Some(init), + els: Some(els), + .. + }) = node + && (init.hir_id == child_id || els.hir_id == child_id) + { + return true; + } + + child_id = parent_id; + } + + false +} + +/// Checks if the given expression is the else clause of a `let else` expression +pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { + let mut child_id = expr.hir_id; + for (parent_id, node) in tcx.hir().parent_iter(child_id) { + if let Node::Local(Local { els: Some(els), .. }) = node + && els.hir_id == child_id + { + return true; + } + + child_id = parent_id; + } + + false +} + /// Checks whether the given `Expr` is a range equivalent to a `RangeFull`. /// For the lower bound, this means that: /// - either there is none @@ -1632,13 +1667,13 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option { /// Convenience function to get the return type of a function. pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId) -> Ty<'tcx> { let ret_ty = cx.tcx.fn_sig(fn_def_id).instantiate_identity().output(); - cx.tcx.erase_late_bound_regions(ret_ty) + cx.tcx.instantiate_bound_regions_with_erased(ret_ty) } /// Convenience function to get the nth argument type of a function. pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId, nth: usize) -> Ty<'tcx> { let arg = cx.tcx.fn_sig(fn_def_id).instantiate_identity().input(nth); - cx.tcx.erase_late_bound_regions(arg) + cx.tcx.instantiate_bound_regions_with_erased(arg) } /// Checks if an expression is constructing a tuple-like enum variant or struct @@ -1671,7 +1706,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { } match pat.kind { - PatKind::Wild => false, + PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable. PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)), PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), PatKind::Lit(..) | PatKind::Range(..) => true, @@ -1736,15 +1771,13 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl It /// operator or the `try` macro. pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { - if_chain! { - if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind; - if ddpos.as_opt_usize().is_none(); - if is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultOk); - if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind; - if path_to_local_id(arm.body, hir_id); - then { - return true; - } + if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind + && ddpos.as_opt_usize().is_none() + && is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultOk) + && let PatKind::Binding(_, hir_id, _, None) = pat[0].kind + && path_to_local_id(arm.body, hir_id) + { + return true; } false } @@ -1763,14 +1796,12 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc return Some(expr); } - if_chain! { - if arms.len() == 2; - if arms[0].guard.is_none(); - if arms[1].guard.is_none(); - if (is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) || (is_ok(cx, &arms[1]) && is_err(cx, &arms[0])); - then { - return Some(expr); - } + if arms.len() == 2 + && arms[0].guard.is_none() + && arms[1].guard.is_none() + && ((is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) || (is_ok(cx, &arms[1]) && is_err(cx, &arms[0]))) + { + return Some(expr); } } @@ -1887,14 +1918,12 @@ pub fn match_function_call<'tcx>( expr: &'tcx Expr<'_>, path: &[&str], ) -> Option<&'tcx [Expr<'tcx>]> { - if_chain! { - if let ExprKind::Call(fun, args) = expr.kind; - if let ExprKind::Path(ref qpath) = fun.kind; - if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id(); - if match_def_path(cx, fun_def_id, path); - then { - return Some(args); - } + if let ExprKind::Call(fun, args) = expr.kind + && let ExprKind::Path(ref qpath) = fun.kind + && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() + && match_def_path(cx, fun_def_id, path) + { + return Some(args); }; None } @@ -1904,13 +1933,11 @@ pub fn match_function_call_with_def_id<'tcx>( expr: &'tcx Expr<'_>, fun_def_id: DefId, ) -> Option<&'tcx [Expr<'tcx>]> { - if_chain! { - if let ExprKind::Call(fun, args) = expr.kind; - if let ExprKind::Path(ref qpath) = fun.kind; - if cx.qpath_res(qpath, fun.hir_id).opt_def_id() == Some(fun_def_id); - then { - return Some(args); - } + if let ExprKind::Call(fun, args) = expr.kind + && let ExprKind::Path(ref qpath) = fun.kind + && cx.qpath_res(qpath, fun.hir_id).opt_def_id() == Some(fun_def_id) + { + return Some(args); }; None } @@ -2008,10 +2035,10 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t // check if expr is calling method or function with #[must_use] attribute pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let did = match expr.kind { - ExprKind::Call(path, _) => if_chain! { - if let ExprKind::Path(ref qpath) = path.kind; - if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id); - then { + ExprKind::Call(path, _) => { + if let ExprKind::Path(ref qpath) = path.kind + && let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id) + { Some(did) } else { None @@ -2034,6 +2061,18 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead. fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { fn check_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<'_>) -> bool { + if cx + .typeck_results() + .pat_binding_modes() + .get(pat.hir_id) + .is_some_and(|mode| matches!(mode, BindingMode::BindByReference(_))) + { + // If a tuple `(x, y)` is of type `&(i32, i32)`, then due to match ergonomics, + // the inner patterns become references. Don't consider this the identity function + // as that changes types. + return false; + } + match (pat.kind, expr.kind) { (PatKind::Binding(_, id, _, _), _) => { path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty() @@ -2071,14 +2110,12 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { }, _, ) => { - if_chain! { - if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind; - if let ExprKind::Ret(Some(ret_val)) = e.kind; - then { - expr = ret_val; - } else { - return false; - } + if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind + && let ExprKind::Ret(Some(ret_val)) = e.kind + { + expr = ret_val; + } else { + return false; } }, _ => return check_pat(cx, param.pat, expr), @@ -2530,7 +2567,7 @@ pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { tcx.has_attr(def_id, sym::cfg) || hir - .parent_iter(hir.local_def_id_to_hir_id(def_id)) + .parent_iter(tcx.local_def_id_to_hir_id(def_id)) .flat_map(|(parent_id, _)| hir.attrs(parent_id)) .any(|attr| attr.has_name(sym::cfg)) } @@ -2650,7 +2687,7 @@ impl<'tcx> ExprUseNode<'tcx> { .and(Binder::dummy(cx.tcx.type_of(id).instantiate_identity())), )), Self::Return(id) => { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(id.def_id); + let hir_id = cx.tcx.local_def_id_to_hir_id(id.def_id); if let Some(Node::Expr(Expr { kind: ExprKind::Closure(c), .. @@ -2974,3 +3011,248 @@ pub fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: i _ => false, } } + +#[derive(Clone, Copy)] +pub enum RequiresSemi { + Yes, + No, +} +impl RequiresSemi { + pub fn requires_semi(self) -> bool { + matches!(self, Self::Yes) + } +} + +/// Check if the expression return `!`, a type coerced from `!`, or could return `!` if the final +/// expression were turned into a statement. +#[expect(clippy::too_many_lines)] +pub fn is_never_expr<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option { + struct BreakTarget { + id: HirId, + unused: bool, + } + + struct V<'cx, 'tcx> { + cx: &'cx LateContext<'tcx>, + break_targets: Vec, + break_targets_for_result_ty: u32, + in_final_expr: bool, + requires_semi: bool, + is_never: bool, + } + + impl<'tcx> V<'_, 'tcx> { + fn push_break_target(&mut self, id: HirId) { + self.break_targets.push(BreakTarget { id, unused: true }); + self.break_targets_for_result_ty += u32::from(self.in_final_expr); + } + } + + impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> { + fn visit_expr(&mut self, e: &'tcx Expr<'_>) { + // Note: Part of the complexity here comes from the fact that + // coercions are applied to the innermost expression. + // e.g. In `let x: u32 = { break () };` the never-to-any coercion + // is applied to the break expression. This means we can't just + // check the block's type as it will be `u32` despite the fact + // that the block always diverges. + + // The rest of the complexity comes from checking blocks which + // syntactically return a value, but will always diverge before + // reaching that point. + // e.g. In `let x = { foo(panic!()) };` the block's type will be the + // return type of `foo` even though it will never actually run. This + // can be trivially fixed by adding a semicolon after the call, but + // we must first detect that a semicolon is needed to make that + // suggestion. + + if self.is_never && self.break_targets.is_empty() { + if self.in_final_expr && !self.requires_semi { + // This expression won't ever run, but we still need to check + // if it can affect the type of the final expression. + match e.kind { + ExprKind::DropTemps(e) => self.visit_expr(e), + ExprKind::If(_, then, Some(else_)) => { + self.visit_expr(then); + self.visit_expr(else_); + }, + ExprKind::Match(_, arms, _) => { + for arm in arms { + self.visit_expr(arm.body); + } + }, + ExprKind::Loop(b, ..) => { + self.push_break_target(e.hir_id); + self.in_final_expr = false; + self.visit_block(b); + self.break_targets.pop(); + }, + ExprKind::Block(b, _) => { + if b.targeted_by_break { + self.push_break_target(b.hir_id); + self.visit_block(b); + self.break_targets.pop(); + } else { + self.visit_block(b); + } + }, + _ => { + self.requires_semi = !self.cx.typeck_results().expr_ty(e).is_never(); + }, + } + } + return; + } + match e.kind { + ExprKind::DropTemps(e) => self.visit_expr(e), + ExprKind::Ret(None) | ExprKind::Continue(_) => self.is_never = true, + ExprKind::Ret(Some(e)) | ExprKind::Become(e) => { + self.in_final_expr = false; + self.visit_expr(e); + self.is_never = true; + }, + ExprKind::Break(dest, e) => { + if let Some(e) = e { + self.in_final_expr = false; + self.visit_expr(e); + } + if let Ok(id) = dest.target_id + && let Some((i, target)) = self + .break_targets + .iter_mut() + .enumerate() + .find(|(_, target)| target.id == id) + { + target.unused &= self.is_never; + if i < self.break_targets_for_result_ty as usize { + self.requires_semi = true; + } + } + self.is_never = true; + }, + ExprKind::If(cond, then, else_) => { + let in_final_expr = mem::replace(&mut self.in_final_expr, false); + self.visit_expr(cond); + self.in_final_expr = in_final_expr; + + if self.is_never { + self.visit_expr(then); + if let Some(else_) = else_ { + self.visit_expr(else_); + } + } else { + self.visit_expr(then); + let is_never = mem::replace(&mut self.is_never, false); + if let Some(else_) = else_ { + self.visit_expr(else_); + self.is_never &= is_never; + } + } + }, + ExprKind::Match(scrutinee, arms, _) => { + let in_final_expr = mem::replace(&mut self.in_final_expr, false); + self.visit_expr(scrutinee); + self.in_final_expr = in_final_expr; + + if self.is_never { + for arm in arms { + self.visit_arm(arm); + } + } else { + let mut is_never = true; + for arm in arms { + self.is_never = false; + if let Some(guard) = arm.guard { + let in_final_expr = mem::replace(&mut self.in_final_expr, false); + self.visit_expr(guard.body()); + self.in_final_expr = in_final_expr; + // The compiler doesn't consider diverging guards as causing the arm to diverge. + self.is_never = false; + } + self.visit_expr(arm.body); + is_never &= self.is_never; + } + self.is_never = is_never; + } + }, + ExprKind::Loop(b, _, _, _) => { + self.push_break_target(e.hir_id); + self.in_final_expr = false; + self.visit_block(b); + self.is_never = self.break_targets.pop().unwrap().unused; + }, + ExprKind::Block(b, _) => { + if b.targeted_by_break { + self.push_break_target(b.hir_id); + self.visit_block(b); + self.is_never &= self.break_targets.pop().unwrap().unused; + } else { + self.visit_block(b); + } + }, + _ => { + self.in_final_expr = false; + walk_expr(self, e); + self.is_never |= self.cx.typeck_results().expr_ty(e).is_never(); + }, + } + } + + fn visit_block(&mut self, b: &'tcx Block<'_>) { + let in_final_expr = mem::replace(&mut self.in_final_expr, false); + for s in b.stmts { + self.visit_stmt(s); + } + self.in_final_expr = in_final_expr; + if let Some(e) = b.expr { + self.visit_expr(e); + } + } + + fn visit_local(&mut self, l: &'tcx Local<'_>) { + if let Some(e) = l.init { + self.visit_expr(e); + } + if let Some(else_) = l.els { + let is_never = self.is_never; + self.visit_block(else_); + self.is_never = is_never; + } + } + + fn visit_arm(&mut self, arm: &Arm<'tcx>) { + if let Some(guard) = arm.guard { + let in_final_expr = mem::replace(&mut self.in_final_expr, false); + self.visit_expr(guard.body()); + self.in_final_expr = in_final_expr; + } + self.visit_expr(arm.body); + } + } + + if cx.typeck_results().expr_ty(e).is_never() { + Some(RequiresSemi::No) + } else if let ExprKind::Block(b, _) = e.kind + && !b.targeted_by_break + && b.expr.is_none() + { + // If a block diverges without a final expression then it's type is `!`. + None + } else { + let mut v = V { + cx, + break_targets: Vec::new(), + break_targets_for_result_ty: 0, + in_final_expr: true, + requires_semi: false, + is_never: false, + }; + v.visit_expr(e); + v.is_never + .then_some(if v.requires_semi && matches!(e.kind, ExprKind::Block(..)) { + RequiresSemi::Yes + } else { + RequiresSemi::No + }) + } +} diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index 5bca554378e74..0a820a1754cae 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -32,7 +32,15 @@ pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncRead pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"]; pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"]; pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"]; +pub const HASHMAP_ITER: [&str; 5] = ["std", "collections", "hash", "map", "Iter"]; +pub const HASHMAP_ITER_MUT: [&str; 5] = ["std", "collections", "hash", "map", "IterMut"]; +pub const HASHMAP_KEYS: [&str; 5] = ["std", "collections", "hash", "map", "Keys"]; +pub const HASHMAP_VALUES: [&str; 5] = ["std", "collections", "hash", "map", "Values"]; +pub const HASHMAP_DRAIN: [&str; 5] = ["std", "collections", "hash", "map", "Drain"]; +pub const HASHMAP_VALUES_MUT: [&str; 5] = ["std", "collections", "hash", "map", "ValuesMut"]; +pub const HASHSET_ITER_TY: [&str; 5] = ["std", "collections", "hash", "set", "Iter"]; pub const HASHSET_ITER: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "iter"]; +pub const HASHSET_DRAIN: [&str; 5] = ["std", "collections", "hash", "set", "Drain"]; pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"]; pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"]; pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"]; @@ -99,3 +107,4 @@ pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"]; pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"]; #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so pub const BOOL_THEN: [&str; 4] = ["core", "bool", "", "then"]; +pub const ALLOCATOR_GLOBAL: [&str; 3] = ["alloc", "alloc", "Global"]; diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index db79dd788018e..9b2bc8df1f307 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -159,7 +159,7 @@ impl<'a> Sugg<'a> { Sugg::BinOp(hirbinop2assignop(op), get_snippet(lhs.span), get_snippet(rhs.span)) }, hir::ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp( - AssocOp::from_ast_binop(op.node.into()), + AssocOp::from_ast_binop(op.node), get_snippet(lhs.span), get_snippet(rhs.span), ), @@ -380,10 +380,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { | AssocOp::NotEqual | AssocOp::Greater | AssocOp::GreaterEqual => { - format!( - "{lhs} {} {rhs}", - op.to_ast_binop().expect("Those are AST ops").to_string() - ) + format!("{lhs} {} {rhs}", op.to_ast_binop().expect("Those are AST ops").as_str()) }, AssocOp::Assign => format!("{lhs} = {rhs}"), AssocOp::AssignOp(op) => { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 7eff93881b26e..1e748a46922cb 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -694,7 +694,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option { let decl = id .as_local() - .and_then(|id| cx.tcx.hir().fn_decl_by_hir_id(cx.tcx.hir().local_def_id_to_hir_id(id))); + .and_then(|id| cx.tcx.hir().fn_decl_by_hir_id(cx.tcx.local_def_id_to_hir_id(id))); Some(ExprFnSig::Closure(decl, subs.as_closure().sig())) }, ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).instantiate(cx.tcx, subs), Some(id))), @@ -890,7 +890,7 @@ pub fn for_each_top_level_late_bound_region( impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow> TypeVisitor> for V { type BreakTy = B; fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow { - if let RegionKind::ReLateBound(idx, bound) = r.kind() + if let RegionKind::ReBound(idx, bound) = r.kind() && idx.as_u32() == self.index { (self.f)(bound) @@ -1160,11 +1160,16 @@ pub fn make_normalized_projection<'tcx>( ) -> Option> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] - if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_late_bound_regions()) { + if let Some((i, arg)) = ty + .args + .iter() + .enumerate() + .find(|(_, arg)| arg.has_escaping_bound_vars()) + { debug_assert!( false, "args contain late-bound region at index `{i}` which can't be normalized.\n\ - use `TyCtxt::erase_late_bound_regions`\n\ + use `TyCtxt::instantiate_bound_regions_with_erased`\n\ note: arg is `{arg:#?}`", ); return None; @@ -1233,11 +1238,16 @@ pub fn make_normalized_projection_with_regions<'tcx>( ) -> Option> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] - if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_late_bound_regions()) { + if let Some((i, arg)) = ty + .args + .iter() + .enumerate() + .find(|(_, arg)| arg.has_escaping_bound_vars()) + { debug_assert!( false, "args contain late-bound region at index `{i}` which can't be normalized.\n\ - use `TyCtxt::erase_late_bound_regions`\n\ + use `TyCtxt::instantiate_bound_regions_with_erased`\n\ note: arg is `{arg:#?}`", ); return None; @@ -1266,3 +1276,8 @@ pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx> Err(_) => ty, } } + +/// Checks if the type is `core::mem::ManuallyDrop<_>` +pub fn is_manually_drop(ty: Ty<'_>) -> bool { + ty.ty_adt_def().map_or(false, AdtDef::is_manually_drop) +} diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs index 76fa15e15880e..da71fc3aaa87f 100644 --- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs @@ -170,19 +170,18 @@ fn qpath_certainty(cx: &LateContext<'_>, qpath: &QPath<'_>, resolves_to_type: bo path_segment_certainty(cx, type_certainty(cx, ty), path_segment, resolves_to_type) }, - QPath::LangItem(lang_item, _, _) => { - cx.tcx - .lang_items() - .get(*lang_item) - .map_or(Certainty::Uncertain, |def_id| { - let generics = cx.tcx.generics_of(def_id); - if generics.parent_count == 0 && generics.params.is_empty() { - Certainty::Certain(if resolves_to_type { Some(def_id) } else { None }) - } else { - Certainty::Uncertain - } - }) - }, + QPath::LangItem(lang_item, ..) => cx + .tcx + .lang_items() + .get(*lang_item) + .map_or(Certainty::Uncertain, |def_id| { + let generics = cx.tcx.generics_of(def_id); + if generics.parent_count == 0 && generics.params.is_empty() { + Certainty::Certain(if resolves_to_type { Some(def_id) } else { None }) + } else { + Certainty::Uncertain + } + }), }; debug_assert!(resolves_to_type || certainty.to_def_id().is_none()); certainty diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml index beea9fd00e7a9..af123e107d5c7 100644 --- a/src/tools/clippy/declare_clippy_lint/Cargo.toml +++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.75" +version = "0.1.76" edition = "2021" publish = false @@ -8,7 +8,7 @@ publish = false proc-macro = true [dependencies] -itertools = "0.10.1" +itertools = "0.11" quote = "1.0.21" syn = "2.0" diff --git a/src/tools/clippy/declare_clippy_lint/src/lib.rs b/src/tools/clippy/declare_clippy_lint/src/lib.rs index dc3037f666926..25b2fc9395cd9 100644 --- a/src/tools/clippy/declare_clippy_lint/src/lib.rs +++ b/src/tools/clippy/declare_clippy_lint/src/lib.rs @@ -148,7 +148,7 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream { let category_variant = format_ident!("{category}"); let output = quote! { - declare_tool_lint! { + rustc_session::declare_tool_lint! { #(#attrs)* pub clippy::#name, #level, diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs index 58cb42316fd2e..841b605f5fbd9 100644 --- a/src/tools/clippy/lintcheck/src/main.rs +++ b/src/tools/clippy/lintcheck/src/main.rs @@ -309,7 +309,7 @@ impl Crate { target_dir_index: &AtomicUsize, total_crates_to_lint: usize, config: &LintcheckConfig, - lint_filter: &Vec, + lint_filter: &[String], server: &Option, ) -> Vec { // advance the atomic index by one @@ -728,7 +728,7 @@ fn read_stats_from_file(file_path: &Path) -> HashMap { } /// print how lint counts changed between runs -fn print_stats(old_stats: HashMap, new_stats: HashMap<&String, usize>, lint_filter: &Vec) { +fn print_stats(old_stats: HashMap, new_stats: HashMap<&String, usize>, lint_filter: &[String]) { let same_in_both_hashmaps = old_stats .iter() .filter(|(old_key, old_val)| new_stats.get::<&String>(old_key) == Some(old_val)) diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 293fcbf39928f..684cf4574b9a9 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-11-02" +channel = "nightly-2023-12-01" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 7bb49d08da655..49f0cad08e014 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -148,7 +148,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { } let conf = clippy_config::Conf::read(sess, &conf_path); - clippy_lints::register_plugins(lint_store, sess, conf); + clippy_lints::register_lints(lint_store, conf); clippy_lints::register_pre_expansion_lints(lint_store, conf); clippy_lints::register_renamed(lint_store); })); @@ -183,7 +183,7 @@ pub fn main() { // as simple as moving the call from the hook to main, because `install_ice_hook` doesn't // accept a generic closure. let version_info = rustc_tools_util::get_version_info!(); - handler.note_without_error(format!("Clippy version: {version_info}")); + handler.note(format!("Clippy version: {version_info}")); }); exit(rustc_driver::catch_with_exit_code(move || { diff --git a/src/tools/clippy/tests/integration.rs b/src/tools/clippy/tests/integration.rs index 031982edbe9e1..267f095f9c20f 100644 --- a/src/tools/clippy/tests/integration.rs +++ b/src/tools/clippy/tests/integration.rs @@ -69,15 +69,15 @@ fn integration_test() { // debug: eprintln!("{stderr}"); - // this is an internal test to make sure we would correctly panic on a delay_span_bug + // this is an internal test to make sure we would correctly panic on a span_delayed_bug if repo_name == "matthiaskrgr/clippy_ci_panic_test" { // we need to kind of switch around our logic here: // if we find a panic, everything is fine, if we don't panic, SOMETHING is broken about our testing - // the repo basically just contains a delay_span_bug that forces rustc/clippy to panic: + // the repo basically just contains a span_delayed_bug that forces rustc/clippy to panic: /* #![feature(rustc_attrs)] - #[rustc_error(delay_span_bug_from_inside_query)] + #[rustc_error(span_delayed_bug_from_inside_query)] fn main() {} */ @@ -86,7 +86,7 @@ fn integration_test() { return; } - panic!("panic caused by delay_span_bug was NOT detected! Something is broken!"); + panic!("panic caused by span_delayed_bug was NOT detected! Something is broken!"); } if let Some(backtrace_start) = stderr.find("error: internal compiler error") { diff --git a/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr b/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr index ca26b649f986a..595e4c138b472 100644 --- a/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr +++ b/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr @@ -18,5 +18,5 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::default_deprecation_reason)]` implied by `#[deny(clippy::internal)]` = note: this error originates in the macro `declare_deprecated_lint` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-internal/default_lint.stderr b/src/tools/clippy/tests/ui-internal/default_lint.stderr index 8961bd4624f45..ab2470210254a 100644 --- a/src/tools/clippy/tests/ui-internal/default_lint.stderr +++ b/src/tools/clippy/tests/ui-internal/default_lint.stderr @@ -17,5 +17,5 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]` = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs b/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs new file mode 100644 index 0000000000000..3155c0235ffd0 --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs @@ -0,0 +1,27 @@ +#![feature(rustc_private)] + +extern crate rustc_errors; +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; + +use rustc_errors::{DiagnosticMessage, MultiSpan}; +use rustc_hir::hir_id::HirId; +use rustc_lint::{Lint, LintContext}; +use rustc_middle::ty::TyCtxt; + +pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into, msg: impl Into) { + cx.struct_span_lint(lint, span, msg, |b| b); +} + +pub fn b( + tcx: TyCtxt<'_>, + lint: &'static Lint, + hir_id: HirId, + span: impl Into, + msg: impl Into, +) { + tcx.struct_span_lint_hir(lint, hir_id, span, msg, |b| b); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr new file mode 100644 index 0000000000000..76c487fb1352e --- /dev/null +++ b/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr @@ -0,0 +1,17 @@ +error: use of a disallowed method `rustc_lint::context::LintContext::struct_span_lint` + --> $DIR/disallow_struct_span_lint.rs:14:5 + | +LL | cx.struct_span_lint(lint, span, msg, |b| b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::disallowed-methods` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` + +error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::struct_span_lint_hir` + --> $DIR/disallow_struct_span_lint.rs:24:5 + | +LL | tcx.struct_span_lint_hir(lint, hir_id, span, msg, |b| b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui-internal/if_chain_style.rs b/src/tools/clippy/tests/ui-internal/if_chain_style.rs deleted file mode 100644 index b462b20e04c67..0000000000000 --- a/src/tools/clippy/tests/ui-internal/if_chain_style.rs +++ /dev/null @@ -1,97 +0,0 @@ -#![warn(clippy::if_chain_style)] -#![allow( - clippy::needless_if, - clippy::no_effect, - clippy::nonminimal_bool, - clippy::missing_clippy_version_attribute -)] - -extern crate if_chain; - -use if_chain::if_chain; - -fn main() { - if true { - let x = ""; - // `if_chain!` inside `if` - if_chain! { - if true; - if true; - then {} - } - } - if_chain! { - if true - // multi-line AND'ed conditions - && false; - if let Some(1) = Some(1); - // `let` before `then` - let x = ""; - then { - (); - } - } - if_chain! { - // single `if` condition - if true; - then { - let x = ""; - // nested if - if true {} - } - } - if_chain! { - // starts with `let ..` - let x = ""; - if let Some(1) = Some(1); - then { - let x = ""; - let x = ""; - // nested if_chain! - if_chain! { - if true; - if true; - then {} - } - } - } -} - -fn negative() { - if true { - (); - if_chain! { - if true; - if true; - then { (); } - } - } - if_chain! { - if true; - let x = ""; - if true; - then { (); } - } - if_chain! { - if true; - if true; - then { - if true { 1 } else { 2 } - } else { - 3 - } - }; - if true { - if_chain! { - if true; - if true; - then {} - } - } else if false { - if_chain! { - if true; - if false; - then {} - } - } -} diff --git a/src/tools/clippy/tests/ui-internal/if_chain_style.stderr b/src/tools/clippy/tests/ui-internal/if_chain_style.stderr deleted file mode 100644 index ea04955323d18..0000000000000 --- a/src/tools/clippy/tests/ui-internal/if_chain_style.stderr +++ /dev/null @@ -1,86 +0,0 @@ -error: this `if` can be part of the inner `if_chain!` - --> $DIR/if_chain_style.rs:14:5 - | -LL | / if true { -LL | | let x = ""; -LL | | // `if_chain!` inside `if` -LL | | if_chain! { -... | -LL | | } -LL | | } - | |_____^ - | -help: this `let` statement can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:15:9 - | -LL | let x = ""; - | ^^^^^^^^^^^ - = note: `-D clippy::if-chain-style` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::if_chain_style)]` - -error: `if a && b;` should be `if a; if b;` - --> $DIR/if_chain_style.rs:24:12 - | -LL | if true - | ____________^ -LL | | // multi-line AND'ed conditions -LL | | && false; - | |____________________^ - -error: `let` expression should be inside `then { .. }` - --> $DIR/if_chain_style.rs:29:9 - | -LL | let x = ""; - | ^^^^^^^^^^^ - -error: this `if` can be part of the outer `if_chain!` - --> $DIR/if_chain_style.rs:40:13 - | -LL | if true {} - | ^^^^^^^^^^ - | -help: this `let` statement can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:38:13 - | -LL | let x = ""; - | ^^^^^^^^^^^ - -error: `if_chain!` only has one `if` - --> $DIR/if_chain_style.rs:34:5 - | -LL | / if_chain! { -LL | | // single `if` condition -LL | | if true; -LL | | then { -... | -LL | | } -LL | | } - | |_____^ - | - = note: this error originates in the macro `__if_chain` which comes from the expansion of the macro `if_chain` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: `let` expression should be above the `if_chain!` - --> $DIR/if_chain_style.rs:45:9 - | -LL | let x = ""; - | ^^^^^^^^^^^ - -error: this `if_chain!` can be merged with the outer `if_chain!` - --> $DIR/if_chain_style.rs:51:13 - | -LL | / if_chain! { -LL | | if true; -LL | | if true; -LL | | then {} -LL | | } - | |_____________^ - | -help: these `let` statements can also be in the `if_chain!` - --> $DIR/if_chain_style.rs:48:13 - | -LL | / let x = ""; -LL | | let x = ""; - | |_______________________^ - -error: aborting due to 7 previous errors - diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr index de04920b8e6f6..de55876b1d709 100644 --- a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr +++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr @@ -17,5 +17,5 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::lint_without_lint_pass)]` implied by `#[deny(clippy::internal)]` = note: this error originates in the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr index e41ace4729d82..0d5b01325994b 100644 --- a/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr @@ -11,5 +11,5 @@ LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::outer_expn_expn_data)]` implied by `#[deny(clippy::internal)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr b/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr index f7d53763a4388..c308b7aa02398 100644 --- a/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr +++ b/src/tools/clippy/tests/ui-toml/bad_toml/conf_bad_toml.stderr @@ -4,5 +4,5 @@ error: error reading Clippy's configuration file: expected `.`, `=` LL | fn this_is_obviously(not: a, toml: file) { | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr b/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr index fb0a14081524b..1bcde2f30ed62 100644 --- a/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr +++ b/src/tools/clippy/tests/ui-toml/bad_toml_type/conf_bad_type.stderr @@ -4,5 +4,5 @@ error: error reading Clippy's configuration file: invalid type: integer `42`, ex LL | disallowed-names = 42 | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr b/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr index a21952c0e7ada..08fdb2d2dc322 100644 --- a/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr +++ b/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr @@ -20,5 +20,5 @@ LL | fn cognitive_complexity() { = note: `-D clippy::cognitive-complexity` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::cognitive_complexity)]` -error: aborting due to previous error; 2 warnings emitted +error: aborting due to 1 previous error; 2 warnings emitted diff --git a/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.stderr b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.stderr index 6f817a3fdde42..4510275c9a9a4 100644 --- a/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.stderr +++ b/src/tools/clippy/tests/ui-toml/decimal_literal_representation/decimal_literal_representation.stderr @@ -7,5 +7,5 @@ LL | let _ = 16777215; = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::decimal_literal_representation)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.stderr b/src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.stderr index d9f25a3eee50a..a5fece575f842 100644 --- a/src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.stderr +++ b/src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.stderr @@ -7,5 +7,5 @@ LL | let ducks = ["quack", "quack"]; = note: `-D clippy::disallowed-names` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::disallowed_names)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.stderr b/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.stderr index 31bb5ee3514a5..e83027e4e28ca 100644 --- a/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.stderr +++ b/src/tools/clippy/tests/ui-toml/disallowed_script_idents/disallowed_script_idents.stderr @@ -7,5 +7,5 @@ LL | let カウンタ = 10; = note: `-D clippy::disallowed-script-idents` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::disallowed_script_idents)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/doc_valid_idents_append/doc_markdown.stderr b/src/tools/clippy/tests/ui-toml/doc_valid_idents_append/doc_markdown.stderr index 92b0350581d33..877ca726fee0c 100644 --- a/src/tools/clippy/tests/ui-toml/doc_valid_idents_append/doc_markdown.stderr +++ b/src/tools/clippy/tests/ui-toml/doc_valid_idents_append/doc_markdown.stderr @@ -11,5 +11,5 @@ help: try LL | /// `TestItemThingyOfCoolness` might sound cool but is not on the list and should be linted. | ~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr b/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr index 7c56dfdb948e9..3f2086b5ecb61 100644 --- a/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr +++ b/src/tools/clippy/tests/ui-toml/duplicated_keys/duplicated_keys.stderr @@ -4,5 +4,5 @@ error: error reading Clippy's configuration file: duplicate key `cognitive-compl LL | cognitive-complexity-threshold = 4 | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr b/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr index 0af8c0add6c6a..3c38396338802 100644 --- a/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr +++ b/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated/duplicated_keys.stderr @@ -10,5 +10,5 @@ warning: error reading Clippy's configuration file: deprecated field `cyclomatic LL | cyclomatic-complexity-threshold = 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr b/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr index a4b1e9c335ca2..3d37e4daa960b 100644 --- a/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr +++ b/src/tools/clippy/tests/ui-toml/duplicated_keys_deprecated_2/duplicated_keys.stderr @@ -10,5 +10,5 @@ warning: error reading Clippy's configuration file: deprecated field `cyclomatic LL | cyclomatic-complexity-threshold = 3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.stderr b/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.stderr index 4d9bc9d48e45a..ca96c47b92bb5 100644 --- a/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.stderr +++ b/src/tools/clippy/tests/ui-toml/enum_variant_size/enum_variant_size.stderr @@ -17,5 +17,5 @@ help: consider boxing the large fields to reduce the total size of the enum LL | B(Box<[u8; 501]>), | ~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr b/src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr index 717a4bbfbfe17..ceec4ea675530 100644 --- a/src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr +++ b/src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr @@ -8,5 +8,5 @@ LL | fn g(_: bool, _: bool) {} = note: `-D clippy::fn-params-excessive-bools` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::fn_params_excessive_bools)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/ifs_same_cond/ifs_same_cond.stderr b/src/tools/clippy/tests/ui-toml/ifs_same_cond/ifs_same_cond.stderr index 305e00af27e54..e0e77bf23f66d 100644 --- a/src/tools/clippy/tests/ui-toml/ifs_same_cond/ifs_same_cond.stderr +++ b/src/tools/clippy/tests/ui-toml/ifs_same_cond/ifs_same_cond.stderr @@ -12,5 +12,5 @@ LL | if x.get() { = note: `-D clippy::ifs-same-cond` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ifs_same_cond)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.stderr b/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.stderr index 80c4f5ed4b0c0..bb1244ada9f44 100644 --- a/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.stderr +++ b/src/tools/clippy/tests/ui-toml/impl_trait_in_params/impl_trait_in_params.stderr @@ -11,5 +11,5 @@ help: add a type parameter LL | fn t<{ /* Generic name */ }: Trait>(_: impl Trait); | +++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr index f127c2408f905..a764840665a37 100644 --- a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr +++ b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr @@ -4,5 +4,5 @@ error: error reading Clippy's configuration file: not a valid Rust version LL | msrv = "invalid.version" | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/large_futures/large_futures.stderr b/src/tools/clippy/tests/ui-toml/large_futures/large_futures.stderr index 7a02fcdbdd2f5..23c6215f9498f 100644 --- a/src/tools/clippy/tests/ui-toml/large_futures/large_futures.stderr +++ b/src/tools/clippy/tests/ui-toml/large_futures/large_futures.stderr @@ -7,5 +7,5 @@ LL | should_warn().await; = note: `-D clippy::large-futures` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_futures)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.stderr b/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.stderr index 67ee57ab672d4..5adf666278fc9 100644 --- a/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.stderr +++ b/src/tools/clippy/tests/ui-toml/large_stack_frames/large_stack_frames.stderr @@ -11,5 +11,5 @@ LL | | } = note: `-D clippy::large-stack-frames` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.stderr b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.stderr index 6678a2b47214f..20026d358aef1 100644 --- a/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.stderr +++ b/src/tools/clippy/tests/ui-toml/large_types_passed_by_value/large_types_passed_by_value.stderr @@ -7,5 +7,5 @@ LL | fn f2(_v: [u8; 513]) {} = note: `-D clippy::large-types-passed-by-value` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_types_passed_by_value)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.stderr b/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.stderr index 5c2c86c373189..67647cc5e95fe 100644 --- a/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.stderr +++ b/src/tools/clippy/tests/ui-toml/manual_let_else/manual_let_else.stderr @@ -11,5 +11,5 @@ LL | | }; = note: `-D clippy::manual-let-else` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr index d319e65d06ce8..20ffacd092ada 100644 --- a/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr +++ b/src/tools/clippy/tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.stderr @@ -18,5 +18,5 @@ help: and replace the index expressions here LL | println!("{}", slice_7); | ~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.stderr b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.stderr index 5b1f8dbd3eab7..5bf2bcd3bc616 100644 --- a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.stderr +++ b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.stderr @@ -7,5 +7,5 @@ LL | let _: Option = Some(&16).map(|b| *b); = note: `-D clippy::map-clone` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::map_clone)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/private-doc-errors/clippy.toml b/src/tools/clippy/tests/ui-toml/private-doc-errors/clippy.toml new file mode 100644 index 0000000000000..8483b87c650ad --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/private-doc-errors/clippy.toml @@ -0,0 +1 @@ +check-private-items = true diff --git a/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs new file mode 100644 index 0000000000000..ae4c3f84c2966 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs @@ -0,0 +1,54 @@ +#![deny( + clippy::unnecessary_safety_doc, + clippy::missing_errors_doc, + clippy::missing_panics_doc +)] + +/// This is a private function, skip to match behavior with `missing_safety_doc`. +/// +/// # Safety +/// +/// Boo! +fn you_dont_see_me() { + //~^ ERROR: safe function's docs have unnecessary `# Safety` section + unimplemented!(); +} + +mod private_mod { + /// This is public but unexported function. + /// + /// # Safety + /// + /// Very safe! + pub fn only_crate_wide_accessible() -> Result<(), ()> { + //~^ ERROR: safe function's docs have unnecessary `# Safety` section + //~| ERROR: docs for function returning `Result` missing `# Errors` section + unimplemented!(); + } +} + +pub struct S; + +impl S { + /// Private, fine again to stay consistent with `missing_safety_doc`. + /// + /// # Safety + /// + /// Unnecessary! + fn private(&self) { + //~^ ERROR: safe function's docs have unnecessary `# Safety` section + //~| ERROR: docs for function which may panic missing `# Panics` section + panic!(); + } +} + +#[doc(hidden)] +pub mod __macro { + pub struct T; + impl T { + pub unsafe fn f() {} + //~^ ERROR: unsafe function's docs miss `# Safety` section + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.stderr b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.stderr new file mode 100644 index 0000000000000..8533674804988 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.stderr @@ -0,0 +1,64 @@ +error: safe function's docs have unnecessary `# Safety` section + --> $DIR/doc_lints.rs:12:1 + | +LL | fn you_dont_see_me() { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/doc_lints.rs:2:5 + | +LL | clippy::unnecessary_safety_doc, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: safe function's docs have unnecessary `# Safety` section + --> $DIR/doc_lints.rs:23:5 + | +LL | pub fn only_crate_wide_accessible() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function returning `Result` missing `# Errors` section + --> $DIR/doc_lints.rs:23:5 + | +LL | pub fn only_crate_wide_accessible() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/doc_lints.rs:3:5 + | +LL | clippy::missing_errors_doc, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: safe function's docs have unnecessary `# Safety` section + --> $DIR/doc_lints.rs:38:5 + | +LL | fn private(&self) { + | ^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> $DIR/doc_lints.rs:38:5 + | +LL | fn private(&self) { + | ^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> $DIR/doc_lints.rs:41:9 + | +LL | panic!(); + | ^^^^^^^^ +note: the lint level is defined here + --> $DIR/doc_lints.rs:4:5 + | +LL | clippy::missing_panics_doc + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unsafe function's docs miss `# Safety` section + --> $DIR/doc_lints.rs:49:9 + | +LL | pub unsafe fn f() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::missing-safety-doc` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::missing_safety_doc)]` + +error: aborting due to 6 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.stderr b/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.stderr index b0936319d1b9d..cc603fc0cc049 100644 --- a/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.stderr +++ b/src/tools/clippy/tests/ui-toml/result_large_err/result_large_err.stderr @@ -8,5 +8,5 @@ LL | fn f2() -> Result<(), [u8; 512]> { = note: `-D clippy::result-large-err` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::result_large_err)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr index ce03d7d75a264..0542e139b3408 100644 --- a/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr +++ b/src/tools/clippy/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr @@ -15,5 +15,5 @@ LL ~ unit_fn_block(); LL ~ } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr b/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr index 9237c9c9d29d9..31e0e33a39b25 100644 --- a/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr +++ b/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr @@ -10,5 +10,5 @@ LL | | } = note: `-D clippy::struct-excessive-bools` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::struct_excessive_bools)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 2f9eaa5178c49..12828cf9dec5f 100644 --- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -21,6 +21,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect await-holding-invalid-types blacklisted-names cargo-ignore-publish + check-private-items cognitive-complexity-threshold cyclomatic-complexity-threshold disallowed-macros @@ -95,6 +96,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect await-holding-invalid-types blacklisted-names cargo-ignore-publish + check-private-items cognitive-complexity-threshold cyclomatic-complexity-threshold disallowed-macros diff --git a/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.stderr b/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.stderr index 2859a29f1b2a2..54990c35228f7 100644 --- a/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.stderr +++ b/src/tools/clippy/tests/ui-toml/too_large_for_stack/boxed_local.stderr @@ -7,5 +7,5 @@ LL | fn f(x: Box<[u8; 500]>) {} = note: `-D clippy::boxed-local` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::boxed_local)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.stderr b/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.stderr index 923cded5eef18..5d289db8534bb 100644 --- a/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.stderr +++ b/src/tools/clippy/tests/ui-toml/too_large_for_stack/useless_vec.stderr @@ -7,5 +7,5 @@ LL | let x = vec![0u8; 500]; = note: `-D clippy::useless-vec` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::useless_vec)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr index 8b9d159b59c3a..81d9bee737e29 100644 --- a/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr +++ b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr @@ -7,5 +7,5 @@ LL | fn too_many(p1: u8, p2: u8, p3: u8, p4: u8, p5: u8, p6: u8, p7: u8, p8: u8, = note: `-D clippy::too-many-arguments` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.stderr b/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.stderr index 8ca637f722251..df824400da82e 100644 --- a/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.stderr +++ b/src/tools/clippy/tests/ui-toml/type_complexity/type_complexity.stderr @@ -7,5 +7,5 @@ LL | fn f2(_: (u8, (u8, (u8, (u8, (u8, (u8, u8))))))) {} = note: `-D clippy::type-complexity` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::type_complexity)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr index 2ae2984975f4b..444fbd12814d0 100644 --- a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr +++ b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr @@ -8,5 +8,5 @@ LL | T: Unpin + PartialEq, = note: `-D clippy::type-repetition-in-bounds` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::type_repetition_in_bounds)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.stderr b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.stderr index df9aa37ac10f4..9a747a19f7952 100644 --- a/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.stderr +++ b/src/tools/clippy/tests/ui-toml/unnecessary_box_returns/unnecessary_box_returns.stderr @@ -8,5 +8,5 @@ LL | fn f() -> Box<[u8; 64]> { = note: `-D clippy::unnecessary-box-returns` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_box_returns)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.stderr b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.stderr index 7377921b42ab1..5fcc63131bf47 100644 --- a/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.stderr +++ b/src/tools/clippy/tests/ui-toml/verbose_bit_mask/verbose_bit_mask.stderr @@ -7,5 +7,5 @@ LL | let _ = v & 0b111111 == 0; = note: `-D clippy::verbose-bit-mask` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::verbose_bit_mask)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr index 13ec3a229ce91..f11fda6a0c6e1 100644 --- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr @@ -7,5 +7,5 @@ LL | use prelude::*; = note: `-D clippy::wildcard-imports` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/arc_with_non_send_sync.rs b/src/tools/clippy/tests/ui/arc_with_non_send_sync.rs index d03a577c45447..349e81912e3c3 100644 --- a/src/tools/clippy/tests/ui/arc_with_non_send_sync.rs +++ b/src/tools/clippy/tests/ui/arc_with_non_send_sync.rs @@ -33,16 +33,16 @@ fn main() { let _ = Arc::new(42); let _ = Arc::new(RefCell::new(42)); - //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync` + //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync` //~| NOTE: the trait `Sync` is not implemented for `RefCell` let mutex = Mutex::new(1); let _ = Arc::new(mutex.lock().unwrap()); - //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync` + //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync` //~| NOTE: the trait `Send` is not implemented for `MutexGuard<'_, i32>` let _ = Arc::new(&42 as *const i32); - //~^ ERROR: usage of an `Arc` that is not `Send` or `Sync` + //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync` //~| NOTE: the trait `Send` is not implemented for `*const i32` //~| NOTE: the trait `Sync` is not implemented for `*const i32` } diff --git a/src/tools/clippy/tests/ui/arc_with_non_send_sync.stderr b/src/tools/clippy/tests/ui/arc_with_non_send_sync.stderr index fd239580d284b..a7f91abda4ebd 100644 --- a/src/tools/clippy/tests/ui/arc_with_non_send_sync.stderr +++ b/src/tools/clippy/tests/ui/arc_with_non_send_sync.stderr @@ -1,35 +1,41 @@ -error: usage of an `Arc` that is not `Send` or `Sync` +error: usage of an `Arc` that is not `Send` and `Sync` --> $DIR/arc_with_non_send_sync.rs:35:13 | LL | let _ = Arc::new(RefCell::new(42)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the trait `Sync` is not implemented for `RefCell` - = note: required for `Arc>` to implement `Send` and `Sync` - = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex` + = note: `Arc>` is not `Send` and `Sync` as: + = note: - the trait `Sync` is not implemented for `RefCell` + = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types + = note: if you intend to use `Arc` with `Send` and `Sync` traits + = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `RefCell` = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]` -error: usage of an `Arc` that is not `Send` or `Sync` +error: usage of an `Arc` that is not `Send` and `Sync` --> $DIR/arc_with_non_send_sync.rs:40:13 | LL | let _ = Arc::new(mutex.lock().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the trait `Send` is not implemented for `MutexGuard<'_, i32>` - = note: required for `Arc>` to implement `Send` and `Sync` - = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex` + = note: `Arc>` is not `Send` and `Sync` as: + = note: - the trait `Send` is not implemented for `MutexGuard<'_, i32>` + = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types + = note: if you intend to use `Arc` with `Send` and `Sync` traits + = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `MutexGuard<'_, i32>` -error: usage of an `Arc` that is not `Send` or `Sync` +error: usage of an `Arc` that is not `Send` and `Sync` --> $DIR/arc_with_non_send_sync.rs:44:13 | LL | let _ = Arc::new(&42 as *const i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the trait `Send` is not implemented for `*const i32` - = note: the trait `Sync` is not implemented for `*const i32` - = note: required for `Arc<*const i32>` to implement `Send` and `Sync` - = help: consider using an `Rc` instead or wrapping the inner type with a `Mutex` + = note: `Arc<*const i32>` is not `Send` and `Sync` as: + = note: - the trait `Send` is not implemented for `*const i32` + = note: - the trait `Sync` is not implemented for `*const i32` + = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types + = note: if you intend to use `Arc` with `Send` and `Sync` traits + = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `*const i32` error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/attrs.rs b/src/tools/clippy/tests/ui/attrs.rs index 05ee48d17b1ef..da96eabede17c 100644 --- a/src/tools/clippy/tests/ui/attrs.rs +++ b/src/tools/clippy/tests/ui/attrs.rs @@ -36,6 +36,9 @@ pub const ANOTHER_CONST: u8 = 23; #[deprecated(since = "0.1.1")] pub const YET_ANOTHER_CONST: u8 = 0; +#[deprecated(since = "TBD")] +pub const GONNA_DEPRECATE_THIS_LATER: u8 = 0; + fn main() { test_attr_lint(); if false { diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout index eb3e5189c8238..140300a167308 100644 --- a/src/tools/clippy/tests/ui/author/blocks.stdout +++ b/src/tools/clippy/tests/ui/author/blocks.stdout @@ -40,10 +40,10 @@ if let ExprKind::Block(block, None) = expr.kind { // report your lint here } -if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind +if let ExprKind::Closure(CaptureBy::Value { .. }, fn_decl, body_id, _, None) = expr.kind && let FnRetTy::DefaultReturn(_) = fn_decl.output && expr1 = &cx.tcx.hir().body(body_id).value - && let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind + && let ExprKind::Closure(CaptureBy::Value { .. }, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind && let FnRetTy::DefaultReturn(_) = fn_decl1.output && expr2 = &cx.tcx.hir().body(body_id1).value && let ExprKind::Block(block, None) = expr2.kind diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref_unfixable.stderr b/src/tools/clippy/tests/ui/borrow_deref_ref_unfixable.stderr index 2a21f5ca236fb..296af6436934f 100644 --- a/src/tools/clippy/tests/ui/borrow_deref_ref_unfixable.stderr +++ b/src/tools/clippy/tests/ui/borrow_deref_ref_unfixable.stderr @@ -15,5 +15,5 @@ help: if you would like to deref, try using `&**` LL | let x: &str = &**s; | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed index 69cabcb32d333..48408e1912573 100644 --- a/src/tools/clippy/tests/ui/box_default.fixed +++ b/src/tools/clippy/tests/ui/box_default.fixed @@ -90,3 +90,17 @@ fn issue_10381() { assert!(maybe_get_bar(2).is_some()); } + +#[allow(unused)] +fn issue_11868() { + fn foo(_: &mut Vec) {} + + macro_rules! bar { + ($baz:expr) => { + Box::leak(Box::new($baz)) + }; + } + + foo(bar!(vec![])); + foo(bar!(vec![1])); +} diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs index 48fa8bc33bc2d..58b9127074728 100644 --- a/src/tools/clippy/tests/ui/box_default.rs +++ b/src/tools/clippy/tests/ui/box_default.rs @@ -90,3 +90,17 @@ fn issue_10381() { assert!(maybe_get_bar(2).is_some()); } + +#[allow(unused)] +fn issue_11868() { + fn foo(_: &mut Vec) {} + + macro_rules! bar { + ($baz:expr) => { + Box::leak(Box::new($baz)) + }; + } + + foo(bar!(vec![])); + foo(bar!(vec![1])); +} diff --git a/src/tools/clippy/tests/ui/cfg_features.fixed b/src/tools/clippy/tests/ui/cfg_features.fixed index 3d52f2382ea72..0fe38f169f9c8 100644 --- a/src/tools/clippy/tests/ui/cfg_features.fixed +++ b/src/tools/clippy/tests/ui/cfg_features.fixed @@ -2,16 +2,28 @@ fn main() { #[cfg(feature = "not-really-a-feature")] - //~^ ERROR: feature may misspelled as features + //~^ ERROR: 'feature' may be misspelled as 'features' //~| NOTE: `-D clippy::maybe-misused-cfg` implied by `-D warnings` let _ = 1 + 2; #[cfg(all(feature = "right", feature = "wrong"))] - //~^ ERROR: feature may misspelled as features + //~^ ERROR: 'feature' may be misspelled as 'features' let _ = 1 + 2; #[cfg(all(feature = "wrong1", any(feature = "right", feature = "wrong2", feature, features)))] - //~^ ERROR: feature may misspelled as features - //~| ERROR: feature may misspelled as features + //~^ ERROR: 'feature' may be misspelled as 'features' + //~| ERROR: 'feature' may be misspelled as 'features' let _ = 1 + 2; + + #[cfg(test)] + //~^ ERROR: 'test' may be misspelled as 'tests' + let _ = 2; + #[cfg(test)] + //~^ ERROR: 'test' may be misspelled as 'Test' + let _ = 2; + + #[cfg(all(test, test))] + //~^ ERROR: 'test' may be misspelled as 'tests' + //~| ERROR: 'test' may be misspelled as 'Test' + let _ = 2; } diff --git a/src/tools/clippy/tests/ui/cfg_features.rs b/src/tools/clippy/tests/ui/cfg_features.rs index a0344a0044799..9c0db035eac41 100644 --- a/src/tools/clippy/tests/ui/cfg_features.rs +++ b/src/tools/clippy/tests/ui/cfg_features.rs @@ -2,16 +2,28 @@ fn main() { #[cfg(features = "not-really-a-feature")] - //~^ ERROR: feature may misspelled as features + //~^ ERROR: 'feature' may be misspelled as 'features' //~| NOTE: `-D clippy::maybe-misused-cfg` implied by `-D warnings` let _ = 1 + 2; #[cfg(all(feature = "right", features = "wrong"))] - //~^ ERROR: feature may misspelled as features + //~^ ERROR: 'feature' may be misspelled as 'features' let _ = 1 + 2; #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] - //~^ ERROR: feature may misspelled as features - //~| ERROR: feature may misspelled as features + //~^ ERROR: 'feature' may be misspelled as 'features' + //~| ERROR: 'feature' may be misspelled as 'features' let _ = 1 + 2; + + #[cfg(tests)] + //~^ ERROR: 'test' may be misspelled as 'tests' + let _ = 2; + #[cfg(Test)] + //~^ ERROR: 'test' may be misspelled as 'Test' + let _ = 2; + + #[cfg(all(tests, Test))] + //~^ ERROR: 'test' may be misspelled as 'tests' + //~| ERROR: 'test' may be misspelled as 'Test' + let _ = 2; } diff --git a/src/tools/clippy/tests/ui/cfg_features.stderr b/src/tools/clippy/tests/ui/cfg_features.stderr index 401c3e92ed952..e1593e2071b49 100644 --- a/src/tools/clippy/tests/ui/cfg_features.stderr +++ b/src/tools/clippy/tests/ui/cfg_features.stderr @@ -1,29 +1,53 @@ -error: feature may misspelled as features +error: 'feature' may be misspelled as 'features' --> $DIR/cfg_features.rs:4:11 | LL | #[cfg(features = "not-really-a-feature")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `feature = "not-really-a-feature"` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `feature = "not-really-a-feature"` | = note: `-D clippy::maybe-misused-cfg` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::maybe_misused_cfg)]` -error: feature may misspelled as features +error: 'feature' may be misspelled as 'features' --> $DIR/cfg_features.rs:9:34 | LL | #[cfg(all(feature = "right", features = "wrong"))] - | ^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong"` + | ^^^^^^^^^^^^^^^^^^ help: did you mean: `feature = "wrong"` -error: feature may misspelled as features +error: 'feature' may be misspelled as 'features' --> $DIR/cfg_features.rs:13:15 | LL | #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] - | ^^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong1"` + | ^^^^^^^^^^^^^^^^^^^ help: did you mean: `feature = "wrong1"` -error: feature may misspelled as features +error: 'feature' may be misspelled as 'features' --> $DIR/cfg_features.rs:13:59 | LL | #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))] - | ^^^^^^^^^^^^^^^^^^^ help: use: `feature = "wrong2"` + | ^^^^^^^^^^^^^^^^^^^ help: did you mean: `feature = "wrong2"` -error: aborting due to 4 previous errors +error: 'test' may be misspelled as 'tests' + --> $DIR/cfg_features.rs:18:11 + | +LL | #[cfg(tests)] + | ^^^^^ help: did you mean: `test` + +error: 'test' may be misspelled as 'Test' + --> $DIR/cfg_features.rs:21:11 + | +LL | #[cfg(Test)] + | ^^^^ help: did you mean: `test` + +error: 'test' may be misspelled as 'tests' + --> $DIR/cfg_features.rs:25:15 + | +LL | #[cfg(all(tests, Test))] + | ^^^^^ help: did you mean: `test` + +error: 'test' may be misspelled as 'Test' + --> $DIR/cfg_features.rs:25:22 + | +LL | #[cfg(all(tests, Test))] + | ^^^^ help: did you mean: `test` + +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/char_lit_as_u8.stderr b/src/tools/clippy/tests/ui/char_lit_as_u8.stderr index ce1f2f8296e5d..22774d2f9f6d0 100644 --- a/src/tools/clippy/tests/ui/char_lit_as_u8.stderr +++ b/src/tools/clippy/tests/ui/char_lit_as_u8.stderr @@ -8,5 +8,5 @@ LL | let _ = '❤' as u8; = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::char_lit_as_u8)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr b/src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr index 9cd25f6fda989..b9af72371e6a6 100644 --- a/src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr +++ b/src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr @@ -8,5 +8,5 @@ LL | fn kaboom() { = note: `-D clippy::cognitive-complexity` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::cognitive_complexity)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/copy_iterator.stderr b/src/tools/clippy/tests/ui/copy_iterator.stderr index 48c3385b6c8a9..30535db50cc9a 100644 --- a/src/tools/clippy/tests/ui/copy_iterator.stderr +++ b/src/tools/clippy/tests/ui/copy_iterator.stderr @@ -14,5 +14,5 @@ LL | | } = note: `-D clippy::copy-iterator` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::copy_iterator)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-10148.stderr b/src/tools/clippy/tests/ui/crashes/ice-10148.stderr index 4d436e3aa04fa..ece3e1c394037 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-10148.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-10148.stderr @@ -9,5 +9,5 @@ LL | println!(with_span!(""something "")); = note: `-D clippy::println-empty-string` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::println_empty_string)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-11230.rs b/src/tools/clippy/tests/ui/crashes/ice-11230.rs new file mode 100644 index 0000000000000..5761882273e00 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-11230.rs @@ -0,0 +1,6 @@ +/// Test for https://github.com/rust-lang/rust-clippy/issues/11230 + +fn main() { + const A: &[for<'a> fn(&'a ())] = &[]; + for v in A.iter() {} +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-11422.stderr b/src/tools/clippy/tests/ui/crashes/ice-11422.stderr index fb80b5b147f57..b3dcc00f3d9ef 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-11422.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-11422.stderr @@ -12,5 +12,5 @@ LL - fn gen() -> impl PartialOrd + PartialEq + Debug {} LL + fn gen() -> impl PartialOrd + Debug {} | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-11755.rs b/src/tools/clippy/tests/ui/crashes/ice-11755.rs new file mode 100644 index 0000000000000..367cb69985786 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-11755.rs @@ -0,0 +1,5 @@ +#![warn(clippy::unused_enumerate_index)] + +fn main() { + for () in [()].iter() {} +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-11803.rs b/src/tools/clippy/tests/ui/crashes/ice-11803.rs new file mode 100644 index 0000000000000..1bb8bf0c746b5 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-11803.rs @@ -0,0 +1,9 @@ +//@no-rustfix + +#![warn(clippy::impl_trait_in_params)] + +pub fn g>>() { + extern "C" fn implementation_detail() {} +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-11803.stderr b/src/tools/clippy/tests/ui/crashes/ice-11803.stderr new file mode 100644 index 0000000000000..b8289048a8b90 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-11803.stderr @@ -0,0 +1,26 @@ +error: `impl Trait` used as a function parameter + --> $DIR/ice-11803.rs:5:54 + | +LL | pub fn g>>() { + | ^^^^^^^^^^ + | + = note: `-D clippy::impl-trait-in-params` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::impl_trait_in_params)]` +help: add a type parameter + | +LL | pub fn g>, { /* Generic name */ }: Clone>() { + | +++++++++++++++++++++++++++++++ + +error: `impl Trait` used as a function parameter + --> $DIR/ice-11803.rs:5:33 + | +LL | pub fn g>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add a type parameter + | +LL | pub fn g>, { /* Generic name */ }: Iterator>() { + | +++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr index ae9610c9acd42..188a5985024e7 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr @@ -12,5 +12,5 @@ LL - pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { LL + pub fn add_barfoos_to_foos(bars: &HashSet<&Bar>) { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr index 4d3d617b69375..863608fca8bdf 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr @@ -18,5 +18,5 @@ help: ...and use generic constructor LL | let _: HashSet = HashSet::default(); | ~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-3891.stderr b/src/tools/clippy/tests/ui/crashes/ice-3891.stderr index 59469ec5891c8..5358734fed04e 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3891.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-3891.stderr @@ -6,5 +6,5 @@ LL | 1x; | = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-5497.stderr b/src/tools/clippy/tests/ui/crashes/ice-5497.stderr index e75e7dc913673..ee69f3379b6a1 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-5497.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-5497.stderr @@ -6,5 +6,5 @@ LL | const OOB: i32 = [1][1] + T::OOB; | = note: `#[deny(unconditional_panic)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-5835.stderr b/src/tools/clippy/tests/ui/crashes/ice-5835.stderr index 74d99a3484729..1f930e1f6d2cc 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-5835.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-5835.stderr @@ -7,5 +7,5 @@ LL | /// 位 = note: `-D clippy::tabs-in-doc-comments` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::tabs_in_doc_comments)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-5872.stderr b/src/tools/clippy/tests/ui/crashes/ice-5872.stderr index 75a26ee318c32..d0067a2239e97 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-5872.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-5872.stderr @@ -7,5 +7,5 @@ LL | let _ = vec![1, 2, 3].into_iter().collect::>().is_empty(); = note: `-D clippy::needless-collect` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_collect)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-6254.stderr b/src/tools/clippy/tests/ui/crashes/ice-6254.stderr index 6ace7dae8bdce..7a34e6cceeea7 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6254.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6254.stderr @@ -11,5 +11,5 @@ LL | FOO_REF_REF => {}, = note: `-D indirect-structural-match` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(indirect_structural_match)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-6255.stderr b/src/tools/clippy/tests/ui/crashes/ice-6255.stderr index db0cb25e34a0f..bc13319bef023 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6255.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6255.stderr @@ -9,5 +9,5 @@ LL | define_other_core!(); | = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr index 671933157c809..cba6df194eccb 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr @@ -9,6 +9,6 @@ LL | let f = |x: &dyn TT| x.func(); | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/src/tools/clippy/tests/ui/crashes/ice-7169.stderr b/src/tools/clippy/tests/ui/crashes/ice-7169.stderr index 47947f89baf53..3126de93d2241 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-7169.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-7169.stderr @@ -7,5 +7,5 @@ LL | if let Ok(_) = Ok::<_, ()>(A::::default()) {} = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr index e5f14f2215d7e..3315a8d907ae6 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr @@ -8,5 +8,5 @@ LL | unsafe { 0 }; = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-7869.stderr b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr index 7acace78a7b26..22f2c7e46fdc5 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-7869.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr @@ -13,5 +13,5 @@ LL | | } = note: `-D clippy::enum-variant-names` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::enum_variant_names)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-8250.stderr b/src/tools/clippy/tests/ui/crashes/ice-8250.stderr index 9c57f334581c5..397e978af0bd6 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-8250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-8250.stderr @@ -7,5 +7,5 @@ LL | let _ = s[1..].splitn(2, '.').next()?; = note: `-D clippy::needless-splitn` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_splitn)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-8821.stderr b/src/tools/clippy/tests/ui/crashes/ice-8821.stderr index c8bd01fb1c645..94ebb20918ed5 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-8821.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-8821.stderr @@ -7,5 +7,5 @@ LL | let _: () = FN(); = note: `-D clippy::let-unit-value` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-9041.stderr b/src/tools/clippy/tests/ui/crashes/ice-9041.stderr index 49c9bdc300ee9..00b65f00d787c 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-9041.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-9041.stderr @@ -7,5 +7,5 @@ LL | things.iter().find(|p| is_thing_ready(p)).is_some() = note: `-D clippy::search-is-some` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-9445.stderr b/src/tools/clippy/tests/ui/crashes/ice-9445.stderr index 9307409ba5852..f97b4536e129a 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-9445.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-9445.stderr @@ -9,5 +9,5 @@ LL | const UNINIT: core::mem::MaybeUninit> = core: = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/ice-96721.stderr b/src/tools/clippy/tests/ui/crashes/ice-96721.stderr index 712bd14c685f0..1741c7c6a0a22 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-96721.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-96721.stderr @@ -4,5 +4,5 @@ error: malformed `path` attribute input LL | #[path = foo!()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr index 37484f5ebd702..2ebb9d5cd1a12 100644 --- a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr +++ b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr @@ -15,5 +15,5 @@ LL - fn baz<'a>(&'a self) -> impl Foo + 'a { LL + fn baz(&self) -> impl Foo + '_ { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr index 6d45393996d07..b318f8d3f7af1 100644 --- a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr +++ b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr @@ -12,5 +12,5 @@ LL | struct Foo<'a>(&'a [(); 100]); = note: `-D clippy::needless-pass-by-value` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_value)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crate_in_macro_def.stderr b/src/tools/clippy/tests/ui/crate_in_macro_def.stderr index 3e624618237c2..1a21d4e92f24a 100644 --- a/src/tools/clippy/tests/ui/crate_in_macro_def.stderr +++ b/src/tools/clippy/tests/ui/crate_in_macro_def.stderr @@ -7,5 +7,5 @@ LL | println!("{}", crate::unhygienic::MESSAGE); = note: `-D clippy::crate-in-macro-def` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::crate_in_macro_def)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr index 01033246dd90b..7ef8d08d5d69e 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr +++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr @@ -11,5 +11,5 @@ LL | | b = a; = note: `-D clippy::almost-swapped` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::almost_swapped)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr b/src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr index f3ffd6a10c717..3bc406206e4b5 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr +++ b/src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr @@ -8,5 +8,5 @@ LL | main(); = note: `-D clippy::main-recursion` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::main_recursion)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/dbg_macro/auxiliary/submodule.rs b/src/tools/clippy/tests/ui/dbg_macro/auxiliary/submodule.rs new file mode 100644 index 0000000000000..b1df24737a27e --- /dev/null +++ b/src/tools/clippy/tests/ui/dbg_macro/auxiliary/submodule.rs @@ -0,0 +1,3 @@ +fn f() { + dbg!(); +} diff --git a/src/tools/clippy/tests/ui/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs similarity index 97% rename from src/tools/clippy/tests/ui/dbg_macro.rs rename to src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs index 149b08476192c..3f4770c63d014 100644 --- a/src/tools/clippy/tests/ui/dbg_macro.rs +++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs @@ -2,10 +2,12 @@ #![warn(clippy::dbg_macro)] +#[path = "auxiliary/submodule.rs"] +mod submodule; + fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } //~^ ERROR: the `dbg!` macro is intended as a debugging tool - //~| NOTE: `-D clippy::dbg-macro` implied by `-D warnings` } fn bar(_: ()) {} diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr similarity index 85% rename from src/tools/clippy/tests/ui/dbg_macro.stderr rename to src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr index f45a7ba1faebd..4d00421c71186 100644 --- a/src/tools/clippy/tests/ui/dbg_macro.stderr +++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr @@ -1,18 +1,30 @@ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:6:22 + --> $DIR/auxiliary/submodule.rs:2:5 | -LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | dbg!(); + | ^^^^^^^ | = note: `-D clippy::dbg-macro` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]` help: remove the invocation before committing it to a version control system | +LL - dbg!(); +LL + + | + +error: the `dbg!` macro is intended as a debugging tool + --> $DIR/dbg_macro.rs:9:22 + | +LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the invocation before committing it to a version control system + | LL | if let Some(n) = n.checked_sub(4) { n } else { n } | ~~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:13:8 + --> $DIR/dbg_macro.rs:15:8 | LL | if dbg!(n <= 1) { | ^^^^^^^^^^^^ @@ -23,7 +35,7 @@ LL | if n <= 1 { | ~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:15:9 + --> $DIR/dbg_macro.rs:17:9 | LL | dbg!(1) | ^^^^^^^ @@ -34,7 +46,7 @@ LL | 1 | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:18:9 + --> $DIR/dbg_macro.rs:20:9 | LL | dbg!(n * factorial(n - 1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,7 +57,7 @@ LL | n * factorial(n - 1) | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:24:5 + --> $DIR/dbg_macro.rs:26:5 | LL | dbg!(42); | ^^^^^^^^ @@ -56,7 +68,7 @@ LL | 42; | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:26:5 + --> $DIR/dbg_macro.rs:28:5 | LL | dbg!(dbg!(dbg!(42))); | ^^^^^^^^^^^^^^^^^^^^ @@ -67,7 +79,7 @@ LL | dbg!(dbg!(42)); | ~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:28:14 + --> $DIR/dbg_macro.rs:30:14 | LL | foo(3) + dbg!(factorial(4)); | ^^^^^^^^^^^^^^^^^^ @@ -78,7 +90,7 @@ LL | foo(3) + factorial(4); | ~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:30:5 + --> $DIR/dbg_macro.rs:32:5 | LL | dbg!(1, 2, dbg!(3, 4)); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +101,7 @@ LL | (1, 2, dbg!(3, 4)); | ~~~~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:32:5 + --> $DIR/dbg_macro.rs:34:5 | LL | dbg!(1, 2, 3, 4, 5); | ^^^^^^^^^^^^^^^^^^^ @@ -100,7 +112,7 @@ LL | (1, 2, 3, 4, 5); | ~~~~~~~~~~~~~~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:53:5 + --> $DIR/dbg_macro.rs:55:5 | LL | dbg!(); | ^^^^^^^ @@ -112,7 +124,7 @@ LL + | error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:56:13 + --> $DIR/dbg_macro.rs:58:13 | LL | let _ = dbg!(); | ^^^^^^ @@ -123,7 +135,7 @@ LL | let _ = (); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:58:9 + --> $DIR/dbg_macro.rs:60:9 | LL | bar(dbg!()); | ^^^^^^ @@ -134,7 +146,7 @@ LL | bar(()); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:60:10 + --> $DIR/dbg_macro.rs:62:10 | LL | foo!(dbg!()); | ^^^^^^ @@ -145,7 +157,7 @@ LL | foo!(()); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:62:16 + --> $DIR/dbg_macro.rs:64:16 | LL | foo2!(foo!(dbg!())); | ^^^^^^ @@ -156,7 +168,7 @@ LL | foo2!(foo!(())); | ~~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:84:9 + --> $DIR/dbg_macro.rs:86:9 | LL | dbg!(2); | ^^^^^^^ @@ -167,7 +179,7 @@ LL | 2; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:91:5 + --> $DIR/dbg_macro.rs:93:5 | LL | dbg!(1); | ^^^^^^^ @@ -178,7 +190,7 @@ LL | 1; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:97:5 + --> $DIR/dbg_macro.rs:99:5 | LL | dbg!(1); | ^^^^^^^ @@ -189,7 +201,7 @@ LL | 1; | ~ error: the `dbg!` macro is intended as a debugging tool - --> $DIR/dbg_macro.rs:104:9 + --> $DIR/dbg_macro.rs:106:9 | LL | dbg!(1); | ^^^^^^^ @@ -199,5 +211,5 @@ help: remove the invocation before committing it to a version control system LL | 1; | ~ -error: aborting due to 18 previous errors +error: aborting due to 19 previous errors diff --git a/src/tools/clippy/tests/ui/def_id_nocore.stderr b/src/tools/clippy/tests/ui/def_id_nocore.stderr index bfd0de4e13acb..6a00331ec69f0 100644 --- a/src/tools/clippy/tests/ui/def_id_nocore.stderr +++ b/src/tools/clippy/tests/ui/def_id_nocore.stderr @@ -8,5 +8,5 @@ LL | pub fn as_ref(self) -> &'static str { = note: `-D clippy::wrong-self-convention` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::wrong_self_convention)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/doc_link_with_quotes.rs b/src/tools/clippy/tests/ui/doc_link_with_quotes.rs index 37d0d13595737..48e1b1819c6ff 100644 --- a/src/tools/clippy/tests/ui/doc_link_with_quotes.rs +++ b/src/tools/clippy/tests/ui/doc_link_with_quotes.rs @@ -11,6 +11,12 @@ pub fn foo() { bar() } +/// Calls ["bar"] uselessly +//~^ ERROR: possible intra-doc link using quotes instead of backticks +pub fn foo2() { + bar() +} + /// # Examples /// This demonstrates issue \#8961 /// ``` diff --git a/src/tools/clippy/tests/ui/doc_link_with_quotes.stderr b/src/tools/clippy/tests/ui/doc_link_with_quotes.stderr index 2db1bc0928953..cd4f87c56b42d 100644 --- a/src/tools/clippy/tests/ui/doc_link_with_quotes.stderr +++ b/src/tools/clippy/tests/ui/doc_link_with_quotes.stderr @@ -7,5 +7,11 @@ LL | /// Calls ['bar'] uselessly = note: `-D clippy::doc-link-with-quotes` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::doc_link_with_quotes)]` -error: aborting due to previous error +error: possible intra-doc link using quotes instead of backticks + --> $DIR/doc_link_with_quotes.rs:14:12 + | +LL | /// Calls ["bar"] uselessly + | ^^^^^ + +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/double_neg.stderr b/src/tools/clippy/tests/ui/double_neg.stderr index a6241c78610a7..a4fa1688d577b 100644 --- a/src/tools/clippy/tests/ui/double_neg.stderr +++ b/src/tools/clippy/tests/ui/double_neg.stderr @@ -7,5 +7,5 @@ LL | --x; = note: `-D clippy::double-neg` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::double_neg)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr b/src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr index f47f6c89622d1..53ee0c4e8c895 100644 --- a/src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr +++ b/src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr @@ -7,5 +7,5 @@ LL | fn join_the_dark_side(darth: i32, _darth: i32) {} = note: `-D clippy::duplicate-underscore-argument` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::duplicate_underscore_argument)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/empty_enum.stderr b/src/tools/clippy/tests/ui/empty_enum.stderr index 92d81c7269a53..c9bd887643e90 100644 --- a/src/tools/clippy/tests/ui/empty_enum.stderr +++ b/src/tools/clippy/tests/ui/empty_enum.stderr @@ -8,5 +8,5 @@ LL | enum Empty {} = note: `-D clippy::empty-enum` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::empty_enum)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/entry_btree.stderr b/src/tools/clippy/tests/ui/entry_btree.stderr index cc0e951d9b421..63e9a0af8b6b3 100644 --- a/src/tools/clippy/tests/ui/entry_btree.stderr +++ b/src/tools/clippy/tests/ui/entry_btree.stderr @@ -17,5 +17,5 @@ LL + foo(); LL + } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/exit1.stderr b/src/tools/clippy/tests/ui/exit1.stderr index 94d8f1e32ee13..bbe0762c8d128 100644 --- a/src/tools/clippy/tests/ui/exit1.stderr +++ b/src/tools/clippy/tests/ui/exit1.stderr @@ -7,5 +7,5 @@ LL | std::process::exit(4); = note: `-D clippy::exit` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::exit)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/exit2.stderr b/src/tools/clippy/tests/ui/exit2.stderr index cd324f182205e..19abbc6062a6e 100644 --- a/src/tools/clippy/tests/ui/exit2.stderr +++ b/src/tools/clippy/tests/ui/exit2.stderr @@ -7,5 +7,5 @@ LL | std::process::exit(3); = note: `-D clippy::exit` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::exit)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed index 12158d0d12a2e..e6ca4bb66ccd3 100644 --- a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed +++ b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed @@ -301,24 +301,47 @@ fn main() { }; // Issue #11474 - pub struct Variant { - pub anonymous: Variant0, + #[derive(Clone, Copy)] + struct Wrap(T); + impl core::ops::Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } } - - pub union Variant0 { - pub anonymous: std::mem::ManuallyDrop, + impl core::ops::DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } } - pub struct Variant00 { - pub anonymous: Variant000, + union U { + u: T, } - pub union Variant000 { - pub val: i32, + #[derive(Clone, Copy)] + struct S8 { + x: &'static str, } unsafe { - let mut p = core::mem::zeroed::(); - (*p.anonymous.anonymous).anonymous.val = 1; + let mut x = U { + u: core::mem::ManuallyDrop::new(S8 { x: "" }), + }; + let _ = &mut (*x.u).x; + let _ = &mut { x.u }.x; + let _ = &mut ({ *x.u }).x; + + let mut x = U { + u: Wrap(core::mem::ManuallyDrop::new(S8 { x: "" })), + }; + let _ = &mut (*x.u).x; + let _ = &mut { x.u }.x; + let _ = &mut ({ **x.u }).x; + + let mut x = U { u: Wrap(S8 { x: "" }) }; + let _ = &mut x.u.x; + let _ = &mut { x.u }.x; + let _ = &mut ({ *x.u }).x; } } diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.rs b/src/tools/clippy/tests/ui/explicit_auto_deref.rs index dec021c183443..7531e1f87b71b 100644 --- a/src/tools/clippy/tests/ui/explicit_auto_deref.rs +++ b/src/tools/clippy/tests/ui/explicit_auto_deref.rs @@ -301,24 +301,47 @@ fn main() { }; // Issue #11474 - pub struct Variant { - pub anonymous: Variant0, + #[derive(Clone, Copy)] + struct Wrap(T); + impl core::ops::Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } } - - pub union Variant0 { - pub anonymous: std::mem::ManuallyDrop, + impl core::ops::DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } } - pub struct Variant00 { - pub anonymous: Variant000, + union U { + u: T, } - pub union Variant000 { - pub val: i32, + #[derive(Clone, Copy)] + struct S8 { + x: &'static str, } unsafe { - let mut p = core::mem::zeroed::(); - (*p.anonymous.anonymous).anonymous.val = 1; + let mut x = U { + u: core::mem::ManuallyDrop::new(S8 { x: "" }), + }; + let _ = &mut (*x.u).x; + let _ = &mut (*{ x.u }).x; + let _ = &mut ({ *x.u }).x; + + let mut x = U { + u: Wrap(core::mem::ManuallyDrop::new(S8 { x: "" })), + }; + let _ = &mut (**x.u).x; + let _ = &mut (**{ x.u }).x; + let _ = &mut ({ **x.u }).x; + + let mut x = U { u: Wrap(S8 { x: "" }) }; + let _ = &mut (*x.u).x; + let _ = &mut (*{ x.u }).x; + let _ = &mut ({ *x.u }).x; } } diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.stderr b/src/tools/clippy/tests/ui/explicit_auto_deref.stderr index 3d2a7b0d9f4f3..cc9eeeb504290 100644 --- a/src/tools/clippy/tests/ui/explicit_auto_deref.stderr +++ b/src/tools/clippy/tests/ui/explicit_auto_deref.stderr @@ -241,5 +241,35 @@ error: deref which would be done by auto-deref LL | Some(x) => &mut *x, | ^^^^^^^ help: try: `x` -error: aborting due to 40 previous errors +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:332:22 + | +LL | let _ = &mut (*{ x.u }).x; + | ^^^^^^^^^^ help: try: `{ x.u }` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:338:22 + | +LL | let _ = &mut (**x.u).x; + | ^^^^^^^ help: try: `(*x.u)` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:339:22 + | +LL | let _ = &mut (**{ x.u }).x; + | ^^^^^^^^^^^ help: try: `{ x.u }` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:343:22 + | +LL | let _ = &mut (*x.u).x; + | ^^^^^^ help: try: `x.u` + +error: deref which would be done by auto-deref + --> $DIR/explicit_auto_deref.rs:344:22 + | +LL | let _ = &mut (*{ x.u }).x; + | ^^^^^^^^^^ help: try: `{ x.u }` + +error: aborting due to 45 previous errors diff --git a/src/tools/clippy/tests/ui/filter_map_next.stderr b/src/tools/clippy/tests/ui/filter_map_next.stderr index 1841553917ff5..07760d8837a39 100644 --- a/src/tools/clippy/tests/ui/filter_map_next.stderr +++ b/src/tools/clippy/tests/ui/filter_map_next.stderr @@ -14,5 +14,5 @@ LL | | .next(); = note: `-D clippy::filter-map-next` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed index a4d6d49e57c91..3ce2edf2c71f3 100644 --- a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed +++ b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed @@ -39,3 +39,21 @@ fn main() { // Cases where the lint shouldn't be applied let _ = (a * a + b * b).sqrt(); } + +fn _issue11831() { + struct NotAFloat; + + impl std::ops::Add for NotAFloat { + type Output = Self; + + fn add(self, _: f64) -> Self { + NotAFloat + } + } + + let a = NotAFloat; + let b = 1.0_f64; + let c = 1.0; + + let _ = a + b * c; +} diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.rs b/src/tools/clippy/tests/ui/floating_point_mul_add.rs index 262a20f0f557b..b5e4a8db4db2a 100644 --- a/src/tools/clippy/tests/ui/floating_point_mul_add.rs +++ b/src/tools/clippy/tests/ui/floating_point_mul_add.rs @@ -39,3 +39,21 @@ fn main() { // Cases where the lint shouldn't be applied let _ = (a * a + b * b).sqrt(); } + +fn _issue11831() { + struct NotAFloat; + + impl std::ops::Add for NotAFloat { + type Output = Self; + + fn add(self, _: f64) -> Self { + NotAFloat + } + } + + let a = NotAFloat; + let b = 1.0_f64; + let c = 1.0; + + let _ = a + b * c; +} diff --git a/src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr b/src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr index afb7c6b4dbda4..f49b7a0977fef 100644 --- a/src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr +++ b/src/tools/clippy/tests/ui/four_forward_slashes_first_line.stderr @@ -12,5 +12,5 @@ help: make this a doc comment by removing one `/` LL + /// borked doc comment on the first line. doesn't combust! | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/functions_maxlines.stderr b/src/tools/clippy/tests/ui/functions_maxlines.stderr index 1d6ddad79ff2d..497acc0a65ea0 100644 --- a/src/tools/clippy/tests/ui/functions_maxlines.stderr +++ b/src/tools/clippy/tests/ui/functions_maxlines.stderr @@ -13,5 +13,5 @@ LL | | } = note: `-D clippy::too-many-lines` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::too_many_lines)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.rs b/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.rs new file mode 100644 index 0000000000000..f6ce6153e01d1 --- /dev/null +++ b/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.rs @@ -0,0 +1,136 @@ +#![warn(clippy::impl_hash_borrow_with_str_and_bytes)] + +use std::borrow::Borrow; +use std::hash::{Hash, Hasher}; + +struct ExampleType { + data: String, +} + +impl Hash for ExampleType { + //~^ ERROR: can't + fn hash(&self, state: &mut H) { + self.data.hash(state); + } +} + +impl Borrow for ExampleType { + fn borrow(&self) -> &str { + &self.data + } +} + +impl Borrow<[u8]> for ExampleType { + fn borrow(&self) -> &[u8] { + self.data.as_bytes() + } +} + +struct ShouldNotRaiseForHash {} +impl Hash for ShouldNotRaiseForHash { + fn hash(&self, state: &mut H) { + todo!(); + } +} + +struct ShouldNotRaiseForBorrow {} +impl Borrow for ShouldNotRaiseForBorrow { + fn borrow(&self) -> &str { + todo!(); + } +} +impl Borrow<[u8]> for ShouldNotRaiseForBorrow { + fn borrow(&self) -> &[u8] { + todo!(); + } +} + +struct ShouldNotRaiseForHashBorrowStr {} +impl Hash for ShouldNotRaiseForHashBorrowStr { + fn hash(&self, state: &mut H) { + todo!(); + } +} +impl Borrow for ShouldNotRaiseForHashBorrowStr { + fn borrow(&self) -> &str { + todo!(); + } +} + +struct ShouldNotRaiseForHashBorrowSlice {} +impl Hash for ShouldNotRaiseForHashBorrowSlice { + fn hash(&self, state: &mut H) { + todo!(); + } +} + +impl Borrow<[u8]> for ShouldNotRaiseForHashBorrowSlice { + fn borrow(&self) -> &[u8] { + todo!(); + } +} + +#[derive(Hash)] +//~^ ERROR: can't +struct Derived { + data: String, +} + +impl Borrow for Derived { + fn borrow(&self) -> &str { + self.data.as_str() + } +} + +impl Borrow<[u8]> for Derived { + fn borrow(&self) -> &[u8] { + self.data.as_bytes() + } +} + +struct GenericExampleType { + data: T, +} + +impl Hash for GenericExampleType { + fn hash(&self, state: &mut H) { + self.data.hash(state); + } +} + +impl Borrow for GenericExampleType { + fn borrow(&self) -> &str { + &self.data + } +} + +impl Borrow<[u8]> for GenericExampleType<&'static [u8]> { + fn borrow(&self) -> &[u8] { + self.data + } +} + +struct GenericExampleType2 { + data: T, +} + +impl Hash for GenericExampleType2 { + //~^ ERROR: can't + // this is correctly throwing an error for generic with concrete impl + // for all 3 types + fn hash(&self, state: &mut H) { + self.data.hash(state); + } +} + +impl Borrow for GenericExampleType2 { + fn borrow(&self) -> &str { + &self.data + } +} + +impl Borrow<[u8]> for GenericExampleType2 { + fn borrow(&self) -> &[u8] { + self.data.as_bytes() + } +} diff --git a/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr b/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr new file mode 100644 index 0000000000000..afc35ef98459b --- /dev/null +++ b/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr @@ -0,0 +1,41 @@ +error: the semantics of `Borrow` around `Hash` can't be satisfied when both `Borrow` and `Borrow<[u8]>` are implemented + --> $DIR/impl_hash_with_borrow_str_and_bytes.rs:10:6 + | +LL | impl Hash for ExampleType { + | ^^^^ + | + = note: the `Borrow` semantics require that `Hash` must behave the same for all implementations of Borrow + = note: however, the hash implementations of a string (`str`) and the bytes of a string `[u8]` do not behave the same ... + = note: ... as (`hash("abc") != hash("abc".as_bytes())` + = help: consider either removing one of the `Borrow` implementations (`Borrow` or `Borrow<[u8]>`) ... + = help: ... or not implementing `Hash` for this type + = note: `-D clippy::impl-hash-borrow-with-str-and-bytes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::impl_hash_borrow_with_str_and_bytes)]` + +error: the semantics of `Borrow` around `Hash` can't be satisfied when both `Borrow` and `Borrow<[u8]>` are implemented + --> $DIR/impl_hash_with_borrow_str_and_bytes.rs:73:10 + | +LL | #[derive(Hash)] + | ^^^^ + | + = note: the `Borrow` semantics require that `Hash` must behave the same for all implementations of Borrow + = note: however, the hash implementations of a string (`str`) and the bytes of a string `[u8]` do not behave the same ... + = note: ... as (`hash("abc") != hash("abc".as_bytes())` + = help: consider either removing one of the `Borrow` implementations (`Borrow` or `Borrow<[u8]>`) ... + = help: ... or not implementing `Hash` for this type + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: the semantics of `Borrow` around `Hash` can't be satisfied when both `Borrow` and `Borrow<[u8]>` are implemented + --> $DIR/impl_hash_with_borrow_str_and_bytes.rs:117:6 + | +LL | impl Hash for GenericExampleType2 { + | ^^^^ + | + = note: the `Borrow` semantics require that `Hash` must behave the same for all implementations of Borrow + = note: however, the hash implementations of a string (`str`) and the bytes of a string `[u8]` do not behave the same ... + = note: ... as (`hash("abc") != hash("abc".as_bytes())` + = help: consider either removing one of the `Borrow` implementations (`Borrow` or `Borrow<[u8]>`) ... + = help: ... or not implementing `Hash` for this type + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr index 11b19428b4fdc..429861e993e82 100644 --- a/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr +++ b/src/tools/clippy/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr @@ -18,5 +18,5 @@ help: and replace the index expressions here LL | println!("{}", slice_0); | ~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/inspect_for_each.stderr b/src/tools/clippy/tests/ui/inspect_for_each.stderr index 80df86ad64ec9..8bd4fe3987c5d 100644 --- a/src/tools/clippy/tests/ui/inspect_for_each.stderr +++ b/src/tools/clippy/tests/ui/inspect_for_each.stderr @@ -14,5 +14,5 @@ LL | | }); = note: `-D clippy::inspect-for-each` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::inspect_for_each)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/issue-3145.stderr b/src/tools/clippy/tests/ui/issue-3145.stderr index d7c2c88a20470..51debc9b72f82 100644 --- a/src/tools/clippy/tests/ui/issue-3145.stderr +++ b/src/tools/clippy/tests/ui/issue-3145.stderr @@ -4,5 +4,5 @@ error: expected `,`, found `a` LL | println!("{}" a); | ^ expected `,` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/issue_2356.stderr b/src/tools/clippy/tests/ui/issue_2356.stderr index d04b49e52a55a..860c545c7b827 100644 --- a/src/tools/clippy/tests/ui/issue_2356.stderr +++ b/src/tools/clippy/tests/ui/issue_2356.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(clippy::while_let_on_iterator)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr index 4e99876365cf8..30aa90d29bf8c 100644 --- a/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr +++ b/src/tools/clippy/tests/ui/items_after_test_module/in_submodule.stderr @@ -10,5 +10,5 @@ LL | fn in_submodule() {} = note: `-D clippy::items-after-test-module` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::items_after_test_module)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr b/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr index 67bc82ebff91f..17b07cc32f4e3 100644 --- a/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr +++ b/src/tools/clippy/tests/ui/items_after_test_module/root_module.stderr @@ -16,5 +16,5 @@ LL | macro_rules! should_lint { = help: to override `-D warnings` add `#[allow(clippy::items_after_test_module)]` = help: move the items to before the test module was defined -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/iter_kv_map.fixed b/src/tools/clippy/tests/ui/iter_kv_map.fixed index 566a5b690d84f..2cbf972fca5fb 100644 --- a/src/tools/clippy/tests/ui/iter_kv_map.fixed +++ b/src/tools/clippy/tests/ui/iter_kv_map.fixed @@ -89,3 +89,46 @@ fn main() { // Don't let a mut interfere. let _ = map.clone().into_values().count(); } + +#[clippy::msrv = "1.53"] +fn msrv_1_53() { + let map: HashMap = HashMap::new(); + + // Don't lint because into_iter is not supported + let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); + let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); + + let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); + let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); + + // Lint + let _ = map.keys().collect::>(); + //~^ ERROR: iterating on a map's keys + let _ = map.values().collect::>(); + //~^ ERROR: iterating on a map's values + let _ = map.values().map(|v| v + 2).collect::>(); + //~^ ERROR: iterating on a map's values +} + +#[clippy::msrv = "1.54"] +fn msrv_1_54() { + // Lint all + let map: HashMap = HashMap::new(); + + let _ = map.clone().into_keys().collect::>(); + //~^ ERROR: iterating on a map's keys + let _ = map.clone().into_keys().map(|key| key + 2).collect::>(); + //~^ ERROR: iterating on a map's keys + + let _ = map.clone().into_values().collect::>(); + //~^ ERROR: iterating on a map's values + let _ = map.clone().into_values().map(|val| val + 2).collect::>(); + //~^ ERROR: iterating on a map's values + + let _ = map.keys().collect::>(); + //~^ ERROR: iterating on a map's keys + let _ = map.values().collect::>(); + //~^ ERROR: iterating on a map's values + let _ = map.values().map(|v| v + 2).collect::>(); + //~^ ERROR: iterating on a map's values +} diff --git a/src/tools/clippy/tests/ui/iter_kv_map.rs b/src/tools/clippy/tests/ui/iter_kv_map.rs index d85e501da487f..6a9a4267a7657 100644 --- a/src/tools/clippy/tests/ui/iter_kv_map.rs +++ b/src/tools/clippy/tests/ui/iter_kv_map.rs @@ -93,3 +93,46 @@ fn main() { // Don't let a mut interfere. let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); } + +#[clippy::msrv = "1.53"] +fn msrv_1_53() { + let map: HashMap = HashMap::new(); + + // Don't lint because into_iter is not supported + let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); + let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); + + let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); + let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); + + // Lint + let _ = map.iter().map(|(key, _)| key).collect::>(); + //~^ ERROR: iterating on a map's keys + let _ = map.iter().map(|(_, value)| value).collect::>(); + //~^ ERROR: iterating on a map's values + let _ = map.iter().map(|(_, v)| v + 2).collect::>(); + //~^ ERROR: iterating on a map's values +} + +#[clippy::msrv = "1.54"] +fn msrv_1_54() { + // Lint all + let map: HashMap = HashMap::new(); + + let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); + //~^ ERROR: iterating on a map's keys + let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); + //~^ ERROR: iterating on a map's keys + + let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); + //~^ ERROR: iterating on a map's values + let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); + //~^ ERROR: iterating on a map's values + + let _ = map.iter().map(|(key, _)| key).collect::>(); + //~^ ERROR: iterating on a map's keys + let _ = map.iter().map(|(_, value)| value).collect::>(); + //~^ ERROR: iterating on a map's values + let _ = map.iter().map(|(_, v)| v + 2).collect::>(); + //~^ ERROR: iterating on a map's values +} diff --git a/src/tools/clippy/tests/ui/iter_kv_map.stderr b/src/tools/clippy/tests/ui/iter_kv_map.stderr index 62155b7f838e2..471615978e1e5 100644 --- a/src/tools/clippy/tests/ui/iter_kv_map.stderr +++ b/src/tools/clippy/tests/ui/iter_kv_map.stderr @@ -201,5 +201,65 @@ error: iterating on a map's values LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` -error: aborting due to 28 previous errors +error: iterating on a map's keys + --> $DIR/iter_kv_map.rs:109:13 + | +LL | let _ = map.iter().map(|(key, _)| key).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` + +error: iterating on a map's values + --> $DIR/iter_kv_map.rs:111:13 + | +LL | let _ = map.iter().map(|(_, value)| value).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` + +error: iterating on a map's values + --> $DIR/iter_kv_map.rs:113:13 + | +LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` + +error: iterating on a map's keys + --> $DIR/iter_kv_map.rs:122:13 + | +LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` + +error: iterating on a map's keys + --> $DIR/iter_kv_map.rs:124:13 + | +LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` + +error: iterating on a map's values + --> $DIR/iter_kv_map.rs:127:13 + | +LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` + +error: iterating on a map's values + --> $DIR/iter_kv_map.rs:129:13 + | +LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` + +error: iterating on a map's keys + --> $DIR/iter_kv_map.rs:132:13 + | +LL | let _ = map.iter().map(|(key, _)| key).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` + +error: iterating on a map's values + --> $DIR/iter_kv_map.rs:134:13 + | +LL | let _ = map.iter().map(|(_, value)| value).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` + +error: iterating on a map's values + --> $DIR/iter_kv_map.rs:136:13 + | +LL | let _ = map.iter().map(|(_, v)| v + 2).collect::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` + +error: aborting due to 38 previous errors diff --git a/src/tools/clippy/tests/ui/iter_next_loop.stderr b/src/tools/clippy/tests/ui/iter_next_loop.stderr index 5bba0e635bba6..5871d21e49157 100644 --- a/src/tools/clippy/tests/ui/iter_next_loop.stderr +++ b/src/tools/clippy/tests/ui/iter_next_loop.stderr @@ -4,6 +4,6 @@ error[E0423]: expected value, found macro `vec` LL | for _ in vec.iter().next() {} | ^^^ not a value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/src/tools/clippy/tests/ui/iter_over_hash_type.rs b/src/tools/clippy/tests/ui/iter_over_hash_type.rs new file mode 100644 index 0000000000000..7000c8bf96f8d --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_over_hash_type.rs @@ -0,0 +1,74 @@ +//@aux-build:proc_macros.rs +#![feature(rustc_private)] +#![warn(clippy::iter_over_hash_type)] +use std::collections::{HashMap, HashSet}; + +extern crate rustc_data_structures; + +extern crate proc_macros; + +fn main() { + let mut hash_set = HashSet::::new(); + let mut hash_map = HashMap::::new(); + let mut fx_hash_map = rustc_data_structures::fx::FxHashMap::::default(); + let mut fx_hash_set = rustc_data_structures::fx::FxHashMap::::default(); + let vec = Vec::::new(); + + // test hashset + for x in &hash_set { + let _ = x; + } + for x in hash_set.iter() { + let _ = x; + } + for x in hash_set.clone() { + let _ = x; + } + for x in hash_set.drain() { + let _ = x; + } + + // test hashmap + for (x, y) in &hash_map { + let _ = (x, y); + } + for x in hash_map.keys() { + let _ = x; + } + for x in hash_map.values() { + let _ = x; + } + for x in hash_map.values_mut() { + *x += 1; + } + for x in hash_map.iter() { + let _ = x; + } + for x in hash_map.clone() { + let _ = x; + } + for x in hash_map.drain() { + let _ = x; + } + + // test type-aliased hashers + for x in fx_hash_set { + let _ = x; + } + for x in fx_hash_map { + let _ = x; + } + + // shouldnt fire + for x in &vec { + let _ = x; + } + for x in vec { + let _ = x; + } + + // should not lint, this comes from an external crate + proc_macros::external! { + for _ in HashMap::::new() {} + } +} diff --git a/src/tools/clippy/tests/ui/iter_over_hash_type.stderr b/src/tools/clippy/tests/ui/iter_over_hash_type.stderr new file mode 100644 index 0000000000000..cf420fb8e996e --- /dev/null +++ b/src/tools/clippy/tests/ui/iter_over_hash_type.stderr @@ -0,0 +1,109 @@ +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:18:5 + | +LL | / for x in &hash_set { +LL | | let _ = x; +LL | | } + | |_____^ + | + = note: `-D clippy::iter-over-hash-type` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::iter_over_hash_type)]` + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:21:5 + | +LL | / for x in hash_set.iter() { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:24:5 + | +LL | / for x in hash_set.clone() { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:27:5 + | +LL | / for x in hash_set.drain() { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:32:5 + | +LL | / for (x, y) in &hash_map { +LL | | let _ = (x, y); +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:35:5 + | +LL | / for x in hash_map.keys() { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:38:5 + | +LL | / for x in hash_map.values() { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:41:5 + | +LL | / for x in hash_map.values_mut() { +LL | | *x += 1; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:44:5 + | +LL | / for x in hash_map.iter() { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:47:5 + | +LL | / for x in hash_map.clone() { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:50:5 + | +LL | / for x in hash_map.drain() { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:55:5 + | +LL | / for x in fx_hash_set { +LL | | let _ = x; +LL | | } + | |_____^ + +error: iteration over unordered hash-based type + --> $DIR/iter_over_hash_type.rs:58:5 + | +LL | / for x in fx_hash_map { +LL | | let _ = x; +LL | | } + | |_____^ + +error: aborting due to 13 previous errors + diff --git a/src/tools/clippy/tests/ui/join_absolute_paths.rs b/src/tools/clippy/tests/ui/join_absolute_paths.rs new file mode 100644 index 0000000000000..efa77a0492e61 --- /dev/null +++ b/src/tools/clippy/tests/ui/join_absolute_paths.rs @@ -0,0 +1,30 @@ +//@no-rustfix + +#![allow(clippy::needless_raw_string_hashes)] +#![warn(clippy::join_absolute_paths)] + +use std::path::{Path, PathBuf}; + +fn main() { + let path = Path::new("/bin"); + path.join("/sh"); + //~^ ERROR: argument to `Path::join` starts with a path separator + + let path = Path::new("C:\\Users"); + path.join("\\user"); + //~^ ERROR: argument to `Path::join` starts with a path separator + + let path = PathBuf::from("/bin"); + path.join("/sh"); + //~^ ERROR: argument to `Path::join` starts with a path separator + + let path = PathBuf::from("/bin"); + path.join(r#"/sh"#); + //~^ ERROR: argument to `Path::join` starts with a path separator + + let path: &[&str] = &["/bin"]; + path.join("/sh"); + + let path = Path::new("/bin"); + path.join("sh"); +} diff --git a/src/tools/clippy/tests/ui/join_absolute_paths.stderr b/src/tools/clippy/tests/ui/join_absolute_paths.stderr new file mode 100644 index 0000000000000..0c2f89d9978b3 --- /dev/null +++ b/src/tools/clippy/tests/ui/join_absolute_paths.stderr @@ -0,0 +1,68 @@ +error: argument to `Path::join` starts with a path separator + --> $DIR/join_absolute_paths.rs:10:15 + | +LL | path.join("/sh"); + | ^^^^^ + | + = note: joining a path starting with separator will replace the path instead + = note: `-D clippy::join-absolute-paths` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::join_absolute_paths)]` +help: if this is unintentional, try removing the starting separator + | +LL | path.join("sh"); + | ~~~~ +help: if this is intentional, try using `Path::new` instead + | +LL | PathBuf::from("/sh"); + | ~~~~~~~~~~~~~~~~~~~~ + +error: argument to `Path::join` starts with a path separator + --> $DIR/join_absolute_paths.rs:14:15 + | +LL | path.join("\\user"); + | ^^^^^^^^ + | + = note: joining a path starting with separator will replace the path instead +help: if this is unintentional, try removing the starting separator + | +LL | path.join("\user"); + | ~~~~~~~ +help: if this is intentional, try using `Path::new` instead + | +LL | PathBuf::from("\\user"); + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: argument to `Path::join` starts with a path separator + --> $DIR/join_absolute_paths.rs:18:15 + | +LL | path.join("/sh"); + | ^^^^^ + | + = note: joining a path starting with separator will replace the path instead +help: if this is unintentional, try removing the starting separator + | +LL | path.join("sh"); + | ~~~~ +help: if this is intentional, try using `Path::new` instead + | +LL | PathBuf::from("/sh"); + | ~~~~~~~~~~~~~~~~~~~~ + +error: argument to `Path::join` starts with a path separator + --> $DIR/join_absolute_paths.rs:22:15 + | +LL | path.join(r#"/sh"#); + | ^^^^^^^^ + | + = note: joining a path starting with separator will replace the path instead +help: if this is unintentional, try removing the starting separator + | +LL | path.join(r#"sh"#); + | ~~~~~~~ +help: if this is intentional, try using `Path::new` instead + | +LL | PathBuf::from(r#"/sh"#); + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed b/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed index 74ef6f72957f7..621115cc13258 100644 --- a/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed +++ b/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed @@ -10,11 +10,17 @@ fn main() -> io::Result<()> { // Lint let f = std::fs::File::open("/")?; BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ()); + // Lint + let f = std::fs::File::open("/")?; + BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ()); + let s = "foo\nbar\nbaz\n"; // Lint io::stdin().lines().map_while(Result::ok).for_each(|_| ()); // Lint io::stdin().lines().map_while(Result::ok).for_each(|_| ()); + // Lint + io::stdin().lines().map_while(Result::ok).for_each(|_| ()); // Do not lint (not a `Lines` iterator) io::stdin() .lines() diff --git a/src/tools/clippy/tests/ui/lines_filter_map_ok.rs b/src/tools/clippy/tests/ui/lines_filter_map_ok.rs index 345f4dc5f3045..a86efbd668623 100644 --- a/src/tools/clippy/tests/ui/lines_filter_map_ok.rs +++ b/src/tools/clippy/tests/ui/lines_filter_map_ok.rs @@ -10,11 +10,17 @@ fn main() -> io::Result<()> { // Lint let f = std::fs::File::open("/")?; BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ()); + // Lint + let f = std::fs::File::open("/")?; + BufReader::new(f).lines().flatten().for_each(|_| ()); + let s = "foo\nbar\nbaz\n"; // Lint io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); // Lint io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); + // Lint + io::stdin().lines().flatten().for_each(|_| ()); // Do not lint (not a `Lines` iterator) io::stdin() .lines() diff --git a/src/tools/clippy/tests/ui/lines_filter_map_ok.stderr b/src/tools/clippy/tests/ui/lines_filter_map_ok.stderr index fa2ba0a9a4625..9833ab16473c8 100644 --- a/src/tools/clippy/tests/ui/lines_filter_map_ok.stderr +++ b/src/tools/clippy/tests/ui/lines_filter_map_ok.stderr @@ -24,29 +24,53 @@ note: this expression returning a `std::io::Lines` may produce an infinite numbe LL | BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ +error: `flatten()` will run forever if the iterator repeatedly produces an `Err` + --> $DIR/lines_filter_map_ok.rs:15:31 + | +LL | BufReader::new(f).lines().flatten().for_each(|_| ()); + | ^^^^^^^^^ help: replace with: `map_while(Result::ok)` + | +note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error + --> $DIR/lines_filter_map_ok.rs:15:5 + | +LL | BufReader::new(f).lines().flatten().for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + error: `filter_map()` will run forever if the iterator repeatedly produces an `Err` - --> $DIR/lines_filter_map_ok.rs:15:25 + --> $DIR/lines_filter_map_ok.rs:19:25 | LL | io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` | note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error - --> $DIR/lines_filter_map_ok.rs:15:5 + --> $DIR/lines_filter_map_ok.rs:19:5 | LL | io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^ error: `filter_map()` will run forever if the iterator repeatedly produces an `Err` - --> $DIR/lines_filter_map_ok.rs:17:25 + --> $DIR/lines_filter_map_ok.rs:21:25 | LL | io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` | note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error - --> $DIR/lines_filter_map_ok.rs:17:5 + --> $DIR/lines_filter_map_ok.rs:21:5 | LL | io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: `flatten()` will run forever if the iterator repeatedly produces an `Err` + --> $DIR/lines_filter_map_ok.rs:23:25 + | +LL | io::stdin().lines().flatten().for_each(|_| ()); + | ^^^^^^^^^ help: replace with: `map_while(Result::ok)` + | +note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error + --> $DIR/lines_filter_map_ok.rs:23:5 + | +LL | io::stdin().lines().flatten().for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr index 6de869699ec6d..5524e7e5642df 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.stderr +++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr @@ -1,8 +1,8 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:25:5 + --> $DIR/macro_use_imports.rs:19:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` | = note: `-D clippy::macro-use-imports` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::macro_use_imports)]` @@ -14,16 +14,16 @@ LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:21:5 + --> $DIR/macro_use_imports.rs:25:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> $DIR/macro_use_imports.rs:19:5 + --> $DIR/macro_use_imports.rs:21:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs index 27717ab3a73a6..5d94660ec89ad 100644 --- a/src/tools/clippy/tests/ui/manual_let_else.rs +++ b/src/tools/clippy/tests/ui/manual_let_else.rs @@ -5,7 +5,9 @@ clippy::let_unit_value, clippy::match_single_binding, clippy::never_loop, - clippy::needless_if + clippy::needless_if, + clippy::diverging_sub_expression, + clippy::single_match )] #![warn(clippy::manual_let_else)] //@no-rustfix @@ -24,7 +26,7 @@ fn main() {} fn fire() { let v = if let Some(v_some) = g() { v_some } else { return }; //~^ ERROR: this could be rewritten as `let...else` - //~| NOTE: `-D clippy::manual-let-else` implied by `-D warnings` + let v = if let Some(v_some) = g() { //~^ ERROR: this could be rewritten as `let...else` v_some @@ -79,22 +81,76 @@ fn fire() { panic!(); }; + // The final expression will need to be turned into a statement. + let v = if let Some(v_some) = g() { + //~^ ERROR: this could be rewritten as `let...else` + v_some + } else { + panic!(); + () + }; + + // Even if the result is buried multiple expressions deep. + let v = if let Some(v_some) = g() { + //~^ ERROR: this could be rewritten as `let...else` + v_some + } else { + panic!(); + if true { + match 0 { + 0 => (), + _ => (), + } + } else { + panic!() + } + }; + + // Or if a break gives the value. + let v = if let Some(v_some) = g() { + //~^ ERROR: this could be rewritten as `let...else` + v_some + } else { + loop { + panic!(); + break (); + } + }; + + // Even if the break is in a weird position. + let v = if let Some(v_some) = g() { + //~^ ERROR: this could be rewritten as `let...else` + v_some + } else { + 'a: loop { + panic!(); + loop { + match 0 { + 0 if (return break 'a ()) => {}, + _ => {}, + } + } + } + }; + // A match diverges if all branches diverge: - // Note: the corresponding let-else requires a ; at the end of the match - // as otherwise the type checker does not turn it into a ! type. let v = if let Some(v_some) = g() { //~^ ERROR: this could be rewritten as `let...else` v_some } else { - match () { - _ if panic!() => {}, + match 0 { + 0 if true => panic!(), _ => panic!(), - } + }; }; // An if's expression can cause divergence: - let v = if let Some(v_some) = g() { v_some } else { if panic!() {} }; - //~^ ERROR: this could be rewritten as `let...else` + let v = if let Some(v_some) = g() { + //~^ ERROR: this could be rewritten as `let...else` + v_some + } else { + if panic!() {}; + }; // An expression of a match can cause divergence: let v = if let Some(v_some) = g() { @@ -103,7 +159,7 @@ fn fire() { } else { match panic!() { _ => {}, - } + }; }; // Top level else if @@ -342,6 +398,43 @@ fn not_fire() { } else { return; }; + + // A break that skips the divergent statement will cause the expression to be non-divergent. + let _x = if let Some(x) = Some(0) { + x + } else { + 'foo: loop { + break 'foo 0; + panic!(); + } + }; + + // Even in inner loops. + let _x = if let Some(x) = Some(0) { + x + } else { + 'foo: { + loop { + break 'foo 0; + } + panic!(); + } + }; + + // But a break that can't ever be reached still affects divergence checking. + let _x = if let Some(x) = g() { + x + } else { + 'foo: { + 'bar: loop { + loop { + break 'bar (); + } + break 'foo (); + } + panic!(); + }; + }; } struct S { diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr index 2b6504a18278d..3beaf766efb13 100644 --- a/src/tools/clippy/tests/ui/manual_let_else.stderr +++ b/src/tools/clippy/tests/ui/manual_let_else.stderr @@ -1,5 +1,5 @@ error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:25:5 + --> $DIR/manual_let_else.rs:27:5 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` @@ -8,7 +8,7 @@ LL | let v = if let Some(v_some) = g() { v_some } else { return }; = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:28:5 + --> $DIR/manual_let_else.rs:30:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -26,7 +26,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:35:5 + --> $DIR/manual_let_else.rs:37:5 | LL | / let v = if let Some(v) = g() { LL | | @@ -47,25 +47,25 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:47:9 + --> $DIR/manual_let_else.rs:49:9 | LL | let v = if let Some(v_some) = g() { v_some } else { continue }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:49:9 + --> $DIR/manual_let_else.rs:51:9 | LL | let v = if let Some(v_some) = g() { v_some } else { break }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:54:5 + --> $DIR/manual_let_else.rs:56:5 | LL | let v = if let Some(v_some) = g() { v_some } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:58:5 + --> $DIR/manual_let_else.rs:60:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -83,7 +83,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:66:5 + --> $DIR/manual_let_else.rs:68:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -101,7 +101,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:74:5 + --> $DIR/manual_let_else.rs:76:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -127,6 +127,26 @@ LL | / let v = if let Some(v_some) = g() { LL | | LL | | v_some LL | | } else { +LL | | panic!(); +LL | | () +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(v) = g() else { +LL + panic!(); +LL + () +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:94:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | +LL | | v_some +LL | | } else { ... | LL | | } LL | | }; @@ -135,21 +155,42 @@ LL | | }; help: consider writing | LL ~ let Some(v) = g() else { -LL + match () { -LL + _ if panic!() => {}, -LL + _ => panic!(), +LL + panic!(); +LL + if true { +LL + match 0 { +LL + 0 => (), +LL + _ => (), +LL + } +LL + } else { +LL + panic!() LL + } LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:96:5 + --> $DIR/manual_let_else.rs:110:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | +LL | | v_some +LL | | } else { +... | +LL | | } +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(v) = g() else { +LL + loop { +LL + panic!(); +LL + break (); +LL + } +LL + }; | -LL | let v = if let Some(v_some) = g() { v_some } else { if panic!() {} }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:100:5 + --> $DIR/manual_let_else.rs:121:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -163,14 +204,81 @@ LL | | }; help: consider writing | LL ~ let Some(v) = g() else { +LL + 'a: loop { +LL + panic!(); +LL + loop { +LL + match 0 { +LL + 0 if (return break 'a ()) => {}, +LL + _ => {}, +LL + } +LL + } +LL + } +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:137:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | +LL | | v_some +LL | | } else { +... | +LL | | }; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(v) = g() else { +LL + match 0 { +LL + 0 if true => panic!(), +LL + _ => panic!(), +LL + }; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:148:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | +LL | | v_some +LL | | } else { +LL | | if panic!() {}; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(v) = g() else { +LL + if panic!() {}; +LL + }; + | + +error: this could be rewritten as `let...else` + --> $DIR/manual_let_else.rs:156:5 + | +LL | / let v = if let Some(v_some) = g() { +LL | | +LL | | v_some +LL | | } else { +... | +LL | | }; +LL | | }; + | |______^ + | +help: consider writing + | +LL ~ let Some(v) = g() else { LL + match panic!() { LL + _ => {}, -LL + } +LL + }; LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:110:5 + --> $DIR/manual_let_else.rs:166:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -191,7 +299,7 @@ LL + } }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:120:5 + --> $DIR/manual_let_else.rs:176:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -220,7 +328,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:138:5 + --> $DIR/manual_let_else.rs:194:5 | LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { LL | | @@ -238,7 +346,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:146:5 + --> $DIR/manual_let_else.rs:202:5 | LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { LL | | @@ -256,7 +364,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:156:13 + --> $DIR/manual_let_else.rs:212:13 | LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` @@ -267,19 +375,19 @@ LL | create_binding_if_some!(w, g()); = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:165:5 + --> $DIR/manual_let_else.rs:221:5 | LL | let v = if let Variant::A(a, 0) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:169:5 + --> $DIR/manual_let_else.rs:225:5 | LL | let mut v = if let Variant::B(b) = e() { b } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:174:5 + --> $DIR/manual_let_else.rs:230:5 | LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { LL | | @@ -297,19 +405,19 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:181:5 + --> $DIR/manual_let_else.rs:237:5 | LL | let v = if let Variant::A(.., a) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:185:5 + --> $DIR/manual_let_else.rs:241:5 | LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };` error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:189:5 + --> $DIR/manual_let_else.rs:245:5 | LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | @@ -327,7 +435,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:197:5 + --> $DIR/manual_let_else.rs:253:5 | LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | @@ -345,7 +453,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:205:5 + --> $DIR/manual_let_else.rs:261:5 | LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { LL | | @@ -363,7 +471,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> $DIR/manual_let_else.rs:322:5 + --> $DIR/manual_let_else.rs:378:5 | LL | / let _ = match ff { LL | | @@ -372,5 +480,5 @@ LL | | _ => macro_call!(), LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` -error: aborting due to 26 previous errors +error: aborting due to 30 previous errors diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs index a224001a3dfd6..8146091a2bbe4 100644 --- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs +++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs @@ -138,6 +138,26 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { for i in 0..dst.len() { dst[i] = src[i]; } + + // Range is equal to array length + let src = [0, 1, 2, 3, 4]; + let mut dst = [0; 4]; + for i in 0..4 { + //~^ ERROR: it looks like you're manually copying between slices + dst[i] = src[i]; + } + + let mut dst = [0; 6]; + for i in 0..5 { + //~^ ERROR: it looks like you're manually copying between slices + dst[i] = src[i]; + } + + let mut dst = [0; 5]; + for i in 0..5 { + //~^ ERROR: it looks like you're manually copying between slices + dst[i] = src[i]; + } } #[warn(clippy::needless_range_loop, clippy::manual_memcpy)] diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr index b9dbda6ede71f..4b5cd274da78f 100644 --- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr +++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr @@ -106,7 +106,7 @@ LL | / for i in 0..5 { LL | | LL | | dst[i - 0] = src[i]; LL | | } - | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src[..5]);` + | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);` error: it looks like you're manually copying between slices --> $DIR/without_loop_counters.rs:121:5 @@ -120,11 +120,38 @@ LL | | } error: it looks like you're manually copying between slices --> $DIR/without_loop_counters.rs:145:5 | +LL | / for i in 0..4 { +LL | | +LL | | dst[i] = src[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..4]);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:151:5 + | +LL | / for i in 0..5 { +LL | | +LL | | dst[i] = src[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:157:5 + | +LL | / for i in 0..5 { +LL | | +LL | | dst[i] = src[i]; +LL | | } + | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src);` + +error: it looks like you're manually copying between slices + --> $DIR/without_loop_counters.rs:165:5 + | LL | / for i in 0..src.len() { LL | | LL | | dst[i] = src[i].clone(); LL | | } | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..]);` -error: aborting due to 13 previous errors +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs index e32ba8631761b..eb38753203110 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs @@ -26,7 +26,7 @@ enum NoDocHidden { _C, } -// name of variant with doc hidden does not start with underscore, should be ignored +// name of variant with doc hidden does not start with underscore enum NoUnderscore { A, B, diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr index 7361a4a2cbbe8..c4b13a577a96b 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr @@ -22,5 +22,26 @@ LL | _C, = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]` -error: aborting due to previous error +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive_enum.rs:30:1 + | +LL | enum NoUnderscore { + | ^---------------- + | | + | _help: add the attribute: `#[non_exhaustive] enum NoUnderscore` + | | +LL | | A, +LL | | B, +LL | | #[doc(hidden)] +LL | | C, +LL | | } + | |_^ + | +help: remove this variant + --> $DIR/manual_non_exhaustive_enum.rs:34:5 + | +LL | C, + | ^ + +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr index 028b8ff763915..0b88b19691e13 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr @@ -38,6 +38,26 @@ help: remove this field LL | _c: (), | ^^^^^^ +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive_struct.rs:29:5 + | +LL | struct NoUnderscore { + | ^------------------ + | | + | _____help: add the attribute: `#[non_exhaustive] struct NoUnderscore` + | | +LL | | pub a: i32, +LL | | pub b: i32, +LL | | c: (), +LL | | } + | |_____^ + | +help: remove this field + --> $DIR/manual_non_exhaustive_struct.rs:32:9 + | +LL | c: (), + | ^^^^^ + error: this seems like a manual implementation of the non-exhaustive pattern --> $DIR/manual_non_exhaustive_struct.rs:56:5 | @@ -64,5 +84,5 @@ help: remove this field LL | struct Tp(pub i32, pub i32, ()); | ^^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/manual_ok_or.stderr b/src/tools/clippy/tests/ui/manual_ok_or.stderr index ddb2cf261e404..b277d22e59b63 100644 --- a/src/tools/clippy/tests/ui/manual_ok_or.stderr +++ b/src/tools/clippy/tests/ui/manual_ok_or.stderr @@ -13,6 +13,15 @@ error: this pattern reimplements `Option::ok_or` LL | foo.map_or(Err("error"), Ok); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `foo.ok_or("error")` +error: called `map_or(Err(_), Ok)` on an `Option` value + --> $DIR/manual_ok_or.rs:14:5 + | +LL | foo.map_or(Err("error"), Ok); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok_or` instead: `foo.ok_or("error")` + | + = note: `-D clippy::option-map-or-err-ok` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::option_map_or_err_ok)]` + error: this pattern reimplements `Option::ok_or` --> $DIR/manual_ok_or.rs:17:5 | @@ -38,5 +47,5 @@ LL + "{}{}{}{}{}{}{}", LL ~ "Alice", "Bob", "Sarah", "Marc", "Sandra", "Eric", "Jenifer")); | -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/manual_try_fold.rs b/src/tools/clippy/tests/ui/manual_try_fold.rs index bddf03ac3f1fe..7299d7cf98629 100644 --- a/src/tools/clippy/tests/ui/manual_try_fold.rs +++ b/src/tools/clippy/tests/ui/manual_try_fold.rs @@ -96,3 +96,33 @@ fn msrv_juust_right() { .fold(Some(0i32), |sum, i| sum?.checked_add(*i)) .unwrap(); } + +mod issue11876 { + struct Foo; + + impl Bar for Foo { + type Output = u32; + } + + trait Bar: Sized { + type Output; + fn fold(self, init: A, func: F) -> Fold + where + A: Clone, + F: Fn(A, Self::Output) -> A, + { + Fold { this: self, init, func } + } + } + + #[allow(dead_code)] + struct Fold { + this: S, + init: A, + func: F, + } + + fn main() { + Foo.fold(Some(0), |acc, entry| Some(acc? + entry)); + } +} diff --git a/src/tools/clippy/tests/ui/map_err.stderr b/src/tools/clippy/tests/ui/map_err.stderr index 6a845c84a2a9d..eb6742ff23382 100644 --- a/src/tools/clippy/tests/ui/map_err.stderr +++ b/src/tools/clippy/tests/ui/map_err.stderr @@ -8,5 +8,5 @@ LL | println!("{:?}", x.map_err(|_| Errors::Ignored)); = note: `-D clippy::map-err-ignore` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::map_err_ignore)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/map_identity.fixed b/src/tools/clippy/tests/ui/map_identity.fixed index 62b0ba0186006..53ebfb40ba0d2 100644 --- a/src/tools/clippy/tests/ui/map_identity.fixed +++ b/src/tools/clippy/tests/ui/map_identity.fixed @@ -24,28 +24,40 @@ fn main() { fn issue7189() { // should lint - let x = [(1, 2), (3, 4)]; - let _ = x.iter(); - let _ = x.iter(); - let _ = x.iter(); + let x = [(1, 2), (3, 4)].iter().copied(); + let _ = x.clone(); + let _ = x.clone(); + let _ = x.clone(); - let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))]; - let _ = y.iter(); + let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied(); + let _ = y.clone(); // should not lint - let _ = x.iter().map(|(x, y)| (x, y, y)); - let _ = x.iter().map(|(x, _y)| (x,)); - let _ = x.iter().map(|(x, _)| (x,)); - let _ = x.iter().map(|(x, ..)| (x,)); - let _ = y.iter().map(|(x, y, (z, _))| (x, y, (z, z))); + let _ = x.clone().map(|(x, y)| (x, y, y)); + let _ = x.clone().map(|(x, _y)| (x,)); + let _ = x.clone().map(|(x, _)| (x,)); + let _ = x.clone().map(|(x, ..)| (x,)); + let _ = y.clone().map(|(x, y, (z, _))| (x, y, (z, z))); let _ = y - .iter() - .map(|(x, y, (z, _)): &(i32, i32, (i32, (i32,)))| (x, y, (z, z))); + .clone() + .map(|(x, y, (z, _)): (i32, i32, (i32, (i32,)))| (x, y, (z, z))); let _ = y - .iter() - .map(|(x, y, (z, (w,))): &(i32, i32, (i32, (i32,)))| (x, y, (z, (w,)))); + .clone() + .map(|(x, y, (z, (w,))): (i32, i32, (i32, (i32,)))| (x, y, (z, (w,)))); } fn not_identity(x: &u16) -> u16 { *x } + +fn issue11764() { + let x = [(1, 2), (3, 4)]; + // don't lint: this is an `Iterator` + // match ergonomics makes the binding patterns into references + // so that its type changes to `Iterator` + let _ = x.iter().map(|(x, y)| (x, y)); + let _ = x.iter().map(|x| (x.0,)).map(|(x,)| x); + + // no match ergonomics for `(i32, i32)` + let _ = x.iter().copied(); +} diff --git a/src/tools/clippy/tests/ui/map_identity.rs b/src/tools/clippy/tests/ui/map_identity.rs index b7f4c99f27309..c646c0568595e 100644 --- a/src/tools/clippy/tests/ui/map_identity.rs +++ b/src/tools/clippy/tests/ui/map_identity.rs @@ -26,30 +26,42 @@ fn main() { fn issue7189() { // should lint - let x = [(1, 2), (3, 4)]; - let _ = x.iter().map(|(x, y)| (x, y)); - let _ = x.iter().map(|(x, y)| { + let x = [(1, 2), (3, 4)].iter().copied(); + let _ = x.clone().map(|(x, y)| (x, y)); + let _ = x.clone().map(|(x, y)| { return (x, y); }); - let _ = x.iter().map(|(x, y)| return (x, y)); + let _ = x.clone().map(|(x, y)| return (x, y)); - let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))]; - let _ = y.iter().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); + let y = [(1, 2, (3, (4,))), (5, 6, (7, (8,)))].iter().copied(); + let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); // should not lint - let _ = x.iter().map(|(x, y)| (x, y, y)); - let _ = x.iter().map(|(x, _y)| (x,)); - let _ = x.iter().map(|(x, _)| (x,)); - let _ = x.iter().map(|(x, ..)| (x,)); - let _ = y.iter().map(|(x, y, (z, _))| (x, y, (z, z))); + let _ = x.clone().map(|(x, y)| (x, y, y)); + let _ = x.clone().map(|(x, _y)| (x,)); + let _ = x.clone().map(|(x, _)| (x,)); + let _ = x.clone().map(|(x, ..)| (x,)); + let _ = y.clone().map(|(x, y, (z, _))| (x, y, (z, z))); let _ = y - .iter() - .map(|(x, y, (z, _)): &(i32, i32, (i32, (i32,)))| (x, y, (z, z))); + .clone() + .map(|(x, y, (z, _)): (i32, i32, (i32, (i32,)))| (x, y, (z, z))); let _ = y - .iter() - .map(|(x, y, (z, (w,))): &(i32, i32, (i32, (i32,)))| (x, y, (z, (w,)))); + .clone() + .map(|(x, y, (z, (w,))): (i32, i32, (i32, (i32,)))| (x, y, (z, (w,)))); } fn not_identity(x: &u16) -> u16 { *x } + +fn issue11764() { + let x = [(1, 2), (3, 4)]; + // don't lint: this is an `Iterator` + // match ergonomics makes the binding patterns into references + // so that its type changes to `Iterator` + let _ = x.iter().map(|(x, y)| (x, y)); + let _ = x.iter().map(|x| (x.0,)).map(|(x,)| x); + + // no match ergonomics for `(i32, i32)` + let _ = x.iter().copied().map(|(x, y)| (x, y)); +} diff --git a/src/tools/clippy/tests/ui/map_identity.stderr b/src/tools/clippy/tests/ui/map_identity.stderr index 4ca24b0b04c4e..ea077d66d6401 100644 --- a/src/tools/clippy/tests/ui/map_identity.stderr +++ b/src/tools/clippy/tests/ui/map_identity.stderr @@ -41,31 +41,37 @@ LL | let _: Result = Ok(1).map_err(|a| a); | ^^^^^^^^^^^^^^^ help: remove the call to `map_err` error: unnecessary map of the identity function - --> $DIR/map_identity.rs:30:21 + --> $DIR/map_identity.rs:30:22 | -LL | let _ = x.iter().map(|(x, y)| (x, y)); - | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` +LL | let _ = x.clone().map(|(x, y)| (x, y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> $DIR/map_identity.rs:31:21 + --> $DIR/map_identity.rs:31:22 | -LL | let _ = x.iter().map(|(x, y)| { - | _____________________^ +LL | let _ = x.clone().map(|(x, y)| { + | ______________________^ LL | | return (x, y); LL | | }); | |______^ help: remove the call to `map` error: unnecessary map of the identity function - --> $DIR/map_identity.rs:34:21 + --> $DIR/map_identity.rs:34:22 | -LL | let _ = x.iter().map(|(x, y)| return (x, y)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` +LL | let _ = x.clone().map(|(x, y)| return (x, y)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` error: unnecessary map of the identity function - --> $DIR/map_identity.rs:37:21 + --> $DIR/map_identity.rs:37:22 | -LL | let _ = y.iter().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` +LL | let _ = y.clone().map(|(x, y, (z, (w,)))| (x, y, (z, (w,)))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` -error: aborting due to 10 previous errors +error: unnecessary map of the identity function + --> $DIR/map_identity.rs:66:30 + | +LL | let _ = x.iter().copied().map(|(x, y)| (x, y)); + | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/map_unwrap_or.stderr b/src/tools/clippy/tests/ui/map_unwrap_or.stderr index 7b7eeb322a55b..54ddd1402e3df 100644 --- a/src/tools/clippy/tests/ui/map_unwrap_or.stderr +++ b/src/tools/clippy/tests/ui/map_unwrap_or.stderr @@ -1,4 +1,4 @@ -error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead +error: called `map().unwrap_or()` on an `Option` value --> $DIR/map_unwrap_or.rs:17:13 | LL | let _ = opt.map(|x| x + 1) @@ -15,7 +15,7 @@ LL - let _ = opt.map(|x| x + 1) LL + let _ = opt.map_or(0, |x| x + 1); | -error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead +error: called `map().unwrap_or()` on an `Option` value --> $DIR/map_unwrap_or.rs:21:13 | LL | let _ = opt.map(|x| { @@ -33,7 +33,7 @@ LL | } LL ~ ); | -error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead +error: called `map().unwrap_or()` on an `Option` value --> $DIR/map_unwrap_or.rs:25:13 | LL | let _ = opt.map(|x| x + 1) @@ -50,7 +50,7 @@ LL + 0 LL ~ }, |x| x + 1); | -error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead +error: called `map().unwrap_or(None)` on an `Option` value --> $DIR/map_unwrap_or.rs:30:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); @@ -62,7 +62,7 @@ LL - let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); LL + let _ = opt.and_then(|x| Some(x + 1)); | -error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead +error: called `map().unwrap_or(None)` on an `Option` value --> $DIR/map_unwrap_or.rs:32:13 | LL | let _ = opt.map(|x| { @@ -80,7 +80,7 @@ LL | } LL ~ ); | -error: called `map().unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then()` instead +error: called `map().unwrap_or(None)` on an `Option` value --> $DIR/map_unwrap_or.rs:36:13 | LL | let _ = opt @@ -95,7 +95,7 @@ LL - .map(|x| Some(x + 1)) LL + .and_then(|x| Some(x + 1)); | -error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead +error: called `map().unwrap_or()` on an `Option` value --> $DIR/map_unwrap_or.rs:47:13 | LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); @@ -107,7 +107,7 @@ LL - let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); LL + let _ = Some("prefix").map_or(id, |p| format!("{}.", p)); | -error: called `map().unwrap_or_else()` on an `Option` value. This can be done more directly by calling `map_or_else(, )` instead +error: called `map().unwrap_or_else()` on an `Option` value --> $DIR/map_unwrap_or.rs:51:13 | LL | let _ = opt.map(|x| { @@ -117,7 +117,7 @@ LL | | } LL | | ).unwrap_or_else(|| 0); | |__________________________^ -error: called `map().unwrap_or_else()` on an `Option` value. This can be done more directly by calling `map_or_else(, )` instead +error: called `map().unwrap_or_else()` on an `Option` value --> $DIR/map_unwrap_or.rs:55:13 | LL | let _ = opt.map(|x| x + 1) @@ -127,7 +127,7 @@ LL | | 0 LL | | ); | |_________^ -error: called `map().unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and()` instead +error: called `map().unwrap_or(false)` on an `Option` value --> $DIR/map_unwrap_or.rs:61:13 | LL | let _ = opt.map(|x| x > 5).unwrap_or(false); @@ -139,7 +139,7 @@ LL - let _ = opt.map(|x| x > 5).unwrap_or(false); LL + let _ = opt.is_some_and(|x| x > 5); | -error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead +error: called `map().unwrap_or_else()` on a `Result` value --> $DIR/map_unwrap_or.rs:71:13 | LL | let _ = res.map(|x| { @@ -149,7 +149,7 @@ LL | | } LL | | ).unwrap_or_else(|_e| 0); | |____________________________^ -error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead +error: called `map().unwrap_or_else()` on a `Result` value --> $DIR/map_unwrap_or.rs:75:13 | LL | let _ = res.map(|x| x + 1) @@ -159,13 +159,13 @@ LL | | 0 LL | | }); | |__________^ -error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead +error: called `map().unwrap_or_else()` on a `Result` value --> $DIR/map_unwrap_or.rs:99:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` -error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead +error: called `map().unwrap_or()` on an `Option` value --> $DIR/map_unwrap_or.rs:106:13 | LL | let _ = opt.map(|x| x > 5).unwrap_or(false); @@ -177,7 +177,7 @@ LL - let _ = opt.map(|x| x > 5).unwrap_or(false); LL + let _ = opt.map_or(false, |x| x > 5); | -error: called `map().unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and()` instead +error: called `map().unwrap_or(false)` on an `Option` value --> $DIR/map_unwrap_or.rs:113:13 | LL | let _ = opt.map(|x| x > 5).unwrap_or(false); diff --git a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.stderr b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.stderr index ca611ac9d7ff1..d1a9fdd6ecffd 100644 --- a/src/tools/clippy/tests/ui/map_unwrap_or_fixable.stderr +++ b/src/tools/clippy/tests/ui/map_unwrap_or_fixable.stderr @@ -1,4 +1,4 @@ -error: called `map().unwrap_or_else()` on an `Option` value. This can be done more directly by calling `map_or_else(, )` instead +error: called `map().unwrap_or_else()` on an `Option` value --> $DIR/map_unwrap_or_fixable.rs:16:13 | LL | let _ = opt.map(|x| x + 1) @@ -10,7 +10,7 @@ LL | | .unwrap_or_else(|| 0); = note: `-D clippy::map-unwrap-or` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::map_unwrap_or)]` -error: called `map().unwrap_or_else()` on a `Result` value. This can be done more directly by calling `.map_or_else(, )` instead +error: called `map().unwrap_or_else()` on a `Result` value --> $DIR/map_unwrap_or_fixable.rs:46:13 | LL | let _ = res.map(|x| x + 1) diff --git a/src/tools/clippy/tests/ui/mem_replace_macro.stderr b/src/tools/clippy/tests/ui/mem_replace_macro.stderr index 842ad3a8565cd..c6435e94e9673 100644 --- a/src/tools/clippy/tests/ui/mem_replace_macro.stderr +++ b/src/tools/clippy/tests/ui/mem_replace_macro.stderr @@ -8,5 +8,5 @@ LL | inline!(std::mem::replace($s, Default::default())); = help: to override `-D warnings` add `#[allow(clippy::mem_replace_with_default)]` = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/methods_fixable.stderr b/src/tools/clippy/tests/ui/methods_fixable.stderr index 1bfe56d912b78..f290c20e5e989 100644 --- a/src/tools/clippy/tests/ui/methods_fixable.stderr +++ b/src/tools/clippy/tests/ui/methods_fixable.stderr @@ -7,5 +7,5 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: `-D clippy::filter-next` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::filter_next)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/methods_unfixable.stderr b/src/tools/clippy/tests/ui/methods_unfixable.stderr index 581a985e0b571..771e10cbe105c 100644 --- a/src/tools/clippy/tests/ui/methods_unfixable.stderr +++ b/src/tools/clippy/tests/ui/methods_unfixable.stderr @@ -12,5 +12,5 @@ LL | let iter = (0..10); = note: `-D clippy::filter-next` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::filter_next)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs b/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs index 4346ed892f277..de53079a47608 100644 --- a/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs +++ b/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.rs @@ -46,4 +46,26 @@ fn index_struct_different_fields(f: &Foo<'_>) { let _ = f.v[0] + f.v2[1]; } +fn shadowing() { + let x: &[i32] = &[1]; + assert!(x.len() > 1); + + let x: &[i32] = &[1]; + let _ = x[0] + x[1]; + //~^ ERROR: indexing into a slice multiple times without an `assert` +} + +pub fn issue11856(values: &[i32]) -> usize { + let mut ascending = Vec::new(); + for w in values.windows(2) { + assert!(w.len() > 1); + if w[0] < w[1] { + ascending.push((w[0], w[1])); + } else { + ascending.push((w[1], w[0])); + } + } + ascending.len() +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr b/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr index 12c9eed5d6619..12e0542279836 100644 --- a/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr +++ b/src/tools/clippy/tests/ui/missing_asserts_for_indexing_unfixable.stderr @@ -160,5 +160,24 @@ LL | let _ = f.v[0] + f.v[1]; | ^^^^^^ = note: asserting the length before indexing will elide bounds checks -error: aborting due to 7 previous errors +error: indexing into a slice multiple times without an `assert` + --> $DIR/missing_asserts_for_indexing_unfixable.rs:54:13 + | +LL | let _ = x[0] + x[1]; + | ^^^^^^^^^^^ + | + = help: consider asserting the length before indexing: `assert!(x.len() > 1);` +note: slice indexed here + --> $DIR/missing_asserts_for_indexing_unfixable.rs:54:13 + | +LL | let _ = x[0] + x[1]; + | ^^^^ +note: slice indexed here + --> $DIR/missing_asserts_for_indexing_unfixable.rs:54:20 + | +LL | let _ = x[0] + x[1]; + | ^^^^ + = note: asserting the length before indexing will elide bounds checks + +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr b/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr index c684bc8e70723..3aa9781c2f1da 100644 --- a/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr +++ b/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr @@ -11,5 +11,5 @@ LL | | fn main() {} = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::missing_docs_in_private_items)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr index 0b7be46165111..d84d06088ba35 100644 --- a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr +++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr @@ -7,5 +7,5 @@ LL | while b.load(Ordering::Acquire) {} = note: `-D clippy::missing-spin-loop` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::missing_spin_loop)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/mut_mutex_lock.stderr b/src/tools/clippy/tests/ui/mut_mutex_lock.stderr index 9b20016be799e..819602882766d 100644 --- a/src/tools/clippy/tests/ui/mut_mutex_lock.stderr +++ b/src/tools/clippy/tests/ui/mut_mutex_lock.stderr @@ -7,5 +7,5 @@ LL | let mut value = value_mutex.lock().unwrap(); = note: `-D clippy::mut-mutex-lock` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::mut_mutex_lock)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr index 183e2dbc8c16e..e91359a3cc182 100644 --- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr +++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr @@ -7,5 +7,5 @@ LL | fn call_with_mut_self(self: &mut Self) {} = note: `-D clippy::needless-arbitrary-self-type` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_arbitrary_self_type)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/needless_bitwise_bool.stderr b/src/tools/clippy/tests/ui/needless_bitwise_bool.stderr index 2ed9208e62306..b1fc1a7a95851 100644 --- a/src/tools/clippy/tests/ui/needless_bitwise_bool.stderr +++ b/src/tools/clippy/tests/ui/needless_bitwise_bool.stderr @@ -7,5 +7,5 @@ LL | if y & !x { = note: `-D clippy::needless-bitwise-bool` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_bitwise_bool)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/needless_bool_assign.stderr b/src/tools/clippy/tests/ui/needless_bool_assign.stderr index 7866c89bd618c..244a88e6691fd 100644 --- a/src/tools/clippy/tests/ui/needless_bool_assign.stderr +++ b/src/tools/clippy/tests/ui/needless_bool_assign.stderr @@ -48,7 +48,8 @@ LL | } else { LL | | a.field = true; LL | | } | |_____^ - = note: `#[deny(clippy::if_same_then_else)]` on by default + = note: `-D clippy::if-same-then-else` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::if_same_then_else)]` error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index c2c5f765abfff..ff1e2dc88756b 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -190,27 +190,48 @@ fn issue9383() { // Should not lint because unions need explicit deref when accessing field use std::mem::ManuallyDrop; - union Coral { - crab: ManuallyDrop>, + #[derive(Clone, Copy)] + struct Wrap(T); + impl core::ops::Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } + } + impl core::ops::DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } } - union Ocean { - coral: ManuallyDrop, + union U { + u: T, } - let mut ocean = Ocean { - coral: ManuallyDrop::new(Coral { - crab: ManuallyDrop::new(vec![1, 2, 3]), - }), - }; + #[derive(Clone, Copy)] + struct Foo { + x: u32, + } unsafe { - ManuallyDrop::drop(&mut (&mut ocean.coral).crab); - - (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]); - ManuallyDrop::drop(&mut (*ocean.coral).crab); - - ManuallyDrop::drop(&mut ocean.coral); + let mut x = U { + u: ManuallyDrop::new(Foo { x: 0 }), + }; + let _ = &mut (&mut x.u).x; + let _ = &mut { x.u }.x; + let _ = &mut ({ &mut x.u }).x; + + let mut x = U { + u: Wrap(ManuallyDrop::new(Foo { x: 0 })), + }; + let _ = &mut (&mut x.u).x; + let _ = &mut { x.u }.x; + let _ = &mut ({ &mut x.u }).x; + + let mut x = U { u: Wrap(Foo { x: 0 }) }; + let _ = &mut x.u.x; + let _ = &mut { x.u }.x; + let _ = &mut ({ &mut x.u }).x; } } diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index 0cd6e41b8a47a..597021539acfa 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -190,27 +190,48 @@ fn issue9383() { // Should not lint because unions need explicit deref when accessing field use std::mem::ManuallyDrop; - union Coral { - crab: ManuallyDrop>, + #[derive(Clone, Copy)] + struct Wrap(T); + impl core::ops::Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } + } + impl core::ops::DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } } - union Ocean { - coral: ManuallyDrop, + union U { + u: T, } - let mut ocean = Ocean { - coral: ManuallyDrop::new(Coral { - crab: ManuallyDrop::new(vec![1, 2, 3]), - }), - }; + #[derive(Clone, Copy)] + struct Foo { + x: u32, + } unsafe { - ManuallyDrop::drop(&mut (&mut ocean.coral).crab); - - (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]); - ManuallyDrop::drop(&mut (*ocean.coral).crab); - - ManuallyDrop::drop(&mut ocean.coral); + let mut x = U { + u: ManuallyDrop::new(Foo { x: 0 }), + }; + let _ = &mut (&mut x.u).x; + let _ = &mut (&mut { x.u }).x; + let _ = &mut ({ &mut x.u }).x; + + let mut x = U { + u: Wrap(ManuallyDrop::new(Foo { x: 0 })), + }; + let _ = &mut (&mut x.u).x; + let _ = &mut (&mut { x.u }).x; + let _ = &mut ({ &mut x.u }).x; + + let mut x = U { u: Wrap(Foo { x: 0 }) }; + let _ = &mut (&mut x.u).x; + let _ = &mut (&mut { x.u }).x; + let _ = &mut ({ &mut x.u }).x; } } diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index e91b78b0a1520..44552ee6abea1 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -133,5 +133,29 @@ error: this expression borrows a value the compiler would automatically borrow LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` -error: aborting due to 22 previous errors +error: this expression borrows a value the compiler would automatically borrow + --> $DIR/needless_borrow.rs:221:22 + | +LL | let _ = &mut (&mut { x.u }).x; + | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` + +error: this expression borrows a value the compiler would automatically borrow + --> $DIR/needless_borrow.rs:228:22 + | +LL | let _ = &mut (&mut { x.u }).x; + | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` + +error: this expression borrows a value the compiler would automatically borrow + --> $DIR/needless_borrow.rs:232:22 + | +LL | let _ = &mut (&mut x.u).x; + | ^^^^^^^^^^ help: change this to: `x.u` + +error: this expression borrows a value the compiler would automatically borrow + --> $DIR/needless_borrow.rs:233:22 + | +LL | let _ = &mut (&mut { x.u }).x; + | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` + +error: aborting due to 26 previous errors diff --git a/src/tools/clippy/tests/ui/needless_else.stderr b/src/tools/clippy/tests/ui/needless_else.stderr index e6f7138e948dd..66552109c48e1 100644 --- a/src/tools/clippy/tests/ui/needless_else.stderr +++ b/src/tools/clippy/tests/ui/needless_else.stderr @@ -9,5 +9,5 @@ LL | | } = note: `-D clippy::needless-else` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_else)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr index 73f249ae6c2f3..24a22e232485b 100644 --- a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr +++ b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr @@ -29,5 +29,5 @@ help: ...and replace `return` with `continue` LL | continue; | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/needless_option_take.stderr b/src/tools/clippy/tests/ui/needless_option_take.stderr index d3c22441d0033..bf43a18e7115c 100644 --- a/src/tools/clippy/tests/ui/needless_option_take.stderr +++ b/src/tools/clippy/tests/ui/needless_option_take.stderr @@ -7,5 +7,5 @@ LL | x.as_ref().take(); = note: `-D clippy::needless-option-take` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_option_take)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs index ea5e74c4c0067..25a02bdd2f2d9 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs @@ -1,4 +1,9 @@ -#![allow(clippy::if_same_then_else, clippy::no_effect, clippy::redundant_closure_call)] +#![allow( + clippy::if_same_then_else, + clippy::no_effect, + clippy::redundant_closure_call, + clippy::ptr_arg +)] #![warn(clippy::needless_pass_by_ref_mut)] #![feature(lint_reasons)] //@no-rustfix diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr index aa937c3f6af2b..92b753276ac9b 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr @@ -1,5 +1,5 @@ error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:7:11 + --> $DIR/needless_pass_by_ref_mut.rs:12:11 | LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` @@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:32:12 + --> $DIR/needless_pass_by_ref_mut.rs:37:12 | LL | fn foo6(s: &mut Vec) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:45:29 + --> $DIR/needless_pass_by_ref_mut.rs:50:29 | LL | fn mushroom(&self, vec: &mut Vec) -> usize { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:50:31 + --> $DIR/needless_pass_by_ref_mut.rs:55:31 | LL | fn badger(&mut self, vec: &mut Vec) -> usize { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:127:16 + --> $DIR/needless_pass_by_ref_mut.rs:132:16 | LL | async fn a1(x: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:131:16 + --> $DIR/needless_pass_by_ref_mut.rs:136:16 | LL | async fn a2(x: &mut i32, y: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:135:16 + --> $DIR/needless_pass_by_ref_mut.rs:140:16 | LL | async fn a3(x: &mut i32, y: String, z: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:139:16 + --> $DIR/needless_pass_by_ref_mut.rs:144:16 | LL | async fn a4(x: &mut i32, y: i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:143:24 + --> $DIR/needless_pass_by_ref_mut.rs:148:24 | LL | async fn a5(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:147:24 + --> $DIR/needless_pass_by_ref_mut.rs:152:24 | LL | async fn a6(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:151:32 + --> $DIR/needless_pass_by_ref_mut.rs:156:32 | LL | async fn a7(x: i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:155:24 + --> $DIR/needless_pass_by_ref_mut.rs:160:24 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:155:45 + --> $DIR/needless_pass_by_ref_mut.rs:160:45 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:189:16 + --> $DIR/needless_pass_by_ref_mut.rs:194:16 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:195:20 + --> $DIR/needless_pass_by_ref_mut.rs:200:20 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -96,19 +96,19 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:209:39 + --> $DIR/needless_pass_by_ref_mut.rs:214:39 | LL | async fn inner_async2(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:217:26 + --> $DIR/needless_pass_by_ref_mut.rs:222:26 | LL | async fn inner_async3(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:236:34 + --> $DIR/needless_pass_by_ref_mut.rs:241:34 | LL | pub async fn call_in_closure1(n: &mut str) { | ^^^^^^^^ help: consider changing to: `&str` @@ -116,7 +116,7 @@ LL | pub async fn call_in_closure1(n: &mut str) { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:248:25 + --> $DIR/needless_pass_by_ref_mut.rs:253:25 | LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() { | ^^^^^^^^^^ help: consider changing to: `&usize` @@ -124,7 +124,7 @@ LL | pub async fn closure(n: &mut usize) -> impl '_ + FnMut() { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:255:20 + --> $DIR/needless_pass_by_ref_mut.rs:260:20 | LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { | ^^^^^^^^^^ help: consider changing to: `&usize` @@ -132,7 +132,7 @@ LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> $DIR/needless_pass_by_ref_mut.rs:266:26 + --> $DIR/needless_pass_by_ref_mut.rs:271:26 | LL | pub async fn closure4(n: &mut usize) { | ^^^^^^^^^^ help: consider changing to: `&usize` diff --git a/src/tools/clippy/tests/ui/needless_raw_string.fixed b/src/tools/clippy/tests/ui/needless_raw_string.fixed index 4ea711fd67a14..1a9c601c462ba 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.fixed +++ b/src/tools/clippy/tests/ui/needless_raw_string.fixed @@ -1,6 +1,5 @@ #![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)] #![warn(clippy::needless_raw_strings)] -#![feature(c_str_literals)] fn main() { "aaa"; diff --git a/src/tools/clippy/tests/ui/needless_raw_string.rs b/src/tools/clippy/tests/ui/needless_raw_string.rs index b6239f9b1f031..1126ea5aa3033 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.rs +++ b/src/tools/clippy/tests/ui/needless_raw_string.rs @@ -1,6 +1,5 @@ #![allow(clippy::needless_raw_string_hashes, clippy::no_effect, unused)] #![warn(clippy::needless_raw_strings)] -#![feature(c_str_literals)] fn main() { r#"aaa"#; diff --git a/src/tools/clippy/tests/ui/needless_raw_string.stderr b/src/tools/clippy/tests/ui/needless_raw_string.stderr index 276bc84c6c375..b2188698564f9 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string.stderr +++ b/src/tools/clippy/tests/ui/needless_raw_string.stderr @@ -1,5 +1,5 @@ error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:6:5 + --> $DIR/needless_raw_string.rs:5:5 | LL | r#"aaa"#; | ^^^^^^^^ @@ -13,7 +13,7 @@ LL + "aaa"; | error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:9:5 + --> $DIR/needless_raw_string.rs:8:5 | LL | br#"aaa"#; | ^^^^^^^^^ @@ -25,7 +25,7 @@ LL + b"aaa"; | error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:12:5 + --> $DIR/needless_raw_string.rs:11:5 | LL | cr#"aaa"#; | ^^^^^^^^^ @@ -37,7 +37,7 @@ LL + c"aaa"; | error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:16:5 + --> $DIR/needless_raw_string.rs:15:5 | LL | / r#" LL | | a @@ -56,7 +56,7 @@ LL ~ "; | error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:22:5 + --> $DIR/needless_raw_string.rs:21:5 | LL | r"no hashes"; | ^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL + "no hashes"; | error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:23:5 + --> $DIR/needless_raw_string.rs:22:5 | LL | br"no hashes"; | ^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL + b"no hashes"; | error: unnecessary raw string literal - --> $DIR/needless_raw_string.rs:24:5 + --> $DIR/needless_raw_string.rs:23:5 | LL | cr"no hashes"; | ^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed index c99c2f46532a3..b2ad657d6b29f 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.fixed @@ -1,6 +1,5 @@ #![allow(clippy::no_effect, unused)] #![warn(clippy::needless_raw_string_hashes)] -#![feature(c_str_literals)] fn main() { r"\aaa"; diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs index dcc2af69f4e9c..54d8ed76d4751 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.rs @@ -1,6 +1,5 @@ #![allow(clippy::no_effect, unused)] #![warn(clippy::needless_raw_string_hashes)] -#![feature(c_str_literals)] fn main() { r#"\aaa"#; diff --git a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr index 017160b1a421d..c74eff8161e94 100644 --- a/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr +++ b/src/tools/clippy/tests/ui/needless_raw_string_hashes.stderr @@ -1,5 +1,5 @@ error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:6:5 + --> $DIR/needless_raw_string_hashes.rs:5:5 | LL | r#"\aaa"#; | ^^^^^^^^^ @@ -13,7 +13,7 @@ LL + r"\aaa"; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:7:5 + --> $DIR/needless_raw_string_hashes.rs:6:5 | LL | r##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + r#"Hello "world"!"#; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:8:5 + --> $DIR/needless_raw_string_hashes.rs:7:5 | LL | r######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + r####" "### "## "# "####; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:9:5 + --> $DIR/needless_raw_string_hashes.rs:8:5 | LL | r######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + r###" "aa" "# "## "###; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:10:5 + --> $DIR/needless_raw_string_hashes.rs:9:5 | LL | br#"\aaa"#; | ^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + br"\aaa"; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:11:5 + --> $DIR/needless_raw_string_hashes.rs:10:5 | LL | br##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + br#"Hello "world"!"#; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:12:5 + --> $DIR/needless_raw_string_hashes.rs:11:5 | LL | br######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + br####" "### "## "# "####; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:13:5 + --> $DIR/needless_raw_string_hashes.rs:12:5 | LL | br######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + br###" "aa" "# "## "###; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:14:5 + --> $DIR/needless_raw_string_hashes.rs:13:5 | LL | cr#"\aaa"#; | ^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + cr"\aaa"; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:15:5 + --> $DIR/needless_raw_string_hashes.rs:14:5 | LL | cr##"Hello "world"!"##; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + cr#"Hello "world"!"#; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:16:5 + --> $DIR/needless_raw_string_hashes.rs:15:5 | LL | cr######" "### "## "# "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + cr####" "### "## "# "####; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:17:5 + --> $DIR/needless_raw_string_hashes.rs:16:5 | LL | cr######" "aa" "# "## "######; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + cr###" "aa" "# "## "###; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:19:5 + --> $DIR/needless_raw_string_hashes.rs:18:5 | LL | / r#" LL | | \a @@ -164,7 +164,7 @@ LL ~ "; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:25:5 + --> $DIR/needless_raw_string_hashes.rs:24:5 | LL | r###"rust"###; | ^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL + r"rust"; | error: unnecessary hashes around raw string literal - --> $DIR/needless_raw_string_hashes.rs:26:5 + --> $DIR/needless_raw_string_hashes.rs:25:5 | LL | r#"hello world"#; | ^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed b/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed index 52d5418092148..0147c73a94b24 100644 --- a/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed +++ b/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed @@ -4,6 +4,8 @@ clippy::no_effect, clippy::unit_arg, clippy::useless_conversion, + clippy::diverging_sub_expression, + clippy::let_unit_value, unused )] @@ -35,5 +37,43 @@ fn main() -> Result<(), ()> { with_span! { return Err(())?; } + + // Issue #11765 + // Should not lint + let Some(s) = Some("") else { + return Err(())?; + }; + + let Some(s) = Some("") else { + let Some(s) = Some("") else { + return Err(())?; + }; + + return Err(())?; + }; + + let Some(_): Option<()> = ({ + return Err(())?; + }) else { + panic!(); + }; + Err(()) } + +fn issue11616() -> Result<(), ()> { + let _x: String = { + return Err(())?; + }; + let _x: () = { + Err(())?; + //~^ ERROR: unneeded `return` statement with `?` operator + }; + let _x = match 1 { + 1 => vec![1, 2], + _ => { + return Err(())?; + }, + }; + Ok(()) +} diff --git a/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs b/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs index d253cae4dc28e..66e1f438f8ce0 100644 --- a/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs +++ b/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs @@ -4,6 +4,8 @@ clippy::no_effect, clippy::unit_arg, clippy::useless_conversion, + clippy::diverging_sub_expression, + clippy::let_unit_value, unused )] @@ -35,5 +37,43 @@ fn main() -> Result<(), ()> { with_span! { return Err(())?; } + + // Issue #11765 + // Should not lint + let Some(s) = Some("") else { + return Err(())?; + }; + + let Some(s) = Some("") else { + let Some(s) = Some("") else { + return Err(())?; + }; + + return Err(())?; + }; + + let Some(_): Option<()> = ({ + return Err(())?; + }) else { + panic!(); + }; + Err(()) } + +fn issue11616() -> Result<(), ()> { + let _x: String = { + return Err(())?; + }; + let _x: () = { + return Err(())?; + //~^ ERROR: unneeded `return` statement with `?` operator + }; + let _x = match 1 { + 1 => vec![1, 2], + _ => { + return Err(())?; + }, + }; + Ok(()) +} diff --git a/src/tools/clippy/tests/ui/needless_return_with_question_mark.stderr b/src/tools/clippy/tests/ui/needless_return_with_question_mark.stderr index 0de0633803bc4..17aa212ae8d7a 100644 --- a/src/tools/clippy/tests/ui/needless_return_with_question_mark.stderr +++ b/src/tools/clippy/tests/ui/needless_return_with_question_mark.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement with `?` operator - --> $DIR/needless_return_with_question_mark.rs:27:5 + --> $DIR/needless_return_with_question_mark.rs:29:5 | LL | return Err(())?; | ^^^^^^^ help: remove it @@ -7,5 +7,11 @@ LL | return Err(())?; = note: `-D clippy::needless-return-with-question-mark` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_return_with_question_mark)]` -error: aborting due to previous error +error: unneeded `return` statement with `?` operator + --> $DIR/needless_return_with_question_mark.rs:69:9 + | +LL | return Err(())?; + | ^^^^^^^ help: remove it + +error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/needless_update.stderr b/src/tools/clippy/tests/ui/needless_update.stderr index 3e9e2941a7a75..60aeb04938702 100644 --- a/src/tools/clippy/tests/ui/needless_update.stderr +++ b/src/tools/clippy/tests/ui/needless_update.stderr @@ -7,5 +7,5 @@ LL | S { a: 1, b: 1, ..base }; = note: `-D clippy::needless-update` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_update)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr index babb634fdcd1a..c0d6a74a51dee 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr +++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr @@ -4,6 +4,6 @@ error[E0275]: overflow evaluating the requirement `::Outpu LL | pub fn new() -> X { | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr index 001fcddd9068e..036d38c22f48d 100644 --- a/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr +++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr @@ -7,5 +7,5 @@ LL | #[cfg(all())] = note: `-D clippy::non-minimal-cfg` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::non_minimal_cfg)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/obfuscated_if_else.stderr b/src/tools/clippy/tests/ui/obfuscated_if_else.stderr index ca9f5e1e374cb..abf5adce44466 100644 --- a/src/tools/clippy/tests/ui/obfuscated_if_else.stderr +++ b/src/tools/clippy/tests/ui/obfuscated_if_else.stderr @@ -7,5 +7,5 @@ LL | true.then_some("a").unwrap_or("b"); = note: `-D clippy::obfuscated-if-else` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::obfuscated_if_else)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.stderr b/src/tools/clippy/tests/ui/option_as_ref_deref.stderr index eb0661c523a91..9d173e409abcc 100644 --- a/src/tools/clippy/tests/ui/option_as_ref_deref.stderr +++ b/src/tools/clippy/tests/ui/option_as_ref_deref.stderr @@ -1,4 +1,4 @@ -error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead +error: called `.as_ref().map(Deref::deref)` on an `Option` value --> $DIR/option_as_ref_deref.rs:11:13 | LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); @@ -7,7 +7,7 @@ LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); = note: `-D clippy::option-as-ref-deref` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::option_as_ref_deref)]` -error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead +error: called `.as_ref().map(Deref::deref)` on an `Option` value --> $DIR/option_as_ref_deref.rs:14:13 | LL | let _ = opt.clone() @@ -17,97 +17,97 @@ LL | | Deref::deref LL | | ) | |_________^ help: try using as_deref instead: `opt.clone().as_deref()` -error: called `.as_mut().map(DerefMut::deref_mut)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead +error: called `.as_mut().map(DerefMut::deref_mut)` on an `Option` value --> $DIR/option_as_ref_deref.rs:20:13 | LL | let _ = opt.as_mut().map(DerefMut::deref_mut); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` -error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(String::as_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:22:13 | LL | let _ = opt.as_ref().map(String::as_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: called `.as_ref().map(|x| x.as_str())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(|x| x.as_str())` on an `Option` value --> $DIR/option_as_ref_deref.rs:23:13 | LL | let _ = opt.as_ref().map(|x| x.as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: called `.as_mut().map(String::as_mut_str)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead +error: called `.as_mut().map(String::as_mut_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:24:13 | LL | let _ = opt.as_mut().map(String::as_mut_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` -error: called `.as_mut().map(|x| x.as_mut_str())` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead +error: called `.as_mut().map(|x| x.as_mut_str())` on an `Option` value --> $DIR/option_as_ref_deref.rs:25:13 | LL | let _ = opt.as_mut().map(|x| x.as_mut_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` -error: called `.as_ref().map(CString::as_c_str)` on an Option value. This can be done more directly by calling `Some(CString::new(vec![]).unwrap()).as_deref()` instead +error: called `.as_ref().map(CString::as_c_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:26:13 | LL | let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(CString::new(vec![]).unwrap()).as_deref()` -error: called `.as_ref().map(OsString::as_os_str)` on an Option value. This can be done more directly by calling `Some(OsString::new()).as_deref()` instead +error: called `.as_ref().map(OsString::as_os_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:27:13 | LL | let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(OsString::new()).as_deref()` -error: called `.as_ref().map(PathBuf::as_path)` on an Option value. This can be done more directly by calling `Some(PathBuf::new()).as_deref()` instead +error: called `.as_ref().map(PathBuf::as_path)` on an `Option` value --> $DIR/option_as_ref_deref.rs:28:13 | LL | let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(PathBuf::new()).as_deref()` -error: called `.as_ref().map(Vec::as_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref()` instead +error: called `.as_ref().map(Vec::as_slice)` on an `Option` value --> $DIR/option_as_ref_deref.rs:29:13 | LL | let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(Vec::<()>::new()).as_deref()` -error: called `.as_mut().map(Vec::as_mut_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref_mut()` instead +error: called `.as_mut().map(Vec::as_mut_slice)` on an `Option` value --> $DIR/option_as_ref_deref.rs:30:13 | LL | let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `Some(Vec::<()>::new()).as_deref_mut()` -error: called `.as_ref().map(|x| x.deref())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(|x| x.deref())` on an `Option` value --> $DIR/option_as_ref_deref.rs:32:13 | LL | let _ = opt.as_ref().map(|x| x.deref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: called `.as_mut().map(|x| x.deref_mut())` on an Option value. This can be done more directly by calling `opt.clone().as_deref_mut()` instead +error: called `.as_mut().map(|x| x.deref_mut())` on an `Option` value --> $DIR/option_as_ref_deref.rs:33:13 | LL | let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.clone().as_deref_mut()` -error: called `.as_ref().map(|x| &**x)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(|x| &**x)` on an `Option` value --> $DIR/option_as_ref_deref.rs:40:13 | LL | let _ = opt.as_ref().map(|x| &**x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: called `.as_mut().map(|x| &mut **x)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead +error: called `.as_mut().map(|x| &mut **x)` on an `Option` value --> $DIR/option_as_ref_deref.rs:41:13 | LL | let _ = opt.as_mut().map(|x| &mut **x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` -error: called `.as_ref().map(std::ops::Deref::deref)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(std::ops::Deref::deref)` on an `Option` value --> $DIR/option_as_ref_deref.rs:44:13 | LL | let _ = opt.as_ref().map(std::ops::Deref::deref); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(String::as_str)` on an `Option` value --> $DIR/option_as_ref_deref.rs:56:13 | LL | let _ = opt.as_ref().map(String::as_str); diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed index f0113ca696e16..363520112ef26 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.fixed +++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed @@ -92,11 +92,13 @@ fn pattern_to_vec(pattern: &str) -> Vec { } // #10335 -fn test_result_impure_else(variable: Result) { +fn test_result_impure_else(variable: Result) -> bool { variable.map_or_else(|_| { println!("Err"); + false }, |binding| { println!("Ok {binding}"); + true }) } @@ -213,15 +215,19 @@ mod issue10729 { pub fn reproduce(initial: &Option) { // 👇 needs `.as_ref()` because initial is an `&Option<_>` - initial.as_ref().map_or({}, |value| do_something(value)) + let _ = initial.as_ref().map_or(42, |value| do_something(value)); } pub fn reproduce2(initial: &mut Option) { - initial.as_mut().map_or({}, |value| do_something2(value)) + let _ = initial.as_mut().map_or(42, |value| do_something2(value)); } - fn do_something(_value: &str) {} - fn do_something2(_value: &mut str) {} + fn do_something(_value: &str) -> u32 { + todo!() + } + fn do_something2(_value: &mut str) -> u32 { + todo!() + } } fn issue11429() { @@ -237,3 +243,13 @@ fn issue11429() { let mut _hm = opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone()); } + +fn issue11893() { + use std::io::Write; + let mut output = std::io::stdout().lock(); + if let Some(name) = Some("stuff") { + writeln!(output, "{name:?}").unwrap(); + } else { + panic!("Haven't thought about this condition."); + } +} diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs index 18b7af4439259..aaa87a0db5495 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.rs +++ b/src/tools/clippy/tests/ui/option_if_let_else.rs @@ -115,11 +115,13 @@ fn pattern_to_vec(pattern: &str) -> Vec { } // #10335 -fn test_result_impure_else(variable: Result) { +fn test_result_impure_else(variable: Result) -> bool { if let Ok(binding) = variable { println!("Ok {binding}"); + true } else { println!("Err"); + false } } @@ -254,21 +256,25 @@ mod issue10729 { pub fn reproduce(initial: &Option) { // 👇 needs `.as_ref()` because initial is an `&Option<_>` - match initial { + let _ = match initial { Some(value) => do_something(value), - None => {}, - } + None => 42, + }; } pub fn reproduce2(initial: &mut Option) { - match initial { + let _ = match initial { Some(value) => do_something2(value), - None => {}, - } + None => 42, + }; } - fn do_something(_value: &str) {} - fn do_something2(_value: &mut str) {} + fn do_something(_value: &str) -> u32 { + todo!() + } + fn do_something2(_value: &mut str) -> u32 { + todo!() + } } fn issue11429() { @@ -288,3 +294,13 @@ fn issue11429() { let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() }; } + +fn issue11893() { + use std::io::Write; + let mut output = std::io::stdout().lock(); + if let Some(name) = Some("stuff") { + writeln!(output, "{name:?}").unwrap(); + } else { + panic!("Haven't thought about this condition."); + } +} diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr index e36357bcb385d..55a8360ffd0c8 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.stderr +++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr @@ -158,8 +158,10 @@ error: use Option::map_or_else instead of an if let/else | LL | / if let Ok(binding) = variable { LL | | println!("Ok {binding}"); +LL | | true LL | | } else { LL | | println!("Err"); +LL | | false LL | | } | |_____^ | @@ -167,19 +169,21 @@ help: try | LL ~ variable.map_or_else(|_| { LL + println!("Err"); +LL + false LL + }, |binding| { LL + println!("Ok {binding}"); +LL + true LL + }) | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:141:13 + --> $DIR/option_if_let_else.rs:143:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:151:13 + --> $DIR/option_if_let_else.rs:153:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -201,13 +205,13 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:179:13 + --> $DIR/option_if_let_else.rs:181:13 | LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:183:13 + --> $DIR/option_if_let_else.rs:185:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -227,7 +231,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:222:13 + --> $DIR/option_if_let_else.rs:224:13 | LL | let _ = match s { | _____________^ @@ -237,7 +241,7 @@ LL | | }; | |_____^ help: try: `s.map_or(1, |string| string.len())` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:226:13 + --> $DIR/option_if_let_else.rs:228:13 | LL | let _ = match Some(10) { | _____________^ @@ -247,7 +251,7 @@ LL | | }; | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:232:13 + --> $DIR/option_if_let_else.rs:234:13 | LL | let _ = match res { | _____________^ @@ -257,7 +261,7 @@ LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:236:13 + --> $DIR/option_if_let_else.rs:238:13 | LL | let _ = match res { | _____________^ @@ -267,31 +271,33 @@ LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:240:13 + --> $DIR/option_if_let_else.rs:242:13 | LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:257:9 + --> $DIR/option_if_let_else.rs:259:17 | -LL | / match initial { +LL | let _ = match initial { + | _________________^ LL | | Some(value) => do_something(value), -LL | | None => {}, -LL | | } - | |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))` +LL | | None => 42, +LL | | }; + | |_________^ help: try: `initial.as_ref().map_or(42, |value| do_something(value))` error: use Option::map_or instead of an if let/else - --> $DIR/option_if_let_else.rs:264:9 + --> $DIR/option_if_let_else.rs:266:17 | -LL | / match initial { +LL | let _ = match initial { + | _________________^ LL | | Some(value) => do_something2(value), -LL | | None => {}, -LL | | } - | |_________^ help: try: `initial.as_mut().map_or({}, |value| do_something2(value))` +LL | | None => 42, +LL | | }; + | |_________^ help: try: `initial.as_mut().map_or(42, |value| do_something2(value))` error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:283:24 + --> $DIR/option_if_let_else.rs:289:24 | LL | let mut _hashmap = if let Some(hm) = &opt { | ________________________^ @@ -302,7 +308,7 @@ LL | | }; | |_____^ help: try: `opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone())` error: use Option::map_or_else instead of an if let/else - --> $DIR/option_if_let_else.rs:289:19 + --> $DIR/option_if_let_else.rs:295:19 | LL | let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())` diff --git a/src/tools/clippy/tests/ui/option_map_or_err_ok.fixed b/src/tools/clippy/tests/ui/option_map_or_err_ok.fixed new file mode 100644 index 0000000000000..131f4b2093e71 --- /dev/null +++ b/src/tools/clippy/tests/ui/option_map_or_err_ok.fixed @@ -0,0 +1,7 @@ +#![warn(clippy::option_map_or_err_ok)] + +fn main() { + let x = Some("a"); + let _ = x.ok_or("a"); + //~^ ERROR: called `map_or(Err(_), Ok)` on an `Option` value +} diff --git a/src/tools/clippy/tests/ui/option_map_or_err_ok.rs b/src/tools/clippy/tests/ui/option_map_or_err_ok.rs new file mode 100644 index 0000000000000..0f07a592ae5fd --- /dev/null +++ b/src/tools/clippy/tests/ui/option_map_or_err_ok.rs @@ -0,0 +1,7 @@ +#![warn(clippy::option_map_or_err_ok)] + +fn main() { + let x = Some("a"); + let _ = x.map_or(Err("a"), Ok); + //~^ ERROR: called `map_or(Err(_), Ok)` on an `Option` value +} diff --git a/src/tools/clippy/tests/ui/option_map_or_err_ok.stderr b/src/tools/clippy/tests/ui/option_map_or_err_ok.stderr new file mode 100644 index 0000000000000..a193e3c4c49d3 --- /dev/null +++ b/src/tools/clippy/tests/ui/option_map_or_err_ok.stderr @@ -0,0 +1,11 @@ +error: called `map_or(Err(_), Ok)` on an `Option` value + --> $DIR/option_map_or_err_ok.rs:5:13 + | +LL | let _ = x.map_or(Err("a"), Ok); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok_or` instead: `x.ok_or("a")` + | + = note: `-D clippy::option-map-or-err-ok` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::option_map_or_err_ok)]` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/option_map_or_none.stderr b/src/tools/clippy/tests/ui/option_map_or_none.stderr index fa150718f8910..f2cfc3f9a2815 100644 --- a/src/tools/clippy/tests/ui/option_map_or_none.stderr +++ b/src/tools/clippy/tests/ui/option_map_or_none.stderr @@ -1,4 +1,4 @@ -error: called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling `map(..)` instead +error: called `map_or(None, ..)` on an `Option` value --> $DIR/option_map_or_none.rs:10:26 | LL | let _: Option = opt.map_or(None, |x| Some(x + 1)); @@ -7,7 +7,7 @@ LL | let _: Option = opt.map_or(None, |x| Some(x + 1)); = note: `-D clippy::option-map-or-none` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::option_map_or_none)]` -error: called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling `map(..)` instead +error: called `map_or(None, ..)` on an `Option` value --> $DIR/option_map_or_none.rs:13:26 | LL | let _: Option = opt.map_or(None, |x| { @@ -16,13 +16,13 @@ LL | | Some(x + 1) LL | | }); | |_________________________^ help: try using `map` instead: `opt.map(|x| x + 1)` -error: called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling `and_then(..)` instead +error: called `map_or(None, ..)` on an `Option` value --> $DIR/option_map_or_none.rs:17:26 | LL | let _: Option = opt.map_or(None, bar); | ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `opt.and_then(bar)` -error: called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling `and_then(..)` instead +error: called `map_or(None, ..)` on an `Option` value --> $DIR/option_map_or_none.rs:18:26 | LL | let _: Option = opt.map_or(None, |x| { @@ -42,7 +42,7 @@ LL + Some(offset + height) LL ~ }); | -error: called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling `ok()` instead +error: called `map_or(None, Some)` on a `Result` value --> $DIR/option_map_or_none.rs:25:26 | LL | let _: Option = r.map_or(None, Some); diff --git a/src/tools/clippy/tests/ui/partialeq_ne_impl.stderr b/src/tools/clippy/tests/ui/partialeq_ne_impl.stderr index 163d6b1dd7b62..2210e706d930d 100644 --- a/src/tools/clippy/tests/ui/partialeq_ne_impl.stderr +++ b/src/tools/clippy/tests/ui/partialeq_ne_impl.stderr @@ -11,5 +11,5 @@ LL | | } = note: `-D clippy::partialeq-ne-impl` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::partialeq_ne_impl)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr b/src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr index 1453d020c412a..f96ce0de77931 100644 --- a/src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr +++ b/src/tools/clippy/tests/ui/path_buf_push_overwrite.stderr @@ -7,5 +7,5 @@ LL | x.push("/bar"); = note: `-D clippy::path-buf-push-overwrite` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::path_buf_push_overwrite)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr b/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr index 58a7de84d8f05..bd34463084a4a 100644 --- a/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr +++ b/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr @@ -10,5 +10,5 @@ LL | permissions.set_readonly(false); = note: `-D clippy::permissions-set-readonly-false` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::permissions_set_readonly_false)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/proc_macro.stderr b/src/tools/clippy/tests/ui/proc_macro.stderr index d912b50275512..122374ea804dd 100644 --- a/src/tools/clippy/tests/ui/proc_macro.stderr +++ b/src/tools/clippy/tests/ui/proc_macro.stderr @@ -7,5 +7,5 @@ LL | let _x = 3.14; = help: consider using the constant directly = note: `#[deny(clippy::approx_constant)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs index 91e2e7fd6427f..fcd716f41444f 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.rs +++ b/src/tools/clippy/tests/ui/ptr_arg.rs @@ -22,6 +22,12 @@ fn do_vec_mut(x: &mut Vec) { //Nothing here } +fn do_vec_mut2(x: &mut Vec) { + //~^ ERROR: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice w + x.len(); + x.is_empty(); +} + fn do_str(x: &String) { //~^ ERROR: writing `&String` instead of `&str` involves a new object where a slice will d //Nothing here either diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index cccf2d62d6319..35bd850920590 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -13,38 +13,44 @@ error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a sl LL | fn do_vec_mut(x: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` +error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do + --> $DIR/ptr_arg.rs:25:19 + | +LL | fn do_vec_mut2(x: &mut Vec) { + | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` + error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:25:14 + --> $DIR/ptr_arg.rs:31:14 | LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:30:18 + --> $DIR/ptr_arg.rs:36:18 | LL | fn do_str_mut(x: &mut String) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:35:15 + --> $DIR/ptr_arg.rs:41:15 | LL | fn do_path(x: &PathBuf) { | ^^^^^^^^ help: change this to: `&Path` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:40:19 + --> $DIR/ptr_arg.rs:46:19 | LL | fn do_path_mut(x: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:49:18 + --> $DIR/ptr_arg.rs:55:18 | LL | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:63:14 + --> $DIR/ptr_arg.rs:69:14 | LL | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ @@ -62,7 +68,7 @@ LL ~ x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:73:18 + --> $DIR/ptr_arg.rs:79:18 | LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ @@ -79,7 +85,7 @@ LL ~ x.to_owned() | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:82:19 + --> $DIR/ptr_arg.rs:88:19 | LL | fn path_cloned(x: &PathBuf) -> PathBuf { | ^^^^^^^^ @@ -96,7 +102,7 @@ LL ~ x.to_path_buf() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:91:44 + --> $DIR/ptr_arg.rs:97:44 | LL | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ @@ -111,19 +117,19 @@ LL ~ let c = y; | error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:106:25 + --> $DIR/ptr_arg.rs:112:25 | LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:136:66 + --> $DIR/ptr_arg.rs:142:66 | LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec, _s: &String) {} | ^^^^^^^ help: change this to: `&str` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:166:21 + --> $DIR/ptr_arg.rs:172:21 | LL | fn foo_vec(vec: &Vec) { | ^^^^^^^^ @@ -137,7 +143,7 @@ LL ~ let _ = vec.to_owned().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:172:23 + --> $DIR/ptr_arg.rs:178:23 | LL | fn foo_path(path: &PathBuf) { | ^^^^^^^^ @@ -151,7 +157,7 @@ LL ~ let _ = path.to_path_buf().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:178:21 + --> $DIR/ptr_arg.rs:184:21 | LL | fn foo_str(str: &PathBuf) { | ^^^^^^^^ @@ -165,46 +171,46 @@ LL ~ let _ = str.to_path_buf().clone(); | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:185:29 + --> $DIR/ptr_arg.rs:191:29 | LL | fn mut_vec_slice_methods(v: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:248:17 + --> $DIR/ptr_arg.rs:254:17 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:248:35 + --> $DIR/ptr_arg.rs:254:35 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> $DIR/ptr_arg.rs:248:51 + --> $DIR/ptr_arg.rs:254:51 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:274:39 + --> $DIR/ptr_arg.rs:280:39 | LL | fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { | ^^^^^^^^^^^^ help: change this to: `&str` error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:280:36 + --> $DIR/ptr_arg.rs:286:36 | LL | fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` error: using a reference to `Cow` is not recommended - --> $DIR/ptr_arg.rs:284:40 + --> $DIR/ptr_arg.rs:290:40 | LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` -error: aborting due to 23 previous errors +error: aborting due to 24 previous errors diff --git a/src/tools/clippy/tests/ui/pub_use.stderr b/src/tools/clippy/tests/ui/pub_use.stderr index 781572736645d..f6f5db9a18004 100644 --- a/src/tools/clippy/tests/ui/pub_use.stderr +++ b/src/tools/clippy/tests/ui/pub_use.stderr @@ -8,5 +8,5 @@ LL | pub use inner::Test; = note: `-D clippy::pub-use` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::pub_use)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/question_mark_used.stderr b/src/tools/clippy/tests/ui/question_mark_used.stderr index a3f440de80a5d..b4e256ddb9ebe 100644 --- a/src/tools/clippy/tests/ui/question_mark_used.stderr +++ b/src/tools/clippy/tests/ui/question_mark_used.stderr @@ -8,5 +8,5 @@ LL | other_function()?; = note: `-D clippy::question-mark-used` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::question_mark_used)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/range.stderr b/src/tools/clippy/tests/ui/range.stderr index 9f174307b829c..78ef17b5ba79d 100644 --- a/src/tools/clippy/tests/ui/range.stderr +++ b/src/tools/clippy/tests/ui/range.stderr @@ -7,5 +7,5 @@ LL | let _x = v1.iter().zip(0..v1.len()); = note: `-D clippy::range-zip-with-len` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::range_zip_with_len)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed index bf268d0b5832a..f272d8359a388 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed +++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed @@ -84,3 +84,21 @@ fn issue9956() { bar()(42, 5); foo(42, 5); } + +async fn issue11357() { + async {}.await; +} + +mod issue11707 { + use core::future::Future; + + fn spawn_on(fut: impl Future) {} + + fn demo() { + spawn_on(async move {}); + } +} + +fn avoid_double_parens() { + std::convert::identity(13_i32 + 36_i32).leading_zeros(); +} diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs index c8a91049d1975..f45db8c9cff5d 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs +++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs @@ -84,3 +84,21 @@ fn issue9956() { bar()((|| || 42)()(), 5); foo((|| || 42)()(), 5); } + +async fn issue11357() { + (|| async {})().await; +} + +mod issue11707 { + use core::future::Future; + + fn spawn_on(fut: impl Future) {} + + fn demo() { + spawn_on((|| async move {})()); + } +} + +fn avoid_double_parens() { + std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros(); +} diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr index a7cdb43693fc9..028d383ad3546 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr +++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr @@ -123,5 +123,23 @@ error: try not to call a closure in the expression where it is declared LL | foo((|| || 42)()(), 5); | ^^^^^^^^^^^^^^ help: try doing something like: `42` -error: aborting due to 14 previous errors +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:89:5 + | +LL | (|| async {})().await; + | ^^^^^^^^^^^^^^^ help: try doing something like: `async {}` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:98:18 + | +LL | spawn_on((|| async move {})()); + | ^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async move {}` + +error: try not to call a closure in the expression where it is declared + --> $DIR/redundant_closure_call_fixable.rs:103:28 + | +LL | std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `13_i32 + 36_i32` + +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_guards.fixed b/src/tools/clippy/tests/ui/redundant_guards.fixed index f8af90927252b..aef26ef225c90 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.fixed +++ b/src/tools/clippy/tests/ui/redundant_guards.fixed @@ -193,3 +193,60 @@ mod issue11465 { } } } + +fn issue11807() { + #![allow(clippy::single_match)] + + match Some(Some("")) { + Some(Some("")) => {}, + _ => {}, + } + + match Some(Some(String::new())) { + // Do not lint: String deref-coerces to &str + Some(Some(x)) if x.is_empty() => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some([])) => {}, + _ => {}, + } + + match Some(Some([] as [i32; 0])) { + Some(Some([])) => {}, + _ => {}, + } + + match Some(Some(Vec::<()>::new())) { + // Do not lint: Vec deref-coerces to &[T] + Some(Some(x)) if x.is_empty() => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some([..])) => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some([1, ..])) => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some([1, 2, ..])) => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some([.., 1, 2])) => {}, + _ => {}, + } + + match Some(Some(Vec::::new())) { + // Do not lint: deref coercion + Some(Some(x)) if x.starts_with(&[1, 2]) => {}, + _ => {}, + } +} diff --git a/src/tools/clippy/tests/ui/redundant_guards.rs b/src/tools/clippy/tests/ui/redundant_guards.rs index b46f8a6207e6f..5d476f5b04035 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.rs +++ b/src/tools/clippy/tests/ui/redundant_guards.rs @@ -193,3 +193,60 @@ mod issue11465 { } } } + +fn issue11807() { + #![allow(clippy::single_match)] + + match Some(Some("")) { + Some(Some(x)) if x.is_empty() => {}, + _ => {}, + } + + match Some(Some(String::new())) { + // Do not lint: String deref-coerces to &str + Some(Some(x)) if x.is_empty() => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some(x)) if x.is_empty() => {}, + _ => {}, + } + + match Some(Some([] as [i32; 0])) { + Some(Some(x)) if x.is_empty() => {}, + _ => {}, + } + + match Some(Some(Vec::<()>::new())) { + // Do not lint: Vec deref-coerces to &[T] + Some(Some(x)) if x.is_empty() => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some(x)) if x.starts_with(&[]) => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some(x)) if x.starts_with(&[1]) => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some(x)) if x.starts_with(&[1, 2]) => {}, + _ => {}, + } + + match Some(Some(&[] as &[i32])) { + Some(Some(x)) if x.ends_with(&[1, 2]) => {}, + _ => {}, + } + + match Some(Some(Vec::::new())) { + // Do not lint: deref coercion + Some(Some(x)) if x.starts_with(&[1, 2]) => {}, + _ => {}, + } +} diff --git a/src/tools/clippy/tests/ui/redundant_guards.stderr b/src/tools/clippy/tests/ui/redundant_guards.stderr index b8d7834e358ca..f78d2a814f9b2 100644 --- a/src/tools/clippy/tests/ui/redundant_guards.stderr +++ b/src/tools/clippy/tests/ui/redundant_guards.stderr @@ -203,5 +203,89 @@ LL - B { ref c, .. } if matches!(c, &1) => {}, LL + B { c: 1, .. } => {}, | -error: aborting due to 17 previous errors +error: redundant guard + --> $DIR/redundant_guards.rs:201:26 + | +LL | Some(Some(x)) if x.is_empty() => {}, + | ^^^^^^^^^^^^ + | +help: try + | +LL - Some(Some(x)) if x.is_empty() => {}, +LL + Some(Some("")) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:212:26 + | +LL | Some(Some(x)) if x.is_empty() => {}, + | ^^^^^^^^^^^^ + | +help: try + | +LL - Some(Some(x)) if x.is_empty() => {}, +LL + Some(Some([])) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:217:26 + | +LL | Some(Some(x)) if x.is_empty() => {}, + | ^^^^^^^^^^^^ + | +help: try + | +LL - Some(Some(x)) if x.is_empty() => {}, +LL + Some(Some([])) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:228:26 + | +LL | Some(Some(x)) if x.starts_with(&[]) => {}, + | ^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - Some(Some(x)) if x.starts_with(&[]) => {}, +LL + Some(Some([..])) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:233:26 + | +LL | Some(Some(x)) if x.starts_with(&[1]) => {}, + | ^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - Some(Some(x)) if x.starts_with(&[1]) => {}, +LL + Some(Some([1, ..])) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:238:26 + | +LL | Some(Some(x)) if x.starts_with(&[1, 2]) => {}, + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - Some(Some(x)) if x.starts_with(&[1, 2]) => {}, +LL + Some(Some([1, 2, ..])) => {}, + | + +error: redundant guard + --> $DIR/redundant_guards.rs:243:26 + | +LL | Some(Some(x)) if x.ends_with(&[1, 2]) => {}, + | ^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - Some(Some(x)) if x.ends_with(&[1, 2]) => {}, +LL + Some(Some([.., 1, 2])) => {}, + | + +error: aborting due to 24 previous errors diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr b/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr index 636d88fcd69c6..662188bbabc5a 100644 --- a/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr +++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr @@ -4,5 +4,5 @@ error: usage of deprecated attribute LL | #[clippy::cyclomatic_complexity = "1"] | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `cognitive_complexity` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/result_map_or_into_option.fixed b/src/tools/clippy/tests/ui/result_map_or_into_option.fixed index fb2db6cf5ec03..cf42b24b2dda7 100644 --- a/src/tools/clippy/tests/ui/result_map_or_into_option.fixed +++ b/src/tools/clippy/tests/ui/result_map_or_into_option.fixed @@ -3,6 +3,12 @@ fn main() { let opt: Result = Ok(1); let _ = opt.ok(); + //~^ ERROR: called `map_or(None, Some)` on a `Result` value + let _ = opt.ok(); + //~^ ERROR: called `map_or_else(|_| None, Some)` on a `Result` value + #[rustfmt::skip] + let _ = opt.ok(); + //~^ ERROR: called `map_or_else(|_| None, Some)` on a `Result` value let rewrap = |s: u32| -> Option { Some(s) }; @@ -14,4 +20,5 @@ fn main() { // return should not emit the lint let opt: Result = Ok(1); _ = opt.map_or(None, |_x| Some(1)); + let _ = opt.map_or_else(|a| a.parse::().ok(), Some); } diff --git a/src/tools/clippy/tests/ui/result_map_or_into_option.rs b/src/tools/clippy/tests/ui/result_map_or_into_option.rs index 06779a6992586..cdb45d6b82a0a 100644 --- a/src/tools/clippy/tests/ui/result_map_or_into_option.rs +++ b/src/tools/clippy/tests/ui/result_map_or_into_option.rs @@ -3,6 +3,12 @@ fn main() { let opt: Result = Ok(1); let _ = opt.map_or(None, Some); + //~^ ERROR: called `map_or(None, Some)` on a `Result` value + let _ = opt.map_or_else(|_| None, Some); + //~^ ERROR: called `map_or_else(|_| None, Some)` on a `Result` value + #[rustfmt::skip] + let _ = opt.map_or_else(|_| { None }, Some); + //~^ ERROR: called `map_or_else(|_| None, Some)` on a `Result` value let rewrap = |s: u32| -> Option { Some(s) }; @@ -14,4 +20,5 @@ fn main() { // return should not emit the lint let opt: Result = Ok(1); _ = opt.map_or(None, |_x| Some(1)); + let _ = opt.map_or_else(|a| a.parse::().ok(), Some); } diff --git a/src/tools/clippy/tests/ui/result_map_or_into_option.stderr b/src/tools/clippy/tests/ui/result_map_or_into_option.stderr index 9396ea4c064ef..3d6bfef48ecab 100644 --- a/src/tools/clippy/tests/ui/result_map_or_into_option.stderr +++ b/src/tools/clippy/tests/ui/result_map_or_into_option.stderr @@ -1,4 +1,4 @@ -error: called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling `ok()` instead +error: called `map_or(None, Some)` on a `Result` value --> $DIR/result_map_or_into_option.rs:5:13 | LL | let _ = opt.map_or(None, Some); @@ -7,5 +7,17 @@ LL | let _ = opt.map_or(None, Some); = note: `-D clippy::result-map-or-into-option` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::result_map_or_into_option)]` -error: aborting due to previous error +error: called `map_or_else(|_| None, Some)` on a `Result` value + --> $DIR/result_map_or_into_option.rs:7:13 + | +LL | let _ = opt.map_or_else(|_| None, Some); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()` + +error: called `map_or_else(|_| None, Some)` on a `Result` value + --> $DIR/result_map_or_into_option.rs:10:13 + | +LL | let _ = opt.map_or_else(|_| { None }, Some); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()` + +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/seek_from_current.stderr b/src/tools/clippy/tests/ui/seek_from_current.stderr index 42eb342c10aa6..4858cb82e7eb0 100644 --- a/src/tools/clippy/tests/ui/seek_from_current.stderr +++ b/src/tools/clippy/tests/ui/seek_from_current.stderr @@ -7,5 +7,5 @@ LL | f.seek(SeekFrom::Current(0))?; = note: `-D clippy::seek-from-current` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::seek_from_current)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/self_named_constructors.stderr b/src/tools/clippy/tests/ui/self_named_constructors.stderr index f299b860d4783..8083ff9651579 100644 --- a/src/tools/clippy/tests/ui/self_named_constructors.stderr +++ b/src/tools/clippy/tests/ui/self_named_constructors.stderr @@ -11,5 +11,5 @@ LL | | } = note: `-D clippy::self-named-constructors` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::self_named_constructors)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/serde.stderr b/src/tools/clippy/tests/ui/serde.stderr index e5d64e271644d..079ba42bd2bc5 100644 --- a/src/tools/clippy/tests/ui/serde.stderr +++ b/src/tools/clippy/tests/ui/serde.stderr @@ -13,5 +13,5 @@ LL | | } = note: `-D clippy::serde-api-misuse` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::serde_api_misuse)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/should_panic_without_expect.stderr b/src/tools/clippy/tests/ui/should_panic_without_expect.stderr index dfcef52a9f5f4..b13db83bd5c71 100644 --- a/src/tools/clippy/tests/ui/should_panic_without_expect.stderr +++ b/src/tools/clippy/tests/ui/should_panic_without_expect.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(clippy::should_panic_without_expect)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/single_element_loop.fixed b/src/tools/clippy/tests/ui/single_element_loop.fixed index a82eb6afcf5f3..4e59c76319863 100644 --- a/src/tools/clippy/tests/ui/single_element_loop.fixed +++ b/src/tools/clippy/tests/ui/single_element_loop.fixed @@ -15,23 +15,19 @@ fn main() { dbg!(item); } - { - let item = &(0..5); + for item in 0..5 { dbg!(item); } - { - let item = &mut (0..5); + for item in 0..5 { dbg!(item); } - { - let item = 0..5; + for item in 0..5 { dbg!(item); } - { - let item = 0..5; + for item in 0..5 { dbg!(item); } diff --git a/src/tools/clippy/tests/ui/single_element_loop.stderr b/src/tools/clippy/tests/ui/single_element_loop.stderr index 603dd7406e4e6..952d704143a5b 100644 --- a/src/tools/clippy/tests/ui/single_element_loop.stderr +++ b/src/tools/clippy/tests/ui/single_element_loop.stderr @@ -32,69 +32,29 @@ LL + dbg!(item); LL + } | -error: for loop over a single element - --> $DIR/single_element_loop.rs:16:5 - | -LL | / for item in &[0..5] { -LL | | dbg!(item); -LL | | } - | |_____^ - | -help: try - | -LL ~ { -LL + let item = &(0..5); -LL + dbg!(item); -LL + } +error: this loops only once with `item` being `0..5` + --> $DIR/single_element_loop.rs:16:17 | +LL | for item in &[0..5] { + | ^^^^^^^ help: did you mean to iterate over the range instead?: `0..5` -error: for loop over a single element - --> $DIR/single_element_loop.rs:20:5 - | -LL | / for item in [0..5].iter_mut() { -LL | | dbg!(item); -LL | | } - | |_____^ - | -help: try - | -LL ~ { -LL + let item = &mut (0..5); -LL + dbg!(item); -LL + } +error: this loops only once with `item` being `0..5` + --> $DIR/single_element_loop.rs:20:17 | +LL | for item in [0..5].iter_mut() { + | ^^^^^^^^^^^^^^^^^ help: did you mean to iterate over the range instead?: `0..5` -error: for loop over a single element - --> $DIR/single_element_loop.rs:24:5 - | -LL | / for item in [0..5] { -LL | | dbg!(item); -LL | | } - | |_____^ - | -help: try - | -LL ~ { -LL + let item = 0..5; -LL + dbg!(item); -LL + } +error: this loops only once with `item` being `0..5` + --> $DIR/single_element_loop.rs:24:17 | +LL | for item in [0..5] { + | ^^^^^^ help: did you mean to iterate over the range instead?: `0..5` -error: for loop over a single element - --> $DIR/single_element_loop.rs:28:5 - | -LL | / for item in [0..5].into_iter() { -LL | | dbg!(item); -LL | | } - | |_____^ - | -help: try - | -LL ~ { -LL + let item = 0..5; -LL + dbg!(item); -LL + } +error: this loops only once with `item` being `0..5` + --> $DIR/single_element_loop.rs:28:17 | +LL | for item in [0..5].into_iter() { + | ^^^^^^^^^^^^^^^^^^ help: did you mean to iterate over the range instead?: `0..5` error: for loop over a single element --> $DIR/single_element_loop.rs:47:5 diff --git a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.stderr b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.stderr index cf5688a978241..4738bef3ae9ea 100644 --- a/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.stderr +++ b/src/tools/clippy/tests/ui/string_from_utf8_as_bytes.stderr @@ -7,5 +7,5 @@ LL | let _ = std::str::from_utf8(&"Hello World!".as_bytes()[6..11]); = note: `-D clippy::string-from-utf8-as-bytes` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::string_from_utf8_as_bytes)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/string_to_string.stderr b/src/tools/clippy/tests/ui/string_to_string.stderr index 27a84431507b2..f1f8e176bc57d 100644 --- a/src/tools/clippy/tests/ui/string_to_string.stderr +++ b/src/tools/clippy/tests/ui/string_to_string.stderr @@ -8,5 +8,5 @@ LL | let mut v = message.to_string(); = note: `-D clippy::string-to-string` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::string_to_string)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/test_attr_in_doctest.rs b/src/tools/clippy/tests/ui/test_attr_in_doctest.rs new file mode 100644 index 0000000000000..4c904f7a09acc --- /dev/null +++ b/src/tools/clippy/tests/ui/test_attr_in_doctest.rs @@ -0,0 +1,51 @@ +/// This is a test for `#[test]` in doctests +/// +/// # Examples +/// +/// ``` +/// #[test] +/// fn should_be_linted() { +/// assert_eq!(1, 1); +/// } +/// ``` +/// +/// Make sure we catch multiple tests in one example, +/// and show that we really parse the attr: +/// +/// ``` +/// #[test] +/// fn should_also_be_linted() { +/// #[cfg(test)] +/// assert!(true); +/// } +/// +/// #[test] +/// fn should_be_linted_too() { +/// assert_eq!("#[test]", " +/// #[test] +/// "); +/// } +/// ``` +/// +/// We don't catch examples that aren't run: +/// +/// ```ignore +/// #[test] +/// fn ignored() { todo!() } +/// ``` +/// +/// ```no_run +/// #[test] +/// fn ignored() { todo!() } +/// ``` +/// +/// ```compile_fail +/// #[test] +/// fn ignored() { Err(()) } +/// ``` +/// +/// ```txt +/// #[test] +/// fn not_even_rust() { panic!("Ouch") } +/// ``` +fn test_attr_in_doctests() {} diff --git a/src/tools/clippy/tests/ui/test_attr_in_doctest.stderr b/src/tools/clippy/tests/ui/test_attr_in_doctest.stderr new file mode 100644 index 0000000000000..605259f3bfb4c --- /dev/null +++ b/src/tools/clippy/tests/ui/test_attr_in_doctest.stderr @@ -0,0 +1,29 @@ +error: unit tests in doctest are not executed + --> $DIR/test_attr_in_doctest.rs:6:5 + | +LL | /// #[test] + | _____^ +LL | | /// fn should_be_linted() { + | |_______________________^ + | + = note: `-D clippy::test-attr-in-doctest` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::test_attr_in_doctest)]` + +error: unit tests in doctest are not executed + --> $DIR/test_attr_in_doctest.rs:16:5 + | +LL | /// #[test] + | _____^ +LL | | /// fn should_also_be_linted() { + | |____________________________^ + +error: unit tests in doctest are not executed + --> $DIR/test_attr_in_doctest.rs:22:5 + | +LL | /// #[test] + | _____^ +LL | | /// fn should_be_linted_too() { + | |___________________________^ + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/tests_outside_test_module.stderr b/src/tools/clippy/tests/ui/tests_outside_test_module.stderr index 112d6ce1f2c46..ec0cdea83d657 100644 --- a/src/tools/clippy/tests/ui/tests_outside_test_module.stderr +++ b/src/tools/clippy/tests/ui/tests_outside_test_module.stderr @@ -8,5 +8,5 @@ LL | fn my_test() {} = note: `-D clippy::tests-outside-test-module` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::tests_outside_test_module)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/track-diagnostics.stderr b/src/tools/clippy/tests/ui/track-diagnostics.stderr index 39418d359288b..131adfd588c25 100644 --- a/src/tools/clippy/tests/ui/track-diagnostics.stderr +++ b/src/tools/clippy/tests/ui/track-diagnostics.stderr @@ -5,6 +5,6 @@ LL | const S: A = B; | ^ expected `A`, found `B` -Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed index 19abced98bb85..4e145693c553a 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.fixed @@ -43,6 +43,9 @@ fn transmute_ptr_to_ptr() { //~^ ERROR: transmute from a reference to a reference let _: &GenericParam = &*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam); //~^ ERROR: transmute from a reference to a reference + let u8_ref: &u8 = &0u8; + let u64_ref: &u64 = unsafe { &*(u8_ref as *const u8 as *const u64) }; + //~^ ERROR: transmute from a reference to a reference } // these are recommendations for solving the above; if these lint we need to update diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs index abba2b8e5244d..086aadc364740 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs @@ -43,6 +43,9 @@ fn transmute_ptr_to_ptr() { //~^ ERROR: transmute from a reference to a reference let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); //~^ ERROR: transmute from a reference to a reference + let u8_ref: &u8 = &0u8; + let u64_ref: &u64 = unsafe { std::mem::transmute(u8_ref) }; + //~^ ERROR: transmute from a reference to a reference } // these are recommendations for solving the above; if these lint we need to update diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr index 564339c067ee1..9f8599921ec7d 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.stderr @@ -37,5 +37,11 @@ error: transmute from a reference to a reference LL | let _: &GenericParam = std::mem::transmute(&GenericParam { t: 1u32 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam as *const GenericParam)` -error: aborting due to 6 previous errors +error: transmute from a reference to a reference + --> $DIR/transmute_ptr_to_ptr.rs:47:38 + | +LL | let u64_ref: &u64 = unsafe { std::mem::transmute(u8_ref) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(u8_ref as *const u8 as *const u64)` + +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/transmute_ref_to_ref.rs b/src/tools/clippy/tests/ui/transmute_ref_to_ref.rs new file mode 100644 index 0000000000000..e7f35c5743684 --- /dev/null +++ b/src/tools/clippy/tests/ui/transmute_ref_to_ref.rs @@ -0,0 +1,18 @@ +//@no-rustfix + +#![deny(clippy::transmute_ptr_to_ptr)] +#![allow(dead_code)] + +fn main() { + unsafe { + let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF]; + let bools: &[bool] = unsafe { std::mem::transmute(single_u64) }; + //~^ ERROR: transmute from a reference to a reference + let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321]; + let b: &[u8] = unsafe { std::mem::transmute(a) }; + //~^ ERROR: transmute from a reference to a reference + let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8]; + let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; + //~^ ERROR: transmute from a reference to a reference + } +} diff --git a/src/tools/clippy/tests/ui/transmute_ref_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ref_to_ref.stderr new file mode 100644 index 0000000000000..cc6b156b18885 --- /dev/null +++ b/src/tools/clippy/tests/ui/transmute_ref_to_ref.stderr @@ -0,0 +1,26 @@ +error: transmute from a reference to a reference + --> $DIR/transmute_ref_to_ref.rs:9:39 + | +LL | let bools: &[bool] = unsafe { std::mem::transmute(single_u64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(single_u64 as *const [u64] as *const [bool])` + | +note: the lint level is defined here + --> $DIR/transmute_ref_to_ref.rs:3:9 + | +LL | #![deny(clippy::transmute_ptr_to_ptr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmute from a reference to a reference + --> $DIR/transmute_ref_to_ref.rs:12:33 + | +LL | let b: &[u8] = unsafe { std::mem::transmute(a) }; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])` + +error: transmute from a reference to a reference + --> $DIR/transmute_ref_to_ref.rs:15:42 + | +LL | let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])` + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/types.stderr b/src/tools/clippy/tests/ui/types.stderr index b253cf33867f7..f7473e1c5c52d 100644 --- a/src/tools/clippy/tests/ui/types.stderr +++ b/src/tools/clippy/tests/ui/types.stderr @@ -7,5 +7,5 @@ LL | let c_i64: i64 = c as i64; = note: `-D clippy::cast-lossless` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.stderr b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.stderr index 221efeb50cd9b..736a68ab1c7e3 100644 --- a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.stderr +++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.stderr @@ -12,5 +12,5 @@ LL - println!("val='{}'", var); LL + println!("val='{var}'"); | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/unknown_attribute.stderr b/src/tools/clippy/tests/ui/unknown_attribute.stderr index 618c5980d64e5..edad35d1591be 100644 --- a/src/tools/clippy/tests/ui/unknown_attribute.stderr +++ b/src/tools/clippy/tests/ui/unknown_attribute.stderr @@ -4,5 +4,5 @@ error: usage of unknown attribute LL | #[clippy::unknown] | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/unnecessary_fallible_conversions.stderr b/src/tools/clippy/tests/ui/unnecessary_fallible_conversions.stderr index b918fdf774b5a..26b152515ac7c 100644 --- a/src/tools/clippy/tests/ui/unnecessary_fallible_conversions.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_fallible_conversions.stderr @@ -4,6 +4,7 @@ error: use of a fallible conversion when an infallible one could be used LL | let _: i64 = 0i32.try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^ help: use: `into()` | + = note: converting `i32` to `i64` cannot fail = note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]` @@ -12,6 +13,8 @@ error: use of a fallible conversion when an infallible one could be used | LL | let _: i64 = 0i32.try_into().expect("can't happen"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `into()` + | + = note: converting `i32` to `i64` cannot fail error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_fallible_conversions_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_fallible_conversions_unfixable.stderr index 286decf8f3581..033de0e925082 100644 --- a/src/tools/clippy/tests/ui/unnecessary_fallible_conversions_unfixable.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_fallible_conversions_unfixable.stderr @@ -4,6 +4,7 @@ error: use of a fallible conversion when an infallible one could be used LL | let _: Result = 0i64.try_into(); | ^^^^^^^^ help: use: `into` | + = note: converting `i64` to `Foo` cannot fail = note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]` @@ -12,30 +13,40 @@ error: use of a fallible conversion when an infallible one could be used | LL | let _: Result = i64::try_into(0i64); | ^^^^^^^^^^^^^ help: use: `Into::into` + | + = note: converting `i64` to `Foo` cannot fail error: use of a fallible conversion when an infallible one could be used --> $DIR/unnecessary_fallible_conversions_unfixable.rs:31:29 | LL | let _: Result = Foo::try_from(0i64); | ^^^^^^^^^^^^^ help: use: `From::from` + | + = note: converting `i64` to `Foo` cannot fail error: use of a fallible conversion when an infallible one could be used --> $DIR/unnecessary_fallible_conversions_unfixable.rs:34:34 | LL | let _: Result = 0i32.try_into(); | ^^^^^^^^ help: use: `into` + | + = note: converting `i32` to `i64` cannot fail error: use of a fallible conversion when an infallible one could be used --> $DIR/unnecessary_fallible_conversions_unfixable.rs:36:29 | LL | let _: Result = i32::try_into(0i32); | ^^^^^^^^^^^^^ help: use: `Into::into` + | + = note: converting `i32` to `i64` cannot fail error: use of a fallible conversion when an infallible one could be used --> $DIR/unnecessary_fallible_conversions_unfixable.rs:38:29 | LL | let _: Result = <_>::try_from(0i32); | ^^^^^^^^^^^^^ help: use: `From::from` + | + = note: converting `i32` to `i64` cannot fail error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed index 4778eaefdbdbb..66598f89208ba 100644 --- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed @@ -6,6 +6,8 @@ #![allow(clippy::needless_borrow)] #![allow(clippy::unnecessary_literal_unwrap)] #![allow(clippy::unit_arg)] +#![allow(arithmetic_overflow)] +#![allow(unconditional_panic)] use std::ops::Deref; @@ -190,3 +192,79 @@ fn issue9485() { // should not lint, is in proc macro with_span!(span Some(42).unwrap_or_else(|| 2);); } + +fn issue9422(x: usize) -> Option { + (x >= 5).then(|| x - 5) + // (x >= 5).then_some(x - 5) // clippy suggestion panics +} + +fn panicky_arithmetic_ops(x: usize, y: isize) { + #![allow(clippy::identity_op, clippy::eq_op)] + + // See comments in `eager_or_lazy.rs` for the rules that this is meant to follow + + let _x = false.then_some(i32::MAX + 1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(i32::MAX * 2); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(i32::MAX - 1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(i32::MIN - 1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some((1 + 2 * 3 - 2 / 3 + 9) << 2); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(255u8 << 7); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(255u8 << 8); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(255u8 >> 8); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 255u8 >> x); + let _x = false.then_some(i32::MAX + -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(-i32::MAX); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(-i32::MIN); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| -y); + let _x = false.then_some(255 >> -7); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(255 << -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(1 / 0); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(x << -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(x << 2); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| x + x); + let _x = false.then(|| x * x); + let _x = false.then(|| x - x); + let _x = false.then(|| x / x); + let _x = false.then(|| x % x); + let _x = false.then(|| x + 1); + let _x = false.then(|| 1 + x); + + let _x = false.then_some(x / 0); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(x % 0); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| y / -1); + let _x = false.then_some(1 / -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(i32::MIN / -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| i32::MIN / x as i32); + let _x = false.then_some(i32::MIN / 0); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then_some(4 / 2); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 1 / x); + + // const eval doesn't read variables, but floating point math never panics, so we can still emit a + // warning + let f1 = 1.0; + let f2 = 2.0; + let _x = false.then_some(f1 + f2); + //~^ ERROR: unnecessary closure used with `bool::then` +} diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs index d4b7fd31b1b0f..5045fcd790eda 100644 --- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs @@ -6,6 +6,8 @@ #![allow(clippy::needless_borrow)] #![allow(clippy::unnecessary_literal_unwrap)] #![allow(clippy::unit_arg)] +#![allow(arithmetic_overflow)] +#![allow(unconditional_panic)] use std::ops::Deref; @@ -190,3 +192,79 @@ fn issue9485() { // should not lint, is in proc macro with_span!(span Some(42).unwrap_or_else(|| 2);); } + +fn issue9422(x: usize) -> Option { + (x >= 5).then(|| x - 5) + // (x >= 5).then_some(x - 5) // clippy suggestion panics +} + +fn panicky_arithmetic_ops(x: usize, y: isize) { + #![allow(clippy::identity_op, clippy::eq_op)] + + // See comments in `eager_or_lazy.rs` for the rules that this is meant to follow + + let _x = false.then(|| i32::MAX + 1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| i32::MAX * 2); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| i32::MAX - 1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| i32::MIN - 1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 255u8 << 7); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 255u8 << 8); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 255u8 >> 8); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 255u8 >> x); + let _x = false.then(|| i32::MAX + -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| -i32::MAX); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| -i32::MIN); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| -y); + let _x = false.then(|| 255 >> -7); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 255 << -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 1 / 0); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| x << -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| x << 2); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| x + x); + let _x = false.then(|| x * x); + let _x = false.then(|| x - x); + let _x = false.then(|| x / x); + let _x = false.then(|| x % x); + let _x = false.then(|| x + 1); + let _x = false.then(|| 1 + x); + + let _x = false.then(|| x / 0); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| x % 0); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| y / -1); + let _x = false.then(|| 1 / -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| i32::MIN / -1); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| i32::MIN / x as i32); + let _x = false.then(|| i32::MIN / 0); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 4 / 2); + //~^ ERROR: unnecessary closure used with `bool::then` + let _x = false.then(|| 1 / x); + + // const eval doesn't read variables, but floating point math never panics, so we can still emit a + // warning + let f1 = 1.0; + let f2 = 2.0; + let _x = false.then(|| f1 + f2); + //~^ ERROR: unnecessary closure used with `bool::then` +} diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr index 1b0db4759bbaa..466664aee6c79 100644 --- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr @@ -1,5 +1,5 @@ error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:69:13 + --> $DIR/unnecessary_lazy_eval.rs:71:13 | LL | let _ = opt.unwrap_or_else(|| 2); | ^^^^-------------------- @@ -10,7 +10,7 @@ LL | let _ = opt.unwrap_or_else(|| 2); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:70:13 + --> $DIR/unnecessary_lazy_eval.rs:72:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | ^^^^--------------------------------- @@ -18,7 +18,7 @@ LL | let _ = opt.unwrap_or_else(|| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:71:13 + --> $DIR/unnecessary_lazy_eval.rs:73:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | ^^^^------------------------------------- @@ -26,7 +26,7 @@ LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:73:13 + --> $DIR/unnecessary_lazy_eval.rs:75:13 | LL | let _ = opt.and_then(|_| ext_opt); | ^^^^--------------------- @@ -34,7 +34,7 @@ LL | let _ = opt.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:74:13 + --> $DIR/unnecessary_lazy_eval.rs:76:13 | LL | let _ = opt.or_else(|| ext_opt); | ^^^^------------------- @@ -42,7 +42,7 @@ LL | let _ = opt.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:75:13 + --> $DIR/unnecessary_lazy_eval.rs:77:13 | LL | let _ = opt.or_else(|| None); | ^^^^---------------- @@ -50,7 +50,7 @@ LL | let _ = opt.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:76:13 + --> $DIR/unnecessary_lazy_eval.rs:78:13 | LL | let _ = opt.get_or_insert_with(|| 2); | ^^^^------------------------ @@ -58,7 +58,7 @@ LL | let _ = opt.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:77:13 + --> $DIR/unnecessary_lazy_eval.rs:79:13 | LL | let _ = opt.ok_or_else(|| 2); | ^^^^---------------- @@ -66,7 +66,7 @@ LL | let _ = opt.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:78:13 + --> $DIR/unnecessary_lazy_eval.rs:80:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | ^^^^^^^^^^^^^^^^^------------------------------- @@ -74,7 +74,7 @@ LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); | help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))` error: unnecessary closure used with `bool::then` - --> $DIR/unnecessary_lazy_eval.rs:79:13 + --> $DIR/unnecessary_lazy_eval.rs:81:13 | LL | let _ = cond.then(|| astronomers_pi); | ^^^^^----------------------- @@ -82,7 +82,7 @@ LL | let _ = cond.then(|| astronomers_pi); | help: use `then_some(..)` instead: `then_some(astronomers_pi)` error: unnecessary closure used with `bool::then` - --> $DIR/unnecessary_lazy_eval.rs:80:13 + --> $DIR/unnecessary_lazy_eval.rs:82:13 | LL | let _ = true.then(|| -> _ {}); | ^^^^^---------------- @@ -90,7 +90,7 @@ LL | let _ = true.then(|| -> _ {}); | help: use `then_some(..)` instead: `then_some({})` error: unnecessary closure used with `bool::then` - --> $DIR/unnecessary_lazy_eval.rs:81:13 + --> $DIR/unnecessary_lazy_eval.rs:83:13 | LL | let _ = true.then(|| {}); | ^^^^^----------- @@ -98,7 +98,7 @@ LL | let _ = true.then(|| {}); | help: use `then_some(..)` instead: `then_some({})` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:85:13 + --> $DIR/unnecessary_lazy_eval.rs:87:13 | LL | let _ = Some(1).unwrap_or_else(|| *r); | ^^^^^^^^--------------------- @@ -106,7 +106,7 @@ LL | let _ = Some(1).unwrap_or_else(|| *r); | help: use `unwrap_or(..)` instead: `unwrap_or(*r)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:87:13 + --> $DIR/unnecessary_lazy_eval.rs:89:13 | LL | let _ = Some(1).unwrap_or_else(|| *b); | ^^^^^^^^--------------------- @@ -114,7 +114,7 @@ LL | let _ = Some(1).unwrap_or_else(|| *b); | help: use `unwrap_or(..)` instead: `unwrap_or(*b)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:89:13 + --> $DIR/unnecessary_lazy_eval.rs:91:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); | ^^^^^^^^^^^^^^^^^--------------------- @@ -122,7 +122,7 @@ LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); | help: use `unwrap_or(..)` instead: `unwrap_or(&r)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:90:13 + --> $DIR/unnecessary_lazy_eval.rs:92:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); | ^^^^^^^^^^^^^^^^^--------------------- @@ -130,7 +130,7 @@ LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); | help: use `unwrap_or(..)` instead: `unwrap_or(&b)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:93:13 + --> $DIR/unnecessary_lazy_eval.rs:95:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); | ^^^^^^^^^-------------------- @@ -138,7 +138,7 @@ LL | let _ = Some(10).unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:94:13 + --> $DIR/unnecessary_lazy_eval.rs:96:13 | LL | let _ = Some(10).and_then(|_| ext_opt); | ^^^^^^^^^--------------------- @@ -146,7 +146,7 @@ LL | let _ = Some(10).and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:95:28 + --> $DIR/unnecessary_lazy_eval.rs:97:28 | LL | let _: Option = None.or_else(|| ext_opt); | ^^^^^------------------- @@ -154,7 +154,7 @@ LL | let _: Option = None.or_else(|| ext_opt); | help: use `or(..)` instead: `or(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:96:13 + --> $DIR/unnecessary_lazy_eval.rs:98:13 | LL | let _ = None.get_or_insert_with(|| 2); | ^^^^^------------------------ @@ -162,7 +162,7 @@ LL | let _ = None.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:97:35 + --> $DIR/unnecessary_lazy_eval.rs:99:35 | LL | let _: Result = None.ok_or_else(|| 2); | ^^^^^---------------- @@ -170,7 +170,7 @@ LL | let _: Result = None.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:98:28 + --> $DIR/unnecessary_lazy_eval.rs:100:28 | LL | let _: Option = None.or_else(|| None); | ^^^^^---------------- @@ -178,7 +178,7 @@ LL | let _: Option = None.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:101:13 + --> $DIR/unnecessary_lazy_eval.rs:103:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); | ^^^^^^^-------------------- @@ -186,7 +186,7 @@ LL | let _ = deep.0.unwrap_or_else(|| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:102:13 + --> $DIR/unnecessary_lazy_eval.rs:104:13 | LL | let _ = deep.0.and_then(|_| ext_opt); | ^^^^^^^--------------------- @@ -194,7 +194,7 @@ LL | let _ = deep.0.and_then(|_| ext_opt); | help: use `and(..)` instead: `and(ext_opt)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:103:13 + --> $DIR/unnecessary_lazy_eval.rs:105:13 | LL | let _ = deep.0.or_else(|| None); | ^^^^^^^---------------- @@ -202,7 +202,7 @@ LL | let _ = deep.0.or_else(|| None); | help: use `or(..)` instead: `or(None)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:104:13 + --> $DIR/unnecessary_lazy_eval.rs:106:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); | ^^^^^^^------------------------ @@ -210,7 +210,7 @@ LL | let _ = deep.0.get_or_insert_with(|| 2); | help: use `get_or_insert(..)` instead: `get_or_insert(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:105:13 + --> $DIR/unnecessary_lazy_eval.rs:107:13 | LL | let _ = deep.0.ok_or_else(|| 2); | ^^^^^^^---------------- @@ -218,7 +218,7 @@ LL | let _ = deep.0.ok_or_else(|| 2); | help: use `ok_or(..)` instead: `ok_or(2)` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:135:28 + --> $DIR/unnecessary_lazy_eval.rs:137:28 | LL | let _: Option = None.or_else(|| Some(3)); | ^^^^^------------------- @@ -226,7 +226,7 @@ LL | let _: Option = None.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:136:13 + --> $DIR/unnecessary_lazy_eval.rs:138:13 | LL | let _ = deep.0.or_else(|| Some(3)); | ^^^^^^^------------------- @@ -234,7 +234,7 @@ LL | let _ = deep.0.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Option::None` - --> $DIR/unnecessary_lazy_eval.rs:137:13 + --> $DIR/unnecessary_lazy_eval.rs:139:13 | LL | let _ = opt.or_else(|| Some(3)); | ^^^^------------------- @@ -242,7 +242,7 @@ LL | let _ = opt.or_else(|| Some(3)); | help: use `or(..)` instead: `or(Some(3))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:143:13 + --> $DIR/unnecessary_lazy_eval.rs:145:13 | LL | let _ = res2.unwrap_or_else(|_| 2); | ^^^^^--------------------- @@ -250,7 +250,7 @@ LL | let _ = res2.unwrap_or_else(|_| 2); | help: use `unwrap_or(..)` instead: `unwrap_or(2)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:144:13 + --> $DIR/unnecessary_lazy_eval.rs:146:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | ^^^^^---------------------------------- @@ -258,7 +258,7 @@ LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:145:13 + --> $DIR/unnecessary_lazy_eval.rs:147:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | ^^^^^-------------------------------------- @@ -266,7 +266,7 @@ LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:167:35 + --> $DIR/unnecessary_lazy_eval.rs:169:35 | LL | let _: Result = res.and_then(|_| Err(2)); | ^^^^-------------------- @@ -274,7 +274,7 @@ LL | let _: Result = res.and_then(|_| Err(2)); | help: use `and(..)` instead: `and(Err(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:168:35 + --> $DIR/unnecessary_lazy_eval.rs:170:35 | LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | ^^^^--------------------------------- @@ -282,7 +282,7 @@ LL | let _: Result = res.and_then(|_| Err(astronomers_pi)); | help: use `and(..)` instead: `and(Err(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:169:35 + --> $DIR/unnecessary_lazy_eval.rs:171:35 | LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)); | ^^^^------------------------------------- @@ -290,7 +290,7 @@ LL | let _: Result = res.and_then(|_| Err(ext_str.some_field)) | help: use `and(..)` instead: `and(Err(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:171:35 + --> $DIR/unnecessary_lazy_eval.rs:173:35 | LL | let _: Result = res.or_else(|_| Ok(2)); | ^^^^------------------ @@ -298,7 +298,7 @@ LL | let _: Result = res.or_else(|_| Ok(2)); | help: use `or(..)` instead: `or(Ok(2))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:172:35 + --> $DIR/unnecessary_lazy_eval.rs:174:35 | LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | ^^^^------------------------------- @@ -306,7 +306,7 @@ LL | let _: Result = res.or_else(|_| Ok(astronomers_pi)); | help: use `or(..)` instead: `or(Ok(astronomers_pi))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:173:35 + --> $DIR/unnecessary_lazy_eval.rs:175:35 | LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | ^^^^----------------------------------- @@ -314,7 +314,7 @@ LL | let _: Result = res.or_else(|_| Ok(ext_str.some_field)); | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` error: unnecessary closure used to substitute value for `Result::Err` - --> $DIR/unnecessary_lazy_eval.rs:174:35 + --> $DIR/unnecessary_lazy_eval.rs:176:35 | LL | let _: Result = res. | ___________________________________^ @@ -328,5 +328,189 @@ LL | | or_else(|_| Ok(ext_str.some_field)); | | | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` -error: aborting due to 40 previous errors +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:206:14 + | +LL | let _x = false.then(|| i32::MAX + 1); + | ^^^^^^--------------------- + | | + | help: use `then_some(..)` instead: `then_some(i32::MAX + 1)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:208:14 + | +LL | let _x = false.then(|| i32::MAX * 2); + | ^^^^^^--------------------- + | | + | help: use `then_some(..)` instead: `then_some(i32::MAX * 2)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:210:14 + | +LL | let _x = false.then(|| i32::MAX - 1); + | ^^^^^^--------------------- + | | + | help: use `then_some(..)` instead: `then_some(i32::MAX - 1)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:212:14 + | +LL | let _x = false.then(|| i32::MIN - 1); + | ^^^^^^--------------------- + | | + | help: use `then_some(..)` instead: `then_some(i32::MIN - 1)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:214:14 + | +LL | let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2); + | ^^^^^^------------------------------------- + | | + | help: use `then_some(..)` instead: `then_some((1 + 2 * 3 - 2 / 3 + 9) << 2)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:216:14 + | +LL | let _x = false.then(|| 255u8 << 7); + | ^^^^^^------------------- + | | + | help: use `then_some(..)` instead: `then_some(255u8 << 7)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:218:14 + | +LL | let _x = false.then(|| 255u8 << 8); + | ^^^^^^------------------- + | | + | help: use `then_some(..)` instead: `then_some(255u8 << 8)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:220:14 + | +LL | let _x = false.then(|| 255u8 >> 8); + | ^^^^^^------------------- + | | + | help: use `then_some(..)` instead: `then_some(255u8 >> 8)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:223:14 + | +LL | let _x = false.then(|| i32::MAX + -1); + | ^^^^^^---------------------- + | | + | help: use `then_some(..)` instead: `then_some(i32::MAX + -1)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:225:14 + | +LL | let _x = false.then(|| -i32::MAX); + | ^^^^^^------------------ + | | + | help: use `then_some(..)` instead: `then_some(-i32::MAX)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:227:14 + | +LL | let _x = false.then(|| -i32::MIN); + | ^^^^^^------------------ + | | + | help: use `then_some(..)` instead: `then_some(-i32::MIN)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:230:14 + | +LL | let _x = false.then(|| 255 >> -7); + | ^^^^^^------------------ + | | + | help: use `then_some(..)` instead: `then_some(255 >> -7)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:232:14 + | +LL | let _x = false.then(|| 255 << -1); + | ^^^^^^------------------ + | | + | help: use `then_some(..)` instead: `then_some(255 << -1)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:234:14 + | +LL | let _x = false.then(|| 1 / 0); + | ^^^^^^-------------- + | | + | help: use `then_some(..)` instead: `then_some(1 / 0)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:236:14 + | +LL | let _x = false.then(|| x << -1); + | ^^^^^^---------------- + | | + | help: use `then_some(..)` instead: `then_some(x << -1)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:238:14 + | +LL | let _x = false.then(|| x << 2); + | ^^^^^^--------------- + | | + | help: use `then_some(..)` instead: `then_some(x << 2)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:248:14 + | +LL | let _x = false.then(|| x / 0); + | ^^^^^^-------------- + | | + | help: use `then_some(..)` instead: `then_some(x / 0)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:250:14 + | +LL | let _x = false.then(|| x % 0); + | ^^^^^^-------------- + | | + | help: use `then_some(..)` instead: `then_some(x % 0)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:253:14 + | +LL | let _x = false.then(|| 1 / -1); + | ^^^^^^--------------- + | | + | help: use `then_some(..)` instead: `then_some(1 / -1)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:255:14 + | +LL | let _x = false.then(|| i32::MIN / -1); + | ^^^^^^---------------------- + | | + | help: use `then_some(..)` instead: `then_some(i32::MIN / -1)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:258:14 + | +LL | let _x = false.then(|| i32::MIN / 0); + | ^^^^^^--------------------- + | | + | help: use `then_some(..)` instead: `then_some(i32::MIN / 0)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:260:14 + | +LL | let _x = false.then(|| 4 / 2); + | ^^^^^^-------------- + | | + | help: use `then_some(..)` instead: `then_some(4 / 2)` + +error: unnecessary closure used with `bool::then` + --> $DIR/unnecessary_lazy_eval.rs:268:14 + | +LL | let _x = false.then(|| f1 + f2); + | ^^^^^^---------------- + | | + | help: use `then_some(..)` instead: `then_some(f1 + f2)` + +error: aborting due to 63 previous errors diff --git a/src/tools/clippy/tests/ui/upper_case_acronyms.fixed b/src/tools/clippy/tests/ui/upper_case_acronyms.fixed index 460567b097e53..a8023ed00d213 100644 --- a/src/tools/clippy/tests/ui/upper_case_acronyms.fixed +++ b/src/tools/clippy/tests/ui/upper_case_acronyms.fixed @@ -59,4 +59,12 @@ enum Yaml { Str(String), } +// test for issue #7708 +enum AllowOnField { + Disallow, + //~^ ERROR: name `DISALLOW` contains a capitalized acronym + #[allow(clippy::upper_case_acronyms)] + ALLOW, +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/upper_case_acronyms.rs b/src/tools/clippy/tests/ui/upper_case_acronyms.rs index 6a20aee62dce7..c4711b87ec380 100644 --- a/src/tools/clippy/tests/ui/upper_case_acronyms.rs +++ b/src/tools/clippy/tests/ui/upper_case_acronyms.rs @@ -59,4 +59,12 @@ enum YAML { Str(String), } +// test for issue #7708 +enum AllowOnField { + DISALLOW, + //~^ ERROR: name `DISALLOW` contains a capitalized acronym + #[allow(clippy::upper_case_acronyms)] + ALLOW, +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/upper_case_acronyms.stderr b/src/tools/clippy/tests/ui/upper_case_acronyms.stderr index c57b325e91a6d..009c53c725b6f 100644 --- a/src/tools/clippy/tests/ui/upper_case_acronyms.stderr +++ b/src/tools/clippy/tests/ui/upper_case_acronyms.stderr @@ -67,5 +67,11 @@ error: name `YAML` contains a capitalized acronym LL | enum YAML { | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Yaml` -error: aborting due to 11 previous errors +error: name `DISALLOW` contains a capitalized acronym + --> $DIR/upper_case_acronyms.rs:64:5 + | +LL | DISALLOW, + | ^^^^^^^^ help: consider making the acronym lowercase, except the initial letter: `Disallow` + +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/vec_box_sized.fixed b/src/tools/clippy/tests/ui/vec_box_sized.fixed deleted file mode 100644 index 4363d2224afd2..0000000000000 --- a/src/tools/clippy/tests/ui/vec_box_sized.fixed +++ /dev/null @@ -1,57 +0,0 @@ -#![allow(dead_code)] - -struct SizedStruct(i32); -struct UnsizedStruct([i32]); -struct BigStruct([i32; 10000]); - -/// The following should trigger the lint -mod should_trigger { - use super::SizedStruct; - const C: Vec = Vec::new(); - static S: Vec = Vec::new(); - - struct StructWithVecBox { - sized_type: Vec, - } - - struct A(Vec); - struct B(Vec>); -} - -/// The following should not trigger the lint -mod should_not_trigger { - use super::{BigStruct, UnsizedStruct}; - - struct C(Vec>); - struct D(Vec>); - - struct StructWithVecBoxButItsUnsized { - unsized_type: Vec>, - } - - struct TraitVec { - // Regression test for #3720. This was causing an ICE. - inner: Vec>, - } -} - -mod inner_mod { - mod inner { - pub struct S; - } - - mod inner2 { - use super::inner::S; - - pub fn f() -> Vec { - vec![] - } - } -} - -// https://github.com/rust-lang/rust-clippy/issues/11417 -fn in_closure() { - let _ = |_: Vec>| {}; -} - -fn main() {} diff --git a/src/tools/clippy/tests/ui/vec_box_sized.rs b/src/tools/clippy/tests/ui/vec_box_sized.rs index f4e27fe4bd509..49eaf8e062af3 100644 --- a/src/tools/clippy/tests/ui/vec_box_sized.rs +++ b/src/tools/clippy/tests/ui/vec_box_sized.rs @@ -1,12 +1,28 @@ +//@no-rustfix + #![allow(dead_code)] +#![feature(allocator_api)] + +use std::alloc::{AllocError, Allocator, Layout}; +use std::ptr::NonNull; struct SizedStruct(i32); struct UnsizedStruct([i32]); struct BigStruct([i32; 10000]); +struct DummyAllocator; +unsafe impl Allocator for DummyAllocator { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + todo!() + } + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + todo!() + } +} + /// The following should trigger the lint mod should_trigger { - use super::SizedStruct; + use super::{DummyAllocator, SizedStruct}; const C: Vec> = Vec::new(); static S: Vec> = Vec::new(); @@ -16,11 +32,21 @@ mod should_trigger { struct A(Vec>); struct B(Vec>>); + + fn allocator_global_defined_vec() -> Vec, std::alloc::Global> { + Vec::new() + } + fn allocator_global_defined_box() -> Vec> { + Vec::new() + } + fn allocator_match() -> Vec, DummyAllocator> { + Vec::new_in(DummyAllocator) + } } /// The following should not trigger the lint mod should_not_trigger { - use super::{BigStruct, UnsizedStruct}; + use super::{BigStruct, DummyAllocator, UnsizedStruct}; struct C(Vec>); struct D(Vec>); @@ -33,6 +59,13 @@ mod should_not_trigger { // Regression test for #3720. This was causing an ICE. inner: Vec>, } + + fn allocator_mismatch() -> Vec> { + Vec::new() + } + fn allocator_mismatch_2() -> Vec, DummyAllocator> { + Vec::new_in(DummyAllocator) + } } mod inner_mod { diff --git a/src/tools/clippy/tests/ui/vec_box_sized.stderr b/src/tools/clippy/tests/ui/vec_box_sized.stderr index 9118f284bb977..d6479271fa632 100644 --- a/src/tools/clippy/tests/ui/vec_box_sized.stderr +++ b/src/tools/clippy/tests/ui/vec_box_sized.stderr @@ -1,5 +1,5 @@ error: `Vec` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:10:14 + --> $DIR/vec_box_sized.rs:26:14 | LL | const C: Vec> = Vec::new(); | ^^^^^^^^^^^^^ help: try: `Vec` @@ -8,34 +8,52 @@ LL | const C: Vec> = Vec::new(); = help: to override `-D warnings` add `#[allow(clippy::vec_box)]` error: `Vec` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:11:15 + --> $DIR/vec_box_sized.rs:27:15 | LL | static S: Vec> = Vec::new(); | ^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:14:21 + --> $DIR/vec_box_sized.rs:30:21 | LL | sized_type: Vec>, | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:17:14 + --> $DIR/vec_box_sized.rs:33:14 | LL | struct A(Vec>); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:18:18 + --> $DIR/vec_box_sized.rs:34:18 | LL | struct B(Vec>>); | ^^^^^^^^^^^^^^^ help: try: `Vec` error: `Vec` is already on the heap, the boxing is unnecessary - --> $DIR/vec_box_sized.rs:46:23 + --> $DIR/vec_box_sized.rs:36:42 + | +LL | fn allocator_global_defined_vec() -> Vec, std::alloc::Global> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` + +error: `Vec` is already on the heap, the boxing is unnecessary + --> $DIR/vec_box_sized.rs:39:42 + | +LL | fn allocator_global_defined_box() -> Vec> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` + +error: `Vec` is already on the heap, the boxing is unnecessary + --> $DIR/vec_box_sized.rs:42:29 + | +LL | fn allocator_match() -> Vec, DummyAllocator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec` + +error: `Vec` is already on the heap, the boxing is unnecessary + --> $DIR/vec_box_sized.rs:79:23 | LL | pub fn f() -> Vec> { | ^^^^^^^^^^^ help: try: `Vec` -error: aborting due to 6 previous errors +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/vec_resize_to_zero.stderr b/src/tools/clippy/tests/ui/vec_resize_to_zero.stderr index 715c9923b2e54..c16ba4e526278 100644 --- a/src/tools/clippy/tests/ui/vec_resize_to_zero.stderr +++ b/src/tools/clippy/tests/ui/vec_resize_to_zero.stderr @@ -10,5 +10,5 @@ LL | v.resize(0, 5); = note: `-D clippy::vec-resize-to-zero` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::vec_resize_to_zero)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml index 419b3c30deb0a..ab2fb1a329193 100644 --- a/src/tools/clippy/triagebot.toml +++ b/src/tools/clippy/triagebot.toml @@ -33,5 +33,4 @@ contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIB "@dswij", "@Jarcho", "@blyxyas", - "@Centri3", ] diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 0e1bf0c6c2dce..e85f6319936bf 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -8,6 +8,7 @@ use std::process::Command; use std::str::FromStr; use crate::util::{add_dylib_path, PathBufExt}; +use build_helper::git::GitConfig; use lazycell::AtomicLazyCell; use serde::de::{Deserialize, Deserializer, Error as _}; use std::collections::{HashMap, HashSet}; @@ -67,7 +68,7 @@ string_enum! { MirOpt => "mir-opt", Assembly => "assembly", CoverageMap => "coverage-map", - RunCoverage => "run-coverage", + CoverageRun => "coverage-run", } } @@ -78,7 +79,7 @@ impl Default for Mode { } impl Mode { - pub fn disambiguator(self) -> &'static str { + pub fn aux_dir_disambiguator(self) -> &'static str { // Pretty-printing tests could run concurrently, and if they do, // they need to keep their output segregated. match self { @@ -86,6 +87,15 @@ impl Mode { _ => "", } } + + pub fn output_dir_disambiguator(self) -> &'static str { + // Coverage tests use the same test files for multiple test modes, + // so each mode should have a separate output directory. + match self { + CoverageMap | CoverageRun => self.to_str(), + _ => "", + } + } } string_enum! { @@ -232,6 +242,9 @@ pub struct Config { /// Run ignored tests pub run_ignored: bool, + /// Whether to run tests with `ignore-debug` header + pub with_debug_assertions: bool, + /// Only run tests that match these filters pub filters: Vec, @@ -370,6 +383,10 @@ pub struct Config { pub target_cfgs: AtomicLazyCell, pub nocapture: bool, + + // Needed both to construct build_helper::git::GitConfig + pub git_repository: String, + pub nightly_branch: String, } impl Config { @@ -396,9 +413,6 @@ impl Config { pub fn matches_arch(&self, arch: &str) -> bool { self.target_cfg().arch == arch || - // Shorthand for convenience. The arch for - // asmjs-unknown-emscripten is actually wasm32. - (arch == "asmjs" && self.target.starts_with("asmjs")) || // Matching all the thumb variants as one can be convenient. // (thumbv6m, thumbv7em, thumbv7m, etc.) (arch == "thumb" && self.target.starts_with("thumb")) @@ -441,6 +455,10 @@ impl Config { ]; ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str()) } + + pub fn git_config(&self) -> GitConfig<'_> { + GitConfig { git_repository: &self.git_repository, nightly_branch: &self.nightly_branch } + } } #[derive(Debug, Clone)] @@ -699,6 +717,7 @@ pub fn output_testname_unique( let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str()); let debugger = config.debugger.as_ref().map_or("", |m| m.to_str()); PathBuf::from(&testpaths.file.file_stem().unwrap()) + .with_extra_extension(config.mode.output_dir_disambiguator()) .with_extra_extension(revision.unwrap_or("")) .with_extra_extension(mode) .with_extra_extension(debugger) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 948439d6e79d2..f85f9e674ab12 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -632,7 +632,7 @@ fn iter_header_extra( it(None, directive, 0); } - let comment = if testfile.extension().map(|e| e == "rs") == Some(true) { "//" } else { "#" }; + let comment = if testfile.extension().is_some_and(|e| e == "rs") { "//" } else { "#" }; let mut rdr = BufReader::new(rdr); let mut ln = String::new(); @@ -911,11 +911,11 @@ pub fn make_test_description( let mut should_fail = false; let extra_directives: &[&str] = match config.mode { - // The run-coverage tests are treated as having these extra directives, + // The coverage-run tests are treated as having these extra directives, // without needing to specify them manually in every test file. // (Some of the comments below have been copied over from // `tests/run-make/coverage-reports/Makefile`, which no longer exists.) - Mode::RunCoverage => { + Mode::CoverageRun => { &[ "needs-profiler-support", // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 77c2866b366a6..e2a04b7e55882 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -146,19 +146,13 @@ pub(super) fn parse_cfg_name_directive<'a>( } // `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown - // (in contrast to `wasm32` which also matches non-bare targets like - // asmjs-unknown-emscripten). + // (in contrast to `wasm32` which also matches non-bare targets) condition! { name: "wasm32-bare", condition: config.target == "wasm32-unknown-unknown", message: "when the target is WASM" } - condition! { - name: "asmjs", - condition: config.target.starts_with("asmjs"), - message: "when the architecture is asm.js", - } condition! { name: "thumb", condition: config.target.starts_with("thumb"), @@ -196,8 +190,8 @@ pub(super) fn parse_cfg_name_directive<'a>( } condition! { name: "debug", - condition: cfg!(debug_assertions), - message: "when building with debug assertions", + condition: config.with_debug_assertions, + message: "when running tests with `ignore-debug` header", } condition! { name: config.debugger.as_ref().map(|d| d.to_str()), diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 2fd80b52ceeee..295134c78dcb1 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -126,6 +126,8 @@ impl ConfigBuilder { self.host.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), "--target", self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), + "--git-repository=", + "--nightly-branch=", ]; let mut args: Vec = args.iter().map(ToString::to_string).collect(); @@ -396,8 +398,6 @@ fn ignore_arch() { ("x86_64-unknown-linux-gnu", "x86_64"), ("i686-unknown-linux-gnu", "x86"), ("nvptx64-nvidia-cuda", "nvptx64"), - ("asmjs-unknown-emscripten", "wasm32"), - ("asmjs-unknown-emscripten", "asmjs"), ("thumbv7m-none-eabi", "thumb"), ]; for (target, arch) in archs { @@ -490,9 +490,6 @@ fn wasm_special() { ("wasm32-unknown-unknown", "wasm32", true), ("wasm32-unknown-unknown", "wasm32-bare", true), ("wasm32-unknown-unknown", "wasm64", false), - ("asmjs-unknown-emscripten", "emscripten", true), - ("asmjs-unknown-emscripten", "wasm32", true), - ("asmjs-unknown-emscripten", "wasm32-bare", false), ("wasm32-unknown-emscripten", "emscripten", true), ("wasm32-unknown-emscripten", "wasm32", true), ("wasm32-unknown-emscripten", "wasm32-bare", false), diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 619ff9b322114..5a80b9121f063 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -81,6 +81,7 @@ pub fn parse_config(args: Vec) -> Config { ) .optopt("", "run", "whether to execute run-* tests", "auto | always | never") .optflag("", "ignored", "run tests marked as ignored") + .optflag("", "with-debug-assertions", "whether to run tests with `ignore-debug` header") .optmulti("", "skip", "skip tests matching SUBSTRING. Can be passed multiple times", "SUBSTRING") .optflag("", "exact", "filters match exactly") .optopt( @@ -144,7 +145,9 @@ pub fn parse_config(args: Vec) -> Config { .optflag("h", "help", "show this message") .reqopt("", "channel", "current Rust channel", "CHANNEL") .optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries") - .optopt("", "edition", "default Rust edition", "EDITION"); + .optopt("", "edition", "default Rust edition", "EDITION") + .reqopt("", "git-repository", "name of the git repository", "ORG/REPO") + .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH"); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { @@ -201,6 +204,7 @@ pub fn parse_config(args: Vec) -> Config { let src_base = opt_path(matches, "src-base"); let run_ignored = matches.opt_present("ignored"); + let with_debug_assertions = matches.opt_present("with-debug-assertions"); let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode"); let has_tidy = if mode == Mode::Rustdoc { Command::new("tidy") @@ -236,6 +240,7 @@ pub fn parse_config(args: Vec) -> Config { suite: matches.opt_str("suite").unwrap(), debugger: None, run_ignored, + with_debug_assertions, filters: matches.free.clone(), skip: matches.opt_strs("skip"), filter_exact: matches.opt_present("exact"), @@ -307,6 +312,9 @@ pub fn parse_config(args: Vec) -> Config { target_cfgs: AtomicLazyCell::new(), nocapture: matches.opt_present("nocapture"), + + git_repository: matches.opt_str("git-repository").unwrap(), + nightly_branch: matches.opt_str("nightly-branch").unwrap(), } } @@ -609,9 +617,10 @@ fn modified_tests(config: &Config, dir: &Path) -> Result, String> { return Ok(vec![]); } let files = - get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]); + get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])? + .unwrap_or(vec![]); // Add new test cases to the list, it will be convenient in daily development. - let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]); + let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]); let all_paths = [&files[..], &untracked_files[..]].concat(); let full_paths = { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e74d66a859926..055671afd14d3 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -6,7 +6,7 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; use crate::common::{Config, TestPaths}; -use crate::common::{CoverageMap, Pretty, RunCoverage, RunPassValgrind}; +use crate::common::{CoverageMap, CoverageRun, Pretty, RunPassValgrind}; use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; @@ -20,12 +20,11 @@ use regex::{Captures, Regex}; use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; use std::borrow::Cow; -use std::collections::hash_map::DefaultHasher; use std::collections::{HashMap, HashSet}; use std::env; use std::ffi::{OsStr, OsString}; use std::fs::{self, create_dir_all, File, OpenOptions}; -use std::hash::{Hash, Hasher}; +use std::hash::{DefaultHasher, Hash, Hasher}; use std::io::prelude::*; use std::io::{self, BufReader}; use std::iter; @@ -257,7 +256,7 @@ impl<'test> TestCx<'test> { Assembly => self.run_assembly_test(), JsDocTest => self.run_js_doc_test(), CoverageMap => self.run_coverage_map_test(), - RunCoverage => self.run_coverage_test(), + CoverageRun => self.run_coverage_run_test(), } } @@ -475,14 +474,12 @@ impl<'test> TestCx<'test> { self.fatal("missing --coverage-dump"); }; - let proc_res = self.compile_test_and_save_ir(); + let (proc_res, llvm_ir_path) = self.compile_test_and_save_ir(); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); } drop(proc_res); - let llvm_ir_path = self.output_base_name().with_extension("ll"); - let mut dump_command = Command::new(coverage_dump_path); dump_command.arg(llvm_ir_path); let proc_res = self.run_command_to_procres(&mut dump_command); @@ -510,7 +507,7 @@ impl<'test> TestCx<'test> { } } - fn run_coverage_test(&self) { + fn run_coverage_run_test(&self) { let should_run = self.run_if_enabled(); let proc_res = self.compile_test(should_run, Emit::None); @@ -549,7 +546,7 @@ impl<'test> TestCx<'test> { let mut profraw_paths = vec![profraw_path]; let mut bin_paths = vec![self.make_exe_name()]; - if self.config.suite == "run-coverage-rustdoc" { + if self.config.suite == "coverage-run-rustdoc" { self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths); } @@ -2193,7 +2190,7 @@ impl<'test> TestCx<'test> { || self.is_vxworks_pure_static() || self.config.target.contains("bpf") || !self.config.target_cfg().dynamic_linking - || self.config.mode == RunCoverage + || matches!(self.config.mode, CoverageMap | CoverageRun) { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible @@ -2395,7 +2392,7 @@ impl<'test> TestCx<'test> { } } DebugInfo => { /* debuginfo tests must be unoptimized */ } - CoverageMap | RunCoverage => { + CoverageMap | CoverageRun => { // Coverage mappings and coverage reports are affected by // optimization level, so they ignore the optimize-tests // setting and set an optimization level in their mode's @@ -2478,12 +2475,12 @@ impl<'test> TestCx<'test> { // by `compile-flags`. rustc.arg("-Copt-level=2"); } - RunCoverage => { + CoverageRun => { rustc.arg("-Cinstrument-coverage"); // Coverage reports are sometimes sensitive to optimizations, - // and the current snapshots assume no optimization unless + // and the current snapshots assume `opt-level=2` unless // overridden by `compile-flags`. - rustc.arg("-Copt-level=0"); + rustc.arg("-Copt-level=2"); } RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake | CodegenUnits | JsDocTest | Assembly => { @@ -2720,7 +2717,7 @@ impl<'test> TestCx<'test> { fn aux_output_dir_name(&self) -> PathBuf { self.output_base_dir() .join("auxiliary") - .with_extra_extension(self.config.mode.disambiguator()) + .with_extra_extension(self.config.mode.aux_dir_disambiguator()) } /// Generates a unique name for the test, such as `testname.revision.mode`. @@ -2786,10 +2783,54 @@ impl<'test> TestCx<'test> { proc_res.fatal(None, || on_failure(*self)); } + fn get_output_file(&self, extension: &str) -> TargetLocation { + let thin_lto = self.props.compile_flags.iter().any(|s| s.ends_with("lto=thin")); + if thin_lto { + TargetLocation::ThisDirectory(self.output_base_dir()) + } else { + // This works with both `--emit asm` (as default output name for the assembly) + // and `ptx-linker` because the latter can write output at requested location. + let output_path = self.output_base_name().with_extension(extension); + let output_file = TargetLocation::ThisFile(output_path.clone()); + output_file + } + } + + fn get_filecheck_file(&self, extension: &str) -> PathBuf { + let thin_lto = self.props.compile_flags.iter().any(|s| s.ends_with("lto=thin")); + if thin_lto { + let name = self.testpaths.file.file_stem().unwrap().to_str().unwrap(); + let canonical_name = name.replace('-', "_"); + let mut output_file = None; + for entry in self.output_base_dir().read_dir().unwrap() { + if let Ok(entry) = entry { + let entry_path = entry.path(); + let entry_file = entry_path.file_name().unwrap().to_str().unwrap(); + if entry_file.starts_with(&format!("{}.{}", name, canonical_name)) + && entry_file.ends_with(extension) + { + assert!( + output_file.is_none(), + "thinlto doesn't support multiple cgu tests" + ); + output_file = Some(entry_file.to_string()); + } + } + } + if let Some(output_file) = output_file { + self.output_base_dir().join(output_file) + } else { + self.output_base_name().with_extension(extension) + } + } else { + self.output_base_name().with_extension(extension) + } + } + // codegen tests (using FileCheck) - fn compile_test_and_save_ir(&self) -> ProcRes { - let output_file = TargetLocation::ThisDirectory(self.output_base_dir()); + fn compile_test_and_save_ir(&self) -> (ProcRes, PathBuf) { + let output_file = self.get_output_file("ll"); let input_file = &self.testpaths.file; let rustc = self.make_compile_args( input_file, @@ -2800,15 +2841,13 @@ impl<'test> TestCx<'test> { Vec::new(), ); - self.compose_and_run_compiler(rustc, None) + let proc_res = self.compose_and_run_compiler(rustc, None); + let output_path = self.get_filecheck_file("ll"); + (proc_res, output_path) } fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) { - // This works with both `--emit asm` (as default output name for the assembly) - // and `ptx-linker` because the latter can write output at requested location. - let output_path = self.output_base_name().with_extension("s"); - - let output_file = TargetLocation::ThisFile(output_path.clone()); + let output_file = self.get_output_file("s"); let input_file = &self.testpaths.file; let mut emit = Emit::None; @@ -2838,7 +2877,9 @@ impl<'test> TestCx<'test> { Vec::new(), ); - (self.compose_and_run_compiler(rustc, None), output_path) + let proc_res = self.compose_and_run_compiler(rustc, None); + let output_path = self.get_filecheck_file("s"); + (proc_res, output_path) } fn verify_with_filecheck(&self, output: &Path) -> ProcRes { @@ -2871,7 +2912,7 @@ impl<'test> TestCx<'test> { self.fatal("missing --llvm-filecheck"); } - let proc_res = self.compile_test_and_save_ir(); + let (proc_res, output_path) = self.compile_test_and_save_ir(); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); } @@ -2879,8 +2920,6 @@ impl<'test> TestCx<'test> { if let Some(PassMode::Build) = self.pass_mode() { return; } - - let output_path = self.output_base_name().with_extension("ll"); let proc_res = self.verify_with_filecheck(&output_path); if !proc_res.status.success() { self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res); @@ -3702,9 +3741,7 @@ impl<'test> TestCx<'test> { let stderr_bits = format!("{}bit.stderr", self.config.get_pointer_width()); let (stderr_kind, stdout_kind) = match output_kind { TestOutput::Compile => ( - { - if self.props.stderr_per_bitwidth { &stderr_bits } else { UI_STDERR } - }, + { if self.props.stderr_per_bitwidth { &stderr_bits } else { UI_STDERR } }, UI_STDOUT, ), TestOutput::Run => (UI_RUN_STDERR, UI_RUN_STDOUT), @@ -3962,7 +3999,7 @@ impl<'test> TestCx<'test> { // And finally, compile the fixed code and make sure it both // succeeds and has no diagnostics. let rustc = self.make_compile_args( - &self.testpaths.file.with_extension(UI_FIXED), + &self.expected_output_path(UI_FIXED), TargetLocation::ThisFile(self.make_exe_name()), emit_metadata, AllowUnused::No, @@ -4251,15 +4288,18 @@ impl<'test> TestCx<'test> { let mut seen_allocs = indexmap::IndexSet::new(); // The alloc-id appears in pretty-printed allocations. - let re = Regex::new(r"╾─*a(lloc)?([0-9]+)(\+0x[0-9]+)?─*╼").unwrap(); + let re = + Regex::new(r"╾─*a(lloc)?([0-9]+)(\+0x[0-9]+)?()?( \([0-9]+ ptr bytes\))?─*╼") + .unwrap(); normalized = re .replace_all(&normalized, |caps: &Captures<'_>| { // Renumber the captured index. let index = caps.get(2).unwrap().as_str().to_string(); let (index, _) = seen_allocs.insert_full(index); let offset = caps.get(3).map_or("", |c| c.as_str()); + let imm = caps.get(4).map_or("", |c| c.as_str()); // Do not bother keeping it pretty, just make it deterministic. - format!("╾ALLOC{index}{offset}╼") + format!("╾ALLOC{index}{offset}{imm}╼") }) .into_owned(); diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 62a58576da555..3a23ff7fe6a72 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -1,6 +1,7 @@ #![feature(rustc_private)] extern crate rustc_driver; +extern crate rustc_log; extern crate rustc_session; use std::env; @@ -173,7 +174,7 @@ fn parse_args() -> (OutputFormat, PathBuf) { fn main() { let handler = rustc_session::EarlyErrorHandler::new(rustc_session::config::ErrorOutputType::default()); - rustc_driver::init_env_logger(&handler, "RUST_LOG"); + rustc_driver::init_logger(&handler, rustc_log::LoggerConfig::from_env("RUST_LOG")); let (format, dst) = parse_args(); let result = main_with_result(format, &dst); if let Err(e) = result { diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml index 9821677a1226e..d8a7a06efc6d4 100644 --- a/src/tools/generate-windows-sys/Cargo.toml +++ b/src/tools/generate-windows-sys/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies.windows-bindgen] -version = "0.51.1" +version = "0.52.0" diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index ccabe6483d7a4..6326a9b1e79c3 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -jsonpath_lib = "0.2" +jsonpath_lib = "0.3" getopts = "0.2" regex = "1.4" shlex = "1.0" diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 67b48a3742da0..dec85e9232fb8 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -35,10 +35,6 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set the tag GC interval to 1 on linux - if: runner.os == 'Linux' - run: echo "MIRIFLAGS=-Zmiri-tag-gc=1" >> $GITHUB_ENV - # Cache the global cargo directory, but NOT the local `target` directory which # we cannot reuse anyway when the nightly changes (and it grows quite large # over time). diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index f90fd1f7fc54e..3dee742fa0dea 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -411,10 +411,10 @@ to Miri failing to detect cases of undefined behavior in a program. without an explicit value), `none` means it never recurses, `scalar` means it only recurses for types where we would also emit `noalias` annotations in the generated LLVM IR (types passed as individual scalars or pairs of scalars). Setting this to `none` is **unsound**. -* `-Zmiri-tag-gc=` configures how often the pointer tag garbage collector runs. The default - is to search for and remove unreachable tags once every `10000` basic blocks. Setting this to - `0` disables the garbage collector, which causes some programs to have explosive memory usage - and/or super-linear runtime. +* `-Zmiri-provenance-gc=` configures how often the pointer provenance garbage collector runs. + The default is to search for and remove unreachable provenance once every `10000` basic blocks. Setting + this to `0` disables the garbage collector, which causes some programs to have explosive memory + usage and/or super-linear runtime. * `-Zmiri-track-alloc-id=,,...` shows a backtrace when the given allocations are being allocated or freed. This helps in debugging memory leaks and use after free bugs. Specifying this argument multiple times does not overwrite the previous @@ -589,6 +589,7 @@ Definite bugs found: * [`regex` incorrectly handling unaligned `Vec` buffers](https://www.reddit.com/r/rust/comments/vq3mmu/comment/ienc7t0?context=3) * [Incorrect use of `compare_exchange_weak` in `once_cell`](https://github.com/matklad/once_cell/issues/186) * [Dropping with unaligned pointers in `vec::IntoIter`](https://github.com/rust-lang/rust/pull/106084) +* [Deallocating with the wrong layout in new specializations for in-place `Iterator::collect`](https://github.com/rust-lang/rust/pull/118460) Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment): diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index d655df6d994d4..a7412f90c8505 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -501,6 +501,14 @@ pub fn phase_runner(mut binary_args: impl Iterator, phase: Runner // Set missing env vars. We prefer build-time env vars over run-time ones; see // for the kind of issue that fixes. for (name, val) in info.env { + // `CARGO_MAKEFLAGS` contains information about how to reach the + // jobserver, but by the time the program is being run, that jobserver + // no longer exists. Hence we shouldn't forward this. + // FIXME: Miri builds the final crate without a jobserver. + // This may be fixed with github.com/rust-lang/cargo/issues/12597. + if name == "CARGO_MAKEFLAGS" { + continue; + } if let Some(old_val) = env::var_os(&name) { if old_val == val { // This one did not actually change, no need to re-set it. diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index d921741d5dec2..8ae5b8c3e82cc 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -2,6 +2,7 @@ use std::env; use std::ffi::OsStr; +use std::fmt::Write; use std::path::PathBuf; use std::process::{self, Command}; @@ -140,12 +141,20 @@ pub fn setup( // Do the build. if print_sysroot { // Be silent. - } else if only_setup { - // We want to be explicit. - eprintln!("Preparing a sysroot for Miri (target: {target})..."); } else { - // We want to be quiet, but still let the user know that something is happening. - eprint!("Preparing a sysroot for Miri (target: {target})... "); + let mut msg = String::new(); + write!(msg, "Preparing a sysroot for Miri (target: {target})").unwrap(); + if verbose > 0 { + write!(msg, " in {}", sysroot_dir.display()).unwrap(); + } + write!(msg, "...").unwrap(); + if only_setup { + // We want to be explicit. + eprintln!("{msg}"); + } else { + // We want to be quiet, but still let the user know that something is happening. + eprint!("{msg} "); + } } SysrootBuilder::new(&sysroot_dir, target) .build_mode(BuildMode::Check) diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 5078e9eaab382..6bcc68ebf7ccd 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -30,16 +30,23 @@ endgroup # Test function run_tests { - if [ -n "${MIRI_TEST_TARGET+exists}" ]; then + if [ -n "${MIRI_TEST_TARGET:-}" ]; then begingroup "Testing foreign architecture $MIRI_TEST_TARGET" else begingroup "Testing host architecture" fi ## ui test suite - ./miri test - if [ -z "${MIRI_TEST_TARGET+exists}" ]; then - # Host-only tests: running these on all targets is unlikely to catch more problems and would + # On the host and on Linux, also stress-test the GC. + if [ -z "${MIRI_TEST_TARGET:-}" ] || [ "$HOST_TARGET" = x86_64-unknown-linux-gnu ]; then + MIRIFLAGS="${MIRIFLAGS:-} -Zmiri-provenance-gc=1" ./miri test + else + ./miri test + fi + + # Host-only tests + if [ -z "${MIRI_TEST_TARGET:-}" ]; then + # Running these on all targets is unlikely to catch more problems and would # cost a lot of CI time. # Tests with optimizations (`-O` is what cargo passes, but crank MIR optimizations up all the @@ -85,10 +92,11 @@ function run_tests { } function run_tests_minimal { - if [ -n "${MIRI_TEST_TARGET+exists}" ]; then + if [ -n "${MIRI_TEST_TARGET:-}" ]; then begingroup "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@" else - begingroup "Testing MINIMAL host architecture: only testing $@" + echo "run_tests_minimal requires MIRI_TEST_TARGET to be set" + exit 1 fi ./miri test -- "$@" @@ -99,16 +107,22 @@ function run_tests_minimal { endgroup } -# host +## Main Testing Logic ## + +# Host target. run_tests +# Extra targets. +# In particular, fully cover all tier 1 targets. case $HOST_TARGET in x86_64-unknown-linux-gnu) MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests - MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic env/var + # Some targets are only partially supported. + MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align + MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index c24035ae0862d..e4789c696b390 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -286,7 +286,7 @@ impl Command { "This will pull a copy of the rust-lang/rust history into this Miri checkout, growing it by about 1GB." ); print!( - "To avoid that, abort now and set the `--rustc-git` flag to an existing rustc checkout. Proceed? [y/N] " + "To avoid that, abort now and set the `RUSTC_GIT` environment variable to an existing rustc checkout. Proceed? [y/N] " ); std::io::stdout().flush()?; let mut answer = String::new(); diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 2beb3bfef9e5f..c60249f35e10d 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3aaa0f57b7b877ef58532a8de075d1e5a79142bf +317d14a56cb8c748bf0e2f2afff89c2249ab4423 diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index cd628444fed93..504b6bd140ec4 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -9,11 +9,12 @@ extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_hir; extern crate rustc_interface; +extern crate rustc_log; extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; -use std::env; +use std::env::{self, VarError}; use std::num::NonZeroU64; use std::path::PathBuf; use std::str::FromStr; @@ -143,7 +144,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { // Otherwise it may cause unexpected behaviours and ICEs // (https://github.com/rust-lang/rust/issues/86261). let is_reachable_non_generic = matches!( - tcx.hir().get(tcx.hir().local_def_id_to_hir_id(local_def_id)), + tcx.hir().get(tcx.local_def_id_to_hir_id(local_def_id)), Node::Item(&hir::Item { kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn(..), .. @@ -164,6 +165,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { level: SymbolExportLevel::C, kind: SymbolExportKind::Text, used: false, + used_compiler: false, }, )) }), @@ -183,45 +185,54 @@ macro_rules! show_error { ($($tt:tt)*) => { show_error(&format_args!($($tt)*)) }; } -fn init_early_loggers(handler: &EarlyErrorHandler) { - // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to - // initialize them both, and we always initialize `miri`'s first. - let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE"); - env_logger::init_from_env(env); - // Enable verbose entry/exit logging by default if MIRI_LOG is set. - if env::var_os("MIRI_LOG").is_some() && env::var_os("RUSTC_LOG_ENTRY_EXIT").is_none() { - env::set_var("RUSTC_LOG_ENTRY_EXIT", "1"); - } - // We only initialize `rustc` if the env var is set (so the user asked for it). - // If it is not set, we avoid initializing now so that we can initialize - // later with our custom settings, and *not* log anything for what happens before - // `miri` gets started. - if env::var_os("RUSTC_LOG").is_some() { - rustc_driver::init_rustc_env_logger(handler); - } -} +fn rustc_logger_config() -> rustc_log::LoggerConfig { + // Start with the usual env vars. + let mut cfg = rustc_log::LoggerConfig::from_env("RUSTC_LOG"); -fn init_late_loggers(handler: &EarlyErrorHandler, tcx: TyCtxt<'_>) { - // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG` - // env var if it is not set, control it based on `MIRI_LOG`. - // (FIXME: use `var_os`, but then we need to manually concatenate instead of `format!`.) + // Overwrite if MIRI_LOG is set. if let Ok(var) = env::var("MIRI_LOG") { - if env::var_os("RUSTC_LOG").is_none() { + // MIRI_LOG serves as default for RUSTC_LOG, if that is not set. + if matches!(cfg.filter, Err(VarError::NotPresent)) { // We try to be a bit clever here: if `MIRI_LOG` is just a single level // used for everything, we only apply it to the parts of rustc that are // CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`. // This way, if you set `MIRI_LOG=trace`, you get only the right parts of // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_const_eval::interpret=debug`. if log::Level::from_str(&var).is_ok() { - env::set_var( - "RUSTC_LOG", - format!("rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var}"), - ); + cfg.filter = Ok(format!( + "rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var}" + )); } else { - env::set_var("RUSTC_LOG", &var); + cfg.filter = Ok(var); } - rustc_driver::init_rustc_env_logger(handler); } + // Enable verbose entry/exit logging by default if MIRI_LOG is set. + if matches!(cfg.verbose_entry_exit, Err(VarError::NotPresent)) { + cfg.verbose_entry_exit = Ok(format!("1")); + } + } + + cfg +} + +fn init_early_loggers(handler: &EarlyErrorHandler) { + // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to + // initialize them both, and we always initialize `miri`'s first. + let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE"); + env_logger::init_from_env(env); + // Now for rustc. We only initialize `rustc` if the env var is set (so the user asked for it). + // If it is not set, we avoid initializing now so that we can initialize later with our custom + // settings, and *not* log anything for what happens before `miri` gets started. + if env::var_os("RUSTC_LOG").is_some() { + rustc_driver::init_logger(handler, rustc_logger_config()); + } +} + +fn init_late_loggers(handler: &EarlyErrorHandler, tcx: TyCtxt<'_>) { + // If `RUSTC_LOG` is not set, then `init_early_loggers` did not call + // `rustc_driver::init_logger`, so we have to do this now. + if env::var_os("RUSTC_LOG").is_none() { + rustc_driver::init_logger(handler, rustc_logger_config()); } // If `MIRI_BACKTRACE` is set and `RUSTC_CTFE_BACKTRACE` is not, set `RUSTC_CTFE_BACKTRACE`. @@ -521,10 +532,10 @@ fn main() { Err(err) => show_error!("-Zmiri-report-progress requires a `u32`: {}", err), }; miri_config.report_progress = Some(interval); - } else if let Some(param) = arg.strip_prefix("-Zmiri-tag-gc=") { + } else if let Some(param) = arg.strip_prefix("-Zmiri-provenance-gc=") { let interval = match param.parse::() { Ok(i) => i, - Err(err) => show_error!("-Zmiri-tag-gc requires a `u32`: {}", err), + Err(err) => show_error!("-Zmiri-provenance-gc requires a `u32`: {}", err), }; miri_config.gc_interval = interval; } else if let Some(param) = arg.strip_prefix("-Zmiri-measureme=") { diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index a95571572d684..8fae526922943 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -59,7 +59,7 @@ impl fmt::Debug for BorTag { #[derive(Debug)] pub struct FrameState { /// The ID of the call this frame corresponds to. - pub call_id: CallId, + call_id: CallId, /// If this frame is protecting any tags, they are listed here. We use this list to do /// incremental updates of the global list of protected tags stored in the @@ -72,11 +72,11 @@ pub struct FrameState { /// /// This will contain one tag per reference passed to the function, so /// a size of 2 is enough for the vast majority of functions. - pub protected_tags: SmallVec<[(AllocId, BorTag); 2]>, + protected_tags: SmallVec<[(AllocId, BorTag); 2]>, } -impl VisitTags for FrameState { - fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for FrameState { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { // `protected_tags` are already recorded by `GlobalStateInner`. } } @@ -85,35 +85,35 @@ impl VisitTags for FrameState { #[derive(Debug)] pub struct GlobalStateInner { /// Borrow tracker method currently in use. - pub borrow_tracker_method: BorrowTrackerMethod, + borrow_tracker_method: BorrowTrackerMethod, /// Next unused pointer ID (tag). - pub next_ptr_tag: BorTag, + next_ptr_tag: BorTag, /// Table storing the "base" tag for each allocation. /// The base tag is the one used for the initial pointer. /// We need this in a separate table to handle cyclic statics. - pub base_ptr_tags: FxHashMap, + base_ptr_tags: FxHashMap, /// Next unused call ID (for protectors). - pub next_call_id: CallId, + next_call_id: CallId, /// All currently protected tags. /// An item is protected if its tag is in this set, *and* it has the "protected" bit set. /// We add tags to this when they are created with a protector in `reborrow`, and /// we remove tags from this when the call which is protecting them returns, in /// `GlobalStateInner::end_call`. See `Stack::item_popped` for more details. - pub protected_tags: FxHashMap, + protected_tags: FxHashMap, /// The pointer ids to trace - pub tracked_pointer_tags: FxHashSet, + tracked_pointer_tags: FxHashSet, /// The call ids to trace - pub tracked_call_ids: FxHashSet, + tracked_call_ids: FxHashSet, /// Whether to recurse into datatypes when searching for pointers to retag. - pub retag_fields: RetagFields, + retag_fields: RetagFields, /// Whether `core::ptr::Unique` gets special (`Box`-like) handling. - pub unique_is_unique: bool, + unique_is_unique: bool, } -impl VisitTags for GlobalStateInner { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for GlobalStateInner { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { for &tag in self.protected_tags.keys() { - visit(tag); + visit(None, Some(tag)); } // The only other candidate is base_ptr_tags, and that does not need visiting since we don't ever // GC the bottommost/root tag. @@ -194,7 +194,7 @@ impl GlobalStateInner { } /// Generates a new pointer tag. Remember to also check track_pointer_tags and log its creation! - pub fn new_ptr(&mut self) -> BorTag { + fn new_ptr(&mut self) -> BorTag { let id = self.next_ptr_tag; self.next_ptr_tag = id.succ().unwrap(); id @@ -210,7 +210,7 @@ impl GlobalStateInner { FrameState { call_id, protected_tags: SmallVec::new() } } - pub fn end_call(&mut self, frame: &machine::FrameExtra<'_>) { + fn end_call(&mut self, frame: &machine::FrameExtra<'_>) { for (_, tag) in &frame .borrow_tracker .as_ref() @@ -236,6 +236,10 @@ impl GlobalStateInner { tag }) } + + pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_, '_>) { + self.base_ptr_tags.retain(|id, _| allocs.is_live(*id)); + } } /// Which borrow tracking method to use @@ -355,6 +359,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { BorrowTrackerMethod::TreeBorrows => this.print_tree(alloc_id, show_unnamed), } } + + fn on_stack_pop( + &self, + frame: &Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>, + ) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); + let borrow_tracker = this.machine.borrow_tracker.as_ref().unwrap(); + // The body of this loop needs `borrow_tracker` immutably + // so we can't move this code inside the following `end_call`. + for (alloc_id, tag) in &frame + .extra + .borrow_tracker + .as_ref() + .expect("we should have borrow tracking data") + .protected_tags + { + // Just because the tag is protected doesn't guarantee that + // the allocation still exists (weak protectors allow deallocations) + // so we must check that the allocation exists. + // If it does exist, then we have the guarantee that the + // pointer is readable, and the implicit read access inserted + // will never cause UB on the pointer itself. + let (_, _, kind) = this.get_alloc_info(*alloc_id); + if matches!(kind, AllocKind::LiveData) { + let alloc_extra = this.get_alloc_extra(*alloc_id).unwrap(); + let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap(); + alloc_borrow_tracker.release_protector(&this.machine, borrow_tracker, *tag)?; + } + } + borrow_tracker.borrow_mut().end_call(&frame.extra); + Ok(()) + } } /// Extra per-allocation data for borrow tracking @@ -471,11 +507,11 @@ impl AllocState { } } -impl VisitTags for AllocState { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for AllocState { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { match self { - AllocState::StackedBorrows(sb) => sb.visit_tags(visit), - AllocState::TreeBorrows(tb) => tb.visit_tags(visit), + AllocState::StackedBorrows(sb) => sb.visit_provenance(visit), + AllocState::TreeBorrows(tb) => tb.visit_provenance(visit), } } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index a74c69d52f236..1df2b1b8391b0 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -37,8 +37,6 @@ pub struct Stacks { history: AllocHistory, /// The set of tags that have been exposed inside this allocation. exposed_tags: FxHashSet, - /// Whether this memory has been modified since the last time the tag GC ran - modified_since_last_gc: bool, } /// Indicates which permissions to grant to the retagged pointer. @@ -450,22 +448,17 @@ impl<'tcx> Stack { /// Integration with the BorTag garbage collector impl Stacks { pub fn remove_unreachable_tags(&mut self, live_tags: &FxHashSet) { - if self.modified_since_last_gc { - for (_stack_range, stack) in self.stacks.iter_mut_all() { - if stack.len() > 64 { - stack.retain(live_tags); - } - } - self.history.retain(live_tags); - self.modified_since_last_gc = false; + for (_stack_range, stack) in self.stacks.iter_mut_all() { + stack.retain(live_tags); } + self.history.retain(live_tags); } } -impl VisitTags for Stacks { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for Stacks { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { for tag in self.exposed_tags.iter().copied() { - visit(tag); + visit(None, Some(tag)); } } } @@ -488,7 +481,6 @@ impl<'tcx> Stacks { stacks: RangeMap::new(size, stack), history: AllocHistory::new(id, item, machine), exposed_tags: FxHashSet::default(), - modified_since_last_gc: false, } } @@ -503,7 +495,6 @@ impl<'tcx> Stacks { &mut FxHashSet, ) -> InterpResult<'tcx>, ) -> InterpResult<'tcx> { - self.modified_since_last_gc = true; for (stack_range, stack) in self.stacks.iter_mut(range.start, range.size) { let mut dcx = dcx_builder.build(&mut self.history, Size::from_bytes(stack_range.start)); f(stack, &mut dcx, &mut self.exposed_tags)?; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index b3001b5b88cdc..43e6616e34a71 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -200,7 +200,7 @@ impl<'tcx> Tree { /// Climb the tree to get the tag of a distant ancestor. /// Allows operations on tags that are unreachable by the program /// but still exist in the tree. Not guaranteed to perform consistently - /// if `tag-gc=1`. + /// if `provenance-gc=1`. fn nth_parent(&self, tag: BorTag, nth_parent: u8) -> Option { let mut idx = self.tag_mapping.get(&tag).unwrap(); for _ in 0..nth_parent { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index 4232cd396c95e..6801397b2cec6 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -742,11 +742,11 @@ impl Tree { } } -impl VisitTags for Tree { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for Tree { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { // To ensure that the root never gets removed, we visit it // (the `root` node of `Tree` is not an `Option<_>`) - visit(self.nodes.get(self.root).unwrap().tag) + visit(None, Some(self.nodes.get(self.root).unwrap().tag)) } } diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 5d109a7d55cef..80d0402fc8758 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -790,9 +790,9 @@ pub struct VClockAlloc { alloc_ranges: RefCell>, } -impl VisitTags for VClockAlloc { - fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) { - // No tags here. +impl VisitProvenance for VClockAlloc { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { + // No tags or allocIds here. } } @@ -1404,8 +1404,8 @@ pub struct GlobalState { pub track_outdated_loads: bool, } -impl VisitTags for GlobalState { - fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for GlobalState { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { // We don't have any tags. } } diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index 71582c75eae57..9a848d50341a4 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -45,10 +45,10 @@ pub(super) struct InitOnce<'mir, 'tcx> { data_race: VClock, } -impl<'mir, 'tcx> VisitTags for InitOnce<'mir, 'tcx> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl<'mir, 'tcx> VisitProvenance for InitOnce<'mir, 'tcx> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { for waiter in self.waiters.iter() { - waiter.callback.visit_tags(visit); + waiter.callback.visit_provenance(visit); } } } diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 62f6d57ef36e1..b288b69e0cef9 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -181,10 +181,10 @@ pub(crate) struct SynchronizationState<'mir, 'tcx> { pub(super) init_onces: IndexVec>, } -impl<'mir, 'tcx> VisitTags for SynchronizationState<'mir, 'tcx> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl<'mir, 'tcx> VisitProvenance for SynchronizationState<'mir, 'tcx> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { for init_once in self.init_onces.iter() { - init_once.visit_tags(visit); + init_once.visit_provenance(visit); } } } diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 9041683fbc46b..754cfa4d2a827 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -33,8 +33,17 @@ enum SchedulingAction { Sleep(Duration), } +/// What to do with TLS allocations from terminated threads +pub enum TlsAllocAction { + /// Deallocate backing memory of thread-local statics as usual + Deallocate, + /// Skip deallocating backing memory of thread-local statics and consider all memory reachable + /// from them as "allowed to leak" (like global `static`s). + Leak, +} + /// Trait for callbacks that can be executed when some event happens, such as after a timeout. -pub trait MachineCallback<'mir, 'tcx>: VisitTags { +pub trait MachineCallback<'mir, 'tcx>: VisitProvenance { fn call(&self, ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx>; } @@ -219,8 +228,8 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> { } } -impl VisitTags for Thread<'_, '_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for Thread<'_, '_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let Thread { panic_payloads: panic_payload, last_error, @@ -233,17 +242,17 @@ impl VisitTags for Thread<'_, '_> { } = self; for payload in panic_payload { - payload.visit_tags(visit); + payload.visit_provenance(visit); } - last_error.visit_tags(visit); + last_error.visit_provenance(visit); for frame in stack { - frame.visit_tags(visit) + frame.visit_provenance(visit) } } } -impl VisitTags for Frame<'_, '_, Provenance, FrameExtra<'_>> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for Frame<'_, '_, Provenance, FrameExtra<'_>> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let Frame { return_place, locals, @@ -257,22 +266,22 @@ impl VisitTags for Frame<'_, '_, Provenance, FrameExtra<'_>> { } = self; // Return place. - return_place.visit_tags(visit); + return_place.visit_provenance(visit); // Locals. for local in locals.iter() { match local.as_mplace_or_imm() { None => {} Some(Either::Left((ptr, meta))) => { - ptr.visit_tags(visit); - meta.visit_tags(visit); + ptr.visit_provenance(visit); + meta.visit_provenance(visit); } Some(Either::Right(imm)) => { - imm.visit_tags(visit); + imm.visit_provenance(visit); } } } - extra.visit_tags(visit); + extra.visit_provenance(visit); } } @@ -332,8 +341,8 @@ pub struct ThreadManager<'mir, 'tcx> { timeout_callbacks: FxHashMap>, } -impl VisitTags for ThreadManager<'_, '_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for ThreadManager<'_, '_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let ThreadManager { threads, thread_local_alloc_ids, @@ -344,15 +353,15 @@ impl VisitTags for ThreadManager<'_, '_> { } = self; for thread in threads { - thread.visit_tags(visit); + thread.visit_provenance(visit); } for ptr in thread_local_alloc_ids.borrow().values() { - ptr.visit_tags(visit); + ptr.visit_provenance(visit); } for callback in timeout_callbacks.values() { - callback.callback.visit_tags(visit); + callback.callback.visit_provenance(visit); } - sync.visit_tags(visit); + sync.visit_provenance(visit); } } @@ -1051,7 +1060,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // See if this thread can do something else. match this.run_on_stack_empty()? { Poll::Pending => {} // keep going - Poll::Ready(()) => this.terminate_active_thread()?, + Poll::Ready(()) => + this.terminate_active_thread(TlsAllocAction::Deallocate)?, } } } @@ -1066,21 +1076,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Handles thread termination of the active thread: wakes up threads joining on this one, - /// and deallocated thread-local statics. + /// and deals with the thread's thread-local statics according to `tls_alloc_action`. /// /// This is called by the eval loop when a thread's on_stack_empty returns `Ready`. #[inline] - fn terminate_active_thread(&mut self) -> InterpResult<'tcx> { + fn terminate_active_thread(&mut self, tls_alloc_action: TlsAllocAction) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let thread = this.active_thread_mut(); assert!(thread.stack.is_empty(), "only threads with an empty stack can be terminated"); thread.state = ThreadState::Terminated; let current_span = this.machine.current_span(); - for ptr in - this.machine.threads.thread_terminated(this.machine.data_race.as_mut(), current_span) - { - this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?; + let thread_local_allocations = + this.machine.threads.thread_terminated(this.machine.data_race.as_mut(), current_span); + for ptr in thread_local_allocations { + match tls_alloc_action { + TlsAllocAction::Deallocate => + this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?, + TlsAllocAction::Leak => + if let Some(alloc) = ptr.provenance.get_alloc_id() { + trace!("Thread-local static leaked and stored as static root: {:?}", alloc); + this.machine.static_roots.push(alloc); + }, + } } Ok(()) } diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs index 2ff344bb1a35f..39e89ce7faa7a 100644 --- a/src/tools/miri/src/concurrency/weak_memory.rs +++ b/src/tools/miri/src/concurrency/weak_memory.rs @@ -108,15 +108,15 @@ pub struct StoreBufferAlloc { store_buffers: RefCell>, } -impl VisitTags for StoreBufferAlloc { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for StoreBufferAlloc { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let Self { store_buffers } = self; for val in store_buffers .borrow() .iter() .flat_map(|buf| buf.buffer.iter().map(|element| &element.val)) { - val.visit_tags(visit); + val.visit_provenance(visit); } } } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index fe445c6dcd962..ef394b163103b 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -44,7 +44,7 @@ pub enum TerminationInfo { }, DataRace { involves_non_atomic: bool, - ptr: Pointer, + ptr: Pointer, op1: RacingOp, op2: RacingOp, extra: Option<&'static str>, @@ -270,7 +270,8 @@ pub fn report_error<'tcx, 'mir>( DataRace { op1, extra, .. } => { let mut helps = vec![(Some(op1.span), format!("and (1) occurred earlier here"))]; if let Some(extra) = extra { - helps.push((None, format!("{extra}"))) + helps.push((None, format!("{extra}"))); + helps.push((None, format!("see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model"))); } helps.push((None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"))); helps.push((None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"))); @@ -383,7 +384,7 @@ pub fn report_error<'tcx, 'mir>( // Include a note like `std` does when we omit frames from a backtrace if was_pruned { - ecx.tcx.sess.diagnostic().note_without_error( + ecx.tcx.sess.diagnostic().note( "some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace", ); } @@ -430,7 +431,7 @@ pub fn report_leaks<'mir, 'tcx>( ); } if any_pruned { - ecx.tcx.sess.diagnostic().note_without_error( + ecx.tcx.sess.diagnostic().note( "some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace", ); } @@ -455,7 +456,7 @@ pub fn report_msg<'tcx>( let mut err = match diag_level { DiagLevel::Error => sess.struct_span_err(span, title).forget_guarantee(), DiagLevel::Warning => sess.struct_span_warn(span, title), - DiagLevel::Note => sess.diagnostic().span_note_diag(span, title), + DiagLevel::Note => sess.diagnostic().struct_span_note(span, title), }; // Show main message. diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 5b785c0143e4d..875a78974fafb 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -11,6 +11,7 @@ use log::info; use rustc_middle::ty::Ty; use crate::borrow_tracker::RetagFields; +use crate::concurrency::thread::TlsAllocAction; use crate::diagnostics::report_leaks; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::Namespace; @@ -244,9 +245,9 @@ impl MainThreadState { // Figure out exit code. let ret_place = this.machine.main_fn_ret_place.clone().unwrap(); let exit_code = this.read_target_isize(&ret_place)?; - // Need to call this ourselves since we are not going to return to the scheduler - // loop, and we want the main thread TLS to not show up as memory leaks. - this.terminate_active_thread()?; + // Deal with our thread-local memory. We do *not* want to actually free it, instead we consider TLS + // to be like a global `static`, so that all memory reached by it is considered to "not leak". + this.terminate_active_thread(TlsAllocAction::Leak)?; // Stop interpreter loop. throw_machine_stop!(TerminationInfo::Exit { code: exit_code, leak_check: true }); } @@ -463,7 +464,7 @@ pub fn eval_entry<'tcx>( // Check for thread leaks. if !ecx.have_all_terminated() { tcx.sess.err("the main thread terminated without waiting for all remaining threads"); - tcx.sess.note_without_error("pass `-Zmiri-ignore-leaks` to disable this check"); + tcx.sess.note("pass `-Zmiri-ignore-leaks` to disable this check"); return None; } // Check for memory leaks. @@ -474,7 +475,7 @@ pub fn eval_entry<'tcx>( let leak_message = "the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check"; if ecx.machine.collect_leak_backtraces { // If we are collecting leak backtraces, each leak is a distinct error diagnostic. - tcx.sess.note_without_error(leak_message); + tcx.sess.note(leak_message); } else { // If we do not have backtraces, we just report an error without any span. tcx.sess.err(leak_message); diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 965cd534d1e5c..57dc3b4734c46 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -5,17 +5,18 @@ use std::time::Duration; use log::trace; +use rustc_apfloat::ieee::{Double, Single}; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::ty::{ self, - layout::{IntegerExt as _, LayoutOf, TyAndLayout}, - IntTy, Ty, TyCtxt, UintTy, + layout::{LayoutOf, TyAndLayout}, + FloatTy, IntTy, Ty, TyCtxt, UintTy, }; use rustc_span::{def_id::CrateNum, sym, Span, Symbol}; -use rustc_target::abi::{Align, FieldIdx, FieldsShape, Integer, Size, Variants}; +use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants}; use rustc_target::spec::abi::Abi; use rand::RngCore; @@ -565,10 +566,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// is part of the UNIX family. It panics showing a message with the `name` of the foreign function /// if this is not the case. fn assert_target_os_is_unix(&self, name: &str) { - assert!( - target_os_is_unix(self.eval_context_ref().tcx.sess.target.os.as_ref()), - "`{name}` is only available for supported UNIX family targets", - ); + assert!(self.target_os_is_unix(), "`{name}` is only available for unix targets",); + } + + fn target_os_is_unix(&self) -> bool { + self.eval_context_ref().tcx.sess.target.families.iter().any(|f| f == "unix") } /// Get last error variable as a place, lazily allocating thread-local storage for it if @@ -985,65 +987,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - /// Converts `f` to integer type `dest_ty` after rounding with mode `round`. + /// Converts `src` from floating point to integer type `dest_ty` + /// after rounding with mode `round`. /// Returns `None` if `f` is NaN or out of range. - fn float_to_int_checked( + fn float_to_int_checked( &self, - f: F, + src: &ImmTy<'tcx, Provenance>, cast_to: TyAndLayout<'tcx>, round: rustc_apfloat::Round, - ) -> Option> - where - F: rustc_apfloat::Float + Into>, - { + ) -> InterpResult<'tcx, Option>> { let this = self.eval_context_ref(); - let val = match cast_to.ty.kind() { - // Unsigned - ty::Uint(t) => { - let size = Integer::from_uint_ty(this, *t).size(); - let res = f.to_u128_r(size.bits_usize(), round, &mut false); - if res.status.intersects( - rustc_apfloat::Status::INVALID_OP - | rustc_apfloat::Status::OVERFLOW - | rustc_apfloat::Status::UNDERFLOW, - ) { - // Floating point value is NaN (flagged with INVALID_OP) or outside the range - // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). - return None; - } else { - // Floating point value can be represented by the integer type after rounding. - // The INEXACT flag is ignored on purpose to allow rounding. - Scalar::from_uint(res.value, size) + fn float_to_int_inner<'tcx, F: rustc_apfloat::Float>( + this: &MiriInterpCx<'_, 'tcx>, + src: F, + cast_to: TyAndLayout<'tcx>, + round: rustc_apfloat::Round, + ) -> (Scalar, rustc_apfloat::Status) { + let int_size = cast_to.layout.size; + match cast_to.ty.kind() { + // Unsigned + ty::Uint(_) => { + let res = src.to_u128_r(int_size.bits_usize(), round, &mut false); + (Scalar::from_uint(res.value, int_size), res.status) } - } - // Signed - ty::Int(t) => { - let size = Integer::from_int_ty(this, *t).size(); - let res = f.to_i128_r(size.bits_usize(), round, &mut false); - if res.status.intersects( - rustc_apfloat::Status::INVALID_OP - | rustc_apfloat::Status::OVERFLOW - | rustc_apfloat::Status::UNDERFLOW, - ) { - // Floating point value is NaN (flagged with INVALID_OP) or outside the range - // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). - return None; - } else { - // Floating point value can be represented by the integer type after rounding. - // The INEXACT flag is ignored on purpose to allow rounding. - Scalar::from_int(res.value, size) + // Signed + ty::Int(_) => { + let res = src.to_i128_r(int_size.bits_usize(), round, &mut false); + (Scalar::from_int(res.value, int_size), res.status) } + // Nothing else + _ => + span_bug!( + this.cur_span(), + "attempted float-to-int conversion with non-int output type {}", + cast_to.ty, + ), } + } + + let (val, status) = match src.layout.ty.kind() { + // f32 + ty::Float(FloatTy::F32) => + float_to_int_inner::(this, src.to_scalar().to_f32()?, cast_to, round), + // f64 + ty::Float(FloatTy::F64) => + float_to_int_inner::(this, src.to_scalar().to_f64()?, cast_to, round), // Nothing else _ => span_bug!( this.cur_span(), - "attempted float-to-int conversion with non-int output type {}", - cast_to.ty, + "attempted float-to-int conversion with non-float input type {}", + src.layout.ty, ), }; - Some(ImmTy::from_scalar(val, cast_to)) + + if status.intersects( + rustc_apfloat::Status::INVALID_OP + | rustc_apfloat::Status::OVERFLOW + | rustc_apfloat::Status::UNDERFLOW, + ) { + // Floating point value is NaN (flagged with INVALID_OP) or outside the range + // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). + Ok(None) + } else { + // Floating point value can be represented by the integer type after rounding. + // The INEXACT flag is ignored on purpose to allow rounding. + Ok(Some(ImmTy::from_scalar(val, cast_to))) + } } /// Returns an integer type that is twice wide as `ty` @@ -1063,6 +1074,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => span_bug!(this.cur_span(), "unexpected type: {ty:?}"), } } + + /// Checks that target feature `target_feature` is enabled. + /// + /// If not enabled, emits an UB error that states that the feature is + /// required by `intrinsic`. + fn expect_target_feature_for_intrinsic( + &self, + intrinsic: Symbol, + target_feature: &str, + ) -> InterpResult<'tcx, ()> { + let this = self.eval_context_ref(); + if !this.tcx.sess.unstable_target_features.contains(&Symbol::intern(target_feature)) { + throw_ub_format!( + "attempted to call intrinsic `{intrinsic}` that requires missing target feature {target_feature}" + ); + } + Ok(()) + } } impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { @@ -1143,12 +1172,6 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec { local_crates } -/// Helper function used inside the shims of foreign functions to check that -/// `target_os` is a supported UNIX OS. -pub fn target_os_is_unix(target_os: &str) -> bool { - matches!(target_os, "linux" | "macos" | "freebsd" | "android") -} - pub(crate) fn bool_to_simd_element(b: bool, size: Size) -> Scalar { // SIMD uses all-1 as pattern for "true". In two's complement, // -1 has all its bits set to one and `from_int` will truncate or @@ -1165,3 +1188,11 @@ pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult< _ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"), }) } + +// This looks like something that would be nice to have in the standard library... +pub(crate) fn round_to_next_multiple_of(x: u64, divisor: u64) -> u64 { + assert_ne!(divisor, 0); + // divisor is nonzero; multiplication cannot overflow since we just divided + #[allow(clippy::arithmetic_side_effects)] + return (x.checked_add(divisor - 1).unwrap() / divisor) * divisor; +} diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/intptrcast.rs index 9966ee3fd919e..68c9a7660ebda 100644 --- a/src/tools/miri/src/intptrcast.rs +++ b/src/tools/miri/src/intptrcast.rs @@ -46,9 +46,21 @@ pub struct GlobalStateInner { provenance_mode: ProvenanceMode, } -impl VisitTags for GlobalStateInner { - fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) { - // Nothing to visit here. +impl VisitProvenance for GlobalStateInner { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { + let GlobalStateInner { + int_to_ptr_map: _, + base_addr: _, + exposed: _, + next_base_addr: _, + provenance_mode: _, + } = self; + // Though base_addr, int_to_ptr_map, and exposed contain AllocIds, we do not want to visit them. + // int_to_ptr_map and exposed must contain only live allocations, and those + // are never garbage collected. + // base_addr is only relevant if we have a pointer to an AllocId and need to look up its + // base address; so if an AllocId is not reachable from somewhere else we can remove it + // here. } } @@ -62,6 +74,12 @@ impl GlobalStateInner { provenance_mode: config.provenance_mode, } } + + pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_, '_>) { + // `exposed` and `int_to_ptr_map` are cleared immediately when an allocation + // is freed, so `base_addr` is the only one we have to clean up based on the GC. + self.base_addr.retain(|id, _| allocs.is_live(*id)); + } } /// Shifts `addr` to make it aligned with `align` by rounding `addr` to the smallest multiple @@ -107,7 +125,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // We only use this provenance if it has been exposed. if global_state.exposed.contains(&alloc_id) { // This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed. - debug_assert!(!matches!(ecx.get_alloc_info(alloc_id).2, AllocKind::Dead)); + debug_assert!(ecx.is_alloc_live(alloc_id)); Some(alloc_id) } else { None @@ -181,12 +199,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let ecx = self.eval_context_mut(); let global_state = ecx.machine.intptrcast.get_mut(); // In strict mode, we don't need this, so we can save some cycles by not tracking it. - if global_state.provenance_mode != ProvenanceMode::Strict { - trace!("Exposing allocation id {alloc_id:?}"); - global_state.exposed.insert(alloc_id); - if ecx.machine.borrow_tracker.is_some() { - ecx.expose_tag(alloc_id, tag)?; - } + if global_state.provenance_mode == ProvenanceMode::Strict { + return Ok(()); + } + // Exposing a dead alloc is a no-op, because it's not possible to get a dead allocation + // via int2ptr. + if !ecx.is_alloc_live(alloc_id) { + return Ok(()); + } + trace!("Exposing allocation id {alloc_id:?}"); + let global_state = ecx.machine.intptrcast.get_mut(); + global_state.exposed.insert(alloc_id); + if ecx.machine.borrow_tracker.is_some() { + ecx.expose_tag(alloc_id, tag)?; } Ok(()) } @@ -231,12 +256,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Convert a relative (tcx) pointer to a Miri pointer. fn ptr_from_rel_ptr( &self, - ptr: Pointer, + ptr: Pointer, tag: BorTag, ) -> InterpResult<'tcx, Pointer> { let ecx = self.eval_context_ref(); - let (alloc_id, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) + let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) + let alloc_id = prov.alloc_id(); let base_addr = ecx.addr_from_alloc_id(alloc_id)?; // Add offset with the right kind of pointer-overflowing arithmetic. diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index b12aae6d4148c..1eb40ab826c45 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -11,7 +11,7 @@ #![feature(round_ties_even)] #![feature(let_chains)] #![feature(lint_reasons)] -#![feature(trait_upcasting)] +#![cfg_attr(bootstrap, feature(trait_upcasting))] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, @@ -77,9 +77,9 @@ mod intptrcast; mod machine; mod mono_hash_map; mod operator; +mod provenance_gc; mod range_map; mod shims; -mod tag_gc; // Establish a "crate-wide prelude": we often import `crate::*`. @@ -125,8 +125,8 @@ pub use crate::machine::{ }; pub use crate::mono_hash_map::MonoHashMap; pub use crate::operator::EvalContextExt as _; +pub use crate::provenance_gc::{EvalContextExt as _, LiveAllocs, VisitProvenance, VisitWith}; pub use crate::range_map::RangeMap; -pub use crate::tag_gc::{EvalContextExt as _, VisitTags}; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index d5775912eabea..4a878f4a36e6c 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -2,7 +2,7 @@ //! `Machine` trait. use std::borrow::Cow; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::fmt; use std::path::Path; use std::process; @@ -17,6 +17,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::static_assert_size; use rustc_middle::{ mir, + query::TyCtxtAt, ty::{ self, layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout}, @@ -77,12 +78,12 @@ impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> { } } -impl VisitTags for FrameExtra<'_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for FrameExtra<'_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _ } = self; - catch_unwind.visit_tags(visit); - borrow_tracker.visit_tags(visit); + catch_unwind.visit_provenance(visit); + borrow_tracker.visit_provenance(visit); } } @@ -259,6 +260,17 @@ impl interpret::Provenance for Provenance { } } + fn fmt(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (prov, addr) = ptr.into_parts(); // address is absolute + write!(f, "{:#x}", addr.bytes())?; + if f.alternate() { + write!(f, "{prov:#?}")?; + } else { + write!(f, "{prov:?}")?; + } + Ok(()) + } + fn join(left: Option, right: Option) -> Option { match (left, right) { // If both are the *same* concrete tag, that is the result. @@ -309,15 +321,24 @@ pub struct AllocExtra<'tcx> { /// if this allocation is leakable. The backtrace is not /// pruned yet; that should be done before printing it. pub backtrace: Option>>, + /// An offset inside this allocation that was deemed aligned even for symbolic alignment checks. + /// Invariant: the promised alignment will never be less than the native alignment of this allocation. + pub symbolic_alignment: Cell>, } -impl VisitTags for AllocExtra<'_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _ } = self; +impl VisitProvenance for AllocExtra<'_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + let AllocExtra { + borrow_tracker, + data_race, + weak_memory, + backtrace: _, + symbolic_alignment: _, + } = self; - borrow_tracker.visit_tags(visit); - data_race.visit_tags(visit); - weak_memory.visit_tags(visit); + borrow_tracker.visit_provenance(visit); + data_race.visit_provenance(visit); + weak_memory.visit_provenance(visit); } } @@ -768,11 +789,6 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { drop(self.profiler.take()); } - pub(crate) fn round_up_to_multiple_of_page_size(&self, length: u64) -> Option { - #[allow(clippy::arithmetic_side_effects)] // page size is nonzero - (length.checked_add(self.page_size - 1)? / self.page_size).checked_mul(self.page_size) - } - pub(crate) fn page_align(&self) -> Align { Align::from_bytes(self.page_size).unwrap() } @@ -793,8 +809,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { } } -impl VisitTags for MiriMachine<'_, '_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for MiriMachine<'_, '_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { #[rustfmt::skip] let MiriMachine { threads, @@ -843,20 +859,20 @@ impl VisitTags for MiriMachine<'_, '_> { allocation_spans: _, } = self; - threads.visit_tags(visit); - tls.visit_tags(visit); - env_vars.visit_tags(visit); - dir_handler.visit_tags(visit); - file_handler.visit_tags(visit); - data_race.visit_tags(visit); - borrow_tracker.visit_tags(visit); - intptrcast.visit_tags(visit); - main_fn_ret_place.visit_tags(visit); - argc.visit_tags(visit); - argv.visit_tags(visit); - cmd_line.visit_tags(visit); + threads.visit_provenance(visit); + tls.visit_provenance(visit); + env_vars.visit_provenance(visit); + dir_handler.visit_provenance(visit); + file_handler.visit_provenance(visit); + data_race.visit_provenance(visit); + borrow_tracker.visit_provenance(visit); + intptrcast.visit_provenance(visit); + main_fn_ret_place.visit_provenance(visit); + argc.visit_provenance(visit); + argv.visit_provenance(visit); + cmd_line.visit_provenance(visit); for ptr in extern_statics.values() { - ptr.visit_tags(visit); + ptr.visit_provenance(visit); } } } @@ -907,8 +923,45 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { } #[inline(always)] - fn use_addr_for_alignment_check(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool { - ecx.machine.check_alignment == AlignmentCheck::Int + fn alignment_check( + ecx: &MiriInterpCx<'mir, 'tcx>, + alloc_id: AllocId, + alloc_align: Align, + alloc_kind: AllocKind, + offset: Size, + align: Align, + ) -> Option { + if ecx.machine.check_alignment != AlignmentCheck::Symbolic { + // Just use the built-in check. + return None; + } + if alloc_kind != AllocKind::LiveData { + // Can't have any extra info here. + return None; + } + // Let's see which alignment we have been promised for this allocation. + let alloc_info = ecx.get_alloc_extra(alloc_id).unwrap(); // cannot fail since the allocation is live + let (promised_offset, promised_align) = + alloc_info.symbolic_alignment.get().unwrap_or((Size::ZERO, alloc_align)); + if promised_align < align { + // Definitely not enough. + Some(Misalignment { has: promised_align, required: align }) + } else { + // What's the offset between us and the promised alignment? + let distance = offset.bytes().wrapping_sub(promised_offset.bytes()); + // That must also be aligned. + if distance % align.bytes() == 0 { + // All looking good! + None + } else { + // The biggest power of two through which `distance` is divisible. + let distance_pow2 = 1 << distance.trailing_zeros(); + Some(Misalignment { + has: Align::from_bytes(distance_pow2).unwrap(), + required: align, + }) + } + } } #[inline(always)] @@ -1112,6 +1165,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { data_race: race_alloc, weak_memory: buffer_alloc, backtrace, + symbolic_alignment: Cell::new(None), }, |ptr| ecx.global_base_pointer(ptr), )?; @@ -1128,11 +1182,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { fn adjust_alloc_base_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, - ptr: Pointer, + ptr: Pointer, ) -> InterpResult<'tcx, Pointer> { + let alloc_id = ptr.provenance.alloc_id(); if cfg!(debug_assertions) { // The machine promises to never call us on thread-local or extern statics. - let alloc_id = ptr.provenance; match ecx.tcx.try_get_global_alloc(alloc_id) { Some(GlobalAlloc::Static(def_id)) if ecx.tcx.is_thread_local_static(def_id) => { panic!("adjust_alloc_base_pointer called on thread-local static") @@ -1143,8 +1197,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { _ => {} } } + // FIXME: can we somehow preserve the immutability of `ptr`? let tag = if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { - borrow_tracker.borrow_mut().base_ptr_tag(ptr.provenance, &ecx.machine) + borrow_tracker.borrow_mut().base_ptr_tag(alloc_id, &ecx.machine) } else { // Value does not matter, SB is disabled BorTag::default() @@ -1203,7 +1258,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { #[inline(always)] fn before_memory_read( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, machine: &Self, alloc_extra: &AllocExtra<'tcx>, (alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra), @@ -1223,7 +1278,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { #[inline(always)] fn before_memory_write( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra<'tcx>, (alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra), @@ -1243,7 +1298,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { #[inline(always)] fn before_memory_deallocation( - _tcx: TyCtxt<'tcx>, + _tcx: TyCtxtAt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra<'tcx>, (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra), @@ -1380,7 +1435,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { // where it mistakenly removes an important tag become visible. if ecx.machine.gc_interval > 0 && ecx.machine.since_gc >= ecx.machine.gc_interval { ecx.machine.since_gc = 0; - ecx.garbage_collect_tags()?; + ecx.run_provenance_gc(); } // These are our preemption points. @@ -1409,34 +1464,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ) -> InterpResult<'tcx> { // We want this *before* the return value copy, because the return place itself is protected // until we do `end_call` here. - if let Some(global_borrow_tracker) = &ecx.machine.borrow_tracker { - // The body of this loop needs `global_borrow_tracker` immutably - // so we can't move this code inside the following `end_call`. - for (alloc_id, tag) in &frame - .extra - .borrow_tracker - .as_ref() - .expect("we should have borrow tracking data") - .protected_tags - { - // Just because the tag is protected doesn't guarantee that - // the allocation still exists (weak protectors allow deallocations) - // so we must check that the allocation exists. - // If it does exist, then we have the guarantee that the - // pointer is readable, and the implicit read access inserted - // will never cause UB on the pointer itself. - let (_, _, kind) = ecx.get_alloc_info(*alloc_id); - if matches!(kind, AllocKind::LiveData) { - let alloc_extra = ecx.get_alloc_extra(*alloc_id).unwrap(); - let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap(); - alloc_borrow_tracker.release_protector( - &ecx.machine, - global_borrow_tracker, - *tag, - )?; - } - } - global_borrow_tracker.borrow_mut().end_call(&frame.extra); + if ecx.machine.borrow_tracker.is_some() { + ecx.on_stack_pop(frame)?; } Ok(()) } diff --git a/src/tools/miri/src/mono_hash_map.rs b/src/tools/miri/src/mono_hash_map.rs index 81b3153517f14..220233f8ff5f0 100644 --- a/src/tools/miri/src/mono_hash_map.rs +++ b/src/tools/miri/src/mono_hash_map.rs @@ -46,6 +46,14 @@ impl AllocMap for MonoHashMap { self.0.get_mut().contains_key(k) } + #[inline(always)] + fn contains_key_ref(&self, k: &Q) -> bool + where + K: Borrow, + { + self.0.borrow().contains_key(k) + } + #[inline(always)] fn insert(&mut self, k: K, v: V) -> Option { self.0.get_mut().insert(k, Box::new(v)).map(|x| *x) diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs new file mode 100644 index 0000000000000..ab178f82d9fde --- /dev/null +++ b/src/tools/miri/src/provenance_gc.rs @@ -0,0 +1,205 @@ +use either::Either; + +use rustc_data_structures::fx::FxHashSet; + +use crate::*; + +pub type VisitWith<'a> = dyn FnMut(Option, Option) + 'a; + +pub trait VisitProvenance { + fn visit_provenance(&self, visit: &mut VisitWith<'_>); +} + +impl VisitProvenance for Option { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + if let Some(x) = self { + x.visit_provenance(visit); + } + } +} + +impl VisitProvenance for std::cell::RefCell { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + self.borrow().visit_provenance(visit) + } +} + +impl VisitProvenance for BorTag { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + visit(None, Some(*self)) + } +} + +impl VisitProvenance for AllocId { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + visit(Some(*self), None) + } +} + +impl VisitProvenance for Provenance { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + if let Provenance::Concrete { alloc_id, tag, .. } = self { + visit(Some(*alloc_id), Some(*tag)); + } + } +} + +impl VisitProvenance for Pointer { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + let (prov, _offset) = self.into_parts(); + prov.visit_provenance(visit); + } +} + +impl VisitProvenance for Pointer> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + let (prov, _offset) = self.into_parts(); + prov.visit_provenance(visit); + } +} + +impl VisitProvenance for Scalar { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + match self { + Scalar::Ptr(ptr, _) => ptr.visit_provenance(visit), + Scalar::Int(_) => (), + } + } +} + +impl VisitProvenance for Immediate { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + match self { + Immediate::Scalar(s) => { + s.visit_provenance(visit); + } + Immediate::ScalarPair(s1, s2) => { + s1.visit_provenance(visit); + s2.visit_provenance(visit); + } + Immediate::Uninit => {} + } + } +} + +impl VisitProvenance for MemPlaceMeta { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + match self { + MemPlaceMeta::Meta(m) => m.visit_provenance(visit), + MemPlaceMeta::None => {} + } + } +} + +impl VisitProvenance for ImmTy<'_, Provenance> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + (**self).visit_provenance(visit) + } +} + +impl VisitProvenance for MPlaceTy<'_, Provenance> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + self.ptr().visit_provenance(visit); + self.meta().visit_provenance(visit); + } +} + +impl VisitProvenance for PlaceTy<'_, Provenance> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + match self.as_mplace_or_local() { + Either::Left(mplace) => mplace.visit_provenance(visit), + Either::Right(_) => (), + } + } +} + +impl VisitProvenance for OpTy<'_, Provenance> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + match self.as_mplace_or_imm() { + Either::Left(mplace) => mplace.visit_provenance(visit), + Either::Right(imm) => imm.visit_provenance(visit), + } + } +} + +impl VisitProvenance for Allocation> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + for prov in self.provenance().provenances() { + prov.visit_provenance(visit); + } + + self.extra.visit_provenance(visit); + } +} + +impl VisitProvenance for crate::MiriInterpCx<'_, '_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { + // Visit the contents of the allocations and the IDs themselves, to account for all + // live allocation IDs and all provenance in the allocation bytes, even if they are leaked. + // We do *not* visit all the `AllocId` of the live allocations; we tried that and adding + // them all to the live set is too expensive. Instead we later do liveness check by + // checking both "is this alloc id live" and "is it mentioned anywhere else in + // the interpreter state". + self.memory.alloc_map().iter(|it| { + for (_id, (_kind, alloc)) in it { + alloc.visit_provenance(visit); + } + }); + // And all the other machine values. + self.machine.visit_provenance(visit); + } +} + +pub struct LiveAllocs<'a, 'mir, 'tcx> { + collected: FxHashSet, + ecx: &'a MiriInterpCx<'mir, 'tcx>, +} + +impl LiveAllocs<'_, '_, '_> { + pub fn is_live(&self, id: AllocId) -> bool { + self.collected.contains(&id) || self.ecx.is_alloc_live(id) + } +} + +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { + fn run_provenance_gc(&mut self) { + // We collect all tags from various parts of the interpreter, but also + let this = self.eval_context_mut(); + + let mut tags = FxHashSet::default(); + let mut alloc_ids = FxHashSet::default(); + this.visit_provenance(&mut |id, tag| { + if let Some(id) = id { + alloc_ids.insert(id); + } + if let Some(tag) = tag { + tags.insert(tag); + } + }); + self.remove_unreachable_tags(tags); + self.remove_unreachable_allocs(alloc_ids); + } + + fn remove_unreachable_tags(&mut self, tags: FxHashSet) { + let this = self.eval_context_mut(); + this.memory.alloc_map().iter(|it| { + for (_id, (_kind, alloc)) in it { + if let Some(bt) = &alloc.extra.borrow_tracker { + bt.remove_unreachable_tags(&tags); + } + } + }); + } + + fn remove_unreachable_allocs(&mut self, allocs: FxHashSet) { + let this = self.eval_context_mut(); + let allocs = LiveAllocs { ecx: this, collected: allocs }; + this.machine.allocation_spans.borrow_mut().retain(|id, _| allocs.is_live(*id)); + this.machine.intptrcast.borrow_mut().remove_unreachable_allocs(&allocs); + if let Some(borrow_tracker) = &this.machine.borrow_tracker { + borrow_tracker.borrow_mut().remove_unreachable_allocs(&allocs); + } + this.remove_unreachable_allocs(&allocs.collected); + } +} diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index 154a7f6983343..9e19f72021123 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -9,7 +9,6 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::Ty; use rustc_target::abi::Size; -use crate::helpers::target_os_is_unix; use crate::*; /// Check whether an operation that writes to a target buffer was successful. @@ -37,13 +36,13 @@ pub struct EnvVars<'tcx> { pub(crate) environ: Option>, } -impl VisitTags for EnvVars<'_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for EnvVars<'_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let EnvVars { map, environ } = self; - environ.visit_tags(visit); + environ.visit_provenance(visit); for ptr in map.values() { - ptr.visit_tags(visit); + ptr.visit_provenance(visit); } } } @@ -53,16 +52,15 @@ impl<'tcx> EnvVars<'tcx> { ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>, config: &MiriConfig, ) -> InterpResult<'tcx> { - let target_os = ecx.tcx.sess.target.os.as_ref(); - + // Initialize the `env_vars` map. // Skip the loop entirely if we don't want to forward anything. if ecx.machine.communicate() || !config.forwarded_env_vars.is_empty() { for (name, value) in &config.env { let forward = ecx.machine.communicate() || config.forwarded_env_vars.iter().any(|v| **v == *name); if forward { - let var_ptr = match target_os { - target if target_os_is_unix(target) => + let var_ptr = match ecx.tcx.sess.target.os.as_ref() { + _ if ecx.target_os_is_unix() => alloc_env_var_as_c_str(name.as_ref(), value.as_ref(), ecx)?, "windows" => alloc_env_var_as_wide_str(name.as_ref(), value.as_ref(), ecx)?, unsupported => @@ -75,7 +73,17 @@ impl<'tcx> EnvVars<'tcx> { } } } - ecx.update_environ() + + // Initialize the `environ` pointer when needed. + if ecx.target_os_is_unix() { + // This is memory backing an extern static, hence `ExternStatic`, not `Env`. + let layout = ecx.machine.layouts.mut_raw_ptr; + let place = ecx.allocate(layout, MiriMemoryKind::ExternStatic.into())?; + ecx.write_null(&place)?; + ecx.machine.env_vars.environ = Some(place); + ecx.update_environ()?; + } + Ok(()) } pub(crate) fn cleanup<'mir>( @@ -87,9 +95,11 @@ impl<'tcx> EnvVars<'tcx> { ecx.deallocate_ptr(ptr, None, MiriMemoryKind::Runtime.into())?; } // Deallocate environ var list. - let environ = ecx.machine.env_vars.environ.as_ref().unwrap(); - let old_vars_ptr = ecx.read_pointer(environ)?; - ecx.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?; + if ecx.target_os_is_unix() { + let environ = ecx.machine.env_vars.environ.as_ref().unwrap(); + let old_vars_ptr = ecx.read_pointer(environ)?; + ecx.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?; + } Ok(()) } } @@ -127,6 +137,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let name_ptr = this.read_pointer(name_op)?; let name = this.read_os_str_from_c_str(name_ptr)?; + this.read_environ()?; Ok(match this.machine.env_vars.map.get(name) { Some(var_ptr) => { // The offset is used to strip the "{name}=" part of the string. @@ -275,7 +286,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Delete environment variable `{name}` if let Some(var) = this.machine.env_vars.map.remove(&name) { this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; - this.update_environ()?; } Ok(this.eval_windows("c", "TRUE")) } else { @@ -284,7 +294,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if let Some(var) = this.machine.env_vars.map.insert(name, var_ptr) { this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; } - this.update_environ()?; Ok(this.eval_windows("c", "TRUE")) } } @@ -431,15 +440,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn update_environ(&mut self) -> InterpResult<'tcx> { let this = self.eval_context_mut(); // Deallocate the old environ list, if any. - if let Some(environ) = this.machine.env_vars.environ.as_ref() { - let old_vars_ptr = this.read_pointer(environ)?; + let environ = this.machine.env_vars.environ.as_ref().unwrap().clone(); + let old_vars_ptr = this.read_pointer(&environ)?; + if !this.ptr_is_null(old_vars_ptr)? { this.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?; - } else { - // No `environ` allocated yet, let's do that. - // This is memory backing an extern static, hence `ExternStatic`, not `Env`. - let layout = this.machine.layouts.mut_raw_ptr; - let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?; - this.machine.env_vars.environ = Some(place); } // Collect all the pointers to each variable in a vector. @@ -459,8 +463,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let place = this.project_field(&vars_place, idx)?; this.write_pointer(var, &place)?; } - this.write_pointer(vars_place.ptr(), &this.machine.env_vars.environ.clone().unwrap())?; + this.write_pointer(vars_place.ptr(), &environ)?; + + Ok(()) + } + /// Reads from the `environ` static. + /// We don't actually care about the result, but we care about this potentially causing a data race. + fn read_environ(&self) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); + let environ = this.machine.env_vars.environ.as_ref().unwrap(); + let _vars_ptr = this.read_pointer(environ)?; Ok(()) } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 2d5df3037452f..8ddfc05dd300a 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -22,7 +22,6 @@ use rustc_target::{ }; use super::backtrace::EvalContextExt as _; -use crate::helpers::target_os_is_unix; use crate::*; /// Type of dynamic symbols (for `dlsym` et al) @@ -345,7 +344,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // List taken from `library/std/src/sys/common/alloc.rs`. // This list should be kept in sync with the one from libstd. let min_align = match this.tcx.sess.target.arch.as_ref() { - "x86" | "arm" | "mips" | "mips32r6" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8, + "x86" | "arm" | "mips" | "mips32r6" | "powerpc" | "powerpc64" | "wasm32" => 8, "x86_64" | "aarch64" | "mips64" | "mips64r6" | "s390x" | "sparc64" | "loongarch64" => 16, arch => bug!("unsupported target architecture for malloc: `{}`", arch), @@ -459,12 +458,16 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // shim, add it to the corresponding submodule. match link_name.as_str() { // Miri-specific extern functions + "miri_run_provenance_gc" => { + let [] = this.check_shim(abi, Abi::Rust, link_name, args)?; + this.run_provenance_gc(); + } "miri_get_alloc_id" => { let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr).map_err(|_e| { err_machine_stop!(TerminationInfo::Abort(format!( - "pointer passed to miri_get_alloc_id must not be dangling, got {ptr:?}" + "pointer passed to `miri_get_alloc_id` must not be dangling, got {ptr:?}" ))) })?; this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?; @@ -496,7 +499,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr)?; if offset != Size::ZERO { throw_unsup_format!( - "pointer passed to miri_static_root must point to beginning of an allocated block" + "pointer passed to `miri_static_root` must point to beginning of an allocated block" ); } this.machine.static_roots.push(alloc_id); @@ -553,6 +556,49 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; } + // Promises that a pointer has a given symbolic alignment. + "miri_promise_symbolic_alignment" => { + use rustc_target::abi::AlignFromBytesError; + + let [ptr, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let align = this.read_target_usize(align)?; + if !align.is_power_of_two() { + throw_unsup_format!( + "`miri_promise_symbolic_alignment`: alignment must be a power of 2, got {align}" + ); + } + let align = Align::from_bytes(align).unwrap_or_else(|err| { + match err { + AlignFromBytesError::NotPowerOfTwo(_) => unreachable!(), + // When the alignment is a power of 2 but too big, clamp it to MAX. + AlignFromBytesError::TooLarge(_) => Align::MAX, + } + }); + let (_, addr) = ptr.into_parts(); // we know the offset is absolute + // Cannot panic since `align` is a power of 2 and hence non-zero. + if addr.bytes().checked_rem(align.bytes()).unwrap() != 0 { + throw_unsup_format!( + "`miri_promise_symbolic_alignment`: pointer is not actually aligned" + ); + } + if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr) { + let (_size, alloc_align, _kind) = this.get_alloc_info(alloc_id); + // Not `get_alloc_extra_mut`, need to handle read-only allocations! + let alloc_extra = this.get_alloc_extra(alloc_id)?; + // If the newly promised alignment is bigger than the native alignment of this + // allocation, and bigger than the previously promised alignment, then set it. + if align > alloc_align + && !alloc_extra + .symbolic_alignment + .get() + .is_some_and(|(_, old_align)| align <= old_align) + { + alloc_extra.symbolic_alignment.set(Some((offset, align))); + } + } + } + // Standard C allocation "malloc" => { let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -1008,9 +1054,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => { let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; let arg = this.read_scalar(arg)?.to_i32()?; + // Note that different arguments might have different target feature requirements. match arg { // YIELD 1 => { + this.expect_target_feature_for_intrinsic(link_name, "v6")?; this.yield_active_thread(); } _ => { @@ -1054,7 +1102,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Platform-specific shims _ => return match this.tcx.sess.target.os.as_ref() { - target_os if target_os_is_unix(target_os) => + _ if this.target_os_is_unix() => shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 8c90ceba1e4aa..66918db995d03 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -365,36 +365,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [val] = check_arg_count(args)?; let val = this.read_immediate(val)?; - let res = match val.layout.ty.kind() { - ty::Float(FloatTy::F32) => { - let f = val.to_scalar().to_f32()?; - this - .float_to_int_checked(f, dest.layout, Round::TowardZero) - .ok_or_else(|| { - err_ub_format!( - "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`", - dest.layout.ty - ) - })? - } - ty::Float(FloatTy::F64) => { - let f = val.to_scalar().to_f64()?; - this - .float_to_int_checked(f, dest.layout, Round::TowardZero) - .ok_or_else(|| { - err_ub_format!( - "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`", - dest.layout.ty - ) - })? - } - _ => - span_bug!( - this.cur_span(), - "`float_to_int_unchecked` called with non-float input type {:?}", - val.layout.ty - ), - }; + let res = this + .float_to_int_checked(&val, dest.layout, Round::TowardZero)? + .ok_or_else(|| { + err_ub_format!( + "`float_to_int_unchecked` intrinsic called on {val} which cannot be represented in target type `{:?}`", + dest.layout.ty + ) + })?; this.write_immediate(*res, dest)?; } diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 70f90aac2c23f..e17c06be9b837 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -1,10 +1,13 @@ use rustc_apfloat::{Float, Round}; use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; use rustc_middle::{mir, ty, ty::FloatTy}; +use rustc_span::{sym, Symbol}; use rustc_target::abi::{Endian, HasDataLayout}; +use crate::helpers::{ + bool_to_simd_element, check_arg_count, round_to_next_multiple_of, simd_element_to_bool, +}; use crate::*; -use helpers::{bool_to_simd_element, check_arg_count, simd_element_to_bool}; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { @@ -25,7 +28,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "floor" | "round" | "trunc" - | "fsqrt" => { + | "fsqrt" + | "ctlz" + | "cttz" + | "bswap" + | "bitreverse" + => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; let (dest, dest_len) = this.place_to_simd(dest)?; @@ -38,6 +46,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Abs, Sqrt, Round(rustc_apfloat::Round), + Numeric(Symbol), } let which = match intrinsic_name { "neg" => Op::MirOp(mir::UnOp::Neg), @@ -47,6 +56,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "floor" => Op::Round(rustc_apfloat::Round::TowardNegative), "round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway), "trunc" => Op::Round(rustc_apfloat::Round::TowardZero), + "ctlz" => Op::Numeric(sym::ctlz), + "cttz" => Op::Numeric(sym::cttz), + "bswap" => Op::Numeric(sym::bswap), + "bitreverse" => Op::Numeric(sym::bitreverse), _ => unreachable!(), }; @@ -101,6 +114,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } } + Op::Numeric(name) => { + this.numeric_intrinsic(name, op.to_scalar(), op.layout)? + } }; this.write_scalar(val, &dest)?; } @@ -126,7 +142,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "fmin" | "saturating_add" | "saturating_sub" - | "arith_offset" => { + | "arith_offset" + => { use mir::BinOp; let [left, right] = check_arg_count(args)?; @@ -379,14 +396,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_immediate(*val, &dest)?; } } + // Variant of `select` that takes a bitmask rather than a "vector of bool". "select_bitmask" => { let [mask, yes, no] = check_arg_count(args)?; let (yes, yes_len) = this.operand_to_simd(yes)?; let (no, no_len) = this.operand_to_simd(no)?; let (dest, dest_len) = this.place_to_simd(dest)?; - let bitmask_len = dest_len.max(8); + let bitmask_len = round_to_next_multiple_of(dest_len, 8); - assert!(mask.layout.ty.is_integral()); + // The mask must be an integer or an array. + assert!( + mask.layout.ty.is_integral() + || matches!(mask.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8) + ); assert!(bitmask_len <= 64); assert_eq!(bitmask_len, mask.layout.size.bits()); assert_eq!(dest_len, yes_len); @@ -394,13 +416,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest_len = u32::try_from(dest_len).unwrap(); let bitmask_len = u32::try_from(bitmask_len).unwrap(); - let mask: u64 = - this.read_scalar(mask)?.to_bits(mask.layout.size)?.try_into().unwrap(); + // To read the mask, we transmute it to an integer. + // That does the right thing wrt endianess. + let mask_ty = this.machine.layouts.uint(mask.layout.size).unwrap(); + let mask = mask.transmute(mask_ty, this)?; + let mask: u64 = this.read_scalar(&mask)?.to_bits(mask_ty.size)?.try_into().unwrap(); + for i in 0..dest_len { - let mask = mask - & 1u64 - .checked_shl(simd_bitmask_index(i, dest_len, this.data_layout().endian)) - .unwrap(); + let bit_i = simd_bitmask_index(i, dest_len, this.data_layout().endian); + let mask = mask & 1u64.checked_shl(bit_i).unwrap(); let yes = this.read_immediate(&this.project_index(&yes, i.into())?)?; let no = this.read_immediate(&this.project_index(&no, i.into())?)?; let dest = this.project_index(&dest, i.into())?; @@ -410,6 +434,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } for i in dest_len..bitmask_len { // If the mask is "padded", ensure that padding is all-zero. + // This deliberately does not use `simd_bitmask_index`; these bits are outside + // the bitmask. It does not matter in which order we check them. let mask = mask & 1u64.checked_shl(i).unwrap(); if mask != 0 { throw_ub_format!( @@ -418,6 +444,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } } + // Converts a "vector of bool" into a bitmask. + "bitmask" => { + let [op] = check_arg_count(args)?; + let (op, op_len) = this.operand_to_simd(op)?; + let bitmask_len = round_to_next_multiple_of(op_len, 8); + + // Returns either an unsigned integer or array of `u8`. + assert!( + dest.layout.ty.is_integral() + || matches!(dest.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8) + ); + assert!(bitmask_len <= 64); + assert_eq!(bitmask_len, dest.layout.size.bits()); + let op_len = u32::try_from(op_len).unwrap(); + + let mut res = 0u64; + for i in 0..op_len { + let op = this.read_immediate(&this.project_index(&op, i.into())?)?; + if simd_element_to_bool(op)? { + res |= 1u64 + .checked_shl(simd_bitmask_index(i, op_len, this.data_layout().endian)) + .unwrap(); + } + } + // We have to change the type of the place to be able to write `res` into it. This + // transmutes the integer to an array, which does the right thing wrt endianess. + let dest = + dest.transmute(this.machine.layouts.uint(dest.layout.size).unwrap(), this)?; + this.write_int(res, &dest)?; + } "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; @@ -447,22 +503,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast => this.float_to_float_or_int(&op, dest.layout)?, // Float-to-int in unchecked mode - (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => { - let f = op.to_scalar().to_f32()?; - this.float_to_int_checked(f, dest.layout, Round::TowardZero) + (ty::Float(_), ty::Int(_) | ty::Uint(_)) if unsafe_cast => { + this.float_to_int_checked(&op, dest.layout, Round::TowardZero)? .ok_or_else(|| { err_ub_format!( - "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`", - dest.layout.ty - ) - })? - } - (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => { - let f = op.to_scalar().to_f64()?; - this.float_to_int_checked(f, dest.layout, Round::TowardZero) - .ok_or_else(|| { - err_ub_format!( - "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`", + "`simd_cast` intrinsic called on {op} which cannot be represented in target type `{:?}`", dest.layout.ty ) })? @@ -611,34 +656,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } } - "bitmask" => { - let [op] = check_arg_count(args)?; - let (op, op_len) = this.operand_to_simd(op)?; - let bitmask_len = op_len.max(8); - - // Returns either an unsigned integer or array of `u8`. - assert!( - dest.layout.ty.is_integral() - || matches!(dest.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8) - ); - assert!(bitmask_len <= 64); - assert_eq!(bitmask_len, dest.layout.size.bits()); - let op_len = u32::try_from(op_len).unwrap(); - - let mut res = 0u64; - for i in 0..op_len { - let op = this.read_immediate(&this.project_index(&op, i.into())?)?; - if simd_element_to_bool(op)? { - res |= 1u64 - .checked_shl(simd_bitmask_index(i, op_len, this.data_layout().endian)) - .unwrap(); - } - } - // We have to force the place type to be an int so that we can write `res` into it. - let mut dest = this.force_allocation(dest)?; - dest.layout = this.machine.layouts.uint(dest.layout.size).unwrap(); - this.write_int(res, &dest)?; - } name => throw_unsup_format!("unimplemented intrinsic: `simd_{name}`"), } diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index a031a2a25c968..1e9d927e1a957 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -23,7 +23,6 @@ use rustc_middle::{mir, ty}; use rustc_target::spec::abi::Abi; use crate::*; -use helpers::check_arg_count; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { @@ -39,16 +38,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); trace!("eval_fn_call: {:#?}, {:?}", instance, dest); - // There are some more lang items we want to hook that CTFE does not hook (yet). - if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) { - let args = this.copy_fn_args(args)?; - let [ptr, align] = check_arg_count(&args)?; - if this.align_offset(ptr, align, dest, ret, unwind)? { - return Ok(None); - } - } - - // Try to see if we can do something about foreign items. + // For foreign items, try to see if we can emulate them. if this.tcx.is_foreign_item(instance.def_id()) { // An external function call that does not have a MIR body. We either find MIR elsewhere // or emulate its effect. @@ -64,53 +54,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Otherwise, load the MIR. Ok(Some((this.load_mir(instance.def, None)?, instance))) } - - /// Returns `true` if the computation was performed, and `false` if we should just evaluate - /// the actual MIR of `align_offset`. - fn align_offset( - &mut self, - ptr_op: &OpTy<'tcx, Provenance>, - align_op: &OpTy<'tcx, Provenance>, - dest: &PlaceTy<'tcx, Provenance>, - ret: Option, - unwind: mir::UnwindAction, - ) -> InterpResult<'tcx, bool> { - let this = self.eval_context_mut(); - let ret = ret.unwrap(); - - if this.machine.check_alignment != AlignmentCheck::Symbolic { - // Just use actual implementation. - return Ok(false); - } - - let req_align = this.read_target_usize(align_op)?; - - // Stop if the alignment is not a power of two. - if !req_align.is_power_of_two() { - this.start_panic("align_offset: align is not a power-of-two", unwind)?; - return Ok(true); // nothing left to do - } - - let ptr = this.read_pointer(ptr_op)?; - // If this carries no provenance, treat it like an integer. - if ptr.provenance.is_none() { - // Use actual implementation. - return Ok(false); - } - - if let Ok((alloc_id, _offset, _)) = this.ptr_try_get_alloc_id(ptr) { - // Only do anything if we can identify the allocation this goes to. - let (_size, cur_align, _kind) = this.get_alloc_info(alloc_id); - if cur_align.bytes() >= req_align { - // If the allocation alignment is at least the required alignment we use the - // real implementation. - return Ok(false); - } - } - - // Return error result (usize::MAX), and jump to caller. - this.write_scalar(Scalar::from_target_usize(this.target_usize_max(), this), dest)?; - this.go_to_block(ret); - Ok(true) - } } diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index 5c0f828e4e6bb..28652c25c2450 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -35,12 +35,12 @@ pub struct CatchUnwindData<'tcx> { ret: mir::BasicBlock, } -impl VisitTags for CatchUnwindData<'_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for CatchUnwindData<'_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let CatchUnwindData { catch_fn, data, dest, ret: _ } = self; - catch_fn.visit_tags(visit); - data.visit_tags(visit); - dest.visit_tags(visit); + catch_fn.visit_provenance(visit); + data.visit_provenance(visit); + dest.visit_provenance(visit); } } diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 4918698c6b277..13ce9d119bc3b 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -31,8 +31,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut relative_clocks; match this.tcx.sess.target.os.as_ref() { - "linux" => { - // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the + "linux" | "freebsd" => { + // Linux and FreeBSD have two main kinds of clocks. REALTIME clocks return the actual time since the // Unix epoch, including effects which may cause time to move backwards such as NTP. // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version // is just specified to be "faster and less precise", so we implement both the same way. @@ -274,8 +274,8 @@ struct UnblockCallback { thread_to_unblock: ThreadId, } -impl VisitTags for UnblockCallback { - fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {} +impl VisitProvenance for UnblockCallback { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {} } impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for UnblockCallback { diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs index 62bd087e7e82d..b319516c25b9e 100644 --- a/src/tools/miri/src/shims/tls.rs +++ b/src/tools/miri/src/shims/tls.rs @@ -207,15 +207,15 @@ impl<'tcx> TlsData<'tcx> { } } -impl VisitTags for TlsData<'_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for TlsData<'_> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let TlsData { keys, macos_thread_dtors, next_key: _ } = self; for scalar in keys.values().flat_map(|v| v.data.values()) { - scalar.visit_tags(visit); + scalar.visit_provenance(visit); } for (_, scalar) in macos_thread_dtors.values() { - scalar.visit_tags(visit); + scalar.visit_provenance(visit); } } } diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs deleted file mode 100644 index f61ebd5a3a8dc..0000000000000 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ /dev/null @@ -1,30 +0,0 @@ -use rustc_span::Symbol; -use rustc_target::spec::abi::Abi; - -use crate::*; -use shims::foreign_items::EmulateForeignItemResult; - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} - -pub fn is_dyn_sym(_name: &str) -> bool { - false -} - -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - #[allow(unused, clippy::match_single_binding)] // there isn't anything here yet - fn emulate_foreign_item_inner( - &mut self, - link_name: Symbol, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { - let this = self.eval_context_mut(); - - match link_name.as_str() { - _ => return Ok(EmulateForeignItemResult::NotSupported), - } - - Ok(EmulateForeignItemResult::NeedsJumping) - } -} diff --git a/src/tools/miri/src/shims/unix/android/mod.rs b/src/tools/miri/src/shims/unix/android/mod.rs deleted file mode 100644 index 09c6507b24f84..0000000000000 --- a/src/tools/miri/src/shims/unix/android/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index c013d27502927..23342c8045e80 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -15,7 +15,6 @@ use shims::unix::mem::EvalContextExt as _; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; -use shims::unix::android::foreign_items as android; use shims::unix::freebsd::foreign_items as freebsd; use shims::unix::linux::foreign_items as linux; use shims::unix::macos::foreign_items as macos; @@ -27,14 +26,15 @@ fn is_dyn_sym(name: &str, target_os: &str) -> bool { // `signal` is set up as a weak symbol in `init_extern_statics` (on Android) so we might as // well allow it in `dlsym`. "signal" => true, + // needed at least on macOS to avoid file-based fallback in getrandom + "getentropy" => true, // Give specific OSes a chance to allow their symbols. _ => match target_os { - "android" => android::is_dyn_sym(name), "freebsd" => freebsd::is_dyn_sym(name), "linux" => linux::is_dyn_sym(name), "macos" => macos::is_dyn_sym(name), - target_os => panic!("unsupported Unix OS {target_os}"), + _ => false, }, } } @@ -161,6 +161,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "ftruncate64" => { let [fd, length] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let length = this.read_scalar(length)?.to_i64()?; + let result = this.ftruncate64(fd, length.into())?; + this.write_scalar(result, dest)?; + } + "ftruncate" => { + let [fd, length] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } @@ -250,6 +260,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(result, dest)?; } + "reallocarray" => { + // Currently this function does not exist on all Unixes, e.g. on macOS. + if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd") { + throw_unsup_format!( + "`reallocarray` is not supported on {}", + this.tcx.sess.target.os + ); + } + let [ptr, nmemb, size] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let nmemb = this.read_target_usize(nmemb)?; + let size = this.read_target_usize(size)?; + // reallocarray checks a possible overflow and returns ENOMEM + // if that happens. + // + // Linux: https://www.unix.com/man-page/linux/3/reallocarray/ + // FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=reallocarray + match nmemb.checked_mul(size) { + None => { + let einval = this.eval_libc("ENOMEM"); + this.set_last_error(einval)?; + this.write_null(dest)?; + } + Some(len) => { + let res = this.realloc(ptr, len, MiriMemoryKind::C)?; + this.write_pointer(res, dest)?; + } + } + } + // Dynamic symbol loading "dlsym" => { let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -525,6 +566,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.getpid()?; this.write_scalar(Scalar::from_i32(result), dest)?; } + "getentropy" => { + // This function is non-standard but exists with the same signature and behavior on + // Linux, macOS, and FreeBSD. + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd") { + throw_unsup_format!( + "`getentropy` is not supported on {}", + this.tcx.sess.target.os + ); + } + + let [buf, bufsize] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let buf = this.read_pointer(buf)?; + let bufsize = this.read_target_usize(bufsize)?; + + // getentropy sets errno to EIO when the buffer size exceeds 256 bytes. + // FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=getentropy&sektion=3&format=html + // Linux: https://man7.org/linux/man-pages/man3/getentropy.3.html + // macOS: https://keith.github.io/xcode-man-pages/getentropy.2.html + if bufsize > 256 { + let err = this.eval_libc("EIO"); + this.set_last_error(err)?; + this.write_scalar(Scalar::from_i32(-1), dest)? + } else { + this.gen_random(buf, bufsize)?; + this.write_scalar(Scalar::from_i32(0), dest)?; + } + } // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. @@ -594,7 +663,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_int(super::UID, dest)?; } - "getpwuid_r" if this.frame_in_std() => { + "getpwuid_r" + if this.frame_in_std() => { let [uid, pwd, buf, buflen, result] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_no_isolation("`getpwuid_r`")?; @@ -634,7 +704,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => { let target_os = &*this.tcx.sess.target.os; return match target_os { - "android" => android::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 869434e8876ed..7c843e106eacf 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -29,13 +29,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "pthread_set_name_np" => { let [thread, name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let max_len = usize::MAX; // freebsd does not seem to have a limit. - let res = this.pthread_setname_np( + let max_len = usize::MAX; // FreeBSD does not seem to have a limit. + // FreeBSD's pthread_set_name_np does not return anything. + this.pthread_setname_np( this.read_scalar(thread)?, this.read_scalar(name)?, max_len, )?; - this.write_scalar(res, dest)?; + } + "pthread_get_name_np" => { + let [thread, name, len] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + // FreeBSD's pthread_get_name_np does not return anything. + this.pthread_getname_np( + this.read_scalar(thread)?, + this.read_scalar(name)?, + this.read_scalar(len)?, + )?; + } + "getrandom" => { + let [ptr, len, flags] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let len = this.read_target_usize(len)?; + let _flags = this.read_scalar(flags)?.to_i32()?; + // flags on freebsd does not really matter + // in practice, GRND_RANDOM does not particularly draw from /dev/random + // since it is the same as to /dev/urandom. + // GRND_INSECURE is only an alias of GRND_NONBLOCK, which + // does not affect the RNG. + // https://man.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2&n=1 + this.gen_random(ptr, len)?; + this.write_scalar(Scalar::from_target_usize(len, this), dest)?; } // errno diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 062623a7f6a60..be30627cf0c32 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -66,11 +66,6 @@ pub trait FileDescriptor: std::fmt::Debug + Any { fn is_tty(&self, _communicate_allowed: bool) -> bool { false } - - #[cfg(unix)] - fn as_unix_host_fd(&self) -> Option { - None - } } impl dyn FileDescriptor { @@ -150,12 +145,6 @@ impl FileDescriptor for FileHandle { Ok(Box::new(FileHandle { file: duplicated, writable: self.writable })) } - #[cfg(unix)] - fn as_unix_host_fd(&self) -> Option { - use std::os::unix::io::AsRawFd; - Some(self.file.as_raw_fd()) - } - fn is_tty(&self, communicate_allowed: bool) -> bool { communicate_allowed && self.file.is_terminal() } @@ -183,11 +172,6 @@ impl FileDescriptor for io::Stdin { Ok(Box::new(io::stdin())) } - #[cfg(unix)] - fn as_unix_host_fd(&self) -> Option { - Some(libc::STDIN_FILENO) - } - fn is_tty(&self, communicate_allowed: bool) -> bool { communicate_allowed && self.is_terminal() } @@ -220,11 +204,6 @@ impl FileDescriptor for io::Stdout { Ok(Box::new(io::stdout())) } - #[cfg(unix)] - fn as_unix_host_fd(&self) -> Option { - Some(libc::STDOUT_FILENO) - } - fn is_tty(&self, communicate_allowed: bool) -> bool { communicate_allowed && self.is_terminal() } @@ -250,11 +229,6 @@ impl FileDescriptor for io::Stderr { Ok(Box::new(io::stderr())) } - #[cfg(unix)] - fn as_unix_host_fd(&self) -> Option { - Some(libc::STDERR_FILENO) - } - fn is_tty(&self, communicate_allowed: bool) -> bool { communicate_allowed && self.is_terminal() } @@ -288,8 +262,8 @@ pub struct FileHandler { pub handles: BTreeMap>, } -impl VisitTags for FileHandler { - fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for FileHandler { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { // All our FileDescriptor do not have any tags. } } @@ -490,12 +464,12 @@ impl Default for DirHandler { } } -impl VisitTags for DirHandler { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { +impl VisitProvenance for DirHandler { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let DirHandler { streams, next_id: _ } = self; for dir in streams.values() { - dir.entry.visit_tags(visit); + dir.entry.visit_provenance(visit); } } } @@ -1504,16 +1478,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn ftruncate64( - &mut self, - fd_op: &OpTy<'tcx, Provenance>, - length_op: &OpTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, Scalar> { + fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let fd = this.read_scalar(fd_op)?.to_i32()?; - let length = this.read_scalar(length_op)?.to_i64()?; - // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`ftruncate64`", reject_with)?; diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs index ff25b8120b1c0..10e06226b3fca 100644 --- a/src/tools/miri/src/shims/unix/linux/sync.rs +++ b/src/tools/miri/src/shims/unix/linux/sync.rs @@ -182,10 +182,10 @@ pub fn futex<'tcx>( dest: PlaceTy<'tcx, Provenance>, } - impl<'tcx> VisitTags for Callback<'tcx> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { + impl<'tcx> VisitProvenance for Callback<'tcx> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let Callback { thread: _, addr_usize: _, dest } = self; - dest.visit_tags(visit); + dest.visit_provenance(visit); } } diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 5881a3f46f295..07e19cadd6e32 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -6,8 +6,8 @@ use shims::foreign_items::EmulateForeignItemResult; use shims::unix::fs::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; -pub fn is_dyn_sym(name: &str) -> bool { - matches!(name, "getentropy") +pub fn is_dyn_sym(_name: &str) -> bool { + false } impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} @@ -72,13 +72,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.lseek64(fd, offset, whence)?; this.write_scalar(result, dest)?; } - "ftruncate" => { - let [fd, length] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // macOS is 64bit-only, so this is ftruncate64 - let result = this.ftruncate64(fd, length)?; - this.write_scalar(result, dest)?; - } "realpath$DARWIN_EXTSN" => { let [path, resolved_path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -113,18 +106,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(result, dest)?; } - // Random generation related shims - "getentropy" => { - let [buf, bufsize] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let buf = this.read_pointer(buf)?; - let bufsize = this.read_target_usize(bufsize)?; - - this.gen_random(buf, bufsize)?; - - this.write_scalar(Scalar::from_i32(0), dest)?; // KERN_SUCCESS - } - // Access to command-line arguments "_NSGetArgc" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs index a33d784d16651..cf36d4b191c7b 100644 --- a/src/tools/miri/src/shims/unix/mem.rs +++ b/src/tools/miri/src/shims/unix/mem.rs @@ -7,7 +7,7 @@ //! equivalent. That is the only part we support: no MAP_FIXED or MAP_SHARED or anything //! else that goes beyond a basic allocation API. -use crate::*; +use crate::{helpers::round_to_next_multiple_of, *}; use rustc_target::abi::Size; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} @@ -89,7 +89,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } let align = this.machine.page_align(); - let map_length = this.machine.round_up_to_multiple_of_page_size(length).unwrap_or(u64::MAX); + let map_length = round_to_next_multiple_of(length, this.machine.page_size); let ptr = this.allocate_ptr(Size::from_bytes(map_length), align, MiriMemoryKind::Mmap.into())?; @@ -123,7 +123,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(Scalar::from_i32(-1)); } - let length = this.machine.round_up_to_multiple_of_page_size(length).unwrap_or(u64::MAX); + let length = round_to_next_multiple_of(length, this.machine.page_size); let ptr = Machine::ptr_from_addr_cast(this, addr)?; diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index 2f8014933521f..638473da02b77 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -5,7 +5,6 @@ mod mem; mod sync; mod thread; -mod android; mod freebsd; mod linux; mod macos; diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 6666ffbd1d578..45b47450b7b2c 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -277,6 +277,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_mutexattr_init` is not supported on {}", + this.tcx.sess.target.os + ); + } + let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"); mutexattr_set_kind(this, attr_op, default_kind)?; @@ -359,6 +366,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_mutex_init` is not supported on {}", + this.tcx.sess.target.os + ); + } + let attr = this.read_pointer(attr_op)?; let kind = if this.ptr_is_null(attr)? { this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT") @@ -513,6 +527,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_rwlock_rdlock` is not supported on {}", + this.tcx.sess.target.os + ); + } + let id = rwlock_get_id(this, rwlock_op)?; let active_thread = this.get_active_thread(); @@ -531,6 +552,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_rwlock_tryrdlock` is not supported on {}", + this.tcx.sess.target.os + ); + } + let id = rwlock_get_id(this, rwlock_op)?; let active_thread = this.get_active_thread(); @@ -548,6 +576,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_rwlock_wrlock` is not supported on {}", + this.tcx.sess.target.os + ); + } + let id = rwlock_get_id(this, rwlock_op)?; let active_thread = this.get_active_thread(); @@ -578,6 +613,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_rwlock_trywrlock` is not supported on {}", + this.tcx.sess.target.os + ); + } + let id = rwlock_get_id(this, rwlock_op)?; let active_thread = this.get_active_thread(); @@ -595,6 +637,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_rwlock_unlock` is not supported on {}", + this.tcx.sess.target.os + ); + } + let id = rwlock_get_id(this, rwlock_op)?; let active_thread = this.get_active_thread(); @@ -614,6 +663,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_rwlock_destroy` is not supported on {}", + this.tcx.sess.target.os + ); + } + let id = rwlock_get_id(this, rwlock_op)?; if this.rwlock_is_locked(id) { @@ -638,6 +694,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_condattr_init` is not supported on {}", + this.tcx.sess.target.os + ); + } + // The default value of the clock attribute shall refer to the system // clock. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html @@ -704,6 +767,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); + if !matches!(&*this.tcx.sess.target.os, "linux" | "macos") { + throw_unsup_format!( + "`pthread_cond_init` is not supported on {}", + this.tcx.sess.target.os + ); + } + let attr = this.read_pointer(attr_op)?; let clock_id = if this.ptr_is_null(attr)? { this.eval_libc_i32("CLOCK_REALTIME") @@ -816,10 +886,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { dest: PlaceTy<'tcx, Provenance>, } - impl<'tcx> VisitTags for Callback<'tcx> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { + impl<'tcx> VisitProvenance for Callback<'tcx> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let Callback { active_thread: _, mutex_id: _, id: _, dest } = self; - dest.visit_tags(visit); + dest.visit_provenance(visit); } } diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 2c9603097c857..2b9801fea68e6 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -204,10 +204,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { pending_place: PlaceTy<'tcx, Provenance>, } - impl<'tcx> VisitTags for Callback<'tcx> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { + impl<'tcx> VisitProvenance for Callback<'tcx> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let Callback { init_once_id: _, pending_place } = self; - pending_place.visit_tags(visit); + pending_place.visit_provenance(visit); } } @@ -337,10 +337,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { dest: PlaceTy<'tcx, Provenance>, } - impl<'tcx> VisitTags for Callback<'tcx> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { + impl<'tcx> VisitProvenance for Callback<'tcx> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let Callback { thread: _, addr: _, dest } = self; - dest.visit_tags(visit); + dest.visit_provenance(visit); } } @@ -441,10 +441,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { dest: PlaceTy<'tcx, Provenance>, } - impl<'tcx> VisitTags for Callback<'tcx> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { + impl<'tcx> VisitProvenance for Callback<'tcx> { + fn visit_provenance(&self, visit: &mut VisitWith<'_>) { let Callback { thread: _, condvar_id: _, lock_id: _, mode: _, dest } = self; - dest.visit_tags(visit); + dest.visit_provenance(visit); } } diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs index aef930595b2d3..fb0b701512708 100644 --- a/src/tools/miri/src/shims/x86/aesni.rs +++ b/src/tools/miri/src/shims/x86/aesni.rs @@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "aes")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.aesni.").unwrap(); diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index d88a3127eccc5..2ae269db41278 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir; +use rustc_middle::{mir, ty}; use rustc_span::Symbol; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; @@ -119,53 +119,32 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } } -/// Floating point comparison operation -/// -/// -/// -/// -/// -#[derive(Copy, Clone)] -enum FloatCmpOp { - Eq, - Lt, - Le, - Unord, - Neq, - /// Not less-than - Nlt, - /// Not less-or-equal - Nle, - /// Ordered, i.e. neither of them is NaN - Ord, -} - -impl FloatCmpOp { - /// Convert from the `imm` argument used to specify the comparison - /// operation in intrinsics such as `llvm.x86.sse.cmp.ss`. - fn from_intrinsic_imm(imm: i8, intrinsic: &str) -> InterpResult<'_, Self> { - match imm { - 0 => Ok(Self::Eq), - 1 => Ok(Self::Lt), - 2 => Ok(Self::Le), - 3 => Ok(Self::Unord), - 4 => Ok(Self::Neq), - 5 => Ok(Self::Nlt), - 6 => Ok(Self::Nle), - 7 => Ok(Self::Ord), - imm => { - throw_unsup_format!("invalid `imm` parameter of {intrinsic}: {imm}"); - } - } - } -} - #[derive(Copy, Clone)] enum FloatBinOp { /// Arithmetic operation Arith(mir::BinOp), /// Comparison - Cmp(FloatCmpOp), + /// + /// The semantics of this operator is a case distinction: we compare the two operands, + /// and then we return one of the four booleans `gt`, `lt`, `eq`, `unord` depending on + /// which class they fall into. + /// + /// AVX supports all 16 combinations, SSE only a subset + /// + /// + /// + /// + /// + Cmp { + /// Result when lhs < rhs + gt: bool, + /// Result when lhs > rhs + lt: bool, + /// Result when lhs == rhs + eq: bool, + /// Result when lhs is NaN or rhs is NaN + unord: bool, + }, /// Minimum value (with SSE semantics) /// /// @@ -182,6 +161,51 @@ enum FloatBinOp { Max, } +impl FloatBinOp { + /// Convert from the `imm` argument used to specify the comparison + /// operation in intrinsics such as `llvm.x86.sse.cmp.ss`. + fn cmp_from_imm<'tcx>( + this: &crate::MiriInterpCx<'_, 'tcx>, + imm: i8, + intrinsic: Symbol, + ) -> InterpResult<'tcx, Self> { + // Only bits 0..=4 are used, remaining should be zero. + if imm & !0b1_1111 != 0 { + throw_unsup_format!("invalid `imm` parameter of {intrinsic}: 0x{imm:x}"); + } + // Bit 4 specifies whether the operation is quiet or signaling, which + // we do not care in Miri. + // Bits 0..=2 specifies the operation. + // `gt` indicates the result to be returned when the LHS is strictly + // greater than the RHS, and so on. + let (gt, lt, eq, mut unord) = match imm & 0b111 { + // Equal + 0x0 => (false, false, true, false), + // Less-than + 0x1 => (false, true, false, false), + // Less-or-equal + 0x2 => (false, true, true, false), + // Unordered (either is NaN) + 0x3 => (false, false, false, true), + // Not equal + 0x4 => (true, true, false, true), + // Not less-than + 0x5 => (true, false, true, true), + // Not less-or-equal + 0x6 => (true, false, false, true), + // Ordered (neither is NaN) + 0x7 => (true, true, true, false), + _ => unreachable!(), + }; + // When bit 3 is 1 (only possible in AVX), unord is toggled. + if imm & 0b1000 != 0 { + this.expect_target_feature_for_intrinsic(intrinsic, "avx")?; + unord = !unord; + } + Ok(Self::Cmp { gt, lt, eq, unord }) + } +} + /// Performs `which` scalar operation on `left` and `right` and returns /// the result. fn bin_op_float<'tcx, F: rustc_apfloat::Float>( @@ -195,20 +219,15 @@ fn bin_op_float<'tcx, F: rustc_apfloat::Float>( let res = this.wrapping_binary_op(which, left, right)?; Ok(res.to_scalar()) } - FloatBinOp::Cmp(which) => { + FloatBinOp::Cmp { gt, lt, eq, unord } => { let left = left.to_scalar().to_float::()?; let right = right.to_scalar().to_float::()?; - // FIXME: Make sure that these operations match the semantics - // of cmpps/cmpss/cmppd/cmpsd - let res = match which { - FloatCmpOp::Eq => left == right, - FloatCmpOp::Lt => left < right, - FloatCmpOp::Le => left <= right, - FloatCmpOp::Unord => left.is_nan() || right.is_nan(), - FloatCmpOp::Neq => left != right, - FloatCmpOp::Nlt => !(left < right), - FloatCmpOp::Nle => !(left <= right), - FloatCmpOp::Ord => !left.is_nan() && !right.is_nan(), + + let res = match left.partial_cmp(&right) { + None => unord, + Some(std::cmp::Ordering::Less) => lt, + Some(std::cmp::Ordering::Equal) => eq, + Some(std::cmp::Ordering::Greater) => gt, }; Ok(bool_to_simd_element(res, Size::from_bits(F::BITS))) } @@ -312,6 +331,43 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>( Ok(()) } +/// Converts each element of `op` from floating point to signed integer. +/// +/// When the input value is NaN or out of range, fall back to minimum value. +/// +/// If `op` has more elements than `dest`, extra elements are ignored. If `op` +/// has less elements than `dest`, the rest is filled with zeros. +fn convert_float_to_int<'tcx>( + this: &mut crate::MiriInterpCx<'_, 'tcx>, + op: &OpTy<'tcx, Provenance>, + rnd: rustc_apfloat::Round, + dest: &PlaceTy<'tcx, Provenance>, +) -> InterpResult<'tcx, ()> { + let (op, op_len) = this.operand_to_simd(op)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + // Output must be *signed* integers. + assert!(matches!(dest.layout.field(this, 0).ty.kind(), ty::Int(_))); + + for i in 0..op_len.min(dest_len) { + let op = this.read_immediate(&this.project_index(&op, i)?)?; + let dest = this.project_index(&dest, i)?; + + let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| { + // Fallback to minimum acording to SSE/AVX semantics. + ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout) + }); + this.write_immediate(*res, &dest)?; + } + // Fill remainder with zeros + for i in op_len..dest_len { + let dest = this.project_index(&dest, i)?; + this.write_scalar(Scalar::from_int(0, dest.layout.size), &dest)?; + } + + Ok(()) +} + /// Horizontaly performs `which` operation on adjacent values of /// `left` and `right` SIMD vectors and stores the result in `dest`. fn horizontal_bin_op<'tcx>( diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 831228b7a26cc..6e06f62b34c3e 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -5,7 +5,7 @@ use rustc_target::spec::abi::Abi; use rand::Rng as _; -use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp}; +use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp}; use crate::*; use shims::foreign_items::EmulateForeignItemResult; @@ -21,6 +21,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sse")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse.").unwrap(); // All these intrinsics operate on 128-bit (f32x4) SIMD vectors unless stated otherwise. @@ -95,33 +96,37 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: unary_op_ps(this, which, op, dest)?; } - // Used to implement the _mm_cmp_ss function. + // Used to implement the _mm_cmp*_ss functions. // Performs a comparison operation on the first component of `left` // and `right`, returning 0 if false or `u32::MAX` if true. The remaining // components are copied from `left`. + // _mm_cmp_ss is actually an AVX function where the operation is specified + // by a const parameter. + // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ss are SSE functions + // with hard-coded operations. "cmp.ss" => { let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm( - this.read_scalar(imm)?.to_i8()?, - "llvm.x86.sse.cmp.ss", - )?); + let which = + FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; bin_op_simd_float_first::(this, which, left, right, dest)?; } - // Used to implement the _mm_cmp_ps function. + // Used to implement the _mm_cmp*_ps functions. // Performs a comparison operation on each component of `left` // and `right`. For each component, returns 0 if false or u32::MAX // if true. + // _mm_cmp_ps is actually an AVX function where the operation is specified + // by a const parameter. + // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ps are SSE functions + // with hard-coded operations. "cmp.ps" => { let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm( - this.read_scalar(imm)?.to_i8()?, - "llvm.x86.sse.cmp.ps", - )?); + let which = + FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; bin_op_simd_float_all::(this, which, left, right, dest)?; } @@ -163,7 +168,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, _) = this.operand_to_simd(op)?; - let op = this.read_scalar(&this.project_index(&op, 0)?)?.to_f32()?; + let op = this.read_immediate(&this.project_index(&op, 0)?)?; let rnd = match unprefixed_name { // "current SSE rounding mode", assume nearest @@ -175,7 +180,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: _ => unreachable!(), }; - let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { + let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| { // Fallback to minimum acording to SSE semantics. ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout) }); diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 3f2b9f5f0adfe..49bf7547ab0d5 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::spec::abi::Abi; -use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp}; +use super::{bin_op_simd_float_all, bin_op_simd_float_first, convert_float_to_int, FloatBinOp}; use crate::*; use shims::foreign_items::EmulateForeignItemResult; @@ -20,6 +20,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sse2")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse2.").unwrap(); @@ -259,37 +260,42 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_u64(res), &dest)?; } } - // Used to implement the _mm_cvtps_epi32 and _mm_cvttps_epi32 functions. - // Converts packed f32 to packed i32. - "cvtps2dq" | "cvttps2dq" => { + // Used to implement the _mm_cvtps_epi32, _mm_cvttps_epi32, _mm_cvtpd_epi32 + // and _mm_cvttpd_epi32 functions. + // Converts packed f32/f64 to packed i32. + "cvtps2dq" | "cvttps2dq" | "cvtpd2dq" | "cvttpd2dq" => { let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; - - assert_eq!(dest_len, op_len); + let (op_len, _) = op.layout.ty.simd_size_and_type(*this.tcx); + let (dest_len, _) = dest.layout.ty.simd_size_and_type(*this.tcx); + match unprefixed_name { + "cvtps2dq" | "cvttps2dq" => { + // f32x4 to i32x4 conversion + assert_eq!(op_len, 4); + assert_eq!(dest_len, op_len); + } + "cvtpd2dq" | "cvttpd2dq" => { + // f64x2 to i32x4 conversion + // the last two values are filled with zeros + assert_eq!(op_len, 2); + assert_eq!(dest_len, 4); + } + _ => unreachable!(), + } let rnd = match unprefixed_name { // "current SSE rounding mode", assume nearest // https://www.felixcloutier.com/x86/cvtps2dq - "cvtps2dq" => rustc_apfloat::Round::NearestTiesToEven, + // https://www.felixcloutier.com/x86/cvtpd2dq + "cvtps2dq" | "cvtpd2dq" => rustc_apfloat::Round::NearestTiesToEven, // always truncate // https://www.felixcloutier.com/x86/cvttps2dq - "cvttps2dq" => rustc_apfloat::Round::TowardZero, + // https://www.felixcloutier.com/x86/cvttpd2dq + "cvttps2dq" | "cvttpd2dq" => rustc_apfloat::Round::TowardZero, _ => unreachable!(), }; - for i in 0..dest_len { - let op = this.read_scalar(&this.project_index(&op, i)?)?.to_f32()?; - let dest = this.project_index(&dest, i)?; - - let res = - this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { - // Fallback to minimum acording to SSE2 semantics. - ImmTy::from_int(i32::MIN, this.machine.layouts.i32) - }); - this.write_immediate(*res, &dest)?; - } + convert_float_to_int(this, op, rnd, dest)?; } // Used to implement the _mm_packs_epi16 function. // Converts two 16-bit integer vectors to a single 8-bit integer @@ -461,18 +467,20 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(res, &dest)?; } } - // Used to implement the _mm_cmp*_sd function. + // Used to implement the _mm_cmp*_sd functions. // Performs a comparison operation on the first component of `left` // and `right`, returning 0 if false or `u64::MAX` if true. The remaining // components are copied from `left`. + // _mm_cmp_sd is actually an AVX function where the operation is specified + // by a const parameter. + // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_sd are SSE2 functions + // with hard-coded operations. "cmp.sd" => { let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm( - this.read_scalar(imm)?.to_i8()?, - "llvm.x86.sse2.cmp.sd", - )?); + let which = + FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; bin_op_simd_float_first::(this, which, left, right, dest)?; } @@ -480,14 +488,16 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // Performs a comparison operation on each component of `left` // and `right`. For each component, returns 0 if false or `u64::MAX` // if true. + // _mm_cmp_pd is actually an AVX function where the operation is specified + // by a const parameter. + // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_pd are SSE2 functions + // with hard-coded operations. "cmp.pd" => { let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm( - this.read_scalar(imm)?.to_i8()?, - "llvm.x86.sse2.cmp.pd", - )?); + let which = + FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; bin_op_simd_float_all::(this, which, left, right, dest)?; } @@ -522,45 +532,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: }; this.write_scalar(Scalar::from_i32(i32::from(res)), dest)?; } - // Used to implement the _mm_cvtpd_epi32 and _mm_cvttpd_epi32 functions. - // Converts packed f64 to packed i32. - "cvtpd2dq" | "cvttpd2dq" => { - let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - - let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; - - // op is f64x2, dest is i32x4 - assert_eq!(op_len, 2); - assert_eq!(dest_len, 4); - - let rnd = match unprefixed_name { - // "current SSE rounding mode", assume nearest - // https://www.felixcloutier.com/x86/cvtpd2dq - "cvtpd2dq" => rustc_apfloat::Round::NearestTiesToEven, - // always truncate - // https://www.felixcloutier.com/x86/cvttpd2dq - "cvttpd2dq" => rustc_apfloat::Round::TowardZero, - _ => unreachable!(), - }; - - for i in 0..op_len { - let op = this.read_scalar(&this.project_index(&op, i)?)?.to_f64()?; - let dest = this.project_index(&dest, i)?; - - let res = - this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { - // Fallback to minimum acording to SSE2 semantics. - ImmTy::from_int(i32::MIN, this.machine.layouts.i32) - }); - this.write_immediate(*res, &dest)?; - } - // Fill the remaining with zeros - for i in op_len..dest_len { - let dest = this.project_index(&dest, i)?; - this.write_scalar(Scalar::from_i32(0), &dest)?; - } - } // Use to implement the _mm_cvtsd_si32, _mm_cvttsd_si32, // _mm_cvtsd_si64 and _mm_cvttsd_si64 functions. // Converts the first component of `op` from f64 to i32/i64. @@ -568,7 +539,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, _) = this.operand_to_simd(op)?; - let op = this.read_scalar(&this.project_index(&op, 0)?)?.to_f64()?; + let op = this.read_immediate(&this.project_index(&op, 0)?)?; let rnd = match unprefixed_name { // "current SSE rounding mode", assume nearest @@ -580,7 +551,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: _ => unreachable!(), }; - let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { + let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| { // Fallback to minimum acording to SSE semantics. ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout) }); diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 270da36f0e32c..99a7a4f2f88ab 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sse3")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap(); diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index cfa06ded6e681..b3d1056ab06d6 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse41.").unwrap(); @@ -148,6 +149,14 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: round_first::(this, left, right, rounding, dest)?; } + // Used to implement the _mm_floor_ps, _mm_ceil_ps and _mm_round_ps + // functions. Rounds the elements of `op` according to `rounding`. + "round.ps" => { + let [op, rounding] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + round_all::(this, op, rounding, dest)?; + } // Used to implement the _mm_floor_sd, _mm_ceil_sd and _mm_round_sd // functions. Rounds the first element of `right` according to `rounding` // and copies the remaining elements from `left`. @@ -157,6 +166,14 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: round_first::(this, left, right, rounding, dest)?; } + // Used to implement the _mm_floor_pd, _mm_ceil_pd and _mm_round_pd + // functions. Rounds the elements of `op` according to `rounding`. + "round.pd" => { + let [op, rounding] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + round_all::(this, op, rounding, dest)?; + } // Used to implement the _mm_minpos_epu16 function. // Find the minimum unsinged 16-bit integer in `op` and // returns its value and position. @@ -183,7 +200,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: Scalar::from_u16(min_index.try_into().unwrap()), &this.project_index(&dest, 1)?, )?; - // Fill remaining with zeros + // Fill remainder with zeros for i in 2..dest_len { this.write_scalar(Scalar::from_u16(0), &this.project_index(&dest, i)?)?; } @@ -283,22 +300,7 @@ fn round_first<'tcx, F: rustc_apfloat::Float>( assert_eq!(dest_len, left_len); assert_eq!(dest_len, right_len); - // The fourth bit of `rounding` only affects the SSE status - // register, which cannot be accessed from Miri (or from Rust, - // for that matter), so we can ignore it. - let rounding = match this.read_scalar(rounding)?.to_i32()? & !0b1000 { - // When the third bit is 0, the rounding mode is determined by the - // first two bits. - 0b000 => rustc_apfloat::Round::NearestTiesToEven, - 0b001 => rustc_apfloat::Round::TowardNegative, - 0b010 => rustc_apfloat::Round::TowardPositive, - 0b011 => rustc_apfloat::Round::TowardZero, - // When the third bit is 1, the rounding mode is determined by the - // SSE status register. Since we do not support modifying it from - // Miri (or Rust), we assume it to be at its default mode (round-to-nearest). - 0b100..=0b111 => rustc_apfloat::Round::NearestTiesToEven, - rounding => throw_unsup_format!("unsupported rounding mode 0x{rounding:02x}"), - }; + let rounding = rounding_from_imm(this.read_scalar(rounding)?.to_i32()?)?; let op0: F = this.read_scalar(&this.project_index(&right, 0)?)?.to_float()?; let res = op0.round_to_integral(rounding).value; @@ -317,3 +319,50 @@ fn round_first<'tcx, F: rustc_apfloat::Float>( Ok(()) } + +// Rounds all elements of `op` according to `rounding`. +fn round_all<'tcx, F: rustc_apfloat::Float>( + this: &mut crate::MiriInterpCx<'_, 'tcx>, + op: &OpTy<'tcx, Provenance>, + rounding: &OpTy<'tcx, Provenance>, + dest: &PlaceTy<'tcx, Provenance>, +) -> InterpResult<'tcx, ()> { + let (op, op_len) = this.operand_to_simd(op)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + assert_eq!(dest_len, op_len); + + let rounding = rounding_from_imm(this.read_scalar(rounding)?.to_i32()?)?; + + for i in 0..dest_len { + let op: F = this.read_scalar(&this.project_index(&op, i)?)?.to_float()?; + let res = op.round_to_integral(rounding).value; + this.write_scalar( + Scalar::from_uint(res.to_bits(), Size::from_bits(F::BITS)), + &this.project_index(&dest, i)?, + )?; + } + + Ok(()) +} + +/// Gets equivalent `rustc_apfloat::Round` from rounding mode immediate of +/// `round.{ss,sd,ps,pd}` intrinsics. +fn rounding_from_imm<'tcx>(rounding: i32) -> InterpResult<'tcx, rustc_apfloat::Round> { + // The fourth bit of `rounding` only affects the SSE status + // register, which cannot be accessed from Miri (or from Rust, + // for that matter), so we can ignore it. + match rounding & !0b1000 { + // When the third bit is 0, the rounding mode is determined by the + // first two bits. + 0b000 => Ok(rustc_apfloat::Round::NearestTiesToEven), + 0b001 => Ok(rustc_apfloat::Round::TowardNegative), + 0b010 => Ok(rustc_apfloat::Round::TowardPositive), + 0b011 => Ok(rustc_apfloat::Round::TowardZero), + // When the third bit is 1, the rounding mode is determined by the + // SSE status register. Since we do not support modifying it from + // Miri (or Rust), we assume it to be at its default mode (round-to-nearest). + 0b100..=0b111 => Ok(rustc_apfloat::Round::NearestTiesToEven), + rounding => throw_unsup_format!("unsupported rounding mode 0x{rounding:02x}"), + } +} diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index dbc2b947b3322..724150fd2fe2d 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "ssse3")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap(); diff --git a/src/tools/miri/src/tag_gc.rs b/src/tools/miri/src/tag_gc.rs deleted file mode 100644 index 3cccdd3635388..0000000000000 --- a/src/tools/miri/src/tag_gc.rs +++ /dev/null @@ -1,169 +0,0 @@ -use either::Either; - -use rustc_data_structures::fx::FxHashSet; - -use crate::*; - -pub trait VisitTags { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)); -} - -impl VisitTags for Option { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - if let Some(x) = self { - x.visit_tags(visit); - } - } -} - -impl VisitTags for std::cell::RefCell { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - self.borrow().visit_tags(visit) - } -} - -impl VisitTags for BorTag { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - visit(*self) - } -} - -impl VisitTags for Provenance { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - if let Provenance::Concrete { tag, .. } = self { - visit(*tag); - } - } -} - -impl VisitTags for Pointer { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - let (prov, _offset) = self.into_parts(); - prov.visit_tags(visit); - } -} - -impl VisitTags for Pointer> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - let (prov, _offset) = self.into_parts(); - prov.visit_tags(visit); - } -} - -impl VisitTags for Scalar { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - match self { - Scalar::Ptr(ptr, _) => ptr.visit_tags(visit), - Scalar::Int(_) => (), - } - } -} - -impl VisitTags for Immediate { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - match self { - Immediate::Scalar(s) => { - s.visit_tags(visit); - } - Immediate::ScalarPair(s1, s2) => { - s1.visit_tags(visit); - s2.visit_tags(visit); - } - Immediate::Uninit => {} - } - } -} - -impl VisitTags for MemPlaceMeta { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - match self { - MemPlaceMeta::Meta(m) => m.visit_tags(visit), - MemPlaceMeta::None => {} - } - } -} - -impl VisitTags for ImmTy<'_, Provenance> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - (**self).visit_tags(visit) - } -} - -impl VisitTags for MPlaceTy<'_, Provenance> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - self.ptr().visit_tags(visit); - self.meta().visit_tags(visit); - } -} - -impl VisitTags for PlaceTy<'_, Provenance> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - match self.as_mplace_or_local() { - Either::Left(mplace) => mplace.visit_tags(visit), - Either::Right(_) => (), - } - } -} - -impl VisitTags for OpTy<'_, Provenance> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - match self.as_mplace_or_imm() { - Either::Left(mplace) => mplace.visit_tags(visit), - Either::Right(imm) => imm.visit_tags(visit), - } - } -} - -impl VisitTags for Allocation> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - for prov in self.provenance().provenances() { - prov.visit_tags(visit); - } - - self.extra.visit_tags(visit); - } -} - -impl VisitTags for crate::MiriInterpCx<'_, '_> { - fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) { - // Memory. - self.memory.alloc_map().iter(|it| { - for (_id, (_kind, alloc)) in it { - alloc.visit_tags(visit); - } - }); - - // And all the other machine values. - self.machine.visit_tags(visit); - } -} - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { - fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - // No reason to do anything at all if stacked borrows is off. - if this.machine.borrow_tracker.is_none() { - return Ok(()); - } - - let mut tags = FxHashSet::default(); - this.visit_tags(&mut |tag| { - tags.insert(tag); - }); - self.remove_unreachable_tags(tags); - - Ok(()) - } - - fn remove_unreachable_tags(&mut self, tags: FxHashSet) { - let this = self.eval_context_mut(); - this.memory.alloc_map().iter(|it| { - for (_id, (_kind, alloc)) in it { - if let Some(bt) = &alloc.extra.borrow_tracker { - bt.remove_unreachable_tags(&tags); - } - } - }); - } -} diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index 670f5c895cbd6..d54560608dc1e 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -12,8 +12,8 @@ edition = "2021" libc = "0.2" num_cpus = "1.10.1" -getrandom_1 = { package = "getrandom", version = "0.1" } -getrandom = { version = "0.2", features = ["js"] } +getrandom_01 = { package = "getrandom", version = "0.1" } +getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] } rand = { version = "0.8", features = ["small_rng"] } [target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies] diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index dbf559631eacb..91df4985c0f0c 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -79,6 +79,11 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> program.args.push(flag); } + // Add a test env var to do environment communication tests. + program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into()))); + // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find). + program.envs.push(("MIRI_TEMP".into(), Some(env::temp_dir().into()))); + let mut config = Config { target: Some(target.to_owned()), stderr_filters: STDERR.clone(), @@ -232,11 +237,6 @@ fn main() -> Result<()> { } } - // Add a test env var to do environment communication tests. - env::set_var("MIRI_ENV_VAR_TEST", "0"); - // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find). - env::set_var("MIRI_TEMP", env::temp_dir()); - ui(Mode::Pass, "tests/pass", &target, WithoutDependencies)?; ui(Mode::Pass, "tests/pass-dep", &target, WithDependencies)?; ui(Mode::Panic, "tests/panic", &target, WithDependencies)?; diff --git a/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr b/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr index e9bc322047195..c031cb0146ad6 100644 --- a/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr +++ b/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr @@ -10,5 +10,5 @@ LL | foo(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.stderr index c5093c0e60113..078b7d2e0d846 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_main_terminate.stderr @@ -2,5 +2,5 @@ error: the main thread terminated without waiting for all remaining threads note: pass `-Zmiri-ignore-leaks` to disable this check -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr index c2de4afd68fa6..383b93024bbde 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr @@ -10,5 +10,5 @@ LL | panic!() = note: inside `thread_start` at RUSTLIB/core/src/panic.rs:LL:CC = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr index 85ae930d439bb..70a565ee7c71d 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr @@ -10,5 +10,5 @@ LL | panic!() = note: inside `thread_start` at RUSTLIB/core/src/panic.rs:LL:CC = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.stderr index 763e0d3665d8f..7238dfb40b723 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_detached.stderr @@ -11,5 +11,5 @@ LL | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr index a3253e2ef933b..e501a086cca4d 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_joined.stderr @@ -11,5 +11,5 @@ LL | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr index 09e14d46a967f..b2edabd7cc984 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_main.stderr @@ -11,5 +11,5 @@ LL | assert_eq!(libc::pthread_join(thread_id, ptr::null_mut()), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.stderr index db5d7bfd5daef..605d6cdf0a41b 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.stderr @@ -11,5 +11,5 @@ LL | ... assert_eq!(libc::pthread_join(native_copy, ptr::null_mut()), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_self.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_self.stderr index 8db4a83f9cebb..9ec749acddd91 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_self.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_self.stderr @@ -11,5 +11,5 @@ LL | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.stderr b/src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.stderr index fccd3fbbc9da7..2339bab3e9f84 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/unwind_top_of_stack.stderr @@ -17,5 +17,5 @@ LL | | } = note: BACKTRACE: = note: inside `thread_start` at $DIR/unwind_top_of_stack.rs:LL:CC -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs new file mode 100644 index 0000000000000..2b9e7a34d6543 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs @@ -0,0 +1,17 @@ +//@compile-flags: -Zmiri-disable-isolation -Zmiri-preemption-rate=0 +//@ignore-target-windows: No libc on Windows + +use std::env; +use std::thread; + +fn main() { + let t = thread::spawn(|| unsafe { + // Access the environment in another thread without taking the env lock. + // This represents some C code that queries the environment. + libc::getenv(b"TZ\0".as_ptr().cast()); //~ERROR: Data race detected + }); + // Meanwhile, the main thread uses the "safe" Rust env accessor. + env::set_var("MY_RUST_VAR", "Ferris"); + + t.join().unwrap(); +} diff --git a/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr new file mode 100644 index 0000000000000..b81e8db9e0c98 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic read on thread `` at ALLOC. (2) just happened here + --> $DIR/env-set_var-data-race.rs:LL:CC + | +LL | libc::getenv(b"TZ/0".as_ptr().cast()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic read on thread `` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/env-set_var-data-race.rs:LL:CC + | +LL | env::set_var("MY_RUST_VAR", "Ferris"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 (of the first span): + = note: inside closure at $DIR/env-set_var-data-race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr b/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr index 02f1eee97fc04..7547ec417194c 100644 --- a/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr +++ b/src/tools/miri/tests/fail-dep/shims/fs/close_stdout.stderr @@ -10,5 +10,5 @@ LL | libc::close(1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/fs/isolated_stdin.stderr b/src/tools/miri/tests/fail-dep/shims/fs/isolated_stdin.stderr index ed826147e3bdb..1d6626dda704f 100644 --- a/src/tools/miri/tests/fail-dep/shims/fs/isolated_stdin.stderr +++ b/src/tools/miri/tests/fail-dep/shims/fs/isolated_stdin.stderr @@ -11,5 +11,5 @@ LL | libc::read(0, bytes.as_mut_ptr() as *mut libc::c_void, 512); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/fs/mkstemp_immutable_arg.stderr b/src/tools/miri/tests/fail-dep/shims/fs/mkstemp_immutable_arg.stderr index 35ff1926b0657..7a2757557ef1a 100644 --- a/src/tools/miri/tests/fail-dep/shims/fs/mkstemp_immutable_arg.stderr +++ b/src/tools/miri/tests/fail-dep/shims/fs/mkstemp_immutable_arg.stderr @@ -16,5 +16,5 @@ LL | test_mkstemp_immutable_arg(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr b/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr index bcece7ad4e55d..355e16d5c3498 100644 --- a/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr +++ b/src/tools/miri/tests/fail-dep/shims/fs/read_from_stdout.stderr @@ -10,5 +10,5 @@ LL | libc::read(1, bytes.as_mut_ptr() as *mut libc::c_void, 512); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/fs/unix_open_missing_required_mode.stderr b/src/tools/miri/tests/fail-dep/shims/fs/unix_open_missing_required_mode.stderr index 5a8e7352c7686..0988eefe22237 100644 --- a/src/tools/miri/tests/fail-dep/shims/fs/unix_open_missing_required_mode.stderr +++ b/src/tools/miri/tests/fail-dep/shims/fs/unix_open_missing_required_mode.stderr @@ -16,5 +16,5 @@ LL | test_file_open_missing_needed_mode(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr b/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr index d4a38e1ca9615..e2ebe234b0bb0 100644 --- a/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr +++ b/src/tools/miri/tests/fail-dep/shims/fs/write_to_stdin.stderr @@ -10,5 +10,5 @@ LL | libc::write(0, bytes.as_ptr() as *const libc::c_void, 5); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/memchr_null.stderr b/src/tools/miri/tests/fail-dep/shims/memchr_null.stderr index 54b58f22c6c74..b76722f5f8f19 100644 --- a/src/tools/miri/tests/fail-dep/shims/memchr_null.stderr +++ b/src/tools/miri/tests/fail-dep/shims/memchr_null.stderr @@ -11,5 +11,5 @@ LL | libc::memchr(ptr::null(), 0, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/memcmp_null.stderr b/src/tools/miri/tests/fail-dep/shims/memcmp_null.stderr index 8b2882fc243a5..5c6ba4fd97979 100644 --- a/src/tools/miri/tests/fail-dep/shims/memcmp_null.stderr +++ b/src/tools/miri/tests/fail-dep/shims/memcmp_null.stderr @@ -11,5 +11,5 @@ LL | libc::memcmp(ptr::null(), ptr::null(), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/memcmp_zero.stderr b/src/tools/miri/tests/fail-dep/shims/memcmp_zero.stderr index e21b9b0600830..4ab37ab569fe4 100644 --- a/src/tools/miri/tests/fail-dep/shims/memcmp_zero.stderr +++ b/src/tools/miri/tests/fail-dep/shims/memcmp_zero.stderr @@ -11,5 +11,5 @@ LL | libc::memcmp(ptr.cast(), ptr.cast(), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/memcpy_zero.stderr b/src/tools/miri/tests/fail-dep/shims/memcpy_zero.stderr index 7c1c3fe20c4e5..3e1ee7b86e31f 100644 --- a/src/tools/miri/tests/fail-dep/shims/memcpy_zero.stderr +++ b/src/tools/miri/tests/fail-dep/shims/memcpy_zero.stderr @@ -11,5 +11,5 @@ LL | libc::memcpy(to.cast(), from.cast(), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/memrchr_null.stderr b/src/tools/miri/tests/fail-dep/shims/memrchr_null.stderr index cc11ba89f8fef..0cc7ac19febc4 100644 --- a/src/tools/miri/tests/fail-dep/shims/memrchr_null.stderr +++ b/src/tools/miri/tests/fail-dep/shims/memrchr_null.stderr @@ -11,5 +11,5 @@ LL | libc::memrchr(ptr::null(), 0, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/mmap_invalid_dealloc.stderr b/src/tools/miri/tests/fail-dep/shims/mmap_invalid_dealloc.stderr index 54e0cd5275d58..cec67b6ef8408 100644 --- a/src/tools/miri/tests/fail-dep/shims/mmap_invalid_dealloc.stderr +++ b/src/tools/miri/tests/fail-dep/shims/mmap_invalid_dealloc.stderr @@ -11,5 +11,5 @@ LL | libc::free(ptr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr b/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr index 35d26972839f5..21b4baa500922 100644 --- a/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr +++ b/src/tools/miri/tests/fail-dep/shims/mmap_use_after_munmap.stderr @@ -43,5 +43,5 @@ LL | libc::munmap(ptr, 4096); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/src/tools/miri/tests/fail-dep/shims/munmap.stderr b/src/tools/miri/tests/fail-dep/shims/munmap.stderr index cb47769c063f6..f17473677f636 100644 --- a/src/tools/miri/tests/fail-dep/shims/munmap.stderr +++ b/src/tools/miri/tests/fail-dep/shims/munmap.stderr @@ -35,5 +35,5 @@ LL | | ) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr b/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr index 9a084c504374b..14eb9d32053ce 100644 --- a/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr +++ b/src/tools/miri/tests/fail-dep/shims/munmap_partial.stderr @@ -25,5 +25,5 @@ LL | libc::munmap(ptr, 1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_cond_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_cond_double_destroy.stderr index ecfedf753703d..899c217efbff7 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_cond_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_cond_double_destroy.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_cond_destroy(cond.as_mut_ptr()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.stderr index f39d909adbd64..ef75b03162d79 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_condattr_double_destroy.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_condattr_destroy(attr.as_mut_ptr()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr index 4a138e6f8a25c..3675ce49f30e4 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_NULL_deadlock.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_mutex_lock(&mut mutex as *mut _); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_deadlock.stderr index 599655a8692b1..272bee38b5a10 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_deadlock.stderr @@ -8,5 +8,5 @@ LL | assert_eq!(libc::pthread_mutex_lock(lock_copy.0.get() as *mut _ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_default_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_default_deadlock.stderr index 8aea3f5c6932f..4d41141b545f8 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_default_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_default_deadlock.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_mutex_lock(&mut mutex as *mut _); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_destroy_locked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_destroy_locked.stderr index a8ab948116e14..ed5e27b607a5d 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_destroy_locked.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_destroy_locked.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_mutex_destroy(&mut mutex as *mut _); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_double_destroy.stderr index 9620fdbd18b2f..05b35ee3b30a1 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_double_destroy.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_mutex_destroy(mutex.as_mut_ptr()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_deadlock.stderr index b7877d3aa397d..16de503bebf68 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_deadlock.stderr @@ -8,5 +8,5 @@ LL | libc::pthread_mutex_lock(&mut mutex as *mut _); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr index 754137b85b9af..d717b4ec56b67 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_normal_unlock_unlocked.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_mutex_unlock(&mut mutex as *mut _); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_wrong_owner.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_wrong_owner.stderr index aa81b06fc80af..a1de36db96674 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_wrong_owner.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutex_wrong_owner.stderr @@ -11,5 +11,5 @@ LL | ...t_eq!(libc::pthread_mutex_unlock(lock_copy.0.get() as *mut _), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutexattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutexattr_double_destroy.stderr index 82949047d2aab..a8425e6f81d0f 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutexattr_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_mutexattr_double_destroy.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_mutexattr_destroy(attr.as_mut_ptr()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr index be73e7f1e2ad4..bb90545c5034a 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_read_locked.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_rwlock_destroy(rw.get()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr index bc2713a5ffbfa..7210c6a742ae5 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_destroy_write_locked.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_rwlock_destroy(rw.get()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_double_destroy.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_double_destroy.stderr index 5004f84358da8..5032e98f11619 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_double_destroy.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_rwlock_destroy(&mut lock); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr index 075c8f0ef529c..21383825f81e0 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_write_deadlock_single_thread.stderr @@ -8,5 +8,5 @@ LL | libc::pthread_rwlock_wrlock(rw.get()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr index 7dfa27b43d073..d1b7d5ca1adac 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_read_wrong_owner.stderr @@ -11,5 +11,5 @@ LL | ... assert_eq!(libc::pthread_rwlock_unlock(lock_copy.0.get() as *mut _), note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr index 1c25ac2c048fb..98b09472904b1 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_unlock_unlocked.stderr @@ -11,5 +11,5 @@ LL | libc::pthread_rwlock_unlock(rw.get()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr index 333fb1afb91b7..6271d5cb2ff7a 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock.stderr @@ -8,5 +8,5 @@ LL | assert_eq!(libc::pthread_rwlock_wrlock(lock_copy.0.get() as *mu note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr index caab19a782f97..3d09c6dbce744 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_read_deadlock_single_thread.stderr @@ -8,5 +8,5 @@ LL | libc::pthread_rwlock_rdlock(rw.get()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr index 93bede54fcf18..faaf3f5e9a0d3 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock.stderr @@ -8,5 +8,5 @@ LL | assert_eq!(libc::pthread_rwlock_wrlock(lock_copy.0.get() as *mu note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr index 30f5f447c717c..3dc99a1fd1951 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_write_deadlock_single_thread.stderr @@ -8,5 +8,5 @@ LL | libc::pthread_rwlock_wrlock(rw.get()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr index 5bf402c775ae5..dea2529b86580 100644 --- a/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr +++ b/src/tools/miri/tests/fail-dep/shims/sync/libc_pthread_rwlock_write_wrong_owner.stderr @@ -11,5 +11,5 @@ LL | ... assert_eq!(libc::pthread_rwlock_unlock(lock_copy.0.get() as *mut _), note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr index ac2a984ed514a..59179478c3025 100644 --- a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr +++ b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr @@ -11,5 +11,5 @@ LL | | )) | = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr b/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr index ec2bba6117289..fabe3bbf1216a 100644 --- a/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr +++ b/src/tools/miri/tests/fail-dep/unsupported_incomplete_function.stderr @@ -10,5 +10,5 @@ LL | libc::signal(libc::SIGPIPE, libc::SIG_IGN); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr b/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr index 095eeeb79de7b..40ed093198d30 100644 --- a/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr +++ b/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr @@ -16,5 +16,5 @@ LL | dealloc(x, Layout::from_size_align_unchecked(1, 2)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr b/src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr index 5fe93c841b22c..e9b935d2c83b2 100644 --- a/src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr +++ b/src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr @@ -16,5 +16,5 @@ LL | dealloc(x, Layout::from_size_align_unchecked(2, 1)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr b/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr index 48d63e5905178..76abd96e24afb 100644 --- a/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr +++ b/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr @@ -26,5 +26,5 @@ LL | dealloc(x, Layout::from_size_align_unchecked(1, 1)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr index 62ffb8142a3fb..de76e925c11cf 100644 --- a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr +++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr @@ -17,5 +17,5 @@ LL | System.deallocate(ptr, l); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr index fe6a22fadc9e2..bd2a6c628f9e5 100644 --- a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr +++ b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr @@ -8,5 +8,5 @@ LL | __rust_alloc(1, 1); = note: BACKTRACE: = note: inside `start` at $DIR/no_global_allocator.rs:LL:CC -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr b/src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr index 24cabb395649c..5347e7a95ac4d 100644 --- a/src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr +++ b/src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr @@ -16,5 +16,5 @@ LL | let _y = realloc(x, Layout::from_size_align_unchecked(2, 1), 1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr b/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr index d4e907bd06706..fb3b035b11611 100644 --- a/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr +++ b/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr @@ -21,5 +21,5 @@ LL | let _y = realloc(x, Layout::from_size_align_unchecked(1, 1), 1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr b/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr index 52cc579c1e612..9b8a892620162 100644 --- a/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr +++ b/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr @@ -26,5 +26,5 @@ LL | let _z = realloc(x, Layout::from_size_align_unchecked(1, 1), 1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/stack_free.stderr b/src/tools/miri/tests/fail/alloc/stack_free.stderr index 7c14d372f0c7c..2adec68c0dd84 100644 --- a/src/tools/miri/tests/fail/alloc/stack_free.stderr +++ b/src/tools/miri/tests/fail/alloc/stack_free.stderr @@ -20,5 +20,5 @@ LL | drop(bad_box); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.stack.stderr b/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.stack.stderr index b22db3eb121ee..6903a52f304c7 100644 --- a/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.stack.stderr @@ -24,5 +24,5 @@ LL | *target = 13; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr b/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr index 655f1b5777769..db36d696e1d95 100644 --- a/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr @@ -28,5 +28,5 @@ LL | *target = 13; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr index 678211a700dbc..fe1f7060f1efe 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr @@ -26,5 +26,5 @@ LL | safe_raw(xraw, xraw); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr index 3271a04eae745..4ee154eeb991a 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr @@ -27,5 +27,5 @@ LL | safe_raw(xraw, xraw); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.stack.stderr index 90134ce367a19..c5bdfcb8fe48f 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.stack.stderr @@ -26,5 +26,5 @@ LL | safe_raw(xshr, xraw); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr index f2694b51ca40a..4b15e93165497 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr @@ -27,5 +27,5 @@ LL | safe_raw(xshr, xraw); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.stack.stderr index a457bd9a6accf..b04139f3bd9cb 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.stack.stderr @@ -29,5 +29,5 @@ LL | safe_raw(xraw, xshr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr index 595381c16ad97..7b8082292a1de 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr @@ -27,5 +27,5 @@ LL | safe_raw(xraw, xshr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.stack.stderr index b53ae9bd5504b..383eb086d1efb 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.stack.stderr @@ -26,5 +26,5 @@ LL | safe_raw(xshr, xraw as *mut _); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr index 106e5c19bf277..5dbcd39321855 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr @@ -35,5 +35,5 @@ LL | safe_raw(xshr, xraw as *mut _); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.stack.stderr index 76f4e81f71ba2..bed0b880c3a39 100644 --- a/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.stack.stderr @@ -34,5 +34,5 @@ LL | demo_box_advanced_unique(Box::new(0)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.tree.stderr index 97f82db6fe732..68ed09409bf93 100644 --- a/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.tree.stderr @@ -38,5 +38,5 @@ LL | demo_box_advanced_unique(Box::new(0)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr index 59377aeb971a8..6e87d3ce06b52 100644 --- a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr @@ -26,5 +26,5 @@ LL | test(Box::from_raw(ptr), ptr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr index 1ecd6620806ec..824a2d36fc485 100644 --- a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr @@ -34,5 +34,5 @@ LL | test(Box::from_raw(ptr), ptr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.stack.stderr b/src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.stack.stderr index fa3d7ca367625..d2bf4c6a59c42 100644 --- a/src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.stack.stderr @@ -24,5 +24,5 @@ LL | unsafe { from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len()) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.tree.stderr b/src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.tree.stderr index 9519c83f71c78..4e5a8bbe0e0bb 100644 --- a/src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.tree.stderr @@ -28,5 +28,5 @@ LL | v1[1] = 5; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr index daa4339225dee..71d962a5523f1 100644 --- a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr @@ -33,5 +33,5 @@ LL | let (a, b) = safe::split_at_mut(&mut array, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.tree.stderr b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.tree.stderr index 4fd92df75d652..7fc795db097d8 100644 --- a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.tree.stderr @@ -28,5 +28,5 @@ LL | a[1] = 5; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write1.stack.stderr index c1e4918146587..3a9faeb80eed5 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write1.stack.stderr @@ -19,5 +19,5 @@ LL | let x: *mut u32 = xref as *const _ as *mut _; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write1.tree.stderr index bb72159be65d4..5dd51b5f25770 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write1.tree.stderr @@ -16,5 +16,5 @@ LL | let xref = &*target; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write5.stack.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write5.stack.stderr index c71780b7e03e0..16f8a3cbd02af 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write5.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write5.stack.stderr @@ -24,5 +24,5 @@ LL | unsafe { *xraw = 15 }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write5.tree.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write5.tree.stderr index 05cc69553a007..3698937d6fcc0 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write5.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write5.tree.stderr @@ -28,5 +28,5 @@ LL | unsafe { *xraw = 15 }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr index 3d3d2a24c2852..159b6cc9a8ec1 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr @@ -26,5 +26,5 @@ LL | foo(x, p); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write6.tree.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write6.tree.stderr index 64e08f545e339..37d5147b5d0e6 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write6.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write6.tree.stderr @@ -34,5 +34,5 @@ LL | foo(x, p); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr index 8f677bd547ce3..5d093aeae88f5 100644 --- a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr @@ -26,5 +26,5 @@ LL | inner(xraw, xref); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.tree.stderr index 66f7f1788e4d5..4ba80e13318a9 100644 --- a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.tree.stderr @@ -28,5 +28,5 @@ LL | inner(xraw, xref); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr index 1648ca9e58bb1..f6eeef33e9ee9 100644 --- a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr @@ -26,5 +26,5 @@ LL | inner(ptr, &*ptr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.tree.stderr b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.tree.stderr index ef807d7362e44..5a8fbe4ce5bcc 100644 --- a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector3.tree.stderr @@ -28,5 +28,5 @@ LL | inner(ptr, &*ptr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr index a5580160c391b..be01c5cc840f8 100644 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr @@ -22,5 +22,5 @@ LL | drop(Box::from_raw(ptr as *mut u32)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr index a5580160c391b..be01c5cc840f8 100644 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr @@ -22,5 +22,5 @@ LL | drop(Box::from_raw(ptr as *mut u32)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr index 23d7fdcd03bc5..e96e641bb0d38 100644 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr @@ -17,5 +17,5 @@ LL | drop(Box::from_raw(ptr.as_ptr())); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr index 23d7fdcd03bc5..e96e641bb0d38 100644 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr @@ -17,5 +17,5 @@ LL | drop(Box::from_raw(ptr.as_ptr())); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.stack.stderr b/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.stack.stderr index 7eb973ae7f2af..e78807ec1c8de 100644 --- a/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.stack.stderr @@ -24,5 +24,5 @@ LL | unsafe { *xraw = 42 }; // unfreeze note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.tree.stderr b/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.tree.stderr index 9a3618ed85e70..5de9c9c14786c 100644 --- a/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.tree.stderr @@ -28,5 +28,5 @@ LL | unsafe { *xraw = 42 }; // unfreeze note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.stack.stderr index 3e7fe11b5202a..264503f2f2fca 100644 --- a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.stack.stderr @@ -34,5 +34,5 @@ LL | demo_mut_advanced_unique(&mut 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.tree.stderr index 9cb500679fa85..892b1299bbce6 100644 --- a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.tree.stderr @@ -38,5 +38,5 @@ LL | demo_mut_advanced_unique(&mut 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation2.stack.stderr index 258189f88783c..35d418f574c9a 100644 --- a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation2.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation2.stack.stderr @@ -24,5 +24,5 @@ LL | let raw2 = ptr2.as_mut(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation2.tree.stderr index 5d126bdaebfce..ca5ac5ac88b61 100644 --- a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation2.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation2.tree.stderr @@ -28,5 +28,5 @@ LL | *raw2 = 2; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr index fcabb751db947..c26c7f397b09f 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr @@ -40,5 +40,5 @@ LL | | ) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr index 456af0f1eac71..3900f5b233ebc 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.tree.stderr @@ -51,5 +51,5 @@ LL | | ) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr index 6cbc6a86c091a..ae54da70fe2d8 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr @@ -40,5 +40,5 @@ LL | | ) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr index d21ec9eddc2f7..dd1344a3ce343 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.tree.stderr @@ -51,5 +51,5 @@ LL | | ) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/outdated_local.stack.stderr b/src/tools/miri/tests/fail/both_borrows/outdated_local.stack.stderr index ad366bdabcee6..9717dd16b5b14 100644 --- a/src/tools/miri/tests/fail/both_borrows/outdated_local.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/outdated_local.stack.stderr @@ -24,5 +24,5 @@ LL | x = 1; // this invalidates y by reactivating the lowermost uniq borrow note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/outdated_local.tree.stderr b/src/tools/miri/tests/fail/both_borrows/outdated_local.tree.stderr index 21800d6f4e445..4f79c427b915d 100644 --- a/src/tools/miri/tests/fail/both_borrows/outdated_local.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/outdated_local.tree.stderr @@ -22,5 +22,5 @@ LL | x = 1; // this invalidates y by reactivating the lowermost uniq borrow note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr.stack.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr.stack.stderr index 5243858a91a7d..57c4a756cf725 100644 --- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr.stack.stderr @@ -24,5 +24,5 @@ LL | unsafe { *xraw = 42 }; // unfreeze note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr.tree.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr.tree.stderr index 677e6eeb48389..8060ea9c4a64c 100644 --- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr.tree.stderr @@ -22,5 +22,5 @@ LL | unsafe { *xraw = 42 }; // unfreeze note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr index 26d9f38f239c4..dfc99ff7cd233 100644 --- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr @@ -25,5 +25,5 @@ LL | unsafe { *xraw = 42 }; // unfreeze note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.tree.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.tree.stderr index 242ae0de730f3..6a92fec38ff15 100644 --- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.tree.stderr @@ -28,5 +28,5 @@ LL | unsafe { *xraw = 42 }; // unfreeze note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr index 5f0fbf127597a..e4ebe22b60e2b 100644 --- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr @@ -25,5 +25,5 @@ LL | unsafe { *xraw0 = 42 }; // unfreeze note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.tree.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.tree.stderr index 87b9b1361b7ba..d391c334faf51 100644 --- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.tree.stderr @@ -28,5 +28,5 @@ LL | unsafe { *xraw0 = 42 }; // unfreeze note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr index 0de2f66fe0b23..63eb90b6bc801 100644 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.stack.stderr @@ -21,5 +21,5 @@ LL | let t2 = std::thread::spawn(move || thread_2(p)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr index 8036c974eec13..f05533a6bb4ca 100644 --- a/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/retag_data_race_write.tree.stderr @@ -21,5 +21,5 @@ LL | let t2 = std::thread::spawn(move || thread_2(p)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr index d3a73a00fa605..858afa6fb3c60 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.stack.stderr @@ -29,5 +29,5 @@ LL | foo(&mut (1, 2)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr index 4c016ea621c7e..9358520d8ed38 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr.tree.stderr @@ -27,5 +27,5 @@ LL | foo(&mut (1, 2)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr index 7a9f061228a52..ab67bb516ffe3 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr @@ -30,5 +30,5 @@ LL | match foo(&mut (1, 2)) { note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr index b9ef6dea6ef4e..d60df19f94513 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.tree.stderr @@ -33,5 +33,5 @@ LL | match foo(&mut (1, 2)) { note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr index 6a98c9121ef76..22a55f0d37cd6 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr @@ -30,5 +30,5 @@ LL | foo(&mut (1, 2)).0; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr index c3fd124e6cb37..b252c691c8d61 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr @@ -33,5 +33,5 @@ LL | foo(&mut (1, 2)).0; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.stack.stderr index a69116f2afae7..52ac2184d4948 100644 --- a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.stack.stderr @@ -29,5 +29,5 @@ LL | println!("{}", foo(&mut 0)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.tree.stderr index 9aeaa7ff0758e..c2025332b9f14 100644 --- a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.tree.stderr @@ -32,5 +32,5 @@ LL | println!("{}", foo(&mut 0)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation2.stack.stderr index 0f09359007dba..e05ffb3d35e18 100644 --- a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation2.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation2.stack.stderr @@ -24,5 +24,5 @@ LL | x = 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation2.tree.stderr index 0269f3ab6409b..40f2d89850ea3 100644 --- a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation2.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation2.tree.stderr @@ -22,5 +22,5 @@ LL | x = 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/box-cell-alias.stderr b/src/tools/miri/tests/fail/box-cell-alias.stderr index 8c68261aaf7ab..697cee52d137e 100644 --- a/src/tools/miri/tests/fail/box-cell-alias.stderr +++ b/src/tools/miri/tests/fail/box-cell-alias.stderr @@ -29,5 +29,5 @@ LL | let res = helper(val, ptr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr b/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr index d68b4b8dfc675..655e682636ead 100644 --- a/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr +++ b/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr @@ -15,5 +15,5 @@ LL | | ) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr index 8b99c1493b538..1b43c594da43c 100644 --- a/src/tools/miri/tests/fail/breakpoint.stderr +++ b/src/tools/miri/tests/fail/breakpoint.stderr @@ -8,5 +8,5 @@ LL | core::intrinsics::breakpoint() note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr b/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr index fc5982e7f94f9..f3e1796f3c9af 100644 --- a/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr +++ b/src/tools/miri/tests/fail/concurrency/read_only_atomic_cmpxchg.stderr @@ -13,5 +13,5 @@ see ().write(zst_val) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr index 1c105991015de..4195c68d500dd 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr @@ -17,5 +17,5 @@ LL | let v = 0u32; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr index 38d691f4c0115..37dbea37ce2dc 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr @@ -17,5 +17,5 @@ LL | let v: Vec = vec![1, 2]; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr index 9669614d47ffa..97b3f3ebe7b5c 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr @@ -17,5 +17,5 @@ LL | let mut v: Vec = vec![1, 2]; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr index 28a9207cff3e1..d5c53e4ad6476 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr @@ -21,5 +21,5 @@ LL | let x = make_ref(&mut 0); // The temporary storing "0" is deallocat note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr index 9b47655a047fd..27e5a865069ad 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr @@ -16,5 +16,5 @@ LL | evil(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr index 802995aea50ad..b7492a09dd090 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr @@ -11,5 +11,5 @@ LL | let x = unsafe { *p }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr index 9d21a3e0a454d..fb0f77d2e6f41 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr +++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr @@ -16,5 +16,5 @@ LL | pointer.store(Box::into_raw(Box::new_uninit()), Ordering::Relax note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr index 13a19109e8868..7e6edc02bc2cf 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr +++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr @@ -16,5 +16,5 @@ LL | .store(Box::into_raw(Box::::new_uninit()) as *mut us note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr index f55f839d0b8c4..04186f7ff7be1 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr @@ -16,5 +16,5 @@ LL | *(c.0 as *mut usize) = 32; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr index a20c220b6c2d8..7e76205da9cb2 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr @@ -16,5 +16,5 @@ LL | atomic_ref.load(Ordering::SeqCst) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr index a91d4cee054ca..69d11a0a83c77 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr @@ -16,5 +16,5 @@ LL | atomic_ref.store(32, Ordering::SeqCst) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr index 8831d9cfc1cd0..4f734ae5465a0 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr @@ -16,5 +16,5 @@ LL | let _val = *(c.0 as *mut usize); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr index 5aed907b16647..8745048df473d 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr @@ -16,5 +16,5 @@ LL | *(c.0 as *mut usize) = 32; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr index 65114296f52c6..7ee5014312483 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr @@ -16,5 +16,5 @@ LL | atomic_ref.store(64, Ordering::SeqCst); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr index 7ac3a9cc929ec..deb6029577ffb 100644 --- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr +++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr @@ -16,5 +16,5 @@ LL | *c.0 = 32; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr index 49256dff51fe0..f8ede3ac4c840 100644 --- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr +++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr @@ -16,5 +16,5 @@ LL | *c.0 = 32; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr index ef6b0c3616b1b..55b0b44721325 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr @@ -21,5 +21,5 @@ LL | let _val = *ptr.0; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr index 792faf8f5d113..8925de139b4b2 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr @@ -25,5 +25,5 @@ LL | | ) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr index 805d7c1964231..b9aa4bb041b45 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr @@ -16,5 +16,5 @@ LL | *pointer.load(Ordering::Acquire) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr index 22ef35959f274..0af2911223fc8 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr @@ -21,5 +21,5 @@ LL | *ptr.0 = 2; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr index 64f654402d7c1..6ab77de8afea7 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr @@ -25,5 +25,5 @@ LL | | ); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr index 52c9abd5fe0c2..c1471ae55838c 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr @@ -16,5 +16,5 @@ LL | *pointer.load(Ordering::Acquire) = 3; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr index 1d8bf2d0d26c0..e51119ddb2f5e 100644 --- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr +++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr @@ -16,5 +16,5 @@ LL | *c.0 = 32; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr index 17bcf24a50578..0b71a41098a7e 100644 --- a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr +++ b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr @@ -16,5 +16,5 @@ LL | unsafe { V = 1 } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr b/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr index cb7dc89359a3f..acbc2306726e7 100644 --- a/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr +++ b/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr @@ -10,6 +10,7 @@ help: and (1) occurred earlier here LL | a16.load(Ordering::SeqCst); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: overlapping unsynchronized atomic accesses must use the same access size + = help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model = 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 (of the first span): @@ -17,5 +18,5 @@ LL | a16.load(Ordering::SeqCst); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr b/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr index b3908e9c6bfdb..761942cbad319 100644 --- a/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr +++ b/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr @@ -10,6 +10,7 @@ help: and (1) occurred earlier here LL | a16.store(1, Ordering::SeqCst); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: overlapping unsynchronized atomic accesses must use the same access size + = help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model = 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 (of the first span): @@ -17,5 +18,5 @@ LL | a16.store(1, Ordering::SeqCst); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/read_read_race1.stderr b/src/tools/miri/tests/fail/data_race/read_read_race1.stderr index 0846a88f362b6..d2ba738f0b9d9 100644 --- a/src/tools/miri/tests/fail/data_race/read_read_race1.stderr +++ b/src/tools/miri/tests/fail/data_race/read_read_race1.stderr @@ -10,6 +10,7 @@ help: and (1) occurred earlier here LL | unsafe { ptr.read() }; | ^^^^^^^^^^ = help: overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only + = help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model = 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 (of the first span): @@ -17,5 +18,5 @@ LL | unsafe { ptr.read() }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/read_read_race2.stderr b/src/tools/miri/tests/fail/data_race/read_read_race2.stderr index c6181cc45b200..8ac0446fccd4c 100644 --- a/src/tools/miri/tests/fail/data_race/read_read_race2.stderr +++ b/src/tools/miri/tests/fail/data_race/read_read_race2.stderr @@ -10,6 +10,7 @@ help: and (1) occurred earlier here LL | a.load(Ordering::SeqCst); | ^^^^^^^^^^^^^^^^^^^^^^^^ = help: overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only + = help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model = 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 (of the first span): @@ -17,5 +18,5 @@ LL | a.load(Ordering::SeqCst); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.stderr b/src/tools/miri/tests/fail/data_race/read_write_race.stderr index c3fdcdf9308f4..0066a11188bb7 100644 --- a/src/tools/miri/tests/fail/data_race/read_write_race.stderr +++ b/src/tools/miri/tests/fail/data_race/read_write_race.stderr @@ -16,5 +16,5 @@ LL | let _val = *c.0; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr index 1e45878bfddcb..35f63af2dc594 100644 --- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr @@ -16,5 +16,5 @@ LL | *pointer.load(Ordering::Acquire) = 3; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr index 0c574299b69d1..6cd232ac3d4bd 100644 --- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr +++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr @@ -16,5 +16,5 @@ LL | *c.0 = 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr index 9aff6c6c3a706..61121bb83472a 100644 --- a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr +++ b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr @@ -16,5 +16,5 @@ LL | *c.0 = 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr index f0522404fde07..d674b30c77033 100644 --- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr +++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr @@ -16,5 +16,5 @@ LL | *c.0 = 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.stderr b/src/tools/miri/tests/fail/data_race/rmw_race.stderr index b400b2b9a1758..eeaada1b0f310 100644 --- a/src/tools/miri/tests/fail/data_race/rmw_race.stderr +++ b/src/tools/miri/tests/fail/data_race/rmw_race.stderr @@ -16,5 +16,5 @@ LL | *c.0 = 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr index e6804f6520ce1..2cef51ec94ba6 100644 --- a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr +++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr @@ -21,5 +21,5 @@ LL | race(0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.stderr b/src/tools/miri/tests/fail/data_race/write_write_race.stderr index bc793e9afb090..ca32984be2f48 100644 --- a/src/tools/miri/tests/fail/data_race/write_write_race.stderr +++ b/src/tools/miri/tests/fail/data_race/write_write_race.stderr @@ -16,5 +16,5 @@ LL | *c.0 = 32; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr index ea62dbf96b994..038e9079c54e5 100644 --- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr +++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr @@ -16,5 +16,5 @@ LL | *pointer.load(Ordering::Acquire) = 3; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr index 03272105c4146..365186bcc4b41 100644 --- a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr +++ b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.stderr @@ -11,5 +11,5 @@ LL | r2.method2(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs index 648ac07c43ec9..7d46ecd8f6ea8 100644 --- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs +++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs @@ -1,6 +1,3 @@ -#![feature(trait_upcasting)] -#![allow(incomplete_features)] - trait Foo: PartialEq + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { 10 diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr index 21870ef3733e8..8bac908b864bc 100644 --- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr +++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.stderr @@ -11,5 +11,5 @@ LL | let _err = baz_fake as &dyn Foo; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/environ-gets-deallocated.stderr b/src/tools/miri/tests/fail/environ-gets-deallocated.stderr index dd7420906d322..c9bda00493e06 100644 --- a/src/tools/miri/tests/fail/environ-gets-deallocated.stderr +++ b/src/tools/miri/tests/fail/environ-gets-deallocated.stderr @@ -11,5 +11,5 @@ LL | let _y = unsafe { *pointer }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/erroneous_const.stderr b/src/tools/miri/tests/fail/erroneous_const.stderr index cacf866393d41..ab036247a314b 100644 --- a/src/tools/miri/tests/fail/erroneous_const.stderr +++ b/src/tools/miri/tests/fail/erroneous_const.stderr @@ -12,6 +12,6 @@ note: erroneous constant encountered LL | let _ = PrintName::::VOID; | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/src/tools/miri/tests/fail/erroneous_const2.stderr b/src/tools/miri/tests/fail/erroneous_const2.stderr index 36e83b8f3bcf1..47b06fa8aaa08 100644 --- a/src/tools/miri/tests/fail/erroneous_const2.stderr +++ b/src/tools/miri/tests/fail/erroneous_const2.stderr @@ -18,6 +18,6 @@ LL | println!("{}", FOO); | = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/src/tools/miri/tests/fail/extern_static.stderr b/src/tools/miri/tests/fail/extern_static.stderr index fa0d55e5f6781..c3de4dadb0a30 100644 --- a/src/tools/miri/tests/fail/extern_static.stderr +++ b/src/tools/miri/tests/fail/extern_static.stderr @@ -10,5 +10,5 @@ LL | let _val = unsafe { std::ptr::addr_of!(FOO) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/extern_static_in_const.stderr b/src/tools/miri/tests/fail/extern_static_in_const.stderr index e4ee8f1acba29..23f775f25888a 100644 --- a/src/tools/miri/tests/fail/extern_static_in_const.stderr +++ b/src/tools/miri/tests/fail/extern_static_in_const.stderr @@ -10,5 +10,5 @@ LL | let _val = X; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/extern_static_wrong_size.stderr b/src/tools/miri/tests/fail/extern_static_wrong_size.stderr index a56eba09df98f..c935a548f806d 100644 --- a/src/tools/miri/tests/fail/extern_static_wrong_size.stderr +++ b/src/tools/miri/tests/fail/extern_static_wrong_size.stderr @@ -10,5 +10,5 @@ LL | let _val = unsafe { environ }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/fast_math_both.stderr b/src/tools/miri/tests/fail/fast_math_both.stderr index 2a0759f8a3ba7..feba0c5991cf7 100644 --- a/src/tools/miri/tests/fail/fast_math_both.stderr +++ b/src/tools/miri/tests/fail/fast_math_both.stderr @@ -11,5 +11,5 @@ LL | ...: f32 = core::intrinsics::fsub_fast(f32::NAN, f32::NAN); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/fast_math_first.stderr b/src/tools/miri/tests/fail/fast_math_first.stderr index 766662ca14ba9..b26b5a3721594 100644 --- a/src/tools/miri/tests/fail/fast_math_first.stderr +++ b/src/tools/miri/tests/fail/fast_math_first.stderr @@ -11,5 +11,5 @@ LL | ... let _x: f32 = core::intrinsics::frem_fast(f32::NAN, 3.2); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/fast_math_second.stderr b/src/tools/miri/tests/fail/fast_math_second.stderr index ce93f9398f2cd..cb46aa97a8de9 100644 --- a/src/tools/miri/tests/fail/fast_math_second.stderr +++ b/src/tools/miri/tests/fail/fast_math_second.stderr @@ -11,5 +11,5 @@ LL | ...f32 = core::intrinsics::fmul_fast(3.4f32, f32::INFINITY); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs index d47af50d407ec..e79bd70e915e5 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs @@ -14,7 +14,7 @@ fn main() { let ptr = std::ptr::addr_of_mut!(non_copy); // Inside `callee`, the first argument and `*ptr` are basically // aliasing places! - Call(_unit = callee(Move(*ptr), ptr), after_call) + Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) } after_call = { Return() diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr index 381442e69b130..1756123c84ebc 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr @@ -27,11 +27,11 @@ LL | unsafe { ptr.write(S(0)) }; note: inside `main` --> $DIR/arg_inplace_mutate.rs:LL:CC | -LL | Call(_unit = callee(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr index 3d8ba68547bd1..76f7ee189e3d4 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr @@ -35,11 +35,11 @@ LL | unsafe { ptr.write(S(0)) }; note: inside `main` --> $DIR/arg_inplace_mutate.rs:LL:CC | -LL | Call(_unit = callee(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs index ea773048dd4e5..e4c00fdd84561 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs @@ -11,7 +11,7 @@ fn main() { { let non_copy = S(42); // This could change `non_copy` in-place - Call(_unit = change_arg(Move(non_copy)), after_call) + Call(_unit = change_arg(Move(non_copy)), after_call, UnwindContinue()) } after_call = { // So now we must not be allowed to observe non-copy again. diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr index 5d9a3af0c8aa0..2cd9966bbf59e 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr @@ -11,5 +11,5 @@ LL | _observe = non_copy.0; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr index cba23c21d12b1..723ca75daef89 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr @@ -11,10 +11,10 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $DIR/arg_inplace_observe_during.rs:LL:CC | -LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs index 8c6a7df7a6dd5..517abd733a9ce 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs @@ -14,7 +14,7 @@ fn main() { let non_copy = S(42); let ptr = std::ptr::addr_of_mut!(non_copy); // This could change `non_copy` in-place - Call(_unit = change_arg(Move(*ptr), ptr), after_call) + Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) } after_call = { Return() diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr index f8532186be204..401e8c6d5a8a6 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr @@ -27,11 +27,11 @@ LL | x.0 = 0; note: inside `main` --> $DIR/arg_inplace_observe_during.rs:LL:CC | -LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr index 7b1846a32dbc3..3529ddd3c53cb 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr @@ -35,11 +35,11 @@ LL | x.0 = 0; note: inside `main` --> $DIR/arg_inplace_observe_during.rs:LL:CC | -LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr b/src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr index 406ccb070bab5..2f24425ed1d64 100644 --- a/src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr +++ b/src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr @@ -11,5 +11,5 @@ LL | let _ = malloc(0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr b/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr index d90a7e31d6ee9..d475801f41cd0 100644 --- a/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr +++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr @@ -11,5 +11,5 @@ LL | abort(1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr index 9e2751a216bcb..ad952804ecc96 100644 --- a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr +++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr @@ -11,5 +11,5 @@ LL | let _ = malloc(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr index e9a38b5ae4218..3b1df8a9d4202 100644 --- a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr +++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr @@ -11,5 +11,5 @@ LL | let _ = malloc(1, 2); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr b/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr index 50afc10979749..f948d08bdbe26 100644 --- a/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr +++ b/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr @@ -16,5 +16,5 @@ LL | | ); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr index ae5c6cb72b3c9..2feba7d8e3480 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr @@ -11,5 +11,5 @@ LL | foo(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr index 17d56793ac5c6..0537508babd9f 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr @@ -11,5 +11,5 @@ LL | std::mem::transmute::(foo)(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr index ae5c6cb72b3c9..2feba7d8e3480 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr @@ -11,5 +11,5 @@ LL | foo(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr index 507b459b718fd..c5ca127457469 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr @@ -16,5 +16,5 @@ LL | unsafe { unwind() } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr index 4c477416416f1..2be02100a35fe 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr @@ -33,5 +33,5 @@ LL | unsafe { nounwind() } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr index 4c477416416f1..2be02100a35fe 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr @@ -33,5 +33,5 @@ LL | unsafe { nounwind() } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr index 25e13d7475421..f89cee0b86332 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr @@ -14,5 +14,5 @@ LL | unsafe { nounwind() } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr index 09e4157b31f4f..2f561ed88e3f1 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr @@ -19,5 +19,5 @@ LL | fn bar() {} note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr index 0d0055bb85c8c..d51156b3c3360 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr @@ -17,5 +17,5 @@ LL | | } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.stderr index 1aa13ce438953..69b710b3d3b16 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.stderr @@ -11,5 +11,5 @@ LL | unsafe { foo(1) } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_type.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_type.stderr index abfd7a9a6c4d9..96b483059b0e3 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_type.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_type.stderr @@ -11,5 +11,5 @@ LL | unsafe { FOO() } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr index 0a31adabf73d8..48db898a250fc 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr @@ -11,10 +11,10 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | Call(*ptr = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs index 3d560af3d5eb3..23b1e38b99f72 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs @@ -15,7 +15,7 @@ pub fn main() { let ptr = &raw mut x; // We arrange for `myfun` to have a pointer that aliases // its return place. Even just reading from that pointer is UB. - Call(*ptr = myfun(ptr), after_call) + Call(*ptr = myfun(ptr), after_call, UnwindContinue()) } after_call = { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr index 875cc5edad986..85dcd29ba5513 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr @@ -27,11 +27,11 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | Call(*ptr = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr index deafbf0207725..ea1867b1a7153 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr @@ -35,11 +35,11 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $DIR/return_pointer_aliasing.rs:LL:CC | -LL | Call(*ptr = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs index c1bbc748e1a08..56706cdb63bad 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs @@ -15,7 +15,7 @@ pub fn main() { let ptr = &raw mut _x; // We arrange for `myfun` to have a pointer that aliases // its return place. Even just reading from that pointer is UB. - Call(_x = myfun(ptr), after_call) + Call(_x = myfun(ptr), after_call, UnwindContinue()) } after_call = { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr index 0666db34fec4e..12a99fbf2931f 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr @@ -30,11 +30,11 @@ LL | unsafe { ptr.write(0) }; note: inside `main` --> $DIR/return_pointer_aliasing2.rs:LL:CC | -LL | Call(_x = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_x = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr index e1b40a6bc1839..926303bb48948 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr @@ -35,11 +35,11 @@ LL | unsafe { ptr.write(0) }; note: inside `main` --> $DIR/return_pointer_aliasing2.rs:LL:CC | -LL | Call(_x = myfun(ptr), after_call) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Call(_x = myfun(ptr), after_call, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs index 79e29b79d6a25..923c59e74299a 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs @@ -14,7 +14,7 @@ struct S(i32, [u8; 128]); fn docall(out: &mut S) { mir! { { - Call(*out = callee(), after_call) + Call(*out = callee(), after_call, UnwindContinue()) } after_call = { @@ -37,7 +37,7 @@ fn callee() -> S { // become visible to the outside. In codegen we can see them // but Miri should detect this as UB! RET.0 = 42; - Call(_unit = startpanic(), after_call) + Call(_unit = startpanic(), after_call, UnwindContinue()) } after_call = { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr index ecd9a111840a8..7f035eb5e8575 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr @@ -15,5 +15,5 @@ LL | dbg!(x.0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr index ab3ff5fcdc12c..2544421c7e8c7 100644 --- a/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr +++ b/src/tools/miri/tests/fail/function_calls/simd_feature_flag_difference.stderr @@ -16,5 +16,5 @@ LL | let copy = bar(input); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/target_feature.stderr b/src/tools/miri/tests/fail/function_calls/target_feature.stderr index bddc6e7e89bdb..4d3cf6e9d3bc0 100644 --- a/src/tools/miri/tests/fail/function_calls/target_feature.stderr +++ b/src/tools/miri/tests/fail/function_calls/target_feature.stderr @@ -11,5 +11,5 @@ LL | ssse3_fn(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr index d1ccaf89974cc..595235088f6f2 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr @@ -13,5 +13,5 @@ LL | g(Default::default()) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr index 3875c2617bb59..a8b1cf40c043c 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr @@ -13,5 +13,5 @@ LL | g(42) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr index 6d1bdfee0073f..60dd3814bf577 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr @@ -13,5 +13,5 @@ LL | g(&42 as *const i32) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr index 07d76c90e5e56..198896b0dd765 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr @@ -13,5 +13,5 @@ LL | g() note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr index 7ac2bc2739fed..daf216a142c9c 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr @@ -13,5 +13,5 @@ LL | g(42) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr index 558d83bcfd247..2e50d054e771f 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr @@ -11,5 +11,5 @@ LL | g() note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr index dc12073952f86..facfe9d31f2d8 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr @@ -11,5 +11,5 @@ LL | g(42) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr index e082eb9e3e3d4..50f4474cc0e1c 100644 --- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr +++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr @@ -13,5 +13,5 @@ LL | g(Default::default()) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/cast_box_int_to_fn_ptr.stderr b/src/tools/miri/tests/fail/function_pointers/cast_box_int_to_fn_ptr.stderr index ad43c2c9d3fe7..f95a62535d893 100644 --- a/src/tools/miri/tests/fail/function_pointers/cast_box_int_to_fn_ptr.stderr +++ b/src/tools/miri/tests/fail/function_pointers/cast_box_int_to_fn_ptr.stderr @@ -11,5 +11,5 @@ LL | (*g)(42) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr b/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr index 81fc9716a4156..7274f62b4d7c0 100644 --- a/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr +++ b/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr @@ -11,5 +11,5 @@ LL | g(42) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/deref_fn_ptr.stderr b/src/tools/miri/tests/fail/function_pointers/deref_fn_ptr.stderr index 954bb8721e7a2..b5cee95d66de3 100644 --- a/src/tools/miri/tests/fail/function_pointers/deref_fn_ptr.stderr +++ b/src/tools/miri/tests/fail/function_pointers/deref_fn_ptr.stderr @@ -11,5 +11,5 @@ LL | *std::mem::transmute::(f) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/execute_memory.stderr b/src/tools/miri/tests/fail/function_pointers/execute_memory.stderr index 10c53ca2beaee..4370e6d6a295c 100644 --- a/src/tools/miri/tests/fail/function_pointers/execute_memory.stderr +++ b/src/tools/miri/tests/fail/function_pointers/execute_memory.stderr @@ -11,5 +11,5 @@ LL | f() note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_pointers/fn_ptr_offset.stderr b/src/tools/miri/tests/fail/function_pointers/fn_ptr_offset.stderr index f8c519c1b54b0..e66ab681860c2 100644 --- a/src/tools/miri/tests/fail/function_pointers/fn_ptr_offset.stderr +++ b/src/tools/miri/tests/fail/function_pointers/fn_ptr_offset.stderr @@ -11,5 +11,5 @@ LL | x(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/assume.stderr b/src/tools/miri/tests/fail/intrinsics/assume.stderr index c1909570d99f2..7fa6f7b5bfcf5 100644 --- a/src/tools/miri/tests/fail/intrinsics/assume.stderr +++ b/src/tools/miri/tests/fail/intrinsics/assume.stderr @@ -11,5 +11,5 @@ LL | std::intrinsics::assume(x > 42); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/copy_null.stderr b/src/tools/miri/tests/fail/intrinsics/copy_null.stderr index 6e3215d9f1c9c..d73c03475d69d 100644 --- a/src/tools/miri/tests/fail/intrinsics/copy_null.stderr +++ b/src/tools/miri/tests/fail/intrinsics/copy_null.stderr @@ -11,5 +11,5 @@ LL | copy_nonoverlapping(std::ptr::null(), ptr, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/copy_overflow.stderr b/src/tools/miri/tests/fail/intrinsics/copy_overflow.stderr index 23a4adbd0ed6f..b7c92cf4a57a8 100644 --- a/src/tools/miri/tests/fail/intrinsics/copy_overflow.stderr +++ b/src/tools/miri/tests/fail/intrinsics/copy_overflow.stderr @@ -11,5 +11,5 @@ LL | (&mut y as *mut i32).copy_from(&x, 1usize << (mem::size_of:: note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr index 13a76aae73045..e9ea262caf743 100644 --- a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr +++ b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr @@ -11,5 +11,5 @@ LL | copy_nonoverlapping(a, b, 2); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr index a275979e6be13..d190f3de6b884 100644 --- a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr +++ b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr @@ -11,5 +11,5 @@ LL | copy_nonoverlapping(&data[5], ptr, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.stderr b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.stderr index 5ae14472a8a63..9889daaa85133 100644 --- a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.stderr @@ -11,5 +11,5 @@ LL | ctlz_nonzero(0u8); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.stderr b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.stderr index ae013fb3d9794..0f75657e170ab 100644 --- a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.stderr +++ b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.stderr @@ -11,5 +11,5 @@ LL | cttz_nonzero(0u8); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/div-by-zero.stderr b/src/tools/miri/tests/fail/intrinsics/div-by-zero.stderr index 8c2910de3eef4..9f66e63ca5cfa 100644 --- a/src/tools/miri/tests/fail/intrinsics/div-by-zero.stderr +++ b/src/tools/miri/tests/fail/intrinsics/div-by-zero.stderr @@ -11,5 +11,5 @@ LL | let _n = unchecked_div(1i64, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/exact_div1.stderr b/src/tools/miri/tests/fail/intrinsics/exact_div1.stderr index 2c7bbc00e1b1b..ca6125ab899f8 100644 --- a/src/tools/miri/tests/fail/intrinsics/exact_div1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/exact_div1.stderr @@ -11,5 +11,5 @@ LL | unsafe { std::intrinsics::exact_div(2, 0) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/exact_div2.stderr b/src/tools/miri/tests/fail/intrinsics/exact_div2.stderr index 6a264b8b4476f..306e9bdc23828 100644 --- a/src/tools/miri/tests/fail/intrinsics/exact_div2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/exact_div2.stderr @@ -11,5 +11,5 @@ LL | unsafe { std::intrinsics::exact_div(2u16, 3) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/exact_div3.stderr b/src/tools/miri/tests/fail/intrinsics/exact_div3.stderr index 1a73822c300f3..cbcb093a4e6cf 100644 --- a/src/tools/miri/tests/fail/intrinsics/exact_div3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/exact_div3.stderr @@ -11,5 +11,5 @@ LL | unsafe { std::intrinsics::exact_div(-19i8, 2) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/exact_div4.stderr b/src/tools/miri/tests/fail/intrinsics/exact_div4.stderr index 27201d9c7cf65..1b903bc97aedb 100644 --- a/src/tools/miri/tests/fail/intrinsics/exact_div4.stderr +++ b/src/tools/miri/tests/fail/intrinsics/exact_div4.stderr @@ -11,5 +11,5 @@ LL | unsafe { std::intrinsics::exact_div(i64::MIN, -1) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr index c82d6b30224fc..2de8f3420b7d9 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_inf1.rs:LL:CC | LL | float_to_int_unchecked::(f32::INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f32::INFINITY); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr index 4ca41b676e9c3..53ed208bdee73 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_infneg1.rs:LL:CC | LL | float_to_int_unchecked::(f32::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f32 which cannot be represented in target type `i32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f32::NEG_INFINITY); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr index 88b8948b0c29e..afda7124c114f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_nan.rs:LL:CC | LL | float_to_int_unchecked::(f32::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f32::NAN); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr index ca798dd391aa9..8ba46de8641d7 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_nanneg.rs:LL:CC | LL | float_to_int_unchecked::(-f32::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(-f32::NAN); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.stderr index 4ff6eb8098540..9f4b2af2167bc 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1f32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_neg.rs:LL:CC | LL | float_to_int_unchecked::(-1.000000001f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1f32 which cannot be represented in target type `u32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(-1.000000001f32); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.stderr index fd17709d164b1..a8e56ddb59b90 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.14748365E+9 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.14748365E+9f32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_too_big1.rs:LL:CC | LL | float_to_int_unchecked::(2147483648.0f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.14748365E+9 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.14748365E+9f32 which cannot be represented in target type `i32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(2147483648.0f32); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.stderr index fdc1f65dc1485..a966e2e639c98 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 4.2949673E+9 which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 4.2949673E+9f32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_too_big2.rs:LL:CC | LL | float_to_int_unchecked::((u32::MAX - 127) as f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 4.2949673E+9 which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 4.2949673E+9f32 which cannot be represented in target type `u32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::((u32::MAX - 127) as f32); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.stderr index 9e743a3214449..6115b381ebec5 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.1474839E+9 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.1474839E+9f32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_too_small1.rs:LL:CC | LL | float_to_int_unchecked::(-2147483904.0f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.1474839E+9 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.1474839E+9f32 which cannot be represented in target type `i32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(-2147483904.0f32); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr index ee01143dc8dfc..5db9fb1417cbc 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_inf1.rs:LL:CC | LL | float_to_int_unchecked::(f64::INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf_f64 which cannot be represented in target type `u128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f64::INFINITY); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr index f37b8ae550643..3e8dadb79e4d1 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_infneg1.rs:LL:CC | LL | float_to_int_unchecked::(f64::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `u128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f64::NEG_INFINITY); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr index 05dcd5ebcf69a..cb59974bf454f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_infneg2.rs:LL:CC | LL | float_to_int_unchecked::(f64::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `i128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f64::NEG_INFINITY); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr index 0a914abb2ce78..686970605154e 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f64 which cannot be represented in target type `u32` --> $DIR/float_to_int_64_nan.rs:LL:CC | LL | float_to_int_unchecked::(f64::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f64 which cannot be represented in target type `u32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f64::NAN); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr index ddf3249d059a1..505a6463cd348 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.0000000000000999f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_neg.rs:LL:CC | LL | float_to_int_unchecked::(-1.0000000000001f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.0000000000000999f64 which cannot be represented in target type `u128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(-1.0000000000001f64); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.stderr index 42da33321f371..bcfd394686b1e 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2147483648 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2147483648f64 which cannot be represented in target type `i32` --> $DIR/float_to_int_64_too_big1.rs:LL:CC | LL | float_to_int_unchecked::(2147483648.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2147483648 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2147483648f64 which cannot be represented in target type `i32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(2147483648.0f64); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.stderr index af4c4ceb3f73f..ac6139d7e7dff 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18 which cannot be represented in target type `i64` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18f64 which cannot be represented in target type `i64` --> $DIR/float_to_int_64_too_big2.rs:LL:CC | LL | float_to_int_unchecked::(9223372036854775808.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18 which cannot be represented in target type `i64` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18f64 which cannot be represented in target type `i64` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(9223372036854775808.0f64); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.stderr index 6e384a6fbc7cb..e289b4c0fc070 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19 which cannot be represented in target type `u64` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19f64 which cannot be represented in target type `u64` --> $DIR/float_to_int_64_too_big3.rs:LL:CC | LL | float_to_int_unchecked::(18446744073709551616.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19 which cannot be represented in target type `u64` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19f64 which cannot be represented in target type `u64` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(18446744073709551616.0f64); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.stderr index 77f05ff91e3b5..657c72daa6f4b 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38 which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_too_big4.rs:LL:CC | LL | float_to_int_unchecked::(u128::MAX as f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38 which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38f64 which cannot be represented in target type `u128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(u128::MAX as f64); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.stderr index cb5eba490b447..2a61b5fe15fe7 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38 which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38f64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_too_big5.rs:LL:CC | LL | float_to_int_unchecked::(240282366920938463463374607431768211455.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38 which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38f64 which cannot be represented in target type `i128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(2402823669209384634633746074317 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.stderr index d899d2f808a5d..1b4b76ced18bb 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308 which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_too_big6.rs:LL:CC | LL | float_to_int_unchecked::(f64::MAX); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308 which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308f64 which cannot be represented in target type `u128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f64::MAX); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.stderr index 443b2759c2606..47df8d90c062d 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308 which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308f64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_too_big7.rs:LL:CC | LL | float_to_int_unchecked::(f64::MIN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308 which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308f64 which cannot be represented in target type `i128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(f64::MIN); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.stderr index f8d88c44aa80d..c5eb405ee95c5 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2147483649 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2147483649f64 which cannot be represented in target type `i32` --> $DIR/float_to_int_64_too_small1.rs:LL:CC | LL | float_to_int_unchecked::(-2147483649.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2147483649 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2147483649f64 which cannot be represented in target type `i32` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(-2147483649.0f64); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.stderr index d94e57b1e67c2..e7d12a18a2a48 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18 which cannot be represented in target type `i64` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18f64 which cannot be represented in target type `i64` --> $DIR/float_to_int_64_too_small2.rs:LL:CC | LL | float_to_int_unchecked::(-9223372036854777856.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18 which cannot be represented in target type `i64` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18f64 which cannot be represented in target type `i64` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(-9223372036854777856.0f64); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.stderr index 59b74f5f51f37..3d8366c725b2a 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38 which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38f64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_too_small3.rs:LL:CC | LL | float_to_int_unchecked::(-240282366920938463463374607431768211455.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38 which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38f64 which cannot be represented in target type `i128` | = 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 @@ -11,5 +11,5 @@ LL | float_to_int_unchecked::(-240282366920938463463374607431 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr index e1102a6d216ab..cc8cca70ddb9f 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr @@ -16,5 +16,5 @@ LL | let v = [0i8; 4]; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr index 6a11ebae108f0..97fa1f19af106 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr @@ -11,5 +11,5 @@ LL | let x = unsafe { x.offset(isize::MIN) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr index 99f28b3e4f810..236b51e82e594 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr @@ -16,5 +16,5 @@ LL | let v = [0i8; 4]; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_0_plus_0.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_0_plus_0.stderr index 9c1c387d54991..a8984c7fa1670 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_0_plus_0.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_0_plus_0.stderr @@ -11,5 +11,5 @@ LL | let _x = unsafe { x.offset(0) }; // UB despite offset 0, NULL is never note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr index 0b9cda62b33c2..32a4461d6bf04 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr @@ -11,5 +11,5 @@ LL | unsafe { end_ptr.offset_from(end_ptr) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr index 803aaaa55c21e..0b4a9faf1b249 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { ptr1.sub_ptr(ptr2) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr index f76881011d079..e03abfb1a2fcd 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr @@ -11,5 +11,5 @@ LL | let _val = (1 as *mut u8).offset(1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr index 6e0744b7d5c39..03ae9bd141c4a 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr @@ -11,5 +11,5 @@ LL | let _val = (1 as *mut u8).offset(ptr as isize); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr index 6fb94cf5f8122..122529c30490a 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { x.offset(isize::MIN) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr index 7cc4bc184a1b3..304d362bbb9f9 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr @@ -16,5 +16,5 @@ LL | let x = Box::into_raw(Box::new(0u32)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr index 2236ad9839c5e..83f81fa726ea9 100644 --- a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr +++ b/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr @@ -11,5 +11,5 @@ LL | unsafe { raw_eq(&x, &x) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/rem-by-zero.stderr b/src/tools/miri/tests/fail/intrinsics/rem-by-zero.stderr index 1fc39188e5a94..9b9fe4da13998 100644 --- a/src/tools/miri/tests/fail/intrinsics/rem-by-zero.stderr +++ b/src/tools/miri/tests/fail/intrinsics/rem-by-zero.stderr @@ -11,5 +11,5 @@ LL | let _n = unchecked_rem(3u32, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.stderr b/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.stderr index ddab24d0c1639..44d3749d68265 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.stderr @@ -11,5 +11,5 @@ LL | simd_div(x, y); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.stderr b/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.stderr index 27d4dd9e3e73f..85058b008eed4 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.stderr @@ -11,5 +11,5 @@ LL | simd_div(x, y); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs index 10939c0f1c38a..0dfa8bdd274e6 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.rs @@ -1,5 +1,5 @@ #![feature(portable_simd)] -use std::simd::*; +use std::simd::prelude::*; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr index 7b2387944af0d..d75fefe1ded24 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32` +error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38f32 which cannot be represented in target type `i32` --> $DIR/simd-float-to-int.rs:LL:CC | LL | let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38f32 which cannot be represented in target type `i32` | = 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 @@ -11,5 +11,5 @@ LL | let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unch note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr b/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr index f3bd275b027e6..d111644eec827 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr @@ -11,5 +11,5 @@ LL | let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.stderr b/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.stderr index 1e5ac5277e6dc..b6c43d34b9de4 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.stderr @@ -11,5 +11,5 @@ LL | simd_reduce_any(x); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.stderr b/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.stderr index 96248e7e599cc..d29d22d8aef05 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.stderr @@ -11,5 +11,5 @@ LL | simd_rem(x, y); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr index 1720a24aa134c..8b517b6e97252 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr @@ -22,5 +22,5 @@ LL | let mut vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18]; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.stderr b/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.stderr index e72cce998d0ed..1f978e13bb9b1 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.stderr @@ -11,5 +11,5 @@ LL | simd_select_bitmask(0b11111111u8, x, x); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.stderr b/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.stderr index 277ceb54ec71e..e0c0547483103 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.stderr @@ -11,5 +11,5 @@ LL | simd_select(x, x, x); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr index c8445bb3cdc75..3a4ec008b449a 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr @@ -11,5 +11,5 @@ LL | simd_shl(x, y); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr index 8eec30c5a52f2..07636b8c0bbd3 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr @@ -11,5 +11,5 @@ LL | simd_shr(x, y); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr index f5e96198ee4c9..922de4226fa80 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { 40000u16.unchecked_add(30000) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr index 5a5c7070ae0b4..05456eaf19509 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { (-30000i16).unchecked_add(-8000) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_div1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_div1.stderr index 9267e0c494731..9dc4bcaee2f9f 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_div1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_div1.stderr @@ -11,5 +11,5 @@ LL | std::intrinsics::unchecked_div(i16::MIN, -1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr index 9a5a585e1cce4..533beaa65ff77 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { 300u16.unchecked_mul(250u16) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr index 46b9f61821728..4c6bae6f0bf68 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { 1_000_000_000i32.unchecked_mul(-4) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_shl.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_shl.stderr index 264e9baf053d6..f30cf4479e6be 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_shl.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_shl.stderr @@ -11,5 +11,5 @@ LL | let _n = 1i8.unchecked_shl(8); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.rs new file mode 100644 index 0000000000000..a5777ebbb7f33 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.rs @@ -0,0 +1,9 @@ +#![feature(core_intrinsics)] +use std::intrinsics; + +fn main() { + unsafe { + let _n = intrinsics::unchecked_shl(1i8, -1); + //~^ ERROR: overflowing shift by -1 in `unchecked_shl` + } +} diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.stderr new file mode 100644 index 0000000000000..a572f34b92cdb --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_shl2.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: overflowing shift by -1 in `unchecked_shl` + --> $DIR/unchecked_shl2.rs:LL:CC + | +LL | let _n = intrinsics::unchecked_shl(1i8, -1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl` + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/unchecked_shl2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_shr.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_shr.stderr index 378ff9734c16e..22e0b1a0d9e32 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_shr.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_shr.stderr @@ -11,5 +11,5 @@ LL | let _n = 1i64.unchecked_shr(64); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr index 01e569767bac0..72187e20e23c3 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { 14u32.unchecked_sub(22) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr index 38c1647b4f49f..ec28384f6336f 100644 --- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { 30000i16.unchecked_sub(-7000) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error 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 c63cfe065530e..2196673c39ae0 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr @@ -22,5 +22,5 @@ LL | let _ = unsafe { std::mem::uninitialized::() }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/write_bytes_null.stderr b/src/tools/miri/tests/fail/intrinsics/write_bytes_null.stderr index b2969ca3b5929..def180935cc39 100644 --- a/src/tools/miri/tests/fail/intrinsics/write_bytes_null.stderr +++ b/src/tools/miri/tests/fail/intrinsics/write_bytes_null.stderr @@ -11,5 +11,5 @@ LL | unsafe { write_bytes::(std::ptr::null_mut(), 0, 0) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/write_bytes_overflow.stderr b/src/tools/miri/tests/fail/intrinsics/write_bytes_overflow.stderr index f88afde879acf..326c180fadbac 100644 --- a/src/tools/miri/tests/fail/intrinsics/write_bytes_overflow.stderr +++ b/src/tools/miri/tests/fail/intrinsics/write_bytes_overflow.stderr @@ -11,5 +11,5 @@ LL | (&mut y as *mut i32).write_bytes(0u8, 1usize << (mem::size_of::() }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/issue-miri-1112.stderr b/src/tools/miri/tests/fail/issue-miri-1112.stderr index f1cb50ab9be78..7ac65c152e952 100644 --- a/src/tools/miri/tests/fail/issue-miri-1112.stderr +++ b/src/tools/miri/tests/fail/issue-miri-1112.stderr @@ -16,5 +16,5 @@ LL | let _raw: &FunnyPointer = FunnyPointer::from_data_ptr(&hello, &meta note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/issue-miri-2432.stderr b/src/tools/miri/tests/fail/issue-miri-2432.stderr index b8e13b61ceb60..3befe31dc5a05 100644 --- a/src/tools/miri/tests/fail/issue-miri-2432.stderr +++ b/src/tools/miri/tests/fail/issue-miri-2432.stderr @@ -11,5 +11,5 @@ LL | ::foo(&()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/memleak.stderr b/src/tools/miri/tests/fail/memleak.stderr index 12bb944b07677..9c885c37f3a84 100644 --- a/src/tools/miri/tests/fail/memleak.stderr +++ b/src/tools/miri/tests/fail/memleak.stderr @@ -19,5 +19,5 @@ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/memleak_no_backtrace.stderr b/src/tools/miri/tests/fail/memleak_no_backtrace.stderr index f44e6ce079779..22e8c558061ae 100644 --- a/src/tools/miri/tests/fail/memleak_no_backtrace.stderr +++ b/src/tools/miri/tests/fail/memleak_no_backtrace.stderr @@ -1,4 +1,4 @@ error: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/memleak_rc.32bit.stderr b/src/tools/miri/tests/fail/memleak_rc.32bit.stderr index 87c5f466bc4be..3f8b7a3e81956 100644 --- a/src/tools/miri/tests/fail/memleak_rc.32bit.stderr +++ b/src/tools/miri/tests/fail/memleak_rc.32bit.stderr @@ -20,5 +20,5 @@ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/memleak_rc.64bit.stderr b/src/tools/miri/tests/fail/memleak_rc.64bit.stderr index ec5f5f5bed368..b68991602ea32 100644 --- a/src/tools/miri/tests/fail/memleak_rc.64bit.stderr +++ b/src/tools/miri/tests/fail/memleak_rc.64bit.stderr @@ -20,5 +20,5 @@ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/modifying_constants.stderr b/src/tools/miri/tests/fail/modifying_constants.stderr index 6425a5d7a0ad4..c1eca7866ad13 100644 --- a/src/tools/miri/tests/fail/modifying_constants.stderr +++ b/src/tools/miri/tests/fail/modifying_constants.stderr @@ -11,5 +11,5 @@ LL | *y = 42; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/never_match_never.stderr b/src/tools/miri/tests/fail/never_match_never.stderr index 33dab81d5b081..751894f19859a 100644 --- a/src/tools/miri/tests/fail/never_match_never.stderr +++ b/src/tools/miri/tests/fail/never_match_never.stderr @@ -11,5 +11,5 @@ LL | unsafe { match (*ptr).1 {} } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/never_say_never.stderr b/src/tools/miri/tests/fail/never_say_never.stderr index 9d3a8df525a49..1720cc893ab45 100644 --- a/src/tools/miri/tests/fail/never_say_never.stderr +++ b/src/tools/miri/tests/fail/never_say_never.stderr @@ -11,5 +11,5 @@ LL | f(x) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/never_transmute_humans.stderr b/src/tools/miri/tests/fail/never_transmute_humans.stderr index a51ca7fe7e767..6916c93599506 100644 --- a/src/tools/miri/tests/fail/never_transmute_humans.stderr +++ b/src/tools/miri/tests/fail/never_transmute_humans.stderr @@ -11,5 +11,5 @@ LL | std::mem::transmute::(Human) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/never_transmute_void.stderr b/src/tools/miri/tests/fail/never_transmute_void.stderr index 413172b25464a..4ca306373a1e1 100644 --- a/src/tools/miri/tests/fail/never_transmute_void.stderr +++ b/src/tools/miri/tests/fail/never_transmute_void.stderr @@ -16,5 +16,5 @@ LL | m::f(v); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/no_main.stderr b/src/tools/miri/tests/fail/no_main.stderr index 88bdfb4e387cf..1c4fc88989b21 100644 --- a/src/tools/miri/tests/fail/no_main.stderr +++ b/src/tools/miri/tests/fail/no_main.stderr @@ -1,4 +1,4 @@ error: miri can only run programs that have a main function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/overlapping_assignment.stderr b/src/tools/miri/tests/fail/overlapping_assignment.stderr index 42a000dfcc6c7..54e104e351370 100644 --- a/src/tools/miri/tests/fail/overlapping_assignment.stderr +++ b/src/tools/miri/tests/fail/overlapping_assignment.stderr @@ -16,5 +16,5 @@ LL | self_copy(ptr, ptr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/bad_miri_start_panic.stderr b/src/tools/miri/tests/fail/panic/bad_miri_start_panic.stderr index 4e5a2dfba3429..2d96ae4b7de4a 100644 --- a/src/tools/miri/tests/fail/panic/bad_miri_start_panic.stderr +++ b/src/tools/miri/tests/fail/panic/bad_miri_start_panic.stderr @@ -13,5 +13,5 @@ LL | unsafe { miri_start_panic(&mut 0) } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/bad_unwind.stderr b/src/tools/miri/tests/fail/panic/bad_unwind.stderr index c2d007e5729da..e4af01feb8d7a 100644 --- a/src/tools/miri/tests/fail/panic/bad_unwind.stderr +++ b/src/tools/miri/tests/fail/panic/bad_unwind.stderr @@ -22,5 +22,5 @@ LL | std::panic::catch_unwind(|| unwind()).unwrap_err(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index 5de7b3cf92980..75ca0901bc82f 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -31,5 +31,5 @@ LL | | } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/no_std.stderr b/src/tools/miri/tests/fail/panic/no_std.stderr index 47ec710052a25..8b48f75296761 100644 --- a/src/tools/miri/tests/fail/panic/no_std.stderr +++ b/src/tools/miri/tests/fail/panic/no_std.stderr @@ -16,5 +16,5 @@ LL | panic!("blarg I am dead") note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr index 6bd7157031afd..690f5bbec13d5 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr @@ -23,5 +23,5 @@ LL | std::panic!("panicking from libstd"); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr index 1d828d2e0f5a8..e937fa02b0ded 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr @@ -23,5 +23,5 @@ LL | std::panic!("{}-panicking from libstd", 42); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr index 5e43444572e36..0513ae7e765f9 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr @@ -23,5 +23,5 @@ LL | core::panic!("panicking from libcore"); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr index 12c4b857134c7..314e0c3079255 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr @@ -23,5 +23,5 @@ LL | core::panic!("{}-panicking from libcore", 42); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/thread_local_const_drop_panic.rs b/src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.rs similarity index 100% rename from src/tools/miri/tests/fail/panic/thread_local_const_drop_panic.rs rename to src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.rs diff --git a/src/tools/miri/tests/fail/panic/thread_local_const_drop_panic.stderr b/src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.stderr similarity index 51% rename from src/tools/miri/tests/fail/panic/thread_local_const_drop_panic.stderr rename to src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.stderr index 550d009607d13..778061490f04a 100644 --- a/src/tools/miri/tests/fail/panic/thread_local_const_drop_panic.stderr +++ b/src/tools/miri/tests/fail/panic/tls_macro_const_drop_panic.stderr @@ -1,7 +1,7 @@ -thread $NAME panicked at $DIR/thread_local_const_drop_panic.rs:LL:CC: +thread $NAME panicked at $DIR/tls_macro_const_drop_panic.rs:LL:CC: ow fatal runtime error: thread local panicked on drop error: abnormal termination: the program aborted execution -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/thread_local_drop_panic.rs b/src/tools/miri/tests/fail/panic/tls_macro_drop_panic.rs similarity index 100% rename from src/tools/miri/tests/fail/panic/thread_local_drop_panic.rs rename to src/tools/miri/tests/fail/panic/tls_macro_drop_panic.rs diff --git a/src/tools/miri/tests/fail/panic/thread_local_drop_panic.stderr b/src/tools/miri/tests/fail/panic/tls_macro_drop_panic.stderr similarity index 52% rename from src/tools/miri/tests/fail/panic/thread_local_drop_panic.stderr rename to src/tools/miri/tests/fail/panic/tls_macro_drop_panic.stderr index 3d6c41faabc40..367e2ee1f0bc6 100644 --- a/src/tools/miri/tests/fail/panic/thread_local_drop_panic.stderr +++ b/src/tools/miri/tests/fail/panic/tls_macro_drop_panic.stderr @@ -1,7 +1,7 @@ -thread $NAME panicked at $DIR/thread_local_drop_panic.rs:LL:CC: +thread $NAME panicked at $DIR/tls_macro_drop_panic.rs:LL:CC: ow fatal runtime error: thread local panicked on drop error: abnormal termination: the program aborted execution -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/panic/unwind_panic_abort.stderr b/src/tools/miri/tests/fail/panic/unwind_panic_abort.stderr index 363e69ba41db9..4739c7f2ac6ba 100644 --- a/src/tools/miri/tests/fail/panic/unwind_panic_abort.stderr +++ b/src/tools/miri/tests/fail/panic/unwind_panic_abort.stderr @@ -11,5 +11,5 @@ LL | miri_start_panic(&mut 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr b/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr index 8fafc7e82c9ba..50bff22f76678 100644 --- a/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr +++ b/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr @@ -11,5 +11,5 @@ LL | let x = *p; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr b/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr index 319517d062b8c..6b1c2941c075c 100644 --- a/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr +++ b/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr @@ -16,5 +16,5 @@ LL | deref(ptr1, ptr2.with_addr(ptr1.addr())); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs index 07de41d10a038..20fd330699890 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(strict_provenance)] +#![feature(strict_provenance, exposed_provenance)] fn main() { let x: i32 = 3; diff --git a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr index 9ebabfb129cc2..92ccec5027497 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr +++ b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr @@ -11,5 +11,5 @@ LL | assert_eq!(unsafe { *ptr }, 3); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid.rs b/src/tools/miri/tests/fail/provenance/ptr_invalid.rs index d7d32d83e0771..5d44928d1d24d 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_invalid.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_invalid.rs @@ -1,4 +1,4 @@ -#![feature(strict_provenance)] +#![feature(strict_provenance, exposed_provenance)] // Ensure that a `ptr::invalid` ptr is truly invalid. fn main() { diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr b/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr index 50ceae7cfda9b..8b8033b0d1d91 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr +++ b/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { *xptr_invalid }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr b/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr index 3607635c8fbe5..8ae140ee004cf 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr +++ b/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr @@ -11,5 +11,5 @@ LL | let _ = unsafe { roundtrip.offset(1) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs b/src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs index 04552d0c332fd..106cf4d804b41 100644 --- a/src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs +++ b/src/tools/miri/tests/fail/provenance/strict_provenance_cast.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-strict-provenance -#![feature(strict_provenance)] +#![feature(exposed_provenance)] fn main() { let addr = &0 as *const i32 as usize; diff --git a/src/tools/miri/tests/fail/provenance/strict_provenance_cast.stderr b/src/tools/miri/tests/fail/provenance/strict_provenance_cast.stderr index 998ccc8bb49c6..a110ed4ebb218 100644 --- a/src/tools/miri/tests/fail/provenance/strict_provenance_cast.stderr +++ b/src/tools/miri/tests/fail/provenance/strict_provenance_cast.stderr @@ -10,5 +10,5 @@ LL | let _ptr = std::ptr::from_exposed_addr::(addr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/rc_as_ptr.stderr b/src/tools/miri/tests/fail/rc_as_ptr.stderr index eb522b2bc0cf2..83d85f8adffa2 100644 --- a/src/tools/miri/tests/fail/rc_as_ptr.stderr +++ b/src/tools/miri/tests/fail/rc_as_ptr.stderr @@ -22,5 +22,5 @@ LL | drop(strong); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/reading_half_a_pointer.stderr b/src/tools/miri/tests/fail/reading_half_a_pointer.stderr index df4adb5ead7c0..03f93510d09b3 100644 --- a/src/tools/miri/tests/fail/reading_half_a_pointer.stderr +++ b/src/tools/miri/tests/fail/reading_half_a_pointer.stderr @@ -11,5 +11,5 @@ LL | let _val = *x; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/rustc-error.stderr b/src/tools/miri/tests/fail/rustc-error.stderr index 09d0f7a6df955..3f911c172d4ef 100644 --- a/src/tools/miri/tests/fail/rustc-error.stderr +++ b/src/tools/miri/tests/fail/rustc-error.stderr @@ -9,6 +9,6 @@ help: use `!` to invoke the macro LL | println!("Hello, world!"); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-decl.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-decl.stderr index 200f5f56213d6..159a02f2c0355 100644 --- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-decl.stderr +++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-decl.stderr @@ -11,5 +11,5 @@ LL | ... miri_resolve_frame(*frame, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr index 5d51790f8a5c1..2523e5063e1b5 100644 --- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr +++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-flags.stderr @@ -10,5 +10,5 @@ LL | miri_get_backtrace(2, std::ptr::null_mut()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr index f23f834000aa1..04dbd657d200c 100644 --- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr +++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr @@ -11,5 +11,5 @@ LL | miri_resolve_frame(std::ptr::null_mut(), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr index fe123c2352f0a..36446ae283bf7 100644 --- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr +++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-flags.stderr @@ -10,5 +10,5 @@ LL | miri_resolve_frame(buf[0], 2); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr index a3003c9093f72..ff60ab09172fd 100644 --- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr +++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-resolve-names-flags.stderr @@ -10,5 +10,5 @@ LL | ... miri_resolve_frame_names(buf[0], 2, std::ptr::null_mut(), std::ptr::n note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr index b4a02c0e363ed..6d4c370050f49 100644 --- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr +++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-size-flags.stderr @@ -10,5 +10,5 @@ LL | miri_backtrace_size(2); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr b/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr index a1b9662961d04..e1b1800086672 100644 --- a/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr +++ b/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr @@ -25,5 +25,5 @@ LL | let _file = std::fs::File::open("file.txt").unwrap(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs new file mode 100644 index 0000000000000..9263ad381d1b6 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs @@ -0,0 +1,42 @@ +// Ignore everything except x86 and x86_64 +// Any new targets that are added to CI should be ignored here. +// We cannot use `cfg`-based tricks here since the output would be +// different for non-x86 targets. +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +// Explicitly disable SSE4.1 because it is enabled by default on macOS +//@compile-flags: -C target-feature=-sse4.1 + +#![feature(link_llvm_intrinsics, simd_ffi)] + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +fn main() { + assert!(is_x86_feature_detected!("sse")); + assert!(!is_x86_feature_detected!("sse4.1")); + + unsafe { + // Pass, since SSE is enabled + addss(_mm_setzero_ps(), _mm_setzero_ps()); + + // Fail, since SSE4.1 is not enabled + dpps(_mm_setzero_ps(), _mm_setzero_ps(), 0); + //~^ ERROR: Undefined Behavior: attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1 + } +} + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.x86.sse.add.ss"] + fn addss(a: __m128, b: __m128) -> __m128; + + #[link_name = "llvm.x86.sse41.dpps"] + fn dpps(a: __m128, b: __m128, imm8: u8) -> __m128; +} diff --git a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr new file mode 100644 index 0000000000000..8e83d20854faf --- /dev/null +++ b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1 + --> $DIR/intrinsic_target_feature.rs:LL:CC + | +LL | dpps(_mm_setzero_ps(), _mm_setzero_ps(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/intrinsic_target_feature.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/shims/shim_arg_size.stderr b/src/tools/miri/tests/fail/shims/shim_arg_size.stderr index d951f81810ef6..b40d02ac34577 100644 --- a/src/tools/miri/tests/fail/shims/shim_arg_size.stderr +++ b/src/tools/miri/tests/fail/shims/shim_arg_size.stderr @@ -11,5 +11,5 @@ LL | memchr(std::ptr::null(), 0, 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr b/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr index 325565fa1e786..966279723c495 100644 --- a/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr +++ b/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr @@ -16,5 +16,5 @@ LL | test_cpp20_rwc_syncs(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr index 00ea6b27d4c92..2cc714f935a13 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr @@ -34,5 +34,5 @@ LL | | }); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr b/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr index bd79b401f667f..aa26a003f22f2 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr @@ -24,5 +24,5 @@ LL | *base = 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr index 3d0cef241c3e6..627c790f843eb 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr @@ -29,5 +29,5 @@ LL | core::ptr::drop_in_place(x); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr index 7f2917e795053..6b8465804a58f 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr @@ -25,5 +25,5 @@ LL | core::ptr::drop_in_place(x.cast_mut()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs b/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs index 0b4fb0ccd33bd..b0e4cceb98f36 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(strict_provenance)] +#![feature(exposed_provenance)] // If we have only exposed read-only pointers, doing a write through a wildcard ptr should fail. diff --git a/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.stderr b/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.stderr index cb5e7bffde480..201bdcdeb9731 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/exposed_only_ro.stderr @@ -14,5 +14,5 @@ LL | unsafe { *ptr = 0 }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr index 236c8fb0187de..2a841aa0a8d3c 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr @@ -24,5 +24,5 @@ LL | x.do_bad(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr index 45c2197050a1b..42f042bfad2f1 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr @@ -24,5 +24,5 @@ LL | let _ = t.sli.as_mut_ptr(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr index 7fff60f25fbbe..7a44c8384a063 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr @@ -26,5 +26,5 @@ LL | dealloc(ptr2, Layout::from_size_align_unchecked(1, 1)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr index 7a159c9d3fefc..2dfb660c53c69 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr @@ -24,5 +24,5 @@ LL | let _val = unsafe { *xraw }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr index e3e79f6f0f05e..ce3b920c1dcbb 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr @@ -24,5 +24,5 @@ LL | let shr = unsafe { &*xraw }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr index 3a8687ad9aa19..2c81fda1411e1 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr @@ -24,5 +24,5 @@ LL | let _val = unsafe { *xref1.r }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr index dcf37b2690154..98bfd56cd3ce3 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr @@ -24,5 +24,5 @@ LL | let _val = unsafe { *xraw }; // use the raw again, this invalidates xre note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr index 1793798d15f6a..e3b18e7d4f81f 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr @@ -24,5 +24,5 @@ LL | mem::forget(unsafe { ptr::read(xshr) }); // but after reading through t note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr index 17b28dee3c7ca..415a85bd68c51 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr @@ -24,5 +24,5 @@ LL | let x = &mut *x; // kill `raw` note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr index 1a9d551431caa..248ae62d5ebe2 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr @@ -24,5 +24,5 @@ LL | let _val = ptr::read(raw); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr index b43079c3b7f3b..fd5ed383f1a6b 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr @@ -24,5 +24,5 @@ LL | *y2 += 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr index fbd5d8b956d97..33fcd11ff7a5f 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr @@ -24,5 +24,5 @@ LL | *exposed_ptr = 0; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr index 19e4cbdb93855..a948c5df1661e 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr @@ -24,5 +24,5 @@ LL | let _val = *exposed_ptr; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr index 3e11e86eb81b3..65b4fc5f3fa06 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr @@ -24,5 +24,5 @@ LL | drop(&mut *target); // reborrow note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr index 4053325821e75..08d9f33a1699d 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr @@ -19,5 +19,5 @@ LL | let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr index fceda8db4cef5..4ee5ec3853958 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr @@ -24,5 +24,5 @@ LL | let _mut_ref: &mut i32 = unsafe { mem::transmute(raw) }; // &mut, with note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr index 1bb3afe483eba..70e9038bab3fb 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr @@ -24,5 +24,5 @@ LL | *exposed_ptr = 0; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr b/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr index ba8977c567456..f8bc1667ddb15 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr @@ -24,5 +24,5 @@ LL | *c.get() = UnsafeCell::new(1); // invalidates inner_shr note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr b/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr index 97ebe72bf29de..a69fc6ff8bab1 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr @@ -24,5 +24,5 @@ LL | *c.get() = UnsafeCell::new(0); // now inner_shr gets invalidated note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr index 95fa4c51d12fd..22a0b42cfd8ba 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr @@ -26,5 +26,5 @@ LL | inner(xraw, xref); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr index 7aca065ca0d70..9d707c3f85d58 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr @@ -24,5 +24,5 @@ LL | let _val = unsafe { *xraw }; // invalidate xref note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr index 96cec327b9df5..0a017e182644f 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr @@ -24,5 +24,5 @@ LL | let _val = unsafe { *xraw }; // invalidate xref note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr index e20b5b89a2fca..1fddcaf3dad0b 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr @@ -29,5 +29,5 @@ LL | fun2(); // if they now use a raw ptr they break our reference note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr b/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr index 9f7e7a058dfcf..0d07d154ba5b2 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr @@ -24,5 +24,5 @@ LL | let raw2 = &mut l as *mut _; // invalidates raw1 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr index ce77976f88bc2..905776155eb8f 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_protected_read.stderr @@ -16,5 +16,5 @@ LL | unsafe { ptr.0.read() }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stack.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stack.stderr index c53a495b5e18b..c6828d62d5ab6 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stack.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stack.stderr @@ -21,5 +21,5 @@ LL | let t2 = std::thread::spawn(move || thread_2(p)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr index 1496c353e52a6..129b9ffb26ec2 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr @@ -21,5 +21,5 @@ LL | let t2 = std::thread::spawn(move || thread_2(p)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.tree.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.tree.stderr index 1e154eb0564a2..675bb01b5e751 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.tree.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.tree.stderr @@ -22,5 +22,5 @@ LL | pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { = note: inside `std::rt::lang_start_internal` at RUSTLIB/std/src/rt.rs:LL:CC = note: inside `std::rt::lang_start::<()>` at RUSTLIB/std/src/rt.rs:LL:CC -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr index 2bf91b676c4c0..78008e92642cd 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr @@ -29,5 +29,5 @@ LL | foo(&mut (1, 2)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr index d357ab9639b40..b9ae34df0775c 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr @@ -30,5 +30,5 @@ LL | match foo(&mut (1, 2)) { note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr index d346e6fa89597..7522115c5166b 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr @@ -30,5 +30,5 @@ LL | foo(&mut (1, 2)).0; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr index 10f97180b7540..b5106c9d94047 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr @@ -24,5 +24,5 @@ LL | shr_rw.set(1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr index 0e37c4ffb394c..ccea83db8574e 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr @@ -24,5 +24,5 @@ LL | shr_rw.replace(1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.stderr b/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.stderr index ca99a8262b8bd..f605fa9d3b962 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.stderr @@ -11,5 +11,5 @@ LL | std::mem::transmute::<&usize, &mut usize>(&X) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr b/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr index 05be0d3f1e98a..f341222a664c3 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr @@ -24,5 +24,5 @@ LL | callee(xraw); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr index ac962311d4260..7d8132b85c89e 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr @@ -19,5 +19,5 @@ LL | let raw = (&mut x[1] as *mut i32).wrapping_offset(-1); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/unescaped_local.stderr b/src/tools/miri/tests/fail/stacked_borrows/unescaped_local.stderr index 4deafa890005b..50c02b3455e4f 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/unescaped_local.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/unescaped_local.stderr @@ -14,5 +14,5 @@ LL | *raw = 13; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr b/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr index 7a40d1078b3b7..7578b89708a82 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr @@ -19,5 +19,5 @@ LL | let ptr_to_first = &ARRAY[0] as *const u8; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs index fd51fa6468a04..be4dac9957d62 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.rs @@ -1,11 +1,10 @@ //@compile-flags: -Zmiri-strict-provenance -//@error-in-other-file: /retag .* tag does not exist in the borrow stack/ fn main() { unsafe { let a = [1, 2, 3]; let s = &a[0..0]; assert_eq!(s.len(), 0); - assert_eq!(*s.get_unchecked(1), 2); + assert_eq!(*s.as_ptr().add(1), 2); //~ ERROR: /retag .* tag does not exist in the borrow stack/ } } diff --git a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr index 950abc4cbcf92..acae479ced28e 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr @@ -1,28 +1,24 @@ error: Undefined Behavior: trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - --> RUSTLIB/core/src/slice/mod.rs:LL:CC + --> $DIR/zst_slice.rs:LL:CC | -LL | unsafe { &*index.get_unchecked(self) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location - | this error occurs as part of retag at ALLOC[0x4..0x8] +LL | assert_eq!(*s.as_ptr().add(1), 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | trying to retag from for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x4..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information help: would have been created here, but this is a zero-size retag ([0x0..0x0]) so the tag in question does not exist anywhere --> $DIR/zst_slice.rs:LL:CC | -LL | assert_eq!(*s.get_unchecked(1), 2); - | ^^^^^^^^^^^^^^^^^^ +LL | assert_eq!(*s.as_ptr().add(1), 2); + | ^^^^^^^^^^ = note: BACKTRACE (of the first span): - = note: inside `core::slice::::get_unchecked::` at RUSTLIB/core/src/slice/mod.rs:LL:CC -note: inside `main` - --> $DIR/zst_slice.rs:LL:CC - | -LL | assert_eq!(*s.get_unchecked(1), 2); - | ^^^^^^^^^^^^^^^^^^ + = note: inside `main` at RUSTLIB/core/src/macros/mod.rs:LL:CC + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/static_memory_modification1.stderr b/src/tools/miri/tests/fail/static_memory_modification1.stderr index 5e7213ee6088e..877cf1d6e4739 100644 --- a/src/tools/miri/tests/fail/static_memory_modification1.stderr +++ b/src/tools/miri/tests/fail/static_memory_modification1.stderr @@ -11,5 +11,5 @@ LL | *std::mem::transmute::<&usize, &mut usize>(&X) = 6; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/static_memory_modification2.stderr b/src/tools/miri/tests/fail/static_memory_modification2.stderr index 4c160cd320688..77bbace4696b1 100644 --- a/src/tools/miri/tests/fail/static_memory_modification2.stderr +++ b/src/tools/miri/tests/fail/static_memory_modification2.stderr @@ -11,5 +11,5 @@ LL | transmute::<&[u8], &mut [u8]>(s.as_bytes())[4] = 42; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/static_memory_modification3.stderr b/src/tools/miri/tests/fail/static_memory_modification3.stderr index 1986059c50a8e..a04609805cb84 100644 --- a/src/tools/miri/tests/fail/static_memory_modification3.stderr +++ b/src/tools/miri/tests/fail/static_memory_modification3.stderr @@ -11,5 +11,5 @@ LL | transmute::<&[u8], &mut [u8]>(bs)[4] = 42; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr index dc634df831f1f..be66bad6fc35b 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.stderr +++ b/src/tools/miri/tests/fail/terminate-terminator.stderr @@ -41,5 +41,5 @@ LL | panic_abort(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.rs b/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs similarity index 100% rename from src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.rs rename to src/tools/miri/tests/fail/tls/tls_static_dealloc.rs diff --git a/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.stderr b/src/tools/miri/tests/fail/tls/tls_static_dealloc.stderr similarity index 79% rename from src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.stderr rename to src/tools/miri/tests/fail/tls/tls_static_dealloc.stderr index 7069e8cccfee1..a49933b7d0574 100644 --- a/src/tools/miri/tests/fail/concurrency/thread_local_static_dealloc.stderr +++ b/src/tools/miri/tests/fail/tls/tls_static_dealloc.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling - --> $DIR/thread_local_static_dealloc.rs:LL:CC + --> $DIR/tls_static_dealloc.rs:LL:CC | LL | let _val = *dangling_ptr.0; | ^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling @@ -7,9 +7,9 @@ LL | let _val = *dangling_ptr.0; = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/thread_local_static_dealloc.rs:LL:CC + = note: inside `main` at $DIR/tls_static_dealloc.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tls_macro_leak.rs b/src/tools/miri/tests/fail/tls_macro_leak.rs new file mode 100644 index 0000000000000..996d7ed4a2360 --- /dev/null +++ b/src/tools/miri/tests/fail/tls_macro_leak.rs @@ -0,0 +1,21 @@ +//@error-in-other-file: memory leaked +//@normalize-stderr-test: ".*│.*" -> "$$stripped$$" + +use std::cell::Cell; + +pub fn main() { + thread_local! { + static TLS: Cell> = Cell::new(None); + } + + std::thread::spawn(|| { + TLS.with(|cell| { + cell.set(Some(Box::leak(Box::new(123)))); + }); + }) + .join() + .unwrap(); + + // Imagine the program running for a long time while the thread is gone + // and this memory still sits around, unused -- leaked. +} diff --git a/src/tools/miri/tests/fail/tls_macro_leak.stderr b/src/tools/miri/tests/fail/tls_macro_leak.stderr new file mode 100644 index 0000000000000..be0e846b63369 --- /dev/null +++ b/src/tools/miri/tests/fail/tls_macro_leak.stderr @@ -0,0 +1,32 @@ +error: memory leaked: ALLOC (Rust heap, size: 4, align: 4), allocated here: + --> RUSTLIB/alloc/src/alloc.rs:LL:CC + | +LL | __rust_alloc(layout.size(), layout.align()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `::allocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `alloc::alloc::exchange_malloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `std::boxed::Box::::new` at RUSTLIB/alloc/src/boxed.rs:LL:CC +note: inside closure + --> $DIR/tls_macro_leak.rs:LL:CC + | +LL | cell.set(Some(Box::leak(Box::new(123)))); + | ^^^^^^^^^^^^^ + = note: inside `std::thread::LocalKey::>>::try_with::<{closure@$DIR/tls_macro_leak.rs:LL:CC}, ()>` at RUSTLIB/std/src/thread/local.rs:LL:CC + = note: inside `std::thread::LocalKey::>>::with::<{closure@$DIR/tls_macro_leak.rs:LL:CC}, ()>` at RUSTLIB/std/src/thread/local.rs:LL:CC +note: inside closure + --> $DIR/tls_macro_leak.rs:LL:CC + | +LL | / TLS.with(|cell| { +LL | | cell.set(Some(Box::leak(Box::new(123)))); +LL | | }); + | |__________^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tls_static_leak.rs b/src/tools/miri/tests/fail/tls_static_leak.rs new file mode 100644 index 0000000000000..637d648fb3fbf --- /dev/null +++ b/src/tools/miri/tests/fail/tls_static_leak.rs @@ -0,0 +1,22 @@ +//@error-in-other-file: memory leaked +//@normalize-stderr-test: ".*│.*" -> "$$stripped$$" + +#![feature(thread_local)] + +use std::cell::Cell; + +/// Ensure that leaks through `thread_local` statics *not in the main thread* +/// are detected. +pub fn main() { + #[thread_local] + static TLS: Cell> = Cell::new(None); + + std::thread::spawn(|| { + TLS.set(Some(Box::leak(Box::new(123)))); + }) + .join() + .unwrap(); + + // Imagine the program running for a long time while the thread is gone + // and this memory still sits around, unused -- leaked. +} diff --git a/src/tools/miri/tests/fail/tls_static_leak.stderr b/src/tools/miri/tests/fail/tls_static_leak.stderr new file mode 100644 index 0000000000000..533651f2efd7f --- /dev/null +++ b/src/tools/miri/tests/fail/tls_static_leak.stderr @@ -0,0 +1,23 @@ +error: memory leaked: ALLOC (Rust heap, size: 4, align: 4), allocated here: + --> RUSTLIB/alloc/src/alloc.rs:LL:CC + | +LL | __rust_alloc(layout.size(), layout.align()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `::allocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `alloc::alloc::exchange_malloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC + = note: inside `std::boxed::Box::::new` at RUSTLIB/alloc/src/boxed.rs:LL:CC +note: inside closure + --> $DIR/tls_static_leak.rs:LL:CC + | +LL | TLS.set(Some(Box::leak(Box::new(123)))); + | ^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.stderr b/src/tools/miri/tests/fail/transmute-pair-uninit.stderr index 642bf0a713436..30306054fbb3a 100644 --- a/src/tools/miri/tests/fail/transmute-pair-uninit.stderr +++ b/src/tools/miri/tests/fail/transmute-pair-uninit.stderr @@ -11,5 +11,5 @@ LL | let v = unsafe { *z.offset(first_undef) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/alternate-read-write.stderr b/src/tools/miri/tests/fail/tree_borrows/alternate-read-write.stderr index fcbc2e1278637..58d22c5641fbc 100644 --- a/src/tools/miri/tests/fail/tree_borrows/alternate-read-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/alternate-read-write.stderr @@ -34,5 +34,5 @@ LL | let _val = *x; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/children-can-alias.default.stderr b/src/tools/miri/tests/fail/tree_borrows/children-can-alias.default.stderr index 1b05be9c54db2..87286f1a1a62a 100644 --- a/src/tools/miri/tests/fail/tree_borrows/children-can-alias.default.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/children-can-alias.default.stderr @@ -11,5 +11,5 @@ LL | std::hint::unreachable_unchecked(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/children-can-alias.uniq.stderr b/src/tools/miri/tests/fail/tree_borrows/children-can-alias.uniq.stderr index 2f77b27729e7a..be85e1a1cee41 100644 --- a/src/tools/miri/tests/fail/tree_borrows/children-can-alias.uniq.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/children-can-alias.uniq.stderr @@ -33,5 +33,5 @@ LL | raw_children_of_unique_can_alias(Unique::new_unchecked(raw)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/error-range.stderr b/src/tools/miri/tests/fail/tree_borrows/error-range.stderr index b58dcd7572b1f..a03869f33bb9f 100644 --- a/src/tools/miri/tests/fail/tree_borrows/error-range.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/error-range.stderr @@ -28,5 +28,5 @@ LL | data[5] = 1; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/fnentry_invalidation.stderr b/src/tools/miri/tests/fail/tree_borrows/fnentry_invalidation.stderr index 0f1e7735a0e31..7df6cd9d9238d 100644 --- a/src/tools/miri/tests/fail/tree_borrows/fnentry_invalidation.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/fnentry_invalidation.stderr @@ -28,5 +28,5 @@ LL | x.do_bad(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/outside-range.stderr b/src/tools/miri/tests/fail/tree_borrows/outside-range.stderr index 8b3bf8414db03..5644862d23e70 100644 --- a/src/tools/miri/tests/fail/tree_borrows/outside-range.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/outside-range.stderr @@ -28,5 +28,5 @@ LL | stuff(&mut *raw, raw); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr b/src/tools/miri/tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr index addba9d809ef7..a9d5b0a68c154 100644 --- a/src/tools/miri/tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr @@ -29,5 +29,5 @@ LL | assert_eq!(root, 0); // Parent Read note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/pass_invalid_mut.stderr b/src/tools/miri/tests/fail/tree_borrows/pass_invalid_mut.stderr index 056ac6db5503d..32cf1c18cde7c 100644 --- a/src/tools/miri/tests/fail/tree_borrows/pass_invalid_mut.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/pass_invalid_mut.stderr @@ -39,5 +39,5 @@ LL | foo(xref); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.rs b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.rs index 465679b72c343..7af1a7636fad7 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.rs @@ -1,4 +1,5 @@ -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 // Check how a Reserved with interior mutability // responds to a Foreign Write under a Protector diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr index fc92770ed165c..ba6c30cf9354e 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr @@ -38,5 +38,5 @@ LL | write_second(x, y); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.rs b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.rs index 1e6e2eebd26ce..e23fe56534415 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.rs @@ -1,4 +1,5 @@ -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 #[path = "../../../utils/mod.rs"] #[macro_use] diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr index 4b4b8f24a68f5..16081871d9432 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/int-protected-write.stderr @@ -38,5 +38,5 @@ LL | write_second(x, y); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/return_invalid_mut.stderr b/src/tools/miri/tests/fail/tree_borrows/return_invalid_mut.stderr index 978e5a340faf3..dff2374ba9f45 100644 --- a/src/tools/miri/tests/fail/tree_borrows/return_invalid_mut.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/return_invalid_mut.stderr @@ -34,5 +34,5 @@ LL | let _val = unsafe { *xraw }; // invalidate xref for writing note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr b/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr index 99ffb84933901..e48145567f579 100644 --- a/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/spurious_read.stderr @@ -40,5 +40,5 @@ LL | let _y = as_mut(unsafe { &mut *ptr.0 }, b.clone()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/strongly-protected.stderr b/src/tools/miri/tests/fail/tree_borrows/strongly-protected.stderr index fb2e77f9d2aa2..4793c2870454b 100644 --- a/src/tools/miri/tests/fail/tree_borrows/strongly-protected.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/strongly-protected.stderr @@ -45,5 +45,5 @@ LL | | }); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/unique.default.stderr b/src/tools/miri/tests/fail/tree_borrows/unique.default.stderr index eb4d5c10c2511..f058c61ec3b46 100644 --- a/src/tools/miri/tests/fail/tree_borrows/unique.default.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/unique.default.stderr @@ -28,5 +28,5 @@ LL | let _definitely_parent = data; // definitely Frozen by now note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/unique.uniq.stderr b/src/tools/miri/tests/fail/tree_borrows/unique.uniq.stderr index 2d8936f273fef..ba53a87f84ad9 100644 --- a/src/tools/miri/tests/fail/tree_borrows/unique.uniq.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/unique.uniq.stderr @@ -34,5 +34,5 @@ LL | let _maybe_parent = *rawptr; // maybe becomes Frozen note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.stderr b/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.stderr index 3a82d028704b7..35087b1146846 100644 --- a/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.stderr @@ -34,5 +34,5 @@ LL | | }); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tree_borrows/write_to_shr.stderr b/src/tools/miri/tests/fail/tree_borrows/write_to_shr.stderr index 0e2002c34f12f..f57b28cbf44c6 100644 --- a/src/tools/miri/tests/fail/tree_borrows/write_to_shr.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/write_to_shr.stderr @@ -22,5 +22,5 @@ LL | let xref = unsafe { &*(x as *mut u64) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/type-too-large.stderr b/src/tools/miri/tests/fail/type-too-large.stderr index cb1d725ec878c..cdff049198d37 100644 --- a/src/tools/miri/tests/fail/type-too-large.stderr +++ b/src/tools/miri/tests/fail/type-too-large.stderr @@ -8,5 +8,5 @@ LL | _fat = [0; (1u64 << 61) as usize + (1u64 << 31) as usize]; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/alignment.stderr b/src/tools/miri/tests/fail/unaligned_pointers/alignment.stderr index 5fdec1dc74c6d..ca3d34661d38d 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/alignment.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/alignment.stderr @@ -11,5 +11,5 @@ LL | *(x_ptr as *mut u32) = 42; *(x_ptr.add(1) as *mut u32) = 42; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr b/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr index 8c3aa3429af5f..161e8977bf4ab 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr @@ -11,5 +11,5 @@ LL | ::std::intrinsics::atomic_load_seqcst(zptr); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr index db35a20ee222d..600028337fa6d 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr @@ -16,5 +16,5 @@ LL | core::ptr::drop_in_place(p); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr index cfb43ae891fe9..05e30f833bb2d 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr @@ -11,5 +11,5 @@ LL | let _ptr = &*ptr; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr index 2ffbc2a434e37..9046502975d47 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment.stderr @@ -16,5 +16,5 @@ LL | foo(odd_ptr.cast()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.stderr b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.stderr index 6d96c62545ae8..0d0057a79abc3 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/field_requires_parent_struct_alignment2.stderr @@ -16,5 +16,5 @@ LL | foo(odd_ptr.cast()); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.stderr b/src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.stderr index 9342b269993a6..318004da6013a 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/intptrcast_alignment_check.stderr @@ -11,5 +11,5 @@ LL | unsafe { *u16_ptr = 2 }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.call_unaligned_ptr.stderr b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.call_unaligned_ptr.stderr new file mode 100644 index 0000000000000..e23ac5ac2fc5d --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.call_unaligned_ptr.stderr @@ -0,0 +1,14 @@ +error: unsupported operation: `miri_promise_symbolic_alignment`: pointer is not actually aligned + --> $DIR/promise_alignment.rs:LL:CC + | +LL | unsafe { utils::miri_promise_symbolic_alignment(align8.add(1).cast(), 8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `miri_promise_symbolic_alignment`: pointer is not actually aligned + | + = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support + = note: BACKTRACE: + = note: inside `main` at $DIR/promise_alignment.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.read_unaligned_ptr.stderr b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.read_unaligned_ptr.stderr new file mode 100644 index 0000000000000..0842ccd6d5bb6 --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.read_unaligned_ptr.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: accessing memory based on pointer with alignment ALIGN, but alignment ALIGN is required + --> $DIR/promise_alignment.rs:LL:CC + | +LL | let _val = unsafe { align8.cast::().read() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory based on pointer with alignment ALIGN, but alignment ALIGN is required + | + = help: this usually indicates that your program performed an invalid operation and caused Undefined Behavior + = help: but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives + = note: BACKTRACE: + = note: inside `main` at $DIR/promise_alignment.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.rs b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.rs new file mode 100644 index 0000000000000..82753fe803caf --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment.rs @@ -0,0 +1,46 @@ +//@compile-flags: -Zmiri-symbolic-alignment-check +//@revisions: call_unaligned_ptr read_unaligned_ptr +#![feature(strict_provenance)] + +#[path = "../../utils/mod.rs"] +mod utils; + +#[repr(align(8))] +#[derive(Copy, Clone)] +struct Align8(u64); + +fn main() { + let buffer = [0u32; 128]; // get some 4-aligned memory + let buffer = buffer.as_ptr(); + // "Promising" the alignment down to 1 must not hurt. + unsafe { utils::miri_promise_symbolic_alignment(buffer.cast(), 1) }; + let _val = unsafe { buffer.read() }; + + // Let's find a place to promise alignment 8. + let align8 = if buffer.addr() % 8 == 0 { buffer } else { buffer.wrapping_add(1) }; + assert!(align8.addr() % 8 == 0); + unsafe { utils::miri_promise_symbolic_alignment(align8.cast(), 8) }; + // Promising the alignment down to 1 *again* still must not hurt. + unsafe { utils::miri_promise_symbolic_alignment(buffer.cast(), 1) }; + // Now we can do 8-aligned reads here. + let _val = unsafe { align8.cast::().read() }; + + // Make sure we error if the pointer is not actually aligned. + if cfg!(call_unaligned_ptr) { + unsafe { utils::miri_promise_symbolic_alignment(align8.add(1).cast(), 8) }; + //~[call_unaligned_ptr]^ ERROR: pointer is not actually aligned + } + + // Also don't accept even higher-aligned reads. + if cfg!(read_unaligned_ptr) { + #[repr(align(16))] + #[derive(Copy, Clone)] + struct Align16(u128); + + let align16 = if align8.addr() % 16 == 0 { align8 } else { align8.wrapping_add(2) }; + assert!(align16.addr() % 16 == 0); + + let _val = unsafe { align8.cast::().read() }; + //~[read_unaligned_ptr]^ ERROR: accessing memory based on pointer with alignment 8, but alignment 16 is required + } +} diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.rs b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.rs new file mode 100644 index 0000000000000..5b0638b1fdfaf --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.rs @@ -0,0 +1,8 @@ +#[path = "../../utils/mod.rs"] +mod utils; + +fn main() { + let buffer = [0u32; 128]; + unsafe { utils::miri_promise_symbolic_alignment(buffer.as_ptr().cast(), 0) }; + //~^ERROR: alignment must be a power of 2 +} diff --git a/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr new file mode 100644 index 0000000000000..b3327e04933d5 --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/promise_alignment_zero.stderr @@ -0,0 +1,14 @@ +error: unsupported operation: `miri_promise_symbolic_alignment`: alignment must be a power of 2, got 0 + --> $DIR/promise_alignment_zero.rs:LL:CC + | +LL | unsafe { utils::miri_promise_symbolic_alignment(buffer.as_ptr().cast(), 0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `miri_promise_symbolic_alignment`: alignment must be a power of 2, got 0 + | + = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support + = note: BACKTRACE: + = note: inside `main` at $DIR/promise_alignment_zero.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.stderr b/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.stderr index fb588854b2a78..938a037572995 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.stderr @@ -16,5 +16,5 @@ LL | let p: &i32 = unsafe { raw_to_ref(ptr::addr_of!(foo.x)) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.stderr b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.stderr index daebabf45571a..ae3be1ed3afb0 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr1.stderr @@ -11,5 +11,5 @@ LL | let _x = unsafe { *x }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.stderr b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.stderr index 38902e693dc8e..2b92602749820 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr2.stderr @@ -11,5 +11,5 @@ LL | let _x = unsafe { *x }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.stderr b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.stderr index 36a13b6331915..5ac4e23bf015e 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr3.stderr @@ -11,5 +11,5 @@ LL | let _x = unsafe { *x }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.stderr b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.stderr index 8d7a62c38503c..4de90118b4b88 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr4.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { *ptr }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.stderr b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.stderr index 7481179f26a01..72db125074b59 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ptr_zst.stderr @@ -11,5 +11,5 @@ LL | let _x = unsafe { *x }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ref_addr_of.stderr b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ref_addr_of.stderr index e47226ecdc7bc..448023a2a3d8f 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ref_addr_of.stderr +++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ref_addr_of.stderr @@ -11,5 +11,5 @@ LL | let _x = unsafe { &*x }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.rs b/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.rs new file mode 100644 index 0000000000000..98f9cc96fd0f9 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.rs @@ -0,0 +1,27 @@ +#![feature(core_intrinsics)] +#![feature(custom_mir)] + +use std::intrinsics::mir::*; +use std::ptr; + +#[repr(C)] +struct S(u8, u16); + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn main() { + mir! { + let s: S; + let sptr; + let sptr2; + let _val; + { + sptr = ptr::addr_of_mut!(s); + sptr2 = sptr as *mut [u8; 4]; + *sptr2 = [0; 4]; + *sptr = S(0, 0); // should reset the padding + _val = *sptr2; // should hence be UB + //~^ERROR: encountered uninitialized memory + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.stderr b/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.stderr new file mode 100644 index 0000000000000..5f3d9bde1f244 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer + --> $DIR/uninit-after-aggregate-assign.rs:LL:CC + | +LL | _val = *sptr2; // should hence be UB + | ^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/uninit-after-aggregate-assign.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit_buffer.rs b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.rs similarity index 93% rename from src/tools/miri/tests/fail/uninit_buffer.rs rename to src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.rs index d622b2fa7d812..8deaa30d50ff2 100644 --- a/src/tools/miri/tests/fail/uninit_buffer.rs +++ b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.rs @@ -1,3 +1,4 @@ +//@compile-flags: -Zmiri-disable-validation //@error-in-other-file: memory is uninitialized at [0x4..0x10] #![allow(dropping_copy_types)] diff --git a/src/tools/miri/tests/fail/uninit_buffer.stderr b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.stderr similarity index 94% rename from src/tools/miri/tests/fail/uninit_buffer.stderr rename to src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.stderr index 90210bf7f11a4..cca17a07ec208 100644 --- a/src/tools/miri/tests/fail/uninit_buffer.stderr +++ b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic.stderr @@ -10,7 +10,7 @@ LL | let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr( = note: inside `::compare` at RUSTLIB/core/src/slice/cmp.rs:LL:CC = note: inside `core::slice::cmp::::cmp` at RUSTLIB/core/src/slice/cmp.rs:LL:CC note: inside `main` - --> $DIR/uninit_buffer.rs:LL:CC + --> $DIR/uninit_alloc_diagnostic.rs:LL:CC | LL | drop(slice1.cmp(slice2)); | ^^^^^^^^^^^^^^^^^^ @@ -23,5 +23,5 @@ ALLOC (Rust heap, size: 32, align: 8) { 0x10 │ 00 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ .░░░░░░░░░░░░░░░ } -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.rs similarity index 96% rename from src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs rename to src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.rs index ca825901372c5..adabff4a2cea2 100644 --- a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs +++ b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.rs @@ -1,3 +1,4 @@ +//@compile-flags: -Zmiri-disable-validation //@error-in-other-file: memory is uninitialized at [0x4..0x8] //@normalize-stderr-test: "a[0-9]+" -> "ALLOC" #![feature(strict_provenance)] diff --git a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr similarity index 94% rename from src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr rename to src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr index 701ec6013696f..4dc2d27ead433 100644 --- a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr +++ b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr @@ -10,7 +10,7 @@ LL | let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr( = note: inside `::compare` at RUSTLIB/core/src/slice/cmp.rs:LL:CC = note: inside `core::slice::cmp::::cmp` at RUSTLIB/core/src/slice/cmp.rs:LL:CC note: inside `main` - --> $DIR/uninit_buffer_with_provenance.rs:LL:CC + --> $DIR/uninit_alloc_diagnostic_with_provenance.rs:LL:CC | LL | drop(slice1.cmp(slice2)); | ^^^^^^^^^^^^^^^^^^ @@ -28,5 +28,5 @@ ALLOC (global (static or const), size: 1, align: 1) { 00 │ . } -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit_byte_read.rs b/src/tools/miri/tests/fail/uninit/uninit_byte_read.rs similarity index 70% rename from src/tools/miri/tests/fail/uninit_byte_read.rs rename to src/tools/miri/tests/fail/uninit/uninit_byte_read.rs index f1dace0cff9b1..9bc2b4338b0db 100644 --- a/src/tools/miri/tests/fail/uninit_byte_read.rs +++ b/src/tools/miri/tests/fail/uninit/uninit_byte_read.rs @@ -1,7 +1,7 @@ //@compile-flags: -Zmiri-disable-stacked-borrows fn main() { let v: Vec = Vec::with_capacity(10); - let undef = unsafe { *v.get_unchecked(5) }; //~ ERROR: uninitialized + let undef = unsafe { *v.as_ptr().add(5) }; //~ ERROR: uninitialized let x = undef + 1; panic!("this should never print: {}", x); } diff --git a/src/tools/miri/tests/fail/uninit_byte_read.stderr b/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr similarity index 72% rename from src/tools/miri/tests/fail/uninit_byte_read.stderr rename to src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr index 9f7638888d643..3917d868289ea 100644 --- a/src/tools/miri/tests/fail/uninit_byte_read.stderr +++ b/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/uninit_byte_read.rs:LL:CC | -LL | let undef = unsafe { *v.get_unchecked(5) }; - | ^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory +LL | let undef = unsafe { *v.as_ptr().add(5) }; + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information @@ -11,5 +11,5 @@ LL | let undef = unsafe { *v.get_unchecked(5) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unreachable.stderr b/src/tools/miri/tests/fail/unreachable.stderr index a57d731f1f713..f6982dc86535e 100644 --- a/src/tools/miri/tests/fail/unreachable.stderr +++ b/src/tools/miri/tests/fail/unreachable.stderr @@ -11,5 +11,5 @@ LL | unsafe { std::hint::unreachable_unchecked() } note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unsized-local.stderr b/src/tools/miri/tests/fail/unsized-local.stderr index 07f94f3b91b33..0ffda9e6d6317 100644 --- a/src/tools/miri/tests/fail/unsized-local.stderr +++ b/src/tools/miri/tests/fail/unsized-local.stderr @@ -10,5 +10,5 @@ LL | let x = *(Box::new(A) as Box); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unsupported_foreign_function.stderr b/src/tools/miri/tests/fail/unsupported_foreign_function.stderr index 519f6d182d7d8..5a2f415bb84b0 100644 --- a/src/tools/miri/tests/fail/unsupported_foreign_function.stderr +++ b/src/tools/miri/tests/fail/unsupported_foreign_function.stderr @@ -10,5 +10,5 @@ LL | foo(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr index 7575300bc575c..a7543df340dff 100644 --- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr +++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr @@ -33,5 +33,5 @@ LL | panic_abort(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr index 21e403b47f8d8..f526f77a4f000 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr @@ -11,5 +11,5 @@ LL | g(0usize as *const i32) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr index ccfb889093993..7d481940acec9 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr @@ -11,5 +11,5 @@ LL | f(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs index ee80186d4b50b..9357b37250508 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs @@ -20,7 +20,7 @@ fn call(f: fn(NonZeroU32)) { let tmp = ptr::addr_of!(c); let ptr = tmp as *const NonZeroU32; // The call site now is a NonZeroU32-to-u32 transmute. - Call(_res = f(*ptr), retblock) //~ERROR: expected something greater or equal to 1 + Call(_res = f(*ptr), retblock, UnwindContinue()) //~ERROR: expected something greater or equal to 1 } retblock = { Return() diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr index 234c280400861..9e9ea710f0e47 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1 --> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC | -LL | Call(_res = f(*ptr), retblock) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 +LL | Call(_res = f(*ptr), retblock, UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | = 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 @@ -16,5 +16,5 @@ LL | call(f); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr index bd9866acbd4fd..7593b8a399873 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr @@ -11,5 +11,5 @@ LL | let _x = g(); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/dangling_ref1.stderr b/src/tools/miri/tests/fail/validity/dangling_ref1.stderr index 830ab9ca501d8..fd4dd502bd5c1 100644 --- a/src/tools/miri/tests/fail/validity/dangling_ref1.stderr +++ b/src/tools/miri/tests/fail/validity/dangling_ref1.stderr @@ -11,5 +11,5 @@ LL | let _x: &i32 = unsafe { mem::transmute(16usize) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/dangling_ref2.stderr b/src/tools/miri/tests/fail/validity/dangling_ref2.stderr index 4be4e8075a728..2d45ae68ca474 100644 --- a/src/tools/miri/tests/fail/validity/dangling_ref2.stderr +++ b/src/tools/miri/tests/fail/validity/dangling_ref2.stderr @@ -11,5 +11,5 @@ LL | let _x: &i32 = unsafe { mem::transmute(ptr) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/dangling_ref3.stderr b/src/tools/miri/tests/fail/validity/dangling_ref3.stderr index 4b7bdf7823686..5ac4f5deffe7c 100644 --- a/src/tools/miri/tests/fail/validity/dangling_ref3.stderr +++ b/src/tools/miri/tests/fail/validity/dangling_ref3.stderr @@ -11,5 +11,5 @@ LL | let _x: &i32 = unsafe { mem::transmute(dangling()) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_bool.stderr b/src/tools/miri/tests/fail/validity/invalid_bool.stderr index 3972787a4d2fd..3ed823dde9427 100644 --- a/src/tools/miri/tests/fail/validity/invalid_bool.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_bool.stderr @@ -11,5 +11,5 @@ LL | let _b = unsafe { std::mem::transmute::(2) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/invalid_bool.rs b/src/tools/miri/tests/fail/validity/invalid_bool_op.rs similarity index 100% rename from src/tools/miri/tests/fail/invalid_bool.rs rename to src/tools/miri/tests/fail/validity/invalid_bool_op.rs diff --git a/src/tools/miri/tests/fail/invalid_bool.stderr b/src/tools/miri/tests/fail/validity/invalid_bool_op.stderr similarity index 81% rename from src/tools/miri/tests/fail/invalid_bool.stderr rename to src/tools/miri/tests/fail/validity/invalid_bool_op.stderr index a522f6cd4fffe..b938d29e760ad 100644 --- a/src/tools/miri/tests/fail/invalid_bool.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_bool_op.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: interpreting an invalid 8-bit value as a bool: 0x02 - --> $DIR/invalid_bool.rs:LL:CC + --> $DIR/invalid_bool_op.rs:LL:CC | LL | let _x = b == std::hint::black_box(true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ interpreting an invalid 8-bit value as a bool: 0x02 @@ -7,9 +7,9 @@ LL | let _x = b == std::hint::black_box(true); = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/invalid_bool.rs:LL:CC + = note: inside `main` at $DIR/invalid_bool_op.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_bool_uninit.stderr b/src/tools/miri/tests/fail/validity/invalid_bool_uninit.stderr index 5a7bd80e40c15..314416766a57a 100644 --- a/src/tools/miri/tests/fail/validity/invalid_bool_uninit.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_bool_uninit.stderr @@ -11,5 +11,5 @@ LL | let _b = unsafe { MyUninit { init: () }.uninit }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_char.stderr b/src/tools/miri/tests/fail/validity/invalid_char.stderr index eeff289dfa4e1..c761669c6db45 100644 --- a/src/tools/miri/tests/fail/validity/invalid_char.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_char.stderr @@ -11,5 +11,5 @@ LL | let _val = match unsafe { std::mem::transmute::(-1) } { note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/invalid_char.rs b/src/tools/miri/tests/fail/validity/invalid_char_op.rs similarity index 100% rename from src/tools/miri/tests/fail/invalid_char.rs rename to src/tools/miri/tests/fail/validity/invalid_char_op.rs diff --git a/src/tools/miri/tests/fail/invalid_char.stderr b/src/tools/miri/tests/fail/validity/invalid_char_op.stderr similarity index 80% rename from src/tools/miri/tests/fail/invalid_char.stderr rename to src/tools/miri/tests/fail/validity/invalid_char_op.stderr index d49d753d9e185..113eecd9cf7aa 100644 --- a/src/tools/miri/tests/fail/invalid_char.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_char_op.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: interpreting an invalid 32-bit value as a char: $HEX - --> $DIR/invalid_char.rs:LL:CC + --> $DIR/invalid_char_op.rs:LL:CC | LL | let _x = c == 'x'; | ^^^^^^^^ interpreting an invalid 32-bit value as a char: $HEX @@ -7,9 +7,9 @@ LL | let _x = c == 'x'; = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/invalid_char.rs:LL:CC + = note: inside `main` at $DIR/invalid_char_op.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_char_uninit.stderr b/src/tools/miri/tests/fail/validity/invalid_char_uninit.stderr index fb5d3ee1f1f9c..34babac4dd330 100644 --- a/src/tools/miri/tests/fail/validity/invalid_char_uninit.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_char_uninit.stderr @@ -11,5 +11,5 @@ LL | let _b = unsafe { MyUninit { init: () }.uninit }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/invalid_enum_tag.rs b/src/tools/miri/tests/fail/validity/invalid_enum_op.rs similarity index 100% rename from src/tools/miri/tests/fail/invalid_enum_tag.rs rename to src/tools/miri/tests/fail/validity/invalid_enum_op.rs diff --git a/src/tools/miri/tests/fail/invalid_enum_tag.stderr b/src/tools/miri/tests/fail/validity/invalid_enum_op.stderr similarity index 80% rename from src/tools/miri/tests/fail/invalid_enum_tag.stderr rename to src/tools/miri/tests/fail/validity/invalid_enum_op.stderr index 01d931de919a4..e7997689c51c0 100644 --- a/src/tools/miri/tests/fail/invalid_enum_tag.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_enum_op.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: enum value has invalid tag: $HEX - --> $DIR/invalid_enum_tag.rs:LL:CC + --> $DIR/invalid_enum_op.rs:LL:CC | LL | let _val = mem::discriminant(&f); | ^^^^^^^^^^^^^^^^^^^^^ enum value has invalid tag: $HEX @@ -7,9 +7,9 @@ LL | let _val = mem::discriminant(&f); = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/invalid_enum_tag.rs:LL:CC + = note: inside `main` at $DIR/invalid_enum_op.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_enum_tag.stderr b/src/tools/miri/tests/fail/validity/invalid_enum_tag.stderr index 9234b4d705a9d..5d27062fbc273 100644 --- a/src/tools/miri/tests/fail/validity/invalid_enum_tag.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_enum_tag.stderr @@ -11,5 +11,5 @@ LL | let _f = unsafe { std::mem::transmute::(42) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_fnptr_null.stderr b/src/tools/miri/tests/fail/validity/invalid_fnptr_null.stderr index 63fad1d56e38b..f781ca04f0334 100644 --- a/src/tools/miri/tests/fail/validity/invalid_fnptr_null.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_fnptr_null.stderr @@ -11,5 +11,5 @@ LL | let _b: fn() = unsafe { std::mem::transmute(0usize) }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_fnptr_uninit.stderr b/src/tools/miri/tests/fail/validity/invalid_fnptr_uninit.stderr index 35309e90136cb..54781b507e081 100644 --- a/src/tools/miri/tests/fail/validity/invalid_fnptr_uninit.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_fnptr_uninit.stderr @@ -11,5 +11,5 @@ LL | let _b = unsafe { MyUninit { init: () }.uninit }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/invalid_int.rs b/src/tools/miri/tests/fail/validity/invalid_int_op.rs similarity index 100% rename from src/tools/miri/tests/fail/invalid_int.rs rename to src/tools/miri/tests/fail/validity/invalid_int_op.rs diff --git a/src/tools/miri/tests/fail/invalid_int.stderr b/src/tools/miri/tests/fail/validity/invalid_int_op.stderr similarity index 84% rename from src/tools/miri/tests/fail/invalid_int.stderr rename to src/tools/miri/tests/fail/validity/invalid_int_op.stderr index eccdbff604574..df344311b7577 100644 --- a/src/tools/miri/tests/fail/invalid_int.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_int_op.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory - --> $DIR/invalid_int.rs:LL:CC + --> $DIR/invalid_int_op.rs:LL:CC | LL | let i = unsafe { std::mem::MaybeUninit::::uninit().assume_init() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory @@ -7,9 +7,9 @@ LL | let i = unsafe { std::mem::MaybeUninit::::uninit().assume_init() } = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/invalid_int.rs:LL:CC + = note: inside `main` at $DIR/invalid_int_op.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_wide_raw.stderr b/src/tools/miri/tests/fail/validity/invalid_wide_raw.stderr index cf12ab8dbd55a..ed34d5255a438 100644 --- a/src/tools/miri/tests/fail/validity/invalid_wide_raw.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_wide_raw.stderr @@ -11,5 +11,5 @@ LL | dbg!(S { x: unsafe { std::mem::transmute((0usize, 0usize)) } }); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr b/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr index c234467bddcbf..a1bfa267cbe0e 100644 --- a/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr +++ b/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr @@ -11,5 +11,5 @@ LL | _x => println!("hi from the void!"), note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr b/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr index 8af2d37d74a75..2d8238350f332 100644 --- a/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr +++ b/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr @@ -11,5 +11,5 @@ LL | _x => println!("hi from the void!"), note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/nonzero.stderr b/src/tools/miri/tests/fail/validity/nonzero.stderr index a9a68177ed973..2add8434ca562 100644 --- a/src/tools/miri/tests/fail/validity/nonzero.stderr +++ b/src/tools/miri/tests/fail/validity/nonzero.stderr @@ -11,5 +11,5 @@ LL | let _x = Some(unsafe { NonZero(0) }); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/ref_to_uninhabited1.stderr b/src/tools/miri/tests/fail/validity/ref_to_uninhabited1.stderr index 4facd2159c8d0..d893f7a9e545e 100644 --- a/src/tools/miri/tests/fail/validity/ref_to_uninhabited1.stderr +++ b/src/tools/miri/tests/fail/validity/ref_to_uninhabited1.stderr @@ -11,5 +11,5 @@ LL | let x: Box = transmute(&mut 42); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/ref_to_uninhabited2.stderr b/src/tools/miri/tests/fail/validity/ref_to_uninhabited2.stderr index 264465f939190..1d9c89c6880c8 100644 --- a/src/tools/miri/tests/fail/validity/ref_to_uninhabited2.stderr +++ b/src/tools/miri/tests/fail/validity/ref_to_uninhabited2.stderr @@ -11,5 +11,5 @@ LL | let _x: &(i32, Void) = transmute(&42); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/too-big-slice.stderr b/src/tools/miri/tests/fail/validity/too-big-slice.stderr index 6df00aefe7561..2abe6c6fdf3d0 100644 --- a/src/tools/miri/tests/fail/validity/too-big-slice.stderr +++ b/src/tools/miri/tests/fail/validity/too-big-slice.stderr @@ -11,5 +11,5 @@ LL | let _x: &[u8] = mem::transmute((ptr, usize::MAX)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/too-big-unsized.stderr b/src/tools/miri/tests/fail/validity/too-big-unsized.stderr index cbcb31b29fc30..bc8a140ac22c0 100644 --- a/src/tools/miri/tests/fail/validity/too-big-unsized.stderr +++ b/src/tools/miri/tests/fail/validity/too-big-unsized.stderr @@ -11,5 +11,5 @@ LL | let _x: &MySlice = mem::transmute((ptr, isize::MAX as usize)); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/transmute_through_ptr.stderr b/src/tools/miri/tests/fail/validity/transmute_through_ptr.stderr index ea155405cd610..fcd077daa38ff 100644 --- a/src/tools/miri/tests/fail/validity/transmute_through_ptr.stderr +++ b/src/tools/miri/tests/fail/validity/transmute_through_ptr.stderr @@ -11,5 +11,5 @@ LL | let y = x; // reading this ought to be enough to trigger validation note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/uninit_float.stderr b/src/tools/miri/tests/fail/validity/uninit_float.stderr index e95e3b18128d2..3d7ec44fdb064 100644 --- a/src/tools/miri/tests/fail/validity/uninit_float.stderr +++ b/src/tools/miri/tests/fail/validity/uninit_float.stderr @@ -11,5 +11,5 @@ LL | let _val: [f32; 1] = unsafe { std::mem::uninitialized() }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/uninit_integer.stderr b/src/tools/miri/tests/fail/validity/uninit_integer.stderr index 2156886cd71c1..55f3f803ad14c 100644 --- a/src/tools/miri/tests/fail/validity/uninit_integer.stderr +++ b/src/tools/miri/tests/fail/validity/uninit_integer.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { std::mem::MaybeUninit::<[usize; 1]>::uninit().assum note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error 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 bbae9cf69ffe1..fed1cf4587431 100644 --- a/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr +++ b/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { std::mem::MaybeUninit::<[*const u8; 1]>::uninit().a note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr index 03b5a4e4c1700..9f92853d0ec6a 100644 --- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr +++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr @@ -10,6 +10,7 @@ help: and (1) occurred earlier here LL | x.store(1, Relaxed); | ^^^^^^^^^^^^^^^^^^^ = help: overlapping unsynchronized atomic accesses must use the same access size + = help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model = 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 (of the first span): @@ -17,5 +18,5 @@ LL | x.store(1, Relaxed); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr index 05eba41f4d54f..a28dec2833fa7 100644 --- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr +++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr @@ -10,6 +10,7 @@ help: and (1) occurred earlier here LL | x.load(Relaxed); | ^^^^^^^^^^^^^^^ = help: overlapping unsynchronized atomic accesses must use the same access size + = help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model = 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 (of the first span): @@ -17,5 +18,5 @@ LL | x.load(Relaxed); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/zst1.stderr b/src/tools/miri/tests/fail/zst1.stderr index 07bf048ab6ec0..cda837da7e71c 100644 --- a/src/tools/miri/tests/fail/zst1.stderr +++ b/src/tools/miri/tests/fail/zst1.stderr @@ -11,5 +11,5 @@ LL | let _val = unsafe { *x }; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/zst2.stderr b/src/tools/miri/tests/fail/zst2.stderr index f42fb07edcd9b..b3f65e7866dc8 100644 --- a/src/tools/miri/tests/fail/zst2.stderr +++ b/src/tools/miri/tests/fail/zst2.stderr @@ -21,5 +21,5 @@ LL | drop(x_box); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/zst3.stderr b/src/tools/miri/tests/fail/zst3.stderr index f8b416ec348b6..b9495fbd2074f 100644 --- a/src/tools/miri/tests/fail/zst3.stderr +++ b/src/tools/miri/tests/fail/zst3.stderr @@ -16,5 +16,5 @@ LL | let mut x_box = Box::new(1u8); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/pass-dep/extra_fn_ptr_gc.rs b/src/tools/miri/tests/pass-dep/extra_fn_ptr_gc.rs new file mode 100644 index 0000000000000..716119a0fc344 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/extra_fn_ptr_gc.rs @@ -0,0 +1,21 @@ +//@ignore-target-windows: No libc on Windows +//@compile-flags: -Zmiri-permissive-provenance + +#[path = "../utils/mod.rs"] +mod utils; + +type GetEntropyFn = unsafe extern "C" fn(*mut u8, libc::size_t) -> libc::c_int; + +fn main() { + let name = "getentropy\0"; + let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize }; + // If the GC does not account for the extra_fn_ptr entry that this dlsym just added, this GC + // run will delete our entry for the base addr of the function pointer we will transmute to, + // and the call through the function pointer will report UB. + utils::run_provenance_gc(); + + let ptr = addr as *mut libc::c_void; + let func: GetEntropyFn = unsafe { std::mem::transmute(ptr) }; + let dest = &mut [0u8]; + unsafe { func(dest.as_mut_ptr(), dest.len()) }; +} diff --git a/src/tools/miri/tests/pass-dep/getrandom.rs b/src/tools/miri/tests/pass-dep/getrandom.rs new file mode 100644 index 0000000000000..c0d9296a9a6d9 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/getrandom.rs @@ -0,0 +1,10 @@ +// mac-os `getrandom_01` does some pointer shenanigans +//@compile-flags: -Zmiri-permissive-provenance + +/// Test direct calls of getrandom 0.1 and 0.2. +/// Make sure they work even with isolation enabled (i.e., we do not hit a file-based fallback path). +fn main() { + let mut data = vec![0; 16]; + getrandom_01::getrandom(&mut data).unwrap(); + getrandom_02::getrandom(&mut data).unwrap(); +} diff --git a/src/tools/miri/tests/pass-dep/getrandom_1.rs b/src/tools/miri/tests/pass-dep/getrandom_1.rs deleted file mode 100644 index 2c7bd93fbdb38..0000000000000 --- a/src/tools/miri/tests/pass-dep/getrandom_1.rs +++ /dev/null @@ -1,8 +0,0 @@ -// mac-os `getrandom_1` does some pointer shenanigans -//@compile-flags: -Zmiri-permissive-provenance - -/// Test old version of `getrandom`. -fn main() { - let mut data = vec![0; 16]; - getrandom_1::getrandom(&mut data).unwrap(); -} diff --git a/src/tools/miri/tests/pass-dep/random.rs b/src/tools/miri/tests/pass-dep/rand.rs similarity index 61% rename from src/tools/miri/tests/pass-dep/random.rs rename to src/tools/miri/tests/pass-dep/rand.rs index 0cd8b06d63d8a..0dce6d86cf481 100644 --- a/src/tools/miri/tests/pass-dep/random.rs +++ b/src/tools/miri/tests/pass-dep/rand.rs @@ -1,10 +1,13 @@ //@compile-flags: -Zmiri-strict-provenance -use rand::{rngs::SmallRng, Rng, SeedableRng}; +use rand::prelude::*; +// Test using the `rand` crate to generate randomness. fn main() { - // Test `getrandom` directly. - let mut data = vec![0; 16]; - getrandom::getrandom(&mut data).unwrap(); + // Fully deterministic seeding. + let mut rng = SmallRng::seed_from_u64(42); + let _val = rng.gen::(); + let _val = rng.gen::(); + let _val = rng.gen::(); // Try seeding with "real" entropy. let mut rng = SmallRng::from_entropy(); diff --git a/src/tools/miri/tests/pass-dep/shims/env-cleanup-data-race.rs b/src/tools/miri/tests/pass-dep/shims/env-cleanup-data-race.rs index d36ffe70321b4..5c29a1b15a792 100644 --- a/src/tools/miri/tests/pass-dep/shims/env-cleanup-data-race.rs +++ b/src/tools/miri/tests/pass-dep/shims/env-cleanup-data-race.rs @@ -2,15 +2,13 @@ //@ignore-target-windows: No libc on Windows use std::ffi::CStr; -use std::ffi::CString; use std::thread; fn main() { unsafe { thread::spawn(|| { // Access the environment in another thread without taking the env lock - let k = CString::new("MIRI_ENV_VAR_TEST".as_bytes()).unwrap(); - let s = libc::getenv(k.as_ptr()) as *const libc::c_char; + let s = libc::getenv("MIRI_ENV_VAR_TEST\0".as_ptr().cast()); if s.is_null() { panic!("null"); } @@ -19,5 +17,6 @@ fn main() { thread::yield_now(); // After the main thread exits, env vars will be cleaned up -- but because we have not *joined* // the other thread, those accesses technically race with those in the other thread. + // We don't want to emit an error here, though. } } diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs index 5185db0b0e29f..adfece586611d 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs @@ -1,4 +1,5 @@ //@ignore-target-windows: no libc on Windows +//@ignore-target-freebsd: FIXME needs foreign function `stat@FBSD_1.0` //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT" diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs index 767a4fdbede38..697970a0885df 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs @@ -23,6 +23,7 @@ fn main() { test_file_open_unix_extra_third_arg(); #[cfg(target_os = "linux")] test_o_tmpfile_flag(); + test_posix_mkstemp(); } /// Prepare: compute filename and make sure the file does not exist. @@ -151,3 +152,45 @@ fn test_o_tmpfile_flag() { .raw_os_error(), ); } + +fn test_posix_mkstemp() { + use std::ffi::OsStr; + use std::os::unix::io::FromRawFd; + use std::path::Path; + + let valid_template = "fooXXXXXX"; + // C needs to own this as `mkstemp(3)` says: + // "Since it will be modified, `template` must not be a string constant, but + // should be declared as a character array." + // There seems to be no `as_mut_ptr` on `CString` so we need to use `into_raw`. + let ptr = CString::new(valid_template).unwrap().into_raw(); + let fd = unsafe { libc::mkstemp(ptr) }; + // Take ownership back in Rust to not leak memory. + let slice = unsafe { CString::from_raw(ptr) }; + assert!(fd > 0); + let osstr = OsStr::from_bytes(slice.to_bytes()); + let path: &Path = osstr.as_ref(); + let name = path.file_name().unwrap().to_string_lossy(); + assert!(name.ne("fooXXXXXX")); + assert!(name.starts_with("foo")); + assert_eq!(name.len(), 9); + assert_eq!( + name.chars().skip(3).filter(char::is_ascii_alphanumeric).collect::>().len(), + 6 + ); + let file = unsafe { File::from_raw_fd(fd) }; + assert!(file.set_len(0).is_ok()); + + let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"]; + for t in invalid_templates { + let ptr = CString::new(t).unwrap().into_raw(); + let fd = unsafe { libc::mkstemp(ptr) }; + let _ = unsafe { CString::from_raw(ptr) }; + // "On error, -1 is returned, and errno is set to + // indicate the error" + assert_eq!(fd, -1); + let e = std::io::Error::last_os_error(); + assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); + assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput); + } +} diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs b/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs new file mode 100644 index 0000000000000..4b863f6851618 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/shims/libc-getentropy.rs @@ -0,0 +1,20 @@ +//@ignore-target-windows: no libc + +// on macOS this is not in the `libc` crate. +#[cfg(target_os = "macos")] +extern "C" { + fn getentropy(bytes: *mut libc::c_void, count: libc::size_t) -> libc::c_int; +} + +#[cfg(not(target_os = "macos"))] +use libc::getentropy; + +fn main() { + let mut buf1 = [0u8; 256]; + let mut buf2 = [0u8; 257]; + unsafe { + assert_eq!(getentropy(buf1.as_mut_ptr() as *mut libc::c_void, buf1.len()), 0); + assert_eq!(getentropy(buf2.as_mut_ptr() as *mut libc::c_void, buf2.len()), -1); + assert_eq!(std::io::Error::last_os_error().raw_os_error().unwrap(), libc::EIO); + } +} diff --git a/src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs b/src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs index a1436c7319d33..9c670cbd5070e 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-getrandom.rs @@ -1,10 +1,12 @@ -//@only-target-linux +//@ignore-target-windows: no libc +//@ignore-target-apple: no getrandom use std::ptr; fn main() { let mut buf = [0u8; 5]; unsafe { + #[cfg(target_os = "linux")] assert_eq!( libc::syscall( libc::SYS_getrandom, @@ -14,6 +16,7 @@ fn main() { ), 0, ); + #[cfg(target_os = "linux")] assert_eq!( libc::syscall( libc::SYS_getrandom, diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs index 40d3fa19e5301..abb384b0a857c 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs @@ -178,7 +178,7 @@ fn test_clocks() { assert_eq!(is_error, 0); let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "freebsd"))] { let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); @@ -237,50 +237,6 @@ fn test_isatty() { } } -fn test_posix_mkstemp() { - use std::ffi::CString; - use std::ffi::OsStr; - use std::os::unix::ffi::OsStrExt; - use std::os::unix::io::FromRawFd; - use std::path::Path; - - let valid_template = "fooXXXXXX"; - // C needs to own this as `mkstemp(3)` says: - // "Since it will be modified, `template` must not be a string constant, but - // should be declared as a character array." - // There seems to be no `as_mut_ptr` on `CString` so we need to use `into_raw`. - let ptr = CString::new(valid_template).unwrap().into_raw(); - let fd = unsafe { libc::mkstemp(ptr) }; - // Take ownership back in Rust to not leak memory. - let slice = unsafe { CString::from_raw(ptr) }; - assert!(fd > 0); - let osstr = OsStr::from_bytes(slice.to_bytes()); - let path: &Path = osstr.as_ref(); - let name = path.file_name().unwrap().to_string_lossy(); - assert!(name.ne("fooXXXXXX")); - assert!(name.starts_with("foo")); - assert_eq!(name.len(), 9); - assert_eq!( - name.chars().skip(3).filter(char::is_ascii_alphanumeric).collect::>().len(), - 6 - ); - let file = unsafe { File::from_raw_fd(fd) }; - assert!(file.set_len(0).is_ok()); - - let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"]; - for t in invalid_templates { - let ptr = CString::new(t).unwrap().into_raw(); - let fd = unsafe { libc::mkstemp(ptr) }; - let _ = unsafe { CString::from_raw(ptr) }; - // "On error, -1 is returned, and errno is set to - // indicate the error" - assert_eq!(fd, -1); - let e = std::io::Error::last_os_error(); - assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); - assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput); - } -} - fn test_memcpy() { unsafe { let src = [1i8, 2, 3]; @@ -388,9 +344,21 @@ fn test_dlsym() { assert_eq!(errno, libc::EBADF); } +#[cfg(not(target_os = "macos"))] +fn test_reallocarray() { + unsafe { + let mut p = libc::reallocarray(std::ptr::null_mut(), 4096, 2); + assert!(!p.is_null()); + libc::free(p); + p = libc::malloc(16); + let r = libc::reallocarray(p, 2, 32); + assert!(!r.is_null()); + libc::free(r); + } +} + fn main() { test_posix_gettimeofday(); - test_posix_mkstemp(); test_posix_realpath_alloc(); test_posix_realpath_noalloc(); @@ -399,12 +367,18 @@ fn main() { test_thread_local_errno(); test_isatty(); + test_clocks(); + test_dlsym(); test_memcpy(); test_strcpy(); + #[cfg(not(target_os = "macos"))] // reallocarray does not exist on macOS + test_reallocarray(); + + // These are Linux-specific #[cfg(target_os = "linux")] { test_posix_fadvise(); diff --git a/src/tools/miri/tests/pass-dep/shims/pthreads.rs b/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs similarity index 79% rename from src/tools/miri/tests/pass-dep/shims/pthreads.rs rename to src/tools/miri/tests/pass-dep/shims/pthread-sync.rs index 80b8d67401ad1..4cc5b7d68a3cc 100644 --- a/src/tools/miri/tests/pass-dep/shims/pthreads.rs +++ b/src/tools/miri/tests/pass-dep/shims/pthread-sync.rs @@ -1,13 +1,10 @@ //@ignore-target-windows: No libc on Windows -use std::ffi::{CStr, CString}; -use std::thread; fn main() { test_mutex_libc_init_recursive(); test_mutex_libc_init_normal(); test_mutex_libc_init_errorcheck(); test_rwlock_libc_static_initializer(); - test_named_thread_truncation(); #[cfg(target_os = "linux")] test_mutex_libc_static_initializer_recursive(); @@ -128,36 +125,3 @@ fn test_rwlock_libc_static_initializer() { assert_eq!(libc::pthread_rwlock_destroy(rw.get()), 0); } } - -fn test_named_thread_truncation() { - let long_name = std::iter::once("test_named_thread_truncation") - .chain(std::iter::repeat(" yada").take(100)) - .collect::(); - - fn set_thread_name(name: &CStr) -> i32 { - #[cfg(target_os = "linux")] - return unsafe { libc::pthread_setname_np(libc::pthread_self(), name.as_ptr().cast()) }; - #[cfg(target_os = "macos")] - return unsafe { libc::pthread_setname_np(name.as_ptr().cast()) }; - } - - let result = thread::Builder::new().name(long_name.clone()).spawn(move || { - // Rust remembers the full thread name itself. - assert_eq!(thread::current().name(), Some(long_name.as_str())); - - // But the system is limited -- make sure we successfully set a truncation. - let mut buf = vec![0u8; long_name.len() + 1]; - unsafe { - libc::pthread_getname_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len()) - }; - let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); - assert!(cstr.to_bytes().len() >= 15); // POSIX seems to promise at least 15 chars - assert!(long_name.as_bytes().starts_with(cstr.to_bytes())); - - // Also test directly calling pthread_setname to check its return value. - assert_eq!(set_thread_name(&cstr), 0); - // But with a too long name it should fail. - assert_ne!(set_thread_name(&CString::new(long_name).unwrap()), 0); - }); - result.unwrap().join().unwrap(); -} diff --git a/src/tools/miri/tests/pass-dep/shims/pthread-threadname.rs b/src/tools/miri/tests/pass-dep/shims/pthread-threadname.rs new file mode 100644 index 0000000000000..bc782044d4d80 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/shims/pthread-threadname.rs @@ -0,0 +1,51 @@ +//@ignore-target-windows: No libc on Windows +use std::ffi::CStr; +#[cfg(not(target_os = "freebsd"))] +use std::ffi::CString; +use std::thread; + +fn main() { + let long_name = std::iter::once("test_named_thread_truncation") + .chain(std::iter::repeat(" yada").take(100)) + .collect::(); + + fn set_thread_name(name: &CStr) -> i32 { + #[cfg(target_os = "linux")] + return unsafe { libc::pthread_setname_np(libc::pthread_self(), name.as_ptr().cast()) }; + #[cfg(target_os = "freebsd")] + unsafe { + // pthread_set_name_np does not return anything + libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr().cast()); + return 0; + }; + #[cfg(target_os = "macos")] + return unsafe { libc::pthread_setname_np(name.as_ptr().cast()) }; + } + + let result = thread::Builder::new().name(long_name.clone()).spawn(move || { + // Rust remembers the full thread name itself. + assert_eq!(thread::current().name(), Some(long_name.as_str())); + + // But the system is limited -- make sure we successfully set a truncation. + let mut buf = vec![0u8; long_name.len() + 1]; + #[cfg(not(target_os = "freebsd"))] + unsafe { + libc::pthread_getname_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len()) + }; + #[cfg(target_os = "freebsd")] + unsafe { + libc::pthread_get_name_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len()) + }; + let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); + assert!(cstr.to_bytes().len() >= 15, "name is too short: len={}", cstr.to_bytes().len()); // POSIX seems to promise at least 15 chars + assert!(long_name.as_bytes().starts_with(cstr.to_bytes())); + + // Also test directly calling pthread_setname to check its return value. + assert_eq!(set_thread_name(&cstr), 0); + // But with a too long name it should fail (except on FreeBSD where the + // function has no return, hence cannot indicate failure). + #[cfg(not(target_os = "freebsd"))] + assert_ne!(set_thread_name(&CString::new(long_name).unwrap()), 0); + }); + result.unwrap().join().unwrap(); +} diff --git a/src/tools/miri/tests/pass/0weak_memory_consistency.rs b/src/tools/miri/tests/pass/0weak_memory_consistency.rs index abfe3b0adeb4d..1cbccb2eebdd8 100644 --- a/src/tools/miri/tests/pass/0weak_memory_consistency.rs +++ b/src/tools/miri/tests/pass/0weak_memory_consistency.rs @@ -1,4 +1,6 @@ -//@compile-flags: -Zmiri-ignore-leaks -Zmiri-disable-stacked-borrows +//@compile-flags: -Zmiri-ignore-leaks -Zmiri-disable-stacked-borrows -Zmiri-provenance-gc=10000 +// This test's runtime explodes if the GC interval is set to 1 (which we do in CI), so we +// override it internally back to the default frequency. // The following tests check whether our weak memory emulation produces // any inconsistent execution outcomes diff --git a/src/tools/miri/tests/pass/align_offset_symbolic.rs b/src/tools/miri/tests/pass/align_offset_symbolic.rs index 4e1584b838714..3e493952d281e 100644 --- a/src/tools/miri/tests/pass/align_offset_symbolic.rs +++ b/src/tools/miri/tests/pass/align_offset_symbolic.rs @@ -1,29 +1,6 @@ //@compile-flags: -Zmiri-symbolic-alignment-check #![feature(strict_provenance)] -use std::ptr; - -fn test_align_offset() { - let d = Box::new([0u32; 4]); - // Get u8 pointer to base - let raw = d.as_ptr() as *const u8; - - assert_eq!(raw.align_offset(2), 0); - assert_eq!(raw.align_offset(4), 0); - assert_eq!(raw.align_offset(8), usize::MAX); // requested alignment higher than allocation alignment - - assert_eq!(raw.wrapping_offset(1).align_offset(2), 1); - assert_eq!(raw.wrapping_offset(1).align_offset(4), 3); - assert_eq!(raw.wrapping_offset(1).align_offset(8), usize::MAX); // requested alignment higher than allocation alignment - - assert_eq!(raw.wrapping_offset(2).align_offset(2), 0); - assert_eq!(raw.wrapping_offset(2).align_offset(4), 2); - assert_eq!(raw.wrapping_offset(2).align_offset(8), usize::MAX); // requested alignment higher than allocation alignment - - let p = ptr::invalid::<()>(1); - assert_eq!(p.align_offset(1), 0); -} - fn test_align_to() { const N: usize = 4; let d = Box::new([0u32; N]); @@ -31,6 +8,8 @@ fn test_align_to() { let s = unsafe { std::slice::from_raw_parts(d.as_ptr() as *const u8, 4 * N) }; let raw = s.as_ptr(); + // Cases where we get the expected "middle" part without any fuzz, since the allocation is + // 4-aligned. { let (l, m, r) = unsafe { s.align_to::() }; assert_eq!(l.len(), 0); @@ -63,18 +42,21 @@ fn test_align_to() { assert_eq!(raw.wrapping_offset(4), m.as_ptr() as *const u8); } + // Cases where we request more alignment than the allocation has. { #[repr(align(8))] + #[derive(Copy, Clone)] struct Align8(u64); - let (l, m, r) = unsafe { s.align_to::() }; // requested alignment higher than allocation alignment - assert_eq!(l.len(), 4 * N); - assert_eq!(r.len(), 0); - assert_eq!(m.len(), 0); + let (_l, m, _r) = unsafe { s.align_to::() }; + assert!(m.len() > 0); + // Ensure the symbolic alignment check has been informed that this is okay now. + let _val = m[0]; } } fn test_from_utf8() { + // uses `align_offset` internally const N: usize = 10; let vec = vec![0x4141414141414141u64; N]; let content = unsafe { std::slice::from_raw_parts(vec.as_ptr() as *const u8, 8 * N) }; @@ -103,9 +85,26 @@ fn test_u64_array() { example(&Data::default()); } +fn test_cstr() { + // uses `align_offset` internally + std::ffi::CStr::from_bytes_with_nul(b"this is a test that is longer than 16 bytes\0").unwrap(); +} + +fn huge_align() { + #[cfg(target_pointer_width = "64")] + const SIZE: usize = 1 << 47; + #[cfg(target_pointer_width = "32")] + const SIZE: usize = 1 << 30; + #[cfg(target_pointer_width = "16")] + const SIZE: usize = 1 << 13; + struct HugeSize([u8; SIZE - 1]); + let _ = std::ptr::invalid::(SIZE).align_offset(SIZE); +} + fn main() { - test_align_offset(); test_align_to(); test_from_utf8(); test_u64_array(); + test_cstr(); + huge_align(); } diff --git a/src/tools/miri/tests/pass/box-custom-alloc.rs b/src/tools/miri/tests/pass/box-custom-alloc.rs index 155e3d74ab9c1..3d055961d15de 100644 --- a/src/tools/miri/tests/pass/box-custom-alloc.rs +++ b/src/tools/miri/tests/pass/box-custom-alloc.rs @@ -1,7 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![allow(incomplete_features)] // for trait upcasting -#![feature(allocator_api, trait_upcasting)] +#![feature(allocator_api)] use std::alloc::Layout; use std::alloc::{AllocError, Allocator}; diff --git a/src/tools/miri/tests/pass/concurrency/sync.rs b/src/tools/miri/tests/pass/concurrency/sync.rs index dccc9d104dd0e..e93e617fd2620 100644 --- a/src/tools/miri/tests/pass/concurrency/sync.rs +++ b/src/tools/miri/tests/pass/concurrency/sync.rs @@ -83,7 +83,7 @@ fn check_conditional_variables_timed_wait_notimeout() { cvar.notify_one(); }); - let (_guard, timeout) = cvar.wait_timeout(guard, Duration::from_millis(500)).unwrap(); + let (_guard, timeout) = cvar.wait_timeout(guard, Duration::from_millis(1000)).unwrap(); assert!(!timeout.timed_out()); handle.join().unwrap(); } diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs index 8432012a9ba52..ddaefeca3a3be 100644 --- a/src/tools/miri/tests/pass/dyn-upcast.rs +++ b/src/tools/miri/tests/pass/dyn-upcast.rs @@ -1,6 +1,3 @@ -#![feature(trait_upcasting)] -#![allow(incomplete_features)] - fn main() { basic(); diamond(); diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index 9b0a40c41b9cb..6ea034e2cda9d 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -20,8 +20,8 @@ use NaNKind::*; #[track_caller] fn check_all_outcomes(expected: HashSet, generate: impl Fn() -> T) { let mut seen = HashSet::new(); - // Let's give it 8x as many tries as we are expecting values. - let tries = expected.len() * 8; + // Let's give it sixteen times as many tries as we are expecting values. + let tries = expected.len() * 16; for _ in 0..tries { let val = generate(); assert!(expected.contains(&val), "got an unexpected value: {val}"); diff --git a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs index d410a875b1bea..89ee689fabe1f 100644 --- a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs +++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs @@ -11,7 +11,7 @@ pub fn main() { { let x = 0; let ptr = &raw mut x; - Call(*ptr = myfun(), after_call) + Call(*ptr = myfun(), after_call, UnwindContinue()) } after_call = { diff --git a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs index 090b1db0af0c2..55d1bacdf4578 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs @@ -1,5 +1,5 @@ // Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here +// Any new targets that are added to CI should be ignored here. // (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) //@ignore-target-aarch64 //@ignore-target-arm diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx.rs b/src/tools/miri/tests/pass/intrinsics-x86-avx.rs new file mode 100644 index 0000000000000..933e3d4153ada --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics-x86-avx.rs @@ -0,0 +1,162 @@ +// Ignore everything except x86 and x86_64 +// Any new targets that are added to CI should be ignored here. +// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +//@compile-flags: -C target-feature=+avx + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::mem::transmute; + +fn main() { + assert!(is_x86_feature_detected!("avx")); + + unsafe { + test_avx(); + } +} + +#[target_feature(enable = "avx")] +unsafe fn test_avx() { + fn expected_cmp(imm: i32, lhs: F, rhs: F, if_t: F, if_f: F) -> F { + let res = match imm { + _CMP_EQ_OQ => lhs == rhs, + _CMP_LT_OS => lhs < rhs, + _CMP_LE_OS => lhs <= rhs, + _CMP_UNORD_Q => lhs.partial_cmp(&rhs).is_none(), + _CMP_NEQ_UQ => lhs != rhs, + _CMP_NLT_UQ => !(lhs < rhs), + _CMP_NLE_UQ => !(lhs <= rhs), + _CMP_ORD_Q => lhs.partial_cmp(&rhs).is_some(), + _CMP_EQ_UQ => lhs == rhs || lhs.partial_cmp(&rhs).is_none(), + _CMP_NGE_US => !(lhs >= rhs), + _CMP_NGT_US => !(lhs > rhs), + _CMP_FALSE_OQ => false, + _CMP_NEQ_OQ => lhs != rhs && lhs.partial_cmp(&rhs).is_some(), + _CMP_GE_OS => lhs >= rhs, + _CMP_GT_OS => lhs > rhs, + _CMP_TRUE_US => true, + _ => unreachable!(), + }; + if res { if_t } else { if_f } + } + fn expected_cmp_f32(imm: i32, lhs: f32, rhs: f32) -> f32 { + expected_cmp(imm, lhs, rhs, f32::from_bits(u32::MAX), 0.0) + } + fn expected_cmp_f64(imm: i32, lhs: f64, rhs: f64) -> f64 { + expected_cmp(imm, lhs, rhs, f64::from_bits(u64::MAX), 0.0) + } + + #[target_feature(enable = "avx")] + unsafe fn test_mm_cmp_ss() { + let values = [ + (1.0, 1.0), + (0.0, 1.0), + (1.0, 0.0), + (f32::NAN, 0.0), + (0.0, f32::NAN), + (f32::NAN, f32::NAN), + ]; + + for (lhs, rhs) in values { + let a = _mm_setr_ps(lhs, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(rhs, 5.0, 6.0, 7.0); + let r: [u32; 4] = transmute(_mm_cmp_ss::(a, b)); + let e: [u32; 4] = + transmute(_mm_setr_ps(expected_cmp_f32(IMM, lhs, rhs), 2.0, 3.0, 4.0)); + assert_eq!(r, e); + } + } + + #[target_feature(enable = "avx")] + unsafe fn test_mm_cmp_ps() { + let values = [ + (1.0, 1.0), + (0.0, 1.0), + (1.0, 0.0), + (f32::NAN, 0.0), + (0.0, f32::NAN), + (f32::NAN, f32::NAN), + ]; + + for (lhs, rhs) in values { + let a = _mm_set1_ps(lhs); + let b = _mm_set1_ps(rhs); + let r: [u32; 4] = transmute(_mm_cmp_ps::(a, b)); + let e: [u32; 4] = transmute(_mm_set1_ps(expected_cmp_f32(IMM, lhs, rhs))); + assert_eq!(r, e); + } + } + + #[target_feature(enable = "avx")] + unsafe fn test_mm_cmp_sd() { + let values = [ + (1.0, 1.0), + (0.0, 1.0), + (1.0, 0.0), + (f64::NAN, 0.0), + (0.0, f64::NAN), + (f64::NAN, f64::NAN), + ]; + + for (lhs, rhs) in values { + let a = _mm_setr_pd(lhs, 2.0); + let b = _mm_setr_pd(rhs, 3.0); + let r: [u64; 2] = transmute(_mm_cmp_sd::(a, b)); + let e: [u64; 2] = transmute(_mm_setr_pd(expected_cmp_f64(IMM, lhs, rhs), 2.0)); + assert_eq!(r, e); + } + } + + #[target_feature(enable = "avx")] + unsafe fn test_mm_cmp_pd() { + let values = [ + (1.0, 1.0), + (0.0, 1.0), + (1.0, 0.0), + (f64::NAN, 0.0), + (0.0, f64::NAN), + (f64::NAN, f64::NAN), + ]; + + for (lhs, rhs) in values { + let a = _mm_set1_pd(lhs); + let b = _mm_set1_pd(rhs); + let r: [u64; 2] = transmute(_mm_cmp_pd::(a, b)); + let e: [u64; 2] = transmute(_mm_set1_pd(expected_cmp_f64(IMM, lhs, rhs))); + assert_eq!(r, e); + } + } + + #[target_feature(enable = "avx")] + unsafe fn test_cmp() { + test_mm_cmp_ss::(); + test_mm_cmp_ps::(); + test_mm_cmp_sd::(); + test_mm_cmp_pd::(); + } + + test_cmp::<_CMP_EQ_OQ>(); + test_cmp::<_CMP_LT_OS>(); + test_cmp::<_CMP_LE_OS>(); + test_cmp::<_CMP_UNORD_Q>(); + test_cmp::<_CMP_NEQ_UQ>(); + test_cmp::<_CMP_NLT_UQ>(); + test_cmp::<_CMP_NLE_UQ>(); + test_cmp::<_CMP_ORD_Q>(); + test_cmp::<_CMP_EQ_UQ>(); + test_cmp::<_CMP_NGE_US>(); + test_cmp::<_CMP_NGT_US>(); + test_cmp::<_CMP_FALSE_OQ>(); + test_cmp::<_CMP_NEQ_OQ>(); + test_cmp::<_CMP_GE_OS>(); + test_cmp::<_CMP_GT_OS>(); + test_cmp::<_CMP_TRUE_US>(); +} diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs index c38158dc797ca..394412a235432 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs @@ -1,5 +1,5 @@ // Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here +// Any new targets that are added to CI should be ignored here. // (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) //@ignore-target-aarch64 //@ignore-target-arm diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs index 0805d9bc30039..7566be4431b7f 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs @@ -1,5 +1,5 @@ // Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here +// Any new targets that are added to CI should be ignored here. // (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) //@ignore-target-aarch64 //@ignore-target-arm diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs index d5489ffaf4ba1..13856d29d3f39 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs @@ -1,5 +1,5 @@ // Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here +// Any new targets that are added to CI should be ignored here. // (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) //@ignore-target-aarch64 //@ignore-target-arm @@ -73,114 +73,342 @@ unsafe fn test_sse41() { test_mm_dp_ps(); #[target_feature(enable = "sse4.1")] - unsafe fn test_mm_floor_sd() { - let a = _mm_setr_pd(2.5, 4.5); - let b = _mm_setr_pd(-1.5, -3.5); - let r = _mm_floor_sd(a, b); - let e = _mm_setr_pd(-2.0, 4.5); - assert_eq_m128d(r, e); + unsafe fn test_round_nearest_f32() { + #[target_feature(enable = "sse4.1")] + unsafe fn test(x: f32, res: f32) { + let a = _mm_setr_ps(3.5, 2.5, 1.5, 4.5); + let b = _mm_setr_ps(x, -1.5, -3.5, -2.5); + let e = _mm_setr_ps(res, 2.5, 1.5, 4.5); + let r = _mm_round_ss::<_MM_FROUND_TO_NEAREST_INT>(a, b); + assert_eq_m128(r, e); + // Assume round-to-nearest by default + let r = _mm_round_ss::<_MM_FROUND_CUR_DIRECTION>(a, b); + assert_eq_m128(r, e); + + let a = _mm_set1_ps(x); + let e = _mm_set1_ps(res); + let r = _mm_round_ps::<_MM_FROUND_TO_NEAREST_INT>(a); + assert_eq_m128(r, e); + // Assume round-to-nearest by default + let r = _mm_round_ps::<_MM_FROUND_CUR_DIRECTION>(a); + assert_eq_m128(r, e); + } + + // Test rounding direction + test(-2.5, -2.0); + test(-1.75, -2.0); + test(-1.5, -2.0); + test(-1.25, -1.0); + test(-1.0, -1.0); + test(0.0, 0.0); + test(1.0, 1.0); + test(1.25, 1.0); + test(1.5, 2.0); + test(1.75, 2.0); + test(2.5, 2.0); + + // Test that each element is rounded + let a = _mm_setr_ps(1.5, 3.5, 5.5, 7.5); + let e = _mm_setr_ps(2.0, 4.0, 6.0, 8.0); + let r = _mm_round_ps::<_MM_FROUND_TO_NEAREST_INT>(a); + assert_eq_m128(r, e); + // Assume round-to-nearest by default + let r = _mm_round_ps::<_MM_FROUND_CUR_DIRECTION>(a); + assert_eq_m128(r, e); } - test_mm_floor_sd(); + test_round_nearest_f32(); #[target_feature(enable = "sse4.1")] - unsafe fn test_mm_floor_ss() { - let a = _mm_setr_ps(2.5, 4.5, 8.5, 16.5); - let b = _mm_setr_ps(-1.5, -3.5, -7.5, -15.5); - let r = _mm_floor_ss(a, b); - let e = _mm_setr_ps(-2.0, 4.5, 8.5, 16.5); + unsafe fn test_round_floor_f32() { + #[target_feature(enable = "sse4.1")] + unsafe fn test(x: f32, res: f32) { + let a = _mm_setr_ps(3.5, 2.5, 1.5, 4.5); + let b = _mm_setr_ps(x, -1.5, -3.5, -2.5); + let e = _mm_setr_ps(res, 2.5, 1.5, 4.5); + let r = _mm_floor_ss(a, b); + assert_eq_m128(r, e); + let r = _mm_round_ss::<_MM_FROUND_TO_NEG_INF>(a, b); + assert_eq_m128(r, e); + + let a = _mm_set1_ps(x); + let e = _mm_set1_ps(res); + let r = _mm_floor_ps(a); + assert_eq_m128(r, e); + let r = _mm_round_ps::<_MM_FROUND_TO_NEG_INF>(a); + assert_eq_m128(r, e); + } + + // Test rounding direction + test(-2.5, -3.0); + test(-1.75, -2.0); + test(-1.5, -2.0); + test(-1.25, -2.0); + test(-1.0, -1.0); + test(0.0, 0.0); + test(1.0, 1.0); + test(1.25, 1.0); + test(1.5, 1.0); + test(1.75, 1.0); + test(2.5, 2.0); + + // Test that each element is rounded + let a = _mm_setr_ps(1.5, 3.5, 5.5, 7.5); + let e = _mm_setr_ps(1.0, 3.0, 5.0, 7.0); + let r = _mm_floor_ps(a); + assert_eq_m128(r, e); + let r = _mm_round_ps::<_MM_FROUND_TO_NEG_INF>(a); assert_eq_m128(r, e); } - test_mm_floor_ss(); + test_round_floor_f32(); #[target_feature(enable = "sse4.1")] - unsafe fn test_mm_ceil_sd() { - let a = _mm_setr_pd(1.5, 3.5); - let b = _mm_setr_pd(-2.5, -4.5); - let r = _mm_ceil_sd(a, b); - let e = _mm_setr_pd(-2.0, 3.5); - assert_eq_m128d(r, e); + unsafe fn test_round_ceil_f32() { + #[target_feature(enable = "sse4.1")] + unsafe fn test(x: f32, res: f32) { + let a = _mm_setr_ps(3.5, 2.5, 1.5, 4.5); + let b = _mm_setr_ps(x, -1.5, -3.5, -2.5); + let e = _mm_setr_ps(res, 2.5, 1.5, 4.5); + let r = _mm_ceil_ss(a, b); + assert_eq_m128(r, e); + let r = _mm_round_ss::<_MM_FROUND_TO_POS_INF>(a, b); + assert_eq_m128(r, e); + + let a = _mm_set1_ps(x); + let e = _mm_set1_ps(res); + let r = _mm_ceil_ps(a); + assert_eq_m128(r, e); + let r = _mm_round_ps::<_MM_FROUND_TO_POS_INF>(a); + assert_eq_m128(r, e); + } + + // Test rounding direction + test(-2.5, -2.0); + test(-1.75, -1.0); + test(-1.5, -1.0); + test(-1.25, -1.0); + test(-1.0, -1.0); + test(0.0, 0.0); + test(1.0, 1.0); + test(1.25, 2.0); + test(1.5, 2.0); + test(1.75, 2.0); + test(2.5, 3.0); + + // Test that each element is rounded + let a = _mm_setr_ps(1.5, 3.5, 5.5, 7.5); + let e = _mm_setr_ps(2.0, 4.0, 6.0, 8.0); + let r = _mm_ceil_ps(a); + assert_eq_m128(r, e); + let r = _mm_round_ps::<_MM_FROUND_TO_POS_INF>(a); + assert_eq_m128(r, e); } - test_mm_ceil_sd(); + test_round_ceil_f32(); #[target_feature(enable = "sse4.1")] - unsafe fn test_mm_ceil_ss() { - let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5); - let b = _mm_setr_ps(-2.5, -4.5, -8.5, -16.5); - let r = _mm_ceil_ss(a, b); - let e = _mm_setr_ps(-2.0, 3.5, 7.5, 15.5); + unsafe fn test_round_trunc_f32() { + #[target_feature(enable = "sse4.1")] + unsafe fn test(x: f32, res: f32) { + let a = _mm_setr_ps(3.5, 2.5, 1.5, 4.5); + let b = _mm_setr_ps(x, -1.5, -3.5, -2.5); + let e = _mm_setr_ps(res, 2.5, 1.5, 4.5); + let r = _mm_round_ss::<_MM_FROUND_TO_ZERO>(a, b); + assert_eq_m128(r, e); + + let a = _mm_set1_ps(x); + let e = _mm_set1_ps(res); + let r = _mm_round_ps::<_MM_FROUND_TO_ZERO>(a); + assert_eq_m128(r, e); + } + + // Test rounding direction + test(-2.5, -2.0); + test(-1.75, -1.0); + test(-1.5, -1.0); + test(-1.25, -1.0); + test(-1.0, -1.0); + test(0.0, 0.0); + test(1.0, 1.0); + test(1.25, 1.0); + test(1.5, 1.0); + test(1.75, 1.0); + test(2.5, 2.0); + + // Test that each element is rounded + let a = _mm_setr_ps(1.5, 3.5, 5.5, 7.5); + let e = _mm_setr_ps(1.0, 3.0, 5.0, 7.0); + let r = _mm_round_ps::<_MM_FROUND_TO_ZERO>(a); assert_eq_m128(r, e); } - test_mm_ceil_ss(); + test_round_trunc_f32(); #[target_feature(enable = "sse4.1")] - unsafe fn test_mm_round_sd() { + unsafe fn test_round_nearest_f64() { + #[target_feature(enable = "sse4.1")] + unsafe fn test(x: f64, res: f64) { + let a = _mm_setr_pd(3.5, 2.5); + let b = _mm_setr_pd(x, -1.5); + let e = _mm_setr_pd(res, 2.5); + let r = _mm_round_sd::<_MM_FROUND_TO_NEAREST_INT>(a, b); + assert_eq_m128d(r, e); + // Assume round-to-nearest by default + let r = _mm_round_sd::<_MM_FROUND_CUR_DIRECTION>(a, b); + assert_eq_m128d(r, e); + + let a = _mm_set1_pd(x); + let e = _mm_set1_pd(res); + let r = _mm_round_pd::<_MM_FROUND_TO_NEAREST_INT>(a); + assert_eq_m128d(r, e); + // Assume round-to-nearest by default + let r = _mm_round_pd::<_MM_FROUND_CUR_DIRECTION>(a); + assert_eq_m128d(r, e); + } + + // Test rounding direction + test(-2.5, -2.0); + test(-1.75, -2.0); + test(-1.5, -2.0); + test(-1.25, -1.0); + test(-1.0, -1.0); + test(0.0, 0.0); + test(1.0, 1.0); + test(1.25, 1.0); + test(1.5, 2.0); + test(1.75, 2.0); + test(2.5, 2.0); + + // Test that each element is rounded let a = _mm_setr_pd(1.5, 3.5); - let b = _mm_setr_pd(-2.5, -4.5); - let r = _mm_round_sd::<_MM_FROUND_TO_NEAREST_INT>(a, b); - let e = _mm_setr_pd(-2.0, 3.5); + let e = _mm_setr_pd(2.0, 4.0); + let r = _mm_round_pd::<_MM_FROUND_TO_NEAREST_INT>(a); assert_eq_m128d(r, e); - - let a = _mm_setr_pd(1.5, 3.5); - let b = _mm_setr_pd(-2.5, -4.5); - let r = _mm_round_sd::<_MM_FROUND_TO_NEG_INF>(a, b); - let e = _mm_setr_pd(-3.0, 3.5); + // Assume round-to-nearest by default + let r = _mm_round_pd::<_MM_FROUND_CUR_DIRECTION>(a); assert_eq_m128d(r, e); + } + test_round_nearest_f64(); + #[target_feature(enable = "sse4.1")] + unsafe fn test_round_floor_f64() { + #[target_feature(enable = "sse4.1")] + unsafe fn test(x: f64, res: f64) { + let a = _mm_setr_pd(3.5, 2.5); + let b = _mm_setr_pd(x, -1.5); + let e = _mm_setr_pd(res, 2.5); + let r = _mm_floor_sd(a, b); + assert_eq_m128d(r, e); + let r = _mm_round_sd::<_MM_FROUND_TO_NEG_INF>(a, b); + assert_eq_m128d(r, e); + + let a = _mm_set1_pd(x); + let e = _mm_set1_pd(res); + let r = _mm_floor_pd(a); + assert_eq_m128d(r, e); + let r = _mm_round_pd::<_MM_FROUND_TO_NEG_INF>(a); + assert_eq_m128d(r, e); + } + + // Test rounding direction + test(-2.5, -3.0); + test(-1.75, -2.0); + test(-1.5, -2.0); + test(-1.25, -2.0); + test(-1.0, -1.0); + test(0.0, 0.0); + test(1.0, 1.0); + test(1.25, 1.0); + test(1.5, 1.0); + test(1.75, 1.0); + test(2.5, 2.0); + + // Test that each element is rounded let a = _mm_setr_pd(1.5, 3.5); - let b = _mm_setr_pd(-2.5, -4.5); - let r = _mm_round_sd::<_MM_FROUND_TO_POS_INF>(a, b); - let e = _mm_setr_pd(-2.0, 3.5); + let e = _mm_setr_pd(1.0, 3.0); + let r = _mm_floor_pd(a); assert_eq_m128d(r, e); - - let a = _mm_setr_pd(1.5, 3.5); - let b = _mm_setr_pd(-2.5, -4.5); - let r = _mm_round_sd::<_MM_FROUND_TO_ZERO>(a, b); - let e = _mm_setr_pd(-2.0, 3.5); + let r = _mm_round_pd::<_MM_FROUND_TO_NEG_INF>(a); assert_eq_m128d(r, e); + } + test_round_floor_f64(); - // Assume round-to-nearest by default + #[target_feature(enable = "sse4.1")] + unsafe fn test_round_ceil_f64() { + #[target_feature(enable = "sse4.1")] + unsafe fn test(x: f64, res: f64) { + let a = _mm_setr_pd(3.5, 2.5); + let b = _mm_setr_pd(x, -1.5); + let e = _mm_setr_pd(res, 2.5); + let r = _mm_ceil_sd(a, b); + assert_eq_m128d(r, e); + let r = _mm_round_sd::<_MM_FROUND_TO_POS_INF>(a, b); + assert_eq_m128d(r, e); + + let a = _mm_set1_pd(x); + let e = _mm_set1_pd(res); + let r = _mm_ceil_pd(a); + assert_eq_m128d(r, e); + let r = _mm_round_pd::<_MM_FROUND_TO_POS_INF>(a); + assert_eq_m128d(r, e); + } + + // Test rounding direction + test(-2.5, -2.0); + test(-1.75, -1.0); + test(-1.5, -1.0); + test(-1.25, -1.0); + test(-1.0, -1.0); + test(0.0, 0.0); + test(1.0, 1.0); + test(1.25, 2.0); + test(1.5, 2.0); + test(1.75, 2.0); + test(2.5, 3.0); + + // Test that each element is rounded let a = _mm_setr_pd(1.5, 3.5); - let b = _mm_setr_pd(-2.5, -4.5); - let r = _mm_round_sd::<_MM_FROUND_CUR_DIRECTION>(a, b); - let e = _mm_setr_pd(-2.0, 3.5); + let e = _mm_setr_pd(2.0, 4.0); + let r = _mm_ceil_pd(a); + assert_eq_m128d(r, e); + let r = _mm_round_pd::<_MM_FROUND_TO_POS_INF>(a); assert_eq_m128d(r, e); } - test_mm_round_sd(); + test_round_ceil_f64(); #[target_feature(enable = "sse4.1")] - unsafe fn test_mm_round_ss() { - let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5); - let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5); - let r = _mm_round_ss::<_MM_FROUND_TO_NEAREST_INT>(a, b); - let e = _mm_setr_ps(-2.0, 3.5, 7.5, 15.5); - assert_eq_m128(r, e); - - let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5); - let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5); - let r = _mm_round_ss::<_MM_FROUND_TO_NEG_INF>(a, b); - let e = _mm_setr_ps(-2.0, 3.5, 7.5, 15.5); - assert_eq_m128(r, e); - - let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5); - let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5); - let r = _mm_round_ss::<_MM_FROUND_TO_POS_INF>(a, b); - let e = _mm_setr_ps(-1.0, 3.5, 7.5, 15.5); - assert_eq_m128(r, e); - - let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5); - let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5); - let r = _mm_round_ss::<_MM_FROUND_TO_ZERO>(a, b); - let e = _mm_setr_ps(-1.0, 3.5, 7.5, 15.5); - assert_eq_m128(r, e); - - // Assume round-to-nearest by default - let a = _mm_setr_ps(1.5, 3.5, 7.5, 15.5); - let b = _mm_setr_ps(-1.75, -4.5, -8.5, -16.5); - let r = _mm_round_ss::<_MM_FROUND_CUR_DIRECTION>(a, b); - let e = _mm_setr_ps(-2.0, 3.5, 7.5, 15.5); - assert_eq_m128(r, e); + unsafe fn test_round_trunc_f64() { + #[target_feature(enable = "sse4.1")] + unsafe fn test(x: f64, res: f64) { + let a = _mm_setr_pd(3.5, 2.5); + let b = _mm_setr_pd(x, -1.5); + let e = _mm_setr_pd(res, 2.5); + let r = _mm_round_sd::<_MM_FROUND_TO_ZERO>(a, b); + assert_eq_m128d(r, e); + + let a = _mm_set1_pd(x); + let e = _mm_set1_pd(res); + let r = _mm_round_pd::<_MM_FROUND_TO_ZERO>(a); + assert_eq_m128d(r, e); + } + + // Test rounding direction + test(-2.5, -2.0); + test(-1.75, -1.0); + test(-1.5, -1.0); + test(-1.25, -1.0); + test(-1.0, -1.0); + test(0.0, 0.0); + test(1.0, 1.0); + test(1.25, 1.0); + test(1.5, 1.0); + test(1.75, 1.0); + test(2.5, 2.0); + + // Test that each element is rounded + let a = _mm_setr_pd(1.5, 3.5); + let e = _mm_setr_pd(1.0, 3.0); + let r = _mm_round_pd::<_MM_FROUND_TO_ZERO>(a); + assert_eq_m128d(r, e); } - test_mm_round_ss(); + test_round_trunc_f64(); #[target_feature(enable = "sse4.1")] unsafe fn test_mm_minpos_epu16() { diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs new file mode 100644 index 0000000000000..b396f3fa835cf --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-3200-packed-field-offset.rs @@ -0,0 +1,37 @@ +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed, C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed, C)] +struct PackedUnsized { + f: u8, + d: [u32], +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { + unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation does *not* think there is + // any padding in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 4 * 4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); + } +} diff --git a/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs new file mode 100644 index 0000000000000..a8a7387ecdcd5 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-3200-packed2-field-offset.rs @@ -0,0 +1,40 @@ +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed(4))] +struct Slice([u32]); + +#[repr(packed(2), C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed(2), C)] +struct PackedUnsized { + f: u8, + d: Slice, +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { + unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation correctly adds exactly 1 byte of padding + // in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4 * 4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); + } +} diff --git a/src/tools/miri/tests/pass/panic/catch_panic.rs b/src/tools/miri/tests/pass/panic/catch_panic.rs index f5b4eaf685da8..b83902a8b19a4 100644 --- a/src/tools/miri/tests/pass/panic/catch_panic.rs +++ b/src/tools/miri/tests/pass/panic/catch_panic.rs @@ -1,5 +1,3 @@ -// We test the `align_offset` panic below, make sure we test the interpreter impl and not the "real" one. -//@compile-flags: -Zmiri-symbolic-alignment-check #![feature(never_type)] #![allow(unconditional_panic, non_fmt_panics)] @@ -70,6 +68,7 @@ fn main() { process::abort() }); + // Panic somewhere in the standard library. test(Some("align_offset: align is not a power-of-two"), |_old_val| { let _ = std::ptr::null::().align_offset(3); process::abort() diff --git a/src/tools/miri/tests/pass/portable-simd-ptrs.rs b/src/tools/miri/tests/pass/portable-simd-ptrs.rs index 843bb0284cfe7..a73b1d03cfa5f 100644 --- a/src/tools/miri/tests/pass/portable-simd-ptrs.rs +++ b/src/tools/miri/tests/pass/portable-simd-ptrs.rs @@ -2,7 +2,7 @@ //@compile-flags: -Zmiri-permissive-provenance #![feature(portable_simd, platform_intrinsics)] use std::ptr; -use std::simd::*; +use std::simd::prelude::*; fn main() { // Pointer casts diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs index 969162e2c1e9e..f370e658272f5 100644 --- a/src/tools/miri/tests/pass/portable-simd.rs +++ b/src/tools/miri/tests/pass/portable-simd.rs @@ -1,11 +1,7 @@ //@compile-flags: -Zmiri-strict-provenance #![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const)] -#![allow(incomplete_features)] -use std::simd::*; - -extern "platform-intrinsic" { - pub(crate) fn simd_bitmask(x: T) -> U; -} +#![allow(incomplete_features, internal_features)] +use std::simd::{prelude::*, StdFloat}; fn simd_ops_f32() { let a = f32x4::splat(10.0); @@ -197,9 +193,32 @@ fn simd_ops_i32() { assert_eq!(b.reduce_or(), -1); assert_eq!(a.reduce_xor(), 0); assert_eq!(b.reduce_xor(), -4); + + assert_eq!(b.leading_zeros(), u32x4::from_array([31, 30, 30, 0])); + assert_eq!(b.trailing_zeros(), u32x4::from_array([0, 1, 0, 2])); + assert_eq!(b.leading_ones(), u32x4::from_array([0, 0, 0, 30])); + assert_eq!(b.trailing_ones(), u32x4::from_array([1, 0, 2, 0])); + assert_eq!( + b.swap_bytes(), + i32x4::from_array([0x01000000, 0x02000000, 0x03000000, 0xfcffffffu32 as i32]) + ); + assert_eq!( + b.reverse_bits(), + i32x4::from_array([ + 0x80000000u32 as i32, + 0x40000000, + 0xc0000000u32 as i32, + 0x3fffffffu32 as i32 + ]) + ); } fn simd_mask() { + extern "platform-intrinsic" { + pub(crate) fn simd_bitmask(x: T) -> U; + pub(crate) fn simd_select_bitmask(m: M, yes: T, no: T) -> T; + } + let intmask = Mask::from_int(i32x4::from_array([0, -1, 0, 0])); assert_eq!(intmask, Mask::from_array([false, true, false, false])); assert_eq!(intmask.to_array(), [false, true, false, false]); @@ -234,8 +253,6 @@ fn simd_mask() { let bitmask = mask.to_bitmask(); assert_eq!(bitmask, 0b1000); assert_eq!(Mask::::from_bitmask(bitmask), mask); - - // Also directly call intrinsic, to test both kinds of return types. unsafe { let bitmask1: u8 = simd_bitmask(mask.to_int()); let bitmask2: [u8; 1] = simd_bitmask(mask.to_int()); @@ -247,6 +264,65 @@ fn simd_mask() { assert_eq!(bitmask2, [0b0001]); } } + + // This used to cause an ICE. It exercises simd_select_bitmask with an array as input. + if cfg!(target_endian = "little") { + // FIXME this test currently fails on big-endian: + // + let bitmask = u8x4::from_array([0b00001101, 0, 0, 0]); + assert_eq!( + mask32x4::from_bitmask_vector(bitmask), + mask32x4::from_array([true, false, true, true]), + ); + } + let bitmask = u8x8::from_array([0b01000101, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!( + mask32x8::from_bitmask_vector(bitmask), + mask32x8::from_array([true, false, true, false, false, false, true, false]), + ); + let bitmask = + u8x16::from_array([0b01000101, 0b11110000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!( + mask32x16::from_bitmask_vector(bitmask), + mask32x16::from_array([ + true, false, true, false, false, false, true, false, false, false, false, false, true, + true, true, true, + ]), + ); + + // Also directly call simd_select_bitmask, to test both kinds of argument types. + unsafe { + // These masks are exactly the results we got out above in the `simd_bitmask` tests. + let selected1 = simd_select_bitmask::( + if cfg!(target_endian = "little") { 0b1010001101001001 } else { 0b1001001011000101 }, + i32x16::splat(1), // yes + i32x16::splat(0), // no + ); + let selected2 = simd_select_bitmask::<[u8; 2], _>( + if cfg!(target_endian = "little") { + [0b01001001, 0b10100011] + } else { + [0b10010010, 0b11000101] + }, + i32x16::splat(1), // yes + i32x16::splat(0), // no + ); + assert_eq!(selected1, i32x16::from_array([1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1])); + assert_eq!(selected2, selected1); + // Also try masks less than a byte long. + let selected1 = simd_select_bitmask::( + if cfg!(target_endian = "little") { 0b1000 } else { 0b0001 }, + i32x4::splat(1), // yes + i32x4::splat(0), // no + ); + let selected2 = simd_select_bitmask::<[u8; 1], _>( + if cfg!(target_endian = "little") { [0b1000] } else { [0b0001] }, + i32x4::splat(1), // yes + i32x4::splat(0), // no + ); + assert_eq!(selected1, i32x4::from_array([0, 0, 0, 1])); + assert_eq!(selected2, selected1); + } } fn simd_cast() { @@ -328,14 +404,12 @@ fn simd_cast() { } fn simd_swizzle() { - use Which::*; - let a = f32x4::splat(10.0); let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]); assert_eq!(simd_swizzle!(b, [3, 0, 0, 2]), f32x4::from_array([-4.0, 1.0, 1.0, 3.0])); assert_eq!(simd_swizzle!(b, [1, 2]), f32x2::from_array([2.0, 3.0])); - assert_eq!(simd_swizzle!(b, a, [First(3), Second(0)]), f32x2::from_array([-4.0, 10.0])); + assert_eq!(simd_swizzle!(b, a, [3, 4]), f32x2::from_array([-4.0, 10.0])); } fn simd_gather_scatter() { @@ -417,13 +491,13 @@ fn simd_intrinsics() { i32x4::from_array([10, 2, 10, 10]) ); assert_eq!(simd_shuffle_generic::<_, i32x4, { &[3, 1, 0, 2] }>(a, b), a,); - assert_eq!(simd_shuffle::<_, _, i32x4>(a, b, const { [3, 1, 0, 2] }), a,); + assert_eq!(simd_shuffle::<_, _, i32x4>(a, b, const { [3u32, 1, 0, 2] }), a,); assert_eq!( simd_shuffle_generic::<_, i32x4, { &[7, 5, 4, 6] }>(a, b), i32x4::from_array([4, 2, 1, 10]), ); assert_eq!( - simd_shuffle::<_, _, i32x4>(a, b, const { [7, 5, 4, 6] }), + simd_shuffle::<_, _, i32x4>(a, b, const { [7u32, 5, 4, 6] }), i32x4::from_array([4, 2, 1, 10]), ); } diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs index 35a52d0220b81..d8d57679e6b36 100644 --- a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs +++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs @@ -1,7 +1,7 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-permissive-provenance -#![feature(strict_provenance)] +#![feature(strict_provenance, exposed_provenance)] use std::ptr; diff --git a/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs b/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs index 9e604f9abb83a..e467356dd04ba 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/int-to-ptr.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(strict_provenance)] +#![feature(exposed_provenance)] use std::ptr; // Just to make sure that casting a ref to raw, to int and back to raw diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs index 74761a89cb94a..9c9db4d1b3b53 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs @@ -1,4 +1,7 @@ -//@compile-flags: -Zmiri-permissive-provenance +// We disable the GC for this test because it would change what is printed. We are testing the +// printing, not how it interacts with the GC. +//@compile-flags: -Zmiri-permissive-provenance -Zmiri-provenance-gc=0 + #![feature(strict_provenance)] use std::{ alloc::{self, Layout}, diff --git a/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs b/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs index e62ee528686d8..5bb4e879c3e44 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(strict_provenance)] +#![feature(exposed_provenance)] use std::ptr; diff --git a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs new file mode 100644 index 0000000000000..7732e3f921774 --- /dev/null +++ b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs @@ -0,0 +1,23 @@ +//@ignore-target-windows: Windows uses a different mechanism for `thread_local!` +#![feature(thread_local)] + +use std::cell::Cell; + +// Thread-local variables in the main thread are basically like `static` (they live +// as long as the program does), so make sure we treat them the same for leak purposes. +// +// The test covers both TLS statics and the TLS macro. +pub fn main() { + thread_local! { + static TLS_KEY: Cell> = Cell::new(None); + } + + TLS_KEY.with(|cell| { + cell.set(Some(Box::leak(Box::new(123)))); + }); + + #[thread_local] + static TLS: Cell> = Cell::new(None); + + TLS.set(Some(Box::leak(Box::new(123)))); +} diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs b/src/tools/miri/tests/pass/tls/tls_macro_drop.rs similarity index 100% rename from src/tools/miri/tests/pass/concurrency/tls_lib_drop.rs rename to src/tools/miri/tests/pass/tls/tls_macro_drop.rs diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.stack.stdout b/src/tools/miri/tests/pass/tls/tls_macro_drop.stack.stdout similarity index 100% rename from src/tools/miri/tests/pass/concurrency/tls_lib_drop.stack.stdout rename to src/tools/miri/tests/pass/tls/tls_macro_drop.stack.stdout diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop.tree.stdout b/src/tools/miri/tests/pass/tls/tls_macro_drop.tree.stdout similarity index 100% rename from src/tools/miri/tests/pass/concurrency/tls_lib_drop.tree.stdout rename to src/tools/miri/tests/pass/tls/tls_macro_drop.tree.stdout diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop_single_thread.rs b/src/tools/miri/tests/pass/tls/tls_macro_drop_single_thread.rs similarity index 89% rename from src/tools/miri/tests/pass/concurrency/tls_lib_drop_single_thread.rs rename to src/tools/miri/tests/pass/tls/tls_macro_drop_single_thread.rs index 2766ba36d12b6..f36c460ae5341 100644 --- a/src/tools/miri/tests/pass/concurrency/tls_lib_drop_single_thread.rs +++ b/src/tools/miri/tests/pass/tls/tls_macro_drop_single_thread.rs @@ -1,4 +1,5 @@ -//! Check that destructors of the thread locals are executed on all OSes. +//! Check that destructors of the thread locals are executed on all OSes +//! (even when we do not support concurrency, and cannot run the other test). use std::cell::RefCell; diff --git a/src/tools/miri/tests/pass/concurrency/tls_lib_drop_single_thread.stderr b/src/tools/miri/tests/pass/tls/tls_macro_drop_single_thread.stderr similarity index 100% rename from src/tools/miri/tests/pass/concurrency/tls_lib_drop_single_thread.stderr rename to src/tools/miri/tests/pass/tls/tls_macro_drop_single_thread.stderr diff --git a/src/tools/miri/tests/pass/concurrency/thread_locals.rs b/src/tools/miri/tests/pass/tls/tls_static.rs similarity index 100% rename from src/tools/miri/tests/pass/concurrency/thread_locals.rs rename to src/tools/miri/tests/pass/tls/tls_static.rs diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.rs b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.rs index 398b542ed4c24..3269acb511938 100644 --- a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.rs +++ b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.rs @@ -1,4 +1,5 @@ -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 #[path = "../../utils/mod.rs"] #[macro_use] mod utils; diff --git a/src/tools/miri/tests/pass/tree_borrows/end-of-protector.rs b/src/tools/miri/tests/pass/tree_borrows/end-of-protector.rs index fecc3360434d2..261419b225b7d 100644 --- a/src/tools/miri/tests/pass/tree_borrows/end-of-protector.rs +++ b/src/tools/miri/tests/pass/tree_borrows/end-of-protector.rs @@ -1,4 +1,5 @@ -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 // Check that a protector goes back to normal behavior when the function // returns. diff --git a/src/tools/miri/tests/pass/tree_borrows/formatting.rs b/src/tools/miri/tests/pass/tree_borrows/formatting.rs index f22c408ad2538..8898205bfb9ac 100644 --- a/src/tools/miri/tests/pass/tree_borrows/formatting.rs +++ b/src/tools/miri/tests/pass/tree_borrows/formatting.rs @@ -1,4 +1,5 @@ -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 #[path = "../../utils/mod.rs"] #[macro_use] diff --git a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.rs b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.rs index a38cd6d289416..4fbccef2367d5 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.rs +++ b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.rs @@ -1,4 +1,5 @@ -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 #[path = "../../utils/mod.rs"] #[macro_use] diff --git a/src/tools/miri/tests/pass/tree_borrows/reserved.rs b/src/tools/miri/tests/pass/tree_borrows/reserved.rs index 8d0beab66f406..87ce91a809f22 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reserved.rs +++ b/src/tools/miri/tests/pass/tree_borrows/reserved.rs @@ -1,4 +1,5 @@ -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 #[path = "../../utils/mod.rs"] #[macro_use] diff --git a/src/tools/miri/tests/pass/tree_borrows/unique.rs b/src/tools/miri/tests/pass/tree_borrows/unique.rs index 44e2e8136252e..f1ca1b51aa857 100644 --- a/src/tools/miri/tests/pass/tree_borrows/unique.rs +++ b/src/tools/miri/tests/pass/tree_borrows/unique.rs @@ -1,5 +1,6 @@ //@revisions: default uniq -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 //@[uniq]compile-flags: -Zmiri-unique-is-unique #![feature(ptr_internals)] diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs b/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs index e5d0a683a7237..05090d685ab2e 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs @@ -1,5 +1,6 @@ //@revisions: default uniq -//@compile-flags: -Zmiri-tree-borrows -Zmiri-tag-gc=0 +// We disable the GC for this test because it would change what is printed. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 //@[uniq]compile-flags: -Zmiri-unique-is-unique #![feature(vec_into_raw_parts)] diff --git a/src/tools/miri/tests/utils/miri_extern.rs b/src/tools/miri/tests/utils/miri_extern.rs index c0ef2c506413d..ff7990561f2c9 100644 --- a/src/tools/miri/tests/utils/miri_extern.rs +++ b/src/tools/miri/tests/utils/miri_extern.rs @@ -84,7 +84,7 @@ extern "Rust" { /// /// The format of what this emits is unstable and may change at any time. In particular, users should be /// aware that Miri will periodically attempt to garbage collect the contents of all stacks. Callers of - /// this function may wish to pass `-Zmiri-tag-gc=0` to disable the GC. + /// this function may wish to pass `-Zmiri-provenance-gc=0` to disable the GC. /// /// This function is extremely unstable. At any time the format of its output may change, its signature may /// change, or it may be removed entirely. @@ -137,4 +137,14 @@ extern "Rust" { out: *mut std::ffi::c_char, out_size: usize, ) -> usize; + + /// Run the provenance GC. The GC will run automatically at some cadence, + /// but in tests we want to for sure run it at certain points to check + /// that it doesn't break anything. + pub fn miri_run_provenance_gc(); + + /// Miri-provided extern function to promise that a given pointer is properly aligned for + /// "symbolic" alignment checks. Will fail if the pointer is not actually aligned or `align` is + /// not a power of two. Has no effect when alignment checks are concrete (which is the default). + pub fn miri_promise_symbolic_alignment(ptr: *const (), align: usize); } diff --git a/src/tools/miri/tests/utils/mod.rs b/src/tools/miri/tests/utils/mod.rs index 7b7dc231a5019..cb9380f5753ce 100644 --- a/src/tools/miri/tests/utils/mod.rs +++ b/src/tools/miri/tests/utils/mod.rs @@ -7,5 +7,10 @@ mod macros; mod fs; mod miri_extern; -pub use fs::*; -pub use miri_extern::*; +pub use self::fs::*; +pub use self::miri_extern::*; + +pub fn run_provenance_gc() { + // SAFETY: No preconditions. The GC is fine to run at any time. + unsafe { miri_run_provenance_gc() } +} diff --git a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml index 310a8a5be7ad5..9a5015005b3dc 100644 --- a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml +++ b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml @@ -19,6 +19,10 @@ jobs: with: fetch-depth: 0 + # https://github.com/jlumbroso/free-disk-space/blob/main/action.yml + - name: Free up some disk space + run: sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup + - name: Install Rust toolchain run: rustup update --no-self-update stable diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index fb7b4b07f9843..1f2a7796d114e 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -8,6 +8,7 @@ on: branches: - auto - try + - automation/bors/try env: CARGO_INCREMENTAL: 0 @@ -84,6 +85,7 @@ jobs: run: cargo build --quiet ${{ env.USE_SYSROOT_ABI }} - name: Test + if: matrix.os == 'ubuntu-latest' || github.event_name == 'push' run: cargo test ${{ env.USE_SYSROOT_ABI }} -- --nocapture --quiet - name: Switch to stable toolchain diff --git a/src/tools/rust-analyzer/.github/workflows/metrics.yaml b/src/tools/rust-analyzer/.github/workflows/metrics.yaml index bbeccd1621df6..741e559953fc8 100644 --- a/src/tools/rust-analyzer/.github/workflows/metrics.yaml +++ b/src/tools/rust-analyzer/.github/workflows/metrics.yaml @@ -140,11 +140,14 @@ jobs: - name: Combine json run: | - git clone --depth 1 https://$METRICS_TOKEN@github.com/rust-analyzer/metrics.git + mkdir ~/.ssh + echo "${{ secrets.METRICS_DEPLOY_KEY }}" > ~/.ssh/id_ed25519 + chmod 600 ~/.ssh/id_ed25519 + chmod 700 ~/.ssh + + git clone --depth 1 git@github.com:rust-analyzer/metrics.git jq -s ".[0] * .[1] * .[2] * .[3] * .[4] * .[5]" build.json self.json ripgrep-13.0.0.json webrender-2022.json diesel-1.4.8.json hyper-0.14.18.json -c >> metrics/metrics.json cd metrics git add . git -c user.name=Bot -c user.email=dummy@example.com commit --message 📈 git push origin master - env: - METRICS_TOKEN: ${{ secrets.METRICS_TOKEN }} diff --git a/src/tools/rust-analyzer/.github/workflows/release.yaml b/src/tools/rust-analyzer/.github/workflows/release.yaml index b5dbe30c3221c..6a3cdfe3a3c7f 100644 --- a/src/tools/rust-analyzer/.github/workflows/release.yaml +++ b/src/tools/rust-analyzer/.github/workflows/release.yaml @@ -30,7 +30,6 @@ jobs: code-target: win32-x64 - os: windows-latest target: i686-pc-windows-msvc - code-target: win32-ia32 - os: windows-latest target: aarch64-pc-windows-msvc code-target: win32-arm64 @@ -102,12 +101,12 @@ jobs: working-directory: editors/code - name: Package Extension (release) - if: github.ref == 'refs/heads/release' + if: github.ref == 'refs/heads/release' && matrix.code-target run: npx vsce package -o "../../dist/rust-analyzer-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} working-directory: editors/code - name: Package Extension (nightly) - if: github.ref != 'refs/heads/release' + if: github.ref != 'refs/heads/release' && matrix.code-target run: npx vsce package -o "../../dist/rust-analyzer-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release working-directory: editors/code diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index bd6554bf8899a..876fd93aab713 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -28,21 +28,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" - -[[package]] -name = "anymap" -version = "1.0.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arbitrary" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" [[package]] name = "arrayvec" @@ -50,17 +44,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -89,8 +72,8 @@ dependencies = [ "cfg", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "profile", + "rust-analyzer-salsa", "rustc-hash", - "salsa", "stdx", "syntax", "test-utils", @@ -107,9 +90,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "byteorder" @@ -137,9 +120,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", @@ -177,32 +160,32 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chalk-derive" -version = "0.92.0" +version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff5053a8a42dbff5279a82423946fc56dc1253b76cf211b2b3c14b3aad4e1281" +checksum = "329427f28cd2bddaacd47c4dcd3d7082d315c61fb164394c690fe98c1b6ee9d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", "synstructure", ] [[package]] name = "chalk-ir" -version = "0.92.0" +version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56de2146a8ed0fcd54f4bd50db852f1de4eac9e1efe568494f106c21b77d2a" +checksum = "9e1e1659238bd598d0f7dbc5034cf1ff46010a3d6827704c9ed443c8359cb484" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "chalk-derive", "lazy_static", ] [[package]] name = "chalk-recursive" -version = "0.92.0" +version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc09e6e9531f3544989ef89b189e80fbc7ad9e2f73f1c5e03ddc9ffb0527463" +checksum = "b3e0bff0ba1bed11407384fcec0353aeb6888901e63cb47d04505ec47adad847" dependencies = [ "chalk-derive", "chalk-ir", @@ -213,14 +196,14 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.92.0" +version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b392e02b4c81ec76d3748da839fc70a5539b83d27c9030668463d34d5110b860" +checksum = "eb9c46d501cf83732a91056c0c846ae7a16d6b3c67a6a6bb5e9cc0a2e91563b6" dependencies = [ "chalk-derive", "chalk-ir", "ena", - "indexmap 1.9.3", + "indexmap", "itertools", "petgraph", "rustc-hash", @@ -233,7 +216,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916" dependencies = [ - "nix", + "nix 0.26.2", "winapi", ] @@ -306,6 +289,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ctrlc" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" +dependencies = [ + "nix 0.27.1", + "windows-sys 0.48.0", +] + [[package]] name = "dashmap" version = "5.4.0" @@ -316,25 +309,25 @@ dependencies = [ "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.6", + "parking_lot_core", ] [[package]] name = "derive_arbitrary" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] name = "dissimilar" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e" +checksum = "86e3bdc80eee6e16b2b6b0f87fbc98c04bee3455e35174c0de1a125d0688c632" [[package]] name = "dot" @@ -350,9 +343,9 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "ena" @@ -393,9 +386,9 @@ dependencies = [ [[package]] name = "fixedbitset" -version = "0.2.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" @@ -461,27 +454,15 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -518,10 +499,9 @@ dependencies = [ name = "hir-def" version = "0.0.0" dependencies = [ - "anymap", "arrayvec", "base-db", - "bitflags 2.3.2", + "bitflags 2.4.1", "cfg", "cov-mark", "dashmap", @@ -531,9 +511,7 @@ dependencies = [ "fst", "hashbrown 0.12.3", "hir-expand", - "hkalbasi-rustc-ap-rustc_abi", - "hkalbasi-rustc-ap-rustc_index", - "indexmap 2.0.0", + "indexmap", "intern", "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -541,7 +519,7 @@ dependencies = [ "mbe", "once_cell", "profile", - "ra-ap-rustc_parse_format", + "rustc-dependencies", "rustc-hash", "smallvec", "stdx", @@ -583,7 +561,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.3.2", + "bitflags 2.4.1", "chalk-derive", "chalk-ir", "chalk-recursive", @@ -594,7 +572,6 @@ dependencies = [ "expect-test", "hir-def", "hir-expand", - "hkalbasi-rustc-ap-rustc_index", "intern", "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -604,6 +581,7 @@ dependencies = [ "oorandom", "profile", "project-model", + "rustc-dependencies", "rustc-hash", "scoped-tls", "smallvec", @@ -617,27 +595,6 @@ dependencies = [ "typed-arena", ] -[[package]] -name = "hkalbasi-rustc-ap-rustc_abi" -version = "0.0.20221221" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adabaadad9aa7576f97af02241cdf5554d62fb3d51a84cb05d77ba28edd3013f" -dependencies = [ - "bitflags 1.3.2", - "hkalbasi-rustc-ap-rustc_index", - "tracing", -] - -[[package]] -name = "hkalbasi-rustc-ap-rustc_index" -version = "0.0.20221221" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4d3c48474e09afb0f5efbd6f758e05411699301a113c47d454d28ec7059d00e" -dependencies = [ - "arrayvec", - "smallvec", -] - [[package]] name = "home" version = "0.5.5" @@ -729,7 +686,7 @@ dependencies = [ "expect-test", "fst", "hir", - "indexmap 2.0.0", + "indexmap", "itertools", "limit", "line-index 0.1.0-pre.1", @@ -802,22 +759,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.2", ] [[package]] @@ -840,15 +787,6 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "intern" version = "0.0.0" @@ -861,9 +799,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.5" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" dependencies = [ "either", ] @@ -918,9 +856,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -1002,6 +940,7 @@ name = "lsp-server" version = "0.7.4" dependencies = [ "crossbeam-channel", + "ctrlc", "log", "lsp-types", "serde", @@ -1050,9 +989,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memmap2" @@ -1141,6 +1080,17 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "libc", +] + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -1153,7 +1103,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.3.2", + "bitflags 2.4.1", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1168,12 +1118,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" dependencies = [ - "overload", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1182,7 +1131,7 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] @@ -1216,23 +1165,6 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.1" @@ -1240,21 +1172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.6", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -1277,7 +1195,7 @@ dependencies = [ "drop_bomb", "expect-test", "limit", - "ra-ap-rustc_lexer", + "rustc-dependencies", "sourcegen", "stdx", ] @@ -1319,12 +1237,12 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.5.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 1.9.3", + "indexmap", ] [[package]] @@ -1389,9 +1307,9 @@ version = "0.0.0" [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -1435,9 +1353,9 @@ dependencies = [ [[package]] name = "protobuf" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee4a7d8b91800c8f167a6268d1a1026607368e1adc84e98fe044aeb905302f7" +checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e" dependencies = [ "once_cell", "protobuf-support", @@ -1446,9 +1364,9 @@ dependencies = [ [[package]] name = "protobuf-support" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca157fe12fc7ee2e315f2f735e27df41b3d97cdd70ea112824dac1ffb08ee1c" +checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372" dependencies = [ "thiserror", ] @@ -1482,21 +1400,45 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "ra-ap-rustc_abi" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5f38444d48da534b3bb612713fce9b0aeeffb2e0dfa242764f55482acc5b52d" +dependencies = [ + "bitflags 1.3.2", + "ra-ap-rustc_index", + "tracing", +] + [[package]] name = "ra-ap-rustc_index" -version = "0.10.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b5fa61d34da18e148dc3a81f654488ea07f40938d8aefb17f8b64bb78c6120" +checksum = "69fb5da07e1a39222d9c311203123c3b6a86420fa06dc695aa1661b0aecf8d16" dependencies = [ "arrayvec", + "ra-ap-rustc_index_macros", "smallvec", ] +[[package]] +name = "ra-ap-rustc_index_macros" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d69f9f6af58124f2da0cb8b0c3d8494e0d883a5fe0c6732258bde81ac5a87cc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "ra-ap-rustc_lexer" -version = "0.10.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e2f6b48422e4eed5218277ab7cc9733e60dd8f3167f4f36a49a0cafe4dc195" +checksum = "9d5e8650195795c4023d8321846466994a975bc457cb8a91c0b3b17a5fc8ba40" dependencies = [ "unicode-properties", "unicode-xid", @@ -1504,9 +1446,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.10.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7369ad01cc79f9e3513c9f6a6326f6b980100e4862a7ac71b9991c88108bb" +checksum = "0a6b325ee1ec90e4dbd4394913adf4ef32e4fcf2b311ec9563a0fa50cd549af6" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", @@ -1514,9 +1456,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -1524,14 +1466,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -1592,12 +1532,14 @@ dependencies = [ "nohash-hasher", "num_cpus", "oorandom", - "parking_lot 0.12.1", - "parking_lot_core 0.9.6", + "parking_lot", + "parking_lot_core", + "parser", "proc-macro-api", "profile", "project-model", "rayon", + "rustc-dependencies", "rustc-hash", "scip", "serde", @@ -1621,52 +1563,62 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "ryu" -version = "1.0.13" +name = "rust-analyzer-salsa" +version = "0.17.0-pre.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - -[[package]] -name = "salsa" -version = "0.17.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b223dccb46c32753144d0b51290da7230bb4aedcd8379d6b4c9a474c18bf17a" +checksum = "4ca92b657d614d076800aa7bf5d5ba33564e71fa7f16cd79eacdfe301a50ab1c" dependencies = [ "crossbeam-utils", - "indexmap 1.9.3", + "indexmap", "lock_api", "log", "oorandom", - "parking_lot 0.11.2", + "parking_lot", + "rust-analyzer-salsa-macros", "rustc-hash", - "salsa-macros", "smallvec", ] [[package]] -name = "salsa-macros" -version = "0.17.0-pre.2" +name = "rust-analyzer-salsa-macros" +version = "0.17.0-pre.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c2e352df550bf019da7b16164ed2f7fa107c39653d1311d1bba42d1582ff7" +checksum = "b190359266d293f2ee13eaa502a766dc8b77b63fbaa5d460d24fd0210675ceef" dependencies = [ "heck", "proc-macro2", "quote", - "syn 1.0.109", + "syn", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-dependencies" +version = "0.0.0" +dependencies = [ + "ra-ap-rustc_abi", + "ra-ap-rustc_index", + "ra-ap-rustc_lexer", + "ra-ap-rustc_parse_format", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + [[package]] name = "same-file" version = "1.0.6" @@ -1678,9 +1630,9 @@ dependencies = [ [[package]] name = "scip" -version = "0.1.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2bfbb10286f69fad7c78db71004b7839bf957788359fe0c479f029f9849136b" +checksum = "3e84d21062a3ba08d58870c8c36b0c005b2b2261c6ad1bf7042585427c781883" dependencies = [ "protobuf", ] @@ -1708,31 +1660,31 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.156" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.156" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "serde_json" -version = "1.0.97" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ - "indexmap 1.9.3", + "indexmap", "itoa", "ryu", "serde", @@ -1746,7 +1698,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] @@ -1807,20 +1759,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.18" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -1835,7 +1776,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", "unicode-xid", ] @@ -1846,16 +1787,16 @@ dependencies = [ "cov-mark", "either", "expect-test", - "indexmap 2.0.0", + "indexmap", "itertools", "once_cell", "parser", "proc-macro2", "profile", "quote", - "ra-ap-rustc_lexer", "rayon", "rowan", + "rustc-dependencies", "rustc-hash", "smol_str", "sourcegen", @@ -1887,9 +1828,9 @@ dependencies = [ [[package]] name = "text-size" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a" +checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" @@ -1908,7 +1849,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] @@ -1992,11 +1933,10 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2004,20 +1944,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -2025,20 +1965,20 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "sharded-slab", "thread_local", @@ -2048,11 +1988,10 @@ dependencies = [ [[package]] name = "tracing-tree" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9742d8df709837409dbb22aa25dd7769c260406f20ff48a2320b80a4a6aed0" +checksum = "65139ecd2c3f6484c3b99bc01c77afe21e95473630747c7aca525e78b0666675" dependencies = [ - "atty", "nu-ansi-term", "tracing-core", "tracing-log", @@ -2061,9 +2000,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db" +checksum = "d0c5a71827ac326072b6405552093e2ad2accd25a32fd78d4edc82d98c7f2409" [[package]] name = "tt" @@ -2121,12 +2060,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0" -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - [[package]] name = "unicode-xid" version = "0.2.4" @@ -2162,7 +2095,7 @@ name = "vfs" version = "0.0.0" dependencies = [ "fst", - "indexmap 2.0.0", + "indexmap", "nohash-hasher", "paths", "rustc-hash", @@ -2375,18 +2308,18 @@ checksum = "f58e7b3ca8977093aae6b87b6a7730216fc4c53a6530bab5c43a783cd810c1a8" [[package]] name = "xshell" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962c039b3a7b16cf4e9a4248397c6585c07547412e7d6a6e035389a802dcfe90" +checksum = "ce2107fe03e558353b4c71ad7626d58ed82efaf56c54134228608893c77023ad" dependencies = [ "xshell-macros", ] [[package]] name = "xshell-macros" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dbabb1cbd15a1d6d12d9ed6b35cc6777d4af87ab3ba155ea37215f20beab80c" +checksum = "7e2c411759b501fb9501aac2b1b2d287a6e93e5bdcf13c25306b23e1b716dd0e" [[package]] name = "xtask" diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index cab88fc18cec6..272f456bf9f86 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -79,6 +79,7 @@ toolchain = { path = "./crates/toolchain", version = "0.0.0" } tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } +rustc-dependencies = { path = "./crates/rustc-dependencies", version = "0.0.0" } # local crates that aren't published to crates.io. These should not have versions. proc-macro-test = { path = "./crates/proc-macro-test" } @@ -89,23 +90,35 @@ la-arena = { version = "0.3.1" } lsp-server = { version = "0.7.4" } # non-local crates +anyhow = "1.0.75" +bitflags = "2.4.1" +cargo_metadata = "0.18.1" +dissimilar = "1.0.7" +either = "1.9.0" +indexmap = "2.1.0" +itertools = "0.12.0" +libc = "0.2.150" smallvec = { version = "1.10.0", features = [ "const_new", "union", "const_generics", ] } +tracing = "0.1.40" +tracing-tree = "0.3.0" +tracing-subscriber = { version = "0.3.18", default-features = false, features = [ + "registry", + "fmt", + "tracing-log", +] } smol_str = "0.2.0" nohash-hasher = "0.2.0" -text-size = "1.1.0" -serde = { version = "1.0.156", features = ["derive"] } -serde_json = "1.0.96" -triomphe = { version = "0.1.8", default-features = false, features = ["std"] } +text-size = "1.1.1" +rayon = "1.8.0" +serde = { version = "1.0.192", features = ["derive"] } +serde_json = "1.0.108" +triomphe = { version = "0.1.10", default-features = false, features = ["std"] } # can't upgrade due to dashmap depending on 0.12.3 currently -hashbrown = { version = "0.12.3", features = ["inline-more"], default-features = false } - -rustc_lexer = { version = "0.10.0", package = "ra-ap-rustc_lexer" } -rustc_parse_format = { version = "0.10.0", package = "ra-ap-rustc_parse_format", default-features = false } - -# Upstream broke this for us so we can't update it -rustc_abi = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_abi", default-features = false } -rustc_index = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_index", default-features = false } +hashbrown = { version = "0.12.3", features = [ + "inline-more", +], default-features = false } +xshell = "0.2.5" diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml index 171c113a950d0..5ad88f65188e0 100644 --- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true doctest = false [dependencies] -salsa = "0.17.0-pre.2" +rust-analyzer-salsa = "0.17.0-pre.3" rustc-hash = "1.1.0" triomphe.workspace = true diff --git a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs index 3f5ccb621c767..3da555a47acb2 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs @@ -13,9 +13,9 @@ use vfs::{file_set::FileSet, VfsPath}; use crate::{ input::{CrateName, CrateOrigin, LangCrateOrigin}, - Change, CrateDisplayName, CrateGraph, CrateId, Dependency, Edition, Env, FileId, FilePosition, - FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacros, ReleaseChannel, - SourceDatabaseExt, SourceRoot, SourceRootId, + Change, CrateDisplayName, CrateGraph, CrateId, Dependency, DependencyKind, Edition, Env, + FileId, FilePosition, FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, + ProcMacros, ReleaseChannel, SourceDatabaseExt, SourceRoot, SourceRootId, }; pub const WORKSPACE: SourceRootId = SourceRootId(0); @@ -237,7 +237,12 @@ impl ChangeFixture { crate_graph .add_dep( from_id, - Dependency::with_prelude(CrateName::new(&to).unwrap(), to_id, prelude), + Dependency::with_prelude( + CrateName::new(&to).unwrap(), + to_id, + prelude, + DependencyKind::Normal, + ), ) .unwrap(); } @@ -275,7 +280,14 @@ impl ChangeFixture { for krate in all_crates { crate_graph - .add_dep(krate, Dependency::new(CrateName::new("core").unwrap(), core_crate)) + .add_dep( + krate, + Dependency::new( + CrateName::new("core").unwrap(), + core_crate, + DependencyKind::Normal, + ), + ) .unwrap(); } } @@ -317,7 +329,11 @@ impl ChangeFixture { crate_graph .add_dep( krate, - Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate), + Dependency::new( + CrateName::new("proc_macros").unwrap(), + proc_macros_crate, + DependencyKind::Normal, + ), ) .unwrap(); } diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index b75c7079be787..e4f78321e215a 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -155,6 +155,10 @@ impl CrateOrigin { pub fn is_local(&self) -> bool { matches!(self, CrateOrigin::Local { .. }) } + + pub fn is_lib(&self) -> bool { + matches!(self, CrateOrigin::Library { .. }) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -257,6 +261,7 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe { ) -> Result; } +#[derive(Debug)] pub enum ProcMacroExpansionError { Panic(String), /// Things like "proc macro server was killed by OOM". @@ -323,6 +328,62 @@ pub struct CrateData { pub channel: Option, } +impl CrateData { + /// Check if [`other`] is almost equal to [`self`] ignoring `CrateOrigin` value. + pub fn eq_ignoring_origin_and_deps(&self, other: &CrateData, ignore_dev_deps: bool) -> bool { + // This method has some obscure bits. These are mostly there to be compliant with + // some patches. References to the patches are given. + if self.root_file_id != other.root_file_id { + return false; + } + + if self.display_name != other.display_name { + return false; + } + + if self.is_proc_macro != other.is_proc_macro { + return false; + } + + if self.edition != other.edition { + return false; + } + + if self.version != other.version { + return false; + } + + let mut opts = self.cfg_options.difference(&other.cfg_options); + if let Some(it) = opts.next() { + // Don't care if rust_analyzer CfgAtom is the only cfg in the difference set of self's and other's cfgs. + // https://github.com/rust-lang/rust-analyzer/blob/0840038f02daec6ba3238f05d8caa037d28701a0/crates/project-model/src/workspace.rs#L894 + if it.to_string() != "rust_analyzer" { + return false; + } + + if let Some(_) = opts.next() { + return false; + } + } + + if self.env != other.env { + return false; + } + + let slf_deps = self.dependencies.iter(); + let other_deps = other.dependencies.iter(); + + if ignore_dev_deps { + return slf_deps + .clone() + .filter(|it| it.kind != DependencyKind::Dev) + .eq(other_deps.clone().filter(|it| it.kind != DependencyKind::Dev)); + } + + slf_deps.eq(other_deps) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Edition { Edition2015, @@ -350,26 +411,43 @@ impl Env { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum DependencyKind { + Normal, + Dev, + Build, +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Dependency { pub crate_id: CrateId, pub name: CrateName, + kind: DependencyKind, prelude: bool, } impl Dependency { - pub fn new(name: CrateName, crate_id: CrateId) -> Self { - Self { name, crate_id, prelude: true } + pub fn new(name: CrateName, crate_id: CrateId, kind: DependencyKind) -> Self { + Self { name, crate_id, prelude: true, kind } } - pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool) -> Self { - Self { name, crate_id, prelude } + pub fn with_prelude( + name: CrateName, + crate_id: CrateId, + prelude: bool, + kind: DependencyKind, + ) -> Self { + Self { name, crate_id, prelude, kind } } /// Whether this dependency is to be added to the depending crate's extern prelude. pub fn is_prelude(&self) -> bool { self.prelude } + + pub fn kind(&self) -> DependencyKind { + self.kind + } } impl CrateGraph { @@ -573,23 +651,46 @@ impl CrateGraph { pub fn extend(&mut self, mut other: CrateGraph, proc_macros: &mut ProcMacroPaths) { let topo = other.crates_in_topological_order(); let mut id_map: FxHashMap = FxHashMap::default(); - for topo in topo { let crate_data = &mut other.arena[topo]; + crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]); crate_data.dependencies.sort_by_key(|dep| dep.crate_id); - - let res = self.arena.iter().find_map( - |(id, data)| { - if data == crate_data { - Some(id) - } else { - None + let res = self.arena.iter().find_map(|(id, data)| { + match (&data.origin, &crate_data.origin) { + (a, b) if a == b => { + if data.eq_ignoring_origin_and_deps(&crate_data, false) { + return Some((id, false)); + } } - }, - ); - if let Some(res) = res { + (a @ CrateOrigin::Local { .. }, CrateOrigin::Library { .. }) + | (a @ CrateOrigin::Library { .. }, CrateOrigin::Local { .. }) => { + // If the origins differ, check if the two crates are equal without + // considering the dev dependencies, if they are, they most likely are in + // different loaded workspaces which may cause issues. We keep the local + // version and discard the library one as the local version may have + // dev-dependencies that we want to keep resolving. See #15656 for more + // information. + if data.eq_ignoring_origin_and_deps(&crate_data, true) { + return Some((id, if a.is_local() { false } else { true })); + } + } + (_, _) => return None, + } + + None + }); + + if let Some((res, should_update_lib_to_local)) = res { id_map.insert(topo, res); + if should_update_lib_to_local { + assert!(self.arena[res].origin.is_lib()); + assert!(crate_data.origin.is_local()); + self.arena[res].origin = crate_data.origin.clone(); + + // Move local's dev dependencies into the newly-local-formerly-lib crate. + self.arena[res].dependencies = crate_data.dependencies.clone(); + } } else { let id = self.arena.alloc(crate_data.clone()); id_map.insert(topo, id); @@ -635,9 +736,11 @@ impl CrateGraph { match (cfg_if, std) { (Some(cfg_if), Some(std)) => { self.arena[cfg_if].dependencies.clear(); - self.arena[std] - .dependencies - .push(Dependency::new(CrateName::new("cfg_if").unwrap(), cfg_if)); + self.arena[std].dependencies.push(Dependency::new( + CrateName::new("cfg_if").unwrap(), + cfg_if, + DependencyKind::Normal, + )); true } _ => false, @@ -657,6 +760,8 @@ impl ops::Index for CrateGraph { } impl CrateData { + /// Add a dependency to `self` without checking if the dependency + // is existent among `self.dependencies`. fn add_dep(&mut self, dep: Dependency) { self.dependencies.push(dep) } @@ -758,7 +863,7 @@ impl fmt::Display for CyclicDependenciesError { #[cfg(test)] mod tests { - use crate::CrateOrigin; + use crate::{CrateOrigin, DependencyKind}; use super::{CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId}; @@ -805,13 +910,22 @@ mod tests { None, ); assert!(graph - .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) + .add_dep( + crate1, + Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal) + ) .is_ok()); assert!(graph - .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3)) + .add_dep( + crate2, + Dependency::new(CrateName::new("crate3").unwrap(), crate3, DependencyKind::Normal) + ) .is_ok()); assert!(graph - .add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1)) + .add_dep( + crate3, + Dependency::new(CrateName::new("crate1").unwrap(), crate1, DependencyKind::Normal) + ) .is_err()); } @@ -845,10 +959,16 @@ mod tests { None, ); assert!(graph - .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) + .add_dep( + crate1, + Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal) + ) .is_ok()); assert!(graph - .add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) + .add_dep( + crate2, + Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal) + ) .is_err()); } @@ -895,10 +1015,16 @@ mod tests { None, ); assert!(graph - .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) + .add_dep( + crate1, + Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal) + ) .is_ok()); assert!(graph - .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3)) + .add_dep( + crate2, + Dependency::new(CrateName::new("crate3").unwrap(), crate3, DependencyKind::Normal) + ) .is_ok()); } @@ -934,12 +1060,20 @@ mod tests { assert!(graph .add_dep( crate1, - Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2) + Dependency::new( + CrateName::normalize_dashes("crate-name-with-dashes"), + crate2, + DependencyKind::Normal + ) ) .is_ok()); assert_eq!( graph[crate1].dependencies, - vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2)] + vec![Dependency::new( + CrateName::new("crate_name_with_dashes").unwrap(), + crate2, + DependencyKind::Normal + )] ); } } diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index af204e44e6ee1..40cfab88afdbe 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -12,6 +12,7 @@ use rustc_hash::FxHashSet; use syntax::{ast, Parse, SourceFile, TextRange, TextSize}; use triomphe::Arc; +pub use crate::input::DependencyKind; pub use crate::{ change::Change, input::{ @@ -75,7 +76,7 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug { #[salsa::input] fn crate_graph(&self) -> Arc; - /// The crate graph. + /// The proc macros. #[salsa::input] fn proc_macros(&self) -> Arc; } diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml index ed380897278b3..4324584df39d6 100644 --- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml +++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml @@ -23,8 +23,8 @@ oorandom = "11.1.3" # We depend on both individually instead of using `features = ["derive"]` to microoptimize the # build graph: if the feature was enabled, syn would be built early on in the graph if `smolstr` # supports `arbitrary`. This way, we avoid feature unification. -arbitrary = "1.3.0" -derive_arbitrary = "1.3.1" +arbitrary = "1.3.2" +derive_arbitrary = "1.3.2" # local deps mbe.workspace = true diff --git a/src/tools/rust-analyzer/crates/cfg/src/lib.rs b/src/tools/rust-analyzer/crates/cfg/src/lib.rs index 0aeb0b0505248..8bbe5e2a8c29b 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/lib.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/lib.rs @@ -58,6 +58,13 @@ impl CfgOptions { self.enabled.insert(CfgAtom::KeyValue { key, value }); } + pub fn difference<'a>( + &'a self, + other: &'a CfgOptions, + ) -> impl Iterator + 'a { + self.enabled.difference(&other.enabled) + } + pub fn apply_diff(&mut self, diff: CfgDiff) { for atom in diff.enable { self.enabled.insert(atom); diff --git a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml index e7f7adc784717..4322d2d966a11 100644 --- a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml +++ b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml @@ -12,9 +12,9 @@ rust-version.workspace = true doctest = false [dependencies] +cargo_metadata.workspace = true crossbeam-channel = "0.5.8" -tracing = "0.1.37" -cargo_metadata = "0.15.4" +tracing.workspace = true rustc-hash = "1.1.0" serde_json.workspace = true serde.workspace = true diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs index 2de719af92ce9..0749d91eb32a1 100644 --- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs +++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs @@ -50,6 +50,7 @@ pub enum FlycheckConfig { extra_args: Vec, extra_env: FxHashMap, ansi_color_output: bool, + target_dir: Option, }, CustomCommand { command: String, @@ -308,6 +309,7 @@ impl FlycheckActor { features, extra_env, ansi_color_output, + target_dir, } => { let mut cmd = Command::new(toolchain::cargo()); cmd.arg(command); @@ -340,6 +342,9 @@ impl FlycheckActor { cmd.arg(features.join(" ")); } } + if let Some(target_dir) = target_dir { + cmd.arg("--target-dir").arg(target_dir); + } cmd.envs(extra_env); (cmd, extra_args) } diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index 8cf61ee04d4e6..e4f2e14c51c72 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -12,29 +12,25 @@ rust-version.workspace = true doctest = false [dependencies] -anymap = "1.0.0-beta.2" arrayvec = "0.7.2" -bitflags = "2.1.0" +bitflags.workspace = true cov-mark = "2.0.0-pre.1" # We need to freeze the version of the crate, as the raw-api feature is considered unstable dashmap = { version = "=5.4.0", features = ["raw-api"] } drop_bomb = "0.1.5" -either = "1.7.0" +either.workspace = true fst = { version = "0.4.7", default-features = false } -indexmap = "2.0.0" -itertools = "0.10.5" +indexmap.workspace = true +itertools.workspace = true la-arena.workspace = true once_cell = "1.17.0" rustc-hash = "1.1.0" -tracing = "0.1.35" +tracing.workspace = true smallvec.workspace = true hashbrown.workspace = true triomphe.workspace = true -rustc_abi.workspace = true -rustc_index.workspace = true -rustc_parse_format.workspace = true - +rustc-dependencies.workspace = true # local deps stdx.workspace = true @@ -48,8 +44,12 @@ cfg.workspace = true tt.workspace = true limit.workspace = true + [dev-dependencies] expect-test = "1.4.0" # local deps test-utils.workspace = true + +[features] +in-rust-tree = ["rustc-dependencies/in-rust-tree"] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index c6454eb9ea024..fa3025e0303d1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -215,6 +215,10 @@ impl Attrs { self.doc_exprs().flat_map(|doc_expr| doc_expr.aliases().to_vec()) } + pub fn export_name(&self) -> Option<&SmolStr> { + self.by_key("export_name").string_value() + } + pub fn is_proc_macro(&self) -> bool { self.by_key("proc_macro").exists() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs index 2ae3cd2a939d5..15dceeb8af254 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs @@ -629,7 +629,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), rustc_attr!( TEST, rustc_error, Normal, - template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly + template!(Word, List: "span_delayed_bug_from_inside_query"), WarnFollowingWordOnly ), rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index c0baf6011f792..1942c60c075d7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -57,7 +57,7 @@ pub struct Body { pub type ExprPtr = AstPtr; pub type ExprSource = InFile; -pub type PatPtr = Either, AstPtr>; +pub type PatPtr = AstPtr>; pub type PatSource = InFile; pub type LabelPtr = AstPtr; @@ -356,12 +356,12 @@ impl BodySourceMap { } pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { - let src = node.map(|it| Either::Left(AstPtr::new(it))); + let src = node.map(|it| AstPtr::new(it).wrap_left()); self.pat_map.get(&src).cloned() } pub fn node_self_param(&self, node: InFile<&ast::SelfParam>) -> Option { - let src = node.map(|it| Either::Right(AstPtr::new(it))); + let src = node.map(|it| AstPtr::new(it).wrap_right()); self.pat_map.get(&src).cloned() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index cc02df80a8ffd..e4158d7564bdb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -196,16 +196,12 @@ impl ExprCollector<'_> { if let Some(self_param) = param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false)) { - let ptr = AstPtr::new(&self_param); - let binding_id: la_arena::Idx = self.alloc_binding( - name![self], - BindingAnnotation::new( - self_param.mut_token().is_some() && self_param.amp_token().is_none(), - false, - ), - ); - let param_pat = - self.alloc_pat(Pat::Bind { id: binding_id, subpat: None }, Either::Right(ptr)); + let is_mutable = + self_param.mut_token().is_some() && self_param.amp_token().is_none(); + let ptr = AstPtr::new(&Either::Right(self_param)); + let binding_id: la_arena::Idx = + self.alloc_binding(name![self], BindingAnnotation::new(is_mutable, false)); + let param_pat = self.alloc_pat(Pat::Bind { id: binding_id, subpat: None }, ptr); self.add_definition_to_binding(binding_id, param_pat); self.body.params.push(param_pat); } @@ -1260,8 +1256,8 @@ impl ExprCollector<'_> { (Some(id), Pat::Bind { id, subpat }) }; - let ptr = AstPtr::new(&pat); - let pat = self.alloc_pat(pattern, Either::Left(ptr)); + let ptr = AstPtr::new(&Either::Left(pat)); + let pat = self.alloc_pat(pattern, ptr); if let Some(binding_id) = binding { self.add_definition_to_binding(binding_id, pat); } @@ -1395,7 +1391,7 @@ impl ExprCollector<'_> { ast::Pat::MacroPat(mac) => match mac.macro_call() { Some(call) => { let macro_ptr = AstPtr::new(&call); - let src = self.expander.to_source(Either::Left(AstPtr::new(&pat))); + let src = self.expander.to_source(AstPtr::new(&Either::Left(pat))); let pat = self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| { this.collect_pat_opt(expanded_pat, binding_list) @@ -1430,8 +1426,8 @@ impl ExprCollector<'_> { Pat::Range { start, end } } }; - let ptr = AstPtr::new(&pat); - self.alloc_pat(pattern, Either::Left(ptr)) + let ptr = AstPtr::new(&Either::Left(pat)); + self.alloc_pat(pattern, ptr) } fn collect_pat_opt(&mut self, pat: Option, binding_list: &mut BindingList) -> PatId { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs index fad4d7a4da66e..6ecf1c20d6c1a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs @@ -54,7 +54,7 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo let mut p = Printer { db, body, buf: header, indent_level: 0, needs_indent: false }; if let DefWithBodyId::FunctionId(it) = owner { p.buf.push('('); - body.params.iter().zip(&db.function_data(it).params).for_each(|(¶m, ty)| { + body.params.iter().zip(db.function_data(it).params.iter()).for_each(|(¶m, ty)| { p.print_pat(param); p.buf.push(':'); p.print_type_ref(ty); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs index 2a90a09f25e8c..baca293e29041 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs @@ -1,7 +1,6 @@ //! Name resolution for expressions. use hir_expand::name::Name; -use la_arena::{Arena, Idx, IdxRange, RawIdx}; -use rustc_hash::FxHashMap; +use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx}; use triomphe::Arc; use crate::{ @@ -17,7 +16,7 @@ pub type ScopeId = Idx; pub struct ExprScopes { scopes: Arena, scope_entries: Arena, - scope_by_expr: FxHashMap, + scope_by_expr: ArenaMap, } #[derive(Debug, PartialEq, Eq)] @@ -77,10 +76,10 @@ impl ExprScopes { } pub fn scope_for(&self, expr: ExprId) -> Option { - self.scope_by_expr.get(&expr).copied() + self.scope_by_expr.get(expr).copied() } - pub fn scope_by_expr(&self) -> &FxHashMap { + pub fn scope_by_expr(&self) -> &ArenaMap { &self.scope_by_expr } } @@ -94,7 +93,7 @@ impl ExprScopes { let mut scopes = ExprScopes { scopes: Arena::default(), scope_entries: Arena::default(), - scope_by_expr: FxHashMap::default(), + scope_by_expr: ArenaMap::with_capacity(body.exprs.len()), }; let mut root = scopes.root_scope(); scopes.add_params_bindings(body, root, &body.params); @@ -476,10 +475,7 @@ fn foo() { .pat_syntax(*body.bindings[resolved.binding()].definitions.first().unwrap()) .unwrap(); - let local_name = pat_src.value.either( - |it| it.syntax_node_ptr().to_node(file.syntax()), - |it| it.syntax_node_ptr().to_node(file.syntax()), - ); + let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax()); assert_eq!(local_name.text_range(), expected_name.syntax().text_range()); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index 68defa3858fc3..72ccc17486f0d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -15,9 +15,7 @@ use crate::{ attr::Attrs, db::DefDatabase, expander::{Expander, Mark}, - item_tree::{ - self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, Param, TreeId, - }, + item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, macro_call_as_call_id, macro_id_to_def_id, nameres::{ attr_resolution::ResolvedAttr, @@ -36,7 +34,7 @@ use crate::{ #[derive(Debug, Clone, PartialEq, Eq)] pub struct FunctionData { pub name: Name, - pub params: Vec>, + pub params: Box<[Interned]>, pub ret_type: Interned, pub attrs: Attrs, pub visibility: RawVisibility, @@ -69,7 +67,7 @@ impl FunctionData { let is_varargs = enabled_params .clone() .next_back() - .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); + .map_or(false, |param| item_tree[param].type_ref.is_none()); let mut flags = func.flags; if is_varargs { @@ -105,10 +103,7 @@ impl FunctionData { name: func.name.clone(), params: enabled_params .clone() - .filter_map(|id| match &item_tree[id] { - Param::Normal(ty) => Some(ty.clone()), - Param::Varargs => None, - }) + .filter_map(|id| item_tree[id].type_ref.clone()) .collect(), ret_type: func.ret_type.clone(), attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), @@ -182,7 +177,7 @@ pub struct TypeAliasData { pub rustc_has_incoherent_inherent_impls: bool, pub rustc_allow_incoherent_impl: bool, /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). - pub bounds: Vec>, + pub bounds: Box<[Interned]>, } impl TypeAliasData { @@ -215,7 +210,7 @@ impl TypeAliasData { is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)), rustc_has_incoherent_inherent_impls, rustc_allow_incoherent_impl, - bounds: typ.bounds.to_vec(), + bounds: typ.bounds.clone(), }) } } @@ -332,6 +327,7 @@ pub struct ImplData { pub self_ty: Interned, pub items: Vec, pub is_negative: bool, + pub is_unsafe: bool, // box it as the vec is usually empty anyways pub attribute_calls: Option, MacroCallId)>>>, } @@ -353,6 +349,7 @@ impl ImplData { let target_trait = impl_def.target_trait.clone(); let self_ty = impl_def.self_ty.clone(); let is_negative = impl_def.is_negative; + let is_unsafe = impl_def.is_unsafe; let mut collector = AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::ImplId(id)); @@ -362,7 +359,14 @@ impl ImplData { let items = items.into_iter().map(|(_, item)| item).collect(); ( - Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }), + Arc::new(ImplData { + target_trait, + self_ty, + items, + is_negative, + is_unsafe, + attribute_calls, + }), diagnostics.into(), ) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index 224f7328f8cdc..b163112db9184 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -11,7 +11,7 @@ use hir_expand::{ }; use intern::Interned; use la_arena::{Arena, ArenaMap}; -use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; +use rustc_dependencies::abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; use syntax::ast::{self, HasName, HasVisibility}; use triomphe::Arc; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs index 63138aa6ad78f..a59bbf7e22111 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs @@ -29,8 +29,8 @@ use std::{ ops::{Index, IndexMut}, }; -use anymap::Map; use rustc_hash::FxHashMap; +use stdx::anymap::Map; pub struct Key { _phantom: PhantomData<(K, V, P)>, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index b9c5ff72792af..1ebd1ba0e66db 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -21,9 +21,10 @@ pub fn find_path( item: ItemInNs, from: ModuleId, prefer_no_std: bool, + prefer_prelude: bool, ) -> Option { let _p = profile::span("find_path"); - find_path_inner(db, item, from, None, prefer_no_std) + find_path_inner(db, item, from, None, prefer_no_std, prefer_prelude) } pub fn find_path_prefixed( @@ -32,9 +33,10 @@ pub fn find_path_prefixed( from: ModuleId, prefix_kind: PrefixKind, prefer_no_std: bool, + prefer_prelude: bool, ) -> Option { let _p = profile::span("find_path_prefixed"); - find_path_inner(db, item, from, Some(prefix_kind), prefer_no_std) + find_path_inner(db, item, from, Some(prefix_kind), prefer_no_std, prefer_prelude) } #[derive(Copy, Clone, Debug)] @@ -88,6 +90,7 @@ fn find_path_inner( from: ModuleId, prefixed: Option, prefer_no_std: bool, + prefer_prelude: bool, ) -> Option { // - if the item is a builtin, it's in scope if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item { @@ -109,6 +112,7 @@ fn find_path_inner( MAX_PATH_LEN, prefixed, prefer_no_std || db.crate_supports_no_std(crate_root.krate), + prefer_prelude, ) .map(|(item, _)| item); } @@ -134,6 +138,7 @@ fn find_path_inner( from, prefixed, prefer_no_std, + prefer_prelude, ) { let data = db.enum_data(variant.parent); path.push_segment(data.variants[variant.local_id].name.clone()); @@ -156,6 +161,7 @@ fn find_path_inner( from, prefixed, prefer_no_std || db.crate_supports_no_std(crate_root.krate), + prefer_prelude, scope_name, ) .map(|(item, _)| item) @@ -171,6 +177,7 @@ fn find_path_for_module( max_len: usize, prefixed: Option, prefer_no_std: bool, + prefer_prelude: bool, ) -> Option<(ModPath, Stability)> { if max_len == 0 { return None; @@ -236,6 +243,7 @@ fn find_path_for_module( from, prefixed, prefer_no_std, + prefer_prelude, scope_name, ) } @@ -316,6 +324,7 @@ fn calculate_best_path( from: ModuleId, mut prefixed: Option, prefer_no_std: bool, + prefer_prelude: bool, scope_name: Option, ) -> Option<(ModPath, Stability)> { if max_len <= 1 { @@ -351,11 +360,14 @@ fn calculate_best_path( best_path_len - 1, prefixed, prefer_no_std, + prefer_prelude, ) { path.0.push_segment(name); let new_path = match best_path.take() { - Some(best_path) => select_best_path(best_path, path, prefer_no_std), + Some(best_path) => { + select_best_path(best_path, path, prefer_no_std, prefer_prelude) + } None => path, }; best_path_len = new_path.0.len(); @@ -367,18 +379,18 @@ fn calculate_best_path( // too (unless we can't name it at all). It could *also* be (re)exported by the same crate // that wants to import it here, but we always prefer to use the external path here. - let crate_graph = db.crate_graph(); - let extern_paths = crate_graph[from.krate].dependencies.iter().filter_map(|dep| { + for dep in &db.crate_graph()[from.krate].dependencies { let import_map = db.import_map(dep.crate_id); - import_map.import_info_for(item).and_then(|info| { + let Some(import_info_for) = import_map.import_info_for(item) else { continue }; + for info in import_info_for { if info.is_doc_hidden { // the item or import is `#[doc(hidden)]`, so skip it as it is in an external crate - return None; + continue; } // Determine best path for containing module and append last segment from `info`. // FIXME: we should guide this to look up the path locally, or from the same crate again? - let (mut path, path_stability) = find_path_for_module( + let Some((mut path, path_stability)) = find_path_for_module( db, def_map, visited_modules, @@ -388,22 +400,26 @@ fn calculate_best_path( max_len - 1, prefixed, prefer_no_std, - )?; + prefer_prelude, + ) else { + continue; + }; cov_mark::hit!(partially_imported); path.push_segment(info.name.clone()); - Some(( + + let path_with_stab = ( path, zip_stability(path_stability, if info.is_unstable { Unstable } else { Stable }), - )) - }) - }); + ); - for path in extern_paths { - let new_path = match best_path.take() { - Some(best_path) => select_best_path(best_path, path, prefer_no_std), - None => path, - }; - update_best_path(&mut best_path, new_path); + let new_path_with_stab = match best_path.take() { + Some(best_path) => { + select_best_path(best_path, path_with_stab, prefer_no_std, prefer_prelude) + } + None => path_with_stab, + }; + update_best_path(&mut best_path, new_path_with_stab); + } } } if let Some(module) = item.module(db) { @@ -420,17 +436,39 @@ fn calculate_best_path( } } +/// Select the best (most relevant) path between two paths. +/// This accounts for stability, path length whether std should be chosen over alloc/core paths as +/// well as ignoring prelude like paths or not. fn select_best_path( - old_path: (ModPath, Stability), - new_path: (ModPath, Stability), + old_path @ (_, old_stability): (ModPath, Stability), + new_path @ (_, new_stability): (ModPath, Stability), prefer_no_std: bool, + prefer_prelude: bool, ) -> (ModPath, Stability) { - match (old_path.1, new_path.1) { + match (old_stability, new_stability) { (Stable, Unstable) => return old_path, (Unstable, Stable) => return new_path, _ => {} } const STD_CRATES: [Name; 3] = [known::std, known::core, known::alloc]; + + let choose = |new_path: (ModPath, _), old_path: (ModPath, _)| { + let new_has_prelude = new_path.0.segments().iter().any(|seg| seg == &known::prelude); + let old_has_prelude = old_path.0.segments().iter().any(|seg| seg == &known::prelude); + match (new_has_prelude, old_has_prelude, prefer_prelude) { + (true, false, true) | (false, true, false) => new_path, + (true, false, false) | (false, true, true) => old_path, + // no prelude difference in the paths, so pick the smaller one + (true, true, _) | (false, false, _) => { + if new_path.0.len() < old_path.0.len() { + new_path + } else { + old_path + } + } + } + }; + match (old_path.0.segments().first(), new_path.0.segments().first()) { (Some(old), Some(new)) if STD_CRATES.contains(old) && STD_CRATES.contains(new) => { let rank = match prefer_no_std { @@ -451,23 +489,11 @@ fn select_best_path( let orank = rank(old); match nrank.cmp(&orank) { Ordering::Less => old_path, - Ordering::Equal => { - if new_path.0.len() < old_path.0.len() { - new_path - } else { - old_path - } - } + Ordering::Equal => choose(new_path, old_path), Ordering::Greater => new_path, } } - _ => { - if new_path.0.len() < old_path.0.len() { - new_path - } else { - old_path - } - } + _ => choose(new_path, old_path), } } @@ -570,7 +596,13 @@ mod tests { /// `code` needs to contain a cursor marker; checks that `find_path` for the /// item the `path` refers to returns that same path when called from the /// module the cursor is in. - fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option) { + #[track_caller] + fn check_found_path_( + ra_fixture: &str, + path: &str, + prefix_kind: Option, + prefer_prelude: bool, + ) { let (db, pos) = TestDB::with_position(ra_fixture); let module = db.module_at_position(pos); let parsed_path_file = syntax::SourceFile::parse(&format!("use {path};")); @@ -589,11 +621,17 @@ mod tests { ) .0 .take_types() - .unwrap(); - - let found_path = - find_path_inner(&db, ItemInNs::Types(resolved), module, prefix_kind, false); - assert_eq!(found_path, Some(mod_path), "{prefix_kind:?}"); + .expect("path does not resolve to a type"); + + let found_path = find_path_inner( + &db, + ItemInNs::Types(resolved), + module, + prefix_kind, + false, + prefer_prelude, + ); + assert_eq!(found_path, Some(mod_path), "on kind: {prefix_kind:?}"); } fn check_found_path( @@ -603,10 +641,23 @@ mod tests { absolute: &str, self_prefixed: &str, ) { - check_found_path_(ra_fixture, unprefixed, None); - check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain)); - check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate)); - check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf)); + check_found_path_(ra_fixture, unprefixed, None, false); + check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain), false); + check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate), false); + check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf), false); + } + + fn check_found_path_prelude( + ra_fixture: &str, + unprefixed: &str, + prefixed: &str, + absolute: &str, + self_prefixed: &str, + ) { + check_found_path_(ra_fixture, unprefixed, None, true); + check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain), true); + check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate), true); + check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf), true); } #[test] @@ -1421,4 +1472,34 @@ pub mod error { "std::error::Error", ); } + + #[test] + fn respects_prelude_setting() { + let ra_fixture = r#" +//- /main.rs crate:main deps:krate +$0 +//- /krate.rs crate:krate +pub mod prelude { + pub use crate::foo::*; +} + +pub mod foo { + pub struct Foo; +} +"#; + check_found_path( + ra_fixture, + "krate::foo::Foo", + "krate::foo::Foo", + "krate::foo::Foo", + "krate::foo::Foo", + ); + check_found_path_prelude( + ra_fixture, + "krate::prelude::Foo", + "krate::prelude::Foo", + "krate::prelude::Foo", + "krate::prelude::Foo", + ); + } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs index 1e2535a8a9993..fac90e6630452 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs @@ -227,7 +227,7 @@ impl GenericParams { let mut expander = Lazy::new(|| { (module.def_map(db), Expander::new(db, loc.source(db).file_id, module)) }); - for param in &func_data.params { + for param in func_data.params.iter() { generic_params.fill_implicit_impl_trait_args(db, &mut expander, param); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 75025a984fcd2..46d24bd4a6142 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -2,7 +2,7 @@ use std::mem; use hir_expand::name::Name; -use rustc_parse_format as parse; +use rustc_dependencies::parse_format as parse; use syntax::{ ast::{self, IsString}, AstToken, SmolStr, TextRange, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index 44b7f1b4f63ed..d589fbe347a9f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -1,49 +1,48 @@ //! A map of all publicly exported items in a crate. -use std::collections::hash_map::Entry; use std::{fmt, hash::BuildHasherDefault}; use base_db::CrateId; -use fst::{self, Streamer}; +use fst::{self, raw::IndexedValue, Streamer}; use hir_expand::name::Name; use indexmap::IndexMap; use itertools::Itertools; -use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; +use rustc_hash::{FxHashSet, FxHasher}; +use smallvec::SmallVec; use triomphe::Arc; -use crate::item_scope::ImportOrExternCrate; use crate::{ - db::DefDatabase, item_scope::ItemInNs, nameres::DefMap, visibility::Visibility, AssocItemId, - ModuleDefId, ModuleId, TraitId, + db::DefDatabase, + item_scope::{ImportOrExternCrate, ItemInNs}, + nameres::DefMap, + visibility::Visibility, + AssocItemId, ModuleDefId, ModuleId, TraitId, }; type FxIndexMap = IndexMap>; -// FIXME: Support aliases: an item may be exported under multiple names, so `ImportInfo` should -// have `Vec<(Name, ModuleId)>` instead of `(Name, ModuleId)`. /// Item import details stored in the `ImportMap`. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct ImportInfo { /// A name that can be used to import the item, relative to the crate's root. pub name: Name, /// The module containing this item. pub container: ModuleId, - /// Whether the import is a trait associated item or not. - pub is_trait_assoc_item: bool, /// Whether this item is annotated with `#[doc(hidden)]`. pub is_doc_hidden: bool, /// Whether this item is annotated with `#[unstable(..)]`. pub is_unstable: bool, } +type ImportMapIndex = FxIndexMap, IsTraitAssocItem)>; + /// A map from publicly exported items to its name. /// /// Reexports of items are taken into account, ie. if something is exported under multiple /// names, the one with the shortest import path will be used. #[derive(Default)] pub struct ImportMap { - map: FxIndexMap, - + map: ImportMapIndex, /// List of keys stored in `map`, sorted lexicographically by their `ModPath`. Indexed by the /// values returned by running `fst`. /// @@ -54,6 +53,12 @@ pub struct ImportMap { fst: fst::Map>, } +#[derive(Copy, Clone, PartialEq, Eq)] +enum IsTraitAssocItem { + Yes, + No, +} + impl ImportMap { pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { let _p = profile::span("import_map_query"); @@ -63,13 +68,18 @@ impl ImportMap { let mut importables: Vec<_> = map .iter() // We've only collected items, whose name cannot be tuple field. - .map(|(&item, info)| (item, info.name.as_str().unwrap().to_ascii_lowercase())) + .flat_map(|(&item, (info, _))| { + info.iter() + .map(move |info| (item, info.name.as_str().unwrap().to_ascii_lowercase())) + }) .collect(); importables.sort_by(|(_, lhs_name), (_, rhs_name)| lhs_name.cmp(rhs_name)); + importables.dedup(); // Build the FST, taking care not to insert duplicate values. let mut builder = fst::MapBuilder::memory(); - let iter = importables.iter().enumerate().dedup_by(|lhs, rhs| lhs.1 .1 == rhs.1 .1); + let iter = + importables.iter().enumerate().dedup_by(|(_, (_, lhs)), (_, (_, rhs))| lhs == rhs); for (start_idx, (_, name)) in iter { let _ = builder.insert(name, start_idx as u64); } @@ -81,12 +91,12 @@ impl ImportMap { }) } - pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> { - self.map.get(&item) + pub fn import_info_for(&self, item: ItemInNs) -> Option<&[ImportInfo]> { + self.map.get(&item).map(|(info, _)| &**info) } } -fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap { +fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex { let _p = profile::span("collect_import_map"); let def_map = db.crate_def_map(krate); @@ -94,11 +104,13 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap FxIndexMap Some(id.into()), } }; - let status @ (is_doc_hidden, is_unstable) = - attr_id.map_or((false, false), |attr_id| { - let attrs = db.attrs(attr_id); - (attrs.has_doc_hidden(), attrs.is_unstable()) - }); + let (is_doc_hidden, is_unstable) = attr_id.map_or((false, false), |attr_id| { + let attrs = db.attrs(attr_id); + (attrs.has_doc_hidden(), attrs.is_unstable()) + }); let import_info = ImportInfo { name: name.clone(), container: module, - is_trait_assoc_item: false, is_doc_hidden, is_unstable, }; - match depth_map.entry(item) { - Entry::Vacant(entry) => _ = entry.insert((depth, status)), - Entry::Occupied(mut entry) => { - let &(occ_depth, (occ_is_doc_hidden, occ_is_unstable)) = entry.get(); - (depth, occ_depth); - let overwrite = match ( - is_doc_hidden, - occ_is_doc_hidden, - is_unstable, - occ_is_unstable, - ) { - // no change of hiddeness or unstableness - (true, true, true, true) - | (true, true, false, false) - | (false, false, true, true) - | (false, false, false, false) => depth < occ_depth, - - // either less hidden or less unstable, accept - (true, true, false, true) - | (false, true, true, true) - | (false, true, false, true) - | (false, true, false, false) - | (false, false, false, true) => true, - // more hidden or unstable, discard - (true, true, true, false) - | (true, false, true, true) - | (true, false, true, false) - | (true, false, false, false) - | (false, false, true, false) => false, - - // exchanges doc(hidden) for unstable (and vice-versa), - (true, false, false, true) | (false, true, true, false) => { - depth < occ_depth - } - }; - if !overwrite { - continue; - } - entry.insert((depth, status)); - } - } - if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() { collect_trait_assoc_items( db, @@ -192,13 +160,14 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap FxIndexMap, + map: &mut ImportMapIndex, tr: TraitId, is_type_in_ns: bool, trait_import_info: &ImportInfo, @@ -236,11 +205,14 @@ fn collect_trait_assoc_items( let assoc_item_info = ImportInfo { container: trait_import_info.container, name: assoc_item_name.clone(), - is_trait_assoc_item: true, is_doc_hidden: attrs.has_doc_hidden(), is_unstable: attrs.is_unstable(), }; - map.insert(assoc_item, assoc_item_info); + + let (infos, _) = + map.entry(assoc_item).or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::Yes)); + infos.reserve_exact(1); + infos.push(assoc_item_info); } } @@ -258,10 +230,13 @@ impl fmt::Debug for ImportMap { let mut importable_names: Vec<_> = self .map .iter() - .map(|(item, _)| match item { - ItemInNs::Types(it) => format!("- {it:?} (t)",), - ItemInNs::Values(it) => format!("- {it:?} (v)",), - ItemInNs::Macros(it) => format!("- {it:?} (m)",), + .map(|(item, (infos, _))| { + let l = infos.len(); + match item { + ItemInNs::Types(it) => format!("- {it:?} (t) [{l}]",), + ItemInNs::Values(it) => format!("- {it:?} (v) [{l}]",), + ItemInNs::Macros(it) => format!("- {it:?} (m) [{l}]",), + } }) .collect(); @@ -271,13 +246,15 @@ impl fmt::Debug for ImportMap { } /// A way to match import map contents against the search query. -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] enum SearchMode { /// Import map entry should strictly match the query string. Exact, /// Import map entry should contain all letters from the query string, /// in the same order, but not necessary adjacent. Fuzzy, + /// Import map entry should match the query string by prefix. + Prefix, } /// Three possible ways to search for the name in associated and/or other items. @@ -319,6 +296,14 @@ impl Query { Self { search_mode: SearchMode::Fuzzy, ..self } } + pub fn prefix(self) -> Self { + Self { search_mode: SearchMode::Prefix, ..self } + } + + pub fn exact(self) -> Self { + Self { search_mode: SearchMode::Exact, ..self } + } + /// Specifies whether we want to include associated items in the result. pub fn assoc_search_mode(self, assoc_mode: AssocSearchMode) -> Self { Self { assoc_mode, ..self } @@ -334,6 +319,15 @@ impl Query { Self { case_sensitive: true, ..self } } + fn matches_assoc_mode(&self, is_trait_assoc_item: IsTraitAssocItem) -> bool { + match (is_trait_assoc_item, self.assoc_mode) { + (IsTraitAssocItem::Yes, AssocSearchMode::Exclude) + | (IsTraitAssocItem::No, AssocSearchMode::AssocItemsOnly) => false, + _ => true, + } + } + + /// Checks whether the import map entry matches the query. fn import_matches( &self, db: &dyn DefDatabase, @@ -341,12 +335,8 @@ impl Query { enforce_lowercase: bool, ) -> bool { let _p = profile::span("import_map::Query::import_matches"); - match (import.is_trait_assoc_item, self.assoc_mode) { - (true, AssocSearchMode::Exclude) => return false, - (false, AssocSearchMode::AssocItemsOnly) => return false, - _ => {} - } + // FIXME: Can we get rid of the alloc here? let mut input = import.name.display(db.upcast()).to_string(); let case_insensitive = enforce_lowercase || !self.case_sensitive; if case_insensitive { @@ -356,7 +346,8 @@ impl Query { let query_string = if case_insensitive { &self.lowercased } else { &self.query }; match self.search_mode { - SearchMode::Exact => &input == query_string, + SearchMode::Exact => input == *query_string, + SearchMode::Prefix => input.starts_with(query_string), SearchMode::Fuzzy => { let mut input_chars = input.chars(); for query_char in query_string.chars() { @@ -376,7 +367,7 @@ impl Query { pub fn search_dependencies( db: &dyn DefDatabase, krate: CrateId, - query: Query, + ref query: Query, ) -> FxHashSet { let _p = profile::span("search_dependencies").detail(|| format!("{query:?}")); @@ -394,31 +385,58 @@ pub fn search_dependencies( let mut stream = op.union(); let mut res = FxHashSet::default(); + let mut common_importable_data_scratch = vec![]; while let Some((_, indexed_values)) = stream.next() { - for indexed_value in indexed_values { - let import_map = &import_maps[indexed_value.index]; - let importables = &import_map.importables[indexed_value.value as usize..]; + for &IndexedValue { index, value } in indexed_values { + let import_map = &import_maps[index]; + let importables @ [importable, ..] = &import_map.importables[value as usize..] else { + continue; + }; - let common_importable_data = &import_map.map[&importables[0]]; - if !query.import_matches(db, common_importable_data, true) { + let &(ref importable_data, is_trait_assoc_item) = &import_map.map[importable]; + if !query.matches_assoc_mode(is_trait_assoc_item) { continue; } - // Name shared by the importable items in this group. - let common_importable_name = - common_importable_data.name.to_smol_str().to_ascii_lowercase(); - // Add the items from this name group. Those are all subsequent items in - // `importables` whose name match `common_importable_name`. - let iter = importables - .iter() - .copied() - .take_while(|item| { - common_importable_name - == import_map.map[item].name.to_smol_str().to_ascii_lowercase() - }) - .filter(|item| { - !query.case_sensitive // we've already checked the common importables name case-insensitively - || query.import_matches(db, &import_map.map[item], false) + common_importable_data_scratch.extend( + importable_data + .iter() + .filter(|&info| query.import_matches(db, info, true)) + // Name shared by the importable items in this group. + .map(|info| info.name.to_smol_str()), + ); + if common_importable_data_scratch.is_empty() { + continue; + } + common_importable_data_scratch.sort(); + common_importable_data_scratch.dedup(); + + let iter = + common_importable_data_scratch.drain(..).flat_map(|common_importable_name| { + // Add the items from this name group. Those are all subsequent items in + // `importables` whose name match `common_importable_name`. + importables + .iter() + .copied() + .take_while(move |item| { + let &(ref import_infos, assoc_mode) = &import_map.map[item]; + query.matches_assoc_mode(assoc_mode) + && import_infos.iter().any(|info| { + info.name + .to_smol_str() + .eq_ignore_ascii_case(&common_importable_name) + }) + }) + .filter(move |item| { + !query.case_sensitive || { + // we've already checked the common importables name case-insensitively + let &(ref import_infos, assoc_mode) = &import_map.map[item]; + query.matches_assoc_mode(assoc_mode) + && import_infos + .iter() + .any(|info| query.import_matches(db, info, false)) + } + }) }); res.extend(iter); @@ -445,6 +463,7 @@ mod tests { let mut importable_paths: Vec<_> = self .map .iter() + .flat_map(|(item, (info, _))| info.iter().map(move |info| (item, info))) .map(|(item, info)| { let path = render_path(db, info); let ns = match item { @@ -483,7 +502,7 @@ mod tests { let (path, mark) = match assoc_item_path(&db, &dependency_imports, dependency) { Some(assoc_item_path) => (assoc_item_path, "a"), None => ( - render_path(&db, dependency_imports.import_info_for(dependency)?), + render_path(&db, &dependency_imports.import_info_for(dependency)?[0]), match dependency { ItemInNs::Types(ModuleDefId::FunctionId(_)) | ItemInNs::Values(ModuleDefId::FunctionId(_)) => "f", @@ -531,7 +550,12 @@ mod tests { .items .iter() .find(|(_, assoc_item_id)| &dependency_assoc_item_id == assoc_item_id)?; - Some(format!("{}::{}", render_path(db, trait_info), assoc_item_name.display(db.upcast()))) + // FIXME: This should check all import infos, not just the first + Some(format!( + "{}::{}", + render_path(db, &trait_info[0]), + assoc_item_name.display(db.upcast()) + )) } fn check(ra_fixture: &str, expect: Expect) { @@ -607,6 +631,7 @@ mod tests { main: - publ1 (t) - real_pu2 (t) + - real_pu2::Pub (t) - real_pub (t) - real_pub::Pub (t) "#]], @@ -632,6 +657,7 @@ mod tests { - sub (t) - sub::Def (t) - sub::subsub (t) + - sub::subsub::Def (t) "#]], ); } @@ -731,7 +757,9 @@ mod tests { - module (t) - module::S (t) - module::S (v) + - module::module (t) - sub (t) + - sub::module (t) "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs index 4c812b62a46a4..473ae298c7744 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs @@ -38,7 +38,6 @@ mod tests; use std::{ fmt::{self, Debug}, hash::{Hash, Hasher}, - marker::PhantomData, ops::Index, }; @@ -340,34 +339,37 @@ pub trait ItemTreeNode: Clone { fn id_to_mod_item(id: FileItemTreeId) -> ModItem; } -pub struct FileItemTreeId { - index: Idx, - _p: PhantomData, +pub struct FileItemTreeId(Idx); + +impl FileItemTreeId { + pub fn index(&self) -> Idx { + self.0 + } } impl Clone for FileItemTreeId { fn clone(&self) -> Self { - Self { index: self.index, _p: PhantomData } + Self(self.0) } } impl Copy for FileItemTreeId {} impl PartialEq for FileItemTreeId { fn eq(&self, other: &FileItemTreeId) -> bool { - self.index == other.index + self.0 == other.0 } } impl Eq for FileItemTreeId {} impl Hash for FileItemTreeId { fn hash(&self, state: &mut H) { - self.index.hash(state) + self.0.hash(state) } } impl fmt::Debug for FileItemTreeId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.index.fmt(f) + self.0.fmt(f) } } @@ -548,7 +550,7 @@ impl Index for ItemTree { impl Index> for ItemTree { type Output = N; fn index(&self, id: FileItemTreeId) -> &N { - N::lookup(self, id.index) + N::lookup(self, id.index()) } } @@ -613,10 +615,17 @@ pub struct Function { pub(crate) flags: FnFlags, } -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Param { - Normal(Interned), - Varargs, +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Param { + /// This is [`None`] for varargs + pub type_ref: Option>, + pub ast_id: ParamAstId, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParamAstId { + Param(FileAstId), + SelfParam(FileAstId), } bitflags::bitflags! { @@ -702,6 +711,7 @@ pub struct Impl { pub target_trait: Option>, pub self_ty: Interned, pub is_negative: bool, + pub is_unsafe: bool, pub items: Box<[AssocItem]>, pub ast_id: FileAstId, } @@ -917,23 +927,23 @@ impl ModItem { pub fn ast_id(&self, tree: &ItemTree) -> FileAstId { match self { - ModItem::Use(it) => tree[it.index].ast_id().upcast(), - ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(), - ModItem::ExternBlock(it) => tree[it.index].ast_id().upcast(), - ModItem::Function(it) => tree[it.index].ast_id().upcast(), - ModItem::Struct(it) => tree[it.index].ast_id().upcast(), - ModItem::Union(it) => tree[it.index].ast_id().upcast(), - ModItem::Enum(it) => tree[it.index].ast_id().upcast(), - ModItem::Const(it) => tree[it.index].ast_id().upcast(), - ModItem::Static(it) => tree[it.index].ast_id().upcast(), - ModItem::Trait(it) => tree[it.index].ast_id().upcast(), - ModItem::TraitAlias(it) => tree[it.index].ast_id().upcast(), - ModItem::Impl(it) => tree[it.index].ast_id().upcast(), - ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(), - ModItem::Mod(it) => tree[it.index].ast_id().upcast(), - ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), - ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), - ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(), + ModItem::Use(it) => tree[it.index()].ast_id().upcast(), + ModItem::ExternCrate(it) => tree[it.index()].ast_id().upcast(), + ModItem::ExternBlock(it) => tree[it.index()].ast_id().upcast(), + ModItem::Function(it) => tree[it.index()].ast_id().upcast(), + ModItem::Struct(it) => tree[it.index()].ast_id().upcast(), + ModItem::Union(it) => tree[it.index()].ast_id().upcast(), + ModItem::Enum(it) => tree[it.index()].ast_id().upcast(), + ModItem::Const(it) => tree[it.index()].ast_id().upcast(), + ModItem::Static(it) => tree[it.index()].ast_id().upcast(), + ModItem::Trait(it) => tree[it.index()].ast_id().upcast(), + ModItem::TraitAlias(it) => tree[it.index()].ast_id().upcast(), + ModItem::Impl(it) => tree[it.index()].ast_id().upcast(), + ModItem::TypeAlias(it) => tree[it.index()].ast_id().upcast(), + ModItem::Mod(it) => tree[it.index()].ast_id().upcast(), + ModItem::MacroCall(it) => tree[it.index()].ast_id().upcast(), + ModItem::MacroRules(it) => tree[it.index()].ast_id().upcast(), + ModItem::MacroDef(it) => tree[it.index()].ast_id().upcast(), } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index e4702c113b850..6807326be5aef 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -13,7 +13,7 @@ use crate::{ use super::*; fn id(index: Idx) -> FileItemTreeId { - FileItemTreeId { index, _p: PhantomData } + FileItemTreeId(index) } pub(super) struct Ctx<'a> { @@ -295,8 +295,12 @@ impl<'a> Ctx<'a> { } } }; - let ty = Interned::new(self_type); - let idx = self.data().params.alloc(Param::Normal(ty)); + let type_ref = Interned::new(self_type); + let ast_id = self.source_ast_id_map.ast_id(&self_param); + let idx = self.data().params.alloc(Param { + type_ref: Some(type_ref), + ast_id: ParamAstId::SelfParam(ast_id), + }); self.add_attrs( idx.into(), RawAttrs::new(self.db.upcast(), &self_param, self.hygiene()), @@ -305,11 +309,19 @@ impl<'a> Ctx<'a> { } for param in param_list.params() { let idx = match param.dotdotdot_token() { - Some(_) => self.data().params.alloc(Param::Varargs), + Some(_) => { + let ast_id = self.source_ast_id_map.ast_id(¶m); + self.data() + .params + .alloc(Param { type_ref: None, ast_id: ParamAstId::Param(ast_id) }) + } None => { let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); let ty = Interned::new(type_ref); - self.data().params.alloc(Param::Normal(ty)) + let ast_id = self.source_ast_id_map.ast_id(¶m); + self.data() + .params + .alloc(Param { type_ref: Some(ty), ast_id: ParamAstId::Param(ast_id) }) } }; self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), ¶m, self.hygiene())); @@ -384,14 +396,7 @@ impl<'a> Ctx<'a> { let bounds = self.lower_type_bounds(type_alias); let generic_params = self.lower_generic_params(HasImplicitSelf::No, type_alias); let ast_id = self.source_ast_id_map.ast_id(type_alias); - let res = TypeAlias { - name, - visibility, - bounds: bounds.into_boxed_slice(), - generic_params, - type_ref, - ast_id, - }; + let res = TypeAlias { name, visibility, bounds, generic_params, type_ref, ast_id }; Some(id(self.data().type_aliases.alloc(res))) } @@ -487,6 +492,7 @@ impl<'a> Ctx<'a> { let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr)); let self_ty = self.lower_type_ref(&impl_def.self_ty()?); let is_negative = impl_def.excl_token().is_some(); + let is_unsafe = impl_def.unsafe_token().is_some(); // We cannot use `assoc_items()` here as that does not include macro calls. let items = impl_def @@ -501,7 +507,8 @@ impl<'a> Ctx<'a> { }) .collect(); let ast_id = self.source_ast_id_map.ast_id(impl_def); - let res = Impl { generic_params, target_trait, self_ty, is_negative, items, ast_id }; + let res = + Impl { generic_params, target_trait, self_ty, is_negative, is_unsafe, items, ast_id }; Some(id(self.data().impls.alloc(res))) } @@ -625,13 +632,13 @@ impl<'a> Ctx<'a> { Interned::new(generics) } - fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Vec> { + fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Box<[Interned]> { match node.type_bound_list() { Some(bound_list) => bound_list .bounds() .map(|it| Interned::new(TypeBound::from_ast(&self.body_ctx, it))) .collect(), - None => Vec::new(), + None => Box::default(), } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs index 417bd37c8a9b0..ca3785bf28dfa 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs @@ -261,15 +261,15 @@ impl Printer<'_> { self.indented(|this| { for param in params.clone() { this.print_attrs_of(param, "\n"); - match &this.tree[param] { - Param::Normal(ty) => { + match &this.tree[param].type_ref { + Some(ty) => { if flags.contains(FnFlags::HAS_SELF_PARAM) { w!(this, "self: "); } this.print_type_ref(ty); wln!(this, ","); } - Param::Varargs => { + None => { wln!(this, "..."); } }; @@ -388,8 +388,18 @@ impl Printer<'_> { wln!(self); } ModItem::Impl(it) => { - let Impl { target_trait, self_ty, is_negative, items, generic_params, ast_id: _ } = - &self.tree[it]; + let Impl { + target_trait, + self_ty, + is_negative, + is_unsafe, + items, + generic_params, + ast_id: _, + } = &self.tree[it]; + if *is_unsafe { + w!(self, "unsafe"); + } w!(self, "impl"); self.print_generic_params(generic_params); w!(self, " "); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 3f87fe62b83cd..fd8f64d6705b0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -8,6 +8,7 @@ //! actually true. #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #[allow(unused)] macro_rules! eprintln { @@ -48,7 +49,7 @@ pub mod visibility; pub mod find_path; pub mod import_map; -pub use rustc_abi as layout; +pub use rustc_dependencies::abi as layout; use triomphe::Arc; #[cfg(test)] @@ -72,6 +73,7 @@ use hir_expand::{ db::ExpandDatabase, eager::expand_eager_macro_input, hygiene::Hygiene, + name::Name, proc_macro::ProcMacroExpander, AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, UnresolvedMacro, @@ -150,7 +152,7 @@ impl TryFrom for CrateRootModuleId { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ModuleId { krate: CrateId, /// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the @@ -173,6 +175,18 @@ impl ModuleId { self.krate } + pub fn name(self, db: &dyn db::DefDatabase) -> Option { + let def_map = self.def_map(db); + let parent = def_map[self.local_id].parent?; + def_map[parent].children.iter().find_map(|(name, module_id)| { + if *module_id == self.local_id { + Some(name.clone()) + } else { + None + } + }) + } + pub fn containing_module(self, db: &dyn db::DefDatabase) -> Option { self.def_map(db).containing_module(self.local_id) } @@ -498,10 +512,7 @@ impl_from!(Macro2Id, MacroRulesId, ProcMacroId for MacroId); impl MacroId { pub fn is_attribute(self, db: &dyn db::DefDatabase) -> bool { - match self { - MacroId::ProcMacroId(it) => it.lookup(db).kind == ProcMacroKind::Attr, - _ => false, - } + matches!(self, MacroId::ProcMacroId(it) if it.lookup(db).kind == ProcMacroKind::Attr) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index 4aedb22c6bc9a..106ead83fad76 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -17,7 +17,7 @@ fn main() { column!(); } #[rustc_builtin_macro] macro_rules! column {() => {}} -fn main() { 0 as u32; } +fn main() { 0u32; } "#]], ); } @@ -74,7 +74,7 @@ fn main() { line!() } #[rustc_builtin_macro] macro_rules! line {() => {}} -fn main() { 0 as u32 } +fn main() { 0u32 } "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index b416f45ff208e..2886b2a366c04 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -970,3 +970,37 @@ builtin #format_args ("{}", &[0 2]); "##]], ); } + +#[test] +fn eager_concat_line() { + check( + r#" +#[rustc_builtin_macro] +#[macro_export] +macro_rules! concat {} + +#[rustc_builtin_macro] +#[macro_export] +macro_rules! line {} + +fn main() { + concat!("event ", line!()); +} + +"#, + expect![[r##" +#[rustc_builtin_macro] +#[macro_export] +macro_rules! concat {} + +#[rustc_builtin_macro] +#[macro_export] +macro_rules! line {} + +fn main() { + "event 0u32"; +} + +"##]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs index 460a908b6db2c..4c1b8f306c50f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs @@ -183,15 +183,6 @@ impl DefMap { shadow: BuiltinShadowMode, expected_macro_subns: Option, ) -> ResolvePathResult { - let graph = db.crate_graph(); - let _cx = stdx::panic_context::enter(format!( - "DefMap {:?} crate_name={:?} block={:?} path={}", - self.krate, - graph[self.krate].display_name, - self.block, - path.display(db.upcast()) - )); - let mut segments = path.segments().iter().enumerate(); let mut curr_per_ns = match path.kind { PathKind::DollarCrate(krate) => { diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml index 1f27204c1917b..361bbec4318f3 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml @@ -13,11 +13,11 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" -tracing = "0.1.35" -either = "1.7.0" +tracing.workspace = true +either.workspace = true rustc-hash = "1.1.0" la-arena.workspace = true -itertools = "0.10.5" +itertools.workspace = true hashbrown.workspace = true smallvec.workspace = true triomphe.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs b/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs index 1906ed15baecc..40726505491b6 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs @@ -99,7 +99,7 @@ register_ast_id_node! { TraitAlias, TypeAlias, Use, - AssocItem, BlockExpr, Variant, RecordField, TupleField, ConstArg + AssocItem, BlockExpr, Variant, RecordField, TupleField, ConstArg, Param, SelfParam } /// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back. diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index 30b19b6e51b8b..a04de10b899cf 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -78,7 +78,7 @@ pub fn find_builtin_macro( register_builtin! { LAZY: - (column, Column) => column_expand, + (column, Column) => line_expand, (file, File) => file_expand, (line, Line) => line_expand, (module_path, ModulePath) => module_path_expand, @@ -127,11 +127,13 @@ fn line_expand( _tt: &tt::Subtree, ) -> ExpandResult { // dummy implementation for type-checking purposes - let expanded = quote! { - 0 as u32 - }; - - ExpandResult::ok(expanded) + ExpandResult::ok(tt::Subtree { + delimiter: tt::Delimiter::unspecified(), + token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + text: "0u32".into(), + span: tt::Span::UNSPECIFIED, + }))], + }) } fn log_syntax_expand( @@ -164,19 +166,6 @@ fn stringify_expand( ExpandResult::ok(expanded) } -fn column_expand( - _db: &dyn ExpandDatabase, - _id: MacroCallId, - _tt: &tt::Subtree, -) -> ExpandResult { - // dummy implementation for type-checking purposes - let expanded = quote! { - 0 as u32 - }; - - ExpandResult::ok(expanded) -} - fn assert_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 5292a5fa1b161..ff0d279d8cce1 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -614,9 +614,12 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult bool; fn contains_unknown(&self) -> bool; fn is_ty_var(&self) -> bool; + fn is_union(&self) -> bool; fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>; fn as_builtin(&self) -> Option; @@ -96,6 +97,10 @@ impl TyExt for Ty { matches!(self.kind(Interner), TyKind::InferenceVar(_, _)) } + fn is_union(&self) -> bool { + matches!(self.adt_id(Interner), Some(AdtId(hir_def::AdtId::UnionId(_)))) + } + fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> { match self.kind(Interner) { TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 7ad3659a4f6db..b395e7f4a8135 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -1159,6 +1159,20 @@ fn pattern_matching_slice() { "#, 33213, ); + check_number( + r#" + //- minicore: slice, index, coerce_unsized, copy + const fn f(mut slice: &[u32]) -> usize { + slice = match slice { + [0, rest @ ..] | rest => rest, + }; + slice.len() + } + const GOAL: usize = f(&[]) + f(&[10]) + f(&[0, 100]) + + f(&[1000, 1000, 1000]) + f(&[0, 57, 34, 46, 10000, 10000]); + "#, + 10, + ); } #[test] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 9c96b5ab8dbb6..410bcbf0356f0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -20,8 +20,8 @@ use crate::{ method_resolution::{InherentImpls, TraitImpls, TyFingerprint}, mir::{BorrowckResult, MirBody, MirLowerError}, Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, InferenceResult, - Interner, PolyFnSig, QuantifiedWhereClause, ReturnTypeImplTraits, Substitution, TraitRef, Ty, - TyDefId, ValueTyDefId, + Interner, PolyFnSig, QuantifiedWhereClause, ReturnTypeImplTraits, Substitution, + TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, }; use hir_expand::name::Name; @@ -47,7 +47,7 @@ pub trait HirDatabase: DefDatabase + Upcast { &self, def: DefWithBodyId, subst: Substitution, - env: Arc, + env: Arc, ) -> Result, MirLowerError>; #[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)] @@ -55,7 +55,7 @@ pub trait HirDatabase: DefDatabase + Upcast { &self, def: ClosureId, subst: Substitution, - env: Arc, + env: Arc, ) -> Result, MirLowerError>; #[salsa::invoke(crate::mir::borrowck_query)] @@ -81,7 +81,7 @@ pub trait HirDatabase: DefDatabase + Upcast { &self, def: GeneralConstId, subst: Substitution, - trait_env: Option>, + trait_env: Option>, ) -> Result; #[salsa::invoke(crate::consteval::const_eval_static_query)] @@ -104,16 +104,12 @@ pub trait HirDatabase: DefDatabase + Upcast { &self, def: AdtId, subst: Substitution, - env: Arc, + env: Arc, ) -> Result, LayoutError>; #[salsa::invoke(crate::layout::layout_of_ty_query)] #[salsa::cycle(crate::layout::layout_of_ty_recover)] - fn layout_of_ty( - &self, - ty: Ty, - env: Arc, - ) -> Result, LayoutError>; + fn layout_of_ty(&self, ty: Ty, env: Arc) -> Result, LayoutError>; #[salsa::invoke(crate::layout::target_data_layout_query)] fn target_data_layout(&self, krate: CrateId) -> Option>; @@ -121,7 +117,7 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::method_resolution::lookup_impl_method_query)] fn lookup_impl_method( &self, - env: Arc, + env: Arc, func: FunctionId, fn_subst: Substitution, ) -> (FunctionId, Substitution); @@ -149,10 +145,10 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::lower::trait_environment_for_body_query)] #[salsa::transparent] - fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc; + fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc; #[salsa::invoke(crate::lower::trait_environment_query)] - fn trait_environment(&self, def: GenericDefId) -> Arc; + fn trait_environment(&self, def: GenericDefId) -> Arc; #[salsa::invoke(crate::lower::generic_defaults_query)] #[salsa::cycle(crate::lower::generic_defaults_recover)] @@ -249,7 +245,7 @@ pub trait HirDatabase: DefDatabase + Upcast { fn normalize_projection( &self, projection: crate::ProjectionTy, - env: Arc, + env: Arc, ) -> Ty; #[salsa::invoke(trait_solve_wait)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs index ef43ed5c463fc..c1b3619009bd4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs @@ -11,9 +11,3 @@ pub use crate::diagnostics::{ }, unsafe_check::{missing_unsafe, unsafe_expressions, UnsafeExpr}, }; - -#[derive(Debug, PartialEq, Eq)] -pub struct IncoherentImpl { - pub file_id: hir_expand::HirFileId, - pub impl_: syntax::AstPtr, -} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 36d69edf9d5d9..f4c079b48c58c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -9,6 +9,7 @@ //! - constants (e.g. `const FOO: u8 = 10;`) //! - static items (e.g. `static FOO: u8 = 10;`) //! - match arm bindings (e.g. `foo @ Some(_)`) +//! - modules (e.g. `mod foo { ... }` or `mod foo;`) mod case_conv; @@ -18,8 +19,8 @@ use hir_def::{ data::adt::VariantData, hir::{Pat, PatId}, src::HasSource, - AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ItemContainerId, - Lookup, ModuleDefId, StaticId, StructId, + AdtId, AttrDefId, ConstId, EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, ModuleId, + StaticId, StructId, }; use hir_expand::{ name::{AsName, Name}, @@ -83,6 +84,7 @@ pub enum IdentType { Structure, Variable, Variant, + Module, } impl fmt::Display for IdentType { @@ -97,6 +99,7 @@ impl fmt::Display for IdentType { IdentType::Structure => "Structure", IdentType::Variable => "Variable", IdentType::Variant => "Variant", + IdentType::Module => "Module", }; repr.fmt(f) @@ -132,6 +135,7 @@ impl<'a> DeclValidator<'a> { pub(super) fn validate_item(&mut self, item: ModuleDefId) { match item { + ModuleDefId::ModuleId(module_id) => self.validate_module(module_id), ModuleDefId::FunctionId(func) => self.validate_func(func), ModuleDefId::AdtId(adt) => self.validate_adt(adt), ModuleDefId::ConstId(const_id) => self.validate_const(const_id), @@ -230,6 +234,55 @@ impl<'a> DeclValidator<'a> { || parent() } + fn validate_module(&mut self, module_id: ModuleId) { + // Check whether non-snake case identifiers are allowed for this module. + if self.allowed(module_id.into(), allow::NON_SNAKE_CASE, false) { + return; + } + + // Check the module name. + let Some(module_name) = module_id.name(self.db.upcast()) else { return }; + let module_name_replacement = + module_name.as_str().and_then(to_lower_snake_case).map(|new_name| Replacement { + current_name: module_name, + suggested_text: new_name, + expected_case: CaseType::LowerSnakeCase, + }); + + if let Some(module_name_replacement) = module_name_replacement { + let module_data = &module_id.def_map(self.db.upcast())[module_id.local_id]; + let module_src = module_data.declaration_source(self.db.upcast()); + + if let Some(module_src) = module_src { + let ast_ptr = match module_src.value.name() { + Some(name) => name, + None => { + never!( + "Replacement ({:?}) was generated for a module without a name: {:?}", + module_name_replacement, + module_src + ); + return; + } + }; + + let diagnostic = IncorrectCase { + file: module_src.file_id, + ident_type: IdentType::Module, + ident: AstPtr::new(&ast_ptr), + expected_case: module_name_replacement.expected_case, + ident_text: module_name_replacement + .current_name + .display(self.db.upcast()) + .to_string(), + suggested_text: module_name_replacement.suggested_text, + }; + + self.sink.push(diagnostic); + } + } + } + fn validate_func(&mut self, func: FunctionId) { let data = self.db.function_data(func); if matches!(func.lookup(self.db.upcast()).container, ItemContainerId::ExternBlockId(_)) { @@ -237,8 +290,6 @@ impl<'a> DeclValidator<'a> { return; } - self.validate_body_inner_items(func.into()); - // Check whether non-snake case identifiers are allowed for this function. if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) { return; @@ -336,48 +387,44 @@ impl<'a> DeclValidator<'a> { for (id, replacement) in pats_replacements { if let Ok(source_ptr) = source_map.pat_syntax(id) { - if let Some(expr) = source_ptr.value.as_ref().left() { + if let Some(ptr) = source_ptr.value.clone().cast::() { let root = source_ptr.file_syntax(self.db.upcast()); - if let ast::Pat::IdentPat(ident_pat) = expr.to_node(&root) { - let parent = match ident_pat.syntax().parent() { - Some(parent) => parent, - None => continue, - }; - let name_ast = match ident_pat.name() { - Some(name_ast) => name_ast, - None => continue, - }; + let ident_pat = ptr.to_node(&root); + let parent = match ident_pat.syntax().parent() { + Some(parent) => parent, + None => continue, + }; + let name_ast = match ident_pat.name() { + Some(name_ast) => name_ast, + None => continue, + }; + + let is_param = ast::Param::can_cast(parent.kind()); + + // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement, + // because e.g. match arms are patterns as well. + // In other words, we check that it's a named variable binding. + let is_binding = ast::LetStmt::can_cast(parent.kind()) + || (ast::MatchArm::can_cast(parent.kind()) + && ident_pat.at_token().is_some()); + if !(is_param || is_binding) { + // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm. + continue; + } - let is_param = ast::Param::can_cast(parent.kind()); - - // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement, - // because e.g. match arms are patterns as well. - // In other words, we check that it's a named variable binding. - let is_binding = ast::LetStmt::can_cast(parent.kind()) - || (ast::MatchArm::can_cast(parent.kind()) - && ident_pat.at_token().is_some()); - if !(is_param || is_binding) { - // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm. - continue; - } + let ident_type = + if is_param { IdentType::Parameter } else { IdentType::Variable }; - let ident_type = - if is_param { IdentType::Parameter } else { IdentType::Variable }; - - let diagnostic = IncorrectCase { - file: source_ptr.file_id, - ident_type, - ident: AstPtr::new(&name_ast), - expected_case: replacement.expected_case, - ident_text: replacement - .current_name - .display(self.db.upcast()) - .to_string(), - suggested_text: replacement.suggested_text, - }; + let diagnostic = IncorrectCase { + file: source_ptr.file_id, + ident_type, + ident: AstPtr::new(&name_ast), + expected_case: replacement.expected_case, + ident_text: replacement.current_name.display(self.db.upcast()).to_string(), + suggested_text: replacement.suggested_text, + }; - self.sink.push(diagnostic); - } + self.sink.push(diagnostic); } } } @@ -519,11 +566,6 @@ impl<'a> DeclValidator<'a> { fn validate_enum(&mut self, enum_id: EnumId) { let data = self.db.enum_data(enum_id); - for (local_id, _) in data.variants.iter() { - let variant_id = EnumVariantId { parent: enum_id, local_id }; - self.validate_body_inner_items(variant_id.into()); - } - // Check whether non-camel case names are allowed for this enum. if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) { return; @@ -648,8 +690,6 @@ impl<'a> DeclValidator<'a> { fn validate_const(&mut self, const_id: ConstId) { let data = self.db.const_data(const_id); - self.validate_body_inner_items(const_id.into()); - if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) { return; } @@ -698,8 +738,6 @@ impl<'a> DeclValidator<'a> { return; } - self.validate_body_inner_items(static_id.into()); - if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) { return; } @@ -737,17 +775,4 @@ impl<'a> DeclValidator<'a> { self.sink.push(diagnostic); } - - // FIXME: We don't currently validate names within `DefWithBodyId::InTypeConstId`. - /// Recursively validates inner scope items, such as static variables and constants. - fn validate_body_inner_items(&mut self, body_id: DefWithBodyId) { - let body = self.db.body(body_id); - for (_, block_def_map) in body.blocks(self.db.upcast()) { - for (_, module) in block_def_map.modules() { - for def_id in module.scope.declarations() { - self.validate_item(def_id); - } - } - } - } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs index 2c13689620924..cbe1af1570375 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs @@ -11,50 +11,7 @@ pub(crate) fn to_camel_case(ident: &str) -> Option { return None; } - // Taken from rustc. - let ret = ident - .trim_matches('_') - .split('_') - .filter(|component| !component.is_empty()) - .map(|component| { - let mut camel_cased_component = String::with_capacity(component.len()); - - let mut new_word = true; - let mut prev_is_lower_case = true; - - for c in component.chars() { - // Preserve the case if an uppercase letter follows a lowercase letter, so that - // `camelCase` is converted to `CamelCase`. - if prev_is_lower_case && c.is_uppercase() { - new_word = true; - } - - if new_word { - camel_cased_component.extend(c.to_uppercase()); - } else { - camel_cased_component.extend(c.to_lowercase()); - } - - prev_is_lower_case = c.is_lowercase(); - new_word = false; - } - - camel_cased_component - }) - .fold((String::new(), None), |(acc, prev): (_, Option), next| { - // separate two components with an underscore if their boundary cannot - // be distinguished using an uppercase/lowercase case distinction - let join = prev - .and_then(|prev| { - let f = next.chars().next()?; - let l = prev.chars().last()?; - Some(!char_has_case(l) && !char_has_case(f)) - }) - .unwrap_or(false); - (acc + if join { "_" } else { "" } + &next, Some(next)) - }) - .0; - Some(ret) + Some(stdx::to_camel_case(ident)) } /// Converts an identifier to a lower_snake_case form. @@ -97,7 +54,9 @@ fn is_camel_case(name: &str) -> bool { && !name.chars().any(|snd| { let ret = match fst { None => false, - Some(fst) => char_has_case(fst) && snd == '_' || char_has_case(snd) && fst == '_', + Some(fst) => { + stdx::char_has_case(fst) && snd == '_' || stdx::char_has_case(snd) && fst == '_' + } }; fst = Some(snd); @@ -135,11 +94,6 @@ fn is_snake_case bool>(ident: &str, wrong_case: F) -> bool { }) } -// Taken from rustc. -fn char_has_case(c: char) -> bool { - c.is_lowercase() || c.is_uppercase() -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs index f8cdeaa5e3549..2e04bbfee83b7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs @@ -147,7 +147,7 @@ impl<'a> PatCtxt<'a> { } hir_def::hir::Pat::Bind { id, subpat, .. } => { - let bm = self.infer.binding_modes[id]; + let bm = self.infer.binding_modes[pat]; ty = &self.infer[id]; let name = &self.body.bindings[id].name; match (bm, ty.kind(Interner)) { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index f6d6b00d740a7..9ccf467358ece 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -945,6 +945,7 @@ impl HirDisplay for Ty { ItemInNs::Types((*def_id).into()), module_id, false, + true, ) { write!(f, "{}", path.display(f.db.upcast()))?; } else { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 78d3c667a1f8d..8262edec22c1e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -420,7 +420,19 @@ pub struct InferenceResult { standard_types: InternedStandardTypes, /// Stores the types which were implicitly dereferenced in pattern binding modes. pub pat_adjustments: FxHashMap>, - pub binding_modes: ArenaMap, + /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings. + /// + /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an + /// or pattern can have multiple binding modes. For example: + /// ``` + /// fn foo(mut slice: &[u32]) -> usize { + /// slice = match slice { + /// [0, rest @ ..] | rest => rest, + /// }; + /// } + /// ``` + /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`. + pub binding_modes: ArenaMap, pub expr_adjustments: FxHashMap>, pub(crate) closure_info: FxHashMap, FnTrait)>, // FIXME: remove this field @@ -1140,20 +1152,15 @@ impl<'a> InferenceContext<'a> { (ty, variant) } TypeNs::TypeAliasId(it) => { - let container = it.lookup(self.db.upcast()).container; - let parent_subst = match container { - ItemContainerId::TraitId(id) => { - let subst = TyBuilder::subst_for_def(self.db, id, None) - .fill_with_inference_vars(&mut self.table) - .build(); - Some(subst) - } - // Type aliases do not exist in impls. - _ => None, + let resolved_seg = match unresolved { + None => path.segments().last().unwrap(), + Some(n) => path.segments().get(path.segments().len() - n - 1).unwrap(), }; - let ty = TyBuilder::def_ty(self.db, it.into(), parent_subst) - .fill_with_inference_vars(&mut self.table) - .build(); + let substs = + ctx.substs_from_path_segment(resolved_seg, Some(it.into()), true, None); + let ty = self.db.ty(it.into()); + let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); + self.resolve_variant_on_alias(ty, unresolved, mod_path) } TypeNs::AdtSelfType(_) => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 13d6b5643ac4a..af74df1032cb8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -679,7 +679,7 @@ impl InferenceContext<'_> { | Pat::Range { .. } => { update_result(CaptureKind::ByRef(BorrowKind::Shared)); } - Pat::Bind { id, .. } => match self.result.binding_modes[*id] { + Pat::Bind { id, .. } => match self.result.binding_modes[p] { crate::BindingMode::Move => { if self.is_ty_copy(self.result.type_of_binding[*id].clone()) { update_result(CaptureKind::ByRef(BorrowKind::Shared)); @@ -735,6 +735,32 @@ impl InferenceContext<'_> { self.walk_expr(expr); } + fn restrict_precision_for_unsafe(&mut self) { + for capture in &mut self.current_captures { + let mut ty = self.table.resolve_completely(self.result[capture.place.local].clone()); + if ty.as_raw_ptr().is_some() || ty.is_union() { + capture.kind = CaptureKind::ByRef(BorrowKind::Shared); + capture.place.projections.truncate(0); + continue; + } + for (i, p) in capture.place.projections.iter().enumerate() { + ty = p.projected_ty( + ty, + self.db, + |_, _, _| { + unreachable!("Closure field only happens in MIR"); + }, + self.owner.module(self.db.upcast()).krate(), + ); + if ty.as_raw_ptr().is_some() || ty.is_union() { + capture.kind = CaptureKind::ByRef(BorrowKind::Shared); + capture.place.projections.truncate(i + 1); + break; + } + } + } + } + fn adjust_for_move_closure(&mut self) { for capture in &mut self.current_captures { if let Some(first_deref) = @@ -838,8 +864,8 @@ impl InferenceContext<'_> { | Pat::ConstBlock(_) | Pat::Path(_) | Pat::Lit(_) => self.consume_place(place, pat.into()), - Pat::Bind { id, subpat: _ } => { - let mode = self.result.binding_modes[*id]; + Pat::Bind { id: _, subpat: _ } => { + let mode = self.result.binding_modes[pat]; let capture_kind = match mode { BindingMode::Move => { self.consume_place(place, pat.into()); @@ -924,6 +950,7 @@ impl InferenceContext<'_> { self.result.mutated_bindings_in_closure.insert(item.place.local); } } + self.restrict_precision_for_unsafe(); // closure_kind should be done before adjust_for_move_closure let closure_kind = self.closure_kind(); match capture_by { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs index 4e28ec06023ed..7ff12e5b7f851 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs @@ -421,7 +421,7 @@ impl InferenceContext<'_> { } else { BindingMode::convert(mode) }; - self.result.binding_modes.insert(binding, mode); + self.result.binding_modes.insert(pat, mode); let inner_ty = match subpat { Some(subpat) => self.infer_pat(subpat, &expected, default_bm), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 0a68a9f3b5831..ac39bdf5bf53c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -43,7 +43,7 @@ where } impl> Canonicalized { - pub(super) fn apply_solution( + pub(crate) fn apply_solution( &self, ctx: &mut InferenceTable<'_>, solution: Canonical, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 1a6106c0244c6..27c7949986878 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -1,5 +1,7 @@ //! Compute the binary representation of a type +use std::fmt; + use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy}; use hir_def::{ layout::{ @@ -9,6 +11,10 @@ use hir_def::{ LocalEnumVariantId, LocalFieldId, StructId, }; use la_arena::{Idx, RawIdx}; +use rustc_dependencies::{ + abi::AddressSpace, + index::{IndexSlice, IndexVec}, +}; use stdx::never; use triomphe::Arc; @@ -22,19 +28,13 @@ pub use self::{ target::target_data_layout_query, }; -macro_rules! user_error { - ($it: expr) => { - return Err(LayoutError::UserError(format!($it).into())) - }; -} - mod adt; mod target; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RustcEnumVariantIdx(pub LocalEnumVariantId); -impl rustc_index::vec::Idx for RustcEnumVariantIdx { +impl rustc_dependencies::index::Idx for RustcEnumVariantIdx { fn new(idx: usize) -> Self { RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32))) } @@ -44,19 +44,63 @@ impl rustc_index::vec::Idx for RustcEnumVariantIdx { } } -pub type Layout = LayoutS; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct RustcFieldIdx(pub LocalFieldId); + +impl RustcFieldIdx { + pub fn new(idx: usize) -> Self { + RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32))) + } +} + +impl rustc_dependencies::index::Idx for RustcFieldIdx { + fn new(idx: usize) -> Self { + RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32))) + } + + fn index(self) -> usize { + u32::from(self.0.into_raw()) as usize + } +} + +pub type Layout = LayoutS; pub type TagEncoding = hir_def::layout::TagEncoding; -pub type Variants = hir_def::layout::Variants; +pub type Variants = hir_def::layout::Variants; #[derive(Debug, PartialEq, Eq, Clone)] pub enum LayoutError { - UserError(Box), - SizeOverflow, - TargetLayoutNotAvailable, - HasPlaceholder, + HasErrorConst, HasErrorType, + HasPlaceholder, + InvalidSimdType, NotImplemented, + RecursiveTypeWithoutIndirection, + SizeOverflow, + TargetLayoutNotAvailable, Unknown, + UserReprTooSmall, +} + +impl std::error::Error for LayoutError {} +impl fmt::Display for LayoutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + LayoutError::HasErrorConst => write!(f, "type contains an unevaluatable const"), + LayoutError::HasErrorType => write!(f, "type contains an error"), + LayoutError::HasPlaceholder => write!(f, "type contains placeholders"), + LayoutError::InvalidSimdType => write!(f, "invalid simd type definition"), + LayoutError::NotImplemented => write!(f, "not implemented"), + LayoutError::RecursiveTypeWithoutIndirection => { + write!(f, "recursive type without indirection") + } + LayoutError::SizeOverflow => write!(f, "size overflow"), + LayoutError::TargetLayoutNotAvailable => write!(f, "target layout not available"), + LayoutError::Unknown => write!(f, "unknown"), + LayoutError::UserReprTooSmall => { + write!(f, "the `#[repr]` hint is too small to hold the discriminants of the enum") + } + } + } } struct LayoutCx<'a> { @@ -66,7 +110,7 @@ struct LayoutCx<'a> { impl<'a> LayoutCalculator for LayoutCx<'a> { type TargetDataLayoutRef = &'a TargetDataLayout; - fn delay_bug(&self, txt: &str) { + fn delayed_bug(&self, txt: String) { never!("{}", txt); } @@ -95,9 +139,7 @@ fn layout_of_simd_ty( let f0_ty = match fields.iter().next() { Some(it) => it.1.clone().substitute(Interner, subst), - None => { - user_error!("simd type with zero fields"); - } + None => return Err(LayoutError::InvalidSimdType), }; // The element type and number of elements of the SIMD vector @@ -111,7 +153,7 @@ fn layout_of_simd_ty( // Extract the number of elements from the layout of the array field: let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields else { - user_error!("Array with non array layout"); + return Err(LayoutError::Unknown); }; (e_ty.clone(), count, true) @@ -123,7 +165,7 @@ fn layout_of_simd_ty( // Compute the ABI of the element type: let e_ly = db.layout_of_ty(e_ty, env.clone())?; let Abi::Scalar(e_abi) = e_ly.abi else { - user_error!("simd type with inner non scalar type"); + return Err(LayoutError::Unknown); }; // Compute the size and alignment of the vector: @@ -145,6 +187,8 @@ fn layout_of_simd_ty( largest_niche: e_ly.largest_niche, size, align, + max_repr_align: None, + unadjusted_abi_align: align.abi, })) } @@ -230,13 +274,11 @@ pub fn layout_of_ty_query( .map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone())) .collect::, _>>()?; let fields = fields.iter().map(|it| &**it).collect::>(); - let fields = fields.iter().collect::>(); + let fields = fields.iter().collect::>(); cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)? } TyKind::Array(element, count) => { - let count = try_const_usize(db, &count).ok_or(LayoutError::UserError(Box::from( - "unevaluated or mistyped const generic parameter", - )))? as u64; + let count = try_const_usize(db, &count).ok_or(LayoutError::HasErrorConst)? as u64; let element = db.layout_of_ty(element.clone(), trait_env.clone())?; let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?; @@ -255,6 +297,8 @@ pub fn layout_of_ty_query( largest_niche, align: element.align, size, + max_repr_align: None, + unadjusted_abi_align: element.align.abi, } } TyKind::Slice(element) => { @@ -266,11 +310,23 @@ pub fn layout_of_ty_query( largest_niche: None, align: element.align, size: Size::ZERO, + max_repr_align: None, + unadjusted_abi_align: element.align.abi, } } + TyKind::Str => Layout { + variants: Variants::Single { index: struct_variant_idx() }, + fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, + abi: Abi::Aggregate { sized: false }, + largest_niche: None, + align: dl.i8_align, + size: Size::ZERO, + max_repr_align: None, + unadjusted_abi_align: dl.i8_align.abi, + }, // Potentially-wide pointers. TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => { - let mut data_ptr = scalar_unit(dl, Primitive::Pointer); + let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA)); if matches!(ty.kind(Interner), TyKind::Ref(..)) { data_ptr.valid_range_mut().start = 1; } @@ -294,7 +350,7 @@ pub fn layout_of_ty_query( scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false)) } TyKind::Dyn(..) => { - let mut vtable = scalar_unit(dl, Primitive::Pointer); + let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA)); vtable.valid_range_mut().start = 1; vtable } @@ -308,32 +364,17 @@ pub fn layout_of_ty_query( cx.scalar_pair(data_ptr, metadata) } TyKind::FnDef(_, _) => layout_of_unit(&cx, dl)?, - TyKind::Str => Layout { - variants: Variants::Single { index: struct_variant_idx() }, - fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, - abi: Abi::Aggregate { sized: false }, - largest_niche: None, - align: dl.i8_align, - size: Size::ZERO, - }, - TyKind::Never => Layout { - variants: Variants::Single { index: struct_variant_idx() }, - fields: FieldsShape::Primitive, - abi: Abi::Uninhabited, - largest_niche: None, - align: dl.i8_align, - size: Size::ZERO, - }, + TyKind::Never => cx.layout_of_never_type(), TyKind::Dyn(_) | TyKind::Foreign(_) => { let mut unit = layout_of_unit(&cx, dl)?; match unit.abi { Abi::Aggregate { ref mut sized } => *sized = false, - _ => user_error!("bug"), + _ => return Err(LayoutError::Unknown), } unit } TyKind::Function(_) => { - let mut ptr = scalar_unit(dl, Primitive::Pointer); + let mut ptr = scalar_unit(dl, Primitive::Pointer(dl.instruction_address_space)); ptr.valid_range_mut().start = 1; Layout::scalar(dl, ptr) } @@ -363,7 +404,7 @@ pub fn layout_of_ty_query( }) .collect::, _>>()?; let fields = fields.iter().map(|it| &**it).collect::>(); - let fields = fields.iter().collect::>(); + let fields = fields.iter().collect::>(); cx.univariant(dl, &fields, &ReprOptions::default(), StructKind::AlwaysSized) .ok_or(LayoutError::Unknown)? } @@ -394,13 +435,13 @@ pub fn layout_of_ty_recover( _: &Ty, _: &Arc, ) -> Result, LayoutError> { - user_error!("infinite sized recursive type"); + Err(LayoutError::RecursiveTypeWithoutIndirection) } fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result { - cx.univariant::( + cx.univariant::( dl, - &[], + IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized, ) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index 85ef649b89593..58a06dc643542 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -8,6 +8,7 @@ use hir_def::{ AdtId, EnumVariantId, LocalEnumVariantId, VariantId, }; use la_arena::RawIdx; +use rustc_dependencies::index::IndexVec; use smallvec::SmallVec; use triomphe::Arc; @@ -20,8 +21,8 @@ use crate::{ use super::LayoutCx; -pub(crate) fn struct_variant_idx() -> RustcEnumVariantIdx { - RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from(0))) +pub(crate) const fn struct_variant_idx() -> RustcEnumVariantIdx { + RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from_u32(0))) } pub fn layout_of_adt_query( @@ -74,7 +75,7 @@ pub fn layout_of_adt_query( .iter() .map(|it| it.iter().map(|it| &**it).collect::>()) .collect::>(); - let variants = variants.iter().map(|it| it.iter().collect()).collect(); + let variants = variants.iter().map(|it| it.iter().collect()).collect::>(); let result = if matches!(def, AdtId::UnionId(..)) { cx.layout_of_union(&repr, &variants).ok_or(LayoutError::Unknown)? } else { @@ -105,7 +106,7 @@ pub fn layout_of_adt_query( && variants .iter() .next() - .and_then(|it| it.last().map(|it| !it.is_unsized())) + .and_then(|it| it.iter().last().map(|it| !it.is_unsized())) .unwrap_or(true), ) .ok_or(LayoutError::SizeOverflow)? @@ -119,7 +120,15 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound, let attr = attrs.by_key(name).tt_values(); for tree in attr { if let Some(it) = tree.token_trees.first() { - if let Ok(it) = it.to_string().parse() { + let text = it.to_string().replace('_', ""); + let (text, base) = match text.as_bytes() { + [b'0', b'x', ..] => (&text[2..], 16), + [b'0', b'o', ..] => (&text[2..], 8), + [b'0', b'b', ..] => (&text[2..], 2), + _ => (&*text, 10), + }; + + if let Ok(it) = u128::from_str_radix(text, base) { return Bound::Included(it); } } @@ -136,7 +145,7 @@ pub fn layout_of_adt_recover( _: &Substitution, _: &Arc, ) -> Result, LayoutError> { - user_error!("infinite sized recursive type"); + Err(LayoutError::RecursiveTypeWithoutIndirection) } /// Finds the appropriate Integer type and signedness for the given @@ -160,11 +169,7 @@ fn repr_discr( let discr = Integer::from_attr(dl, ity); let fit = if ity.is_signed() { signed_fit } else { unsigned_fit }; if discr < fit { - return Err(LayoutError::UserError( - "Integer::repr_discr: `#[repr]` hint too small for \ - discriminant range of enum " - .into(), - )); + return Err(LayoutError::UserReprTooSmall); } return Ok((discr, ity.is_signed())); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index ffdbb9de934dc..5e3a86c80e3fc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -210,16 +210,13 @@ fn recursive() { struct BoxLike(*mut T); struct Goal(BoxLike); } - check_fail( - r#"struct Goal(Goal);"#, - LayoutError::UserError("infinite sized recursive type".into()), - ); + check_fail(r#"struct Goal(Goal);"#, LayoutError::RecursiveTypeWithoutIndirection); check_fail( r#" struct Foo(Foo); struct Goal(Foo); "#, - LayoutError::UserError("infinite sized recursive type".into()), + LayoutError::RecursiveTypeWithoutIndirection, ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests/closure.rs index bbe855a14de7e..939025461f369 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests/closure.rs @@ -186,9 +186,9 @@ fn capture_specific_fields() { fn match_pattern() { size_and_align_expr! { struct X(i64, i32, (u8, i128)); - let y: X = X(2, 5, (7, 3)); + let _y: X = X(2, 5, (7, 3)); move |x: i64| { - match y { + match _y { _ => x, } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 405bb001b5d1a..bcf7bfa0d2730 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -1,6 +1,7 @@ //! The type system. We currently use this to infer types for completion, hover //! information and various assists. #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #[allow(unused)] macro_rules! eprintln { @@ -80,6 +81,7 @@ pub use mapping::{ lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id, to_placeholder_idx, }; +pub use method_resolution::check_orphan_rules; pub use traits::TraitEnvironment; pub use utils::{all_super_traits, is_fn_unsafe_to_call}; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 9a61f15359932..9f5b59b239a4b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -768,7 +768,7 @@ impl<'a> TyLoweringContext<'a> { } } - fn substs_from_path_segment( + pub(super) fn substs_from_path_segment( &self, segment: PathSegment<'_>, def: Option, @@ -1097,10 +1097,25 @@ impl<'a> TyLoweringContext<'a> { binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), ); if let Some(type_ref) = &binding.type_ref { - let ty = self.lower_ty(type_ref); - let alias_eq = - AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; - predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); + if let (TypeRef::ImplTrait(bounds), ImplTraitLoweringState::Disallowed) = + (type_ref, &self.impl_trait_mode) + { + for bound in bounds { + predicates.extend( + self.lower_type_bound( + bound, + TyKind::Alias(AliasTy::Projection(projection_ty.clone())) + .intern(Interner), + false, + ), + ); + } + } else { + let ty = self.lower_ty(type_ref); + let alias_eq = + AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; + predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq))); + } } for bound in binding.bounds.iter() { predicates.extend(self.lower_type_bound( @@ -1383,51 +1398,50 @@ pub(crate) fn generic_predicates_for_param_query( let ctx = TyLoweringContext::new(db, &resolver, def.into()) .with_type_param_mode(ParamLoweringMode::Variable); let generics = generics(db.upcast(), def); - let mut predicates: Vec<_> = resolver - .where_predicates_in_scope() - // we have to filter out all other predicates *first*, before attempting to lower them - .filter(|pred| match pred { - WherePredicate::ForLifetime { target, bound, .. } - | WherePredicate::TypeBound { target, bound, .. } => { - match target { - WherePredicateTypeTarget::TypeRef(type_ref) => { - if ctx.lower_ty_only_param(type_ref) != Some(param_id) { - return false; - } - } - &WherePredicateTypeTarget::TypeOrConstParam(local_id) => { - let target_id = TypeOrConstParamId { parent: def, local_id }; - if target_id != param_id { - return false; - } - } - }; - match &**bound { - TypeBound::ForLifetime(_, path) | TypeBound::Path(path, _) => { - // Only lower the bound if the trait could possibly define the associated - // type we're looking for. + // we have to filter out all other predicates *first*, before attempting to lower them + let predicate = |pred: &&_| match pred { + WherePredicate::ForLifetime { target, bound, .. } + | WherePredicate::TypeBound { target, bound, .. } => { + let invalid_target = match target { + WherePredicateTypeTarget::TypeRef(type_ref) => { + ctx.lower_ty_only_param(type_ref) != Some(param_id) + } + &WherePredicateTypeTarget::TypeOrConstParam(local_id) => { + let target_id = TypeOrConstParamId { parent: def, local_id }; + target_id != param_id + } + }; + if invalid_target { + return false; + } - let assoc_name = match &assoc_name { - Some(it) => it, - None => return true, - }; - let tr = match resolver.resolve_path_in_type_ns_fully(db.upcast(), path) { - Some(TypeNs::TraitId(tr)) => tr, - _ => return false, - }; + match &**bound { + TypeBound::ForLifetime(_, path) | TypeBound::Path(path, _) => { + // Only lower the bound if the trait could possibly define the associated + // type we're looking for. - all_super_traits(db.upcast(), tr).iter().any(|tr| { - db.trait_data(*tr).items.iter().any(|(name, item)| { - matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name - }) + let Some(assoc_name) = &assoc_name else { return true }; + let Some(TypeNs::TraitId(tr)) = + resolver.resolve_path_in_type_ns_fully(db.upcast(), path) + else { + return false; + }; + + all_super_traits(db.upcast(), tr).iter().any(|tr| { + db.trait_data(*tr).items.iter().any(|(name, item)| { + matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name }) - } - TypeBound::Lifetime(_) | TypeBound::Error => false, + }) } + TypeBound::Lifetime(_) | TypeBound::Error => false, } - WherePredicate::Lifetime { .. } => false, - }) + } + WherePredicate::Lifetime { .. } => false, + }; + let mut predicates: Vec<_> = resolver + .where_predicates_in_scope() + .filter(predicate) .flat_map(|pred| { ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p)) }) @@ -1519,7 +1533,12 @@ pub(crate) fn trait_environment_query( let env = chalk_ir::Environment::new(Interner).add_clauses(Interner, clauses); - Arc::new(TraitEnvironment { krate, block: None, traits_from_clauses: traits_in_scope, env }) + Arc::new(TraitEnvironment { + krate, + block: None, + traits_from_clauses: traits_in_scope.into_boxed_slice(), + env, + }) } /// Resolve the where clause(s) of an item with generics. diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index f3a5f69b2a63c..732643566a2d6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -27,8 +27,9 @@ use crate::{ primitive::{FloatTy, IntTy, UintTy}, static_lifetime, to_chalk_trait_id, utils::all_super_traits, - AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, InEnvironment, - Interner, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, + AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, Goal, Guidance, + InEnvironment, Interner, Scalar, Solution, Substitution, TraitEnvironment, TraitRef, + TraitRefExt, Ty, TyBuilder, TyExt, }; /// This is used as a key for indexing impls. @@ -862,6 +863,62 @@ fn is_inherent_impl_coherent( } } +/// Checks whether the impl satisfies the orphan rules. +/// +/// Given `impl Trait for T0`, an `impl`` is valid only if at least one of the following is true: +/// - Trait is a local trait +/// - All of +/// - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type. +/// - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`) +pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { + let substs = TyBuilder::placeholder_subst(db, impl_); + let Some(impl_trait) = db.impl_trait(impl_) else { + // not a trait impl + return true; + }; + + let local_crate = impl_.lookup(db.upcast()).container.krate(); + let is_local = |tgt_crate| tgt_crate == local_crate; + + let trait_ref = impl_trait.substitute(Interner, &substs); + let trait_id = from_chalk_trait_id(trait_ref.trait_id); + if is_local(trait_id.module(db.upcast()).krate()) { + // trait to be implemented is local + return true; + } + + let unwrap_fundamental = |ty: Ty| match ty.kind(Interner) { + TyKind::Ref(_, _, referenced) => referenced.clone(), + &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => { + let struct_data = db.struct_data(s); + if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) { + let next = subs.type_parameters(Interner).next(); + match next { + Some(ty) => ty, + None => ty, + } + } else { + ty + } + } + _ => ty, + }; + // - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type. + let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| { + match unwrap_fundamental(ty).kind(Interner) { + &TyKind::Adt(AdtId(id), _) => is_local(id.module(db.upcast()).krate()), + TyKind::Error => true, + TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| { + is_local(from_chalk_trait_id(trait_ref.trait_id).module(db.upcast()).krate()) + }), + _ => false, + } + }); + // FIXME: param coverage + // - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti`` (excluding `Ti`) + is_not_orphan +} + pub fn iterate_path_candidates( ty: &Canonical, db: &dyn HirDatabase, @@ -1422,26 +1479,52 @@ fn is_valid_fn_candidate( // We need to consider the bounds on the impl to distinguish functions of the same name // for a type. let predicates = db.generic_predicates(impl_id.into()); - let valid = predicates - .iter() - .map(|predicate| { - let (p, b) = predicate - .clone() - .substitute(Interner, &impl_subst) - // Skipping the inner binders is ok, as we don't handle quantified where - // clauses yet. - .into_value_and_skipped_binders(); - stdx::always!(b.len(Interner) == 0); - p - }) - // It's ok to get ambiguity here, as we may not have enough information to prove - // obligations. We'll check if the user is calling the selected method properly - // later anyway. - .all(|p| table.try_obligation(p.cast(Interner)).is_some()); - match valid { - true => IsValidCandidate::Yes, - false => IsValidCandidate::No, + let goals = predicates.iter().map(|p| { + let (p, b) = p + .clone() + .substitute(Interner, &impl_subst) + // Skipping the inner binders is ok, as we don't handle quantified where + // clauses yet. + .into_value_and_skipped_binders(); + stdx::always!(b.len(Interner) == 0); + + p.cast::(Interner) + }); + + for goal in goals.clone() { + let in_env = InEnvironment::new(&table.trait_env.env, goal); + let canonicalized = table.canonicalize(in_env); + let solution = table.db.trait_solve( + table.trait_env.krate, + table.trait_env.block, + canonicalized.value.clone(), + ); + + match solution { + Some(Solution::Unique(canonical_subst)) => { + canonicalized.apply_solution( + table, + Canonical { + binders: canonical_subst.binders, + value: canonical_subst.value.subst, + }, + ); + } + Some(Solution::Ambig(Guidance::Definite(substs))) => { + canonicalized.apply_solution(table, substs); + } + Some(_) => (), + None => return IsValidCandidate::No, + } } + + for goal in goals { + if table.try_obligation(goal).is_none() { + return IsValidCandidate::No; + } + } + + IsValidCandidate::Yes } else { // For `ItemContainerId::TraitId`, we check if `self_ty` implements the trait in // `iterate_trait_method_candidates()`. diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index e953058ccca45..2e6fe59d3bd80 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -243,16 +243,16 @@ impl Default for ProjectionStore { } impl ProjectionStore { - fn shrink_to_fit(&mut self) { + pub fn shrink_to_fit(&mut self) { self.id_to_proj.shrink_to_fit(); self.proj_to_id.shrink_to_fit(); } - fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option { + pub fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option { self.proj_to_id.get(projection).copied() } - fn intern(&mut self, projection: Box<[PlaceElem]>) -> ProjectionId { + pub fn intern(&mut self, projection: Box<[PlaceElem]>) -> ProjectionId { let new_id = ProjectionId(self.proj_to_id.len() as u32); match self.proj_to_id.entry(projection) { Entry::Occupied(id) => *id.get(), @@ -267,20 +267,24 @@ impl ProjectionStore { } impl ProjectionId { - const EMPTY: ProjectionId = ProjectionId(0); + pub const EMPTY: ProjectionId = ProjectionId(0); + + pub fn is_empty(self) -> bool { + self == ProjectionId::EMPTY + } - fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] { + pub fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] { store.id_to_proj.get(&self).unwrap() } - fn project(self, projection: PlaceElem, store: &mut ProjectionStore) -> ProjectionId { + pub fn project(self, projection: PlaceElem, store: &mut ProjectionStore) -> ProjectionId { let mut current = self.lookup(store).to_vec(); current.push(projection); store.intern(current.into()) } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Place { pub local: LocalId, pub projection: ProjectionId, @@ -1007,7 +1011,7 @@ pub enum Rvalue { #[derive(Debug, PartialEq, Eq, Clone)] pub enum StatementKind { Assign(Place, Rvalue), - //FakeRead(Box<(FakeReadCause, Place)>), + FakeRead(Place), //SetDiscriminant { // place: Box, // variant_index: VariantIdx, @@ -1069,6 +1073,10 @@ pub struct MirBody { } impl MirBody { + pub fn local_to_binding_map(&self) -> ArenaMap { + self.binding_locals.iter().map(|(it, y)| (*y, it)).collect() + } + fn walk_places(&mut self, mut f: impl FnMut(&mut Place, &mut ProjectionStore)) { fn for_operand( op: &mut Operand, @@ -1109,7 +1117,9 @@ impl MirBody { } } } - StatementKind::Deinit(p) => f(p, &mut self.projection_store), + StatementKind::FakeRead(p) | StatementKind::Deinit(p) => { + f(p, &mut self.projection_store) + } StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), @@ -1186,3 +1196,9 @@ pub enum MirSpan { } impl_from!(ExprId, PatId for MirSpan); + +impl From<&ExprId> for MirSpan { + fn from(value: &ExprId) -> Self { + (*value).into() + } +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs index 41fb129652a1e..74c5efd6c3f45 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -24,6 +24,7 @@ use super::{ pub enum MutabilityReason { Mut { spans: Vec }, Not, + Unused, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -144,7 +145,8 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec } } }, - StatementKind::Deinit(_) + StatementKind::FakeRead(_) + | StatementKind::Deinit(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), @@ -264,7 +266,10 @@ fn ever_initialized_map( is_ever_initialized = false; } } - StatementKind::Deinit(_) | StatementKind::Nop | StatementKind::StorageLive(_) => (), + StatementKind::Deinit(_) + | StatementKind::FakeRead(_) + | StatementKind::Nop + | StatementKind::StorageLive(_) => (), } } let Some(terminator) = &block.terminator else { @@ -331,16 +336,37 @@ fn ever_initialized_map( result } +fn push_mut_span(local: LocalId, span: MirSpan, result: &mut ArenaMap) { + match &mut result[local] { + MutabilityReason::Mut { spans } => spans.push(span), + it @ (MutabilityReason::Not | MutabilityReason::Unused) => { + *it = MutabilityReason::Mut { spans: vec![span] } + } + }; +} + +fn record_usage(local: LocalId, result: &mut ArenaMap) { + match &mut result[local] { + it @ MutabilityReason::Unused => { + *it = MutabilityReason::Not; + } + _ => (), + }; +} + +fn record_usage_for_operand(arg: &Operand, result: &mut ArenaMap) { + if let Operand::Copy(p) | Operand::Move(p) = arg { + record_usage(p.local, result); + } +} + fn mutability_of_locals( db: &dyn HirDatabase, body: &MirBody, ) -> ArenaMap { let mut result: ArenaMap = - body.locals.iter().map(|it| (it.0, MutabilityReason::Not)).collect(); - let mut push_mut_span = |local, span| match &mut result[local] { - MutabilityReason::Mut { spans } => spans.push(span), - it @ MutabilityReason::Not => *it = MutabilityReason::Mut { spans: vec![span] }, - }; + body.locals.iter().map(|it| (it.0, MutabilityReason::Unused)).collect(); + let ever_init_maps = ever_initialized_map(db, body); for (block_id, mut ever_init_map) in ever_init_maps.into_iter() { let block = &body.basic_blocks[block_id]; @@ -350,23 +376,51 @@ fn mutability_of_locals( match place_case(db, body, place) { ProjectionCase::Direct => { if ever_init_map.get(place.local).copied().unwrap_or_default() { - push_mut_span(place.local, statement.span); + push_mut_span(place.local, statement.span, &mut result); } else { ever_init_map.insert(place.local, true); } } ProjectionCase::DirectPart => { // Partial initialization is not supported, so it is definitely `mut` - push_mut_span(place.local, statement.span); + push_mut_span(place.local, statement.span, &mut result); + } + ProjectionCase::Indirect => { + record_usage(place.local, &mut result); } - ProjectionCase::Indirect => (), + } + match value { + Rvalue::CopyForDeref(p) + | Rvalue::Discriminant(p) + | Rvalue::Len(p) + | Rvalue::Ref(_, p) => { + record_usage(p.local, &mut result); + } + Rvalue::Use(o) + | Rvalue::Repeat(o, _) + | Rvalue::Cast(_, o, _) + | Rvalue::UnaryOp(_, o) => record_usage_for_operand(o, &mut result), + Rvalue::CheckedBinaryOp(_, o1, o2) => { + for o in [o1, o2] { + record_usage_for_operand(o, &mut result); + } + } + Rvalue::Aggregate(_, args) => { + for arg in args.iter() { + record_usage_for_operand(arg, &mut result); + } + } + Rvalue::ShallowInitBox(_, _) | Rvalue::ShallowInitBoxWithAlloc(_) => (), } if let Rvalue::Ref(BorrowKind::Mut { .. }, p) = value { if place_case(db, body, p) != ProjectionCase::Indirect { - push_mut_span(p.local, statement.span); + push_mut_span(p.local, statement.span, &mut result); } } } + StatementKind::FakeRead(p) => { + record_usage(p.local, &mut result); + } StatementKind::StorageDead(p) => { ever_init_map.insert(*p, false); } @@ -386,15 +440,21 @@ fn mutability_of_locals( | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop - | TerminatorKind::SwitchInt { .. } | TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Assert { .. } | TerminatorKind::Yield { .. } => (), - TerminatorKind::Call { destination, .. } => { + TerminatorKind::SwitchInt { discr, targets: _ } => { + record_usage_for_operand(discr, &mut result); + } + TerminatorKind::Call { destination, args, func, .. } => { + record_usage_for_operand(func, &mut result); + for arg in args.iter() { + record_usage_for_operand(arg, &mut result); + } if destination.projection.lookup(&body.projection_store).len() == 0 { if ever_init_map.get(destination.local).copied().unwrap_or_default() { - push_mut_span(destination.local, MirSpan::Unknown); + push_mut_span(destination.local, MirSpan::Unknown, &mut result); } else { ever_init_map.insert(destination.local, true); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 4364e0d323bbc..62efb858511b4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -162,7 +162,7 @@ pub struct Evaluator<'a> { not_special_fn_cache: RefCell>, mir_or_dyn_index_cache: RefCell>, /// Constantly dropping and creating `Locals` is very costly. We store - /// old locals that we normaly want to drop here, to reuse their allocations + /// old locals that we normally want to drop here, to reuse their allocations /// later. unused_locals_store: RefCell>>, cached_ptr_size: usize, @@ -375,10 +375,7 @@ impl MirEvalError { Err(_) => continue, }, MirSpan::PatId(p) => match source_map.pat_syntax(*p) { - Ok(s) => s.map(|it| match it { - Either::Left(e) => e.into(), - Either::Right(e) => e.into(), - }), + Ok(s) => s.map(|it| it.syntax_node_ptr()), Err(_) => continue, }, MirSpan::Unknown => continue, @@ -842,6 +839,7 @@ impl Evaluator<'_> { } StatementKind::Deinit(_) => not_supported!("de-init statement"), StatementKind::StorageLive(_) + | StatementKind::FakeRead(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), } @@ -2301,7 +2299,7 @@ impl Evaluator<'_> { match self.get_mir_or_dyn_index(def, generic_args.clone(), locals, span)? { MirOrDynIndex::Dyn(self_ty_idx) => { // In the layout of current possible receiver, which at the moment of writing this code is one of - // `&T`, `&mut T`, `Box`, `Rc`, `Arc`, and `Pin

    ` where `P` is one of possible recievers, + // `&T`, `&mut T`, `Box`, `Rc`, `Arc`, and `Pin

    ` where `P` is one of possible receivers, // the vtable is exactly in the `[ptr_size..2*ptr_size]` bytes. So we can use it without branching on // the type. let first_arg = arg_bytes.clone().next().unwrap(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 803ef631f1e03..2de99e41659cf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -1045,7 +1045,7 @@ impl Evaluator<'_> { } "transmute" => { let [arg] = args else { - return Err(MirEvalError::TypeError("trasmute arg is not provided")); + return Err(MirEvalError::TypeError("transmute arg is not provided")); }; destination.write_from_interval(self, arg.interval) } @@ -1065,7 +1065,7 @@ impl Evaluator<'_> { } "ctlz" | "ctlz_nonzero" => { let [arg] = args else { - return Err(MirEvalError::TypeError("cttz arg is not provided")); + return Err(MirEvalError::TypeError("ctlz arg is not provided")); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).leading_zeros() as usize; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index dd2dba717f95e..922aee011cf33 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -105,9 +105,14 @@ pub enum MirLowerError { /// A token to ensuring that each drop scope is popped at most once, thanks to the compiler that checks moves. struct DropScopeToken; impl DropScopeToken { - fn pop_and_drop(self, ctx: &mut MirLowerCtx<'_>, current: BasicBlockId) -> BasicBlockId { + fn pop_and_drop( + self, + ctx: &mut MirLowerCtx<'_>, + current: BasicBlockId, + span: MirSpan, + ) -> BasicBlockId { std::mem::forget(self); - ctx.pop_drop_scope_internal(current) + ctx.pop_drop_scope_internal(current, span) } /// It is useful when we want a drop scope is syntaxically closed, but we don't want to execute any drop @@ -529,6 +534,7 @@ impl<'ctx> MirLowerCtx<'ctx> { else { return Ok(None); }; + self.push_fake_read(current, cond_place, expr_id.into()); let (then_target, else_target) = self.pattern_match(current, None, cond_place, *pat)?; self.write_bytes_to_place( @@ -581,7 +587,7 @@ impl<'ctx> MirLowerCtx<'ctx> { self.lower_loop(current, place, *label, expr_id.into(), |this, begin| { let scope = this.push_drop_scope(); if let Some((_, mut current)) = this.lower_expr_as_place(begin, *body, true)? { - current = scope.pop_and_drop(this, current); + current = scope.pop_and_drop(this, current, body.into()); this.set_goto(current, begin, expr_id.into()); } else { scope.pop_assume_dropped(this); @@ -668,6 +674,7 @@ impl<'ctx> MirLowerCtx<'ctx> { else { return Ok(None); }; + self.push_fake_read(current, cond_place, expr_id.into()); let mut end = None; for MatchArm { pat, guard, expr } in arms.iter() { let (then, mut otherwise) = @@ -718,7 +725,8 @@ impl<'ctx> MirLowerCtx<'ctx> { .ok_or(MirLowerError::ContinueWithoutLoop)?, }; let begin = loop_data.begin; - current = self.drop_until_scope(loop_data.drop_scope_index, current); + current = + self.drop_until_scope(loop_data.drop_scope_index, current, expr_id.into()); self.set_goto(current, begin, expr_id.into()); Ok(None) } @@ -757,7 +765,7 @@ impl<'ctx> MirLowerCtx<'ctx> { self.current_loop_blocks.as_ref().unwrap().drop_scope_index, ), }; - current = self.drop_until_scope(drop_scope, current); + current = self.drop_until_scope(drop_scope, current, expr_id.into()); self.set_goto(current, end, expr_id.into()); Ok(None) } @@ -771,7 +779,7 @@ impl<'ctx> MirLowerCtx<'ctx> { return Ok(None); } } - current = self.drop_until_scope(0, current); + current = self.drop_until_scope(0, current, expr_id.into()); self.set_terminator(current, TerminatorKind::Return, expr_id.into()); Ok(None) } @@ -1299,6 +1307,7 @@ impl<'ctx> MirLowerCtx<'ctx> { return Ok(None); }; if matches!(&self.body.exprs[lhs], Expr::Underscore) { + self.push_fake_read_for_operand(current, rhs_op, span); return Ok(Some(current)); } if matches!( @@ -1575,6 +1584,16 @@ impl<'ctx> MirLowerCtx<'ctx> { self.result.basic_blocks[block].statements.push(statement); } + fn push_fake_read(&mut self, block: BasicBlockId, p: Place, span: MirSpan) { + self.push_statement(block, StatementKind::FakeRead(p).with_span(span)); + } + + fn push_fake_read_for_operand(&mut self, block: BasicBlockId, operand: Operand, span: MirSpan) { + if let Operand::Move(p) | Operand::Copy(p) = operand { + self.push_fake_read(block, p, span); + } + } + fn push_assignment( &mut self, block: BasicBlockId, @@ -1733,6 +1752,7 @@ impl<'ctx> MirLowerCtx<'ctx> { return Ok(None); }; current = c; + self.push_fake_read(current, init_place, span); (current, else_block) = self.pattern_match(current, None, init_place, *pat)?; match (else_block, else_branch) { @@ -1760,14 +1780,15 @@ impl<'ctx> MirLowerCtx<'ctx> { } } } - hir_def::hir::Statement::Expr { expr, has_semi: _ } => { + &hir_def::hir::Statement::Expr { expr, has_semi: _ } => { let scope2 = self.push_drop_scope(); - let Some((_, c)) = self.lower_expr_as_place(current, *expr, true)? else { + let Some((p, c)) = self.lower_expr_as_place(current, expr, true)? else { scope2.pop_assume_dropped(self); scope.pop_assume_dropped(self); return Ok(None); }; - current = scope2.pop_and_drop(self, c); + self.push_fake_read(c, p, expr.into()); + current = scope2.pop_and_drop(self, c, expr.into()); } } } @@ -1778,7 +1799,7 @@ impl<'ctx> MirLowerCtx<'ctx> { }; current = c; } - current = scope.pop_and_drop(self, current); + current = scope.pop_and_drop(self, current, span); Ok(Some(current)) } @@ -1858,9 +1879,14 @@ impl<'ctx> MirLowerCtx<'ctx> { } } - fn drop_until_scope(&mut self, scope_index: usize, mut current: BasicBlockId) -> BasicBlockId { + fn drop_until_scope( + &mut self, + scope_index: usize, + mut current: BasicBlockId, + span: MirSpan, + ) -> BasicBlockId { for scope in self.drop_scopes[scope_index..].to_vec().iter().rev() { - self.emit_drop_and_storage_dead_for_scope(scope, &mut current); + self.emit_drop_and_storage_dead_for_scope(scope, &mut current, span); } current } @@ -1876,17 +1902,22 @@ impl<'ctx> MirLowerCtx<'ctx> { } /// Don't call directly - fn pop_drop_scope_internal(&mut self, mut current: BasicBlockId) -> BasicBlockId { + fn pop_drop_scope_internal( + &mut self, + mut current: BasicBlockId, + span: MirSpan, + ) -> BasicBlockId { let scope = self.drop_scopes.pop().unwrap(); - self.emit_drop_and_storage_dead_for_scope(&scope, &mut current); + self.emit_drop_and_storage_dead_for_scope(&scope, &mut current, span); current } fn pop_drop_scope_assert_finished( &mut self, mut current: BasicBlockId, + span: MirSpan, ) -> Result { - current = self.pop_drop_scope_internal(current); + current = self.pop_drop_scope_internal(current, span); if !self.drop_scopes.is_empty() { implementation_error!("Mismatched count between drop scope push and pops"); } @@ -1897,6 +1928,7 @@ impl<'ctx> MirLowerCtx<'ctx> { &mut self, scope: &DropScope, current: &mut Idx, + span: MirSpan, ) { for &l in scope.locals.iter().rev() { if !self.result.locals[l].ty.clone().is_copy(self.db, self.owner) { @@ -1904,13 +1936,10 @@ impl<'ctx> MirLowerCtx<'ctx> { self.set_terminator( prev, TerminatorKind::Drop { place: l.into(), target: *current, unwind: None }, - MirSpan::Unknown, + span, ); } - self.push_statement( - *current, - StatementKind::StorageDead(l).with_span(MirSpan::Unknown), - ); + self.push_statement(*current, StatementKind::StorageDead(l).with_span(span)); } } } @@ -1987,7 +2016,7 @@ pub fn mir_body_for_closure_query( |_| true, )?; if let Some(current) = ctx.lower_expr_to_place(*root, return_slot().into(), current)? { - let current = ctx.pop_drop_scope_assert_finished(current)?; + let current = ctx.pop_drop_scope_assert_finished(current, root.into())?; ctx.set_terminator(current, TerminatorKind::Return, (*root).into()); } let mut upvar_map: FxHashMap> = FxHashMap::default(); @@ -2131,7 +2160,7 @@ pub fn lower_to_mir( ctx.lower_params_and_bindings([].into_iter(), binding_picker)? }; if let Some(current) = ctx.lower_expr_to_place(root_expr, return_slot().into(), current)? { - let current = ctx.pop_drop_scope_assert_finished(current)?; + let current = ctx.pop_drop_scope_assert_finished(current, root_expr.into())?; ctx.set_terminator(current, TerminatorKind::Return, root_expr.into()); } Ok(ctx.result) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index 270f75ad9674c..1120bb1c1123d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -284,6 +284,7 @@ impl MirLowerCtx<'_> { ); (current, current_else) = self.pattern_match_binding( id, + *slice, next_place, (*slice).into(), current, @@ -395,6 +396,7 @@ impl MirLowerCtx<'_> { if mode == MatchingMode::Bind { self.pattern_match_binding( *id, + pattern, cond_place, pattern.into(), current, @@ -431,13 +433,14 @@ impl MirLowerCtx<'_> { fn pattern_match_binding( &mut self, id: BindingId, + pat: PatId, cond_place: Place, span: MirSpan, current: BasicBlockId, current_else: Option, ) -> Result<(BasicBlockId, Option)> { let target_place = self.binding_local(id)?; - let mode = self.infer.binding_modes[id]; + let mode = self.infer.binding_modes[pat]; self.push_storage_live(id, current)?; self.push_assignment( current, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs index df16d0d82015c..7d2bb95d931c2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs @@ -248,6 +248,7 @@ impl Filler<'_> { | Rvalue::CopyForDeref(_) => (), }, StatementKind::Deinit(_) + | StatementKind::FakeRead(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs index 0108859ff32ee..a91f90bc249e5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs @@ -145,7 +145,7 @@ impl<'a> MirPrettyCtx<'a> { let indent = mem::take(&mut self.indent); let mut ctx = MirPrettyCtx { body: &body, - local_to_binding: body.binding_locals.iter().map(|(it, y)| (*y, it)).collect(), + local_to_binding: body.local_to_binding_map(), result, indent, ..*self @@ -167,7 +167,7 @@ impl<'a> MirPrettyCtx<'a> { } fn new(body: &'a MirBody, hir_body: &'a Body, db: &'a dyn HirDatabase) -> Self { - let local_to_binding = body.binding_locals.iter().map(|(it, y)| (*y, it)).collect(); + let local_to_binding = body.local_to_binding_map(); MirPrettyCtx { body, db, @@ -233,6 +233,11 @@ impl<'a> MirPrettyCtx<'a> { this.place(p); wln!(this, ");"); } + StatementKind::FakeRead(p) => { + w!(this, "FakeRead("); + this.place(p); + wln!(this, ");"); + } StatementKind::Nop => wln!(this, "Nop;"), } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index d22d0d85c8e1b..1446e83fa8876 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -269,12 +269,7 @@ fn pat_node( Some(match body_source_map.pat_syntax(pat) { Ok(sp) => { let root = db.parse_or_expand(sp.file_id); - sp.map(|ptr| { - ptr.either( - |it| it.to_node(&root).syntax().clone(), - |it| it.to_node(&root).syntax().clone(), - ) - }) + sp.map(|ptr| ptr.to_node(&root).syntax().clone()) } Err(SyntheticSyntax) => return None, }) @@ -303,12 +298,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let syntax_ptr = match body_source_map.pat_syntax(pat) { Ok(sp) => { let root = db.parse_or_expand(sp.file_id); - sp.map(|ptr| { - ptr.either( - |it| it.to_node(&root).syntax().clone(), - |it| it.to_node(&root).syntax().clone(), - ) - }) + sp.map(|ptr| ptr.to_node(&root).syntax().clone()) } Err(SyntheticSyntax) => continue, }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs index 1e6e946a13f8b..d16e0eb0137bf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs @@ -684,8 +684,7 @@ fn infer_builtin_macros_line() { } "#, expect![[r#" - !0..1 '0': i32 - !0..6 '0asu32': u32 + !0..4 '0u32': u32 63..87 '{ ...!(); }': () 73..74 'x': u32 "#]], @@ -723,8 +722,7 @@ fn infer_builtin_macros_column() { } "#, expect![[r#" - !0..1 '0': i32 - !0..6 '0asu32': u32 + !0..4 '0u32': u32 65..91 '{ ...!(); }': () 75..76 'x': u32 "#]], diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs index 0f5a3e1752cf5..5d7bab09c26e6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs @@ -1129,3 +1129,27 @@ fn foo() { "#, ); } + +#[test] +fn generic_alias() { + check_types( + r#" +type Wrap = T; + +enum X { + A { cool: u32, stuff: u32 }, + B, +} + +fn main() { + let wrapped = Wrap::::A { + cool: 100, + stuff: 100, + }; + + if let Wrap::::A { cool, ..} = &wrapped {} + //^^^^ &u32 +} +"#, + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index d36b885ec14a4..003ae60e8e517 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -2597,6 +2597,34 @@ fn test() { ); } +#[test] +fn associated_type_in_type_bound() { + check_types( + r#" +//- minicore: deref +fn fb(f: Foo<&u8>) { + f.foobar(); + //^^^^^^^^^^ u8 +} +trait Bar { + fn bar(&self) -> u8; +} +impl Bar for u8 { + fn bar(&self) -> u8 { *self } +} + +struct Foo { + foo: F, +} +impl> Foo { + fn foobar(&self) -> u8 { + self.foo.deref().bar() + } +} +"#, + ) +} + #[test] fn dyn_trait_through_chalk() { check_types( @@ -4439,42 +4467,42 @@ fn test(v: S) { fn associated_type_in_argument() { check( r#" - trait A { - fn m(&self) -> i32; - } +trait A { + fn m(&self) -> i32; +} - fn x(k: &::Ty) { - k.m(); - } +fn x(k: &::Ty) { + k.m(); +} - struct X; - struct Y; +struct X; +struct Y; - impl A for X { - fn m(&self) -> i32 { - 8 - } +impl A for X { + fn m(&self) -> i32 { + 8 } +} - impl A for Y { - fn m(&self) -> i32 { - 32 - } +impl A for Y { + fn m(&self) -> i32 { + 32 } +} - trait B { - type Ty: A; - } +trait B { + type Ty: A; +} - impl B for u16 { - type Ty = X; - } +impl B for u16 { + type Ty = X; +} - fn ttt() { - let inp = Y; - x::(&inp); - //^^^^ expected &X, got &Y - } - "#, +fn ttt() { + let inp = Y; + x::(&inp); + //^^^^ expected &X, got &Y +} +"#, ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index 3c7cfbaed3a40..467b94a2662a1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -48,7 +48,7 @@ pub struct TraitEnvironment { pub krate: CrateId, pub block: Option, // FIXME make this a BTreeMap - pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, + pub(crate) traits_from_clauses: Box<[(Ty, TraitId)]>, pub env: chalk_ir::Environment, } @@ -57,7 +57,7 @@ impl TraitEnvironment { TraitEnvironment { krate, block: None, - traits_from_clauses: Vec::new(), + traits_from_clauses: Box::default(), env: chalk_ir::Environment::new(Interner), } } diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml index f860ee9484526..4c1dfbc294e5b 100644 --- a/src/tools/rust-analyzer/crates/hir/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml @@ -13,9 +13,9 @@ doctest = false [dependencies] rustc-hash = "1.1.0" -either = "1.7.0" +either.workspace = true arrayvec = "0.7.2" -itertools = "0.10.5" +itertools.workspace = true smallvec.workspace = true triomphe.workspace = true once_cell = "1.17.1" @@ -30,3 +30,6 @@ profile.workspace = true stdx.workspace = true syntax.workspace = true tt.workspace = true + +[features] +in-rust-tree = [] diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 479138b67f829..cf9a2b73d9b1f 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -3,7 +3,7 @@ //! //! This probably isn't the best way to do this -- ideally, diagnostics should //! be expressed in terms of hir types themselves. -pub use hir_ty::diagnostics::{CaseType, IncoherentImpl, IncorrectCase}; +pub use hir_ty::diagnostics::{CaseType, IncorrectCase}; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; @@ -53,6 +53,9 @@ diagnostics![ PrivateAssocItem, PrivateField, ReplaceFilterMapNextWithFindMap, + TraitImplIncorrectSafety, + TraitImplMissingAssocItems, + TraitImplOrphan, TypedHole, TypeMismatch, UndeclaredLabel, @@ -66,6 +69,7 @@ diagnostics![ UnresolvedModule, UnresolvedProcMacro, UnusedMut, + UnusedVariable, ]; #[derive(Debug)] @@ -173,20 +177,19 @@ pub struct MalformedDerive { #[derive(Debug)] pub struct NoSuchField { - pub field: InFile, AstPtr>>, + pub field: InFile>>, pub private: bool, } #[derive(Debug)] pub struct PrivateAssocItem { - pub expr_or_pat: - InFile, Either, AstPtr>>>, + pub expr_or_pat: InFile>>>, pub item: AssocItem, } #[derive(Debug)] pub struct MismatchedTupleStructPatArgCount { - pub expr_or_pat: InFile, AstPtr>>, + pub expr_or_pat: InFile>>, pub expected: usize, pub found: usize, } @@ -227,7 +230,7 @@ pub struct MissingUnsafe { #[derive(Debug)] pub struct MissingFields { pub file: HirFileId, - pub field_list_parent: Either, AstPtr>, + pub field_list_parent: AstPtr>, pub field_list_parent_path: Option>, pub missed_fields: Vec, } @@ -254,7 +257,7 @@ pub struct MissingMatchArms { #[derive(Debug)] pub struct TypeMismatch { - pub expr_or_pat: Either>, InFile>>, + pub expr_or_pat: InFile>>, pub expected: Type, pub actual: Type, } @@ -270,8 +273,40 @@ pub struct UnusedMut { pub local: Local, } +#[derive(Debug)] +pub struct UnusedVariable { + pub local: Local, +} + #[derive(Debug)] pub struct MovedOutOfRef { pub ty: Type, pub span: InFile, } + +#[derive(Debug, PartialEq, Eq)] +pub struct IncoherentImpl { + pub file_id: HirFileId, + pub impl_: AstPtr, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct TraitImplOrphan { + pub file_id: HirFileId, + pub impl_: AstPtr, +} + +// FIXME: Split this off into the corresponding 4 rustc errors +#[derive(Debug, PartialEq, Eq)] +pub struct TraitImplIncorrectSafety { + pub file_id: HirFileId, + pub impl_: AstPtr, + pub should_be_safe: bool, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct TraitImplMissingAssocItems { + pub file_id: HirFileId, + pub impl_: AstPtr, + pub missing: Vec<(Name, AssocItem)>, +} diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index ac171026d5d7f..5847c8a9fb52b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -1,6 +1,6 @@ //! HirDisplay implementations for various hir types. use hir_def::{ - data::adt::VariantData, + data::adt::{StructKind, VariantData}, generics::{ TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, }, @@ -163,7 +163,40 @@ impl HirDisplay for Struct { write!(f, "{}", self.name(f.db).display(f.db.upcast()))?; let def_id = GenericDefId::AdtId(AdtId::StructId(self.id)); write_generic_params(def_id, f)?; + + let variant_data = self.variant_data(f.db); + if let StructKind::Tuple = variant_data.kind() { + f.write_char('(')?; + let mut it = variant_data.fields().iter().peekable(); + + while let Some((id, _)) = it.next() { + let field = Field { parent: (*self).into(), id }; + field.ty(f.db).hir_fmt(f)?; + if it.peek().is_some() { + f.write_str(", ")?; + } + } + + f.write_str(");")?; + } + write_where_clause(def_id, f)?; + + if let StructKind::Record = variant_data.kind() { + let fields = self.fields(f.db); + if fields.is_empty() { + f.write_str(" {}")?; + } else { + f.write_str(" {\n")?; + for field in self.fields(f.db) { + f.write_str(" ")?; + field.hir_fmt(f)?; + f.write_str(",\n")?; + } + f.write_str("}")?; + } + } + Ok(()) } } @@ -176,6 +209,18 @@ impl HirDisplay for Enum { let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id)); write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; + + let variants = self.variants(f.db); + if !variants.is_empty() { + f.write_str(" {\n")?; + for variant in variants { + f.write_str(" ")?; + variant.hir_fmt(f)?; + f.write_str(",\n")?; + } + f.write_str("}")?; + } + Ok(()) } } @@ -188,6 +233,18 @@ impl HirDisplay for Union { let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id)); write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; + + let fields = self.fields(f.db); + if !fields.is_empty() { + f.write_str(" {\n")?; + for field in self.fields(f.db) { + f.write_str(" ")?; + field.hir_fmt(f)?; + f.write_str(",\n")?; + } + f.write_str("}")?; + } + Ok(()) } } @@ -559,7 +616,7 @@ impl HirDisplay for TypeAlias { write_where_clause(def_id, f)?; if !data.bounds.is_empty() { f.write_str(": ")?; - f.write_joined(&data.bounds, " + ")?; + f.write_joined(data.bounds.iter(), " + ")?; } if let Some(ty) = &data.type_ref { f.write_str(" = ")?; diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index b215ed38f28b1..908027a2026d1 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -18,6 +18,7 @@ //! . #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![recursion_limit = "512"] mod semantics; @@ -33,7 +34,7 @@ pub mod symbols; mod display; -use std::{iter, ops::ControlFlow}; +use std::{iter, mem::discriminant, ops::ControlFlow}; use arrayvec::ArrayVec; use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind}; @@ -53,20 +54,20 @@ use hir_def::{ resolver::{HasResolver, Resolver}, src::HasSource as _, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, - EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, HasModule, ImplId, - InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, Lookup, - MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, - TypeOrConstParamId, TypeParamId, UnionId, + EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, + ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalEnumVariantId, LocalFieldId, + Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, + TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{name::name, MacroCallKind}; use hir_ty::{ - all_super_traits, autoderef, + all_super_traits, autoderef, check_orphan_rules, consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, diagnostics::BodyValidationDiagnostic, known_const_to_ast, - layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding}, + layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, method_resolution::{self, TyFingerprint}, - mir::{self, interpret_mir}, + mir::interpret_mir, primitive::UintTy, traits::FnTrait, AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, @@ -89,17 +90,7 @@ use crate::db::{DefDatabase, HirDatabase}; pub use crate::{ attrs::{resolve_doc_path_on, HasAttrs}, - diagnostics::{ - AnyDiagnostic, BreakOutsideOfLoop, CaseType, ExpectedFunction, InactiveCode, - IncoherentImpl, IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError, - MacroExpansionParseError, MalformedDerive, MismatchedArgCount, - MismatchedTupleStructPatArgCount, MissingFields, MissingMatchArms, MissingUnsafe, - MovedOutOfRef, NeedMut, NoSuchField, PrivateAssocItem, PrivateField, - ReplaceFilterMapNextWithFindMap, TypeMismatch, TypedHole, UndeclaredLabel, - UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate, UnresolvedField, - UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule, - UnresolvedProcMacro, UnusedMut, - }, + diagnostics::*, has_source::HasSource, semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits}, }; @@ -138,9 +129,10 @@ pub use { hir_ty::{ display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, layout::LayoutError, - mir::MirEvalError, PointerCast, Safety, }, + // FIXME: Properly encapsulate mir + hir_ty::{mir, Interner as ChalkTyInterner}, }; // These are negative re-exports: pub using these names is forbidden, they @@ -452,15 +444,7 @@ impl HasVisibility for ModuleDef { impl Module { /// Name of this module. pub fn name(self, db: &dyn HirDatabase) -> Option { - let def_map = self.id.def_map(db.upcast()); - let parent = def_map[self.id.local_id].parent?; - def_map[parent].children.iter().find_map(|(name, module_id)| { - if *module_id == self.id.local_id { - Some(name.clone()) - } else { - None - } - }) + self.id.name(db.upcast()) } /// Returns the crate this module is part of. @@ -571,6 +555,7 @@ impl Module { if def_map[m.id.local_id].origin.is_inline() { m.diagnostics(db, acc) } + acc.extend(def.diagnostics(db)) } ModuleDef::Trait(t) => { for diag in db.trait_data_with_diagnostics(t.id).1.iter() { @@ -610,6 +595,7 @@ impl Module { let inherent_impls = db.inherent_impls_in_crate(self.id.krate()); + let mut impl_assoc_items_scratch = vec![]; for impl_def in self.impl_defs(db) { let loc = impl_def.id.lookup(db.upcast()); let tree = loc.id.item_tree(db.upcast()); @@ -620,19 +606,109 @@ impl Module { // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow continue; } + let ast_id_map = db.ast_id_map(file_id); for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() { emit_def_diagnostic(db, acc, diag); } if inherent_impls.invalid_impls().contains(&impl_def.id) { - let ast_id_map = db.ast_id_map(file_id); - acc.push(IncoherentImpl { impl_: ast_id_map.get(node.ast_id()), file_id }.into()) } - for item in impl_def.items(db) { - let def: DefWithBody = match item { + if !impl_def.check_orphan_rules(db) { + acc.push(TraitImplOrphan { impl_: ast_id_map.get(node.ast_id()), file_id }.into()) + } + + let trait_ = impl_def.trait_(db); + let trait_is_unsafe = trait_.map_or(false, |t| t.is_unsafe(db)); + let impl_is_negative = impl_def.is_negative(db); + let impl_is_unsafe = impl_def.is_unsafe(db); + + let drop_maybe_dangle = (|| { + // FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper + let trait_ = trait_?; + let drop_trait = db.lang_item(self.krate().into(), LangItem::Drop)?.as_trait()?; + if drop_trait != trait_.into() { + return None; + } + let parent = impl_def.id.into(); + let generic_params = db.generic_params(parent); + let lifetime_params = generic_params.lifetimes.iter().map(|(local_id, _)| { + GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id }) + }); + let type_params = generic_params + .iter() + .filter(|(_, it)| it.type_param().is_some()) + .map(|(local_id, _)| { + GenericParamId::TypeParamId(TypeParamId::from_unchecked( + TypeOrConstParamId { parent, local_id }, + )) + }); + let res = type_params + .chain(lifetime_params) + .any(|p| db.attrs(AttrDefId::GenericParamId(p)).by_key("may_dangle").exists()); + Some(res) + })() + .unwrap_or(false); + + match (impl_is_unsafe, trait_is_unsafe, impl_is_negative, drop_maybe_dangle) { + // unsafe negative impl + (true, _, true, _) | + // unsafe impl for safe trait + (true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: true }.into()), + // safe impl for unsafe trait + (false, true, false, _) | + // safe impl of dangling drop + (false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: false }.into()), + _ => (), + }; + + if let Some(trait_) = trait_ { + let items = &db.trait_data(trait_.into()).items; + let required_items = items.iter().filter(|&(_, assoc)| match *assoc { + AssocItemId::FunctionId(it) => !db.function_data(it).has_body(), + AssocItemId::ConstId(id) => Const::from(id).value(db).is_none(), + AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(), + }); + impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().filter_map( + |&item| { + Some(( + item, + match item { + AssocItemId::FunctionId(it) => db.function_data(it).name.clone(), + AssocItemId::ConstId(it) => { + db.const_data(it).name.as_ref()?.clone() + } + AssocItemId::TypeAliasId(it) => db.type_alias_data(it).name.clone(), + }, + )) + }, + )); + + let missing: Vec<_> = required_items + .filter(|(name, id)| { + !impl_assoc_items_scratch.iter().any(|(impl_item, impl_name)| { + discriminant(impl_item) == discriminant(id) && impl_name == name + }) + }) + .map(|(name, item)| (name.clone(), AssocItem::from(*item))) + .collect(); + if !missing.is_empty() { + acc.push( + TraitImplMissingAssocItems { + impl_: ast_id_map.get(node.ast_id()), + file_id, + missing, + } + .into(), + ) + } + impl_assoc_items_scratch.clear(); + } + + for &item in &db.impl_data(impl_def.id).items { + let def: DefWithBody = match AssocItem::from(item) { AssocItem::Function(it) => it.into(), AssocItem::Const(it) => it.into(), AssocItem::TypeAlias(_) => continue, @@ -671,8 +747,15 @@ impl Module { db: &dyn DefDatabase, item: impl Into, prefer_no_std: bool, + prefer_prelude: bool, ) -> Option { - hir_def::find_path::find_path(db, item.into().into(), self.into(), prefer_no_std) + hir_def::find_path::find_path( + db, + item.into().into(), + self.into(), + prefer_no_std, + prefer_prelude, + ) } /// Finds a path that can be used to refer to the given item from within @@ -683,6 +766,7 @@ impl Module { item: impl Into, prefix_kind: PrefixKind, prefer_no_std: bool, + prefer_prelude: bool, ) -> Option { hir_def::find_path::find_path_prefixed( db, @@ -690,6 +774,7 @@ impl Module { self.into(), prefix_kind, prefer_no_std, + prefer_prelude, ) } } @@ -1453,9 +1538,7 @@ impl DefWithBody { let (body, source_map) = db.body_with_source_map(self.into()); for (_, def_map) in body.blocks(db.upcast()) { - for diag in def_map.diagnostics() { - emit_def_diagnostic(db, acc, diag); - } + Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc); } for diag in source_map.diagnostics() { @@ -1509,10 +1592,10 @@ impl DefWithBody { &hir_ty::InferenceDiagnostic::NoSuchField { field: expr, private } => { let expr_or_pat = match expr { ExprOrPatId::ExprId(expr) => { - source_map.field_syntax(expr).map(Either::Left) + source_map.field_syntax(expr).map(AstPtr::wrap_left) } ExprOrPatId::PatId(pat) => { - source_map.pat_field_syntax(pat).map(Either::Right) + source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) } }; acc.push(NoSuchField { field: expr_or_pat, private }.into()) @@ -1530,8 +1613,8 @@ impl DefWithBody { } &hir_ty::InferenceDiagnostic::PrivateAssocItem { id, item } => { let expr_or_pat = match id { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(Either::Left), - ExprOrPatId::PatId(pat) => pat_syntax(pat).map(Either::Right), + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), }; let item = item.into(); acc.push(PrivateAssocItem { expr_or_pat, item }.into()) @@ -1609,12 +1692,17 @@ impl DefWithBody { found, } => { let expr_or_pat = match pat { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(Either::Left), - ExprOrPatId::PatId(pat) => source_map - .pat_syntax(pat) - .expect("unexpected synthetic") - .map(|it| it.unwrap_left()) - .map(Either::Right), + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => { + let InFile { file_id, value } = + source_map.pat_syntax(pat).expect("unexpected synthetic"); + + // cast from Either -> Either<_, Pat> + let Some(ptr) = AstPtr::try_from_raw(value.syntax_node_ptr()) else { + continue; + }; + InFile { file_id, value: ptr } + } }; acc.push( MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into(), @@ -1628,11 +1716,15 @@ impl DefWithBody { ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right), }; let expr_or_pat = match expr_or_pat { - Ok(Either::Left(expr)) => Either::Left(expr), - Ok(Either::Right(InFile { file_id, value: Either::Left(pat) })) => { - Either::Right(InFile { file_id, value: pat }) + Ok(Either::Left(expr)) => expr.map(AstPtr::wrap_left), + Ok(Either::Right(InFile { file_id, value: pat })) => { + // cast from Either -> Either<_, Pat> + let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else { + continue; + }; + InFile { file_id, value: ptr } } - Ok(Either::Right(_)) | Err(SyntheticSyntax) => continue, + Err(SyntheticSyntax) => continue, }; acc.push( @@ -1667,10 +1759,7 @@ impl DefWithBody { Err(_) => continue, }, mir::MirSpan::PatId(p) => match source_map.pat_syntax(p) { - Ok(s) => s.map(|it| match it { - Either::Left(e) => e.into(), - Either::Right(e) => e.into(), - }), + Ok(s) => s.map(|it| it.into()), Err(_) => continue, }, mir::MirSpan::Unknown => continue, @@ -1697,9 +1786,20 @@ impl DefWithBody { // Skip synthetic bindings continue; } - let need_mut = &mol[local]; + let mut need_mut = &mol[local]; + if body[binding_id].name.as_str() == Some("self") + && need_mut == &mir::MutabilityReason::Unused + { + need_mut = &mir::MutabilityReason::Not; + } let local = Local { parent: self.into(), binding_id }; match (need_mut, local.is_mut(db)) { + (mir::MutabilityReason::Unused, _) => { + let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with("_")); + if !should_ignore { + acc.push(UnusedVariable { local }.into()) + } + } (mir::MutabilityReason::Mut { .. }, true) | (mir::MutabilityReason::Not, false) => (), (mir::MutabilityReason::Mut { spans }, false) => { @@ -1710,10 +1810,7 @@ impl DefWithBody { Err(_) => continue, }, mir::MirSpan::PatId(p) => match source_map.pat_syntax(*p) { - Ok(s) => s.map(|it| match it { - Either::Left(e) => e.into(), - Either::Right(e) => e.into(), - }), + Ok(s) => s.map(|it| it.into()), Err(_) => continue, }, mir::MirSpan::Unknown => continue, @@ -1752,18 +1849,18 @@ impl DefWithBody { Ok(source_ptr) => { let root = source_ptr.file_syntax(db.upcast()); if let ast::Expr::RecordExpr(record_expr) = - &source_ptr.value.to_node(&root) + source_ptr.value.to_node(&root) { if record_expr.record_expr_field_list().is_some() { + let field_list_parent_path = + record_expr.path().map(|path| AstPtr::new(&path)); acc.push( MissingFields { file: source_ptr.file_id, - field_list_parent: Either::Left(AstPtr::new( + field_list_parent: AstPtr::new(&Either::Left( record_expr, )), - field_list_parent_path: record_expr - .path() - .map(|path| AstPtr::new(&path)), + field_list_parent_path, missed_fields, } .into(), @@ -1775,24 +1872,24 @@ impl DefWithBody { }, Either::Right(record_pat) => match source_map.pat_syntax(record_pat) { Ok(source_ptr) => { - if let Some(expr) = source_ptr.value.as_ref().left() { + if let Some(ptr) = source_ptr.value.clone().cast::() + { let root = source_ptr.file_syntax(db.upcast()); - if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { - if record_pat.record_pat_field_list().is_some() { - acc.push( - MissingFields { - file: source_ptr.file_id, - field_list_parent: Either::Right(AstPtr::new( - &record_pat, - )), - field_list_parent_path: record_pat - .path() - .map(|path| AstPtr::new(&path)), - missed_fields, - } - .into(), - ) - } + let record_pat = ptr.to_node(&root); + if record_pat.record_pat_field_list().is_some() { + let field_list_parent_path = + record_pat.path().map(|path| AstPtr::new(&path)); + acc.push( + MissingFields { + file: source_ptr.file_id, + field_list_parent: AstPtr::new(&Either::Right( + record_pat, + )), + field_list_parent_path, + missed_fields, + } + .into(), + ) } } } @@ -1818,17 +1915,20 @@ impl DefWithBody { if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) { - if let Some(scrut_expr) = match_expr.expr() { - acc.push( - MissingMatchArms { - scrutinee_expr: InFile::new( - source_ptr.file_id, - AstPtr::new(&scrut_expr), - ), - uncovered_patterns, - } - .into(), - ); + match match_expr.expr() { + Some(scrut_expr) if match_expr.match_arm_list().is_some() => { + acc.push( + MissingMatchArms { + scrutinee_expr: InFile::new( + source_ptr.file_id, + AstPtr::new(&scrut_expr), + ), + uncovered_patterns, + } + .into(), + ); + } + _ => {} } } } @@ -1960,6 +2060,17 @@ impl Function { db.function_data(self.id).attrs.is_test() } + /// is this a `fn main` or a function with an `export_name` of `main`? + pub fn is_main(self, db: &dyn HirDatabase) -> bool { + if !self.module(db).is_crate_root() { + return false; + } + let data = db.function_data(self.id); + + data.name.to_smol_str() == "main" + || data.attrs.export_name().map(core::ops::Deref::deref) == Some("main") + } + /// Does this function have the ignore attribute? pub fn is_ignore(self, db: &dyn HirDatabase) -> bool { db.function_data(self.id).attrs.is_ignore() @@ -2926,10 +3037,10 @@ impl Local { .map(|&definition| { let src = source_map.pat_syntax(definition).unwrap(); // Hmm... let root = src.file_syntax(db.upcast()); - src.map(|ast| match ast { - // Suspicious unwrap - Either::Left(it) => Either::Left(it.cast().unwrap().to_node(&root)), - Either::Right(it) => Either::Right(it.to_node(&root)), + src.map(|ast| match ast.to_node(&root) { + Either::Left(ast::Pat::IdentPat(it)) => Either::Left(it), + Either::Left(_) => unreachable!("local with non ident-pattern"), + Either::Right(it) => Either::Right(it), }) }) .map(move |source| LocalSource { local: self, source }) @@ -3371,6 +3482,10 @@ impl Impl { db.impl_data(self.id).is_negative } + pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { + db.impl_data(self.id).is_unsafe + } + pub fn module(self, db: &dyn HirDatabase) -> Module { self.id.lookup(db.upcast()).container.into() } @@ -3379,6 +3494,10 @@ impl Impl { let src = self.source(db)?; src.file_id.as_builtin_derive_attr_node(db.upcast()) } + + pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool { + check_orphan_rules(db, self.id) + } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -4515,15 +4634,31 @@ impl Layout { Some(self.0.largest_niche?.available(&*self.1)) } - pub fn field_offset(&self, idx: usize) -> Option { + pub fn field_offset(&self, field: Field) -> Option { + match self.0.fields { + layout::FieldsShape::Primitive => None, + layout::FieldsShape::Union(_) => Some(0), + layout::FieldsShape::Array { stride, count } => { + let i = u64::try_from(field.index()).ok()?; + (i < count).then_some((stride * i).bytes()) + } + layout::FieldsShape::Arbitrary { ref offsets, .. } => { + Some(offsets.get(RustcFieldIdx(field.id))?.bytes()) + } + } + } + + pub fn tuple_field_offset(&self, field: usize) -> Option { match self.0.fields { layout::FieldsShape::Primitive => None, layout::FieldsShape::Union(_) => Some(0), layout::FieldsShape::Array { stride, count } => { - let i = u64::try_from(idx).ok()?; + let i = u64::try_from(field).ok()?; (i < count).then_some((stride * i).bytes()) } - layout::FieldsShape::Arbitrary { ref offsets, .. } => Some(offsets.get(idx)?.bytes()), + layout::FieldsShape::Arbitrary { ref offsets, .. } => { + Some(offsets.get(RustcFieldIdx::new(field))?.bytes()) + } } } diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index f29fb1edf00bf..55c2f8324c6d0 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -236,9 +236,9 @@ impl SourceAnalyzer { _db: &dyn HirDatabase, pat: &ast::IdentPat, ) -> Option { - let binding_id = self.binding_id_of_pat(pat)?; + let id = self.pat_id(&pat.clone().into())?; let infer = self.infer.as_ref()?; - infer.binding_modes.get(binding_id).map(|bm| match bm { + infer.binding_modes.get(id).map(|bm| match bm { hir_ty::BindingMode::Move => BindingMode::Move, hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut), hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => { @@ -888,7 +888,7 @@ fn scope_for_offset( .scope_by_expr() .iter() .filter_map(|(id, scope)| { - let InFile { file_id, value } = source_map.expr_syntax(*id).ok()?; + let InFile { file_id, value } = source_map.expr_syntax(id).ok()?; if from_file == file_id { return Some((value.text_range(), scope)); } @@ -923,7 +923,7 @@ fn adjust( .scope_by_expr() .iter() .filter_map(|(id, scope)| { - let source = source_map.expr_syntax(*id).ok()?; + let source = source_map.expr_syntax(id).ok()?; // FIXME: correctly handle macro expansion if source.file_id != from_file { return None; diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml index 447e38f91f43e..a622ec1a9532e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml @@ -14,8 +14,8 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" -itertools = "0.10.5" -either = "1.7.0" +itertools.workspace = true +either.workspace = true smallvec.workspace = true # local deps diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs index b273ebc85a506..fbe17dbfd7714 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs @@ -14,5 +14,6 @@ pub struct AssistConfig { pub allowed: Option>, pub insert_use: InsertUseConfig, pub prefer_no_std: bool, + pub prefer_prelude: bool, pub assist_emit_must_use: bool, } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs index c0e5429a22c9b..410c623109ea0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -2245,6 +2245,37 @@ impl b::LocalTrait for B { fn no_skip_default_2() -> Option<()> { todo!() } +} + "#, + ) + } + + #[test] + fn doc_hidden_nondefault_member() { + check_assist( + add_missing_impl_members, + r#" +//- /lib.rs crate:b new_source_root:local +trait LocalTrait { + #[doc(hidden)] + fn no_skip_non_default() -> Option<()>; + + #[doc(hidden)] + fn skip_default() -> Option<()> { + todo!() + } +} + +//- /main.rs crate:a deps:b +struct B; +impl b::Loc$0alTrait for B {} + "#, + r#" +struct B; +impl b::LocalTrait for B { + fn no_skip_non_default() -> Option<()> { + ${0:todo!()} + } } "#, ) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 3b162d7c4d82f..2374da9a343f4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -88,7 +88,13 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) .into_iter() .filter_map(|variant| { Some(( - build_pat(ctx.db(), module, variant, ctx.config.prefer_no_std)?, + build_pat( + ctx.db(), + module, + variant, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + )?, variant.should_be_hidden(ctx.db(), module.krate()), )) }) @@ -140,7 +146,13 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) .iter() .any(|variant| variant.should_be_hidden(ctx.db(), module.krate())); let patterns = variants.into_iter().filter_map(|variant| { - build_pat(ctx.db(), module, variant, ctx.config.prefer_no_std) + build_pat( + ctx.db(), + module, + variant, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) }); (ast::Pat::from(make::tuple_pat(patterns)), is_hidden) @@ -173,7 +185,13 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) .iter() .any(|variant| variant.should_be_hidden(ctx.db(), module.krate())); let patterns = variants.into_iter().filter_map(|variant| { - build_pat(ctx.db(), module, variant.clone(), ctx.config.prefer_no_std) + build_pat( + ctx.db(), + module, + variant.clone(), + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) }); (ast::Pat::from(make::slice_pat(patterns)), is_hidden) }) @@ -273,9 +291,10 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) syntax::SyntaxElement::Token(it) => { // Don't have a way to make tokens mut, so instead make the parent mut // and find the token again - let parent = edit.make_syntax_mut(it.parent().unwrap()); + let parent = + edit.make_syntax_mut(it.parent().expect("Token must have a parent.")); let mut_token = - parent.covering_element(it.text_range()).into_token().unwrap(); + parent.covering_element(it.text_range()).into_token().expect("Covering element cannot be found. Range may be beyond the current node's range"); syntax::SyntaxElement::from(mut_token) } @@ -439,28 +458,35 @@ fn build_pat( module: hir::Module, var: ExtendedVariant, prefer_no_std: bool, + prefer_prelude: bool, ) -> Option { match var { ExtendedVariant::Variant(var) => { - let path = - mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var), prefer_no_std)?); + let path = mod_path_to_ast(&module.find_use_path( + db, + ModuleDef::from(var), + prefer_no_std, + prefer_prelude, + )?); // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though - let pat: ast::Pat = match var.source(db)?.value.kind() { + Some(match var.source(db)?.value.kind() { ast::StructKind::Tuple(field_list) => { let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count()); make::tuple_struct_pat(path, pats).into() } ast::StructKind::Record(field_list) => { - let pats = field_list - .fields() - .map(|f| make::ext::simple_ident_pat(f.name().unwrap()).into()); + let pats = field_list.fields().map(|f| { + make::ext::simple_ident_pat( + f.name().expect("Record field must have a name"), + ) + .into() + }); make::record_pat(path, pats).into() } ast::StructKind::Unit => make::path_pat(path), - }; - Some(pat) + }) } ExtendedVariant::True => Some(ast::Pat::from(make::literal_pat("true"))), ExtendedVariant::False => Some(ast::Pat::from(make::literal_pat("false"))), @@ -1941,4 +1967,35 @@ fn main() { "#, ); } + + /// See [`discussion`](https://github.com/rust-lang/rust-analyzer/pull/15594#discussion_r1322960614) + #[test] + fn missing_field_name() { + check_assist( + add_missing_match_arms, + r#" +enum A { + A, + Missing { a: u32, : u32, c: u32 } +} + +fn a() { + let b = A::A; + match b$0 {} +}"#, + r#" +enum A { + A, + Missing { a: u32, : u32, c: u32 } +} + +fn a() { + let b = A::A; + match b { + $0A::A => todo!(), + A::Missing { a, u32, c } => todo!(), + } +}"#, + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs index 36f68d1767735..88fd0b1b7339b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs @@ -1,6 +1,9 @@ +use either::Either; use ide_db::defs::{Definition, NameRefClass}; -use itertools::Itertools; -use syntax::{ast, AstNode, SyntaxKind, T}; +use syntax::{ + ast::{self, make, HasArgList}, + ted, AstNode, +}; use crate::{ assist_context::{AssistContext, Assists}, @@ -25,21 +28,45 @@ use crate::{ // } // ``` pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let ident = ctx.find_token_syntax_at_offset(SyntaxKind::IDENT).or_else(|| { - let arg_list = ctx.find_node_at_offset::()?; - if arg_list.args().next().is_some() { - return None; - } - cov_mark::hit!(add_turbo_fish_after_call); - cov_mark::hit!(add_type_ascription_after_call); - arg_list.l_paren_token()?.prev_token().filter(|it| it.kind() == SyntaxKind::IDENT) - })?; - let next_token = ident.next_token()?; - if next_token.kind() == T![::] { + let turbofish_target = + ctx.find_node_at_offset::().map(Either::Left).or_else(|| { + let callable_expr = ctx.find_node_at_offset::()?; + + if callable_expr.arg_list()?.args().next().is_some() { + return None; + } + + cov_mark::hit!(add_turbo_fish_after_call); + cov_mark::hit!(add_type_ascription_after_call); + + match callable_expr { + ast::CallableExpr::Call(it) => { + let ast::Expr::PathExpr(path) = it.expr()? else { + return None; + }; + + Some(Either::Left(path.path()?.segment()?)) + } + ast::CallableExpr::MethodCall(it) => Some(Either::Right(it)), + } + })?; + + let already_has_turbofish = match &turbofish_target { + Either::Left(path_segment) => path_segment.generic_arg_list().is_some(), + Either::Right(method_call) => method_call.generic_arg_list().is_some(), + }; + + if already_has_turbofish { cov_mark::hit!(add_turbo_fish_one_fish_is_enough); return None; } - let name_ref = ast::NameRef::cast(ident.parent()?)?; + + let name_ref = match &turbofish_target { + Either::Left(path_segment) => path_segment.name_ref()?, + Either::Right(method_call) => method_call.name_ref()?, + }; + let ident = name_ref.ident_token()?; + let def = match NameRefClass::classify(&ctx.sema, &name_ref)? { NameRefClass::Definition(def) => def, NameRefClass::FieldShorthand { .. } | NameRefClass::ExternCrateShorthand { .. } => { @@ -58,20 +85,27 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti if let Some(let_stmt) = ctx.find_node_at_offset::() { if let_stmt.colon_token().is_none() { - let type_pos = let_stmt.pat()?.syntax().last_token()?.text_range().end(); - let semi_pos = let_stmt.syntax().last_token()?.text_range().end(); + if let_stmt.pat().is_none() { + return None; + } acc.add( AssistId("add_type_ascription", AssistKind::RefactorRewrite), "Add `: _` before assignment operator", ident.text_range(), - |builder| { + |edit| { + let let_stmt = edit.make_mut(let_stmt); + if let_stmt.semicolon_token().is_none() { - builder.insert(semi_pos, ";"); + ted::append_child(let_stmt.syntax(), make::tokens::semicolon()); } - match ctx.config.snippet_cap { - Some(cap) => builder.insert_snippet(cap, type_pos, ": ${0:_}"), - None => builder.insert(type_pos, ": _"), + + let placeholder_ty = make::ty_placeholder().clone_for_update(); + + let_stmt.set_ty(Some(placeholder_ty.clone())); + + if let Some(cap) = ctx.config.snippet_cap { + edit.add_placeholder_snippet(cap, placeholder_ty); } }, )? @@ -91,38 +125,46 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti AssistId("add_turbo_fish", AssistKind::RefactorRewrite), "Add `::<>`", ident.text_range(), - |builder| { - builder.trigger_signature_help(); - match ctx.config.snippet_cap { - Some(cap) => { - let fish_head = get_snippet_fish_head(number_of_arguments); - let snip = format!("::<{fish_head}>"); - builder.insert_snippet(cap, ident.text_range().end(), snip) + |edit| { + edit.trigger_signature_help(); + + let new_arg_list = match turbofish_target { + Either::Left(path_segment) => { + edit.make_mut(path_segment).get_or_create_generic_arg_list() + } + Either::Right(method_call) => { + edit.make_mut(method_call).get_or_create_generic_arg_list() } - None => { - let fish_head = std::iter::repeat("_").take(number_of_arguments).format(", "); - let snip = format!("::<{fish_head}>"); - builder.insert(ident.text_range().end(), snip); + }; + + let fish_head = get_fish_head(number_of_arguments).clone_for_update(); + + // Note: we need to replace the `new_arg_list` instead of being able to use something like + // `GenericArgList::add_generic_arg` as `PathSegment::get_or_create_generic_arg_list` + // always creates a non-turbofish form generic arg list. + ted::replace(new_arg_list.syntax(), fish_head.syntax()); + + if let Some(cap) = ctx.config.snippet_cap { + for arg in fish_head.generic_args() { + edit.add_placeholder_snippet(cap, arg) } } }, ) } -/// This will create a snippet string with tabstops marked -fn get_snippet_fish_head(number_of_arguments: usize) -> String { - let mut fish_head = (1..number_of_arguments) - .format_with("", |i, f| f(&format_args!("${{{i}:_}}, "))) - .to_string(); - - // tabstop 0 is a special case and always the last one - fish_head.push_str("${0:_}"); - fish_head +/// This will create a turbofish generic arg list corresponding to the number of arguments +fn get_fish_head(number_of_arguments: usize) -> ast::GenericArgList { + let args = (0..number_of_arguments).map(|_| make::type_arg(make::ty_placeholder()).into()); + make::turbofish_generic_arg_list(args) } #[cfg(test)] mod tests { - use crate::tests::{check_assist, check_assist_by_label, check_assist_not_applicable}; + use crate::tests::{ + check_assist, check_assist_by_label, check_assist_not_applicable, + check_assist_not_applicable_by_label, + }; use super::*; @@ -363,6 +405,20 @@ fn main() { ); } + #[test] + fn add_type_ascription_missing_pattern() { + check_assist_not_applicable_by_label( + add_turbo_fish, + r#" +fn make() -> T {} +fn main() { + let = make$0() +} +"#, + "Add `: _` before assignment operator", + ); + } + #[test] fn add_turbo_fish_function_lifetime_parameter() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs index 66bc2f6dadc3c..2d41243c20eb6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -1,7 +1,13 @@ use std::collections::VecDeque; +use ide_db::{ + assists::GroupLabel, + famous_defs::FamousDefs, + source_change::SourceChangeBuilder, + syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, +}; use syntax::{ - ast::{self, AstNode, Expr::BinExpr}, + ast::{self, make, AstNode, Expr::BinExpr, HasArgList}, ted::{self, Position}, SyntaxKind, }; @@ -89,7 +95,8 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti let dm_lhs = demorganed.lhs()?; - acc.add( + acc.add_group( + &GroupLabel("Apply De Morgan's law".to_string()), AssistId("apply_demorgan", AssistKind::RefactorRewrite), "Apply De Morgan's law", op_range, @@ -143,6 +150,127 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti ) } +// Assist: apply_demorgan_iterator +// +// Apply https://en.wikipedia.org/wiki/De_Morgan%27s_laws[De Morgan's law] to +// `Iterator::all` and `Iterator::any`. +// +// This transforms expressions of the form `!iter.any(|x| predicate(x))` into +// `iter.all(|x| !predicate(x))` and vice versa. This also works the other way for +// `Iterator::all` into `Iterator::any`. +// +// ``` +// # //- minicore: iterator +// fn main() { +// let arr = [1, 2, 3]; +// if !arr.into_iter().$0any(|num| num == 4) { +// println!("foo"); +// } +// } +// ``` +// -> +// ``` +// fn main() { +// let arr = [1, 2, 3]; +// if arr.into_iter().all(|num| num != 4) { +// println!("foo"); +// } +// } +// ``` +pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let method_call: ast::MethodCallExpr = ctx.find_node_at_offset()?; + let (name, arg_expr) = validate_method_call_expr(ctx, &method_call)?; + + let ast::Expr::ClosureExpr(closure_expr) = arg_expr else { return None }; + let closure_body = closure_expr.body()?; + + let op_range = method_call.syntax().text_range(); + let label = format!("Apply De Morgan's law to `Iterator::{}`", name.text().as_str()); + acc.add_group( + &GroupLabel("Apply De Morgan's law".to_string()), + AssistId("apply_demorgan_iterator", AssistKind::RefactorRewrite), + label, + op_range, + |edit| { + // replace the method name + let new_name = match name.text().as_str() { + "all" => make::name_ref("any"), + "any" => make::name_ref("all"), + _ => unreachable!(), + } + .clone_for_update(); + edit.replace_ast(name, new_name); + + // negate all tail expressions in the closure body + let tail_cb = &mut |e: &_| tail_cb_impl(edit, e); + walk_expr(&closure_body, &mut |expr| { + if let ast::Expr::ReturnExpr(ret_expr) = expr { + if let Some(ret_expr_arg) = &ret_expr.expr() { + for_each_tail_expr(ret_expr_arg, tail_cb); + } + } + }); + for_each_tail_expr(&closure_body, tail_cb); + + // negate the whole method call + if let Some(prefix_expr) = method_call + .syntax() + .parent() + .and_then(ast::PrefixExpr::cast) + .filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not))) + { + edit.delete( + prefix_expr + .op_token() + .expect("prefix expression always has an operator") + .text_range(), + ); + } else { + edit.insert(method_call.syntax().text_range().start(), "!"); + } + }, + ) +} + +/// Ensures that the method call is to `Iterator::all` or `Iterator::any`. +fn validate_method_call_expr( + ctx: &AssistContext<'_>, + method_call: &ast::MethodCallExpr, +) -> Option<(ast::NameRef, ast::Expr)> { + let name_ref = method_call.name_ref()?; + if name_ref.text() != "all" && name_ref.text() != "any" { + return None; + } + let arg_expr = method_call.arg_list()?.args().next()?; + + let sema = &ctx.sema; + + let receiver = method_call.receiver()?; + let it_type = sema.type_of_expr(&receiver)?.adjusted(); + let module = sema.scope(receiver.syntax())?.module(); + let krate = module.krate(); + + let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?; + it_type.impls_trait(sema.db, iter_trait, &[]).then_some((name_ref, arg_expr)) +} + +fn tail_cb_impl(edit: &mut SourceChangeBuilder, e: &ast::Expr) { + match e { + ast::Expr::BreakExpr(break_expr) => { + if let Some(break_expr_arg) = break_expr.expr() { + for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(edit, e)) + } + } + ast::Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop + } + e => { + let inverted_body = invert_boolean_expression(e.clone()); + edit.replace(e.syntax().text_range(), inverted_body.syntax().text()); + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -255,4 +383,206 @@ fn f() { !(S <= S || S < S) } "fn() { let x = a && b && c; }", ) } + + #[test] + fn demorgan_iterator_any_all_reverse() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| num $0!= 4) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().any(|num| num == 4) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_all_any() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0all(|num| num > 3) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().any(|num| num <= 3) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_multiple_terms() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0any(|num| num > 3 && num == 23 && num <= 30) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| !(num > 3 && num == 23 && num <= 30)) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_double_negation() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0all(|num| !(num > 3)) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().any(|num| num > 3) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_double_parens() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0any(|num| (num > 3 && (num == 1 || num == 2))) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| !(num > 3 && (num == 1 || num == 2))) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_multiline() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if arr + .into_iter() + .all$0(|num| !num.is_negative()) + { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [1, 2, 3]; + if !arr + .into_iter() + .any(|num| num.is_negative()) + { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_block_closure() { + check_assist( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [-1, 1, 2, 3]; + if arr.into_iter().all(|num: i32| { + $0if num.is_positive() { + num <= 3 + } else { + num >= -1 + } + }) { + println!("foo"); + } +} +"#, + r#" +fn main() { + let arr = [-1, 1, 2, 3]; + if !arr.into_iter().any(|num: i32| { + if num.is_positive() { + num > 3 + } else { + num < -1 + } + }) { + println!("foo"); + } +} +"#, + ); + } + + #[test] + fn demorgan_iterator_wrong_method() { + check_assist_not_applicable( + apply_demorgan_iterator, + r#" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0map(|num| num > 3) { + println!("foo"); + } +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs index 7acf2ea0a0de6..f508c42c53e4b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs @@ -5,7 +5,7 @@ use ide_db::{ helpers::mod_path_to_ast, imports::{ import_assets::{ImportAssets, ImportCandidate, LocatedImport}, - insert_use::{insert_use, ImportScope}, + insert_use::{insert_use, insert_use_as_alias, ImportScope}, }, }; use syntax::{ast, AstNode, NodeOrToken, SyntaxElement}; @@ -93,6 +93,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< &ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std, + ctx.config.prefer_no_std, ); if proposed_imports.is_empty() { return None; @@ -129,10 +130,12 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< for import in proposed_imports { let import_path = import.import_path; + let (assist_id, import_name) = + (AssistId("auto_import", AssistKind::QuickFix), import_path.display(ctx.db())); acc.add_group( &group_label, - AssistId("auto_import", AssistKind::QuickFix), - format!("Import `{}`", import_path.display(ctx.db())), + assist_id, + format!("Import `{}`", import_name), range, |builder| { let scope = match scope.clone() { @@ -143,6 +146,38 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< insert_use(&scope, mod_path_to_ast(&import_path), &ctx.config.insert_use); }, ); + + match import_assets.import_candidate() { + ImportCandidate::TraitAssocItem(name) | ImportCandidate::TraitMethod(name) => { + let is_method = + matches!(import_assets.import_candidate(), ImportCandidate::TraitMethod(_)); + let type_ = if is_method { "method" } else { "item" }; + let group_label = GroupLabel(format!( + "Import a trait for {} {} by alias", + type_, + name.assoc_item_name.text() + )); + acc.add_group( + &group_label, + assist_id, + format!("Import `{} as _`", import_name), + range, + |builder| { + let scope = match scope.clone() { + ImportScope::File(it) => ImportScope::File(builder.make_mut(it)), + ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)), + ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)), + }; + insert_use_as_alias( + &scope, + mod_path_to_ast(&import_path), + &ctx.config.insert_use, + ); + }, + ); + } + _ => {} + } } Some(()) } @@ -253,7 +288,8 @@ mod tests { }; use crate::tests::{ - check_assist, check_assist_not_applicable, check_assist_target, TEST_CONFIG, + check_assist, check_assist_by_label, check_assist_not_applicable, check_assist_target, + TEST_CONFIG, }; fn check_auto_import_order(before: &str, order: &[&str]) { @@ -705,7 +741,7 @@ fn main() { #[test] fn associated_trait_function() { - check_assist( + check_assist_by_label( auto_import, r" mod test_mod { @@ -739,6 +775,44 @@ fn main() { test_mod::TestStruct::test_function } ", + "Import `test_mod::TestTrait`", + ); + + check_assist_by_label( + auto_import, + r" + mod test_mod { + pub trait TestTrait { + fn test_function(); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_function() {} + } + } + + fn main() { + test_mod::TestStruct::test_function$0 + } + ", + r" + use test_mod::TestTrait as _; + + mod test_mod { + pub trait TestTrait { + fn test_function(); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_function() {} + } + } + + fn main() { + test_mod::TestStruct::test_function + } + ", + "Import `test_mod::TestTrait as _`", ); } @@ -776,7 +850,44 @@ fn main() { #[test] fn associated_trait_const() { - check_assist( + check_assist_by_label( + auto_import, + r" + mod test_mod { + pub trait TestTrait { + const TEST_CONST: u8; + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const TEST_CONST: u8 = 42; + } + } + + fn main() { + test_mod::TestStruct::TEST_CONST$0 + } + ", + r" + use test_mod::TestTrait as _; + + mod test_mod { + pub trait TestTrait { + const TEST_CONST: u8; + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const TEST_CONST: u8 = 42; + } + } + + fn main() { + test_mod::TestStruct::TEST_CONST + } + ", + "Import `test_mod::TestTrait as _`", + ); + + check_assist_by_label( auto_import, r" mod test_mod { @@ -810,6 +921,7 @@ fn main() { test_mod::TestStruct::TEST_CONST } ", + "Import `test_mod::TestTrait`", ); } @@ -847,7 +959,46 @@ fn main() { #[test] fn trait_method() { - check_assist( + check_assist_by_label( + auto_import, + r" + mod test_mod { + pub trait TestTrait { + fn test_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_method(&self) {} + } + } + + fn main() { + let test_struct = test_mod::TestStruct {}; + test_struct.test_meth$0od() + } + ", + r" + use test_mod::TestTrait as _; + + mod test_mod { + pub trait TestTrait { + fn test_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_method(&self) {} + } + } + + fn main() { + let test_struct = test_mod::TestStruct {}; + test_struct.test_method() + } + ", + "Import `test_mod::TestTrait as _`", + ); + + check_assist_by_label( auto_import, r" mod test_mod { @@ -883,12 +1034,43 @@ fn main() { test_struct.test_method() } ", + "Import `test_mod::TestTrait`", ); } #[test] fn trait_method_cross_crate() { - check_assist( + check_assist_by_label( + auto_import, + r" + //- /main.rs crate:main deps:dep + fn main() { + let test_struct = dep::test_mod::TestStruct {}; + test_struct.test_meth$0od() + } + //- /dep.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + fn test_method(&self); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_method(&self) {} + } + } + ", + r" + use dep::test_mod::TestTrait as _; + + fn main() { + let test_struct = dep::test_mod::TestStruct {}; + test_struct.test_method() + } + ", + "Import `dep::test_mod::TestTrait as _`", + ); + + check_assist_by_label( auto_import, r" //- /main.rs crate:main deps:dep @@ -915,12 +1097,41 @@ fn main() { test_struct.test_method() } ", + "Import `dep::test_mod::TestTrait`", ); } #[test] fn assoc_fn_cross_crate() { - check_assist( + check_assist_by_label( + auto_import, + r" + //- /main.rs crate:main deps:dep + fn main() { + dep::test_mod::TestStruct::test_func$0tion + } + //- /dep.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + fn test_function(); + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + fn test_function() {} + } + } + ", + r" + use dep::test_mod::TestTrait as _; + + fn main() { + dep::test_mod::TestStruct::test_function + } + ", + "Import `dep::test_mod::TestTrait as _`", + ); + + check_assist_by_label( auto_import, r" //- /main.rs crate:main deps:dep @@ -945,12 +1156,41 @@ fn main() { dep::test_mod::TestStruct::test_function } ", + "Import `dep::test_mod::TestTrait`", ); } #[test] fn assoc_const_cross_crate() { - check_assist( + check_assist_by_label( + auto_import, + r" + //- /main.rs crate:main deps:dep + fn main() { + dep::test_mod::TestStruct::CONST$0 + } + //- /dep.rs crate:dep + pub mod test_mod { + pub trait TestTrait { + const CONST: bool; + } + pub struct TestStruct {} + impl TestTrait for TestStruct { + const CONST: bool = true; + } + } + ", + r" + use dep::test_mod::TestTrait as _; + + fn main() { + dep::test_mod::TestStruct::CONST + } + ", + "Import `dep::test_mod::TestTrait as _`", + ); + + check_assist_by_label( auto_import, r" //- /main.rs crate:main deps:dep @@ -975,6 +1215,7 @@ fn main() { dep::test_mod::TestStruct::CONST } ", + "Import `dep::test_mod::TestTrait`", ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs new file mode 100644 index 0000000000000..11facc5bee2ac --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -0,0 +1,1673 @@ +use hir::ModuleDef; +use ide_db::{ + assists::{AssistId, AssistKind}, + defs::Definition, + helpers::mod_path_to_ast, + imports::insert_use::{insert_use, ImportScope}, + search::{FileReference, UsageSearchResult}, + source_change::SourceChangeBuilder, + FxHashSet, +}; +use itertools::Itertools; +use syntax::{ + ast::{ + self, + edit::IndentLevel, + edit_in_place::{AttrsOwnerEdit, Indent}, + make, HasName, + }, + ted, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, +}; +use text_edit::TextRange; + +use crate::assist_context::{AssistContext, Assists}; + +// Assist: bool_to_enum +// +// This converts boolean local variables, fields, constants, and statics into a new +// enum with two variants `Bool::True` and `Bool::False`, as well as replacing +// all assignments with the variants and replacing all usages with `== Bool::True` or +// `== Bool::False`. +// +// ``` +// fn main() { +// let $0bool = true; +// +// if bool { +// println!("foo"); +// } +// } +// ``` +// -> +// ``` +// #[derive(PartialEq, Eq)] +// enum Bool { True, False } +// +// fn main() { +// let bool = Bool::True; +// +// if bool == Bool::True { +// println!("foo"); +// } +// } +// ``` +pub(crate) fn bool_to_enum(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let BoolNodeData { target_node, name, ty_annotation, initializer, definition } = + find_bool_node(ctx)?; + let target_module = ctx.sema.scope(&target_node)?.module().nearest_non_block_module(ctx.db()); + + let target = name.syntax().text_range(); + acc.add( + AssistId("bool_to_enum", AssistKind::RefactorRewrite), + "Convert boolean to enum", + target, + |edit| { + if let Some(ty) = &ty_annotation { + cov_mark::hit!(replaces_ty_annotation); + edit.replace(ty.syntax().text_range(), "Bool"); + } + + if let Some(initializer) = initializer { + replace_bool_expr(edit, initializer); + } + + let usages = definition.usages(&ctx.sema).all(); + add_enum_def(edit, ctx, &usages, target_node, &target_module); + replace_usages(edit, ctx, &usages, definition, &target_module); + }, + ) +} + +struct BoolNodeData { + target_node: SyntaxNode, + name: ast::Name, + ty_annotation: Option, + initializer: Option, + definition: Definition, +} + +/// Attempts to find an appropriate node to apply the action to. +fn find_bool_node(ctx: &AssistContext<'_>) -> Option { + let name: ast::Name = ctx.find_node_at_offset()?; + + if let Some(let_stmt) = name.syntax().ancestors().find_map(ast::LetStmt::cast) { + let bind_pat = match let_stmt.pat()? { + ast::Pat::IdentPat(pat) => pat, + _ => { + cov_mark::hit!(not_applicable_in_non_ident_pat); + return None; + } + }; + let def = ctx.sema.to_def(&bind_pat)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_local); + return None; + } + + Some(BoolNodeData { + target_node: let_stmt.syntax().clone(), + name, + ty_annotation: let_stmt.ty(), + initializer: let_stmt.initializer(), + definition: Definition::Local(def), + }) + } else if let Some(const_) = name.syntax().parent().and_then(ast::Const::cast) { + let def = ctx.sema.to_def(&const_)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_const); + return None; + } + + Some(BoolNodeData { + target_node: const_.syntax().clone(), + name, + ty_annotation: const_.ty(), + initializer: const_.body(), + definition: Definition::Const(def), + }) + } else if let Some(static_) = name.syntax().parent().and_then(ast::Static::cast) { + let def = ctx.sema.to_def(&static_)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_static); + return None; + } + + Some(BoolNodeData { + target_node: static_.syntax().clone(), + name, + ty_annotation: static_.ty(), + initializer: static_.body(), + definition: Definition::Static(def), + }) + } else { + let field = name.syntax().parent().and_then(ast::RecordField::cast)?; + if field.name()? != name { + return None; + } + + let adt = field.syntax().ancestors().find_map(ast::Adt::cast)?; + let def = ctx.sema.to_def(&field)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_field); + return None; + } + Some(BoolNodeData { + target_node: adt.syntax().clone(), + name, + ty_annotation: field.ty(), + initializer: None, + definition: Definition::Field(def), + }) + } +} + +fn replace_bool_expr(edit: &mut SourceChangeBuilder, expr: ast::Expr) { + let expr_range = expr.syntax().text_range(); + let enum_expr = bool_expr_to_enum_expr(expr); + edit.replace(expr_range, enum_expr.syntax().text()) +} + +/// Converts an expression of type `bool` to one of the new enum type. +fn bool_expr_to_enum_expr(expr: ast::Expr) -> ast::Expr { + let true_expr = make::expr_path(make::path_from_text("Bool::True")).clone_for_update(); + let false_expr = make::expr_path(make::path_from_text("Bool::False")).clone_for_update(); + + if let ast::Expr::Literal(literal) = &expr { + match literal.kind() { + ast::LiteralKind::Bool(true) => true_expr, + ast::LiteralKind::Bool(false) => false_expr, + _ => expr, + } + } else { + make::expr_if( + expr, + make::tail_only_block_expr(true_expr), + Some(ast::ElseBranch::Block(make::tail_only_block_expr(false_expr))), + ) + .clone_for_update() + } +} + +/// Replaces all usages of the target identifier, both when read and written to. +fn replace_usages( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + target_definition: Definition, + target_module: &hir::Module, +) { + for (file_id, references) in usages.iter() { + edit.edit_file(*file_id); + + let refs_with_imports = + augment_references_with_imports(edit, ctx, references, target_module); + + refs_with_imports.into_iter().rev().for_each( + |FileReferenceWithImport { range, old_name, new_name, import_data }| { + // replace the usages in patterns and expressions + if let Some(ident_pat) = old_name.syntax().ancestors().find_map(ast::IdentPat::cast) + { + cov_mark::hit!(replaces_record_pat_shorthand); + + let definition = ctx.sema.to_def(&ident_pat).map(Definition::Local); + if let Some(def) = definition { + replace_usages( + edit, + ctx, + &def.usages(&ctx.sema).all(), + target_definition, + target_module, + ) + } + } else if let Some(initializer) = find_assignment_usage(&new_name) { + cov_mark::hit!(replaces_assignment); + + replace_bool_expr(edit, initializer); + } else if let Some((prefix_expr, inner_expr)) = find_negated_usage(&new_name) { + cov_mark::hit!(replaces_negation); + + edit.replace( + prefix_expr.syntax().text_range(), + format!("{} == Bool::False", inner_expr), + ); + } else if let Some((record_field, initializer)) = old_name + .as_name_ref() + .and_then(ast::RecordExprField::for_field_name) + .and_then(|record_field| ctx.sema.resolve_record_field(&record_field)) + .and_then(|(got_field, _, _)| { + find_record_expr_usage(&new_name, got_field, target_definition) + }) + { + cov_mark::hit!(replaces_record_expr); + + let record_field = edit.make_mut(record_field); + let enum_expr = bool_expr_to_enum_expr(initializer); + record_field.replace_expr(enum_expr); + } else if let Some(pat) = find_record_pat_field_usage(&old_name) { + match pat { + ast::Pat::IdentPat(ident_pat) => { + cov_mark::hit!(replaces_record_pat); + + let definition = ctx.sema.to_def(&ident_pat).map(Definition::Local); + if let Some(def) = definition { + replace_usages( + edit, + ctx, + &def.usages(&ctx.sema).all(), + target_definition, + target_module, + ) + } + } + ast::Pat::LiteralPat(literal_pat) => { + cov_mark::hit!(replaces_literal_pat); + + if let Some(expr) = literal_pat.literal().and_then(|literal| { + literal.syntax().ancestors().find_map(ast::Expr::cast) + }) { + replace_bool_expr(edit, expr); + } + } + _ => (), + } + } else if let Some((ty_annotation, initializer)) = find_assoc_const_usage(&new_name) + { + edit.replace(ty_annotation.syntax().text_range(), "Bool"); + replace_bool_expr(edit, initializer); + } else if let Some(receiver) = find_method_call_expr_usage(&new_name) { + edit.replace( + receiver.syntax().text_range(), + format!("({} == Bool::True)", receiver), + ); + } else if new_name.syntax().ancestors().find_map(ast::UseTree::cast).is_none() { + // for any other usage in an expression, replace it with a check that it is the true variant + if let Some((record_field, expr)) = new_name + .as_name_ref() + .and_then(ast::RecordExprField::for_field_name) + .and_then(|record_field| { + record_field.expr().map(|expr| (record_field, expr)) + }) + { + record_field.replace_expr( + make::expr_bin_op( + expr, + ast::BinaryOp::CmpOp(ast::CmpOp::Eq { negated: false }), + make::expr_path(make::path_from_text("Bool::True")), + ) + .clone_for_update(), + ); + } else { + edit.replace(range, format!("{} == Bool::True", new_name.text())); + } + } + + // add imports across modules where needed + if let Some((import_scope, path)) = import_data { + insert_use(&import_scope, path, &ctx.config.insert_use); + } + }, + ) + } +} + +struct FileReferenceWithImport { + range: TextRange, + old_name: ast::NameLike, + new_name: ast::NameLike, + import_data: Option<(ImportScope, ast::Path)>, +} + +fn augment_references_with_imports( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + references: &[FileReference], + target_module: &hir::Module, +) -> Vec { + let mut visited_modules = FxHashSet::default(); + + references + .iter() + .filter_map(|FileReference { range, name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| (*range, name, scope.module())) + }) + .map(|(range, name, ref_module)| { + let old_name = name.clone(); + let new_name = edit.make_mut(name.clone()); + + // if the referenced module is not the same as the target one and has not been seen before, add an import + let import_data = if ref_module.nearest_non_block_module(ctx.db()) != *target_module + && !visited_modules.contains(&ref_module) + { + visited_modules.insert(ref_module); + + let import_scope = + ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema); + let path = ref_module + .find_use_path_prefixed( + ctx.sema.db, + ModuleDef::Module(*target_module), + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) + .map(|mod_path| { + make::path_concat(mod_path_to_ast(&mod_path), make::path_from_text("Bool")) + }); + + import_scope.zip(path) + } else { + None + }; + + FileReferenceWithImport { range, old_name, new_name, import_data } + }) + .collect() +} + +fn find_assignment_usage(name: &ast::NameLike) -> Option { + let bin_expr = name.syntax().ancestors().find_map(ast::BinExpr::cast)?; + + if !bin_expr.lhs()?.syntax().descendants().contains(name.syntax()) { + cov_mark::hit!(dont_assign_incorrect_ref); + return None; + } + + if let Some(ast::BinaryOp::Assignment { op: None }) = bin_expr.op_kind() { + bin_expr.rhs() + } else { + None + } +} + +fn find_negated_usage(name: &ast::NameLike) -> Option<(ast::PrefixExpr, ast::Expr)> { + let prefix_expr = name.syntax().ancestors().find_map(ast::PrefixExpr::cast)?; + + if !matches!(prefix_expr.expr()?, ast::Expr::PathExpr(_) | ast::Expr::FieldExpr(_)) { + cov_mark::hit!(dont_overwrite_expression_inside_negation); + return None; + } + + if let Some(ast::UnaryOp::Not) = prefix_expr.op_kind() { + let inner_expr = prefix_expr.expr()?; + Some((prefix_expr, inner_expr)) + } else { + None + } +} + +fn find_record_expr_usage( + name: &ast::NameLike, + got_field: hir::Field, + target_definition: Definition, +) -> Option<(ast::RecordExprField, ast::Expr)> { + let name_ref = name.as_name_ref()?; + let record_field = ast::RecordExprField::for_field_name(name_ref)?; + let initializer = record_field.expr()?; + + if let Definition::Field(expected_field) = target_definition { + if got_field != expected_field { + return None; + } + } + + Some((record_field, initializer)) +} + +fn find_record_pat_field_usage(name: &ast::NameLike) -> Option { + let record_pat_field = name.syntax().parent().and_then(ast::RecordPatField::cast)?; + let pat = record_pat_field.pat()?; + + match pat { + ast::Pat::IdentPat(_) | ast::Pat::LiteralPat(_) | ast::Pat::WildcardPat(_) => Some(pat), + _ => None, + } +} + +fn find_assoc_const_usage(name: &ast::NameLike) -> Option<(ast::Type, ast::Expr)> { + let const_ = name.syntax().parent().and_then(ast::Const::cast)?; + if const_.syntax().parent().and_then(ast::AssocItemList::cast).is_none() { + return None; + } + + Some((const_.ty()?, const_.body()?)) +} + +fn find_method_call_expr_usage(name: &ast::NameLike) -> Option { + let method_call = name.syntax().ancestors().find_map(ast::MethodCallExpr::cast)?; + let receiver = method_call.receiver()?; + + if !receiver.syntax().descendants().contains(name.syntax()) { + return None; + } + + Some(receiver) +} + +/// Adds the definition of the new enum before the target node. +fn add_enum_def( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + target_node: SyntaxNode, + target_module: &hir::Module, +) { + let make_enum_pub = usages + .iter() + .flat_map(|(_, refs)| refs) + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| scope.module()) + }) + .any(|module| module.nearest_non_block_module(ctx.db()) != *target_module); + let enum_def = make_bool_enum(make_enum_pub); + + let insert_before = node_to_insert_before(target_node); + let indent = IndentLevel::from_node(&insert_before); + enum_def.reindent_to(indent); + + ted::insert_all( + ted::Position::before(&edit.make_syntax_mut(insert_before)), + vec![ + enum_def.syntax().clone().into(), + make::tokens::whitespace(&format!("\n\n{indent}")).into(), + ], + ); +} + +/// Finds where to put the new enum definition. +/// Tries to find the ast node at the nearest module or at top-level, otherwise just +/// returns the input node. +fn node_to_insert_before(target_node: SyntaxNode) -> SyntaxNode { + target_node + .ancestors() + .take_while(|it| !matches!(it.kind(), SyntaxKind::MODULE | SyntaxKind::SOURCE_FILE)) + .filter(|it| ast::Item::can_cast(it.kind())) + .last() + .unwrap_or(target_node) +} + +fn make_bool_enum(make_pub: bool) -> ast::Enum { + let enum_def = make::enum_( + if make_pub { Some(make::visibility_pub()) } else { None }, + make::name("Bool"), + make::variant_list(vec![ + make::variant(make::name("True"), None), + make::variant(make::name("False"), None), + ]), + ) + .clone_for_update(); + + let derive_eq = make::attr_outer(make::meta_token_tree( + make::ext::ident_path("derive"), + make::token_tree( + T!['('], + vec![ + NodeOrToken::Token(make::tokens::ident("PartialEq")), + NodeOrToken::Token(make::token(T![,])), + NodeOrToken::Token(make::tokens::single_space()), + NodeOrToken::Token(make::tokens::ident("Eq")), + ], + ), + )) + .clone_for_update(); + enum_def.add_attr(derive_eq); + + enum_def +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn local_variable_with_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::True; + + if foo == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn local_variable_with_usage_negated() { + cov_mark::check!(replaces_negation); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if !foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::True; + + if foo == Bool::False { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn local_variable_with_type_annotation() { + cov_mark::check!(replaces_ty_annotation); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo: bool = false; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo: Bool = Bool::False; +} +"#, + ) + } + + #[test] + fn local_variable_with_non_literal_initializer() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = 1 == 2; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = if 1 == 2 { Bool::True } else { Bool::False }; +} +"#, + ) + } + + #[test] + fn local_variable_binexpr_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = false; + let bar = true; + + if !foo && bar { + println!("foobar"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::False; + let bar = true; + + if foo == Bool::False && bar { + println!("foobar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_unop_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if *&foo { + println!("foobar"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::True; + + if *&foo == Bool::True { + println!("foobar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_assigned_later() { + cov_mark::check!(replaces_assignment); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo: bool; + foo = true; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo: Bool; + foo = Bool::True; +} +"#, + ) + } + + #[test] + fn local_variable_does_not_apply_recursively() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + let bar = !foo; + + if bar { + println!("bar"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::True; + let bar = foo == Bool::False; + + if bar { + println!("bar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_nested_in_negation() { + cov_mark::check!(dont_overwrite_expression_inside_negation); + check_assist( + bool_to_enum, + r#" +fn main() { + if !"foo".chars().any(|c| { + let $0foo = true; + foo + }) { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + if !"foo".chars().any(|c| { + let foo = Bool::True; + foo == Bool::True + }) { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn local_variable_non_bool() { + cov_mark::check!(not_applicable_non_bool_local); + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let $0foo = 1; +} +"#, + ) + } + + #[test] + fn local_variable_cursor_not_on_ident() { + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let foo = $0true; +} +"#, + ) + } + + #[test] + fn local_variable_non_ident_pat() { + cov_mark::check!(not_applicable_in_non_ident_pat); + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let ($0foo, bar) = (true, false); +} +"#, + ) + } + + #[test] + fn field_struct_basic() { + cov_mark::check!(replaces_record_expr); + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, + baz: bool, +} + +fn main() { + let foo = Foo { bar: true, baz: false }; + + if foo.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bar: Bool, + baz: bool, +} + +fn main() { + let foo = Foo { bar: Bool::True, baz: false }; + + if foo.bar == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_enum_basic() { + cov_mark::check!(replaces_record_pat); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: baz } = foo { + if baz { + println!("foo"); + } + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: baz } = foo { + if baz == Bool::True { + println!("foo"); + } + } +} +"#, + ) + } + + #[test] + fn field_enum_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /foo.rs +pub enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn foo() { + let foo = Foo::Bar { bar: true }; +} + +//- /main.rs +use foo::Foo; + +mod foo; + +fn main() { + let foo = Foo::Bar { bar: false }; +} +"#, + r#" +//- /foo.rs +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +pub enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn foo() { + let foo = Foo::Bar { bar: Bool::True }; +} + +//- /main.rs +use foo::{Foo, Bool}; + +mod foo; + +fn main() { + let foo = Foo::Bar { bar: Bool::False }; +} +"#, + ) + } + + #[test] + fn field_enum_shorthand() { + cov_mark::check!(replaces_record_pat_shorthand); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + match foo { + Foo::Bar { bar } => { + if bar { + println!("foo"); + } + } + _ => (), + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + match foo { + Foo::Bar { bar } => { + if bar == Bool::True { + println!("foo"); + } + } + _ => (), + } +} +"#, + ) + } + + #[test] + fn field_enum_replaces_literal_patterns() { + cov_mark::check!(replaces_literal_pat); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: true } = foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: Bool::True } = foo { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_enum_keeps_wildcard_patterns() { + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: _ } = foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: _ } = foo { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_union_basic() { + check_assist( + bool_to_enum, + r#" +union Foo { + $0foo: bool, + bar: usize, +} + +fn main() { + let foo = Foo { foo: true }; + + if unsafe { foo.foo } { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +union Foo { + foo: Bool, + bar: usize, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + + if unsafe { foo.foo == Bool::True } { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_negated() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, +} + +fn main() { + let foo = Foo { bar: false }; + + if !foo.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bar: Bool, +} + +fn main() { + let foo = Foo { bar: Bool::False }; + + if foo.bar == Bool::False { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_in_mod_properly_indented() { + check_assist( + bool_to_enum, + r#" +mod foo { + struct Bar { + $0baz: bool, + } + + impl Bar { + fn new(baz: bool) -> Self { + Self { baz } + } + } +} +"#, + r#" +mod foo { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + struct Bar { + baz: Bool, + } + + impl Bar { + fn new(baz: bool) -> Self { + Self { baz: if baz { Bool::True } else { Bool::False } } + } + } +} +"#, + ) + } + + #[test] + fn field_multiple_initializations() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, + baz: bool, +} + +fn main() { + let foo1 = Foo { bar: true, baz: false }; + let foo2 = Foo { bar: false, baz: false }; + + if foo1.bar && foo2.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bar: Bool, + baz: bool, +} + +fn main() { + let foo1 = Foo { bar: Bool::True, baz: false }; + let foo2 = Foo { bar: Bool::False, baz: false }; + + if foo1.bar == Bool::True && foo2.bar == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_assigned_to_another() { + cov_mark::check!(dont_assign_incorrect_ref); + check_assist( + bool_to_enum, + r#" +struct Foo { + $0foo: bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: true }; + let mut bar = Bar { bar: true }; + + bar.bar = foo.foo; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + foo: Bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + let mut bar = Bar { bar: true }; + + bar.bar = foo.foo == Bool::True; +} +"#, + ) + } + + #[test] + fn field_initialized_with_other() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0foo: bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: true }; + let bar = Bar { bar: foo.foo }; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + foo: Bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + let bar = Bar { bar: foo.foo == Bool::True }; +} +"#, + ) + } + + #[test] + fn field_method_chain_usage() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bool: bool, +} + +fn main() { + let foo = Foo { bool: true }; + + foo.bool.then(|| 2); +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bool: Bool, +} + +fn main() { + let foo = Foo { bool: Bool::True }; + + (foo.bool == Bool::True).then(|| 2); +} +"#, + ) + } + + #[test] + fn field_non_bool() { + cov_mark::check!(not_applicable_non_bool_field); + check_assist_not_applicable( + bool_to_enum, + r#" +struct Foo { + $0bar: usize, +} + +fn main() { + let foo = Foo { bar: 1 }; +} +"#, + ) + } + + #[test] + fn const_basic() { + check_assist( + bool_to_enum, + r#" +const $0FOO: bool = false; + +fn main() { + if FOO { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +const FOO: Bool = Bool::False; + +fn main() { + if FOO == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn const_in_module() { + check_assist( + bool_to_enum, + r#" +fn main() { + if foo::FOO { + println!("foo"); + } +} + +mod foo { + pub const $0FOO: bool = true; +} +"#, + r#" +use foo::Bool; + +fn main() { + if foo::FOO == Bool::True { + println!("foo"); + } +} + +mod foo { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const FOO: Bool = Bool::True; +} +"#, + ) + } + + #[test] + fn const_in_module_with_import() { + check_assist( + bool_to_enum, + r#" +fn main() { + use foo::FOO; + + if FOO { + println!("foo"); + } +} + +mod foo { + pub const $0FOO: bool = true; +} +"#, + r#" +use crate::foo::Bool; + +fn main() { + use foo::FOO; + + if FOO == Bool::True { + println!("foo"); + } +} + +mod foo { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const FOO: Bool = Bool::True; +} +"#, + ) + } + + #[test] + fn const_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +fn main() { + if foo::FOO { + println!("foo"); + } +} + +//- /foo.rs +pub const $0FOO: bool = true; +"#, + r#" +//- /main.rs +use foo::Bool; + +mod foo; + +fn main() { + if foo::FOO == Bool::True { + println!("foo"); + } +} + +//- /foo.rs +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +pub const FOO: Bool = Bool::True; +"#, + ) + } + + #[test] + fn const_cross_file_and_module() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +fn main() { + use foo::bar; + + if bar::BAR { + println!("foo"); + } +} + +//- /foo.rs +pub mod bar { + pub const $0BAR: bool = false; +} +"#, + r#" +//- /main.rs +use crate::foo::bar::Bool; + +mod foo; + +fn main() { + use foo::bar; + + if bar::BAR == Bool::True { + println!("foo"); + } +} + +//- /foo.rs +pub mod bar { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const BAR: Bool = Bool::False; +} +"#, + ) + } + + #[test] + fn const_in_impl_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +struct Foo; + +impl Foo { + pub const $0BOOL: bool = true; +} + +//- /foo.rs +use crate::Foo; + +fn foo() -> bool { + Foo::BOOL +} +"#, + r#" +//- /main.rs +mod foo; + +struct Foo; + +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +impl Foo { + pub const BOOL: Bool = Bool::True; +} + +//- /foo.rs +use crate::{Foo, Bool}; + +fn foo() -> bool { + Foo::BOOL == Bool::True +} +"#, + ) + } + + #[test] + fn const_in_trait() { + check_assist( + bool_to_enum, + r#" +trait Foo { + const $0BOOL: bool; +} + +impl Foo for usize { + const BOOL: bool = true; +} + +fn main() { + if ::BOOL { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +trait Foo { + const BOOL: Bool; +} + +impl Foo for usize { + const BOOL: Bool = Bool::True; +} + +fn main() { + if ::BOOL == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn const_non_bool() { + cov_mark::check!(not_applicable_non_bool_const); + check_assist_not_applicable( + bool_to_enum, + r#" +const $0FOO: &str = "foo"; + +fn main() { + println!("{FOO}"); +} +"#, + ) + } + + #[test] + fn static_basic() { + check_assist( + bool_to_enum, + r#" +static mut $0BOOL: bool = true; + +fn main() { + unsafe { BOOL = false }; + if unsafe { BOOL } { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +static mut BOOL: Bool = Bool::True; + +fn main() { + unsafe { BOOL = Bool::False }; + if unsafe { BOOL == Bool::True } { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn static_non_bool() { + cov_mark::check!(not_applicable_non_bool_static); + check_assist_not_applicable( + bool_to_enum, + r#" +static mut $0FOO: usize = 0; + +fn main() { + if unsafe { FOO } == 0 { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn not_applicable_to_other_names() { + check_assist_not_applicable(bool_to_enum, "fn $0main() {}") + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs index 1acd5ee97283f..3f478ee7d39ad 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -25,9 +25,7 @@ pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext<'_>) let comment = ctx.find_token_at_offset::()?; // Only allow comments which are alone on their line if let Some(prev) = comment.syntax().prev_token() { - if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { - return None; - } + Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?; } match comment.kind().shape { @@ -78,7 +76,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { // Establish the target of our edit based on the comments we found let target = TextRange::new( comments[0].syntax().text_range().start(), - comments.last().unwrap().syntax().text_range().end(), + comments.last()?.syntax().text_range().end(), ); acc.add( @@ -91,8 +89,12 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { // contents of each line comment when they're put into the block comment. let indentation = IndentLevel::from_token(comment.syntax()); - let block_comment_body = - comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n"); + let block_comment_body = comments + .into_iter() + .map(|c| line_comment_text(indentation, c)) + .collect::>() + .into_iter() + .join("\n"); let block_prefix = CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix(); @@ -160,7 +162,8 @@ pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec { // // But since such comments aren't idiomatic we're okay with this. pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String { - let contents_without_prefix = comm.text().strip_prefix(comm.prefix()).unwrap(); + let text = comm.text(); + let contents_without_prefix = text.strip_prefix(comm.prefix()).unwrap_or(text); let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix); // Don't add the indentation if the line is empty diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs index 872b52c98fff2..d649f13d6ee35 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs @@ -50,7 +50,12 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) - _ => return None, }; - mod_path_to_ast(&module.find_use_path(ctx.db(), src_type_def, ctx.config.prefer_no_std)?) + mod_path_to_ast(&module.find_use_path( + ctx.db(), + src_type_def, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + )?) }; let dest_type = match &ast_trait { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index 7d0e424769eca..73ba3f5c4cdc8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs @@ -51,22 +51,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' // Check if there is an IfLet that we can handle. let (if_let_pat, cond_expr) = if is_pattern_cond(cond.clone()) { let let_ = single_let(cond)?; - match let_.pat() { - Some(ast::Pat::TupleStructPat(pat)) if pat.fields().count() == 1 => { - let path = pat.path()?; - if path.qualifier().is_some() { - return None; - } - - let bound_ident = pat.fields().next()?; - if !ast::IdentPat::can_cast(bound_ident.syntax().kind()) { - return None; - } - - (Some((path, bound_ident)), let_.expr()?) - } - _ => return None, // Unsupported IfLet. - } + (Some(let_.pat()?), let_.expr()?) } else { (None, cond) }; @@ -136,11 +121,10 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' }; new_expr.syntax().clone_for_update() } - Some((path, bound_ident)) => { + Some(pat) => { // If-let. - let pat = make::tuple_struct_pat(path, once(bound_ident)); let let_else_stmt = make::let_else_stmt( - pat.into(), + pat, None, cond_expr, ast::make::tail_only_block_expr(early_expression), @@ -442,6 +426,60 @@ fn main() { ); } + #[test] + fn convert_arbitrary_if_let_patterns() { + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let None = Some(92) { + foo(); + } +} +"#, + r#" +fn main() { + let None = Some(92) else { return }; + foo(); +} +"#, + ); + + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let [1, x] = [1, 92] { + foo(x); + } +} +"#, + r#" +fn main() { + let [1, x] = [1, 92] else { return }; + foo(x); +} +"#, + ); + + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let (Some(x), None) = (Some(92), None) { + foo(x); + } +} +"#, + r#" +fn main() { + let (Some(x), None) = (Some(92), None) else { return }; + foo(x); +} +"#, + ); + } + #[test] fn ignore_already_converted_if() { check_assist_not_applicable( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs new file mode 100644 index 0000000000000..1f3caa7db33f1 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs @@ -0,0 +1,887 @@ +use either::Either; +use hir::ModuleDef; +use ide_db::{ + assists::{AssistId, AssistKind}, + defs::Definition, + helpers::mod_path_to_ast, + imports::insert_use::{insert_use, ImportScope}, + search::{FileReference, UsageSearchResult}, + source_change::SourceChangeBuilder, + syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, + FxHashSet, +}; +use syntax::{ + ast::{self, edit::IndentLevel, edit_in_place::Indent, make, HasName}, + match_ast, ted, AstNode, SyntaxNode, +}; + +use crate::assist_context::{AssistContext, Assists}; + +// Assist: convert_tuple_return_type_to_struct +// +// This converts the return type of a function from a tuple type +// into a tuple struct and updates the body accordingly. +// +// ``` +// fn bar() { +// let (a, b, c) = foo(); +// } +// +// fn foo() -> ($0u32, u32, u32) { +// (1, 2, 3) +// } +// ``` +// -> +// ``` +// fn bar() { +// let FooResult(a, b, c) = foo(); +// } +// +// struct FooResult(u32, u32, u32); +// +// fn foo() -> FooResult { +// FooResult(1, 2, 3) +// } +// ``` +pub(crate) fn convert_tuple_return_type_to_struct( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let ret_type = ctx.find_node_at_offset::()?; + let type_ref = ret_type.ty()?; + + let ast::Type::TupleType(tuple_ty) = &type_ref else { return None }; + if tuple_ty.fields().any(|field| matches!(field, ast::Type::ImplTraitType(_))) { + return None; + } + + let fn_ = ret_type.syntax().parent().and_then(ast::Fn::cast)?; + let fn_def = ctx.sema.to_def(&fn_)?; + let fn_name = fn_.name()?; + let target_module = ctx.sema.scope(fn_.syntax())?.module().nearest_non_block_module(ctx.db()); + + let target = type_ref.syntax().text_range(); + acc.add( + AssistId("convert_tuple_return_type_to_struct", AssistKind::RefactorRewrite), + "Convert tuple return type to tuple struct", + target, + move |edit| { + let ret_type = edit.make_mut(ret_type); + let fn_ = edit.make_mut(fn_); + + let usages = Definition::Function(fn_def).usages(&ctx.sema).all(); + let struct_name = format!("{}Result", stdx::to_camel_case(&fn_name.to_string())); + let parent = fn_.syntax().ancestors().find_map(>::cast); + add_tuple_struct_def( + edit, + ctx, + &usages, + parent.as_ref().map(|it| it.syntax()).unwrap_or(fn_.syntax()), + tuple_ty, + &struct_name, + &target_module, + ); + + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty(&struct_name)).syntax().clone_for_update(), + ); + + if let Some(fn_body) = fn_.body() { + replace_body_return_values(ast::Expr::BlockExpr(fn_body), &struct_name); + } + + replace_usages(edit, ctx, &usages, &struct_name, &target_module); + }, + ) +} + +/// Replaces tuple usages with the corresponding tuple struct pattern. +fn replace_usages( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + struct_name: &str, + target_module: &hir::Module, +) { + for (file_id, references) in usages.iter() { + edit.edit_file(*file_id); + + let refs_with_imports = + augment_references_with_imports(edit, ctx, references, struct_name, target_module); + + refs_with_imports.into_iter().rev().for_each(|(name, import_data)| { + if let Some(fn_) = name.syntax().parent().and_then(ast::Fn::cast) { + cov_mark::hit!(replace_trait_impl_fns); + + if let Some(ret_type) = fn_.ret_type() { + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty(struct_name)).syntax().clone_for_update(), + ); + } + + if let Some(fn_body) = fn_.body() { + replace_body_return_values(ast::Expr::BlockExpr(fn_body), struct_name); + } + } else { + // replace tuple patterns + let pats = name + .syntax() + .ancestors() + .find(|node| { + ast::CallExpr::can_cast(node.kind()) + || ast::MethodCallExpr::can_cast(node.kind()) + }) + .and_then(|node| node.parent()) + .and_then(node_to_pats) + .unwrap_or(Vec::new()); + + let tuple_pats = pats.iter().filter_map(|pat| match pat { + ast::Pat::TuplePat(tuple_pat) => Some(tuple_pat), + _ => None, + }); + for tuple_pat in tuple_pats { + ted::replace( + tuple_pat.syntax(), + make::tuple_struct_pat( + make::path_from_text(struct_name), + tuple_pat.fields(), + ) + .clone_for_update() + .syntax(), + ); + } + } + // add imports across modules where needed + if let Some((import_scope, path)) = import_data { + insert_use(&import_scope, path, &ctx.config.insert_use); + } + }) + } +} + +fn node_to_pats(node: SyntaxNode) -> Option> { + match_ast! { + match node { + ast::LetStmt(it) => it.pat().map(|pat| vec![pat]), + ast::LetExpr(it) => it.pat().map(|pat| vec![pat]), + ast::MatchExpr(it) => it.match_arm_list().map(|arm_list| { + arm_list.arms().filter_map(|arm| arm.pat()).collect() + }), + _ => None, + } + } +} + +fn augment_references_with_imports( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + references: &[FileReference], + struct_name: &str, + target_module: &hir::Module, +) -> Vec<(ast::NameLike, Option<(ImportScope, ast::Path)>)> { + let mut visited_modules = FxHashSet::default(); + + references + .iter() + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| (name, scope.module())) + }) + .map(|(name, ref_module)| { + let new_name = edit.make_mut(name.clone()); + + // if the referenced module is not the same as the target one and has not been seen before, add an import + let import_data = if ref_module.nearest_non_block_module(ctx.db()) != *target_module + && !visited_modules.contains(&ref_module) + { + visited_modules.insert(ref_module); + + let import_scope = + ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema); + let path = ref_module + .find_use_path_prefixed( + ctx.sema.db, + ModuleDef::Module(*target_module), + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) + .map(|mod_path| { + make::path_concat( + mod_path_to_ast(&mod_path), + make::path_from_text(struct_name), + ) + }); + + import_scope.zip(path) + } else { + None + }; + + (new_name, import_data) + }) + .collect() +} + +// Adds the definition of the tuple struct before the parent function. +fn add_tuple_struct_def( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + parent: &SyntaxNode, + tuple_ty: &ast::TupleType, + struct_name: &str, + target_module: &hir::Module, +) { + let make_struct_pub = usages + .iter() + .flat_map(|(_, refs)| refs) + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| scope.module()) + }) + .any(|module| module.nearest_non_block_module(ctx.db()) != *target_module); + let visibility = if make_struct_pub { Some(make::visibility_pub()) } else { None }; + + let field_list = ast::FieldList::TupleFieldList(make::tuple_field_list( + tuple_ty.fields().map(|ty| make::tuple_field(visibility.clone(), ty)), + )); + let struct_name = make::name(struct_name); + let struct_def = make::struct_(visibility, struct_name, None, field_list).clone_for_update(); + + let indent = IndentLevel::from_node(parent); + struct_def.reindent_to(indent); + + edit.insert(parent.text_range().start(), format!("{struct_def}\n\n{indent}")); +} + +/// Replaces each returned tuple in `body` with the constructor of the tuple struct named `struct_name`. +fn replace_body_return_values(body: ast::Expr, struct_name: &str) { + let mut exprs_to_wrap = Vec::new(); + + let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e); + walk_expr(&body, &mut |expr| { + if let ast::Expr::ReturnExpr(ret_expr) = expr { + if let Some(ret_expr_arg) = &ret_expr.expr() { + for_each_tail_expr(ret_expr_arg, tail_cb); + } + } + }); + for_each_tail_expr(&body, tail_cb); + + for ret_expr in exprs_to_wrap { + if let ast::Expr::TupleExpr(tuple_expr) = &ret_expr { + let struct_constructor = make::expr_call( + make::expr_path(make::ext::ident_path(struct_name)), + make::arg_list(tuple_expr.fields()), + ) + .clone_for_update(); + ted::replace(ret_expr.syntax(), struct_constructor.syntax()); + } + } +} + +fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { + match e { + ast::Expr::BreakExpr(break_expr) => { + if let Some(break_expr_arg) = break_expr.expr() { + for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) + } + } + ast::Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop + } + e => acc.push(e.clone()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn function_basic() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(&'static str, bool) { + ("bar", true) +} +"#, + r#" +struct BarResult(&'static str, bool); + +fn bar() -> BarResult { + BarResult("bar", true) +} +"#, + ) + } + + #[test] + fn struct_and_usages_indented() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +mod foo { + pub(crate) fn foo() { + let (bar, baz) = bar(); + println!("{bar} {baz}"); + } + + pub(crate) fn bar() -> $0(usize, bool) { + (42, true) + } +} +"#, + r#" +mod foo { + pub(crate) fn foo() { + let BarResult(bar, baz) = bar(); + println!("{bar} {baz}"); + } + + struct BarResult(usize, bool); + + pub(crate) fn bar() -> BarResult { + BarResult(42, true) + } +} +"#, + ) + } + + #[test] + fn field_usage() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + let bar_result = bar(); + println!("{} {}", bar_result.1, bar().0); +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + let bar_result = bar(); + println!("{} {}", bar_result.1, bar().0); +} +"#, + ) + } + + #[test] + fn method_usage() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Foo; + +impl Foo { + fn foo(&self, x: usize) -> $0(usize, usize) { + (x, x) + } +} + +fn main() { + let foo = Foo {}; + let (x, y) = foo.foo(2); +} +"#, + r#" +struct Foo; + +struct FooResult(usize, usize); + +impl Foo { + fn foo(&self, x: usize) -> FooResult { + FooResult(x, x) + } +} + +fn main() { + let foo = Foo {}; + let FooResult(x, y) = foo.foo(2); +} +"#, + ) + } + + #[test] + fn method_usage_within_same_impl() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Foo; + +impl Foo { + fn new() -> $0(usize, usize) { + (0, 0) + } + + fn foo() { + let (mut foo1, mut foo2) = Self::new(); + } +} +"#, + r#" +struct Foo; + +struct NewResult(usize, usize); + +impl Foo { + fn new() -> NewResult { + NewResult(0, 0) + } + + fn foo() { + let NewResult(mut foo1, mut foo2) = Self::new(); + } +} +"#, + ) + } + + #[test] + fn multiple_usages() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, usize) { + (42, 24) +} + +fn main() { + let bar_result = bar(); + let (foo, b) = bar(); + let (b, baz) = bar(); + + if foo == b && b == baz { + println!("{} {}", bar_result.1, bar().0); + } +} +"#, + r#" +struct BarResult(usize, usize); + +fn bar() -> BarResult { + BarResult(42, 24) +} + +fn main() { + let bar_result = bar(); + let BarResult(foo, b) = bar(); + let BarResult(b, baz) = bar(); + + if foo == b && b == baz { + println!("{} {}", bar_result.1, bar().0); + } +} +"#, + ) + } + + #[test] + fn usage_match_tuple_pat() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + match bar() { + x if x.0 == 0 => println!("0"), + (x, false) => println!("{x}"), + (42, true) => println!("bar"), + _ => println!("foo"), + } +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + match bar() { + x if x.0 == 0 => println!("0"), + BarResult(x, false) => println!("{x}"), + BarResult(42, true) => println!("bar"), + _ => println!("foo"), + } +} +"#, + ) + } + + #[test] + fn usage_if_let_tuple_pat() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + if let (42, true) = bar() { + println!("bar") + } +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + if let BarResult(42, true) = bar() { + println!("bar") + } +} +"#, + ) + } + + #[test] + fn function_nested_outer() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + fn foo() -> (usize, bool) { + (42, true) + } + + foo() +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + fn foo() -> (usize, bool) { + (42, true) + } + + foo() +} +"#, + ) + } + + #[test] + fn function_nested_inner() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> (usize, bool) { + fn foo() -> $0(usize, bool) { + (42, true) + } + + foo() +} +"#, + r#" +fn bar() -> (usize, bool) { + struct FooResult(usize, bool); + + fn foo() -> FooResult { + FooResult(42, true) + } + + foo() +} +"#, + ) + } + + #[test] + fn trait_impl_and_usage() { + cov_mark::check!(replace_trait_impl_fns); + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Struct; + +trait Foo { + fn foo(&self) -> $0(usize, bool); +} + +impl Foo for Struct { + fn foo(&self) -> (usize, bool) { + (0, true) + } +} + +fn main() { + let s = Struct {}; + let (foo, bar) = s.foo(); + let (foo, bar) = Struct::foo(&s); + println!("{foo} {bar}"); +} +"#, + r#" +struct Struct; + +struct FooResult(usize, bool); + +trait Foo { + fn foo(&self) -> FooResult; +} + +impl Foo for Struct { + fn foo(&self) -> FooResult { + FooResult(0, true) + } +} + +fn main() { + let s = Struct {}; + let FooResult(foo, bar) = s.foo(); + let FooResult(foo, bar) = Struct::foo(&s); + println!("{foo} {bar}"); +} +"#, + ) + } + + #[test] + fn body_wraps_nested() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo() -> $0(u8, usize, u32) { + if true { + match 3 { + 0 => (1, 2, 3), + _ => return (4, 5, 6), + } + } else { + (2, 1, 3) + } +} +"#, + r#" +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + if true { + match 3 { + 0 => FooResult(1, 2, 3), + _ => return FooResult(4, 5, 6), + } + } else { + FooResult(2, 1, 3) + } +} +"#, + ) + } + + #[test] + fn body_wraps_break_and_return() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo(mut i: isize) -> (usize, $0u32, u8) { + if i < 0 { + return (0, 0, 0); + } + + loop { + if i == 2 { + println!("foo"); + break (1, 2, 3); + } + i += 1; + } +} +"#, + r#" +struct FooResult(usize, u32, u8); + +fn foo(mut i: isize) -> FooResult { + if i < 0 { + return FooResult(0, 0, 0); + } + + loop { + if i == 2 { + println!("foo"); + break FooResult(1, 2, 3); + } + i += 1; + } +} +"#, + ) + } + + #[test] + fn body_doesnt_wrap_identifier() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo() -> $0(u8, usize, u32) { + let tuple = (1, 2, 3); + tuple +} +"#, + r#" +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + let tuple = (1, 2, 3); + tuple +} +"#, + ) + } + + #[test] + fn body_doesnt_wrap_other_exprs() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar(num: usize) -> (u8, usize, u32) { + (1, num, 3) +} + +fn foo() -> $0(u8, usize, u32) { + bar(2) +} +"#, + r#" +fn bar(num: usize) -> (u8, usize, u32) { + (1, num, 3) +} + +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + bar(2) +} +"#, + ) + } + + #[test] + fn cross_file_and_module() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +//- /main.rs +mod foo; + +fn main() { + use foo::bar; + + let (bar, baz) = bar::bar(); + println!("{}", bar == baz); +} + +//- /foo.rs +pub mod bar { + pub fn bar() -> $0(usize, usize) { + (1, 3) + } +} +"#, + r#" +//- /main.rs +use crate::foo::bar::BarResult; + +mod foo; + +fn main() { + use foo::bar; + + let BarResult(bar, baz) = bar::bar(); + println!("{}", bar == baz); +} + +//- /foo.rs +pub mod bar { + pub struct BarResult(pub usize, pub usize); + + pub fn bar() -> BarResult { + BarResult(1, 3) + } +} +"#, + ) + } + + #[test] + fn does_not_replace_nested_usage() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + let ((bar1, bar2), foo) = (bar(), 3); + println!("{bar1} {bar2} {foo}"); +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + let ((bar1, bar2), foo) = (bar(), 3); + println!("{bar1} {bar2} {foo}"); +} +"#, + ) + } + + #[test] + fn function_with_non_tuple_return_type() { + check_assist_not_applicable( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0usize { + 0 +} +"#, + ) + } + + #[test] + fn function_with_impl_type() { + check_assist_not_applicable( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(impl Clone, usize) { + ("bar", 0) +} +"#, + ) + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs index f30ca2552d368..65b497e83aa2a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs @@ -3,10 +3,12 @@ use ide_db::{ defs::Definition, search::{FileReference, SearchScope, UsageSearchResult}, }; +use itertools::Itertools; use syntax::{ - ast::{self, AstNode, FieldExpr, HasName, IdentPat, MethodCallExpr}, - TextRange, + ast::{self, make, AstNode, FieldExpr, HasName, IdentPat, MethodCallExpr}, + ted, T, }; +use text_edit::TextRange; use crate::assist_context::{AssistContext, Assists, SourceChangeBuilder}; @@ -61,27 +63,36 @@ pub(crate) fn destructure_tuple_binding_impl( acc.add( AssistId("destructure_tuple_binding_in_sub_pattern", AssistKind::RefactorRewrite), "Destructure tuple in sub-pattern", - data.range, - |builder| { - edit_tuple_assignment(ctx, builder, &data, true); - edit_tuple_usages(&data, builder, ctx, true); - }, + data.ident_pat.syntax().text_range(), + |edit| destructure_tuple_edit_impl(ctx, edit, &data, true), ); } acc.add( AssistId("destructure_tuple_binding", AssistKind::RefactorRewrite), if with_sub_pattern { "Destructure tuple in place" } else { "Destructure tuple" }, - data.range, - |builder| { - edit_tuple_assignment(ctx, builder, &data, false); - edit_tuple_usages(&data, builder, ctx, false); - }, + data.ident_pat.syntax().text_range(), + |edit| destructure_tuple_edit_impl(ctx, edit, &data, false), ); Some(()) } +fn destructure_tuple_edit_impl( + ctx: &AssistContext<'_>, + edit: &mut SourceChangeBuilder, + data: &TupleData, + in_sub_pattern: bool, +) { + let assignment_edit = edit_tuple_assignment(ctx, edit, &data, in_sub_pattern); + let current_file_usages_edit = edit_tuple_usages(&data, edit, ctx, in_sub_pattern); + + assignment_edit.apply(); + if let Some(usages_edit) = current_file_usages_edit { + usages_edit.into_iter().for_each(|usage_edit| usage_edit.apply(edit)) + } +} + fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option { if ident_pat.at_token().is_some() { // Cannot destructure pattern with sub-pattern: @@ -109,7 +120,6 @@ fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option) -> Option>(); - Some(TupleData { ident_pat, range, ref_type, field_names, usages }) + Some(TupleData { ident_pat, ref_type, field_names, usages }) } fn generate_name( @@ -142,72 +152,100 @@ enum RefType { } struct TupleData { ident_pat: IdentPat, - // name: String, - range: TextRange, ref_type: Option, field_names: Vec, - // field_types: Vec, usages: Option, } fn edit_tuple_assignment( ctx: &AssistContext<'_>, - builder: &mut SourceChangeBuilder, + edit: &mut SourceChangeBuilder, data: &TupleData, in_sub_pattern: bool, -) { +) -> AssignmentEdit { + let ident_pat = edit.make_mut(data.ident_pat.clone()); + let tuple_pat = { let original = &data.ident_pat; let is_ref = original.ref_token().is_some(); let is_mut = original.mut_token().is_some(); - let fields = data.field_names.iter().map(|name| { - ast::Pat::from(ast::make::ident_pat(is_ref, is_mut, ast::make::name(name))) - }); - ast::make::tuple_pat(fields) + let fields = data + .field_names + .iter() + .map(|name| ast::Pat::from(make::ident_pat(is_ref, is_mut, make::name(name)))); + make::tuple_pat(fields).clone_for_update() }; - let add_cursor = |text: &str| { - // place cursor on first tuple item - let first_tuple = &data.field_names[0]; - text.replacen(first_tuple, &format!("$0{first_tuple}"), 1) - }; + if let Some(cap) = ctx.config.snippet_cap { + // place cursor on first tuple name + if let Some(ast::Pat::IdentPat(first_pat)) = tuple_pat.fields().next() { + edit.add_tabstop_before( + cap, + first_pat.name().expect("first ident pattern should have a name"), + ) + } + } - // with sub_pattern: keep original tuple and add subpattern: `tup @ (_0, _1)` - if in_sub_pattern { - let text = format!(" @ {tuple_pat}"); - match ctx.config.snippet_cap { - Some(cap) => { - let snip = add_cursor(&text); - builder.insert_snippet(cap, data.range.end(), snip); - } - None => builder.insert(data.range.end(), text), - }; - } else { - let text = tuple_pat.to_string(); - match ctx.config.snippet_cap { - Some(cap) => { - let snip = add_cursor(&text); - builder.replace_snippet(cap, data.range, snip); - } - None => builder.replace(data.range, text), - }; + AssignmentEdit { ident_pat, tuple_pat, in_sub_pattern } +} +struct AssignmentEdit { + ident_pat: ast::IdentPat, + tuple_pat: ast::TuplePat, + in_sub_pattern: bool, +} + +impl AssignmentEdit { + fn apply(self) { + // with sub_pattern: keep original tuple and add subpattern: `tup @ (_0, _1)` + if self.in_sub_pattern { + self.ident_pat.set_pat(Some(self.tuple_pat.into())) + } else { + ted::replace(self.ident_pat.syntax(), self.tuple_pat.syntax()) + } } } fn edit_tuple_usages( data: &TupleData, - builder: &mut SourceChangeBuilder, + edit: &mut SourceChangeBuilder, ctx: &AssistContext<'_>, in_sub_pattern: bool, -) { +) -> Option> { + let mut current_file_usages = None; + if let Some(usages) = data.usages.as_ref() { - for (file_id, refs) in usages.iter() { - builder.edit_file(*file_id); + // We need to collect edits first before actually applying them + // as mapping nodes to their mutable node versions requires an + // unmodified syntax tree. + // + // We also defer editing usages in the current file first since + // tree mutation in the same file breaks when `builder.edit_file` + // is called + + if let Some((_, refs)) = usages.iter().find(|(file_id, _)| **file_id == ctx.file_id()) { + current_file_usages = Some( + refs.iter() + .filter_map(|r| edit_tuple_usage(ctx, edit, r, data, in_sub_pattern)) + .collect_vec(), + ); + } - for r in refs { - edit_tuple_usage(ctx, builder, r, data, in_sub_pattern); + for (file_id, refs) in usages.iter() { + if *file_id == ctx.file_id() { + continue; } + + edit.edit_file(*file_id); + + let tuple_edits = refs + .iter() + .filter_map(|r| edit_tuple_usage(ctx, edit, r, data, in_sub_pattern)) + .collect_vec(); + + tuple_edits.into_iter().for_each(|tuple_edit| tuple_edit.apply(edit)) } } + + current_file_usages } fn edit_tuple_usage( ctx: &AssistContext<'_>, @@ -215,25 +253,14 @@ fn edit_tuple_usage( usage: &FileReference, data: &TupleData, in_sub_pattern: bool, -) { +) -> Option { match detect_tuple_index(usage, data) { - Some(index) => edit_tuple_field_usage(ctx, builder, data, index), - None => { - if in_sub_pattern { - cov_mark::hit!(destructure_tuple_call_with_subpattern); - return; - } - - // no index access -> make invalid -> requires handling by user - // -> put usage in block comment - // - // Note: For macro invocations this might result in still valid code: - // When a macro accepts the tuple as argument, as well as no arguments at all, - // uncommenting the tuple still leaves the macro call working (see `tests::in_macro_call::empty_macro`). - // But this is an unlikely case. Usually the resulting macro call will become erroneous. - builder.insert(usage.range.start(), "/*"); - builder.insert(usage.range.end(), "*/"); + Some(index) => Some(edit_tuple_field_usage(ctx, builder, data, index)), + None if in_sub_pattern => { + cov_mark::hit!(destructure_tuple_call_with_subpattern); + return None; } + None => Some(EditTupleUsage::NoIndex(usage.range)), } } @@ -242,19 +269,47 @@ fn edit_tuple_field_usage( builder: &mut SourceChangeBuilder, data: &TupleData, index: TupleIndex, -) { +) -> EditTupleUsage { let field_name = &data.field_names[index.index]; + let field_name = make::expr_path(make::ext::ident_path(field_name)); if data.ref_type.is_some() { - let ref_data = handle_ref_field_usage(ctx, &index.field_expr); - builder.replace(ref_data.range, ref_data.format(field_name)); + let (replace_expr, ref_data) = handle_ref_field_usage(ctx, &index.field_expr); + let replace_expr = builder.make_mut(replace_expr); + EditTupleUsage::ReplaceExpr(replace_expr, ref_data.wrap_expr(field_name)) } else { - builder.replace(index.range, field_name); + let field_expr = builder.make_mut(index.field_expr); + EditTupleUsage::ReplaceExpr(field_expr.into(), field_name) + } +} +enum EditTupleUsage { + /// no index access -> make invalid -> requires handling by user + /// -> put usage in block comment + /// + /// Note: For macro invocations this might result in still valid code: + /// When a macro accepts the tuple as argument, as well as no arguments at all, + /// uncommenting the tuple still leaves the macro call working (see `tests::in_macro_call::empty_macro`). + /// But this is an unlikely case. Usually the resulting macro call will become erroneous. + NoIndex(TextRange), + ReplaceExpr(ast::Expr, ast::Expr), +} + +impl EditTupleUsage { + fn apply(self, edit: &mut SourceChangeBuilder) { + match self { + EditTupleUsage::NoIndex(range) => { + edit.insert(range.start(), "/*"); + edit.insert(range.end(), "*/"); + } + EditTupleUsage::ReplaceExpr(target_expr, replace_with) => { + ted::replace(target_expr.syntax(), replace_with.clone_for_update().syntax()) + } + } } } + struct TupleIndex { index: usize, - range: TextRange, field_expr: FieldExpr, } fn detect_tuple_index(usage: &FileReference, data: &TupleData) -> Option { @@ -296,7 +351,7 @@ fn detect_tuple_index(usage: &FileReference, data: &TupleData) -> Option Option String { - match (self.needs_deref, self.needs_parentheses) { - (true, true) => format!("(*{field_name})"), - (true, false) => format!("*{field_name}"), - (false, true) => format!("({field_name})"), - (false, false) => field_name.to_string(), + fn wrap_expr(&self, mut expr: ast::Expr) -> ast::Expr { + if self.needs_deref { + expr = make::expr_prefix(T![*], expr); } + + if self.needs_parentheses { + expr = make::expr_paren(expr); + } + + return expr; } } -fn handle_ref_field_usage(ctx: &AssistContext<'_>, field_expr: &FieldExpr) -> RefData { +fn handle_ref_field_usage(ctx: &AssistContext<'_>, field_expr: &FieldExpr) -> (ast::Expr, RefData) { let s = field_expr.syntax(); - let mut ref_data = - RefData { range: s.text_range(), needs_deref: true, needs_parentheses: true }; + let mut ref_data = RefData { needs_deref: true, needs_parentheses: true }; + let mut target_node = field_expr.clone().into(); let parent = match s.parent().map(ast::Expr::cast) { Some(Some(parent)) => parent, Some(None) => { ref_data.needs_parentheses = false; - return ref_data; + return (target_node, ref_data); } - None => return ref_data, + None => return (target_node, ref_data), }; match parent { @@ -342,7 +399,7 @@ fn handle_ref_field_usage(ctx: &AssistContext<'_>, field_expr: &FieldExpr) -> Re // there might be a ref outside: `&(t.0)` -> can be removed if let Some(it) = it.syntax().parent().and_then(ast::RefExpr::cast) { ref_data.needs_deref = false; - ref_data.range = it.syntax().text_range(); + target_node = it.into(); } } ast::Expr::RefExpr(it) => { @@ -351,8 +408,8 @@ fn handle_ref_field_usage(ctx: &AssistContext<'_>, field_expr: &FieldExpr) -> Re ref_data.needs_parentheses = false; // might be surrounded by parens -> can be removed too match it.syntax().parent().and_then(ast::ParenExpr::cast) { - Some(parent) => ref_data.range = parent.syntax().text_range(), - None => ref_data.range = it.syntax().text_range(), + Some(parent) => target_node = parent.into(), + None => target_node = it.into(), }; } // higher precedence than deref `*` @@ -414,7 +471,7 @@ fn handle_ref_field_usage(ctx: &AssistContext<'_>, field_expr: &FieldExpr) -> Re } }; - ref_data + (target_node, ref_data) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs index ddc8a50ed4006..c859e98524e85 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs @@ -33,9 +33,7 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> // Only allow comments which are alone on their line if let Some(prev) = comment.syntax().prev_token() { - if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { - return None; - } + Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?; } let indentation = IndentLevel::from_token(comment.syntax()).to_string(); @@ -50,7 +48,7 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> ( TextRange::new( comments[0].syntax().text_range().start(), - comments.last().unwrap().syntax().text_range().end(), + comments.last()?.syntax().text_range().end(), ), Either::Right(comments), ) @@ -71,9 +69,11 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> .map(|l| l.strip_prefix(&indentation).unwrap_or(l)) .join("\n") } - Either::Right(comments) => { - comments.into_iter().map(|c| line_comment_text(IndentLevel(0), c)).join("\n") - } + Either::Right(comments) => comments + .into_iter() + .map(|cm| line_comment_text(IndentLevel(0), cm)) + .collect::>() + .join("\n"), }; let hashes = "#".repeat(required_hashes(&text)); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index de591cfde9499..6b48d15881523 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -163,6 +163,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op ModuleDef::from(control_flow_enum), ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std, + ctx.config.prefer_prelude, ); if let Some(mod_path) = mod_path { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs index e4f64ccc754e0..37db27a8fc022 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs @@ -384,6 +384,7 @@ fn process_references( *enum_module_def, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std, + ctx.config.prefer_prelude, ); if let Some(mut mod_path) = mod_path { mod_path.pop_segment(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 014c23197face..e7c884dcb706c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -29,22 +29,31 @@ use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; // } // ``` pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - if ctx.has_empty_selection() { - return None; - } - - let node = match ctx.covering_element() { - NodeOrToken::Node(it) => it, - NodeOrToken::Token(it) if it.kind() == COMMENT => { - cov_mark::hit!(extract_var_in_comment_is_not_applicable); + let node = if ctx.has_empty_selection() { + if let Some(expr_stmt) = ctx.find_node_at_offset::() { + expr_stmt.syntax().clone() + } else if let Some(expr) = ctx.find_node_at_offset::() { + expr.syntax().ancestors().find_map(valid_target_expr)?.syntax().clone() + } else { return None; } - NodeOrToken::Token(it) => it.parent()?, + } else { + match ctx.covering_element() { + NodeOrToken::Node(it) => it, + NodeOrToken::Token(it) if it.kind() == COMMENT => { + cov_mark::hit!(extract_var_in_comment_is_not_applicable); + return None; + } + NodeOrToken::Token(it) => it.parent()?, + } }; + let node = node.ancestors().take_while(|anc| anc.text_range() == node.text_range()).last()?; + let range = node.text_range(); + let to_extract = node .descendants() - .take_while(|it| ctx.selection_trimmed().contains_range(it.text_range())) + .take_while(|it| range.contains_range(it.text_range())) .find_map(valid_target_expr)?; let ty = ctx.sema.type_of_expr(&to_extract).map(TypeInfo::adjusted); @@ -235,6 +244,138 @@ mod tests { use super::*; + #[test] + fn test_extract_var_simple_without_select() { + check_assist( + extract_variable, + r#" +fn main() -> i32 { + if true { + 1 + } else { + 2 + }$0 +} +"#, + r#" +fn main() -> i32 { + let $0var_name = if true { + 1 + } else { + 2 + }; + var_name +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn foo() -> i32 { 1 } +fn main() { + foo();$0 +} +"#, + r#" +fn foo() -> i32 { 1 } +fn main() { + let $0foo = foo(); +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + let a = Some(2); + a.is_some();$0 +} +"#, + r#" +fn main() { + let a = Some(2); + let $0is_some = a.is_some(); +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + "hello"$0; +} +"#, + r#" +fn main() { + let $0var_name = "hello"; +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + 1 + 2$0; +} +"#, + r#" +fn main() { + let $0var_name = 1 + 2; +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + match () { + () if true => 1, + _ => 2, + };$0 +} +"#, + r#" +fn main() { + let $0var_name = match () { + () if true => 1, + _ => 2, + }; +} +"#, + ); + } + + #[test] + fn test_extract_var_unit_expr_without_select_not_applicable() { + check_assist_not_applicable( + extract_variable, + r#" +fn foo() {} +fn main() { + foo()$0; +} +"#, + ); + + check_assist_not_applicable( + extract_variable, + r#" +fn foo() { + let mut i = 3; + if i >= 0 { + i += 1; + } else { + i -= 1; + }$0 +}"#, + ); + } + #[test] fn test_extract_var_simple() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs index 81545396175ba..473c699b595c6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs @@ -58,8 +58,12 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let module = ctx.sema.to_def(&strukt)?.module(ctx.db()); let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?; - let trait_path = - module.find_use_path(ctx.db(), ModuleDef::Trait(trait_), ctx.config.prefer_no_std)?; + let trait_path = module.find_use_path( + ctx.db(), + ModuleDef::Trait(trait_), + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + )?; let field_type = field.ty()?; let field_name = field.name()?; @@ -99,8 +103,12 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<() let module = ctx.sema.to_def(&strukt)?.module(ctx.db()); let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?; - let trait_path = - module.find_use_path(ctx.db(), ModuleDef::Trait(trait_), ctx.config.prefer_no_std)?; + let trait_path = module.find_use_path( + ctx.db(), + ModuleDef::Trait(trait_), + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + )?; let field_type = field.ty()?; let target = field.syntax().text_range(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs index 5b13e01b13305..f74fc5df4bd26 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs @@ -404,7 +404,11 @@ impl FunctionBuilder { leading_ws, ret_type: fn_def.ret_type(), // PANIC: we guarantee we always create a function body with a tail expr - tail_expr: fn_def.body().unwrap().tail_expr().unwrap(), + tail_expr: fn_def + .body() + .expect("generated function should have a body") + .tail_expr() + .expect("function body should have a tail expression"), should_focus_return_type: self.should_focus_return_type, fn_def, trailing_ws, @@ -683,7 +687,7 @@ where { // This function should be only called with `Impl`, `Trait`, or `Function`, for which it's // infallible to get source ast. - let node = ctx.sema.source(def).unwrap().value; + let node = ctx.sema.source(def).expect("definition's source couldn't be found").value; let generic_params = node.generic_param_list().into_iter().flat_map(|it| it.generic_params()); let where_clauses = node.where_clause().into_iter().flat_map(|it| it.predicates()); (generic_params, where_clauses) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs new file mode 100644 index 0000000000000..cb8ef395650be --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -0,0 +1,202 @@ +use ide_db::famous_defs::FamousDefs; +use syntax::{ + ast::{self, make}, + ted, AstNode, +}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// FIXME: Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredicable case [#15581]. +// Here just leave the `index_mut` method body be same as `index` method body, user can modify it manually to meet their need. + +// Assist: generate_mut_trait_impl +// +// Adds a IndexMut impl from the `Index` trait. +// +// ``` +// # //- minicore: index +// pub enum Axis { X = 0, Y = 1, Z = 2 } +// +// impl core::ops::Index$0 for [T; 3] { +// type Output = T; +// +// fn index(&self, index: Axis) -> &Self::Output { +// &self[index as usize] +// } +// } +// ``` +// -> +// ``` +// pub enum Axis { X = 0, Y = 1, Z = 2 } +// +// $0impl core::ops::IndexMut for [T; 3] { +// fn index_mut(&mut self, index: Axis) -> &mut Self::Output { +// &self[index as usize] +// } +// } +// +// impl core::ops::Index for [T; 3] { +// type Output = T; +// +// fn index(&self, index: Axis) -> &Self::Output { +// &self[index as usize] +// } +// } +// ``` +pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let impl_def = ctx.find_node_at_offset::()?.clone_for_update(); + + let trait_ = impl_def.trait_()?; + if let ast::Type::PathType(trait_path) = trait_.clone() { + let trait_type = ctx.sema.resolve_trait(&trait_path.path()?)?; + let scope = ctx.sema.scope(trait_path.syntax())?; + if trait_type != FamousDefs(&ctx.sema, scope.krate()).core_convert_Index()? { + return None; + } + } + + // Index -> IndexMut + let index_trait = impl_def + .syntax() + .descendants() + .filter_map(ast::NameRef::cast) + .find(|it| it.text() == "Index")?; + ted::replace( + index_trait.syntax(), + make::path_segment(make::name_ref("IndexMut")).clone_for_update().syntax(), + ); + + // index -> index_mut + let trait_method_name = impl_def + .syntax() + .descendants() + .filter_map(ast::Name::cast) + .find(|it| it.text() == "index")?; + ted::replace(trait_method_name.syntax(), make::name("index_mut").clone_for_update().syntax()); + + let type_alias = impl_def.syntax().descendants().find_map(ast::TypeAlias::cast)?; + ted::remove(type_alias.syntax()); + + // &self -> &mut self + let mut_self_param = make::mut_self_param(); + let self_param: ast::SelfParam = + impl_def.syntax().descendants().find_map(ast::SelfParam::cast)?; + ted::replace(self_param.syntax(), mut_self_param.clone_for_update().syntax()); + + // &Self::Output -> &mut Self::Output + let ret_type = impl_def.syntax().descendants().find_map(ast::RetType::cast)?; + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty("&mut Self::Output")).clone_for_update().syntax(), + ); + + let fn_ = impl_def.assoc_item_list()?.assoc_items().find_map(|it| match it { + ast::AssocItem::Fn(f) => Some(f), + _ => None, + })?; + + let assoc_list = make::assoc_item_list().clone_for_update(); + assoc_list.add_item(syntax::ast::AssocItem::Fn(fn_)); + ted::replace(impl_def.assoc_item_list()?.syntax(), assoc_list.syntax()); + + let target = impl_def.syntax().text_range(); + acc.add( + AssistId("generate_mut_trait_impl", AssistKind::Generate), + "Generate `IndexMut` impl from this `Index` trait", + target, + |edit| { + edit.insert(target.start(), format!("$0{}\n\n", impl_def.to_string())); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn test_generate_mut_trait_impl() { + check_assist( + generate_mut_trait_impl, + r#" +//- minicore: index +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl core::ops::Index$0 for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#, + r#" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl core::ops::IndexMut for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl core::ops::Index for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#, + ); + + check_assist( + generate_mut_trait_impl, + r#" +//- minicore: index +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl core::ops::Index$0 for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } +} +"#, + r#" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl core::ops::IndexMut for [T; 3] where T: Copy { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + let var_name = &self[index as usize]; + var_name + } +} + +impl core::ops::Index for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } +} +"#, + ); + } + + #[test] + fn test_generate_mut_trait_impl_not_applicable() { + check_assist_not_applicable( + generate_mut_trait_impl, + r#" +pub trait Index {} + +impl Index$0 for [T; 3] {} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs index 824255e4f8e32..7bfd599660db1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs @@ -67,6 +67,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?, ctx.config.prefer_no_std, + ctx.config.prefer_prelude, )?; let expr = use_trivial_constructor( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index ffab58509b182..f8c75bdb0de1c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -224,7 +224,6 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< syntax.text_range(), |builder| { let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info); - builder.replace_ast( match call_info.node { ast::CallableExpr::Call(it) => ast::Expr::CallExpr(it), @@ -363,16 +362,22 @@ fn inline( .collect(); if function.self_param(sema.db).is_some() { - let this = || make::name_ref("this").syntax().clone_for_update().first_token().unwrap(); + let this = || { + make::name_ref("this") + .syntax() + .clone_for_update() + .first_token() + .expect("NameRef should have had a token.") + }; if let Some(self_local) = params[0].2.as_local(sema.db) { usages_for_locals(self_local) .filter_map(|FileReference { name, range, .. }| match name { ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)), _ => None, }) - .for_each(|it| { - ted::replace(it, &this()); - }) + .for_each(|usage| { + ted::replace(usage, &this()); + }); } } @@ -470,7 +475,9 @@ fn inline( } } else if let Some(stmt_list) = body.stmt_list() { ted::insert_all( - ted::Position::after(stmt_list.l_curly_token().unwrap()), + ted::Position::after( + stmt_list.l_curly_token().expect("L_CURLY for StatementList is missing."), + ), let_stmts.into_iter().map(|stmt| stmt.syntax().clone().into()).collect(), ); } @@ -481,8 +488,12 @@ fn inline( }; body.reindent_to(original_indentation); + let no_stmts = body.statements().next().is_none(); match body.tail_expr() { - Some(expr) if !is_async_fn && body.statements().next().is_none() => expr, + Some(expr) if matches!(expr, ast::Expr::ClosureExpr(_)) && no_stmts => { + make::expr_paren(expr).clone_for_update() + } + Some(expr) if !is_async_fn && no_stmts => expr, _ => match node .syntax() .parent() @@ -1471,6 +1482,31 @@ fn main() { } }); } +"#, + ); + } + + #[test] + fn inline_call_closure_body() { + check_assist( + inline_call, + r#" +fn f() -> impl Fn() -> i32 { + || 2 +} + +fn main() { + let _ = $0f()(); +} +"#, + r#" +fn f() -> impl Fn() -> i32 { + || 2 +} + +fn main() { + let _ = (|| 2)(); +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index e69d1a29677a9..49dcde75d2b31 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -96,8 +96,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) ); let parent = matches!( usage_parent, - ast::Expr::CallExpr(_) - | ast::Expr::TupleExpr(_) + ast::Expr::TupleExpr(_) | ast::Expr::ArrayExpr(_) | ast::Expr::ParenExpr(_) | ast::Expr::ForExpr(_) @@ -949,6 +948,24 @@ fn f() { let S$0 = S; S; } +"#, + ); + } + + #[test] + fn test_inline_closure() { + check_assist( + inline_local_variable, + r#" +fn main() { + let $0f = || 2; + let _ = f(); +} +"#, + r#" +fn main() { + let _ = (|| 2)(); +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs index 663df266b6f82..965e4aa786e7a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -52,9 +52,13 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) == FamousDefs(sema, scope.krate()).core_convert_Into()? { let type_call = sema.type_of_expr(&method_call.clone().into())?; - let type_call_disp = - type_call.adjusted().display_source_code(db, scope.module().into(), true).ok()?; + let adjusted_tc = type_call.adjusted(); + if adjusted_tc.contains_unknown() { + return None; + } + + let sc = adjusted_tc.display_source_code(db, scope.module().into(), true).ok()?; acc.add( AssistId("into_to_qualified_from", AssistKind::Generate), "Convert `into` to fully qualified `from`", @@ -62,7 +66,11 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) |edit| { edit.replace( method_call.syntax().text_range(), - format!("{}::from({})", type_call_disp, receiver), + if sc.chars().all(|c| c.is_alphanumeric() || c == ':') { + format!("{}::from({})", sc, receiver) + } else { + format!("<{}>::from({})", sc, receiver) + }, ); }, ); @@ -199,6 +207,66 @@ mod C { fn main() -> () { let a: A = A; let b: C::B = C::B::from(a); +}"#, + ) + } + + #[test] + fn preceding_type_qualifier() { + check_assist( + into_to_qualified_from, + r#" +//- minicore: from +impl From<(i32,i32)> for [i32;2] { + fn from(value: (i32,i32)) -> Self { + [value.0, value.1] + } +} + +fn tuple_to_array() -> [i32; 2] { + (0,1).in$0to() +}"#, + r#" +impl From<(i32,i32)> for [i32;2] { + fn from(value: (i32,i32)) -> Self { + [value.0, value.1] + } +} + +fn tuple_to_array() -> [i32; 2] { + <[i32; 2]>::from((0,1)) +}"#, + ) + } + + #[test] + fn type_with_gens() { + check_assist( + into_to_qualified_from, + r#" +//- minicore: from +struct StructA(Gen); + +impl From for StructA { + fn from(value: i32) -> Self { + StructA(value + 1) + } +} + +fn main() -> () { + let a: StructA = 3.in$0to(); +}"#, + r#" +struct StructA(Gen); + +impl From for StructA { + fn from(value: i32) -> Self { + StructA(value + 1) + } +} + +fn main() -> () { + let a: StructA = >::from(3); }"#, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs index 4bf974a5655af..ff65aac82e070 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs @@ -48,6 +48,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?, ctx.config.prefer_no_std, + ctx.config.prefer_prelude, )?; let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs index 239149dc411d6..fde46db3058e6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs @@ -37,8 +37,11 @@ use crate::{ // ``` pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let (import_assets, syntax_under_caret) = find_importable_node(ctx)?; - let mut proposed_imports = - import_assets.search_for_relative_paths(&ctx.sema, ctx.config.prefer_no_std); + let mut proposed_imports = import_assets.search_for_relative_paths( + &ctx.sema, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ); if proposed_imports.is_empty() { return None; } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs index ffc32f8049968..0281b29cd4279 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs @@ -1,4 +1,4 @@ -use syntax::{ast, AstNode}; +use syntax::{ast, AstNode, SyntaxKind, T}; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -39,7 +39,19 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) -> AssistId("remove_parentheses", AssistKind::Refactor), "Remove redundant parentheses", target, - |builder| builder.replace_ast(parens.into(), expr), + |builder| { + let prev_token = parens.syntax().first_token().and_then(|it| it.prev_token()); + let need_to_add_ws = match prev_token { + Some(it) => { + let tokens = vec![T![&], T![!], T!['('], T!['['], T!['{']]; + it.kind() != SyntaxKind::WHITESPACE && !tokens.contains(&it.kind()) + } + None => false, + }; + let expr = if need_to_add_ws { format!(" {}", expr) } else { expr.to_string() }; + + builder.replace(parens.syntax().text_range(), expr) + }, ) } @@ -49,6 +61,15 @@ mod tests { use super::*; + #[test] + fn remove_parens_space() { + check_assist( + remove_parentheses, + r#"fn f() { match$0(true) {} }"#, + r#"fn f() { match true {} }"#, + ); + } + #[test] fn remove_parens_simple() { check_assist(remove_parentheses, r#"fn f() { $0(2) + 2; }"#, r#"fn f() { 2 + 2; }"#); @@ -94,8 +115,8 @@ mod tests { check_assist(remove_parentheses, r#"fn f() { f(($02 + 2)); }"#, r#"fn f() { f(2 + 2); }"#); check_assist( remove_parentheses, - r#"fn f() { (1<2)&&$0(3>4); }"#, - r#"fn f() { (1<2)&&3>4; }"#, + r#"fn f() { (1<2) &&$0(3>4); }"#, + r#"fn f() { (1<2) && 3>4; }"#, ); } @@ -164,8 +185,8 @@ mod tests { fn remove_parens_weird_places() { check_assist( remove_parentheses, - r#"fn f() { match () { _=>$0(()) } }"#, - r#"fn f() { match () { _=>() } }"#, + r#"fn f() { match () { _ =>$0(()) } }"#, + r#"fn f() { match () { _ => () } }"#, ); check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index ac45581b7b440..69a4e748b7c5d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -82,7 +82,12 @@ pub(crate) fn replace_derive_with_manual_impl( }) .flat_map(|trait_| { current_module - .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_), ctx.config.prefer_no_std) + .find_use_path( + ctx.sema.db, + hir::ModuleDef::Trait(trait_), + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) .as_ref() .map(mod_path_to_ast) .zip(Some(trait_)) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs new file mode 100644 index 0000000000000..b1daaea1ed1b2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -0,0 +1,172 @@ +use syntax::ast::{self, AstNode}; + +use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; + +// Assist: replace_is_some_with_if_let_some +// +// Replace `if x.is_some()` with `if let Some(_tmp) = x` or `if x.is_ok()` with `if let Ok(_tmp) = x`. +// +// ``` +// fn main() { +// let x = Some(1); +// if x.is_som$0e() {} +// } +// ``` +// -> +// ``` +// fn main() { +// let x = Some(1); +// if let Some(${0:x}) = x {} +// } +// ``` +pub(crate) fn replace_is_method_with_if_let_method( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let if_expr = ctx.find_node_at_offset::()?; + + let cond = if_expr.condition()?; + let call_expr = match cond { + ast::Expr::MethodCallExpr(call) => call, + _ => return None, + }; + + let name_ref = call_expr.name_ref()?; + match name_ref.text().as_str() { + "is_some" | "is_ok" => { + let receiver = call_expr.receiver()?; + + let var_name = if let ast::Expr::PathExpr(path_expr) = receiver.clone() { + path_expr.path()?.to_string() + } else { + suggest_name::for_variable(&receiver, &ctx.sema) + }; + + let target = call_expr.syntax().text_range(); + + let (assist_id, message, text) = if name_ref.text() == "is_some" { + ("replace_is_some_with_if_let_some", "Replace `is_some` with `if let Some`", "Some") + } else { + ("replace_is_ok_with_if_let_ok", "Replace `is_ok` with `if let Ok`", "Ok") + }; + + acc.add(AssistId(assist_id, AssistKind::RefactorRewrite), message, target, |edit| { + let var_name = format!("${{0:{}}}", var_name); + let replacement = format!("let {}({}) = {}", text, var_name, receiver); + edit.replace(target, replacement); + }) + } + _ => return None, + } +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::replace_is_method_with_if_let_method; + + #[test] + fn replace_is_some_with_if_let_some_works() { + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + if x.is_som$0e() {} +} +"#, + r#" +fn main() { + let x = Some(1); + if let Some(${0:x}) = x {} +} +"#, + ); + + check_assist( + replace_is_method_with_if_let_method, + r#" +fn test() -> Option { + Some(1) +} +fn main() { + if test().is_som$0e() {} +} +"#, + r#" +fn test() -> Option { + Some(1) +} +fn main() { + if let Some(${0:test}) = test() {} +} +"#, + ); + } + + #[test] + fn replace_is_some_with_if_let_some_not_applicable() { + check_assist_not_applicable( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + if x.is_non$0e() {} +} +"#, + ); + } + + #[test] + fn replace_is_ok_with_if_let_ok_works() { + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Ok(1); + if x.is_o$0k() {} +} +"#, + r#" +fn main() { + let x = Ok(1); + if let Ok(${0:x}) = x {} +} +"#, + ); + + check_assist( + replace_is_method_with_if_let_method, + r#" +fn test() -> Result { + Ok(1) +} +fn main() { + if test().is_o$0k() {} +} +"#, + r#" +fn test() -> Result { + Ok(1) +} +fn main() { + if let Ok(${0:test}) = test() {} +} +"#, + ); + } + + #[test] + fn replace_is_ok_with_if_let_ok_not_applicable() { + check_assist_not_applicable( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Ok(1); + if x.is_e$0rr() {} +} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs index dbbc56958f1e2..f03eb6118a524 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs @@ -68,6 +68,7 @@ pub(crate) fn replace_qualified_name_with_use( module, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std, + ctx.config.prefer_prelude, ) }) .flatten(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs index b7d57f02be566..f864ee50c81da 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs @@ -55,7 +55,7 @@ pub(crate) fn toggle_ignore(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio } fn has_ignore_attribute(fn_def: &ast::Fn) -> Option { - fn_def.attrs().find(|attr| attr.path().map(|it| it.syntax().text() == "ignore") == Some(true)) + fn_def.attrs().find(|attr| attr.path().is_some_and(|it| it.syntax().text() == "ignore")) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs index dac216b69b727..52df30d9623fe 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs @@ -36,29 +36,25 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< let old_parent_range = use_.syntax().parent()?.text_range(); let new_parent = use_.syntax().parent()?; + // If possible, explain what is going to be done. + let label = match tree.path().and_then(|path| path.first_segment()) { + Some(name) => format!("Unmerge use of `{name}`"), + None => "Unmerge use".into(), + }; + let target = tree.syntax().text_range(); - acc.add( - AssistId("unmerge_use", AssistKind::RefactorRewrite), - "Unmerge use", - target, - |builder| { - let new_use = make::use_( - use_.visibility(), - make::use_tree( - path, - tree.use_tree_list(), - tree.rename(), - tree.star_token().is_some(), - ), - ) - .clone_for_update(); - - tree.remove(); - ted::insert(Position::after(use_.syntax()), new_use.syntax()); - - builder.replace(old_parent_range, new_parent.to_string()); - }, - ) + acc.add(AssistId("unmerge_use", AssistKind::RefactorRewrite), label, target, |builder| { + let new_use = make::use_( + use_.visibility(), + make::use_tree(path, tree.use_tree_list(), tree.rename(), tree.star_token().is_some()), + ) + .clone_for_update(); + + tree.remove(); + ted::insert(Position::after(use_.syntax()), new_use.syntax()); + + builder.replace(old_parent_range, new_parent.to_string()); + }) } fn resolve_full_path(tree: &ast::UseTree) -> Option { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs index e9d4e270cdcfb..0876246e90b10 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs @@ -1,3 +1,4 @@ +use ide_db::imports::insert_use::ImportScope; use syntax::{ ast::{self, make, AstNode, HasArgList}, TextRange, @@ -17,6 +18,8 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // ``` // -> // ``` +// use std::ops::Add; +// // fn main() { // 1.add(2); // } @@ -38,7 +41,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) let first_arg = args_iter.next()?; let second_arg = args_iter.next(); - _ = path.qualifier()?; + let qualifier = path.qualifier()?; let method_name = path.segment()?.name_ref()?; let res = ctx.sema.resolve_path(&path)?; @@ -76,10 +79,51 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) edit.insert(close, ")"); } edit.replace(replace_comma, format!(".{method_name}(")); + add_import(qualifier, ctx, edit); }, ) } +fn add_import( + qualifier: ast::Path, + ctx: &AssistContext<'_>, + edit: &mut ide_db::source_change::SourceChangeBuilder, +) { + if let Some(path_segment) = qualifier.segment() { + // for `` + let path_type = path_segment.qualifying_trait(); + let import = match path_type { + Some(it) => { + if let Some(path) = it.path() { + path + } else { + return; + } + } + None => qualifier, + }; + + // in case for `<_>` + if import.coloncolon_token().is_none() { + return; + } + + let scope = ide_db::imports::insert_use::ImportScope::find_insert_use_container( + import.syntax(), + &ctx.sema, + ); + + if let Some(scope) = scope { + let scope = match scope { + ImportScope::File(it) => ImportScope::File(edit.make_mut(it)), + ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)), + ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)), + }; + ide_db::imports::insert_use::insert_use(&scope, import, &ctx.config.insert_use); + } + } +} + fn needs_parens_as_receiver(expr: &ast::Expr) -> bool { // Make `(expr).dummy()` let dummy_call = make::expr_method_call( @@ -127,6 +171,8 @@ fn f() { S.f(S); }"#, //- minicore: add fn f() { ::$0add(2, 2); }"#, r#" +use core::ops::Add; + fn f() { 2.add(2); }"#, ); @@ -136,6 +182,8 @@ fn f() { 2.add(2); }"#, //- minicore: add fn f() { core::ops::Add::$0add(2, 2); }"#, r#" +use core::ops::Add; + fn f() { 2.add(2); }"#, ); @@ -179,6 +227,8 @@ impl core::ops::Deref for S { } fn f() { core::ops::Deref::$0deref(&S); }"#, r#" +use core::ops::Deref; + struct S; impl core::ops::Deref for S { type Target = S; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs index f235b554e61f4..03e6dfebebfb2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs @@ -123,10 +123,8 @@ fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) } } - Expr::ReturnExpr(ret_expr) => { - if let Some(ret_expr_arg) = &ret_expr.expr() { - for_each_tail_expr(ret_expr_arg, &mut |e| tail_cb_impl(acc, e)); - } + Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop } e => acc.push(e.clone()), } @@ -800,6 +798,24 @@ fn foo() -> i32 { ); } + #[test] + fn wrap_return_in_tail_position() { + check_assist( + unwrap_result_return_type, + r#" +//- minicore: result +fn foo(num: i32) -> $0Result { + return Ok(num) +} +"#, + r#" +fn foo(num: i32) -> i32 { + return num +} +"#, + ); + } + #[test] fn unwrap_result_return_type_simple_with_closure() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs index 61e9bcdcc5162..b68ed00f77210 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs @@ -98,10 +98,8 @@ fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) } } - Expr::ReturnExpr(ret_expr) => { - if let Some(ret_expr_arg) = &ret_expr.expr() { - for_each_tail_expr(ret_expr_arg, &mut |e| tail_cb_impl(acc, e)); - } + Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop } e => acc.push(e.clone()), } @@ -732,6 +730,24 @@ fn foo() -> Result { ); } + #[test] + fn wrap_return_in_tail_position() { + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +fn foo(num: i32) -> $0i32 { + return num +} +"#, + r#" +fn foo(num: i32) -> Result { + return Ok(num) +} +"#, + ); + } + #[test] fn wrap_return_type_in_result_simple_with_closure() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 6f973ab53eec1..e6f03214ed30d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -115,6 +115,7 @@ mod handlers { mod apply_demorgan; mod auto_import; mod bind_unused_param; + mod bool_to_enum; mod change_visibility; mod convert_bool_then; mod convert_comment_block; @@ -124,6 +125,7 @@ mod handlers { mod convert_let_else_to_match; mod convert_match_to_let_else; mod convert_nested_function_to_closure; + mod convert_tuple_return_type_to_struct; mod convert_tuple_struct_to_named_struct; mod convert_named_struct_to_tuple_struct; mod convert_to_guarded_return; @@ -158,6 +160,7 @@ mod handlers { mod generate_getter_or_setter; mod generate_impl; mod generate_is_empty_from_len; + mod generate_mut_trait_impl; mod generate_new; mod generate_delegate_methods; mod generate_trait_from_impl; @@ -193,6 +196,7 @@ mod handlers { mod replace_try_expr_with_match; mod replace_derive_with_manual_impl; mod replace_if_let_with_match; + mod replace_is_method_with_if_let_method; mod replace_method_eager_lazy; mod replace_arith_op; mod introduce_named_generic; @@ -225,8 +229,10 @@ mod handlers { add_return_type::add_return_type, add_turbo_fish::add_turbo_fish, apply_demorgan::apply_demorgan, + apply_demorgan::apply_demorgan_iterator, auto_import::auto_import, bind_unused_param::bind_unused_param, + bool_to_enum::bool_to_enum, change_visibility::change_visibility, convert_bool_then::convert_bool_then_to_if, convert_bool_then::convert_if_to_bool_then, @@ -237,6 +243,7 @@ mod handlers { convert_iter_for_each_to_for::convert_for_loop_with_for_each, convert_let_else_to_match::convert_let_else_to_match, convert_match_to_let_else::convert_match_to_let_else, + convert_tuple_return_type_to_struct::convert_tuple_return_type_to_struct, convert_named_struct_to_tuple_struct::convert_named_struct_to_tuple_struct, convert_nested_function_to_closure::convert_nested_function_to_closure, convert_to_guarded_return::convert_to_guarded_return, @@ -268,6 +275,7 @@ mod handlers { generate_function::generate_function, generate_impl::generate_impl, generate_impl::generate_trait_impl, + generate_mut_trait_impl::generate_mut_trait_impl, generate_is_empty_from_len::generate_is_empty_from_len, generate_new::generate_new, generate_trait_from_impl::generate_trait_from_impl, @@ -308,6 +316,7 @@ mod handlers { replace_derive_with_manual_impl::replace_derive_with_manual_impl, replace_if_let_with_match::replace_if_let_with_match, replace_if_let_with_match::replace_match_with_if_let, + replace_is_method_with_if_let_method::replace_is_method_with_if_let_method, replace_let_with_if_let::replace_let_with_if_let, replace_method_eager_lazy::replace_with_eager_method, replace_method_eager_lazy::replace_with_lazy_method, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index cc3e251a8f2a6..25b3d6d9da91c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -30,6 +30,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { skip_glob_imports: true, }, prefer_no_std: false, + prefer_prelude: true, assist_emit_must_use: false, }; @@ -44,6 +45,7 @@ pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig { skip_glob_imports: true, }, prefer_no_std: false, + prefer_prelude: true, assist_emit_must_use: false, }; @@ -98,6 +100,11 @@ pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) { check(assist, ra_fixture, ExpectedResult::NotApplicable, None); } +#[track_caller] +pub(crate) fn check_assist_not_applicable_by_label(assist: Handler, ra_fixture: &str, label: &str) { + check(assist, ra_fixture, ExpectedResult::NotApplicable, Some(label)); +} + /// Check assist in unresolved state. Useful to check assists for lazy computation. #[track_caller] pub(crate) fn check_assist_unresolved(assist: Handler, ra_fixture: &str) { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index dfaa53449f42d..da5822bba9c88 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -244,6 +244,30 @@ fn main() { ) } +#[test] +fn doctest_apply_demorgan_iterator() { + check_doc_test( + "apply_demorgan_iterator", + r#####" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0any(|num| num == 4) { + println!("foo"); + } +} +"#####, + r#####" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| num != 4) { + println!("foo"); + } +} +"#####, + ) +} + #[test] fn doctest_auto_import() { check_doc_test( @@ -280,6 +304,34 @@ fn some_function(x: i32) { ) } +#[test] +fn doctest_bool_to_enum() { + check_doc_test( + "bool_to_enum", + r#####" +fn main() { + let $0bool = true; + + if bool { + println!("foo"); + } +} +"#####, + r#####" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let bool = Bool::True; + + if bool == Bool::True { + println!("foo"); + } +} +"#####, + ) +} + #[test] fn doctest_change_visibility() { check_doc_test( @@ -558,6 +610,33 @@ fn main() { ) } +#[test] +fn doctest_convert_tuple_return_type_to_struct() { + check_doc_test( + "convert_tuple_return_type_to_struct", + r#####" +fn bar() { + let (a, b, c) = foo(); +} + +fn foo() -> ($0u32, u32, u32) { + (1, 2, 3) +} +"#####, + r#####" +fn bar() { + let FooResult(a, b, c) = foo(); +} + +struct FooResult(u32, u32, u32); + +fn foo() -> FooResult { + FooResult(1, 2, 3) +} +"#####, + ) +} + #[test] fn doctest_convert_tuple_struct_to_named_struct() { check_doc_test( @@ -1459,6 +1538,42 @@ impl MyStruct { ) } +#[test] +fn doctest_generate_mut_trait_impl() { + check_doc_test( + "generate_mut_trait_impl", + r#####" +//- minicore: index +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl core::ops::Index$0 for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#####, + r#####" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl core::ops::IndexMut for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl core::ops::Index for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#####, + ) +} + #[test] fn doctest_generate_new() { check_doc_test( @@ -2479,6 +2594,25 @@ fn handle(action: Action) { ) } +#[test] +fn doctest_replace_is_some_with_if_let_some() { + check_doc_test( + "replace_is_some_with_if_let_some", + r#####" +fn main() { + let x = Some(1); + if x.is_som$0e() {} +} +"#####, + r#####" +fn main() { + let x = Some(1); + if let Some(${0:x}) = x {} +} +"#####, + ) +} + #[test] fn doctest_replace_let_with_if_let() { check_doc_test( @@ -2850,6 +2984,8 @@ fn main() { mod std { pub mod ops { pub trait Add { fn add(self, _: Self) {} } impl Add for i32 {} } } "#####, r#####" +use std::ops::Add; + fn main() { 1.add(2); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index a262570d94e7d..f51e99a914e2b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -106,8 +106,18 @@ pub fn filter_assoc_items( .iter() .copied() .filter(|assoc_item| { - !(ignore_items == IgnoreAssocItems::DocHiddenAttrPresent - && assoc_item.attrs(sema.db).has_doc_hidden()) + if ignore_items == IgnoreAssocItems::DocHiddenAttrPresent + && assoc_item.attrs(sema.db).has_doc_hidden() + { + if let hir::AssocItem::Function(f) = assoc_item { + if !f.has_body(sema.db) { + return true; + } + } + return false; + } + + return true; }) // Note: This throws away items with no source. .filter_map(|assoc_item| { diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml index 092fb303668fe..60f90a41b962f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml @@ -13,7 +13,7 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" -itertools = "0.10.5" +itertools.workspace = true once_cell = "1.17.0" smallvec.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index f60ac150164c4..7d38c638a8ed5 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -626,6 +626,7 @@ fn enum_variants_with_paths( ctx.db, hir::ModuleDef::from(variant), ctx.config.prefer_no_std, + ctx.config.prefer_prelude, ) { // Variants with trivial paths are already added by the existing completion logic, // so we should avoid adding these twice diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index c5bbb7f8d755d..57e06461099e5 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -26,17 +26,17 @@ pub(crate) fn complete_dot( item.add_to(acc, ctx.db); } - if let DotAccessKind::Method { .. } = dot_access.kind { - cov_mark::hit!(test_no_struct_field_completion_for_method_call); - } else { - complete_fields( - acc, - ctx, - receiver_ty, - |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty), - |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty), - ); - } + let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. }); + + complete_fields( + acc, + ctx, + receiver_ty, + |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty), + |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty), + is_field_access, + ); + complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None)); } @@ -82,6 +82,7 @@ pub(crate) fn complete_undotted_self( ) }, |acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty), + true, ); complete_methods(ctx, &ty, |func| { acc.add_method( @@ -104,18 +105,23 @@ fn complete_fields( receiver: &hir::Type, mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type), mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type), + is_field_access: bool, ) { let mut seen_names = FxHashSet::default(); for receiver in receiver.autoderef(ctx.db) { for (field, ty) in receiver.fields(ctx.db) { - if seen_names.insert(field.name(ctx.db)) { + if seen_names.insert(field.name(ctx.db)) + && (is_field_access || ty.is_fn() || ty.is_closure()) + { named_field(acc, field, ty); } } for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() { // Tuples are always the last type in a deref chain, so just check if the name is // already seen without inserting into the hashset. - if !seen_names.contains(&hir::Name::new_tuple_field(i)) { + if !seen_names.contains(&hir::Name::new_tuple_field(i)) + && (is_field_access || ty.is_fn() || ty.is_closure()) + { // Tuple fields are always public (tuple struct fields are handled above). tuple_index(acc, i, ty); } @@ -250,7 +256,6 @@ impl A { #[test] fn test_no_struct_field_completion_for_method_call() { - cov_mark::check!(test_no_struct_field_completion_for_method_call); check( r#" struct A { the_field: u32 } @@ -1095,4 +1100,140 @@ fn test(s: S) { "#]], ); } + + #[test] + fn assoc_impl_1() { + check( + r#" +//- minicore: deref +fn main() { + let foo: Foo<&u8> = Foo::new(&42_u8); + foo.$0 +} + +trait Bar { + fn bar(&self); +} + +impl Bar for u8 { + fn bar(&self) {} +} + +struct Foo { + foo: F, +} + +impl Foo { + fn new(foo: F) -> Foo { + Foo { foo } + } +} + +impl> Foo { + fn foobar(&self) { + self.foo.deref().bar() + } +} +"#, + expect![[r#" + fd foo &u8 + me foobar() fn(&self) + "#]], + ); + } + + #[test] + fn assoc_impl_2() { + check( + r#" +//- minicore: deref +fn main() { + let foo: Foo<&u8> = Foo::new(&42_u8); + foo.$0 +} + +trait Bar { + fn bar(&self); +} + +struct Foo { + foo: F, +} + +impl Foo { + fn new(foo: F) -> Foo { + Foo { foo } + } +} + +impl> Foo { + fn foobar(&self) { + self.foo.deref().bar() + } +} +"#, + expect![[r#" + fd foo &u8 + "#]], + ); + } + + #[test] + fn test_struct_function_field_completion() { + check( + r#" +struct S { va_field: u32, fn_field: fn() } +fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() } +"#, + expect![[r#" + fd fn_field fn() + "#]], + ); + + check_edit( + "fn_field", + r#" +struct S { va_field: u32, fn_field: fn() } +fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() } +"#, + r#" +struct S { va_field: u32, fn_field: fn() } +fn foo() { (S { va_field: 0, fn_field: || {} }.fn_field)() } +"#, + ); + } + + #[test] + fn test_tuple_function_field_completion() { + check( + r#" +struct B(u32, fn()) +fn foo() { + let b = B(0, || {}); + b.$0() +} +"#, + expect![[r#" + fd 1 fn() + "#]], + ); + + check_edit( + "1", + r#" +struct B(u32, fn()) +fn foo() { + let b = B(0, || {}); + b.$0() +} +"#, + r#" +struct B(u32, fn()) +fn foo() { + let b = B(0, || {}); + (b.1)() +} +"#, + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 9daa6984c3e38..d3c817d4b43ad 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -175,6 +175,7 @@ pub(crate) fn complete_expr_path( ctx.db, hir::ModuleDef::from(strukt), ctx.config.prefer_no_std, + ctx.config.prefer_prelude, ) .filter(|it| it.len() > 1); @@ -197,6 +198,7 @@ pub(crate) fn complete_expr_path( ctx.db, hir::ModuleDef::from(un), ctx.config.prefer_no_std, + ctx.config.prefer_prelude, ) .filter(|it| it.len() > 1); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index 39c1b7f7b3fb4..d74d3b264ae5f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs @@ -13,10 +13,9 @@ use crate::{ TypeLocation, }, render::{render_resolution_with_import, render_resolution_with_import_pat, RenderContext}, + Completions, }; -use super::Completions; - // Feature: Completion With Autoimport // // When completing names in the current scope, proposes additional imports from other modules or crates, @@ -258,7 +257,12 @@ fn import_on_the_fly( let user_input_lowercased = potential_import_name.to_lowercase(); import_assets - .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std) + .search_for_imports( + &ctx.sema, + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) .into_iter() .filter(ns_filter) .filter(|import| { @@ -300,7 +304,12 @@ fn import_on_the_fly_pat_( let user_input_lowercased = potential_import_name.to_lowercase(); import_assets - .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std) + .search_for_imports( + &ctx.sema, + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) .into_iter() .filter(ns_filter) .filter(|import| { @@ -337,7 +346,12 @@ fn import_on_the_fly_method( let user_input_lowercased = potential_import_name.to_lowercase(); import_assets - .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std) + .search_for_imports( + &ctx.sema, + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) .into_iter() .filter(|import| { !ctx.is_item_hidden(&import.item_to_import) @@ -377,9 +391,12 @@ fn import_assets_for_path( &ctx.sema, ctx.token.parent()?, )?; - if fuzzy_name_length < 3 { - cov_mark::hit!(flyimport_exact_on_short_path); - assets_for_path.path_fuzzy_name_to_exact(false); + if fuzzy_name_length == 0 { + // nothing matches the empty string exactly, but we still compute assoc items in this case + assets_for_path.path_fuzzy_name_to_exact(); + } else if fuzzy_name_length < 3 { + cov_mark::hit!(flyimport_prefix_on_short_path); + assets_for_path.path_fuzzy_name_to_prefix(); } Some(assets_for_path) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs index 8f6a97e1e09d8..ed5ddde8fbfe9 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs @@ -14,10 +14,12 @@ pub struct CompletionConfig { pub enable_imports_on_the_fly: bool, pub enable_self_on_the_fly: bool, pub enable_private_editable: bool, + pub full_function_signatures: bool, pub callable: Option, pub snippet_cap: Option, pub insert_use: InsertUseConfig, pub prefer_no_std: bool, + pub prefer_prelude: bool, pub snippets: Vec, pub limit: Option, } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index c45cc8d7b37e2..99b895eed4d23 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -26,6 +26,10 @@ use crate::{ pub struct CompletionItem { /// Label in the completion pop up which identifies completion. pub label: SmolStr, + /// Additional label details in the completion pop up that are + /// displayed and aligned on the right side after the label. + pub label_detail: Option, + /// Range of identifier that is being completed. /// /// It should be used primarily for UI, but we also use this to convert @@ -89,7 +93,7 @@ impl fmt::Debug for CompletionItem { let mut s = f.debug_struct("CompletionItem"); s.field("label", &self.label).field("source_range", &self.source_range); if self.text_edit.len() == 1 { - let atom = &self.text_edit.iter().next().unwrap(); + let atom = self.text_edit.iter().next().unwrap(); s.field("delete", &atom.delete); s.field("insert", &atom.insert); } else { @@ -425,13 +429,14 @@ impl Builder { pub(crate) fn build(self, db: &RootDatabase) -> CompletionItem { let _p = profile::span("item::Builder::build"); - let mut label = self.label; + let label = self.label; + let mut label_detail = None; let mut lookup = self.lookup.unwrap_or_else(|| label.clone()); let insert_text = self.insert_text.unwrap_or_else(|| label.to_string()); if !self.doc_aliases.is_empty() { let doc_aliases = self.doc_aliases.iter().join(", "); - label = SmolStr::from(format!("{label} (alias {doc_aliases})")); + label_detail.replace(SmolStr::from(format!(" (alias {doc_aliases})"))); let lookup_doc_aliases = self .doc_aliases .iter() @@ -454,10 +459,17 @@ impl Builder { if let [import_edit] = &*self.imports_to_add { // snippets can have multiple imports, but normal completions only have up to one if let Some(original_path) = import_edit.original_path.as_ref() { - label = SmolStr::from(format!("{label} (use {})", original_path.display(db))); + label_detail.replace(SmolStr::from(format!( + "{} (use {})", + label_detail.as_deref().unwrap_or_default(), + original_path.display(db) + ))); } } else if let Some(trait_name) = self.trait_name { - label = SmolStr::from(format!("{label} (as {trait_name})")); + label_detail.replace(SmolStr::from(format!( + "{} (as {trait_name})", + label_detail.as_deref().unwrap_or_default(), + ))); } let text_edit = match self.text_edit { @@ -479,6 +491,7 @@ impl Builder { CompletionItem { source_range: self.source_range, label, + label_detail, text_edit, is_snippet: self.is_snippet, detail: self.detail, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs index 2eaa42040a019..aaf7cd7843afe 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -169,6 +169,28 @@ pub fn completions( return Some(completions.into()); } + // when the user types a bare `_` (that is it does not belong to an identifier) + // the user might just wanted to type a `_` for type inference or pattern discarding + // so try to suppress completions in those cases + if trigger_character == Some('_') && ctx.original_token.kind() == syntax::SyntaxKind::UNDERSCORE + { + if let CompletionAnalysis::NameRef(NameRefContext { + kind: + NameRefKind::Path( + path_ctx @ PathCompletionCtx { + kind: PathKind::Type { .. } | PathKind::Pat { .. }, + .. + }, + ), + .. + }) = analysis + { + if path_ctx.is_trivial_path() { + return None; + } + } + } + { let acc = &mut completions; @@ -241,6 +263,7 @@ pub fn resolve_completion_edits( candidate, config.insert_use.prefix_kind, config.prefer_no_std, + config.prefer_prelude, ) }) .find(|mod_path| mod_path.display(db).to_string() == full_import_path); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index dfe8fe7e2f7f7..048730c078d7b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -18,9 +18,10 @@ use ide_db::{ RootDatabase, SnippetCap, SymbolKind, }; use syntax::{AstNode, SmolStr, SyntaxKind, TextRange}; +use text_edit::TextEdit; use crate::{ - context::{DotAccess, PathCompletionCtx, PathKind, PatternContext}, + context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext}, item::{Builder, CompletionRelevanceTypeMatch}, render::{ function::render_fn, @@ -147,7 +148,42 @@ pub(crate) fn render_field( .set_documentation(field.docs(db)) .set_deprecated(is_deprecated) .lookup_by(name); - item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name)); + + let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. }); + if !is_field_access || ty.is_fn() || ty.is_closure() { + let mut builder = TextEdit::builder(); + // Using TextEdit, insert '(' before the struct name and ')' before the + // dot access, then comes the field name and optionally insert function + // call parens. + + builder.replace( + ctx.source_range(), + field_with_receiver(db, receiver.as_ref(), &escaped_name).into(), + ); + + let expected_fn_type = + ctx.completion.expected_type.as_ref().is_some_and(|ty| ty.is_fn() || ty.is_closure()); + + if !expected_fn_type { + if let Some(receiver) = &dot_access.receiver { + if let Some(receiver) = ctx.completion.sema.original_ast_node(receiver.clone()) { + builder.insert(receiver.syntax().text_range().start(), "(".to_string()); + builder.insert(ctx.source_range().end(), ")".to_string()); + } + } + + let is_parens_needed = + !matches!(dot_access.kind, DotAccessKind::Method { has_parens: true }); + + if is_parens_needed { + builder.insert(ctx.source_range().end(), "()".to_string()); + } + } + + item.text_edit(builder.finish()); + } else { + item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name)); + } if let Some(receiver) = &dot_access.receiver { if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) { if let Some(ref_match) = compute_ref_match(ctx.completion, ty) { @@ -557,7 +593,11 @@ mod tests { let tag = it.kind.tag(); let relevance = display_relevance(it.relevance); - items.push(format!("{tag} {} {relevance}\n", it.label)); + items.push(format!( + "{tag} {}{} {relevance}\n", + it.label, + it.label_detail.clone().unwrap_or_default(), + )); if let Some((label, _indel, relevance)) = it.ref_match() { let relevance = display_relevance(relevance); @@ -1596,7 +1636,7 @@ fn main() { fn struct_field_method_ref() { check_kinds( r#" -struct Foo { bar: u32 } +struct Foo { bar: u32, qux: fn() } impl Foo { fn baz(&self) -> u32 { 0 } } fn foo(f: Foo) { let _: &u32 = f.b$0 } @@ -1606,30 +1646,92 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } [ CompletionItem { label: "baz()", - source_range: 98..99, - delete: 98..99, + source_range: 109..110, + delete: 109..110, insert: "baz()$0", kind: Method, lookup: "baz", detail: "fn(&self) -> u32", - ref_match: "&@96", + ref_match: "&@107", }, CompletionItem { label: "bar", - source_range: 98..99, - delete: 98..99, + source_range: 109..110, + delete: 109..110, insert: "bar", kind: SymbolKind( Field, ), detail: "u32", - ref_match: "&@96", + ref_match: "&@107", + }, + CompletionItem { + label: "qux", + source_range: 109..110, + text_edit: TextEdit { + indels: [ + Indel { + insert: "(", + delete: 107..107, + }, + Indel { + insert: "qux)()", + delete: 109..110, + }, + ], + }, + kind: SymbolKind( + Field, + ), + detail: "fn()", }, ] "#]], ); } + #[test] + fn expected_fn_type_ref() { + check_kinds( + r#" +struct S { field: fn() } + +fn foo() { + let foo: fn() = S { fields: || {}}.fi$0; +} +"#, + &[CompletionItemKind::SymbolKind(SymbolKind::Field)], + expect![[r#" + [ + CompletionItem { + label: "field", + source_range: 76..78, + delete: 76..78, + insert: "field", + kind: SymbolKind( + Field, + ), + detail: "fn()", + relevance: CompletionRelevance { + exact_name_match: false, + type_match: Some( + Exact, + ), + is_local: false, + is_item_from_trait: false, + is_name_already_imported: false, + requires_import: false, + is_op_method: false, + is_private_editable: false, + postfix_match: None, + is_definite: false, + }, + }, + ] + "#]], + ) + } + #[test] fn qualified_path_ref() { check_kinds( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index 8afce8db5ea86..dfae715afe36d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -98,9 +98,14 @@ fn render( _ => (), } + let detail = if ctx.completion.config.full_function_signatures { + detail_full(db, func) + } else { + detail(db, func) + }; item.set_documentation(ctx.docs(func)) .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func)) - .detail(detail(db, func)) + .detail(detail) .lookup_by(name.unescaped().to_smol_str()); match ctx.completion.config.snippet_cap { @@ -263,6 +268,21 @@ fn detail(db: &dyn HirDatabase, func: hir::Function) -> String { detail } +fn detail_full(db: &dyn HirDatabase, func: hir::Function) -> String { + let signature = format!("{}", func.display(db)); + let mut detail = String::with_capacity(signature.len()); + + for segment in signature.split_whitespace() { + if !detail.is_empty() { + detail.push(' '); + } + + detail.push_str(segment); + } + + detail +} + fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String { if let Some(self_param) = func.self_param(db) { let assoc_fn_params = func.assoc_fn_params(db); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs index 343719c53694e..50618296ee437 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs @@ -179,6 +179,7 @@ fn import_edits(ctx: &CompletionContext<'_>, requires: &[GreenNode]) -> Option 1).then(|| LocatedImport::new(path.clone(), item, item, None))) }; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs index 2464e8d5f8175..f28afacc586ff 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs @@ -64,9 +64,11 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig { enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: false, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), prefer_no_std: false, + prefer_prelude: true, insert_use: InsertUseConfig { granularity: ImportGranularity::Crate, prefix_kind: PrefixKind::Plain, @@ -148,16 +150,29 @@ fn render_completion_list(completions: Vec) -> String { fn monospace_width(s: &str) -> usize { s.chars().count() } - let label_width = - completions.iter().map(|it| monospace_width(&it.label)).max().unwrap_or_default().min(22); + let label_width = completions + .iter() + .map(|it| { + monospace_width(&it.label) + + monospace_width(it.label_detail.as_deref().unwrap_or_default()) + }) + .max() + .unwrap_or_default() + .min(22); completions .into_iter() .map(|it| { let tag = it.kind.tag(); let var_name = format!("{tag} {}", it.label); let mut buf = var_name; + if let Some(ref label_detail) = it.label_detail { + format_to!(buf, "{label_detail}"); + } if let Some(detail) = it.detail { - let width = label_width.saturating_sub(monospace_width(&it.label)); + let width = label_width.saturating_sub( + monospace_width(&it.label) + + monospace_width(&it.label_detail.unwrap_or_default()), + ); format_to!(buf, "{:width$} {}", "", detail, width = width); } if it.deprecated { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 4cdfd546f6ad0..21f693d79f1db 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -116,19 +116,47 @@ fn main() { } #[test] -fn short_paths_are_ignored() { - cov_mark::check!(flyimport_exact_on_short_path); +fn short_paths_are_prefix_matched() { + cov_mark::check!(flyimport_prefix_on_short_path); check( r#" //- /lib.rs crate:dep -pub struct Bar; +pub struct Barc; pub struct Rcar; pub struct Rc; +pub const RC: () = (); pub mod some_module { pub struct Bar; pub struct Rcar; pub struct Rc; + pub const RC: () = (); +} + +//- /main.rs crate:main deps:dep +fn main() { + Rc$0 +} +"#, + expect![[r#" + st Rc (use dep::Rc) + st Rcar (use dep::Rcar) + st Rc (use dep::some_module::Rc) + st Rcar (use dep::some_module::Rcar) + "#]], + ); + check( + r#" +//- /lib.rs crate:dep +pub struct Barc; +pub struct Rcar; +pub struct Rc; +pub const RC: () = (); +pub mod some_module { + pub struct Bar; + pub struct Rcar; + pub struct Rc; + pub const RC: () = (); } //- /main.rs crate:main deps:dep @@ -137,8 +165,36 @@ fn main() { } "#, expect![[r#" + ct RC (use dep::RC) st Rc (use dep::Rc) + st Rcar (use dep::Rcar) + ct RC (use dep::some_module::RC) st Rc (use dep::some_module::Rc) + st Rcar (use dep::some_module::Rcar) + "#]], + ); + check( + r#" +//- /lib.rs crate:dep +pub struct Barc; +pub struct Rcar; +pub struct Rc; +pub const RC: () = (); +pub mod some_module { + pub struct Bar; + pub struct Rcar; + pub struct Rc; + pub const RC: () = (); +} + +//- /main.rs crate:main deps:dep +fn main() { + RC$0 +} +"#, + expect![[r#" + ct RC (use dep::RC) + ct RC (use dep::some_module::RC) "#]], ); } @@ -841,8 +897,8 @@ fn main() { TES$0 }"#, expect![[r#" - ct TEST_CONST (use foo::TEST_CONST) - "#]], + ct TEST_CONST (use foo::TEST_CONST) + "#]], ); check( @@ -858,9 +914,9 @@ fn main() { tes$0 }"#, expect![[r#" - ct TEST_CONST (use foo::TEST_CONST) - fn test_function() (use foo::test_function) fn() -> i32 - "#]], + ct TEST_CONST (use foo::TEST_CONST) + fn test_function() (use foo::test_function) fn() -> i32 + "#]], ); check( @@ -873,9 +929,9 @@ mod foo { } fn main() { - Te$0 + Tes$0 }"#, - expect![[]], + expect![""], ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs index 8af6cce98f635..b2e8274a84d7d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs @@ -354,6 +354,35 @@ fn outer(Foo { bar$0 }: Foo) {} ) } +#[test] +fn completes_in_record_field_pat_with_generic_type_alias() { + check_empty( + r#" +type Wrap = T; + +enum X { + A { cool: u32, stuff: u32 }, + B, +} + +fn main() { + let wrapped = Wrap::::A { + cool: 100, + stuff: 100, + }; + + if let Wrap::::A { $0 } = &wrapped {}; +} +"#, + expect![[r#" + fd cool u32 + fd stuff u32 + kw mut + kw ref + "#]], + ) +} + #[test] fn completes_in_fn_param() { check_empty( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index e80a289049f1d..d3dbd7cc22777 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -2,10 +2,15 @@ use expect_test::{expect, Expect}; -use crate::tests::{ - check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, +use crate::{ + tests::{ + check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, + }, + CompletionItemKind, }; +use super::{do_completion_with_config, TEST_CONFIG}; + fn check_no_kw(ra_fixture: &str, expect: Expect) { let actual = completion_list_no_kw(ra_fixture); expect.assert_eq(&actual) @@ -1303,3 +1308,176 @@ struct Foo(x: &'x mut T) -> u8 where T: Clone, { 0u8 } +fn main() { fo$0 } +"#, + CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), + expect!("fn(&mut T) -> u8"), + expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"), + ); + + check_signatures( + r#" +struct Foo; +struct Bar; +impl Bar { + pub const fn baz(x: Foo) -> ! { loop {} }; +} + +fn main() { Bar::b$0 } +"#, + CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), + expect!("const fn(Foo) -> !"), + expect!("pub const fn baz(x: Foo) -> !"), + ); + + check_signatures( + r#" +struct Foo; +struct Bar; +impl Bar { + pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> ! { loop {} }; +} + +fn main() { + let mut bar = Bar; + bar.b$0 +} +"#, + CompletionItemKind::Method, + expect!("const fn(&'foo mut self, &Foo) -> !"), + expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"), + ); +} + +#[test] +fn skips_underscore() { + check_with_trigger_character( + r#" +fn foo(_$0) { } +"#, + Some('_'), + expect![[r#""#]], + ); + check_with_trigger_character( + r#" +fn foo(_: _$0) { } +"#, + Some('_'), + expect![[r#""#]], + ); + check_with_trigger_character( + r#" +fn foo() { + foo::<_$0>(); +} +"#, + Some('_'), + expect![[r#""#]], + ); + // underscore expressions are fine, they are invalid so the user definitely meant to type an + // underscored name here + check_with_trigger_character( + r#" +fn foo() { + _$0 +} +"#, + Some('_'), + expect![[r#" + fn foo() fn() + bt u32 + kw const + kw crate:: + kw enum + kw extern + kw false + kw fn + kw for + kw if + kw if let + kw impl + kw let + kw loop + kw match + kw mod + kw return + kw self:: + kw static + kw struct + kw trait + kw true + kw type + kw union + kw unsafe + kw use + kw while + kw while let + sn macro_rules + sn pd + sn ppd + "#]], + ); +} + +#[test] +fn no_skip_underscore_ident() { + check_with_trigger_character( + r#" +fn foo(a_$0) { } +"#, + Some('_'), + expect![[r#" + kw mut + kw ref + "#]], + ); + check_with_trigger_character( + r#" +fn foo(_: a_$0) { } +"#, + Some('_'), + expect![[r#" + bt u32 + kw crate:: + kw self:: + "#]], + ); + check_with_trigger_character( + r#" +fn foo() { + foo::(); +} +"#, + Some('_'), + expect![[r#" + tp T + bt u32 + kw crate:: + kw self:: + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml index faec742068117..4a2e770f193a0 100644 --- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml @@ -13,16 +13,16 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" -tracing = "0.1.35" -rayon = "1.6.1" +tracing.workspace = true +rayon.workspace = true fst = { version = "0.4.7", default-features = false } rustc-hash = "1.1.0" once_cell = "1.17.0" -either = "1.7.0" -itertools = "0.10.5" +either.workspace = true +itertools.workspace = true arrayvec = "0.7.2" -indexmap = "2.0.0" -memchr = "2.5.0" +indexmap.workspace = true +memchr = "2.6.4" triomphe.workspace = true nohash-hasher.workspace = true @@ -43,7 +43,7 @@ line-index.workspace = true [dev-dependencies] expect-test = "1.4.0" oorandom = "11.1.3" -xshell = "0.2.2" +xshell.workspace = true # local deps test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 4ce80532e8efa..ef72fc3861a7f 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -161,8 +161,8 @@ impl IdentClass { ast::AwaitExpr(await_expr) => OperatorClass::classify_await(sema, &await_expr).map(IdentClass::Operator), ast::BinExpr(bin_expr) => OperatorClass::classify_bin(sema, &bin_expr).map(IdentClass::Operator), ast::IndexExpr(index_expr) => OperatorClass::classify_index(sema, &index_expr).map(IdentClass::Operator), - ast::PrefixExpr(prefix_expr) => OperatorClass::classify_prefix(sema,&prefix_expr).map(IdentClass::Operator), - ast::TryExpr(try_expr) => OperatorClass::classify_try(sema,&try_expr).map(IdentClass::Operator), + ast::PrefixExpr(prefix_expr) => OperatorClass::classify_prefix(sema, &prefix_expr).map(IdentClass::Operator), + ast::TryExpr(try_expr) => OperatorClass::classify_try(sema, &try_expr).map(IdentClass::Operator), _ => None, } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs index b63dde2c21e73..722517a7677bf 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -54,6 +54,10 @@ impl FamousDefs<'_, '_> { self.find_trait("core:convert:Into") } + pub fn core_convert_Index(&self) -> Option { + self.find_trait("core:ops:Index") + } + pub fn core_option_Option(&self) -> Option { self.find_enum("core:option:Option") } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 57563a1748333..1cb6ff8627a23 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -9,12 +9,18 @@ pub struct LintGroup { pub lint: Lint, pub children: &'static [&'static str], } + pub const DEFAULT_LINTS: &[Lint] = &[ Lint { label: "absolute_paths_not_starting_with_crate", description: r##"fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name"##, }, Lint { label: "ambiguous_associated_items", description: r##"ambiguous associated items"## }, + Lint { + label: "ambiguous_glob_imports", + description: r##"detects certain glob imports that require reporting an ambiguity error"##, + }, + Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## }, Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## }, Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## }, Lint { @@ -25,6 +31,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "asm_sub_register", description: r##"using only a subset of a register for inline asm inputs"##, }, + Lint { + label: "async_fn_in_trait", + description: r##"use of `async fn` in definition of a publicly-reachable trait"##, + }, Lint { label: "bad_asm_style", description: r##"incorrect use of inline assembly"## }, Lint { label: "bare_trait_objects", @@ -39,6 +49,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "break_with_label_and_loop", description: r##"`break` expression with label and unlabeled loop as value expression"##, }, + Lint { + label: "byte_slice_in_packed_struct_with_derive", + description: r##"`[u8]` or `str` used in a packed struct with `derive`"##, + }, Lint { label: "cenum_impl_drop_cast", description: r##"a C-like enum implementing Drop is cast"##, @@ -51,6 +65,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "coherence_leak_check", description: r##"distinct impls distinguished only by the leak-check code"##, }, + Lint { + label: "coinductive_overlap_in_coherence", + description: r##"impls that are not considered to overlap may be considered to overlap in the future"##, + }, Lint { label: "conflicting_repr_hints", description: r##"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"##, @@ -59,10 +77,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "confusable_idents", description: r##"detects visually confusable pairs between identifiers"##, }, - Lint { - label: "const_err", - description: r##"constant evaluation encountered erroneous expression"##, - }, Lint { label: "const_evaluatable_unchecked", description: r##"detects a generic constant is used in a type without a emitting a warning"##, @@ -71,12 +85,24 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "const_item_mutation", description: r##"detects attempts to mutate a `const` item"##, }, + Lint { + label: "const_patterns_without_partial_eq", + description: r##"constant in pattern does not implement `PartialEq`"##, + }, Lint { label: "dead_code", description: r##"detect unused, unexported items"## }, Lint { label: "deprecated", description: r##"detects use of deprecated items"## }, + Lint { + label: "deprecated_cfg_attr_crate_type_name", + description: r##"detects usage of `#![cfg_attr(..., crate_type/crate_name = "...")]`"##, + }, Lint { label: "deprecated_in_future", description: r##"detects use of items that will be deprecated in a future version"##, }, + Lint { + label: "deprecated_where_clause_location", + description: r##"deprecated where clause location"##, + }, Lint { label: "deref_into_dyn_supertrait", description: r##"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future"##, @@ -89,10 +115,23 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "drop_bounds", description: r##"bounds of the form `T: Drop` are most likely incorrect"##, }, + Lint { + label: "dropping_copy_types", + description: r##"calls to `std::mem::drop` with a value that implements Copy"##, + }, + Lint { + label: "dropping_references", + description: r##"calls to `std::mem::drop` with a reference instead of an owned value"##, + }, + Lint { label: "duplicate_macro_attributes", description: r##"duplicated attribute"## }, Lint { label: "dyn_drop", description: r##"trait objects of the form `dyn Drop` are useless"##, }, + Lint { + label: "elided_lifetimes_in_associated_constant", + description: r##"elided lifetimes cannot be used in associated constants in impls"##, + }, Lint { label: "elided_lifetimes_in_paths", description: r##"hidden lifetime parameters in types are deprecated"##, @@ -113,14 +152,38 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "exported_private_dependencies", description: r##"public interface leaks type from a private dependency"##, }, + Lint { + label: "ffi_unwind_calls", + description: r##"call to foreign functions or function pointers with FFI-unwind ABI"##, + }, + Lint { + label: "for_loops_over_fallibles", + description: r##"for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`"##, + }, Lint { label: "forbidden_lint_groups", description: r##"applying forbid to lint-groups"## }, + Lint { + label: "forgetting_copy_types", + description: r##"calls to `std::mem::forget` with a value that implements Copy"##, + }, + Lint { + label: "forgetting_references", + description: r##"calls to `std::mem::forget` with a reference instead of an owned value"##, + }, Lint { label: "function_item_references", description: r##"suggest casting to a function pointer when attempting to take references to function items"##, }, Lint { label: "future_incompatible", - description: r##"lint group for: forbidden-lint-groups, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, const-err, unaligned-references, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, uninhabited-static, unsupported-naked-functions, invalid-doc-attributes, semicolon-in-expressions-from-macros, legacy-derive-helpers, proc-macro-back-compat, unsupported-calling-conventions, deref-into-dyn-supertrait"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + }, + Lint { + label: "fuzzy_provenance_casts", + description: r##"a fuzzy integer to pointer cast is used"##, + }, + Lint { + label: "hidden_glob_reexports", + description: r##"name introduced by a private item shadows a name introduced by a public glob re-export"##, }, Lint { label: "ill_formed_attribute_input", @@ -130,6 +193,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "illegal_floating_point_literal_pattern", description: r##"floating-point literals cannot be used in patterns"##, }, + Lint { + label: "implied_bounds_entailment", + description: r##"impl method assumes more implied bounds than its corresponding trait method"##, + }, Lint { label: "improper_ctypes", description: r##"proper use of libc types in foreign modules"##, @@ -155,6 +222,14 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "inline_no_sanitize", description: r##"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`"##, }, + Lint { + label: "internal_features", + description: r##"internal features are not supposed to be used"##, + }, + Lint { + label: "invalid_alignment", + description: r##"raw pointers must be aligned before dereferencing"##, + }, Lint { label: "invalid_atomic_ordering", description: r##"usage of invalid atomic ordering in atomic operations and memory fences"##, @@ -163,6 +238,26 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "invalid_doc_attributes", description: r##"detects invalid `#[doc(...)]` attributes"##, }, + Lint { + label: "invalid_from_utf8", + description: r##"using a non UTF-8 literal in `std::str::from_utf8`"##, + }, + Lint { + label: "invalid_from_utf8_unchecked", + description: r##"using a non UTF-8 literal in `std::str::from_utf8_unchecked`"##, + }, + Lint { + label: "invalid_macro_export_arguments", + description: r##""invalid_parameter" isn't a valid argument for `#[macro_export]`"##, + }, + Lint { + label: "invalid_nan_comparisons", + description: r##"detects invalid floating point NaN comparisons"##, + }, + Lint { + label: "invalid_reference_casting", + description: r##"casts of `&T` to `&mut T` without interior mutability"##, + }, Lint { label: "invalid_type_param_default", description: r##"type parameter default erroneously allowed in invalid location"##, @@ -188,6 +283,26 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "legacy_derive_helpers", description: r##"detects derive helper attributes that are used before they are introduced"##, }, + Lint { + label: "let_underscore", + description: r##"lint group for: let-underscore-drop, let-underscore-lock"##, + }, + Lint { + label: "let_underscore_drop", + description: r##"non-binding let on a type that implements `Drop`"##, + }, + Lint { + label: "let_underscore_lock", + description: r##"non-binding let on a synchronization lock"##, + }, + Lint { + label: "long_running_const_eval", + description: r##"detects long const eval operations"##, + }, + Lint { + label: "lossy_provenance_casts", + description: r##"a lossy pointer to integer cast is used"##, + }, Lint { label: "macro_expanded_macro_exports_accessed_by_absolute_paths", description: r##"macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths"##, @@ -196,6 +311,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "macro_use_extern_crate", description: r##"the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system"##, }, + Lint { + label: "map_unit_fn", + description: r##"`Iterator::map` call that discard the iterator's values"##, + }, Lint { label: "meta_variable_misuse", description: r##"possible meta-variable misuse at macro definition"##, @@ -221,17 +340,21 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "mixed_script_confusables", description: r##"detects Unicode scripts whose mixed script confusables codepoints are solely used"##, }, + Lint { + label: "multiple_supertrait_upcastable", + description: r##"detect when an object-safe trait has multiple supertraits"##, + }, Lint { label: "must_not_suspend", description: r##"use of a `#[must_not_suspend]` value across a yield point"##, }, Lint { - label: "mutable_borrow_reservation_conflict", - description: r##"reservation of a two-phased borrow conflicts with other shared borrows"##, + label: "mutable_transmutes", + description: r##"transmuting &T to &mut T is undefined behavior, even if the reference is unused"##, }, Lint { - label: "mutable_transmutes", - description: r##"mutating transmuted &mut T from &T may cause undefined behavior"##, + label: "named_arguments_used_positionally", + description: r##"named arguments in format used positionally"##, }, Lint { label: "named_asm_labels", description: r##"named labels in inline assembly"## }, Lint { @@ -276,6 +399,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "noop_method_call", description: r##"detects the use of well-known noop methods"##, }, + Lint { + label: "opaque_hidden_inferred_bound", + description: r##"detects the use of nested `impl Trait` types in associated type bounds that are not general enough"##, + }, Lint { label: "order_dependent_trait_objects", description: r##"trait-object types were treated as different depending on marker-trait order"##, @@ -295,8 +422,12 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"pointers are not structural-match"##, }, Lint { - label: "private_in_public", - description: r##"detect private items in public interfaces not caught by the old implementation"##, + label: "private_bounds", + description: r##"private type in secondary interface of an item"##, + }, + Lint { + label: "private_interfaces", + description: r##"private type in primary interface of an item"##, }, Lint { label: "proc_macro_back_compat", @@ -314,13 +445,21 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "redundant_semicolons", description: r##"detects unnecessary trailing semicolons"##, }, + Lint { + label: "refining_impl_trait", + description: r##"impl trait in impl method signature does not match trait method signature"##, + }, Lint { label: "renamed_and_removed_lints", description: r##"lints that have been renamed or removed"##, }, + Lint { + label: "repr_transparent_external_private_fields", + description: r##"transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields"##, + }, Lint { label: "rust_2018_compatibility", - description: r##"lint group for: keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate"##, + description: r##"lint group for: keyword-idents, anonymous-parameters, absolute-paths-not-starting-with-crate, tyvar-behind-raw-pointer"##, }, Lint { label: "rust_2018_idioms", @@ -328,7 +467,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "rust_2021_compatibility", - description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prelude-collisions, rust-2021-prefixes-incompatible-syntax, array-into-iter, non-fmt-panics"##, + description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prefixes-incompatible-syntax, rust-2021-prelude-collisions, array-into-iter, non-fmt-panics"##, }, Lint { label: "rust_2021_incompatible_closure_captures", @@ -358,14 +497,30 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "soft_unstable", description: r##"a feature gate that doesn't break dependent crates"##, }, + Lint { + label: "special_module_name", + description: r##"module declarations for files with a special meaning"##, + }, Lint { label: "stable_features", description: r##"stable features found in `#[feature]` directive"##, }, + Lint { + label: "suspicious_auto_trait_impls", + description: r##"the rules governing auto traits have recently changed resulting in potential breakage"##, + }, + Lint { + label: "suspicious_double_ref_op", + description: r##"suspicious call of trait method on `&&T`"##, + }, Lint { label: "temporary_cstring_as_ptr", description: r##"detects getting the inner pointer of a temporary `CString`"##, }, + Lint { + label: "test_unstable_lint", + description: r##"this unstable lint is only for testing"##, + }, Lint { label: "text_direction_codepoint_in_comment", description: r##"invisible directionality-changing codepoints in comment"##, @@ -394,10 +549,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "tyvar_behind_raw_pointer", description: r##"raw pointer to an inference variable"##, }, - Lint { - label: "unaligned_references", - description: r##"detects unaligned references to fields of packed structs"##, - }, Lint { label: "uncommon_codepoints", description: r##"detects uncommon Unicode codepoints in identifiers"##, @@ -410,23 +561,54 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unconditional_recursion", description: r##"functions that cannot return without calling themselves"##, }, + Lint { + label: "undefined_naked_function_abi", + description: r##"undefined naked function ABI"##, + }, + Lint { + label: "undropped_manually_drops", + description: r##"calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of it's inner value"##, + }, + Lint { + label: "unexpected_cfgs", + description: r##"detects unexpected names and values in `#[cfg]` conditions"##, + }, + Lint { + label: "unfulfilled_lint_expectations", + description: r##"unfulfilled lint expectation"##, + }, + Lint { + label: "ungated_async_fn_track_caller", + description: r##"enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"##, + }, Lint { label: "uninhabited_static", description: r##"uninhabited static"## }, Lint { label: "unknown_crate_types", description: r##"unknown crate type found in `#[crate_type]` directive"##, }, Lint { label: "unknown_lints", description: r##"unrecognized lint attribute"## }, + Lint { + label: "unknown_or_malformed_diagnostic_attributes", + description: r##"unrecognized or malformed diagnostic attribute"##, + }, Lint { label: "unnameable_test_items", description: r##"detects an item that cannot be named being marked as `#[test_case]`"##, }, + Lint { + label: "unnameable_types", + description: r##"effective visibility of a type is larger than the area in which it can be named"##, + }, Lint { label: "unreachable_code", description: r##"detects unreachable code paths"## }, Lint { label: "unreachable_patterns", description: r##"detects unreachable patterns"## }, Lint { label: "unreachable_pub", description: r##"`pub` items not reachable from crate root"##, }, - Lint { label: "unsafe_code", description: r##"usage of `unsafe` code"## }, + Lint { + label: "unsafe_code", + description: r##"usage of `unsafe` code and other potentially unsound constructs"##, + }, Lint { label: "unsafe_op_in_unsafe_fn", description: r##"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"##, @@ -440,16 +622,16 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"detects name collision with an existing but unstable method"##, }, Lint { - label: "unsupported_calling_conventions", - description: r##"use of unsupported calling convention"##, + label: "unstable_syntax_pre_expansion", + description: r##"unstable syntax can change at any point in the future, causing a hard error!"##, }, Lint { - label: "unsupported_naked_functions", - description: r##"unsupported naked function definitions"##, + label: "unsupported_calling_conventions", + description: r##"use of unsupported calling convention"##, }, Lint { label: "unused", - description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons"##, + description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, }, Lint { label: "unused_allocation", @@ -459,6 +641,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_assignments", description: r##"detect assignments that will never be read"##, }, + Lint { + label: "unused_associated_type_bounds", + description: r##"detects unused `Foo = Bar` bounds in `dyn Trait`"##, + }, Lint { label: "unused_attributes", description: r##"detects attributes that were not used by the compiler"##, @@ -491,6 +677,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_lifetimes", description: r##"detects lifetime parameters that are never used"##, }, + Lint { + label: "unused_macro_rules", + description: r##"detects macro rules that were not used"##, + }, Lint { label: "unused_macros", description: r##"detects macros that were not used"## }, Lint { label: "unused_must_use", @@ -512,6 +702,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_results", description: r##"unused result of an expression in a statement"##, }, + Lint { + label: "unused_tuple_struct_fields", + description: r##"detects tuple struct fields that are never read"##, + }, Lint { label: "unused_unsafe", description: r##"unnecessary use of an `unsafe` block"## }, Lint { label: "unused_variables", @@ -521,6 +715,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "useless_deprecated", description: r##"detects deprecation attributes with no effect"##, }, + Lint { + label: "useless_ptr_null_checks", + description: r##"useless checking of non-null-typed pointer"##, + }, Lint { label: "variant_size_differences", description: r##"detects enums with widely varying variant sizes"##, @@ -542,49 +740,63 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"suggest using `loop { }` instead of `while true { }`"##, }, ]; + pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: forbidden-lint-groups, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, const-err, unaligned-references, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, uninhabited-static, unsupported-naked-functions, invalid-doc-attributes, semicolon-in-expressions-from-macros, legacy-derive-helpers, proc-macro-back-compat, unsupported-calling-conventions, deref-into-dyn-supertrait"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, children: &[ + "deref_into_dyn_supertrait", + "ambiguous_associated_items", + "ambiguous_glob_imports", + "byte_slice_in_packed_struct_with_derive", + "cenum_impl_drop_cast", + "coherence_leak_check", + "coinductive_overlap_in_coherence", + "conflicting_repr_hints", + "const_evaluatable_unchecked", + "const_patterns_without_partial_eq", + "deprecated_cfg_attr_crate_type_name", + "elided_lifetimes_in_associated_constant", "forbidden_lint_groups", + "ill_formed_attribute_input", "illegal_floating_point_literal_pattern", - "private_in_public", - "pub_use_of_private_extern_crate", + "implied_bounds_entailment", + "indirect_structural_match", + "invalid_alignment", + "invalid_doc_attributes", "invalid_type_param_default", - "const_err", - "unaligned_references", - "patterns_in_fns_without_body", - "missing_fragment_specifier", "late_bound_lifetime_arguments", - "order_dependent_trait_objects", - "coherence_leak_check", - "unstable_name_collisions", - "where_clauses_object_safety", - "proc_macro_derive_resolution_fallback", + "legacy_derive_helpers", "macro_expanded_macro_exports_accessed_by_absolute_paths", - "ill_formed_attribute_input", - "conflicting_repr_hints", - "ambiguous_associated_items", - "mutable_borrow_reservation_conflict", - "indirect_structural_match", - "pointer_structural_match", + "missing_fragment_specifier", "nontrivial_structural_match", + "order_dependent_trait_objects", + "patterns_in_fns_without_body", + "pointer_structural_match", + "proc_macro_back_compat", + "proc_macro_derive_resolution_fallback", + "pub_use_of_private_extern_crate", + "repr_transparent_external_private_fields", + "semicolon_in_expressions_from_macros", "soft_unstable", - "cenum_impl_drop_cast", - "const_evaluatable_unchecked", + "suspicious_auto_trait_impls", "uninhabited_static", - "unsupported_naked_functions", - "invalid_doc_attributes", - "semicolon_in_expressions_from_macros", - "legacy_derive_helpers", - "proc_macro_back_compat", + "unstable_name_collisions", + "unstable_syntax_pre_expansion", "unsupported_calling_conventions", - "deref_into_dyn_supertrait", + "where_clauses_object_safety", ], }, + LintGroup { + lint: Lint { + label: "let_underscore", + description: r##"lint group for: let-underscore-drop, let-underscore-lock"##, + }, + children: &["let_underscore_drop", "let_underscore_lock"], + }, LintGroup { lint: Lint { label: "nonstandard_style", @@ -595,13 +807,13 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "rust_2018_compatibility", - description: r##"lint group for: keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate"##, + description: r##"lint group for: keyword-idents, anonymous-parameters, absolute-paths-not-starting-with-crate, tyvar-behind-raw-pointer"##, }, children: &[ "keyword_idents", "anonymous_parameters", - "tyvar_behind_raw_pointer", "absolute_paths_not_starting_with_crate", + "tyvar_behind_raw_pointer", ], }, LintGroup { @@ -620,15 +832,15 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "rust_2021_compatibility", - description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prelude-collisions, rust-2021-prefixes-incompatible-syntax, array-into-iter, non-fmt-panics"##, + description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prefixes-incompatible-syntax, rust-2021-prelude-collisions, array-into-iter, non-fmt-panics"##, }, children: &[ "ellipsis_inclusive_range_patterns", "bare_trait_objects", "rust_2021_incompatible_closure_captures", "rust_2021_incompatible_or_patterns", - "rust_2021_prelude_collisions", "rust_2021_prefixes_incompatible_syntax", + "rust_2021_prelude_collisions", "array_into_iter", "non_fmt_panics", ], @@ -636,7 +848,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "unused", - description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons"##, + description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, }, children: &[ "unused_imports", @@ -651,6 +863,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "path_statements", "unused_attributes", "unused_macros", + "unused_macro_rules", "unused_allocation", "unused_doc_comments", "unused_extern_crates", @@ -659,6 +872,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "unused_parens", "unused_braces", "redundant_semicolons", + "map_unit_fn", ], }, LintGroup { @@ -673,7 +887,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ pub const RUSTDOC_LINTS: &[Lint] = &[ Lint { label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::missing-doc-code-examples, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs"##, + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, }, Lint { label: "rustdoc::bare_urls", description: r##"detects URLs that are not hyperlinks"## }, Lint { @@ -708,26 +922,69 @@ pub const RUSTDOC_LINTS: &[Lint] = &[ label: "rustdoc::private_intra_doc_links", description: r##"linking from a public item to a private one"##, }, + Lint { + label: "rustdoc::redundant_explicit_links", + description: r##"detects redundant explicit links in doc comments"##, + }, + Lint { + label: "rustdoc::unescaped_backticks", + description: r##"detects unescaped backticks in doc comments"##, + }, ]; + pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &[LintGroup { lint: Lint { label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::missing-doc-code-examples, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs"##, + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, }, children: &[ "rustdoc::broken_intra_doc_links", "rustdoc::private_intra_doc_links", - "rustdoc::missing_doc_code_examples", "rustdoc::private_doc_tests", "rustdoc::invalid_codeblock_attributes", "rustdoc::invalid_rust_codeblocks", "rustdoc::invalid_html_tags", "rustdoc::bare_urls", "rustdoc::missing_crate_level_docs", + "rustdoc::unescaped_backticks", + "rustdoc::redundant_explicit_links", ], }]; pub const FEATURES: &[Lint] = &[ + Lint { + label: "aarch64_ver_target_feature", + description: r##"# `aarch64_ver_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "abi_amdgpu_kernel", + description: r##"# `abi_amdgpu_kernel` + +The tracking issue for this feature is: [#51575] + +[#51575]: https://github.com/rust-lang/rust/issues/51575 + +------------------------ +"##, + }, + Lint { + label: "abi_avr_interrupt", + description: r##"# `abi_avr_interrupt` + +The tracking issue for this feature is: [#69664] + +[#69664]: https://github.com/rust-lang/rust/issues/69664 + +------------------------ +"##, + }, Lint { label: "abi_c_cmse_nonsecure_call", description: r##"# `abi_c_cmse_nonsecure_call` @@ -931,117 +1188,354 @@ $ cat $(find -name '*.s') "##, }, Lint { - label: "allocator_api", - description: r##"# `allocator_api` + label: "abi_riscv_interrupt", + description: r##"# `abi_riscv_interrupt` -The tracking issue for this feature is [#32838] +The tracking issue for this feature is: [#111889] -[#32838]: https://github.com/rust-lang/rust/issues/32838 +[#111889]: https://github.com/rust-lang/rust/issues/111889 ------------------------ +"##, + }, + Lint { + label: "abi_unadjusted", + description: r##"# `abi_unadjusted` -Sometimes you want the memory for one collection to use a different -allocator than the memory for another collection. In this case, -replacing the global allocator is not a workable option. Instead, -you need to pass in an instance of an `AllocRef` to each collection -for which you want a custom allocator. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -TBD +------------------------ "##, }, Lint { - label: "allocator_internals", - description: r##"# `allocator_internals` + label: "abi_vectorcall", + description: r##"# `abi_vectorcall` -This feature does not have a tracking issue, it is an unstable implementation -detail of the `global_allocator` feature not intended for use outside the -compiler. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, }, Lint { - label: "arbitrary_enum_discriminant", - description: r##"# `arbitrary_enum_discriminant` + label: "abi_x86_interrupt", + description: r##"# `abi_x86_interrupt` -The tracking issue for this feature is: [#60553] +The tracking issue for this feature is: [#40180] -[#60553]: https://github.com/rust-lang/rust/issues/60553 +[#40180]: https://github.com/rust-lang/rust/issues/40180 ------------------------ +"##, + }, + Lint { + label: "absolute_path", + description: r##"# `absolute_path` -The `arbitrary_enum_discriminant` feature permits tuple-like and -struct-like enum variants with `#[repr()]` to have explicit discriminants. +The tracking issue for this feature is: [#92750] -## Examples +[#92750]: https://github.com/rust-lang/rust/issues/92750 -```rust -#![feature(arbitrary_enum_discriminant)] - -#[allow(dead_code)] -#[repr(u8)] -enum Enum { - Unit = 3, - Tuple(u16) = 2, - Struct { - a: u8, - b: u16, - } = 1, -} +------------------------ +"##, + }, + Lint { + label: "addr_parse_ascii", + description: r##"# `addr_parse_ascii` -impl Enum { - fn tag(&self) -> u8 { - unsafe { *(self as *const Self as *const u8) } - } -} +The tracking issue for this feature is: [#101035] -assert_eq!(3, Enum::Unit.tag()); -assert_eq!(2, Enum::Tuple(5).tag()); -assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag()); -``` +[#101035]: https://github.com/rust-lang/rust/issues/101035 + +------------------------ "##, }, Lint { - label: "asm_const", - description: r##"# `asm_const` + label: "adt_const_params", + description: r##"# `adt_const_params` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#95174] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#95174]: https://github.com/rust-lang/rust/issues/95174 ------------------------ +"##, + }, + Lint { + label: "alloc_error_handler", + description: r##"# `alloc_error_handler` -This feature adds a `const ` operand type to `asm!` and `global_asm!`. -- `` must be an integer constant expression. -- The value of the expression is formatted as a string and substituted directly into the asm template string. +The tracking issue for this feature is: [#51540] + +[#51540]: https://github.com/rust-lang/rust/issues/51540 + +------------------------ "##, }, Lint { - label: "asm_experimental_arch", - description: r##"# `asm_experimental_arch` + label: "alloc_error_hook", + description: r##"# `alloc_error_hook` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#51245] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#51245]: https://github.com/rust-lang/rust/issues/51245 ------------------------ +"##, + }, + Lint { + label: "alloc_internals", + description: r##"# `alloc_internals` -This feature tracks `asm!` and `global_asm!` support for the following architectures: -- NVPTX -- PowerPC -- Hexagon -- MIPS32r2 and MIPS64r2 -- wasm32 -- BPF -- SPIR-V -- AVR +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -## Register classes +------------------------ +"##, + }, + Lint { + label: "alloc_layout_extra", + description: r##"# `alloc_layout_extra` -| Architecture | Register class | Registers | LLVM constraint code | -| ------------ | -------------- | ---------------------------------- | -------------------- | -| MIPS | `reg` | `$[2-25]` | `r` | -| MIPS | `freg` | `$f[0-31]` | `f` | +The tracking issue for this feature is: [#55724] + +[#55724]: https://github.com/rust-lang/rust/issues/55724 + +------------------------ +"##, + }, + Lint { + label: "allocator_api", + description: r##"# `allocator_api` + +The tracking issue for this feature is [#32838] + +[#32838]: https://github.com/rust-lang/rust/issues/32838 + +------------------------ + +Sometimes you want the memory for one collection to use a different +allocator than the memory for another collection. In this case, +replacing the global allocator is not a workable option. Instead, +you need to pass in an instance of an `AllocRef` to each collection +for which you want a custom allocator. + +TBD +"##, + }, + Lint { + label: "allocator_internals", + description: r##"# `allocator_internals` + +This feature does not have a tracking issue, it is an unstable implementation +detail of the `global_allocator` feature not intended for use outside the +compiler. + +------------------------ +"##, + }, + Lint { + label: "allow_internal_unsafe", + description: r##"# `allow_internal_unsafe` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "allow_internal_unstable", + description: r##"# `allow_internal_unstable` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "anonymous_lifetime_in_impl_trait", + description: r##"# `anonymous_lifetime_in_impl_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "arbitrary_self_types", + description: r##"# `arbitrary_self_types` + +The tracking issue for this feature is: [#44874] + +[#44874]: https://github.com/rust-lang/rust/issues/44874 + +------------------------ +"##, + }, + Lint { + label: "arc_unwrap_or_clone", + description: r##"# `arc_unwrap_or_clone` + +The tracking issue for this feature is: [#93610] + +[#93610]: https://github.com/rust-lang/rust/issues/93610 + +------------------------ +"##, + }, + Lint { + label: "arm_target_feature", + description: r##"# `arm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "array_chunks", + description: r##"# `array_chunks` + +The tracking issue for this feature is: [#74985] + +[#74985]: https://github.com/rust-lang/rust/issues/74985 + +------------------------ +"##, + }, + Lint { + label: "array_into_iter_constructors", + description: r##"# `array_into_iter_constructors` + +The tracking issue for this feature is: [#91583] + +[#91583]: https://github.com/rust-lang/rust/issues/91583 + +------------------------ +"##, + }, + Lint { + label: "array_methods", + description: r##"# `array_methods` + +The tracking issue for this feature is: [#76118] + +[#76118]: https://github.com/rust-lang/rust/issues/76118 + +------------------------ +"##, + }, + Lint { + label: "array_try_from_fn", + description: r##"# `array_try_from_fn` + +The tracking issue for this feature is: [#89379] + +[#89379]: https://github.com/rust-lang/rust/issues/89379 + +------------------------ +"##, + }, + Lint { + label: "array_try_map", + description: r##"# `array_try_map` + +The tracking issue for this feature is: [#79711] + +[#79711]: https://github.com/rust-lang/rust/issues/79711 + +------------------------ +"##, + }, + Lint { + label: "array_windows", + description: r##"# `array_windows` + +The tracking issue for this feature is: [#75027] + +[#75027]: https://github.com/rust-lang/rust/issues/75027 + +------------------------ +"##, + }, + Lint { + label: "as_array_of_cells", + description: r##"# `as_array_of_cells` + +The tracking issue for this feature is: [#88248] + +[#88248]: https://github.com/rust-lang/rust/issues/88248 + +------------------------ +"##, + }, + Lint { + label: "ascii_char", + description: r##"# `ascii_char` + +The tracking issue for this feature is: [#110998] + +[#110998]: https://github.com/rust-lang/rust/issues/110998 + +------------------------ +"##, + }, + Lint { + label: "ascii_char_variants", + description: r##"# `ascii_char_variants` + +The tracking issue for this feature is: [#110998] + +[#110998]: https://github.com/rust-lang/rust/issues/110998 + +------------------------ +"##, + }, + Lint { + label: "asm_const", + description: r##"# `asm_const` + +The tracking issue for this feature is: [#93332] + +[#93332]: https://github.com/rust-lang/rust/issues/93332 + +------------------------ + +This feature adds a `const ` operand type to `asm!` and `global_asm!`. +- `` must be an integer constant expression. +- The value of the expression is formatted as a string and substituted directly into the asm template string. +"##, + }, + Lint { + label: "asm_experimental_arch", + description: r##"# `asm_experimental_arch` + +The tracking issue for this feature is: [#93335] + +[#93335]: https://github.com/rust-lang/rust/issues/93335 + +------------------------ + +This feature tracks `asm!` and `global_asm!` support for the following architectures: +- NVPTX +- PowerPC +- Hexagon +- MIPS32r2 and MIPS64r2 +- wasm32 +- BPF +- SPIR-V +- AVR +- MSP430 +- M68k +- CSKY +- s390x + +## Register classes + +| Architecture | Register class | Registers | LLVM constraint code | +| ------------ | -------------- | ---------------------------------- | -------------------- | +| MIPS | `reg` | `$[2-25]` | `r` | +| MIPS | `freg` | `$f[0-31]` | `f` | | NVPTX | `reg16` | None\* | `h` | | NVPTX | `reg32` | None\* | `r` | | NVPTX | `reg64` | None\* | `l` | @@ -1059,6 +1553,14 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | AVR | `reg_pair` | `r3r2` .. `r25r24`, `X`, `Z` | `r` | | AVR | `reg_iw` | `r25r24`, `X`, `Z` | `w` | | AVR | `reg_ptr` | `X`, `Z` | `e` | +| MSP430 | `reg` | `r[0-15]` | `r` | +| M68k | `reg` | `d[0-7]`, `a[0-7]` | `r` | +| M68k | `reg_data` | `d[0-7]` | `d` | +| M68k | `reg_addr` | `a[0-3]` | `a` | +| CSKY | `reg` | `r[0-31]` | `r` | +| CSKY | `freg` | `f[0-31]` | `f` | +| s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | +| s390x | `freg` | `f[0-15]` | `f` | > **Notes**: > - NVPTX doesn't have a fixed register set, so named registers are not supported. @@ -1087,6 +1589,13 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | BPF | `wreg` | `alu32` | `i8` `i16` `i32` | | AVR | `reg`, `reg_upper` | None | `i8` | | AVR | `reg_pair`, `reg_iw`, `reg_ptr` | None | `i16` | +| MSP430 | `reg` | None | `i8`, `i16` | +| M68k | `reg`, `reg_addr` | None | `i16`, `i32` | +| M68k | `reg_data` | None | `i8`, `i16`, `i32` | +| CSKY | `reg` | None | `i8`, `i16`, `i32` | +| CSKY | `freg` | None | `f32`, | +| s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | +| s390x | `freg` | None | `f32`, `f64` | ## Register aliases @@ -1100,13 +1609,36 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | AVR | `XL` | `r26` | | AVR | `ZH` | `r31` | | AVR | `ZL` | `r30` | +| MSP430 | `r0` | `pc` | +| MSP430 | `r1` | `sp` | +| MSP430 | `r2` | `sr` | +| MSP430 | `r3` | `cg` | +| MSP430 | `r4` | `fp` | +| M68k | `a5` | `bp` | +| M68k | `a6` | `fp` | +| M68k | `a7` | `sp`, `usp`, `ssp`, `isp` | +| CSKY | `r[0-3]` | `a[0-3]` | +| CSKY | `r[4-11]` | `l[0-7]` | +| CSKY | `r[12-13]` | `t[0-1]` | +| CSKY | `r14` | `sp` | +| CSKY | `r15` | `lr` | +| CSKY | `r[16-17]` | `l[8-9]` | +| CSKY | `r[18-25]` | `t[2-9]` | +| CSKY | `r28` | `rgb` | +| CSKY | `r29` | `rtb` | +| CSKY | `r30` | `svbr` | +| CSKY | `r31` | `tls` | + +> **Notes**: +> - TI does not mandate a frame pointer for MSP430, but toolchains are allowed + to use one; LLVM uses `r4`. ## Unsupported registers | Architecture | Unsupported register | Reason | | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR) | The frame pointer cannot be used as an input or output. | +| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. | +| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x) | The frame pointer cannot be used as an input or output. | | All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | | MIPS | `$1` or `$at` | Reserved for assembler. | @@ -1115,6 +1647,15 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | MIPS | `$ra` | Return address cannot be used as inputs or outputs. | | Hexagon | `lr` | This is the link register which cannot be used as an input or output. | | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | +|MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | +| M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r7`, `r28` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r8` | Used internally by LLVM for the frame pointer. | +| CSKY | `r14` | Used internally by LLVM for the stack pointer. | +| CSKY | `r15` | This is the link register. | +| CSKY | `r[26-30]` | Reserved by its ABI. | +| CSKY | `r31` | This is the TLS register. | + ## Template modifiers @@ -1129,116 +1670,241 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg` | None | `0` | None | | PowerPC | `reg_nonzero` | None | `3` | `b` | | PowerPC | `freg` | None | `0` | None | +| s390x | `reg` | None | `%r0` | None | +| s390x | `freg` | None | `%f0` | None | +| CSKY | `reg` | None | `r0` | None | +| CSKY | `freg` | None | `f0` | None | # Flags covered by `preserves_flags` These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set: - AVR - The status register `SREG`. +- MSP430 + - The status register `r2`. +- M68k + - The condition code register `ccr`. +- s390x + - The condition code register `cc`. "##, }, Lint { - label: "asm_sym", - description: r##"# `asm_sym` + label: "asm_unwind", + description: r##"# `asm_unwind` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93334] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93334]: https://github.com/rust-lang/rust/issues/93334 ------------------------ -This feature adds a `sym ` operand type to `asm!` and `global_asm!`. -- `` must refer to a `fn` or `static`. -- A mangled symbol name referring to the item is substituted into the asm template string. -- The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc). -- `` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data. +This feature adds a `may_unwind` option to `asm!` which allows an `asm` block to unwind stack and be part of the stack unwinding process. This option is only supported by the LLVM backend right now. "##, }, Lint { - label: "asm_unwind", - description: r##"# `asm_unwind` + label: "assert_matches", + description: r##"# `assert_matches` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#82775] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#82775]: https://github.com/rust-lang/rust/issues/82775 ------------------------ - -This feature adds a `may_unwind` option to `asm!` which allows an `asm` block to unwind stack and be part of the stack unwinding process. This option is only supported by the LLVM backend right now. "##, }, Lint { - label: "auto_traits", - description: r##"# `auto_traits` + label: "associated_const_equality", + description: r##"# `associated_const_equality` -The tracking issue for this feature is [#13231] +The tracking issue for this feature is: [#92827] -[#13231]: https://github.com/rust-lang/rust/issues/13231 +[#92827]: https://github.com/rust-lang/rust/issues/92827 ----- +------------------------ +"##, + }, + Lint { + label: "associated_type_bounds", + description: r##"# `associated_type_bounds` -The `auto_traits` feature gate allows you to define auto traits. +The tracking issue for this feature is: [#52662] -Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits -that are automatically implemented for every type, unless the type, or a type it contains, -has explicitly opted out via a negative impl. (Negative impls are separately controlled -by the `negative_impls` feature.) +[#52662]: https://github.com/rust-lang/rust/issues/52662 -[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html -[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +------------------------ +"##, + }, + Lint { + label: "associated_type_defaults", + description: r##"# `associated_type_defaults` -```rust,ignore (partial-example) -impl !Trait for Type {} -``` +The tracking issue for this feature is: [#29661] -Example: +[#29661]: https://github.com/rust-lang/rust/issues/29661 -```rust -#![feature(negative_impls)] -#![feature(auto_traits)] +------------------------ +"##, + }, + Lint { + label: "async_closure", + description: r##"# `async_closure` -auto trait Valid {} +The tracking issue for this feature is: [#62290] -struct True; -struct False; +[#62290]: https://github.com/rust-lang/rust/issues/62290 -impl !Valid for False {} +------------------------ +"##, + }, + Lint { + label: "async_fn_in_trait", + description: r##"# `async_fn_in_trait` -struct MaybeValid(T); +The tracking issue for this feature is: [#91611] -fn must_be_valid(_t: T) { } +[#91611]: https://github.com/rust-lang/rust/issues/91611 -fn main() { - // works - must_be_valid( MaybeValid(True) ); +------------------------ +"##, + }, + Lint { + label: "async_fn_track_caller", + description: r##"# `async_fn_track_caller` - // compiler error - trait bound not satisfied - // must_be_valid( MaybeValid(False) ); -} -``` +The tracking issue for this feature is: [#110011] -## Automatic trait implementations +[#110011]: https://github.com/rust-lang/rust/issues/110011 -When a type is declared as an `auto trait`, we will automatically -create impls for every struct/enum/union, unless an explicit impl is -provided. These automatic impls contain a where clause for each field -of the form `T: AutoTrait`, where `T` is the type of the field and -`AutoTrait` is the auto trait in question. As an example, consider the -struct `List` and the auto trait `Send`: +------------------------ +"##, + }, + Lint { + label: "async_iter_from_iter", + description: r##"# `async_iter_from_iter` -```rust -struct List { - data: T, - next: Option>>, -} -``` +The tracking issue for this feature is: [#81798] -Presuming that there is no explicit impl of `Send` for `List`, the -compiler will supply an automatic impl of the form: +[#81798]: https://github.com/rust-lang/rust/issues/81798 -```rust -struct List { - data: T, +------------------------ +"##, + }, + Lint { + label: "async_iterator", + description: r##"# `async_iterator` + +The tracking issue for this feature is: [#79024] + +[#79024]: https://github.com/rust-lang/rust/issues/79024 + +------------------------ +"##, + }, + Lint { + label: "atomic_bool_fetch_not", + description: r##"# `atomic_bool_fetch_not` + +The tracking issue for this feature is: [#98485] + +[#98485]: https://github.com/rust-lang/rust/issues/98485 + +------------------------ +"##, + }, + Lint { + label: "atomic_from_mut", + description: r##"# `atomic_from_mut` + +The tracking issue for this feature is: [#76314] + +[#76314]: https://github.com/rust-lang/rust/issues/76314 + +------------------------ +"##, + }, + Lint { + label: "atomic_from_ptr", + description: r##"# `atomic_from_ptr` + +The tracking issue for this feature is: [#108652] + +[#108652]: https://github.com/rust-lang/rust/issues/108652 + +------------------------ +"##, + }, + Lint { + label: "auto_traits", + description: r##"# `auto_traits` + +The tracking issue for this feature is [#13231] + +[#13231]: https://github.com/rust-lang/rust/issues/13231 + +---- + +The `auto_traits` feature gate allows you to define auto traits. + +Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits +that are automatically implemented for every type, unless the type, or a type it contains, +has explicitly opted out via a negative impl. (Negative impls are separately controlled +by the `negative_impls` feature.) + +[`Send`]: ../../std/marker/trait.Send.html +[`Sync`]: ../../std/marker/trait.Sync.html + +```rust,ignore (partial-example) +impl !Trait for Type {} +``` + +Example: + +```rust +#![feature(negative_impls)] +#![feature(auto_traits)] + +auto trait Valid {} + +struct True; +struct False; + +impl !Valid for False {} + +struct MaybeValid(T); + +fn must_be_valid(_t: T) { } + +fn main() { + // works + must_be_valid( MaybeValid(True) ); + + // compiler error - trait bound not satisfied + // must_be_valid( MaybeValid(False) ); +} +``` + +## Automatic trait implementations + +When a type is declared as an `auto trait`, we will automatically +create impls for every struct/enum/union, unless an explicit impl is +provided. These automatic impls contain a where clause for each field +of the form `T: AutoTrait`, where `T` is the type of the field and +`AutoTrait` is the auto trait in question. As an example, consider the +struct `List` and the auto trait `Send`: + +```rust +struct List { + data: T, + next: Option>>, +} +``` + +Presuming that there is no explicit impl of `Send` for `List`, the +compiler will supply an automatic impl of the form: + +```rust +struct List { + data: T, next: Option>>, } @@ -1275,6 +1941,116 @@ Auto traits cannot have any trait items, such as methods or associated types. Th ## Supertraits Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile. +"##, + }, + Lint { + label: "avx512_target_feature", + description: r##"# `avx512_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "backtrace_frames", + description: r##"# `backtrace_frames` + +The tracking issue for this feature is: [#79676] + +[#79676]: https://github.com/rust-lang/rust/issues/79676 + +------------------------ +"##, + }, + Lint { + label: "bigint_helper_methods", + description: r##"# `bigint_helper_methods` + +The tracking issue for this feature is: [#85532] + +[#85532]: https://github.com/rust-lang/rust/issues/85532 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_as_slice", + description: r##"# `binary_heap_as_slice` + +The tracking issue for this feature is: [#83659] + +[#83659]: https://github.com/rust-lang/rust/issues/83659 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_drain_sorted", + description: r##"# `binary_heap_drain_sorted` + +The tracking issue for this feature is: [#59278] + +[#59278]: https://github.com/rust-lang/rust/issues/59278 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_into_iter_sorted", + description: r##"# `binary_heap_into_iter_sorted` + +The tracking issue for this feature is: [#59278] + +[#59278]: https://github.com/rust-lang/rust/issues/59278 + +------------------------ +"##, + }, + Lint { + label: "bound_as_ref", + description: r##"# `bound_as_ref` + +The tracking issue for this feature is: [#80996] + +[#80996]: https://github.com/rust-lang/rust/issues/80996 + +------------------------ +"##, + }, + Lint { + label: "bound_map", + description: r##"# `bound_map` + +The tracking issue for this feature is: [#86026] + +[#86026]: https://github.com/rust-lang/rust/issues/86026 + +------------------------ +"##, + }, + Lint { + label: "box_into_boxed_slice", + description: r##"# `box_into_boxed_slice` + +The tracking issue for this feature is: [#71582] + +[#71582]: https://github.com/rust-lang/rust/issues/71582 + +------------------------ +"##, + }, + Lint { + label: "box_into_inner", + description: r##"# `box_into_inner` + +The tracking issue for this feature is: [#80437] + +[#80437]: https://github.com/rust-lang/rust/issues/80437 + +------------------------ "##, }, Lint { @@ -1285,8 +2061,6 @@ The tracking issue for this feature is: [#29641] [#29641]: https://github.com/rust-lang/rust/issues/29641 -See also [`box_syntax`](box-syntax.md) - ------------------------ Box patterns let you match on `Box`s: @@ -1299,10 +2073,10 @@ fn main() { let b = Some(Box::new(5)); match b { Some(box n) if n < 0 => { - println!("Box contains negative number {}", n); + println!("Box contains negative number {n}"); }, Some(box n) if n >= 0 => { - println!("Box contains non-negative number {}", n); + println!("Box contains non-negative number {n}"); }, None => { println!("No box"); @@ -1314,29 +2088,102 @@ fn main() { "##, }, Lint { - label: "box_syntax", - description: r##"# `box_syntax` + label: "bpf_target_feature", + description: r##"# `bpf_target_feature` -The tracking issue for this feature is: [#49733] +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "btree_cursors", + description: r##"# `btree_cursors` -[#49733]: https://github.com/rust-lang/rust/issues/49733 +The tracking issue for this feature is: [#107540] -See also [`box_patterns`](box-patterns.md) +[#107540]: https://github.com/rust-lang/rust/issues/107540 ------------------------ +"##, + }, + Lint { + label: "btree_extract_if", + description: r##"# `btree_extract_if` -Currently the only stable way to create a `Box` is via the `Box::new` method. -Also it is not possible in stable Rust to destructure a `Box` in a match -pattern. The unstable `box` keyword can be used to create a `Box`. An example -usage would be: +The tracking issue for this feature is: [#70530] -```rust -#![feature(box_syntax)] +[#70530]: https://github.com/rust-lang/rust/issues/70530 -fn main() { - let b = box 5; -} -``` +------------------------ +"##, + }, + Lint { + label: "btreemap_alloc", + description: r##"# `btreemap_alloc` + +The tracking issue for this feature is: [#32838] + +[#32838]: https://github.com/rust-lang/rust/issues/32838 + +------------------------ +"##, + }, + Lint { + label: "buf_read_has_data_left", + description: r##"# `buf_read_has_data_left` + +The tracking issue for this feature is: [#86423] + +[#86423]: https://github.com/rust-lang/rust/issues/86423 + +------------------------ +"##, + }, + Lint { + label: "builtin_syntax", + description: r##"# `builtin_syntax` + +The tracking issue for this feature is: [#110680] + +[#110680]: https://github.com/rust-lang/rust/issues/110680 + +------------------------ +"##, + }, + Lint { + label: "byte_slice_trim_ascii", + description: r##"# `byte_slice_trim_ascii` + +The tracking issue for this feature is: [#94035] + +[#94035]: https://github.com/rust-lang/rust/issues/94035 + +------------------------ +"##, + }, + Lint { + label: "c_size_t", + description: r##"# `c_size_t` + +The tracking issue for this feature is: [#88345] + +[#88345]: https://github.com/rust-lang/rust/issues/88345 + +------------------------ +"##, + }, + Lint { + label: "c_str_literals", + description: r##"# `c_str_literals` + +The tracking issue for this feature is: [#105723] + +[#105723]: https://github.com/rust-lang/rust/issues/105723 + +------------------------ "##, }, Lint { @@ -1349,9 +2196,20 @@ The tracking issue for this feature is: [#74990] ------------------------ -Introduces four new ABI strings: "C-unwind", "stdcall-unwind", -"thiscall-unwind", and "system-unwind". These enable unwinding from other -languages (such as C++) into Rust frames and from Rust into other languages. +Introduces new ABI strings: +- "C-unwind" +- "cdecl-unwind" +- "stdcall-unwind" +- "fastcall-unwind" +- "vectorcall-unwind" +- "thiscall-unwind" +- "aapcs-unwind" +- "win64-unwind" +- "sysv64-unwind" +- "system-unwind" + +These enable unwinding from other languages (such as C++) into Rust frames and +from Rust into other languages. See [RFC 2945] for more information. @@ -1369,7 +2227,7 @@ The tracking issue for this feature is: [#44930] ------------------------ The `c_variadic` language feature enables C-variadic functions to be -defined in Rust. The may be called both from within Rust and via FFI. +defined in Rust. They may be called both from within Rust and via FFI. ## Examples @@ -1426,52 +2284,98 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { - label: "cfg_panic", - description: r##"# `cfg_panic` + label: "can_vector", + description: r##"# `can_vector` -The tracking issue for this feature is: [#77443] +The tracking issue for this feature is: [#69941] -[#77443]: https://github.com/rust-lang/rust/issues/77443 +[#69941]: https://github.com/rust-lang/rust/issues/69941 ------------------------ +"##, + }, + Lint { + label: "cell_leak", + description: r##"# `cell_leak` -The `cfg_panic` feature makes it possible to execute different code -depending on the panic strategy. - -Possible values at the moment are `"unwind"` or `"abort"`, although -it is possible that new panic strategies may be added to Rust in the -future. +The tracking issue for this feature is: [#69099] -## Examples +[#69099]: https://github.com/rust-lang/rust/issues/69099 -```rust -#![feature(cfg_panic)] +------------------------ +"##, + }, + Lint { + label: "cell_update", + description: r##"# `cell_update` -#[cfg(panic = "unwind")] -fn a() { - // ... -} +The tracking issue for this feature is: [#50186] -#[cfg(not(panic = "unwind"))] -fn a() { - // ... -} +[#50186]: https://github.com/rust-lang/rust/issues/50186 -fn b() { - if cfg!(panic = "abort") { - // ... - } else { - // ... - } -} -``` +------------------------ "##, }, Lint { - label: "cfg_sanitize", - description: r##"# `cfg_sanitize` + label: "cfg_accessible", + description: r##"# `cfg_accessible` -The tracking issue for this feature is: [#39699] +The tracking issue for this feature is: [#64797] + +[#64797]: https://github.com/rust-lang/rust/issues/64797 + +------------------------ +"##, + }, + Lint { + label: "cfg_eval", + description: r##"# `cfg_eval` + +The tracking issue for this feature is: [#82679] + +[#82679]: https://github.com/rust-lang/rust/issues/82679 + +------------------------ +"##, + }, + Lint { + label: "cfg_match", + description: r##"# `cfg_match` + +The tracking issue for this feature is: [#115585] + +[#115585]: https://github.com/rust-lang/rust/issues/115585 + +------------------------ +"##, + }, + Lint { + label: "cfg_overflow_checks", + description: r##"# `cfg_overflow_checks` + +The tracking issue for this feature is: [#111466] + +[#111466]: https://github.com/rust-lang/rust/issues/111466 + +------------------------ +"##, + }, + Lint { + label: "cfg_relocation_model", + description: r##"# `cfg_relocation_model` + +The tracking issue for this feature is: [#114929] + +[#114929]: https://github.com/rust-lang/rust/issues/114929 + +------------------------ +"##, + }, + Lint { + label: "cfg_sanitize", + description: r##"# `cfg_sanitize` + +The tracking issue for this feature is: [#39699] [#39699]: https://github.com/rust-lang/rust/issues/39699 @@ -1503,6 +2407,61 @@ fn b() { } } ``` +"##, + }, + Lint { + label: "cfg_target_abi", + description: r##"# `cfg_target_abi` + +The tracking issue for this feature is: [#80970] + +[#80970]: https://github.com/rust-lang/rust/issues/80970 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_compact", + description: r##"# `cfg_target_compact` + +The tracking issue for this feature is: [#96901] + +[#96901]: https://github.com/rust-lang/rust/issues/96901 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_has_atomic", + description: r##"# `cfg_target_has_atomic` + +The tracking issue for this feature is: [#94039] + +[#94039]: https://github.com/rust-lang/rust/issues/94039 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_has_atomic_equal_alignment", + description: r##"# `cfg_target_has_atomic_equal_alignment` + +The tracking issue for this feature is: [#93822] + +[#93822]: https://github.com/rust-lang/rust/issues/93822 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_thread_local", + description: r##"# `cfg_target_thread_local` + +The tracking issue for this feature is: [#29594] + +[#29594]: https://github.com/rust-lang/rust/issues/29594 + +------------------------ "##, }, Lint { @@ -1545,10 +2504,72 @@ fn b() { "##, }, Lint { - label: "char_error_internals", - description: r##"# `char_error_internals` + label: "cfi_encoding", + description: r##"# `cfi_encoding` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#89653] + +[#89653]: https://github.com/rust-lang/rust/issues/89653 + +------------------------ + +The `cfi_encoding` feature allows the user to define a CFI encoding for a type. +It allows the user to use a different names for types that otherwise would be +required to have the same name as used in externally defined C functions. + +## Examples + +```rust +#![feature(cfi_encoding, extern_types)] + +#[cfi_encoding = "3Foo"] +pub struct Type1(i32); + +extern { + #[cfi_encoding = "3Bar"] + type Type2; +} +``` +"##, + }, + Lint { + label: "char_indices_offset", + description: r##"# `char_indices_offset` + +The tracking issue for this feature is: [#83871] + +[#83871]: https://github.com/rust-lang/rust/issues/83871 + +------------------------ +"##, + }, + Lint { + label: "char_internals", + description: r##"# `char_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "char_min", + description: r##"# `char_min` + +The tracking issue for this feature is: [#114298] + +[#114298]: https://github.com/rust-lang/rust/issues/114298 + +------------------------ +"##, + }, + Lint { + label: "closure_lifetime_binder", + description: r##"# `closure_lifetime_binder` + +The tracking issue for this feature is: [#97362] + +[#97362]: https://github.com/rust-lang/rust/issues/97362 ------------------------ "##, @@ -1567,6 +2588,17 @@ Allows using the `#[track_caller]` attribute on closures and generators. Calls made to the closure or generator will have caller information available through `std::panic::Location::caller()`, just like using `#[track_caller]` on a function. +"##, + }, + Lint { + label: "cmp_minmax", + description: r##"# `cmp_minmax` + +The tracking issue for this feature is: [#115939] + +[#115939]: https://github.com/rust-lang/rust/issues/115939 + +------------------------ "##, }, Lint { @@ -1652,6 +2684,28 @@ $ arm-none-eabi-objdump -D function.o 3c: f7ff fffe bl 0 <_ZN4core9panicking5panic17h5c028258ca2fb3f5E> 40: defe udf #254 ; 0xfe ``` +"##, + }, + Lint { + label: "coerce_unsized", + description: r##"# `coerce_unsized` + +The tracking issue for this feature is: [#18598] + +[#18598]: https://github.com/rust-lang/rust/issues/18598 + +------------------------ +"##, + }, + Lint { + label: "collapse_debuginfo", + description: r##"# `collapse_debuginfo` + +The tracking issue for this feature is: [#100758] + +[#100758]: https://github.com/rust-lang/rust/issues/100758 + +------------------------ "##, }, Lint { @@ -1660,6 +2714,17 @@ $ arm-none-eabi-objdump -D function.o This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "concat_bytes", + description: r##"# `concat_bytes` + +The tracking issue for this feature is: [#87555] + +[#87555]: https://github.com/rust-lang/rust/issues/87555 + ------------------------ "##, }, @@ -1690,988 +2755,4496 @@ fn main() { "##, }, Lint { - label: "const_eval_limit", - description: r##"# `const_eval_limit` + label: "const_align_of_val", + description: r##"# `const_align_of_val` -The tracking issue for this feature is: [#67217] +The tracking issue for this feature is: [#46571] -[#67217]: https://github.com/rust-lang/rust/issues/67217 +[#46571]: https://github.com/rust-lang/rust/issues/46571 -The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. +------------------------ "##, }, Lint { - label: "core_intrinsics", - description: r##"# `core_intrinsics` + label: "const_align_of_val_raw", + description: r##"# `const_align_of_val_raw` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 ------------------------ "##, }, Lint { - label: "core_panic", - description: r##"# `core_panic` + label: "const_align_offset", + description: r##"# `const_align_offset` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#90962] + +[#90962]: https://github.com/rust-lang/rust/issues/90962 ------------------------ "##, }, Lint { - label: "core_private_bignum", - description: r##"# `core_private_bignum` + label: "const_alloc_error", + description: r##"# `const_alloc_error` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#92523] + +[#92523]: https://github.com/rust-lang/rust/issues/92523 ------------------------ "##, }, Lint { - label: "core_private_diy_float", - description: r##"# `core_private_diy_float` + label: "const_alloc_layout", + description: r##"# `const_alloc_layout` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#67521] + +[#67521]: https://github.com/rust-lang/rust/issues/67521 ------------------------ "##, }, Lint { - label: "crate_visibility_modifier", - description: r##"# `crate_visibility_modifier` + label: "const_arguments_as_str", + description: r##"# `const_arguments_as_str` -The tracking issue for this feature is: [#53120] +The tracking issue for this feature is: [#103900] -[#53120]: https://github.com/rust-lang/rust/issues/53120 +[#103900]: https://github.com/rust-lang/rust/issues/103900 ------ +------------------------ +"##, + }, + Lint { + label: "const_array_from_ref", + description: r##"# `const_array_from_ref` -The `crate_visibility_modifier` feature allows the `crate` keyword to be used -as a visibility modifier synonymous to `pub(crate)`, indicating that a type -(function, _&c._) is to be visible to the entire enclosing crate, but not to -other crates. +The tracking issue for this feature is: [#90206] -```rust -#![feature(crate_visibility_modifier)] +[#90206]: https://github.com/rust-lang/rust/issues/90206 -crate struct Foo { - bar: usize, -} -``` +------------------------ "##, }, Lint { - label: "custom_test_frameworks", - description: r##"# `custom_test_frameworks` + label: "const_array_into_iter_constructors", + description: r##"# `const_array_into_iter_constructors` -The tracking issue for this feature is: [#50297] +The tracking issue for this feature is: [#91583] -[#50297]: https://github.com/rust-lang/rust/issues/50297 +[#91583]: https://github.com/rust-lang/rust/issues/91583 ------------------------ +"##, + }, + Lint { + label: "const_assert_type2", + description: r##"# `const_assert_type2` -The `custom_test_frameworks` feature allows the use of `#[test_case]` and `#![test_runner]`. -Any function, const, or static can be annotated with `#[test_case]` causing it to be aggregated (like `#[test]`) -and be passed to the test runner determined by the `#![test_runner]` crate attribute. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -```rust -#![feature(custom_test_frameworks)] -#![test_runner(my_runner)] +------------------------ +"##, + }, + Lint { + label: "const_assume", + description: r##"# `const_assume` -fn my_runner(tests: &[&i32]) { - for t in tests { - if **t == 0 { - println!("PASSED"); - } else { - println!("FAILED"); - } - } -} +The tracking issue for this feature is: [#76972] -#[test_case] -const WILL_PASS: i32 = 0; +[#76972]: https://github.com/rust-lang/rust/issues/76972 -#[test_case] -const WILL_FAIL: i32 = 4; -``` +------------------------ "##, }, Lint { - label: "dec2flt", - description: r##"# `dec2flt` + label: "const_async_blocks", + description: r##"# `const_async_blocks` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#85368] + +[#85368]: https://github.com/rust-lang/rust/issues/85368 ------------------------ "##, }, Lint { - label: "default_free_fn", - description: r##"# `default_free_fn` + label: "const_bigint_helper_methods", + description: r##"# `const_bigint_helper_methods` -The tracking issue for this feature is: [#73014] +The tracking issue for this feature is: [#85532] -[#73014]: https://github.com/rust-lang/rust/issues/73014 +[#85532]: https://github.com/rust-lang/rust/issues/85532 ------------------------ +"##, + }, + Lint { + label: "const_black_box", + description: r##"# `const_black_box` -Adds a free `default()` function to the `std::default` module. This function -just forwards to [`Default::default()`], but may remove repetition of the word -"default" from the call site. - -[`Default::default()`]: https://doc.rust-lang.org/nightly/std/default/trait.Default.html#tymethod.default +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -Here is an example: +------------------------ +"##, + }, + Lint { + label: "const_box", + description: r##"# `const_box` -```rust -#![feature(default_free_fn)] -use std::default::default; +The tracking issue for this feature is: [#92521] -#[derive(Default)] -struct AppConfig { - foo: FooConfig, - bar: BarConfig, -} +[#92521]: https://github.com/rust-lang/rust/issues/92521 -#[derive(Default)] -struct FooConfig { - foo: i32, -} +------------------------ +"##, + }, + Lint { + label: "const_btree_len", + description: r##"# `const_btree_len` -#[derive(Default)] -struct BarConfig { - bar: f32, - baz: u8, -} +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -fn main() { - let options = AppConfig { - foo: default(), - bar: BarConfig { - bar: 10.1, - ..default() - }, - }; -} -``` +------------------------ "##, }, Lint { - label: "derive_clone_copy", - description: r##"# `derive_clone_copy` + label: "const_caller_location", + description: r##"# `const_caller_location` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#76156] + +[#76156]: https://github.com/rust-lang/rust/issues/76156 ------------------------ "##, }, Lint { - label: "derive_eq", - description: r##"# `derive_eq` + label: "const_cell_into_inner", + description: r##"# `const_cell_into_inner` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#78729] + +[#78729]: https://github.com/rust-lang/rust/issues/78729 ------------------------ "##, }, Lint { - label: "doc_cfg", - description: r##"# `doc_cfg` + label: "const_char_from_u32_unchecked", + description: r##"# `const_char_from_u32_unchecked` -The tracking issue for this feature is: [#43781] +The tracking issue for this feature is: [#89259] ------- +[#89259]: https://github.com/rust-lang/rust/issues/89259 -The `doc_cfg` feature allows an API be documented as only available in some specific platforms. -This attribute has two effects: +------------------------ +"##, + }, + Lint { + label: "const_closures", + description: r##"# `const_closures` -1. In the annotated item's documentation, there will be a message saying "This is supported on - (platform) only". +The tracking issue for this feature is: [#106003] -2. The item's doc-tests will only run on the specific platform. +[#106003]: https://github.com/rust-lang/rust/issues/106003 -In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a -special conditional compilation flag, `#[cfg(doc)]`, set whenever building documentation on your -crate. +------------------------ +"##, + }, + Lint { + label: "const_collections_with_hasher", + description: r##"# `const_collections_with_hasher` -This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the -standard library be documented. +The tracking issue for this feature is: [#102575] -```rust -#![feature(doc_cfg)] +[#102575]: https://github.com/rust-lang/rust/issues/102575 -#[cfg(any(windows, doc))] -#[doc(cfg(windows))] -/// The application's icon in the notification area (a.k.a. system tray). -/// -/// # Examples -/// -/// ```no_run -/// extern crate my_awesome_ui_library; -/// use my_awesome_ui_library::current_app; -/// use my_awesome_ui_library::windows::notification; -/// -/// let icon = current_app().get::(); -/// icon.show(); -/// icon.show_message("Hello"); -/// ``` -pub struct Icon { - // ... -} -``` - -[#43781]: https://github.com/rust-lang/rust/issues/43781 -[#43348]: https://github.com/rust-lang/rust/issues/43348 +------------------------ "##, }, Lint { - label: "doc_masked", - description: r##"# `doc_masked` + label: "const_cow_is_borrowed", + description: r##"# `const_cow_is_borrowed` -The tracking issue for this feature is: [#44027] +The tracking issue for this feature is: [#65143] ------ +[#65143]: https://github.com/rust-lang/rust/issues/65143 -The `doc_masked` feature allows a crate to exclude types from a given crate from appearing in lists -of trait implementations. The specifics of the feature are as follows: +------------------------ +"##, + }, + Lint { + label: "const_cstr_from_ptr", + description: r##"# `const_cstr_from_ptr` -1. When rustdoc encounters an `extern crate` statement annotated with a `#[doc(masked)]` attribute, - it marks the crate as being masked. +The tracking issue for this feature is: [#113219] -2. When listing traits a given type implements, rustdoc ensures that traits from masked crates are - not emitted into the documentation. +[#113219]: https://github.com/rust-lang/rust/issues/113219 -3. When listing types that implement a given trait, rustdoc ensures that types from masked crates - are not emitted into the documentation. +------------------------ +"##, + }, + Lint { + label: "const_discriminant", + description: r##"# `const_discriminant` -This feature was introduced in PR [#44026] to ensure that compiler-internal and -implementation-specific types and traits were not included in the standard library's documentation. -Such types would introduce broken links into the documentation. +The tracking issue for this feature is: [#69821] -[#44026]: https://github.com/rust-lang/rust/pull/44026 -[#44027]: https://github.com/rust-lang/rust/pull/44027 +[#69821]: https://github.com/rust-lang/rust/issues/69821 + +------------------------ "##, }, Lint { - label: "doc_notable_trait", - description: r##"# `doc_notable_trait` + label: "const_eval_select", + description: r##"# `const_eval_select` -The tracking issue for this feature is: [#45040] +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -The `doc_notable_trait` feature allows the use of the `#[doc(notable_trait)]` -attribute, which will display the trait in a "Notable traits" dialog for -functions returning types that implement the trait. For example, this attribute -is applied to the `Iterator`, `Future`, `io::Read`, and `io::Write` traits in -the standard library. +------------------------ +"##, + }, + Lint { + label: "const_exact_div", + description: r##"# `const_exact_div` -You can do this on your own traits like so: +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -``` -#![feature(doc_notable_trait)] +------------------------ +"##, + }, + Lint { + label: "const_extern_fn", + description: r##"# `const_extern_fn` -#[doc(notable_trait)] -pub trait MyTrait {} +The tracking issue for this feature is: [#64926] -pub struct MyStruct; -impl MyTrait for MyStruct {} +[#64926]: https://github.com/rust-lang/rust/issues/64926 -/// The docs for this function will have a button that displays a dialog about -/// `MyStruct` implementing `MyTrait`. -pub fn my_fn() -> MyStruct { MyStruct } -``` +------------------------ +"##, + }, + Lint { + label: "const_float_bits_conv", + description: r##"# `const_float_bits_conv` -This feature was originally implemented in PR [#45039]. +The tracking issue for this feature is: [#72447] -See also its documentation in [the rustdoc book][rustdoc-book-notable_trait]. +[#72447]: https://github.com/rust-lang/rust/issues/72447 -[#45040]: https://github.com/rust-lang/rust/issues/45040 -[#45039]: https://github.com/rust-lang/rust/pull/45039 -[rustdoc-book-notable_trait]: ../../rustdoc/unstable-features.html#adding-your-trait-to-the-notable-traits-dialog +------------------------ "##, }, Lint { - label: "exclusive_range_pattern", - description: r##"# `exclusive_range_pattern` + label: "const_float_classify", + description: r##"# `const_float_classify` -The tracking issue for this feature is: [#37854]. +The tracking issue for this feature is: [#72505] +[#72505]: https://github.com/rust-lang/rust/issues/72505 -[#67264]: https://github.com/rust-lang/rust/issues/67264 -[#37854]: https://github.com/rust-lang/rust/issues/37854 ------ +------------------------ +"##, + }, + Lint { + label: "const_fmt_arguments_new", + description: r##"# `const_fmt_arguments_new` -The `exclusive_range_pattern` feature allows non-inclusive range -patterns (`0..10`) to be used in appropriate pattern matching -contexts. It also can be combined with `#![feature(half_open_range_patterns]` -to be able to use RangeTo patterns (`..10`). +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -It also enabled RangeFrom patterns but that has since been -stabilized. +------------------------ +"##, + }, + Lint { + label: "const_fn_floating_point_arithmetic", + description: r##"# `const_fn_floating_point_arithmetic` -```rust -#![feature(exclusive_range_pattern)] - let x = 5; - match x { - 0..10 => println!("single digit"), - 10 => println!("ten isn't part of the above range"), - _ => println!("nor is everything else.") - } -``` +The tracking issue for this feature is: [#57241] + +[#57241]: https://github.com/rust-lang/rust/issues/57241 + +------------------------ "##, }, Lint { - label: "explicit_generic_args_with_impl_trait", - description: r##"# `explicit_generic_args_with_impl_trait` + label: "const_for", + description: r##"# `const_for` -The tracking issue for this feature is: [#83701] +The tracking issue for this feature is: [#87575] -[#83701]: https://github.com/rust-lang/rust/issues/83701 +[#87575]: https://github.com/rust-lang/rust/issues/87575 ------------------------ +"##, + }, + Lint { + label: "const_format_args", + description: r##"# `const_format_args` -The `explicit_generic_args_with_impl_trait` feature gate lets you specify generic arguments even -when `impl Trait` is used in argument position. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -A simple example is: +------------------------ +"##, + }, + Lint { + label: "const_hash", + description: r##"# `const_hash` -```rust -#![feature(explicit_generic_args_with_impl_trait)] +The tracking issue for this feature is: [#104061] -fn foo(_f: impl AsRef) {} +[#104061]: https://github.com/rust-lang/rust/issues/104061 -fn main() { - foo::("".to_string()); -} -``` +------------------------ +"##, + }, + Lint { + label: "const_heap", + description: r##"# `const_heap` -This is currently rejected: +The tracking issue for this feature is: [#79597] -```text -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> src/main.rs:6:11 - | -6 | foo::("".to_string()); - | ^^^ explicit generic argument not allowed +[#79597]: https://github.com/rust-lang/rust/issues/79597 -``` +------------------------ +"##, + }, + Lint { + label: "const_index_range_slice_index", + description: r##"# `const_index_range_slice_index` -However it would compile if `explicit_generic_args_with_impl_trait` is enabled. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_inherent_unchecked_arith", + description: r##"# `const_inherent_unchecked_arith` -Note that the synthetic type parameters from `impl Trait` are still implicit and you -cannot explicitly specify these: +The tracking issue for this feature is: [#85122] -```rust,compile_fail -#![feature(explicit_generic_args_with_impl_trait)] +[#85122]: https://github.com/rust-lang/rust/issues/85122 -fn foo(_f: impl AsRef) {} -fn bar>(_f: F) {} +------------------------ +"##, + }, + Lint { + label: "const_int_unchecked_arith", + description: r##"# `const_int_unchecked_arith` -fn main() { - bar::("".to_string()); // Okay - bar::("".to_string()); // Okay +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. - foo::("".to_string()); // Okay - foo::("".to_string()); // Error, you cannot specify `impl Trait` explicitly -} -``` +------------------------ "##, }, Lint { - label: "fd", - description: r##"# `fd` + label: "const_intoiterator_identity", + description: r##"# `const_intoiterator_identity` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#90603] + +[#90603]: https://github.com/rust-lang/rust/issues/90603 ------------------------ "##, }, Lint { - label: "fd_read", - description: r##"# `fd_read` + label: "const_intrinsic_compare_bytes", + description: r##"# `const_intrinsic_compare_bytes` -This feature is internal to the Rust compiler and is not intended for general use. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, }, Lint { - label: "ffi_const", - description: r##"# `ffi_const` + label: "const_intrinsic_forget", + description: r##"# `const_intrinsic_forget` -The tracking issue for this feature is: [#58328] +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------- +------------------------ +"##, + }, + Lint { + label: "const_intrinsic_raw_eq", + description: r##"# `const_intrinsic_raw_eq` -The `#[ffi_const]` attribute applies clang's `const` attribute to foreign -functions declarations. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -That is, `#[ffi_const]` functions shall have no effects except for its return -value, which can only depend on the values of the function parameters, and is -not affected by changes to the observable state of the program. +------------------------ +"##, + }, + Lint { + label: "const_io_structs", + description: r##"# `const_io_structs` -Applying the `#[ffi_const]` attribute to a function that violates these -requirements is undefined behaviour. +The tracking issue for this feature is: [#78812] -This attribute enables Rust to perform common optimizations, like sub-expression -elimination, and it can avoid emitting some calls in repeated invocations of the -function with the same argument values regardless of other operations being -performed in between these functions calls (as opposed to `#[ffi_pure]` -functions). +[#78812]: https://github.com/rust-lang/rust/issues/78812 -## Pitfalls +------------------------ +"##, + }, + Lint { + label: "const_ip", + description: r##"# `const_ip` -A `#[ffi_const]` function can only read global memory that would not affect -its return value for the whole execution of the program (e.g. immutable global -memory). `#[ffi_const]` functions are referentially-transparent and therefore -more strict than `#[ffi_pure]` functions. +The tracking issue for this feature is: [#76205] -A common pitfall involves applying the `#[ffi_const]` attribute to a -function that reads memory through pointer arguments which do not necessarily -point to immutable global memory. +[#76205]: https://github.com/rust-lang/rust/issues/76205 -A `#[ffi_const]` function that returns unit has no effect on the abstract -machine's state, and a `#[ffi_const]` function cannot be `#[ffi_pure]`. +------------------------ +"##, + }, + Lint { + label: "const_ipv4", + description: r##"# `const_ipv4` -A `#[ffi_const]` function must not diverge, neither via a side effect (e.g. a -call to `abort`) nor by infinite loops. +The tracking issue for this feature is: [#76205] -When translating C headers to Rust FFI, it is worth verifying for which targets -the `const` attribute is enabled in those headers, and using the appropriate -`cfg` macros in the Rust side to match those definitions. While the semantics of -`const` are implemented identically by many C and C++ compilers, e.g., clang, -[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily -implemented in this way on all of them. It is therefore also worth verifying -that the semantics of the C toolchain used to compile the binary being linked -against are compatible with those of the `#[ffi_const]`. +[#76205]: https://github.com/rust-lang/rust/issues/76205 -[#58328]: https://github.com/rust-lang/rust/issues/58328 -[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacgigch.html -[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute -[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_const.htm +------------------------ "##, }, Lint { - label: "ffi_pure", - description: r##"# `ffi_pure` + label: "const_ipv6", + description: r##"# `const_ipv6` -The tracking issue for this feature is: [#58329] +The tracking issue for this feature is: [#76205] ------- +[#76205]: https://github.com/rust-lang/rust/issues/76205 -The `#[ffi_pure]` attribute applies clang's `pure` attribute to foreign -functions declarations. +------------------------ +"##, + }, + Lint { + label: "const_likely", + description: r##"# `const_likely` -That is, `#[ffi_pure]` functions shall have no effects except for its return -value, which shall not change across two consecutive function calls with -the same parameters. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -Applying the `#[ffi_pure]` attribute to a function that violates these -requirements is undefined behavior. +------------------------ +"##, + }, + Lint { + label: "const_location_fields", + description: r##"# `const_location_fields` -This attribute enables Rust to perform common optimizations, like sub-expression -elimination and loop optimizations. Some common examples of pure functions are -`strlen` or `memcmp`. +The tracking issue for this feature is: [#102911] -These optimizations are only applicable when the compiler can prove that no -program state observable by the `#[ffi_pure]` function has changed between calls -of the function, which could alter the result. See also the `#[ffi_const]` -attribute, which provides stronger guarantees regarding the allowable behavior -of a function, enabling further optimization. +[#102911]: https://github.com/rust-lang/rust/issues/102911 -## Pitfalls +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_array_assume_init", + description: r##"# `const_maybe_uninit_array_assume_init` -A `#[ffi_pure]` function can read global memory through the function -parameters (e.g. pointers), globals, etc. `#[ffi_pure]` functions are not -referentially-transparent, and are therefore more relaxed than `#[ffi_const]` -functions. +The tracking issue for this feature is: [#96097] -However, accessing global memory through volatile or atomic reads can violate the -requirement that two consecutive function calls shall return the same value. +[#96097]: https://github.com/rust-lang/rust/issues/96097 -A `pure` function that returns unit has no effect on the abstract machine's -state. - -A `#[ffi_pure]` function must not diverge, neither via a side effect (e.g. a -call to `abort`) nor by infinite loops. +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_as_mut_ptr", + description: r##"# `const_maybe_uninit_as_mut_ptr` -When translating C headers to Rust FFI, it is worth verifying for which targets -the `pure` attribute is enabled in those headers, and using the appropriate -`cfg` macros in the Rust side to match those definitions. While the semantics of -`pure` are implemented identically by many C and C++ compilers, e.g., clang, -[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily -implemented in this way on all of them. It is therefore also worth verifying -that the semantics of the C toolchain used to compile the binary being linked -against are compatible with those of the `#[ffi_pure]`. +The tracking issue for this feature is: [#75251] +[#75251]: https://github.com/rust-lang/rust/issues/75251 -[#58329]: https://github.com/rust-lang/rust/issues/58329 -[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html -[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute -[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm +------------------------ "##, }, Lint { - label: "flt2dec", - description: r##"# `flt2dec` + label: "const_maybe_uninit_assume_init", + description: r##"# `const_maybe_uninit_assume_init` -This feature is internal to the Rust compiler and is not intended for general use. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, }, Lint { - label: "fmt_internals", - description: r##"# `fmt_internals` + label: "const_maybe_uninit_assume_init_read", + description: r##"# `const_maybe_uninit_assume_init_read` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#63567] + +[#63567]: https://github.com/rust-lang/rust/issues/63567 ------------------------ "##, }, Lint { - label: "fn_traits", - description: r##"# `fn_traits` - -The tracking issue for this feature is [#29625] + label: "const_maybe_uninit_uninit_array", + description: r##"# `const_maybe_uninit_uninit_array` -See Also: [`unboxed_closures`](../language-features/unboxed-closures.md) +The tracking issue for this feature is: [#96097] -[#29625]: https://github.com/rust-lang/rust/issues/29625 +[#96097]: https://github.com/rust-lang/rust/issues/96097 ----- +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_write", + description: r##"# `const_maybe_uninit_write` -The `fn_traits` feature allows for implementation of the [`Fn*`] traits -for creating custom closure-like types. +The tracking issue for this feature is: [#63567] -[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html +[#63567]: https://github.com/rust-lang/rust/issues/63567 -```rust -#![feature(unboxed_closures)] -#![feature(fn_traits)] +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_zeroed", + description: r##"# `const_maybe_uninit_zeroed` -struct Adder { - a: u32 -} +The tracking issue for this feature is: [#91850] -impl FnOnce<(u32, )> for Adder { - type Output = u32; - extern "rust-call" fn call_once(self, b: (u32, )) -> Self::Output { - self.a + b.0 - } -} +[#91850]: https://github.com/rust-lang/rust/issues/91850 -fn main() { - let adder = Adder { a: 3 }; - assert_eq!(adder(2), 5); -} -``` +------------------------ "##, }, Lint { - label: "generators", - description: r##"# `generators` + label: "const_mut_refs", + description: r##"# `const_mut_refs` -The tracking issue for this feature is: [#43122] +The tracking issue for this feature is: [#57349] -[#43122]: https://github.com/rust-lang/rust/issues/43122 +[#57349]: https://github.com/rust-lang/rust/issues/57349 ------------------------ +"##, + }, + Lint { + label: "const_nonnull_new", + description: r##"# `const_nonnull_new` -The `generators` feature gate in Rust allows you to define generator or -coroutine literals. A generator is a "resumable function" that syntactically -resembles a closure but compiles to much different semantics in the compiler -itself. The primary feature of a generator is that it can be suspended during -execution to be resumed at a later date. Generators use the `yield` keyword to -"return", and then the caller can `resume` a generator to resume execution just -after the `yield` keyword. +The tracking issue for this feature is: [#93235] -Generators are an extra-unstable feature in the compiler right now. Added in -[RFC 2033] they're mostly intended right now as a information/constraint -gathering phase. The intent is that experimentation can happen on the nightly -compiler before actual stabilization. A further RFC will be required to -stabilize generators/coroutines and will likely contain at least a few small -tweaks to the overall design. +[#93235]: https://github.com/rust-lang/rust/issues/93235 -[RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 +------------------------ +"##, + }, + Lint { + label: "const_num_midpoint", + description: r##"# `const_num_midpoint` -A syntactical example of a generator is: +The tracking issue for this feature is: [#110840] -```rust -#![feature(generators, generator_trait)] +[#110840]: https://github.com/rust-lang/rust/issues/110840 -use std::ops::{Generator, GeneratorState}; -use std::pin::Pin; +------------------------ +"##, + }, + Lint { + label: "const_option", + description: r##"# `const_option` -fn main() { - let mut generator = || { - yield 1; - return "foo" - }; +The tracking issue for this feature is: [#67441] - match Pin::new(&mut generator).resume(()) { - GeneratorState::Yielded(1) => {} - _ => panic!("unexpected value from resume"), - } - match Pin::new(&mut generator).resume(()) { - GeneratorState::Complete("foo") => {} - _ => panic!("unexpected value from resume"), - } -} -``` +[#67441]: https://github.com/rust-lang/rust/issues/67441 -Generators are closure-like literals which can contain a `yield` statement. The -`yield` statement takes an optional expression of a value to yield out of the -generator. All generator literals implement the `Generator` trait in the -`std::ops` module. The `Generator` trait has one main method, `resume`, which -resumes execution of the generator at the previous suspension point. +------------------------ +"##, + }, + Lint { + label: "const_option_ext", + description: r##"# `const_option_ext` -An example of the control flow of generators is that the following example -prints all numbers in order: +The tracking issue for this feature is: [#91930] -```rust -#![feature(generators, generator_trait)] +[#91930]: https://github.com/rust-lang/rust/issues/91930 -use std::ops::Generator; -use std::pin::Pin; +------------------------ +"##, + }, + Lint { + label: "const_pin", + description: r##"# `const_pin` -fn main() { - let mut generator = || { - println!("2"); - yield; - println!("4"); - }; +The tracking issue for this feature is: [#76654] - println!("1"); - Pin::new(&mut generator).resume(()); - println!("3"); - Pin::new(&mut generator).resume(()); - println!("5"); -} -``` +[#76654]: https://github.com/rust-lang/rust/issues/76654 -At this time the main intended use case of generators is an implementation -primitive for async/await syntax, but generators will likely be extended to -ergonomic implementations of iterators and other primitives in the future. -Feedback on the design and usage is always appreciated! +------------------------ +"##, + }, + Lint { + label: "const_pointer_byte_offsets", + description: r##"# `const_pointer_byte_offsets` -### The `Generator` trait +The tracking issue for this feature is: [#96283] -The `Generator` trait in `std::ops` currently looks like: +[#96283]: https://github.com/rust-lang/rust/issues/96283 -```rust -# #![feature(arbitrary_self_types, generator_trait)] -# use std::ops::GeneratorState; -# use std::pin::Pin; +------------------------ +"##, + }, + Lint { + label: "const_pointer_is_aligned", + description: r##"# `const_pointer_is_aligned` -pub trait Generator { - type Yield; - type Return; - fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState; -} -``` +The tracking issue for this feature is: [#104203] -The `Generator::Yield` type is the type of values that can be yielded with the -`yield` statement. The `Generator::Return` type is the returned type of the -generator. This is typically the last expression in a generator's definition or -any value passed to `return` in a generator. The `resume` function is the entry -point for executing the `Generator` itself. +[#104203]: https://github.com/rust-lang/rust/issues/104203 -The return value of `resume`, `GeneratorState`, looks like: +------------------------ +"##, + }, + Lint { + label: "const_precise_live_drops", + description: r##"# `const_precise_live_drops` -```rust -pub enum GeneratorState { - Yielded(Y), - Complete(R), -} -``` +The tracking issue for this feature is: [#73255] -The `Yielded` variant indicates that the generator can later be resumed. This -corresponds to a `yield` point in a generator. The `Complete` variant indicates -that the generator is complete and cannot be resumed again. Calling `resume` -after a generator has returned `Complete` will likely result in a panic of the -program. +[#73255]: https://github.com/rust-lang/rust/issues/73255 -### Closure-like semantics +------------------------ +"##, + }, + Lint { + label: "const_pref_align_of", + description: r##"# `const_pref_align_of` -The closure-like syntax for generators alludes to the fact that they also have -closure-like semantics. Namely: +The tracking issue for this feature is: [#91971] -* When created, a generator executes no code. A closure literal does not - actually execute any of the closure's code on construction, and similarly a - generator literal does not execute any code inside the generator when - constructed. +[#91971]: https://github.com/rust-lang/rust/issues/91971 -* Generators can capture outer variables by reference or by move, and this can - be tweaked with the `move` keyword at the beginning of the closure. Like - closures all generators will have an implicit environment which is inferred by - the compiler. Outer variables can be moved into a generator for use as the - generator progresses. +------------------------ +"##, + }, + Lint { + label: "const_ptr_as_ref", + description: r##"# `const_ptr_as_ref` -* Generator literals produce a value with a unique type which implements the - `std::ops::Generator` trait. This allows actual execution of the generator - through the `Generator::resume` method as well as also naming it in return - types and such. +The tracking issue for this feature is: [#91822] -* Traits like `Send` and `Sync` are automatically implemented for a `Generator` - depending on the captured variables of the environment. Unlike closures, - generators also depend on variables live across suspension points. This means - that although the ambient environment may be `Send` or `Sync`, the generator - itself may not be due to internal variables live across `yield` points being - not-`Send` or not-`Sync`. Note that generators do - not implement traits like `Copy` or `Clone` automatically. +[#91822]: https://github.com/rust-lang/rust/issues/91822 -* Whenever a generator is dropped it will drop all captured environment - variables. +------------------------ +"##, + }, + Lint { + label: "const_ptr_is_null", + description: r##"# `const_ptr_is_null` -### Generators as state machines +The tracking issue for this feature is: [#74939] -In the compiler, generators are currently compiled as state machines. Each -`yield` expression will correspond to a different state that stores all live -variables over that suspension point. Resumption of a generator will dispatch on -the current state and then execute internally until a `yield` is reached, at -which point all state is saved off in the generator and a value is returned. +[#74939]: https://github.com/rust-lang/rust/issues/74939 -Let's take a look at an example to see what's going on here: +------------------------ +"##, + }, + Lint { + label: "const_ptr_sub_ptr", + description: r##"# `const_ptr_sub_ptr` -```rust -#![feature(generators, generator_trait)] +The tracking issue for this feature is: [#95892] -use std::ops::Generator; -use std::pin::Pin; +[#95892]: https://github.com/rust-lang/rust/issues/95892 -fn main() { - let ret = "foo"; - let mut generator = move || { - yield 1; - return ret - }; +------------------------ +"##, + }, + Lint { + label: "const_ptr_write", + description: r##"# `const_ptr_write` - Pin::new(&mut generator).resume(()); - Pin::new(&mut generator).resume(()); -} -``` +The tracking issue for this feature is: [#86302] + +[#86302]: https://github.com/rust-lang/rust/issues/86302 + +------------------------ +"##, + }, + Lint { + label: "const_range_bounds", + description: r##"# `const_range_bounds` + +The tracking issue for this feature is: [#108082] + +[#108082]: https://github.com/rust-lang/rust/issues/108082 + +------------------------ +"##, + }, + Lint { + label: "const_raw_ptr_comparison", + description: r##"# `const_raw_ptr_comparison` + +The tracking issue for this feature is: [#53020] + +[#53020]: https://github.com/rust-lang/rust/issues/53020 + +------------------------ +"##, + }, + Lint { + label: "const_refs_to_cell", + description: r##"# `const_refs_to_cell` + +The tracking issue for this feature is: [#80384] + +[#80384]: https://github.com/rust-lang/rust/issues/80384 + +------------------------ +"##, + }, + Lint { + label: "const_replace", + description: r##"# `const_replace` + +The tracking issue for this feature is: [#83164] + +[#83164]: https://github.com/rust-lang/rust/issues/83164 + +------------------------ +"##, + }, + Lint { + label: "const_result", + description: r##"# `const_result` + +The tracking issue for this feature is: [#82814] + +[#82814]: https://github.com/rust-lang/rust/issues/82814 + +------------------------ +"##, + }, + Lint { + label: "const_size_of_val", + description: r##"# `const_size_of_val` + +The tracking issue for this feature is: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 + +------------------------ +"##, + }, + Lint { + label: "const_size_of_val_raw", + description: r##"# `const_size_of_val_raw` + +The tracking issue for this feature is: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 + +------------------------ +"##, + }, + Lint { + label: "const_slice_first_last", + description: r##"# `const_slice_first_last` + +The tracking issue for this feature is: [#83570] + +[#83570]: https://github.com/rust-lang/rust/issues/83570 + +------------------------ +"##, + }, + Lint { + label: "const_slice_from_mut_ptr_range", + description: r##"# `const_slice_from_mut_ptr_range` + +The tracking issue for this feature is: [#89792] + +[#89792]: https://github.com/rust-lang/rust/issues/89792 + +------------------------ +"##, + }, + Lint { + label: "const_slice_from_ptr_range", + description: r##"# `const_slice_from_ptr_range` + +The tracking issue for this feature is: [#89792] + +[#89792]: https://github.com/rust-lang/rust/issues/89792 + +------------------------ +"##, + }, + Lint { + label: "const_slice_from_raw_parts_mut", + description: r##"# `const_slice_from_raw_parts_mut` + +The tracking issue for this feature is: [#67456] + +[#67456]: https://github.com/rust-lang/rust/issues/67456 + +------------------------ +"##, + }, + Lint { + label: "const_slice_from_ref", + description: r##"# `const_slice_from_ref` + +The tracking issue for this feature is: [#90206] + +[#90206]: https://github.com/rust-lang/rust/issues/90206 + +------------------------ +"##, + }, + Lint { + label: "const_slice_index", + description: r##"# `const_slice_index` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_slice_ptr_len", + description: r##"# `const_slice_ptr_len` + +The tracking issue for this feature is: [#71146] + +[#71146]: https://github.com/rust-lang/rust/issues/71146 + +------------------------ +"##, + }, + Lint { + label: "const_slice_split_at_mut", + description: r##"# `const_slice_split_at_mut` + +The tracking issue for this feature is: [#101804] + +[#101804]: https://github.com/rust-lang/rust/issues/101804 + +------------------------ +"##, + }, + Lint { + label: "const_str_from_utf8", + description: r##"# `const_str_from_utf8` + +The tracking issue for this feature is: [#91006] + +[#91006]: https://github.com/rust-lang/rust/issues/91006 + +------------------------ +"##, + }, + Lint { + label: "const_str_from_utf8_unchecked_mut", + description: r##"# `const_str_from_utf8_unchecked_mut` + +The tracking issue for this feature is: [#91005] + +[#91005]: https://github.com/rust-lang/rust/issues/91005 + +------------------------ +"##, + }, + Lint { + label: "const_swap", + description: r##"# `const_swap` + +The tracking issue for this feature is: [#83163] + +[#83163]: https://github.com/rust-lang/rust/issues/83163 + +------------------------ +"##, + }, + Lint { + label: "const_trait_impl", + description: r##"# `const_trait_impl` + +The tracking issue for this feature is: [#67792] + +[#67792]: https://github.com/rust-lang/rust/issues/67792 + +------------------------ +"##, + }, + Lint { + label: "const_try", + description: r##"# `const_try` + +The tracking issue for this feature is: [#74935] + +[#74935]: https://github.com/rust-lang/rust/issues/74935 + +------------------------ +"##, + }, + Lint { + label: "const_type_id", + description: r##"# `const_type_id` + +The tracking issue for this feature is: [#77125] + +[#77125]: https://github.com/rust-lang/rust/issues/77125 + +------------------------ +"##, + }, + Lint { + label: "const_type_name", + description: r##"# `const_type_name` + +The tracking issue for this feature is: [#63084] + +[#63084]: https://github.com/rust-lang/rust/issues/63084 + +------------------------ +"##, + }, + Lint { + label: "const_unicode_case_lookup", + description: r##"# `const_unicode_case_lookup` + +The tracking issue for this feature is: [#101400] + +[#101400]: https://github.com/rust-lang/rust/issues/101400 + +------------------------ +"##, + }, + Lint { + label: "const_unsafecell_get_mut", + description: r##"# `const_unsafecell_get_mut` + +The tracking issue for this feature is: [#88836] + +[#88836]: https://github.com/rust-lang/rust/issues/88836 + +------------------------ +"##, + }, + Lint { + label: "const_waker", + description: r##"# `const_waker` + +The tracking issue for this feature is: [#102012] + +[#102012]: https://github.com/rust-lang/rust/issues/102012 + +------------------------ +"##, + }, + Lint { + label: "container_error_extra", + description: r##"# `container_error_extra` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "control_flow_enum", + description: r##"# `control_flow_enum` + +The tracking issue for this feature is: [#75744] + +[#75744]: https://github.com/rust-lang/rust/issues/75744 + +------------------------ +"##, + }, + Lint { + label: "convert_float_to_int", + description: r##"# `convert_float_to_int` + +The tracking issue for this feature is: [#67057] + +[#67057]: https://github.com/rust-lang/rust/issues/67057 + +------------------------ +"##, + }, + Lint { + label: "core_intrinsics", + description: r##"# `core_intrinsics` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "core_panic", + description: r##"# `core_panic` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "core_private_bignum", + description: r##"# `core_private_bignum` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "core_private_diy_float", + description: r##"# `core_private_diy_float` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "coverage_attribute", + description: r##"# `coverage_attribute` + +The tracking issue for this feature is: [#84605] + +[#84605]: https://github.com/rust-lang/rust/issues/84605 + +--- + +The `coverage` attribute can be used to selectively disable coverage +instrumentation in an annotated function. This might be useful to: + +- Avoid instrumentation overhead in a performance critical function +- Avoid generating coverage for a function that is not meant to be executed, + but still target 100% coverage for the rest of the program. + +## Example + +```rust +#![feature(coverage_attribute)] + +// `foo()` will get coverage instrumentation (by default) +fn foo() { + // ... +} + +#[coverage(off)] +fn bar() { + // ... +} +``` +"##, + }, + Lint { + label: "cow_is_borrowed", + description: r##"# `cow_is_borrowed` + +The tracking issue for this feature is: [#65143] + +[#65143]: https://github.com/rust-lang/rust/issues/65143 + +------------------------ +"##, + }, + Lint { + label: "csky_target_feature", + description: r##"# `csky_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "cstr_count_bytes", + description: r##"# `cstr_count_bytes` + +The tracking issue for this feature is: [#114441] + +[#114441]: https://github.com/rust-lang/rust/issues/114441 + +------------------------ +"##, + }, + Lint { + label: "cursor_remaining", + description: r##"# `cursor_remaining` + +The tracking issue for this feature is: [#86369] + +[#86369]: https://github.com/rust-lang/rust/issues/86369 + +------------------------ +"##, + }, + Lint { + label: "custom_code_classes_in_docs", + description: r##"# `custom_code_classes_in_docs` + +The tracking issue for this feature is: [#79483] + +[#79483]: https://github.com/rust-lang/rust/issues/79483 + +------------------------ +"##, + }, + Lint { + label: "custom_inner_attributes", + description: r##"# `custom_inner_attributes` + +The tracking issue for this feature is: [#54726] + +[#54726]: https://github.com/rust-lang/rust/issues/54726 + +------------------------ +"##, + }, + Lint { + label: "custom_mir", + description: r##"# `custom_mir` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "custom_test_frameworks", + description: r##"# `custom_test_frameworks` + +The tracking issue for this feature is: [#50297] + +[#50297]: https://github.com/rust-lang/rust/issues/50297 + +------------------------ + +The `custom_test_frameworks` feature allows the use of `#[test_case]` and `#![test_runner]`. +Any function, const, or static can be annotated with `#[test_case]` causing it to be aggregated (like `#[test]`) +and be passed to the test runner determined by the `#![test_runner]` crate attribute. + +```rust +#![feature(custom_test_frameworks)] +#![test_runner(my_runner)] + +fn my_runner(tests: &[&i32]) { + for t in tests { + if **t == 0 { + println!("PASSED"); + } else { + println!("FAILED"); + } + } +} + +#[test_case] +const WILL_PASS: i32 = 0; + +#[test_case] +const WILL_FAIL: i32 = 4; +``` +"##, + }, + Lint { + label: "deadline_api", + description: r##"# `deadline_api` + +The tracking issue for this feature is: [#46316] + +[#46316]: https://github.com/rust-lang/rust/issues/46316 + +------------------------ +"##, + }, + Lint { + label: "dec2flt", + description: r##"# `dec2flt` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "decl_macro", + description: r##"# `decl_macro` + +The tracking issue for this feature is: [#39412] + +[#39412]: https://github.com/rust-lang/rust/issues/39412 + +------------------------ +"##, + }, + Lint { + label: "default_type_parameter_fallback", + description: r##"# `default_type_parameter_fallback` + +The tracking issue for this feature is: [#27336] + +[#27336]: https://github.com/rust-lang/rust/issues/27336 + +------------------------ +"##, + }, + Lint { + label: "deprecated_safe", + description: r##"# `deprecated_safe` + +The tracking issue for this feature is: [#94978] + +[#94978]: https://github.com/rust-lang/rust/issues/94978 + +------------------------ +"##, + }, + Lint { + label: "deprecated_suggestion", + description: r##"# `deprecated_suggestion` + +The tracking issue for this feature is: [#94785] + +[#94785]: https://github.com/rust-lang/rust/issues/94785 + +------------------------ +"##, + }, + Lint { + label: "derive_clone_copy", + description: r##"# `derive_clone_copy` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "derive_const", + description: r##"# `derive_const` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "derive_eq", + description: r##"# `derive_eq` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "diagnostic_namespace", + description: r##"# `diagnostic_namespace` + +The tracking issue for this feature is: [#111996] + +[#111996]: https://github.com/rust-lang/rust/issues/111996 + +------------------------ +"##, + }, + Lint { + label: "dir_entry_ext2", + description: r##"# `dir_entry_ext2` + +The tracking issue for this feature is: [#85573] + +[#85573]: https://github.com/rust-lang/rust/issues/85573 + +------------------------ +"##, + }, + Lint { + label: "discriminant_kind", + description: r##"# `discriminant_kind` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "dispatch_from_dyn", + description: r##"# `dispatch_from_dyn` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "div_duration", + description: r##"# `div_duration` + +The tracking issue for this feature is: [#63139] + +[#63139]: https://github.com/rust-lang/rust/issues/63139 + +------------------------ +"##, + }, + Lint { + label: "do_not_recommend", + description: r##"# `do_not_recommend` + +The tracking issue for this feature is: [#51992] + +[#51992]: https://github.com/rust-lang/rust/issues/51992 + +------------------------ +"##, + }, + Lint { + label: "doc_auto_cfg", + description: r##"# `doc_auto_cfg` + +The tracking issue for this feature is: [#43781] + +[#43781]: https://github.com/rust-lang/rust/issues/43781 + +------------------------ +"##, + }, + Lint { + label: "doc_cfg", + description: r##"# `doc_cfg` + +The tracking issue for this feature is: [#43781] + +------ + +The `doc_cfg` feature allows an API be documented as only available in some specific platforms. +This attribute has two effects: + +1. In the annotated item's documentation, there will be a message saying "Available on + (platform) only". + +2. The item's doc-tests will only run on the specific platform. + +In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a +special conditional compilation flag, `#[cfg(doc)]`, set whenever building documentation on your +crate. + +This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the +standard library be documented. + +```rust +#![feature(doc_cfg)] + +#[cfg(any(windows, doc))] +#[doc(cfg(windows))] +/// The application's icon in the notification area (a.k.a. system tray). +/// +/// # Examples +/// +/// ```no_run +/// extern crate my_awesome_ui_library; +/// use my_awesome_ui_library::current_app; +/// use my_awesome_ui_library::windows::notification; +/// +/// let icon = current_app().get::(); +/// icon.show(); +/// icon.show_message("Hello"); +/// ``` +pub struct Icon { + // ... +} +``` + +[#43781]: https://github.com/rust-lang/rust/issues/43781 +[#43348]: https://github.com/rust-lang/rust/issues/43348 +"##, + }, + Lint { + label: "doc_cfg_hide", + description: r##"# `doc_cfg_hide` + +The tracking issue for this feature is: [#43781] + +[#43781]: https://github.com/rust-lang/rust/issues/43781 + +------------------------ +"##, + }, + Lint { + label: "doc_masked", + description: r##"# `doc_masked` + +The tracking issue for this feature is: [#44027] + +----- + +The `doc_masked` feature allows a crate to exclude types from a given crate from appearing in lists +of trait implementations. The specifics of the feature are as follows: + +1. When rustdoc encounters an `extern crate` statement annotated with a `#[doc(masked)]` attribute, + it marks the crate as being masked. + +2. When listing traits a given type implements, rustdoc ensures that traits from masked crates are + not emitted into the documentation. + +3. When listing types that implement a given trait, rustdoc ensures that types from masked crates + are not emitted into the documentation. + +This feature was introduced in PR [#44026] to ensure that compiler-internal and +implementation-specific types and traits were not included in the standard library's documentation. +Such types would introduce broken links into the documentation. + +[#44026]: https://github.com/rust-lang/rust/pull/44026 +[#44027]: https://github.com/rust-lang/rust/pull/44027 +"##, + }, + Lint { + label: "doc_notable_trait", + description: r##"# `doc_notable_trait` + +The tracking issue for this feature is: [#45040] + +The `doc_notable_trait` feature allows the use of the `#[doc(notable_trait)]` +attribute, which will display the trait in a "Notable traits" dialog for +functions returning types that implement the trait. For example, this attribute +is applied to the `Iterator`, `Future`, `io::Read`, and `io::Write` traits in +the standard library. + +You can do this on your own traits like so: + +``` +#![feature(doc_notable_trait)] + +#[doc(notable_trait)] +pub trait MyTrait {} + +pub struct MyStruct; +impl MyTrait for MyStruct {} + +/// The docs for this function will have a button that displays a dialog about +/// `MyStruct` implementing `MyTrait`. +pub fn my_fn() -> MyStruct { MyStruct } +``` + +This feature was originally implemented in PR [#45039]. + +See also its documentation in [the rustdoc book][rustdoc-book-notable_trait]. + +[#45040]: https://github.com/rust-lang/rust/issues/45040 +[#45039]: https://github.com/rust-lang/rust/pull/45039 +[rustdoc-book-notable_trait]: ../../rustdoc/unstable-features.html#adding-your-trait-to-the-notable-traits-dialog +"##, + }, + Lint { + label: "downcast_unchecked", + description: r##"# `downcast_unchecked` + +The tracking issue for this feature is: [#90850] + +[#90850]: https://github.com/rust-lang/rust/issues/90850 + +------------------------ +"##, + }, + Lint { + label: "drain_keep_rest", + description: r##"# `drain_keep_rest` + +The tracking issue for this feature is: [#101122] + +[#101122]: https://github.com/rust-lang/rust/issues/101122 + +------------------------ +"##, + }, + Lint { + label: "dropck_eyepatch", + description: r##"# `dropck_eyepatch` + +The tracking issue for this feature is: [#34761] + +[#34761]: https://github.com/rust-lang/rust/issues/34761 + +------------------------ +"##, + }, + Lint { + label: "duration_constants", + description: r##"# `duration_constants` + +The tracking issue for this feature is: [#57391] + +[#57391]: https://github.com/rust-lang/rust/issues/57391 + +------------------------ +"##, + }, + Lint { + label: "duration_consts_float", + description: r##"# `duration_consts_float` + +The tracking issue for this feature is: [#72440] + +[#72440]: https://github.com/rust-lang/rust/issues/72440 + +------------------------ +"##, + }, + Lint { + label: "dyn_star", + description: r##"# `dyn_star` + +The tracking issue for this feature is: [#102425] + +[#102425]: https://github.com/rust-lang/rust/issues/102425 + +------------------------ +"##, + }, + Lint { + label: "edition_panic", + description: r##"# `edition_panic` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "effects", + description: r##"# `effects` + +The tracking issue for this feature is: [#102090] + +[#102090]: https://github.com/rust-lang/rust/issues/102090 + +------------------------ +"##, + }, + Lint { + label: "entry_insert", + description: r##"# `entry_insert` + +The tracking issue for this feature is: [#65225] + +[#65225]: https://github.com/rust-lang/rust/issues/65225 + +------------------------ +"##, + }, + Lint { + label: "ermsb_target_feature", + description: r##"# `ermsb_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "error_generic_member_access", + description: r##"# `error_generic_member_access` + +The tracking issue for this feature is: [#99301] + +[#99301]: https://github.com/rust-lang/rust/issues/99301 + +------------------------ +"##, + }, + Lint { + label: "error_in_core", + description: r##"# `error_in_core` + +The tracking issue for this feature is: [#103765] + +[#103765]: https://github.com/rust-lang/rust/issues/103765 + +------------------------ +"##, + }, + Lint { + label: "error_iter", + description: r##"# `error_iter` + +The tracking issue for this feature is: [#58520] + +[#58520]: https://github.com/rust-lang/rust/issues/58520 + +------------------------ +"##, + }, + Lint { + label: "error_reporter", + description: r##"# `error_reporter` + +The tracking issue for this feature is: [#90172] + +[#90172]: https://github.com/rust-lang/rust/issues/90172 + +------------------------ +"##, + }, + Lint { + label: "error_type_id", + description: r##"# `error_type_id` + +The tracking issue for this feature is: [#60784] + +[#60784]: https://github.com/rust-lang/rust/issues/60784 + +------------------------ +"##, + }, + Lint { + label: "exact_size_is_empty", + description: r##"# `exact_size_is_empty` + +The tracking issue for this feature is: [#35428] + +[#35428]: https://github.com/rust-lang/rust/issues/35428 + +------------------------ +"##, + }, + Lint { + label: "exclusive_range_pattern", + description: r##"# `exclusive_range_pattern` + +The tracking issue for this feature is: [#37854]. + + +[#67264]: https://github.com/rust-lang/rust/issues/67264 +[#37854]: https://github.com/rust-lang/rust/issues/37854 +----- + +The `exclusive_range_pattern` feature allows non-inclusive range +patterns (`0..10`) to be used in appropriate pattern matching +contexts. It also can be combined with `#![feature(half_open_range_patterns]` +to be able to use RangeTo patterns (`..10`). + +It also enabled RangeFrom patterns but that has since been +stabilized. + +```rust +#![feature(exclusive_range_pattern)] + let x = 5; + match x { + 0..10 => println!("single digit"), + 10 => println!("ten isn't part of the above range"), + _ => println!("nor is everything else.") + } +``` +"##, + }, + Lint { + label: "exclusive_wrapper", + description: r##"# `exclusive_wrapper` + +The tracking issue for this feature is: [#98407] + +[#98407]: https://github.com/rust-lang/rust/issues/98407 + +------------------------ +"##, + }, + Lint { + label: "exhaustive_patterns", + description: r##"# `exhaustive_patterns` + +The tracking issue for this feature is: [#51085] + +[#51085]: https://github.com/rust-lang/rust/issues/51085 + +------------------------ +"##, + }, + Lint { + label: "exit_status_error", + description: r##"# `exit_status_error` + +The tracking issue for this feature is: [#84908] + +[#84908]: https://github.com/rust-lang/rust/issues/84908 + +------------------------ +"##, + }, + Lint { + label: "exitcode_exit_method", + description: r##"# `exitcode_exit_method` + +The tracking issue for this feature is: [#97100] + +[#97100]: https://github.com/rust-lang/rust/issues/97100 + +------------------------ +"##, + }, + Lint { + label: "explicit_tail_calls", + description: r##"# `explicit_tail_calls` + +The tracking issue for this feature is: [#112788] + +[#112788]: https://github.com/rust-lang/rust/issues/112788 + +------------------------ +"##, + }, + Lint { + label: "extend_one", + description: r##"# `extend_one` + +The tracking issue for this feature is: [#72631] + +[#72631]: https://github.com/rust-lang/rust/issues/72631 + +------------------------ +"##, + }, + Lint { + label: "extended_varargs_abi_support", + description: r##"# `extended_varargs_abi_support` + +The tracking issue for this feature is: [#100189] + +[#100189]: https://github.com/rust-lang/rust/issues/100189 + +------------------------ + +This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling +conventions on functions with varargs. +"##, + }, + Lint { + label: "extern_types", + description: r##"# `extern_types` + +The tracking issue for this feature is: [#43467] + +[#43467]: https://github.com/rust-lang/rust/issues/43467 + +------------------------ +"##, + }, + Lint { + label: "extract_if", + description: r##"# `extract_if` + +The tracking issue for this feature is: [#43244] + +[#43244]: https://github.com/rust-lang/rust/issues/43244 + +------------------------ +"##, + }, + Lint { + label: "fd", + description: r##"# `fd` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "fd_read", + description: r##"# `fd_read` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "ffi_const", + description: r##"# `ffi_const` + +The tracking issue for this feature is: [#58328] + +------ + +The `#[ffi_const]` attribute applies clang's `const` attribute to foreign +functions declarations. + +That is, `#[ffi_const]` functions shall have no effects except for its return +value, which can only depend on the values of the function parameters, and is +not affected by changes to the observable state of the program. + +Applying the `#[ffi_const]` attribute to a function that violates these +requirements is undefined behaviour. + +This attribute enables Rust to perform common optimizations, like sub-expression +elimination, and it can avoid emitting some calls in repeated invocations of the +function with the same argument values regardless of other operations being +performed in between these functions calls (as opposed to `#[ffi_pure]` +functions). + +## Pitfalls + +A `#[ffi_const]` function can only read global memory that would not affect +its return value for the whole execution of the program (e.g. immutable global +memory). `#[ffi_const]` functions are referentially-transparent and therefore +more strict than `#[ffi_pure]` functions. + +A common pitfall involves applying the `#[ffi_const]` attribute to a +function that reads memory through pointer arguments which do not necessarily +point to immutable global memory. + +A `#[ffi_const]` function that returns unit has no effect on the abstract +machine's state, and a `#[ffi_const]` function cannot be `#[ffi_pure]`. + +A `#[ffi_const]` function must not diverge, neither via a side effect (e.g. a +call to `abort`) nor by infinite loops. + +When translating C headers to Rust FFI, it is worth verifying for which targets +the `const` attribute is enabled in those headers, and using the appropriate +`cfg` macros in the Rust side to match those definitions. While the semantics of +`const` are implemented identically by many C and C++ compilers, e.g., clang, +[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily +implemented in this way on all of them. It is therefore also worth verifying +that the semantics of the C toolchain used to compile the binary being linked +against are compatible with those of the `#[ffi_const]`. + +[#58328]: https://github.com/rust-lang/rust/issues/58328 +[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacgigch.html +[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute +[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_const.htm +"##, + }, + Lint { + label: "ffi_pure", + description: r##"# `ffi_pure` + +The tracking issue for this feature is: [#58329] + +------ + +The `#[ffi_pure]` attribute applies clang's `pure` attribute to foreign +functions declarations. + +That is, `#[ffi_pure]` functions shall have no effects except for its return +value, which shall not change across two consecutive function calls with +the same parameters. + +Applying the `#[ffi_pure]` attribute to a function that violates these +requirements is undefined behavior. + +This attribute enables Rust to perform common optimizations, like sub-expression +elimination and loop optimizations. Some common examples of pure functions are +`strlen` or `memcmp`. + +These optimizations are only applicable when the compiler can prove that no +program state observable by the `#[ffi_pure]` function has changed between calls +of the function, which could alter the result. See also the `#[ffi_const]` +attribute, which provides stronger guarantees regarding the allowable behavior +of a function, enabling further optimization. + +## Pitfalls + +A `#[ffi_pure]` function can read global memory through the function +parameters (e.g. pointers), globals, etc. `#[ffi_pure]` functions are not +referentially-transparent, and are therefore more relaxed than `#[ffi_const]` +functions. + +However, accessing global memory through volatile or atomic reads can violate the +requirement that two consecutive function calls shall return the same value. + +A `pure` function that returns unit has no effect on the abstract machine's +state. + +A `#[ffi_pure]` function must not diverge, neither via a side effect (e.g. a +call to `abort`) nor by infinite loops. + +When translating C headers to Rust FFI, it is worth verifying for which targets +the `pure` attribute is enabled in those headers, and using the appropriate +`cfg` macros in the Rust side to match those definitions. While the semantics of +`pure` are implemented identically by many C and C++ compilers, e.g., clang, +[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily +implemented in this way on all of them. It is therefore also worth verifying +that the semantics of the C toolchain used to compile the binary being linked +against are compatible with those of the `#[ffi_pure]`. + + +[#58329]: https://github.com/rust-lang/rust/issues/58329 +[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html +[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute +[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm +"##, + }, + Lint { + label: "ffi_returns_twice", + description: r##"# `ffi_returns_twice` + +The tracking issue for this feature is: [#58314] + +[#58314]: https://github.com/rust-lang/rust/issues/58314 + +------------------------ +"##, + }, + Lint { + label: "file_create_new", + description: r##"# `file_create_new` + +The tracking issue for this feature is: [#105135] + +[#105135]: https://github.com/rust-lang/rust/issues/105135 + +------------------------ +"##, + }, + Lint { + label: "file_set_times", + description: r##"# `file_set_times` + +The tracking issue for this feature is: [#98245] + +[#98245]: https://github.com/rust-lang/rust/issues/98245 + +------------------------ +"##, + }, + Lint { + label: "float_gamma", + description: r##"# `float_gamma` + +The tracking issue for this feature is: [#99842] + +[#99842]: https://github.com/rust-lang/rust/issues/99842 + +------------------------ +"##, + }, + Lint { + label: "float_minimum_maximum", + description: r##"# `float_minimum_maximum` + +The tracking issue for this feature is: [#91079] + +[#91079]: https://github.com/rust-lang/rust/issues/91079 + +------------------------ +"##, + }, + Lint { + label: "float_next_up_down", + description: r##"# `float_next_up_down` + +The tracking issue for this feature is: [#91399] + +[#91399]: https://github.com/rust-lang/rust/issues/91399 + +------------------------ +"##, + }, + Lint { + label: "flt2dec", + description: r##"# `flt2dec` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "fmt_helpers_for_derive", + description: r##"# `fmt_helpers_for_derive` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "fmt_internals", + description: r##"# `fmt_internals` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "fn_align", + description: r##"# `fn_align` + +The tracking issue for this feature is: [#82232] + +[#82232]: https://github.com/rust-lang/rust/issues/82232 + +------------------------ +"##, + }, + Lint { + label: "fn_ptr_trait", + description: r##"# `fn_ptr_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "fn_traits", + description: r##"# `fn_traits` + +The tracking issue for this feature is [#29625] + +See Also: [`unboxed_closures`](../language-features/unboxed-closures.md) + +[#29625]: https://github.com/rust-lang/rust/issues/29625 + +---- + +The `fn_traits` feature allows for implementation of the [`Fn*`] traits +for creating custom closure-like types. + +[`Fn*`]: ../../std/ops/trait.Fn.html + +```rust +#![feature(unboxed_closures)] +#![feature(fn_traits)] + +struct Adder { + a: u32 +} + +impl FnOnce<(u32, )> for Adder { + type Output = u32; + extern "rust-call" fn call_once(self, b: (u32, )) -> Self::Output { + self.a + b.0 + } +} + +fn main() { + let adder = Adder { a: 3 }; + assert_eq!(adder(2), 5); +} +``` +"##, + }, + Lint { + label: "forget_unsized", + description: r##"# `forget_unsized` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "format_args_nl", + description: r##"# `format_args_nl` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "fs_try_exists", + description: r##"# `fs_try_exists` + +The tracking issue for this feature is: [#83186] + +[#83186]: https://github.com/rust-lang/rust/issues/83186 + +------------------------ +"##, + }, + Lint { + label: "fundamental", + description: r##"# `fundamental` + +The tracking issue for this feature is: [#29635] + +[#29635]: https://github.com/rust-lang/rust/issues/29635 + +------------------------ +"##, + }, + Lint { + label: "future_join", + description: r##"# `future_join` + +The tracking issue for this feature is: [#91642] + +[#91642]: https://github.com/rust-lang/rust/issues/91642 + +------------------------ +"##, + }, + Lint { + label: "gen_future", + description: r##"# `gen_future` + +The tracking issue for this feature is: [#50547] + +[#50547]: https://github.com/rust-lang/rust/issues/50547 + +------------------------ +"##, + }, + Lint { + label: "generator_clone", + description: r##"# `generator_clone` + +The tracking issue for this feature is: [#95360] + +[#95360]: https://github.com/rust-lang/rust/issues/95360 + +------------------------ +"##, + }, + Lint { + label: "generator_trait", + description: r##"# `generator_trait` + +The tracking issue for this feature is: [#43122] + +[#43122]: https://github.com/rust-lang/rust/issues/43122 + +------------------------ +"##, + }, + Lint { + label: "generators", + description: r##"# `generators` + +The tracking issue for this feature is: [#43122] + +[#43122]: https://github.com/rust-lang/rust/issues/43122 + +------------------------ + +The `generators` feature gate in Rust allows you to define generator or +coroutine literals. A generator is a "resumable function" that syntactically +resembles a closure but compiles to much different semantics in the compiler +itself. The primary feature of a generator is that it can be suspended during +execution to be resumed at a later date. Generators use the `yield` keyword to +"return", and then the caller can `resume` a generator to resume execution just +after the `yield` keyword. + +Generators are an extra-unstable feature in the compiler right now. Added in +[RFC 2033] they're mostly intended right now as a information/constraint +gathering phase. The intent is that experimentation can happen on the nightly +compiler before actual stabilization. A further RFC will be required to +stabilize generators/coroutines and will likely contain at least a few small +tweaks to the overall design. + +[RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033 + +A syntactical example of a generator is: + +```rust +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +fn main() { + let mut generator = || { + yield 1; + return "foo" + }; + + match Pin::new(&mut generator).resume(()) { + GeneratorState::Yielded(1) => {} + _ => panic!("unexpected value from resume"), + } + match Pin::new(&mut generator).resume(()) { + GeneratorState::Complete("foo") => {} + _ => panic!("unexpected value from resume"), + } +} +``` + +Generators are closure-like literals which can contain a `yield` statement. The +`yield` statement takes an optional expression of a value to yield out of the +generator. All generator literals implement the `Generator` trait in the +`std::ops` module. The `Generator` trait has one main method, `resume`, which +resumes execution of the generator at the previous suspension point. + +An example of the control flow of generators is that the following example +prints all numbers in order: + +```rust +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let mut generator = || { + println!("2"); + yield; + println!("4"); + }; + + println!("1"); + Pin::new(&mut generator).resume(()); + println!("3"); + Pin::new(&mut generator).resume(()); + println!("5"); +} +``` + +At this time the main intended use case of generators is an implementation +primitive for async/await syntax, but generators will likely be extended to +ergonomic implementations of iterators and other primitives in the future. +Feedback on the design and usage is always appreciated! + +### The `Generator` trait + +The `Generator` trait in `std::ops` currently looks like: + +```rust +# #![feature(arbitrary_self_types, generator_trait)] +# use std::ops::GeneratorState; +# use std::pin::Pin; + +pub trait Generator { + type Yield; + type Return; + fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState; +} +``` + +The `Generator::Yield` type is the type of values that can be yielded with the +`yield` statement. The `Generator::Return` type is the returned type of the +generator. This is typically the last expression in a generator's definition or +any value passed to `return` in a generator. The `resume` function is the entry +point for executing the `Generator` itself. + +The return value of `resume`, `GeneratorState`, looks like: + +```rust +pub enum GeneratorState { + Yielded(Y), + Complete(R), +} +``` + +The `Yielded` variant indicates that the generator can later be resumed. This +corresponds to a `yield` point in a generator. The `Complete` variant indicates +that the generator is complete and cannot be resumed again. Calling `resume` +after a generator has returned `Complete` will likely result in a panic of the +program. + +### Closure-like semantics + +The closure-like syntax for generators alludes to the fact that they also have +closure-like semantics. Namely: + +* When created, a generator executes no code. A closure literal does not + actually execute any of the closure's code on construction, and similarly a + generator literal does not execute any code inside the generator when + constructed. + +* Generators can capture outer variables by reference or by move, and this can + be tweaked with the `move` keyword at the beginning of the closure. Like + closures all generators will have an implicit environment which is inferred by + the compiler. Outer variables can be moved into a generator for use as the + generator progresses. + +* Generator literals produce a value with a unique type which implements the + `std::ops::Generator` trait. This allows actual execution of the generator + through the `Generator::resume` method as well as also naming it in return + types and such. + +* Traits like `Send` and `Sync` are automatically implemented for a `Generator` + depending on the captured variables of the environment. Unlike closures, + generators also depend on variables live across suspension points. This means + that although the ambient environment may be `Send` or `Sync`, the generator + itself may not be due to internal variables live across `yield` points being + not-`Send` or not-`Sync`. Note that generators do + not implement traits like `Copy` or `Clone` automatically. + +* Whenever a generator is dropped it will drop all captured environment + variables. + +### Generators as state machines + +In the compiler, generators are currently compiled as state machines. Each +`yield` expression will correspond to a different state that stores all live +variables over that suspension point. Resumption of a generator will dispatch on +the current state and then execute internally until a `yield` is reached, at +which point all state is saved off in the generator and a value is returned. + +Let's take a look at an example to see what's going on here: + +```rust +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let ret = "foo"; + let mut generator = move || { + yield 1; + return ret + }; + + Pin::new(&mut generator).resume(()); + Pin::new(&mut generator).resume(()); +} +``` This generator literal will compile down to something similar to: -```rust -#![feature(arbitrary_self_types, generators, generator_trait)] +```rust +#![feature(arbitrary_self_types, generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +fn main() { + let ret = "foo"; + let mut generator = { + enum __Generator { + Start(&'static str), + Yield1(&'static str), + Done, + } + + impl Generator for __Generator { + type Yield = i32; + type Return = &'static str; + + fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState { + use std::mem; + match mem::replace(&mut *self, __Generator::Done) { + __Generator::Start(s) => { + *self = __Generator::Yield1(s); + GeneratorState::Yielded(1) + } + + __Generator::Yield1(s) => { + *self = __Generator::Done; + GeneratorState::Complete(s) + } + + __Generator::Done => { + panic!("generator resumed after completion") + } + } + } + } + + __Generator::Start(ret) + }; + + Pin::new(&mut generator).resume(()); + Pin::new(&mut generator).resume(()); +} +``` + +Notably here we can see that the compiler is generating a fresh type, +`__Generator` in this case. This type has a number of states (represented here +as an `enum`) corresponding to each of the conceptual states of the generator. +At the beginning we're closing over our outer variable `foo` and then that +variable is also live over the `yield` point, so it's stored in both states. + +When the generator starts it'll immediately yield 1, but it saves off its state +just before it does so indicating that it has reached the yield point. Upon +resuming again we'll execute the `return ret` which returns the `Complete` +state. + +Here we can also note that the `Done` state, if resumed, panics immediately as +it's invalid to resume a completed generator. It's also worth noting that this +is just a rough desugaring, not a normative specification for what the compiler +does. +"##, + }, + Lint { + label: "generic_arg_infer", + description: r##"# `generic_arg_infer` + +The tracking issue for this feature is: [#85077] + +[#85077]: https://github.com/rust-lang/rust/issues/85077 + +------------------------ +"##, + }, + Lint { + label: "generic_assert", + description: r##"# `generic_assert` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "generic_assert_internals", + description: r##"# `generic_assert_internals` + +The tracking issue for this feature is: [#44838] + +[#44838]: https://github.com/rust-lang/rust/issues/44838 + +------------------------ +"##, + }, + Lint { + label: "generic_associated_types_extended", + description: r##"# `generic_associated_types_extended` + +The tracking issue for this feature is: [#95451] + +[#95451]: https://github.com/rust-lang/rust/issues/95451 + +------------------------ +"##, + }, + Lint { + label: "generic_const_exprs", + description: r##"# `generic_const_exprs` + +The tracking issue for this feature is: [#76560] + +[#76560]: https://github.com/rust-lang/rust/issues/76560 + +------------------------ +"##, + }, + Lint { + label: "generic_const_items", + description: r##"# `generic_const_items` + +The tracking issue for this feature is: [#113521] + +[#113521]: https://github.com/rust-lang/rust/issues/113521 + +------------------------ +"##, + }, + Lint { + label: "get_many_mut", + description: r##"# `get_many_mut` + +The tracking issue for this feature is: [#104642] + +[#104642]: https://github.com/rust-lang/rust/issues/104642 + +------------------------ +"##, + }, + Lint { + label: "get_mut_unchecked", + description: r##"# `get_mut_unchecked` + +The tracking issue for this feature is: [#63292] + +[#63292]: https://github.com/rust-lang/rust/issues/63292 + +------------------------ +"##, + }, + Lint { + label: "half_open_range_patterns_in_slices", + description: r##"# `half_open_range_patterns_in_slices` + +The tracking issue for this feature is: [#67264] +It is part of the `exclusive_range_pattern` feature, +tracked at [#37854]. + +[#67264]: https://github.com/rust-lang/rust/issues/67264 +[#37854]: https://github.com/rust-lang/rust/issues/37854 +----- + +This feature allow using top-level half-open range patterns in slices. + +```rust +#![feature(half_open_range_patterns_in_slices)] +#![feature(exclusive_range_pattern)] + +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { return; }; +} +``` + +Note that this feature is not required if the patterns are wrapped between parenthesis. + +```rust +fn main() { + let xs = [13, 1]; + let [(a @ 3..), c] = xs else { return; }; +} +``` +"##, + }, + Lint { + label: "hash_extract_if", + description: r##"# `hash_extract_if` + +The tracking issue for this feature is: [#59618] + +[#59618]: https://github.com/rust-lang/rust/issues/59618 + +------------------------ +"##, + }, + Lint { + label: "hash_raw_entry", + description: r##"# `hash_raw_entry` + +The tracking issue for this feature is: [#56167] + +[#56167]: https://github.com/rust-lang/rust/issues/56167 + +------------------------ +"##, + }, + Lint { + label: "hash_set_entry", + description: r##"# `hash_set_entry` + +The tracking issue for this feature is: [#60896] + +[#60896]: https://github.com/rust-lang/rust/issues/60896 + +------------------------ +"##, + }, + Lint { + label: "hasher_prefixfree_extras", + description: r##"# `hasher_prefixfree_extras` + +The tracking issue for this feature is: [#96762] + +[#96762]: https://github.com/rust-lang/rust/issues/96762 + +------------------------ +"##, + }, + Lint { + label: "hashmap_internals", + description: r##"# `hashmap_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "hexagon_target_feature", + description: r##"# `hexagon_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "hint_must_use", + description: r##"# `hint_must_use` + +The tracking issue for this feature is: [#94745] + +[#94745]: https://github.com/rust-lang/rust/issues/94745 + +------------------------ +"##, + }, + Lint { + label: "if_let_guard", + description: r##"# `if_let_guard` + +The tracking issue for this feature is: [#51114] + +[#51114]: https://github.com/rust-lang/rust/issues/51114 + +------------------------ +"##, + }, + Lint { + label: "impl_trait_in_assoc_type", + description: r##"# `impl_trait_in_assoc_type` + +The tracking issue for this feature is: [#63063] + +[#63063]: https://github.com/rust-lang/rust/issues/63063 + +------------------------ +"##, + }, + Lint { + label: "impl_trait_in_fn_trait_return", + description: r##"# `impl_trait_in_fn_trait_return` + +The tracking issue for this feature is: [#99697] + +[#99697]: https://github.com/rust-lang/rust/issues/99697 + +------------------------ +"##, + }, + Lint { + label: "imported_main", + description: r##"# `imported_main` + +The tracking issue for this feature is: [#28937] + +[#28937]: https://github.com/rust-lang/rust/issues/28937 + +------------------------ +"##, + }, + Lint { + label: "inherent_associated_types", + description: r##"# `inherent_associated_types` + +The tracking issue for this feature is: [#8995] + +[#8995]: https://github.com/rust-lang/rust/issues/8995 + +------------------------ +"##, + }, + Lint { + label: "inline_const", + description: r##"# `inline_const` + +The tracking issue for this feature is: [#76001] + +See also [`inline_const_pat`](inline-const-pat.md) + +------ + +This feature allows you to use inline constant expressions. For example, you can +turn this code: + +```rust +# fn add_one(x: i32) -> i32 { x + 1 } +const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4; + +fn main() { + let x = add_one(MY_COMPUTATION); +} +``` + +into this code: + +```rust +#![feature(inline_const)] + +# fn add_one(x: i32) -> i32 { x + 1 } +fn main() { + let x = add_one(const { 1 + 2 * 3 / 4 }); +} +``` + +[#76001]: https://github.com/rust-lang/rust/issues/76001 +"##, + }, + Lint { + label: "inline_const_pat", + description: r##"# `inline_const_pat` + +The tracking issue for this feature is: [#76001] + +See also [`inline_const`](inline-const.md) + +------ + +This feature allows you to use inline constant expressions in pattern position: + +```rust +#![feature(inline_const_pat)] + +const fn one() -> i32 { 1 } + +let some_int = 3; +match some_int { + const { 1 + 2 } => println!("Matched 1 + 2"), + const { one() } => println!("Matched const fn returning 1"), + _ => println!("Didn't match anything :("), +} +``` + +[#76001]: https://github.com/rust-lang/rust/issues/76001 +"##, + }, + Lint { + label: "inplace_iteration", + description: r##"# `inplace_iteration` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "int_roundings", + description: r##"# `int_roundings` + +The tracking issue for this feature is: [#88581] + +[#88581]: https://github.com/rust-lang/rust/issues/88581 + +------------------------ +"##, + }, + Lint { + label: "integer_atomics", + description: r##"# `integer_atomics` + +The tracking issue for this feature is: [#99069] + +[#99069]: https://github.com/rust-lang/rust/issues/99069 + +------------------------ +"##, + }, + Lint { + label: "internal_impls_macro", + description: r##"# `internal_impls_macro` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "internal_output_capture", + description: r##"# `internal_output_capture` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "intra_doc_pointers", + description: r##"# `intra-doc-pointers` + +The tracking issue for this feature is: [#80896] + +[#80896]: https://github.com/rust-lang/rust/issues/80896 + +------------------------ + +Rustdoc does not currently allow disambiguating between `*const` and `*mut`, and +raw pointers in intra-doc links are unstable until it does. + +```rust +#![feature(intra_doc_pointers)] +//! [pointer::add] +``` +"##, + }, + Lint { + label: "intrinsics", + description: r##"# `intrinsics` + +The tracking issue for this feature is: None. + +Intrinsics are never intended to be stable directly, but intrinsics are often +exported in some sort of stable manner. Prefer using the stable interfaces to +the intrinsic directly when you can. + +------------------------ + + +These are imported as if they were FFI functions, with the special +`rust-intrinsic` ABI. For example, if one was in a freestanding +context, but wished to be able to `transmute` between types, and +perform efficient pointer arithmetic, one would import those functions +via a declaration like + +```rust +#![feature(intrinsics)] +#![allow(internal_features)] +# fn main() {} + +extern "rust-intrinsic" { + fn transmute(x: T) -> U; + + fn arith_offset(dst: *const T, offset: isize) -> *const T; +} +``` + +As with any other FFI functions, these are always `unsafe` to call. +"##, + }, + Lint { + label: "io_error_downcast", + description: r##"# `io_error_downcast` + +The tracking issue for this feature is: [#99262] + +[#99262]: https://github.com/rust-lang/rust/issues/99262 + +------------------------ +"##, + }, + Lint { + label: "io_error_more", + description: r##"# `io_error_more` + +The tracking issue for this feature is: [#86442] + +[#86442]: https://github.com/rust-lang/rust/issues/86442 + +------------------------ +"##, + }, + Lint { + label: "io_error_uncategorized", + description: r##"# `io_error_uncategorized` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "io_slice_advance", + description: r##"# `io_slice_advance` + +The tracking issue for this feature is: [#62726] + +[#62726]: https://github.com/rust-lang/rust/issues/62726 + +------------------------ +"##, + }, + Lint { + label: "ip", + description: r##"# `ip` + +The tracking issue for this feature is: [#27709] + +[#27709]: https://github.com/rust-lang/rust/issues/27709 + +------------------------ +"##, + }, + Lint { + label: "ip_bits", + description: r##"# `ip_bits` + +The tracking issue for this feature is: [#113744] + +[#113744]: https://github.com/rust-lang/rust/issues/113744 + +------------------------ +"##, + }, + Lint { + label: "ip_in_core", + description: r##"# `ip_in_core` + +The tracking issue for this feature is: [#108443] + +[#108443]: https://github.com/rust-lang/rust/issues/108443 + +------------------------ +"##, + }, + Lint { + label: "is_ascii_octdigit", + description: r##"# `is_ascii_octdigit` + +The tracking issue for this feature is: [#101288] + +[#101288]: https://github.com/rust-lang/rust/issues/101288 + +------------------------ +"##, + }, + Lint { + label: "is_sorted", + description: r##"# `is_sorted` + +The tracking issue for this feature is: [#53485] + +[#53485]: https://github.com/rust-lang/rust/issues/53485 + +------------------------ + +Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`; +add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to +`Iterator`. +"##, + }, + Lint { + label: "isqrt", + description: r##"# `isqrt` + +The tracking issue for this feature is: [#116226] + +[#116226]: https://github.com/rust-lang/rust/issues/116226 + +------------------------ +"##, + }, + Lint { + label: "iter_advance_by", + description: r##"# `iter_advance_by` + +The tracking issue for this feature is: [#77404] + +[#77404]: https://github.com/rust-lang/rust/issues/77404 + +------------------------ +"##, + }, + Lint { + label: "iter_array_chunks", + description: r##"# `iter_array_chunks` + +The tracking issue for this feature is: [#100450] + +[#100450]: https://github.com/rust-lang/rust/issues/100450 + +------------------------ +"##, + }, + Lint { + label: "iter_collect_into", + description: r##"# `iter_collect_into` + +The tracking issue for this feature is: [#94780] + +[#94780]: https://github.com/rust-lang/rust/issues/94780 + +------------------------ +"##, + }, + Lint { + label: "iter_from_generator", + description: r##"# `iter_from_generator` + +The tracking issue for this feature is: [#43122] + +[#43122]: https://github.com/rust-lang/rust/issues/43122 + +------------------------ +"##, + }, + Lint { + label: "iter_intersperse", + description: r##"# `iter_intersperse` + +The tracking issue for this feature is: [#79524] + +[#79524]: https://github.com/rust-lang/rust/issues/79524 + +------------------------ +"##, + }, + Lint { + label: "iter_is_partitioned", + description: r##"# `iter_is_partitioned` + +The tracking issue for this feature is: [#62544] + +[#62544]: https://github.com/rust-lang/rust/issues/62544 + +------------------------ +"##, + }, + Lint { + label: "iter_map_windows", + description: r##"# `iter_map_windows` + +The tracking issue for this feature is: [#87155] + +[#87155]: https://github.com/rust-lang/rust/issues/87155 + +------------------------ +"##, + }, + Lint { + label: "iter_next_chunk", + description: r##"# `iter_next_chunk` + +The tracking issue for this feature is: [#98326] + +[#98326]: https://github.com/rust-lang/rust/issues/98326 + +------------------------ +"##, + }, + Lint { + label: "iter_order_by", + description: r##"# `iter_order_by` + +The tracking issue for this feature is: [#64295] + +[#64295]: https://github.com/rust-lang/rust/issues/64295 + +------------------------ +"##, + }, + Lint { + label: "iter_partition_in_place", + description: r##"# `iter_partition_in_place` + +The tracking issue for this feature is: [#62543] + +[#62543]: https://github.com/rust-lang/rust/issues/62543 + +------------------------ +"##, + }, + Lint { + label: "iter_repeat_n", + description: r##"# `iter_repeat_n` + +The tracking issue for this feature is: [#104434] + +[#104434]: https://github.com/rust-lang/rust/issues/104434 + +------------------------ +"##, + }, + Lint { + label: "iterator_try_collect", + description: r##"# `iterator_try_collect` + +The tracking issue for this feature is: [#94047] + +[#94047]: https://github.com/rust-lang/rust/issues/94047 + +------------------------ +"##, + }, + Lint { + label: "iterator_try_reduce", + description: r##"# `iterator_try_reduce` + +The tracking issue for this feature is: [#87053] + +[#87053]: https://github.com/rust-lang/rust/issues/87053 + +------------------------ +"##, + }, + Lint { + label: "lang_items", + description: r##"# `lang_items` + +The tracking issue for this feature is: None. + +------------------------ + +The `rustc` compiler has certain pluggable operations, that is, +functionality that isn't hard-coded into the language, but is +implemented in libraries, with a special marker to tell the compiler +it exists. The marker is the attribute `#[lang = "..."]` and there are +various different values of `...`, i.e. various different 'lang +items'. Most of them can only be defined once. + +Lang items are loaded lazily by the compiler; e.g. if one never uses `Box` +then there is no need to define a function for `exchange_malloc`. +`rustc` will emit an error when an item is needed but not found in the current +crate or any that it depends on. + +Some features provided by lang items: + +- overloadable operators via traits: the traits corresponding to the + `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all + marked with lang items; those specific four are `eq`, `partial_ord`, + `deref`/`deref_mut`, and `add` respectively. +- panicking: the `panic` and `panic_impl` lang items, among others. +- stack unwinding: the lang item `eh_personality` is a function used by the + failure mechanisms of the compiler. This is often mapped to GCC's personality + function (see the [`std` implementation][personality] for more information), + but programs which don't trigger a panic can be assured that this function is + never called. Additionally, a `eh_catch_typeinfo` static is needed for certain + targets which implement Rust panics on top of C++ exceptions. +- the traits in `core::marker` used to indicate types of + various kinds; e.g. lang items `sized`, `sync` and `copy`. +- memory allocation, see below. + +Most lang items are defined by `core`, but if you're trying to build +an executable without the `std` crate, you might run into the need +for lang item definitions. + +[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/sys/personality/gcc.rs + +## Example: Implementing a `Box` + +`Box` pointers require two lang items: one for the type itself and one for +allocation. A freestanding program that uses the `Box` sugar for dynamic +allocations via `malloc` and `free`: + +```rust,ignore (libc-is-finicky) +#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] +#![allow(internal_features)] +#![no_std] + +extern crate libc; +extern crate unwind; + +use core::ffi::c_void; +use core::intrinsics; +use core::panic::PanicInfo; +use core::ptr::NonNull; + +pub struct Global; // the global allocator +struct Unique(NonNull); + +#[lang = "owned_box"] +pub struct Box(Unique, A); + +impl Box { + pub fn new(x: T) -> Self { + #[rustc_box] + Box::new(x) + } +} + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + libc::free(self.0.0.as_ptr() as *mut c_void); + } + } +} + +#[lang = "exchange_malloc"] +unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { + let p = libc::malloc(size) as *mut u8; + + // Check if `malloc` failed: + if p.is_null() { + intrinsics::abort(); + } + + p +} + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let _x = Box::new(1); + + 0 +} + +#[lang = "eh_personality"] +fn rust_eh_personality() {} + +#[panic_handler] +fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } +``` + +Note the use of `abort`: the `exchange_malloc` lang item is assumed to +return a valid pointer, and so needs to do the check internally. + +## List of all language items + +An up-to-date list of all language items can be found [here] in the compiler code. + +[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs +"##, + }, + Lint { + label: "large_assignments", + description: r##"# `large_assignments` + +The tracking issue for this feature is: [#83518] + +[#83518]: https://github.com/rust-lang/rust/issues/83518 + +------------------------ +"##, + }, + Lint { + label: "layout_for_ptr", + description: r##"# `layout_for_ptr` + +The tracking issue for this feature is: [#69835] + +[#69835]: https://github.com/rust-lang/rust/issues/69835 + +------------------------ +"##, + }, + Lint { + label: "lazy_cell", + description: r##"# `lazy_cell` + +The tracking issue for this feature is: [#109736] + +[#109736]: https://github.com/rust-lang/rust/issues/109736 + +------------------------ +"##, + }, + Lint { + label: "lazy_cell_consume", + description: r##"# `lazy_cell_consume` + +The tracking issue for this feature is: [#109736] + +[#109736]: https://github.com/rust-lang/rust/issues/109736 + +------------------------ +"##, + }, + Lint { + label: "lazy_type_alias", + description: r##"# `lazy_type_alias` + +The tracking issue for this feature is: [#112792] + +[#112792]: https://github.com/rust-lang/rust/issues/112792 + +------------------------ +"##, + }, + Lint { + label: "let_chains", + description: r##"# `let_chains` + +The tracking issue for this feature is: [#53667] + +[#53667]: https://github.com/rust-lang/rust/issues/53667 + +------------------------ +"##, + }, + Lint { + label: "liballoc_internals", + description: r##"# `liballoc_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "libstd_sys_internals", + description: r##"# `libstd_sys_internals` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "link_cfg", + description: r##"# `link_cfg` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "link_llvm_intrinsics", + description: r##"# `link_llvm_intrinsics` + +The tracking issue for this feature is: [#29602] + +[#29602]: https://github.com/rust-lang/rust/issues/29602 + +------------------------ +"##, + }, + Lint { + label: "linkage", + description: r##"# `linkage` + +The tracking issue for this feature is: [#29603] + +[#29603]: https://github.com/rust-lang/rust/issues/29603 + +------------------------ +"##, + }, + Lint { + label: "linked_list_cursors", + description: r##"# `linked_list_cursors` + +The tracking issue for this feature is: [#58533] + +[#58533]: https://github.com/rust-lang/rust/issues/58533 + +------------------------ +"##, + }, + Lint { + label: "linked_list_remove", + description: r##"# `linked_list_remove` + +The tracking issue for this feature is: [#69210] + +[#69210]: https://github.com/rust-lang/rust/issues/69210 + +------------------------ +"##, + }, + Lint { + label: "lint_reasons", + description: r##"# `lint_reasons` + +The tracking issue for this feature is: [#54503] + +[#54503]: https://github.com/rust-lang/rust/issues/54503 + +------------------------ +"##, + }, + Lint { + label: "linux_pidfd", + description: r##"# `linux_pidfd` + +The tracking issue for this feature is: [#82971] + +[#82971]: https://github.com/rust-lang/rust/issues/82971 + +------------------------ +"##, + }, + Lint { + label: "log_syntax", + description: r##"# `log_syntax` + +The tracking issue for this feature is: [#29598] + +[#29598]: https://github.com/rust-lang/rust/issues/29598 + +------------------------ +"##, + }, + Lint { + label: "macro_metavar_expr", + description: r##"# `macro_metavar_expr` + +The tracking issue for this feature is: [#83527] + +[#83527]: https://github.com/rust-lang/rust/issues/83527 + +------------------------ +"##, + }, + Lint { + label: "map_entry_replace", + description: r##"# `map_entry_replace` + +The tracking issue for this feature is: [#44286] + +[#44286]: https://github.com/rust-lang/rust/issues/44286 + +------------------------ +"##, + }, + Lint { + label: "map_many_mut", + description: r##"# `map_many_mut` + +The tracking issue for this feature is: [#97601] + +[#97601]: https://github.com/rust-lang/rust/issues/97601 + +------------------------ +"##, + }, + Lint { + label: "map_try_insert", + description: r##"# `map_try_insert` + +The tracking issue for this feature is: [#82766] + +[#82766]: https://github.com/rust-lang/rust/issues/82766 + +------------------------ +"##, + }, + Lint { + label: "marker_trait_attr", + description: r##"# `marker_trait_attr` + +The tracking issue for this feature is: [#29864] + +[#29864]: https://github.com/rust-lang/rust/issues/29864 + +------------------------ + +Normally, Rust keeps you from adding trait implementations that could +overlap with each other, as it would be ambiguous which to use. This +feature, however, carves out an exception to that rule: a trait can +opt-in to having overlapping implementations, at the cost that those +implementations are not allowed to override anything (and thus the +trait itself cannot have any associated items, as they're pointless +when they'd need to do the same thing for every type anyway). + +```rust +#![feature(marker_trait_attr)] + +#[marker] trait CheapToClone: Clone {} + +impl CheapToClone for T {} + +// These could potentially overlap with the blanket implementation above, +// so are only allowed because CheapToClone is a marker trait. +impl CheapToClone for (T, U) {} +impl CheapToClone for std::ops::Range {} + +fn cheap_clone(t: T) -> T { + t.clone() +} +``` + +This is expected to replace the unstable `overlapping_marker_traits` +feature, which applied to all empty traits (without needing an opt-in). +"##, + }, + Lint { + label: "maybe_uninit_array_assume_init", + description: r##"# `maybe_uninit_array_assume_init` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_as_bytes", + description: r##"# `maybe_uninit_as_bytes` + +The tracking issue for this feature is: [#93092] + +[#93092]: https://github.com/rust-lang/rust/issues/93092 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_slice", + description: r##"# `maybe_uninit_slice` + +The tracking issue for this feature is: [#63569] + +[#63569]: https://github.com/rust-lang/rust/issues/63569 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_uninit_array", + description: r##"# `maybe_uninit_uninit_array` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_uninit_array_transpose", + description: r##"# `maybe_uninit_uninit_array_transpose` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_write_slice", + description: r##"# `maybe_uninit_write_slice` + +The tracking issue for this feature is: [#79995] + +[#79995]: https://github.com/rust-lang/rust/issues/79995 + +------------------------ +"##, + }, + Lint { + label: "mem_copy_fn", + description: r##"# `mem_copy_fn` + +The tracking issue for this feature is: [#98262] + +[#98262]: https://github.com/rust-lang/rust/issues/98262 + +------------------------ +"##, + }, + Lint { + label: "min_specialization", + description: r##"# `min_specialization` + +The tracking issue for this feature is: [#31844] + +[#31844]: https://github.com/rust-lang/rust/issues/31844 + +------------------------ +"##, + }, + Lint { + label: "mips_target_feature", + description: r##"# `mips_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "more_float_constants", + description: r##"# `more_float_constants` + +The tracking issue for this feature is: [#103883] + +[#103883]: https://github.com/rust-lang/rust/issues/103883 + +------------------------ +"##, + }, + Lint { + label: "more_qualified_paths", + description: r##"# `more_qualified_paths` + +The `more_qualified_paths` feature can be used in order to enable the +use of qualified paths in patterns. + +## Example + +```rust +#![feature(more_qualified_paths)] + +fn main() { + // destructure through a qualified path + let ::Assoc { br } = StructStruct { br: 2 }; +} + +struct StructStruct { + br: i8, +} + +struct Foo; + +trait A { + type Assoc; +} + +impl A for Foo { + type Assoc = StructStruct; +} +``` +"##, + }, + Lint { + label: "multiple_supertrait_upcastable", + description: r##"# `multiple_supertrait_upcastable` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "must_not_suspend", + description: r##"# `must_not_suspend` + +The tracking issue for this feature is: [#83310] + +[#83310]: https://github.com/rust-lang/rust/issues/83310 + +------------------------ +"##, + }, + Lint { + label: "mutex_unlock", + description: r##"# `mutex_unlock` + +The tracking issue for this feature is: [#81872] + +[#81872]: https://github.com/rust-lang/rust/issues/81872 + +------------------------ +"##, + }, + Lint { + label: "mutex_unpoison", + description: r##"# `mutex_unpoison` + +The tracking issue for this feature is: [#96469] + +[#96469]: https://github.com/rust-lang/rust/issues/96469 + +------------------------ +"##, + }, + Lint { + label: "naked_functions", + description: r##"# `naked_functions` + +The tracking issue for this feature is: [#32408] + +[#32408]: https://github.com/rust-lang/rust/issues/32408 + +------------------------ +"##, + }, + Lint { + label: "native_link_modifiers_as_needed", + description: r##"# `native_link_modifiers_as_needed` + +The tracking issue for this feature is: [#81490] + +[#81490]: https://github.com/rust-lang/rust/issues/81490 + +------------------------ + +The `native_link_modifiers_as_needed` feature allows you to use the `as-needed` modifier. + +`as-needed` is only compatible with the `dynamic` and `framework` linking kinds. Using any other kind will result in a compiler error. + +`+as-needed` means that the library will be actually linked only if it satisfies some undefined symbols at the point at which it is specified on the command line, making it similar to static libraries in this regard. + +This modifier translates to `--as-needed` for ld-like linkers, and to `-dead_strip_dylibs` / `-needed_library` / `-needed_framework` for ld64. +The modifier does nothing for linkers that don't support it (e.g. `link.exe`). + +The default for this modifier is unclear, some targets currently specify it as `+as-needed`, some do not. We may want to try making `+as-needed` a default for all targets. +"##, + }, + Lint { + label: "needs_panic_runtime", + description: r##"# `needs_panic_runtime` + +The tracking issue for this feature is: [#32837] + +[#32837]: https://github.com/rust-lang/rust/issues/32837 + +------------------------ +"##, + }, + Lint { + label: "negative_bounds", + description: r##"# `negative_bounds` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "negative_impls", + description: r##"# `negative_impls` + +The tracking issue for this feature is [#68318]. + +[#68318]: https://github.com/rust-lang/rust/issues/68318 + +---- + +With the feature gate `negative_impls`, you can write negative impls as well as positive ones: + +```rust +#![feature(negative_impls)] +trait DerefMut { } +impl !DerefMut for &T { } +``` + +Negative impls indicate a semver guarantee that the given trait will not be implemented for the given types. Negative impls play an additional purpose for auto traits, described below. + +Negative impls have the following characteristics: + +* They do not have any items. +* They must obey the orphan rules as if they were a positive impl. +* They cannot "overlap" with any positive impls. + +## Semver interaction + +It is a breaking change to remove a negative impl. Negative impls are a commitment not to implement the given trait for the named types. + +## Orphan and overlap rules + +Negative impls must obey the same orphan rules as a positive impl. This implies you cannot add a negative impl for types defined in upstream crates and so forth. + +Similarly, negative impls cannot overlap with positive impls, again using the same "overlap" check that we ordinarily use to determine if two impls overlap. (Note that positive impls typically cannot overlap with one another either, except as permitted by specialization.) + +## Interaction with auto traits + +Declaring a negative impl `impl !SomeAutoTrait for SomeType` for an +auto-trait serves two purposes: + +* as with any trait, it declares that `SomeType` will never implement `SomeAutoTrait`; +* it disables the automatic `SomeType: SomeAutoTrait` impl that would otherwise have been generated. + +Note that, at present, there is no way to indicate that a given type +does not implement an auto trait *but that it may do so in the +future*. For ordinary types, this is done by simply not declaring any +impl at all, but that is not an option for auto traits. A workaround +is that one could embed a marker type as one of the fields, where the +marker type is `!AutoTrait`. + +## Immediate uses + +Negative impls are used to declare that `&T: !DerefMut` and `&mut T: !Clone`, as required to fix the soundness of `Pin` described in [#66544](https://github.com/rust-lang/rust/issues/66544). + +This serves two purposes: + +* For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists. +* It prevents downstream crates from creating such impls. +"##, + }, + Lint { + label: "never_type", + description: r##"# `never_type` + +The tracking issue for this feature is: [#35121] + +[#35121]: https://github.com/rust-lang/rust/issues/35121 + +------------------------ +"##, + }, + Lint { + label: "never_type_fallback", + description: r##"# `never_type_fallback` + +The tracking issue for this feature is: [#65992] + +[#65992]: https://github.com/rust-lang/rust/issues/65992 + +------------------------ +"##, + }, + Lint { + label: "new_uninit", + description: r##"# `new_uninit` + +The tracking issue for this feature is: [#63291] + +[#63291]: https://github.com/rust-lang/rust/issues/63291 + +------------------------ +"##, + }, + Lint { + label: "no_core", + description: r##"# `no_core` + +The tracking issue for this feature is: [#29639] + +[#29639]: https://github.com/rust-lang/rust/issues/29639 + +------------------------ +"##, + }, + Lint { + label: "no_sanitize", + description: r##"# `no_sanitize` + +The tracking issue for this feature is: [#39699] + +[#39699]: https://github.com/rust-lang/rust/issues/39699 + +------------------------ + +The `no_sanitize` attribute can be used to selectively disable sanitizer +instrumentation in an annotated function. This might be useful to: avoid +instrumentation overhead in a performance critical function, or avoid +instrumenting code that contains constructs unsupported by given sanitizer. + +The precise effect of this annotation depends on particular sanitizer in use. +For example, with `no_sanitize(thread)`, the thread sanitizer will no longer +instrument non-atomic store / load operations, but it will instrument atomic +operations to avoid reporting false positives and provide meaning full stack +traces. + +## Examples + +``` rust +#![feature(no_sanitize)] + +#[no_sanitize(address)] +fn foo() { + // ... +} +``` +"##, + }, + Lint { + label: "non_exhaustive_omitted_patterns_lint", + description: r##"# `non_exhaustive_omitted_patterns_lint` + +The tracking issue for this feature is: [#89554] + +[#89554]: https://github.com/rust-lang/rust/issues/89554 + +------------------------ +"##, + }, + Lint { + label: "non_lifetime_binders", + description: r##"# `non_lifetime_binders` + +The tracking issue for this feature is: [#108185] + +[#108185]: https://github.com/rust-lang/rust/issues/108185 + +------------------------ +"##, + }, + Lint { + label: "nonzero_ops", + description: r##"# `nonzero_ops` + +The tracking issue for this feature is: [#84186] + +[#84186]: https://github.com/rust-lang/rust/issues/84186 + +------------------------ +"##, + }, + Lint { + label: "noop_waker", + description: r##"# `noop_waker` + +The tracking issue for this feature is: [#98286] + +[#98286]: https://github.com/rust-lang/rust/issues/98286 + +------------------------ +"##, + }, + Lint { + label: "num_midpoint", + description: r##"# `num_midpoint` + +The tracking issue for this feature is: [#110840] + +[#110840]: https://github.com/rust-lang/rust/issues/110840 + +------------------------ +"##, + }, + Lint { + label: "numfmt", + description: r##"# `numfmt` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "object_safe_for_dispatch", + description: r##"# `object_safe_for_dispatch` + +The tracking issue for this feature is: [#43561] + +[#43561]: https://github.com/rust-lang/rust/issues/43561 + +------------------------ +"##, + }, + Lint { + label: "offset_of", + description: r##"# `offset_of` + +The tracking issue for this feature is: [#106655] + +[#106655]: https://github.com/rust-lang/rust/issues/106655 + +------------------------ +"##, + }, + Lint { + label: "omit_gdb_pretty_printer_section", + description: r##"# `omit_gdb_pretty_printer_section` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "once_cell_try", + description: r##"# `once_cell_try` + +The tracking issue for this feature is: [#109737] + +[#109737]: https://github.com/rust-lang/rust/issues/109737 + +------------------------ +"##, + }, + Lint { + label: "one_sided_range", + description: r##"# `one_sided_range` + +The tracking issue for this feature is: [#69780] + +[#69780]: https://github.com/rust-lang/rust/issues/69780 + +------------------------ +"##, + }, + Lint { + label: "optimize_attribute", + description: r##"# `optimize_attribute` + +The tracking issue for this feature is: [#54882] + +[#54882]: https://github.com/rust-lang/rust/issues/54882 + +------------------------ +"##, + }, + Lint { + label: "option_get_or_insert_default", + description: r##"# `option_get_or_insert_default` + +The tracking issue for this feature is: [#82901] -use std::ops::{Generator, GeneratorState}; -use std::pin::Pin; +[#82901]: https://github.com/rust-lang/rust/issues/82901 -fn main() { - let ret = "foo"; - let mut generator = { - enum __Generator { - Start(&'static str), - Yield1(&'static str), - Done, +------------------------ +"##, + }, + Lint { + label: "option_take_if", + description: r##"# `option_take_if` + +The tracking issue for this feature is: [#98934] + +[#98934]: https://github.com/rust-lang/rust/issues/98934 + +------------------------ +"##, + }, + Lint { + label: "option_zip", + description: r##"# `option_zip` + +The tracking issue for this feature is: [#70086] + +[#70086]: https://github.com/rust-lang/rust/issues/70086 + +------------------------ +"##, + }, + Lint { + label: "panic_abort", + description: r##"# `panic_abort` + +The tracking issue for this feature is: [#32837] + +[#32837]: https://github.com/rust-lang/rust/issues/32837 + +------------------------ +"##, + }, + Lint { + label: "panic_always_abort", + description: r##"# `panic_always_abort` + +The tracking issue for this feature is: [#84438] + +[#84438]: https://github.com/rust-lang/rust/issues/84438 + +------------------------ +"##, + }, + Lint { + label: "panic_backtrace_config", + description: r##"# `panic_backtrace_config` + +The tracking issue for this feature is: [#93346] + +[#93346]: https://github.com/rust-lang/rust/issues/93346 + +------------------------ +"##, + }, + Lint { + label: "panic_can_unwind", + description: r##"# `panic_can_unwind` + +The tracking issue for this feature is: [#92988] + +[#92988]: https://github.com/rust-lang/rust/issues/92988 + +------------------------ +"##, + }, + Lint { + label: "panic_info_message", + description: r##"# `panic_info_message` + +The tracking issue for this feature is: [#66745] + +[#66745]: https://github.com/rust-lang/rust/issues/66745 + +------------------------ +"##, + }, + Lint { + label: "panic_internals", + description: r##"# `panic_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "panic_runtime", + description: r##"# `panic_runtime` + +The tracking issue for this feature is: [#32837] + +[#32837]: https://github.com/rust-lang/rust/issues/32837 + +------------------------ +"##, + }, + Lint { + label: "panic_unwind", + description: r##"# `panic_unwind` + +The tracking issue for this feature is: [#32837] + +[#32837]: https://github.com/rust-lang/rust/issues/32837 + +------------------------ +"##, + }, + Lint { + label: "panic_update_hook", + description: r##"# `panic_update_hook` + +The tracking issue for this feature is: [#92649] + +[#92649]: https://github.com/rust-lang/rust/issues/92649 + +------------------------ +"##, + }, + Lint { + label: "path_file_prefix", + description: r##"# `path_file_prefix` + +The tracking issue for this feature is: [#86319] + +[#86319]: https://github.com/rust-lang/rust/issues/86319 + +------------------------ +"##, + }, + Lint { + label: "pattern", + description: r##"# `pattern` + +The tracking issue for this feature is: [#27721] + +[#27721]: https://github.com/rust-lang/rust/issues/27721 + +------------------------ +"##, + }, + Lint { + label: "peer_credentials_unix_socket", + description: r##"# `peer_credentials_unix_socket` + +The tracking issue for this feature is: [#42839] + +[#42839]: https://github.com/rust-lang/rust/issues/42839 + +------------------------ +"##, + }, + Lint { + label: "pin_deref_mut", + description: r##"# `pin_deref_mut` + +The tracking issue for this feature is: [#86918] + +[#86918]: https://github.com/rust-lang/rust/issues/86918 + +------------------------ +"##, + }, + Lint { + label: "platform_intrinsics", + description: r##"# `platform_intrinsics` + +The tracking issue for this feature is: [#27731] + +[#27731]: https://github.com/rust-lang/rust/issues/27731 + +------------------------ +"##, + }, + Lint { + label: "plugin", + description: r##"# `plugin` + +The tracking issue for this feature is: [#29597] + +[#29597]: https://github.com/rust-lang/rust/issues/29597 + + +This feature is part of "compiler plugins." It will often be used with the +`rustc_private` feature. + +------------------------ + +`rustc` can load compiler plugins, which are user-provided libraries that +extend the compiler's behavior with new lint checks, etc. + +A plugin is a dynamic library crate with a designated *registrar* function that +registers extensions with `rustc`. Other crates can load these extensions using +the crate attribute `#![plugin(...)]`. See the +`rustc_driver::plugin` documentation for more about the +mechanics of defining and loading a plugin. + +In the vast majority of cases, a plugin should *only* be used through +`#![plugin]` and not through an `extern crate` item. Linking a plugin would +pull in all of librustc_ast and librustc as dependencies of your crate. This is +generally unwanted unless you are building another plugin. + +The usual practice is to put compiler plugins in their own crate, separate from +any `macro_rules!` macros or ordinary Rust code meant to be used by consumers +of a library. + +# Lint plugins + +Plugins can extend [Rust's lint +infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with +additional checks for code style, safety, etc. Now let's write a plugin +[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs) +that warns about any item named `lintme`. + +```rust,ignore (requires-stage-2) +#![feature(rustc_private)] + +extern crate rustc_ast; + +// Load rustc as a plugin to get macros +extern crate rustc_driver; +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; + +use rustc_ast::ast; +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; + +declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); + +declare_lint_pass!(Pass => [TEST_LINT]); + +impl EarlyLintPass for Pass { + fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { + if it.ident.name.as_str() == "lintme" { + cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)); } + } +} - impl Generator for __Generator { - type Yield = i32; - type Return = &'static str; +#[no_mangle] +fn __rustc_plugin_registrar(reg: &mut Registry) { + reg.lint_store.register_lints(&[&TEST_LINT]); + reg.lint_store.register_early_pass(|| Box::new(Pass)); +} +``` + +Then code like + +```rust,ignore (requires-plugin) +#![feature(plugin)] +#![plugin(lint_plugin_test)] + +fn lintme() { } +``` + +will produce a compiler warning: + +```txt +foo.rs:4:1: 4:16 warning: item is named 'lintme', #[warn(test_lint)] on by default +foo.rs:4 fn lintme() { } + ^~~~~~~~~~~~~~~ +``` + +The components of a lint plugin are: + +* one or more `declare_lint!` invocations, which define static `Lint` structs; + +* a struct holding any state needed by the lint pass (here, none); + +* a `LintPass` + implementation defining how to check each syntax element. A single + `LintPass` may call `span_lint` for several different `Lint`s, but should + register them all through the `get_lints` method. + +Lint passes are syntax traversals, but they run at a late stage of compilation +where type information is available. `rustc`'s [built-in +lints](https://github.com/rust-lang/rust/blob/master/compiler/rustc_lint_defs/src/builtin.rs) +mostly use the same infrastructure as lint plugins, and provide examples of how +to access type information. + +Lints defined by plugins are controlled by the usual [attributes and compiler +flags](../../reference/attributes/diagnostics.md#lint-check-attributes), e.g. +`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the +first argument to `declare_lint!`, with appropriate case and punctuation +conversion. + +You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`, +including those provided by plugins loaded by `foo.rs`. +"##, + }, + Lint { + label: "pointer_byte_offsets", + description: r##"# `pointer_byte_offsets` + +The tracking issue for this feature is: [#96283] + +[#96283]: https://github.com/rust-lang/rust/issues/96283 + +------------------------ +"##, + }, + Lint { + label: "pointer_is_aligned", + description: r##"# `pointer_is_aligned` + +The tracking issue for this feature is: [#96284] + +[#96284]: https://github.com/rust-lang/rust/issues/96284 + +------------------------ +"##, + }, + Lint { + label: "pointer_like_trait", + description: r##"# `pointer_like_trait` - fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState { - use std::mem; - match mem::replace(&mut *self, __Generator::Done) { - __Generator::Start(s) => { - *self = __Generator::Yield1(s); - GeneratorState::Yielded(1) - } +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. - __Generator::Yield1(s) => { - *self = __Generator::Done; - GeneratorState::Complete(s) - } +------------------------ +"##, + }, + Lint { + label: "portable_simd", + description: r##"# `portable_simd` - __Generator::Done => { - panic!("generator resumed after completion") - } - } - } - } +The tracking issue for this feature is: [#86656] - __Generator::Start(ret) - }; +[#86656]: https://github.com/rust-lang/rust/issues/86656 - Pin::new(&mut generator).resume(()); - Pin::new(&mut generator).resume(()); -} -``` +------------------------ +"##, + }, + Lint { + label: "powerpc_target_feature", + description: r##"# `powerpc_target_feature` -Notably here we can see that the compiler is generating a fresh type, -`__Generator` in this case. This type has a number of states (represented here -as an `enum`) corresponding to each of the conceptual states of the generator. -At the beginning we're closing over our outer variable `foo` and then that -variable is also live over the `yield` point, so it's stored in both states. +The tracking issue for this feature is: [#44839] -When the generator starts it'll immediately yield 1, but it saves off its state -just before it does so indicating that it has reached the yield point. Upon -resuming again we'll execute the `return ret` which returns the `Complete` -state. +[#44839]: https://github.com/rust-lang/rust/issues/44839 -Here we can also note that the `Done` state, if resumed, panics immediately as -it's invalid to resume a completed generator. It's also worth noting that this -is just a rough desugaring, not a normative specification for what the compiler -does. +------------------------ "##, }, Lint { - label: "half_open_range_patterns", - description: r##"# `half_open_range_patterns` + label: "precise_pointer_size_matching", + description: r##"# `precise_pointer_size_matching` -The tracking issue for this feature is: [#67264] -It is part of the `#![exclusive_range_pattern]` feature, -tracked at [#37854]. +The tracking issue for this feature is: [#56354] -[#67264]: https://github.com/rust-lang/rust/issues/67264 -[#37854]: https://github.com/rust-lang/rust/issues/37854 ------ +[#56354]: https://github.com/rust-lang/rust/issues/56354 -The `half_open_range_patterns` feature allows RangeTo patterns -(`..10`) to be used in appropriate pattern matching contexts. -This requires also enabling the `exclusive_range_pattern` feature. +------------------------ +"##, + }, + Lint { + label: "prelude_2024", + description: r##"# `prelude_2024` -It also enabled RangeFrom patterns but that has since been -stabilized. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -```rust -#![feature(half_open_range_patterns)] -#![feature(exclusive_range_pattern)] - let x = 5; - match x { - ..0 => println!("negative!"), // "RangeTo" pattern. Unstable. - 0 => println!("zero!"), - 1.. => println!("positive!"), // "RangeFrom" pattern. Stable. - } -``` +------------------------ "##, }, Lint { - label: "infer_static_outlives_requirements", - description: r##"# `infer_static_outlives_requirements` + label: "prelude_import", + description: r##"# `prelude_import` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -The tracking issue for this feature is: [#54185] +------------------------ +"##, + }, + Lint { + label: "print_internals", + description: r##"# `print_internals` -[#54185]: https://github.com/rust-lang/rust/issues/54185 +This feature is internal to the Rust compiler and is not intended for general use. ------------------------ -The `infer_static_outlives_requirements` feature indicates that certain -`'static` outlives requirements can be inferred by the compiler rather than -stating them explicitly. +"##, + }, + Lint { + label: "proc_macro_byte_character", + description: r##"# `proc_macro_byte_character` -Note: It is an accompanying feature to `infer_outlives_requirements`, -which must be enabled to infer outlives requirements. +The tracking issue for this feature is: [#115268] -For example, currently generic struct definitions that contain -references, require where-clauses of the form T: 'static. By using -this feature the outlives predicates will be inferred, although -they may still be written explicitly. +[#115268]: https://github.com/rust-lang/rust/issues/115268 -```rust,ignore (pseudo-Rust) -struct Foo where U: 'static { // <-- currently required - bar: Bar -} -struct Bar { - x: T, -} -``` +------------------------ +"##, + }, + Lint { + label: "proc_macro_def_site", + description: r##"# `proc_macro_def_site` +The tracking issue for this feature is: [#54724] -## Examples: +[#54724]: https://github.com/rust-lang/rust/issues/54724 -```rust,ignore (pseudo-Rust) -#![feature(infer_outlives_requirements)] -#![feature(infer_static_outlives_requirements)] +------------------------ +"##, + }, + Lint { + label: "proc_macro_diagnostic", + description: r##"# `proc_macro_diagnostic` -#[rustc_outlives] -// Implicitly infer U: 'static -struct Foo { - bar: Bar -} -struct Bar { - x: T, -} -``` +The tracking issue for this feature is: [#54140] + +[#54140]: https://github.com/rust-lang/rust/issues/54140 + +------------------------ "##, }, Lint { - label: "inline_const", - description: r##"# `inline_const` + label: "proc_macro_expand", + description: r##"# `proc_macro_expand` -The tracking issue for this feature is: [#76001] +The tracking issue for this feature is: [#90765] -See also [`inline_const_pat`](inline-const-pat.md) +[#90765]: https://github.com/rust-lang/rust/issues/90765 ------- +------------------------ +"##, + }, + Lint { + label: "proc_macro_hygiene", + description: r##"# `proc_macro_hygiene` -This feature allows you to use inline constant expressions. For example, you can -turn this code: +The tracking issue for this feature is: [#54727] -```rust -# fn add_one(x: i32) -> i32 { x + 1 } -const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4; +[#54727]: https://github.com/rust-lang/rust/issues/54727 -fn main() { - let x = add_one(MY_COMPUTATION); -} -``` +------------------------ +"##, + }, + Lint { + label: "proc_macro_internals", + description: r##"# `proc_macro_internals` -into this code: +The tracking issue for this feature is: [#27812] -```rust -#![feature(inline_const)] +[#27812]: https://github.com/rust-lang/rust/issues/27812 -# fn add_one(x: i32) -> i32 { x + 1 } -fn main() { - let x = add_one(const { 1 + 2 * 3 / 4 }); -} -``` +------------------------ +"##, + }, + Lint { + label: "proc_macro_quote", + description: r##"# `proc_macro_quote` -[#76001]: https://github.com/rust-lang/rust/issues/76001 +The tracking issue for this feature is: [#54722] + +[#54722]: https://github.com/rust-lang/rust/issues/54722 + +------------------------ "##, }, Lint { - label: "inline_const_pat", - description: r##"# `inline_const_pat` + label: "proc_macro_span", + description: r##"# `proc_macro_span` -The tracking issue for this feature is: [#76001] +The tracking issue for this feature is: [#54725] -See also [`inline_const`](inline-const.md) +[#54725]: https://github.com/rust-lang/rust/issues/54725 ------- +------------------------ +"##, + }, + Lint { + label: "proc_macro_tracked_env", + description: r##"# `proc_macro_tracked_env` -This feature allows you to use inline constant expressions in pattern position: +The tracking issue for this feature is: [#99515] -```rust -#![feature(inline_const_pat)] +[#99515]: https://github.com/rust-lang/rust/issues/99515 -const fn one() -> i32 { 1 } +------------------------ +"##, + }, + Lint { + label: "process_exitcode_internals", + description: r##"# `process_exitcode_internals` -let some_int = 3; -match some_int { - const { 1 + 2 } => println!("Matched 1 + 2"), - const { one() } => println!("Matched const fn returning 1"), - _ => println!("Didn't match anything :("), -} -``` +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -[#76001]: https://github.com/rust-lang/rust/issues/76001 +------------------------ "##, }, Lint { - label: "int_error_internals", - description: r##"# `int_error_internals` + label: "process_internals", + description: r##"# `process_internals` -This feature is internal to the Rust compiler and is not intended for general use. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, }, Lint { - label: "internal_output_capture", - description: r##"# `internal_output_capture` + label: "profiler_runtime", + description: r##"# `profiler_runtime` + +The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524). + +------------------------ +"##, + }, + Lint { + label: "profiler_runtime_lib", + description: r##"# `profiler_runtime_lib` This feature is internal to the Rust compiler and is not intended for general use. @@ -2679,1021 +7252,934 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { - label: "intra_doc_pointers", - description: r##"# `intra-doc-pointers` + label: "ptr_addr_eq", + description: r##"# `ptr_addr_eq` -The tracking issue for this feature is: [#80896] +The tracking issue for this feature is: [#116324] -[#80896]: https://github.com/rust-lang/rust/issues/80896 +[#116324]: https://github.com/rust-lang/rust/issues/116324 ------------------------ +"##, + }, + Lint { + label: "ptr_alignment_type", + description: r##"# `ptr_alignment_type` -Rustdoc does not currently allow disambiguating between `*const` and `*mut`, and -raw pointers in intra-doc links are unstable until it does. +The tracking issue for this feature is: [#102070] -```rust -#![feature(intra_doc_pointers)] -//! [pointer::add] -``` +[#102070]: https://github.com/rust-lang/rust/issues/102070 + +------------------------ "##, }, Lint { - label: "intrinsics", - description: r##"# `intrinsics` + label: "ptr_as_uninit", + description: r##"# `ptr_as_uninit` -The tracking issue for this feature is: None. +The tracking issue for this feature is: [#75402] -Intrinsics are never intended to be stable directly, but intrinsics are often -exported in some sort of stable manner. Prefer using the stable interfaces to -the intrinsic directly when you can. +[#75402]: https://github.com/rust-lang/rust/issues/75402 ------------------------ +"##, + }, + Lint { + label: "ptr_from_ref", + description: r##"# `ptr_from_ref` +The tracking issue for this feature is: [#106116] -These are imported as if they were FFI functions, with the special -`rust-intrinsic` ABI. For example, if one was in a freestanding -context, but wished to be able to `transmute` between types, and -perform efficient pointer arithmetic, one would import those functions -via a declaration like - -```rust -#![feature(intrinsics)] -# fn main() {} +[#106116]: https://github.com/rust-lang/rust/issues/106116 -extern "rust-intrinsic" { - fn transmute(x: T) -> U; +------------------------ +"##, + }, + Lint { + label: "ptr_internals", + description: r##"# `ptr_internals` - fn offset(dst: *const T, offset: isize) -> *const T; -} -``` +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -As with any other FFI functions, these are always `unsafe` to call. +------------------------ "##, }, Lint { - label: "is_sorted", - description: r##"# `is_sorted` + label: "ptr_mask", + description: r##"# `ptr_mask` -The tracking issue for this feature is: [#53485] +The tracking issue for this feature is: [#98290] -[#53485]: https://github.com/rust-lang/rust/issues/53485 +[#98290]: https://github.com/rust-lang/rust/issues/98290 ------------------------ +"##, + }, + Lint { + label: "ptr_metadata", + description: r##"# `ptr_metadata` -Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`; -add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to -`Iterator`. +The tracking issue for this feature is: [#81513] + +[#81513]: https://github.com/rust-lang/rust/issues/81513 + +------------------------ "##, }, Lint { - label: "lang_items", - description: r##"# `lang_items` + label: "ptr_sub_ptr", + description: r##"# `ptr_sub_ptr` -The tracking issue for this feature is: None. +The tracking issue for this feature is: [#95892] + +[#95892]: https://github.com/rust-lang/rust/issues/95892 ------------------------ +"##, + }, + Lint { + label: "ptr_to_from_bits", + description: r##"# `ptr_to_from_bits` -The `rustc` compiler has certain pluggable operations, that is, -functionality that isn't hard-coded into the language, but is -implemented in libraries, with a special marker to tell the compiler -it exists. The marker is the attribute `#[lang = "..."]` and there are -various different values of `...`, i.e. various different 'lang -items'. +The tracking issue for this feature is: [#91126] -For example, `Box` pointers require two lang items, one for allocation -and one for deallocation. A freestanding program that uses the `Box` -sugar for dynamic allocations via `malloc` and `free`: +[#91126]: https://github.com/rust-lang/rust/issues/91126 -```rust,ignore (libc-is-finicky) -#![feature(lang_items, box_syntax, start, libc, core_intrinsics, rustc_private)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; +------------------------ +"##, + }, + Lint { + label: "pub_crate_should_not_need_unstable_attr", + description: r##"# `pub_crate_should_not_need_unstable_attr` -extern crate libc; +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -#[lang = "owned_box"] -pub struct Box(*mut T); +------------------------ +"##, + }, + Lint { + label: "raw_os_error_ty", + description: r##"# `raw_os_error_ty` -#[lang = "exchange_malloc"] -unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as libc::size_t) as *mut u8; +The tracking issue for this feature is: [#107792] - // Check if `malloc` failed: - if p as usize == 0 { - intrinsics::abort(); - } +[#107792]: https://github.com/rust-lang/rust/issues/107792 - p -} +------------------------ +"##, + }, + Lint { + label: "raw_os_nonzero", + description: r##"# `raw_os_nonzero` -#[lang = "box_free"] -unsafe fn box_free(ptr: *mut T) { - libc::free(ptr as *mut libc::c_void) -} +The tracking issue for this feature is: [#82363] -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { - let _x = box 1; +[#82363]: https://github.com/rust-lang/rust/issues/82363 - 0 -} +------------------------ +"##, + }, + Lint { + label: "raw_ref_op", + description: r##"# `raw_ref_op` -#[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } -#[no_mangle] pub extern fn rust_eh_register_frames () {} -#[no_mangle] pub extern fn rust_eh_unregister_frames () {} -``` +The tracking issue for this feature is: [#64490] -Note the use of `abort`: the `exchange_malloc` lang item is assumed to -return a valid pointer, and so needs to do the check internally. +[#64490]: https://github.com/rust-lang/rust/issues/64490 -Other features provided by lang items include: +------------------------ +"##, + }, + Lint { + label: "raw_slice_split", + description: r##"# `raw_slice_split` -- overloadable operators via traits: the traits corresponding to the - `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all - marked with lang items; those specific four are `eq`, `ord`, - `deref`, and `add` respectively. -- stack unwinding and general failure; the `eh_personality`, - `panic` and `panic_bounds_check` lang items. -- the traits in `std::marker` used to indicate types of - various kinds; lang items `send`, `sync` and `copy`. -- the marker types and variance indicators found in - `std::marker`; lang items `covariant_type`, - `contravariant_lifetime`, etc. - -Lang items are loaded lazily by the compiler; e.g. if one never uses -`Box` then there is no need to define functions for `exchange_malloc` -and `box_free`. `rustc` will emit an error when an item is needed -but not found in the current crate or any that it depends on. - -Most lang items are defined by `libcore`, but if you're trying to build -an executable without the standard library, you'll run into the need -for lang items. The rest of this page focuses on this use-case, even though -lang items are a bit broader than that. - -### Using libc - -In order to build a `#[no_std]` executable we will need libc as a dependency. -We can specify this using our `Cargo.toml` file: - -```toml -[dependencies] -libc = { version = "0.2.14", default-features = false } -``` +The tracking issue for this feature is: [#95595] -Note that the default features have been disabled. This is a critical step - -**the default features of libc include the standard library and so must be -disabled.** +[#95595]: https://github.com/rust-lang/rust/issues/95595 -### Writing an executable without stdlib +------------------------ +"##, + }, + Lint { + label: "raw_vec_internals", + description: r##"# `raw_vec_internals` -Controlling the entry point is possible in two ways: the `#[start]` attribute, -or overriding the default shim for the C `main` function with your own. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -The function marked `#[start]` is passed the command line parameters -in the same format as C: +------------------------ +"##, + }, + Lint { + label: "read_buf", + description: r##"# `read_buf` -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; +The tracking issue for this feature is: [#78485] -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; +[#78485]: https://github.com/rust-lang/rust/issues/78485 -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} +------------------------ +"##, + }, + Lint { + label: "ready_into_inner", + description: r##"# `ready_into_inner` -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} +The tracking issue for this feature is: [#101196] -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` +[#101196]: https://github.com/rust-lang/rust/issues/101196 -To override the compiler-inserted `main` shim, one has to disable it -with `#![no_main]` and then create the appropriate symbol with the -correct ABI and the correct name, which requires overriding the -compiler's name mangling too: +------------------------ +"##, + }, + Lint { + label: "receiver_trait", + description: r##"# `receiver_trait` -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -#![no_main] -use core::intrinsics; -use core::panic::PanicInfo; +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; +------------------------ +"##, + }, + Lint { + label: "register_tool", + description: r##"# `register_tool` -// Entry point for this program. -#[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { - 0 -} +The tracking issue for this feature is: [#66079] -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} +[#66079]: https://github.com/rust-lang/rust/issues/66079 -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` +------------------------ +"##, + }, + Lint { + label: "repr128", + description: r##"# `repr128` -In many cases, you may need to manually link to the `compiler_builtins` crate -when building a `no_std` binary. You may observe this via linker error messages -such as "```undefined reference to `__rust_probestack'```". +The tracking issue for this feature is: [#56071] -## More about the language items +[#56071]: https://github.com/rust-lang/rust/issues/56071 -The compiler currently makes a few assumptions about symbols which are -available in the executable to call. Normally these functions are provided by -the standard library, but without it you must define your own. These symbols -are called "language items", and they each have an internal name, and then a -signature that an implementation must conform to. +------------------------ -The first of these functions, `rust_eh_personality`, is used by the failure -mechanisms of the compiler. This is often mapped to GCC's personality function -(see the [libstd implementation][unwind] for more information), but crates -which do not trigger a panic can be assured that this function is never -called. The language item's name is `eh_personality`. +The `repr128` feature adds support for `#[repr(u128)]` on `enum`s. -[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs +```rust +#![feature(repr128)] -The second function, `rust_begin_panic`, is also used by the failure mechanisms of the -compiler. When a panic happens, this controls the message that's displayed on -the screen. While the language item's name is `panic_impl`, the symbol name is -`rust_begin_panic`. +#[repr(u128)] +enum Foo { + Bar(u64), +} +``` +"##, + }, + Lint { + label: "repr_simd", + description: r##"# `repr_simd` -Finally, a `eh_catch_typeinfo` static is needed for certain targets which -implement Rust panics on top of C++ exceptions. +The tracking issue for this feature is: [#27731] -## List of all language items +[#27731]: https://github.com/rust-lang/rust/issues/27731 -This is a list of all language items in Rust along with where they are located in -the source code. - -- Primitives - - `i8`: `libcore/num/mod.rs` - - `i16`: `libcore/num/mod.rs` - - `i32`: `libcore/num/mod.rs` - - `i64`: `libcore/num/mod.rs` - - `i128`: `libcore/num/mod.rs` - - `isize`: `libcore/num/mod.rs` - - `u8`: `libcore/num/mod.rs` - - `u16`: `libcore/num/mod.rs` - - `u32`: `libcore/num/mod.rs` - - `u64`: `libcore/num/mod.rs` - - `u128`: `libcore/num/mod.rs` - - `usize`: `libcore/num/mod.rs` - - `f32`: `libstd/f32.rs` - - `f64`: `libstd/f64.rs` - - `char`: `libcore/char.rs` - - `slice`: `liballoc/slice.rs` - - `str`: `liballoc/str.rs` - - `const_ptr`: `libcore/ptr.rs` - - `mut_ptr`: `libcore/ptr.rs` - - `unsafe_cell`: `libcore/cell.rs` -- Runtime - - `start`: `libstd/rt.rs` - - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) - - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) - - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) - - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) - - `panic`: `libcore/panicking.rs` - - `panic_bounds_check`: `libcore/panicking.rs` - - `panic_impl`: `libcore/panicking.rs` - - `panic_impl`: `libstd/panicking.rs` -- Allocations - - `owned_box`: `liballoc/boxed.rs` - - `exchange_malloc`: `liballoc/heap.rs` - - `box_free`: `liballoc/heap.rs` -- Operands - - `not`: `libcore/ops/bit.rs` - - `bitand`: `libcore/ops/bit.rs` - - `bitor`: `libcore/ops/bit.rs` - - `bitxor`: `libcore/ops/bit.rs` - - `shl`: `libcore/ops/bit.rs` - - `shr`: `libcore/ops/bit.rs` - - `bitand_assign`: `libcore/ops/bit.rs` - - `bitor_assign`: `libcore/ops/bit.rs` - - `bitxor_assign`: `libcore/ops/bit.rs` - - `shl_assign`: `libcore/ops/bit.rs` - - `shr_assign`: `libcore/ops/bit.rs` - - `deref`: `libcore/ops/deref.rs` - - `deref_mut`: `libcore/ops/deref.rs` - - `index`: `libcore/ops/index.rs` - - `index_mut`: `libcore/ops/index.rs` - - `add`: `libcore/ops/arith.rs` - - `sub`: `libcore/ops/arith.rs` - - `mul`: `libcore/ops/arith.rs` - - `div`: `libcore/ops/arith.rs` - - `rem`: `libcore/ops/arith.rs` - - `neg`: `libcore/ops/arith.rs` - - `add_assign`: `libcore/ops/arith.rs` - - `sub_assign`: `libcore/ops/arith.rs` - - `mul_assign`: `libcore/ops/arith.rs` - - `div_assign`: `libcore/ops/arith.rs` - - `rem_assign`: `libcore/ops/arith.rs` - - `eq`: `libcore/cmp.rs` - - `ord`: `libcore/cmp.rs` -- Functions - - `fn`: `libcore/ops/function.rs` - - `fn_mut`: `libcore/ops/function.rs` - - `fn_once`: `libcore/ops/function.rs` - - `generator_state`: `libcore/ops/generator.rs` - - `generator`: `libcore/ops/generator.rs` -- Other - - `coerce_unsized`: `libcore/ops/unsize.rs` - - `drop`: `libcore/ops/drop.rs` - - `drop_in_place`: `libcore/ptr.rs` - - `clone`: `libcore/clone.rs` - - `copy`: `libcore/marker.rs` - - `send`: `libcore/marker.rs` - - `sized`: `libcore/marker.rs` - - `unsize`: `libcore/marker.rs` - - `sync`: `libcore/marker.rs` - - `phantom_data`: `libcore/marker.rs` - - `discriminant_kind`: `libcore/marker.rs` - - `freeze`: `libcore/marker.rs` - - `debug_trait`: `libcore/fmt/mod.rs` - - `non_zero`: `libcore/nonzero.rs` - - `arc`: `liballoc/sync.rs` - - `rc`: `liballoc/rc.rs` +------------------------ "##, }, Lint { - label: "libstd_sys_internals", - description: r##"# `libstd_sys_internals` + label: "restricted_std", + description: r##"# `restricted_std` -This feature is internal to the Rust compiler and is not intended for general use. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, }, Lint { - label: "libstd_thread_internals", - description: r##"# `libstd_thread_internals` + label: "result_flattening", + description: r##"# `result_flattening` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#70142] + +[#70142]: https://github.com/rust-lang/rust/issues/70142 ------------------------ "##, }, Lint { - label: "link_cfg", - description: r##"# `link_cfg` + label: "result_option_inspect", + description: r##"# `result_option_inspect` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#91345] + +[#91345]: https://github.com/rust-lang/rust/issues/91345 ------------------------ "##, }, Lint { - label: "llvm_asm", - description: r##"# `llvm_asm` + label: "return_position_impl_trait_in_trait", + description: r##"# `return_position_impl_trait_in_trait` -The tracking issue for this feature is: [#70173] +The tracking issue for this feature is: [#91611] -[#70173]: https://github.com/rust-lang/rust/issues/70173 +[#91611]: https://github.com/rust-lang/rust/issues/91611 ------------------------ +"##, + }, + Lint { + label: "return_type_notation", + description: r##"# `return_type_notation` -For extremely low-level manipulations and performance reasons, one -might wish to control the CPU directly. Rust supports using inline -assembly to do this via the `llvm_asm!` macro. +The tracking issue for this feature is: [#109417] -```rust,ignore (pseudo-code) -llvm_asm!(assembly template - : output operands - : input operands - : clobbers - : options - ); -``` +[#109417]: https://github.com/rust-lang/rust/issues/109417 -Any use of `llvm_asm` is feature gated (requires `#![feature(llvm_asm)]` on the -crate to allow) and of course requires an `unsafe` block. +------------------------ +"##, + }, + Lint { + label: "riscv_target_feature", + description: r##"# `riscv_target_feature` -> **Note**: the examples here are given in x86/x86-64 assembly, but -> all platforms are supported. +The tracking issue for this feature is: [#44839] -## Assembly template +[#44839]: https://github.com/rust-lang/rust/issues/44839 -The `assembly template` is the only required parameter and must be a -literal string (i.e. `""`) +------------------------ +"##, + }, + Lint { + label: "round_char_boundary", + description: r##"# `round_char_boundary` -```rust -#![feature(llvm_asm)] +The tracking issue for this feature is: [#93743] -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn foo() { - unsafe { - llvm_asm!("NOP"); - } -} +[#93743]: https://github.com/rust-lang/rust/issues/93743 -// Other platforms: -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -fn foo() { /* ... */ } +------------------------ +"##, + }, + Lint { + label: "round_ties_even", + description: r##"# `round_ties_even` -fn main() { - // ... - foo(); - // ... -} -``` +The tracking issue for this feature is: [#96710] -(The `feature(llvm_asm)` and `#[cfg]`s are omitted from now on.) +[#96710]: https://github.com/rust-lang/rust/issues/96710 -Output operands, input operands, clobbers and options are all optional -but you must add the right number of `:` if you skip them: +------------------------ +"##, + }, + Lint { + label: "rt", + description: r##"# `rt` -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -llvm_asm!("xor %eax, %eax" - : - : - : "eax" - ); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` +This feature is internal to the Rust compiler and is not intended for general use. -Whitespace also doesn't matter: +------------------------ +"##, + }, + Lint { + label: "rtm_target_feature", + description: r##"# `rtm_target_feature` -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -llvm_asm!("xor %eax, %eax" ::: "eax"); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` +The tracking issue for this feature is: [#44839] -## Operands +[#44839]: https://github.com/rust-lang/rust/issues/44839 -Input and output operands follow the same format: `: -"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand -expressions must be mutable place, or not yet assigned: +------------------------ +"##, + }, + Lint { + label: "rust_cold_cc", + description: r##"# `rust_cold_cc` -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn add(a: i32, b: i32) -> i32 { - let c: i32; - unsafe { - llvm_asm!("add $2, $0" - : "=r"(c) - : "0"(a), "r"(b) - ); - } - c -} -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn add(a: i32, b: i32) -> i32 { a + b } +The tracking issue for this feature is: [#97544] -fn main() { - assert_eq!(add(3, 14159), 14162) -} -``` +[#97544]: https://github.com/rust-lang/rust/issues/97544 -If you would like to use real operands in this position, however, -you are required to put curly braces `{}` around the register that -you want, and you are required to put the specific size of the -operand. This is useful for very low level programming, where -which register you use is important: +------------------------ +"##, + }, + Lint { + label: "rustc_allow_const_fn_unstable", + description: r##"# `rustc_allow_const_fn_unstable` -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# unsafe fn read_byte_in(port: u16) -> u8 { -let result: u8; -llvm_asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port)); -result -# } -``` +The tracking issue for this feature is: [#69399] -## Clobbers +[#69399]: https://github.com/rust-lang/rust/issues/69399 -Some instructions modify registers which might otherwise have held -different values so we use the clobbers list to indicate to the -compiler not to assume any values loaded into those registers will -stay valid. +------------------------ +"##, + }, + Lint { + label: "rustc_attrs", + description: r##"# `rustc_attrs` -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -// Put the value 0x200 in eax: -llvm_asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax"); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` +This feature has no tracking issue, and is therefore internal to +the compiler, not being intended for general use. -Input and output registers need not be listed since that information -is already communicated by the given constraints. Otherwise, any other -registers used either implicitly or explicitly should be listed. +Note: `rustc_attrs` enables many rustc-internal attributes and this page +only discuss a few of them. -If the assembly changes the condition code register `cc` should be -specified as one of the clobbers. Similarly, if the assembly modifies -memory, `memory` should also be specified. +------------------------ -## Options +The `rustc_attrs` feature allows debugging rustc type layouts by using +`#[rustc_layout(...)]` to debug layout at compile time (it even works +with `cargo check`) as an alternative to `rustc -Z print-type-sizes` +that is way more verbose. -The last section, `options` is specific to Rust. The format is comma -separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to -specify some extra info about the inline assembly: +Options provided by `#[rustc_layout(...)]` are `debug`, `size`, `align`, +`abi`. Note that it only works on sized types without generics. -Current valid options are: +## Examples -1. `volatile` - specifying this is analogous to - `__asm__ __volatile__ (...)` in gcc/clang. -2. `alignstack` - certain instructions expect the stack to be - aligned a certain way (i.e. SSE) and specifying this indicates to - the compiler to insert its usual stack alignment code -3. `intel` - use intel syntax instead of the default AT&T. +```rust,compile_fail +#![feature(rustc_attrs)] -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { -let result: i32; -unsafe { - llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel") +#[rustc_layout(abi, size)] +pub enum X { + Y(u8, u8, u8), + Z(isize), } -println!("eax is currently {}", result); -# } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} ``` -## More Information +When that is compiled, the compiler will error with something like + +```text +error: abi: Aggregate { sized: true } + --> src/lib.rs:4:1 + | +4 | / pub enum T { +5 | | Y(u8, u8, u8), +6 | | Z(isize), +7 | | } + | |_^ -The current implementation of the `llvm_asm!` macro is a direct binding to [LLVM's -inline assembler expressions][llvm-docs], so be sure to check out [their -documentation as well][llvm-docs] for more information about clobbers, -constraints, etc. +error: size: Size { raw: 16 } + --> src/lib.rs:4:1 + | +4 | / pub enum T { +5 | | Y(u8, u8, u8), +6 | | Z(isize), +7 | | } + | |_^ -[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions +error: aborting due to 2 previous errors +``` "##, }, Lint { - label: "marker_trait_attr", - description: r##"# `marker_trait_attr` + label: "rustc_private", + description: r##"# `rustc_private` -The tracking issue for this feature is: [#29864] +The tracking issue for this feature is: [#27812] -[#29864]: https://github.com/rust-lang/rust/issues/29864 +[#27812]: https://github.com/rust-lang/rust/issues/27812 ------------------------ +"##, + }, + Lint { + label: "rustdoc_internals", + description: r##"# `rustdoc_internals` -Normally, Rust keeps you from adding trait implementations that could -overlap with each other, as it would be ambiguous which to use. This -feature, however, carves out an exception to that rule: a trait can -opt-in to having overlapping implementations, at the cost that those -implementations are not allowed to override anything (and thus the -trait itself cannot have any associated items, as they're pointless -when they'd need to do the same thing for every type anyway). +The tracking issue for this feature is: [#90418] -```rust -#![feature(marker_trait_attr)] +[#90418]: https://github.com/rust-lang/rust/issues/90418 -#[marker] trait CheapToClone: Clone {} +------------------------ +"##, + }, + Lint { + label: "rustdoc_missing_doc_code_examples", + description: r##"# `rustdoc_missing_doc_code_examples` -impl CheapToClone for T {} +The tracking issue for this feature is: [#101730] -// These could potentially overlap with the blanket implementation above, -// so are only allowed because CheapToClone is a marker trait. -impl CheapToClone for (T, U) {} -impl CheapToClone for std::ops::Range {} +[#101730]: https://github.com/rust-lang/rust/issues/101730 -fn cheap_clone(t: T) -> T { - t.clone() -} -``` +------------------------ +"##, + }, + Lint { + label: "sealed", + description: r##"# `sealed` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "seek_stream_len", + description: r##"# `seek_stream_len` -This is expected to replace the unstable `overlapping_marker_traits` -feature, which applied to all empty traits (without needing an opt-in). +The tracking issue for this feature is: [#59359] + +[#59359]: https://github.com/rust-lang/rust/issues/59359 + +------------------------ "##, }, Lint { - label: "more_qualified_paths", - description: r##"# `more_qualified_paths` + label: "set_ptr_value", + description: r##"# `set_ptr_value` -The `more_qualified_paths` feature can be used in order to enable the -use of qualified paths in patterns. +The tracking issue for this feature is: [#75091] -## Example +[#75091]: https://github.com/rust-lang/rust/issues/75091 -```rust -#![feature(more_qualified_paths)] +------------------------ +"##, + }, + Lint { + label: "setgroups", + description: r##"# `setgroups` -fn main() { - // destructure through a qualified path - let ::Assoc { br } = StructStruct { br: 2 }; -} +The tracking issue for this feature is: [#90747] -struct StructStruct { - br: i8, -} +[#90747]: https://github.com/rust-lang/rust/issues/90747 -struct Foo; +------------------------ +"##, + }, + Lint { + label: "sgx_platform", + description: r##"# `sgx_platform` -trait A { - type Assoc; -} +The tracking issue for this feature is: [#56975] -impl A for Foo { - type Assoc = StructStruct; -} -``` +[#56975]: https://github.com/rust-lang/rust/issues/56975 + +------------------------ "##, }, Lint { - label: "native_link_modifiers", - description: r##"# `native_link_modifiers` + label: "simd_ffi", + description: r##"# `simd_ffi` -The tracking issue for this feature is: [#81490] +The tracking issue for this feature is: [#27731] -[#81490]: https://github.com/rust-lang/rust/issues/81490 +[#27731]: https://github.com/rust-lang/rust/issues/27731 ------------------------ +"##, + }, + Lint { + label: "sized_type_properties", + description: r##"# `sized_type_properties` -The `native_link_modifiers` feature allows you to use the `modifiers` syntax with the `#[link(..)]` attribute. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -Modifiers are specified as a comma-delimited string with each modifier prefixed with either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively. The last boolean value specified for a given modifier wins. +------------------------ "##, }, Lint { - label: "native_link_modifiers_as_needed", - description: r##"# `native_link_modifiers_as_needed` + label: "slice_as_chunks", + description: r##"# `slice_as_chunks` -The tracking issue for this feature is: [#81490] +The tracking issue for this feature is: [#74985] -[#81490]: https://github.com/rust-lang/rust/issues/81490 +[#74985]: https://github.com/rust-lang/rust/issues/74985 ------------------------ +"##, + }, + Lint { + label: "slice_concat_ext", + description: r##"# `slice_concat_ext` -The `native_link_modifiers_as_needed` feature allows you to use the `as-needed` modifier. +The tracking issue for this feature is: [#27747] -`as-needed` is only compatible with the `dynamic` and `framework` linking kinds. Using any other kind will result in a compiler error. +[#27747]: https://github.com/rust-lang/rust/issues/27747 -`+as-needed` means that the library will be actually linked only if it satisfies some undefined symbols at the point at which it is specified on the command line, making it similar to static libraries in this regard. +------------------------ +"##, + }, + Lint { + label: "slice_concat_trait", + description: r##"# `slice_concat_trait` -This modifier translates to `--as-needed` for ld-like linkers, and to `-dead_strip_dylibs` / `-needed_library` / `-needed_framework` for ld64. -The modifier does nothing for linkers that don't support it (e.g. `link.exe`). +The tracking issue for this feature is: [#27747] -The default for this modifier is unclear, some targets currently specify it as `+as-needed`, some do not. We may want to try making `+as-needed` a default for all targets. +[#27747]: https://github.com/rust-lang/rust/issues/27747 + +------------------------ "##, }, Lint { - label: "native_link_modifiers_bundle", - description: r##"# `native_link_modifiers_bundle` + label: "slice_first_last_chunk", + description: r##"# `slice_first_last_chunk` -The tracking issue for this feature is: [#81490] +The tracking issue for this feature is: [#111774] -[#81490]: https://github.com/rust-lang/rust/issues/81490 +[#111774]: https://github.com/rust-lang/rust/issues/111774 ------------------------ +"##, + }, + Lint { + label: "slice_flatten", + description: r##"# `slice_flatten` -The `native_link_modifiers_bundle` feature allows you to use the `bundle` modifier. +The tracking issue for this feature is: [#95629] -Only compatible with the `static` linking kind. Using any other kind will result in a compiler error. +[#95629]: https://github.com/rust-lang/rust/issues/95629 -`+bundle` means objects from the static library are bundled into the produced crate (a rlib, for example) and are used from this crate later during linking of the final binary. +------------------------ +"##, + }, + Lint { + label: "slice_from_ptr_range", + description: r##"# `slice_from_ptr_range` -`-bundle` means the static library is included into the produced rlib "by name" and object files from it are included only during linking of the final binary, the file search by that name is also performed during final linking. +The tracking issue for this feature is: [#89792] -This modifier is supposed to supersede the `static-nobundle` linking kind defined by [RFC 1717](https://github.com/rust-lang/rfcs/pull/1717). +[#89792]: https://github.com/rust-lang/rust/issues/89792 -The default for this modifier is currently `+bundle`, but it could be changed later on some future edition boundary. +------------------------ "##, }, Lint { - label: "native_link_modifiers_verbatim", - description: r##"# `native_link_modifiers_verbatim` + label: "slice_group_by", + description: r##"# `slice_group_by` -The tracking issue for this feature is: [#81490] +The tracking issue for this feature is: [#80552] -[#81490]: https://github.com/rust-lang/rust/issues/81490 +[#80552]: https://github.com/rust-lang/rust/issues/80552 ------------------------ +"##, + }, + Lint { + label: "slice_index_methods", + description: r##"# `slice_index_methods` -The `native_link_modifiers_verbatim` feature allows you to use the `verbatim` modifier. - -`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -For `ld`-like linkers rustc will use the `-l:filename` syntax (note the colon) when passing the library, so the linker won't add any prefixes or suffixes as well. -See [`-l namespec`](https://sourceware.org/binutils/docs/ld/Options.html) in ld documentation for more details. -For linkers not supporting any verbatim modifiers (e.g. `link.exe` or `ld64`) the library name will be passed as is. +------------------------ +"##, + }, + Lint { + label: "slice_internals", + description: r##"# `slice_internals` -The default for this modifier is `-verbatim`. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -This RFC changes the behavior of `raw-dylib` linking kind specified by [RFC 2627](https://github.com/rust-lang/rfcs/pull/2627). The `.dll` suffix (or other target-specified suffixes for other targets) is now added automatically. -If your DLL doesn't have the `.dll` suffix, it can be specified with `+verbatim`. +------------------------ "##, }, Lint { - label: "native_link_modifiers_whole_archive", - description: r##"# `native_link_modifiers_whole_archive` + label: "slice_iter_mut_as_mut_slice", + description: r##"# `slice_iter_mut_as_mut_slice` -The tracking issue for this feature is: [#81490] +The tracking issue for this feature is: [#93079] -[#81490]: https://github.com/rust-lang/rust/issues/81490 +[#93079]: https://github.com/rust-lang/rust/issues/93079 ------------------------ +"##, + }, + Lint { + label: "slice_partition_dedup", + description: r##"# `slice_partition_dedup` + +The tracking issue for this feature is: [#54279] -The `native_link_modifiers_whole_archive` feature allows you to use the `whole-archive` modifier. +[#54279]: https://github.com/rust-lang/rust/issues/54279 -Only compatible with the `static` linking kind. Using any other kind will result in a compiler error. +------------------------ +"##, + }, + Lint { + label: "slice_pattern", + description: r##"# `slice_pattern` -`+whole-archive` means that the static library is linked as a whole archive without throwing any object files away. +The tracking issue for this feature is: [#56345] -This modifier translates to `--whole-archive` for `ld`-like linkers, to `/WHOLEARCHIVE` for `link.exe`, and to `-force_load` for `ld64`. -The modifier does nothing for linkers that don't support it. +[#56345]: https://github.com/rust-lang/rust/issues/56345 -The default for this modifier is `-whole-archive`. +------------------------ "##, }, Lint { - label: "negative_impls", - description: r##"# `negative_impls` - -The tracking issue for this feature is [#68318]. + label: "slice_ptr_get", + description: r##"# `slice_ptr_get` -[#68318]: https://github.com/rust-lang/rust/issues/68318 +The tracking issue for this feature is: [#74265] ----- +[#74265]: https://github.com/rust-lang/rust/issues/74265 -With the feature gate `negative_impls`, you can write negative impls as well as positive ones: +------------------------ +"##, + }, + Lint { + label: "slice_ptr_len", + description: r##"# `slice_ptr_len` -```rust -#![feature(negative_impls)] -trait DerefMut { } -impl !DerefMut for &T { } -``` +The tracking issue for this feature is: [#71146] -Negative impls indicate a semver guarantee that the given trait will not be implemented for the given types. Negative impls play an additional purpose for auto traits, described below. +[#71146]: https://github.com/rust-lang/rust/issues/71146 -Negative impls have the following characteristics: +------------------------ +"##, + }, + Lint { + label: "slice_range", + description: r##"# `slice_range` -* They do not have any items. -* They must obey the orphan rules as if they were a positive impl. -* They cannot "overlap" with any positive impls. +The tracking issue for this feature is: [#76393] -## Semver interaction +[#76393]: https://github.com/rust-lang/rust/issues/76393 -It is a breaking change to remove a negative impl. Negative impls are a commitment not to implement the given trait for the named types. +------------------------ +"##, + }, + Lint { + label: "slice_split_at_unchecked", + description: r##"# `slice_split_at_unchecked` -## Orphan and overlap rules +The tracking issue for this feature is: [#76014] -Negative impls must obey the same orphan rules as a positive impl. This implies you cannot add a negative impl for types defined in upstream crates and so forth. +[#76014]: https://github.com/rust-lang/rust/issues/76014 -Similarly, negative impls cannot overlap with positive impls, again using the same "overlap" check that we ordinarily use to determine if two impls overlap. (Note that positive impls typically cannot overlap with one another either, except as permitted by specialization.) +------------------------ +"##, + }, + Lint { + label: "slice_swap_unchecked", + description: r##"# `slice_swap_unchecked` -## Interaction with auto traits +The tracking issue for this feature is: [#88539] -Declaring a negative impl `impl !SomeAutoTrait for SomeType` for an -auto-trait serves two purposes: +[#88539]: https://github.com/rust-lang/rust/issues/88539 -* as with any trait, it declares that `SomeType` will never implement `SomeAutoTrait`; -* it disables the automatic `SomeType: SomeAutoTrait` impl that would otherwise have been generated. +------------------------ +"##, + }, + Lint { + label: "slice_take", + description: r##"# `slice_take` -Note that, at present, there is no way to indicate that a given type -does not implement an auto trait *but that it may do so in the -future*. For ordinary types, this is done by simply not declaring any -impl at all, but that is not an option for auto traits. A workaround -is that one could embed a marker type as one of the fields, where the -marker type is `!AutoTrait`. +The tracking issue for this feature is: [#62280] -## Immediate uses +[#62280]: https://github.com/rust-lang/rust/issues/62280 -Negative impls are used to declare that `&T: !DerefMut` and `&mut T: !Clone`, as required to fix the soundness of `Pin` described in [#66544](https://github.com/rust-lang/rust/issues/66544). +------------------------ +"##, + }, + Lint { + label: "solid_ext", + description: r##"# `solid_ext` -This serves two purposes: +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -* For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists. -* It prevents downstream crates from creating such impls. +------------------------ "##, }, Lint { - label: "coverage", - description: r##"# `coverage` + label: "sort_floats", + description: r##"# `sort_floats` -The tracking issue for this feature is: [#84605] +The tracking issue for this feature is: [#93396] -[#84605]: https://github.com/rust-lang/rust/issues/84605 +[#93396]: https://github.com/rust-lang/rust/issues/93396 ---- +------------------------ +"##, + }, + Lint { + label: "sort_internals", + description: r##"# `sort_internals` -The `coverage` attribute can be used to selectively disable coverage -instrumentation in an annotated function. This might be useful to: +This feature is internal to the Rust compiler and is not intended for general use. -- Avoid instrumentation overhead in a performance critical function -- Avoid generating coverage for a function that is not meant to be executed, - but still target 100% coverage for the rest of the program. +------------------------ +"##, + }, + Lint { + label: "spec_option_partial_eq", + description: r##"# `spec_option_partial_eq` -## Example +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -```rust -#![feature(coverage)] +------------------------ +"##, + }, + Lint { + label: "specialization", + description: r##"# `specialization` -// `foo()` will get coverage instrumentation (by default) -fn foo() { - // ... -} +The tracking issue for this feature is: [#31844] -#[coverage(off)] -fn bar() { - // ... -} -``` +[#31844]: https://github.com/rust-lang/rust/issues/31844 + +------------------------ "##, }, Lint { - label: "no_sanitize", - description: r##"# `no_sanitize` + label: "split_array", + description: r##"# `split_array` -The tracking issue for this feature is: [#39699] +The tracking issue for this feature is: [#90091] -[#39699]: https://github.com/rust-lang/rust/issues/39699 +[#90091]: https://github.com/rust-lang/rust/issues/90091 ------------------------ +"##, + }, + Lint { + label: "split_as_slice", + description: r##"# `split_as_slice` -The `no_sanitize` attribute can be used to selectively disable sanitizer -instrumentation in an annotated function. This might be useful to: avoid -instrumentation overhead in a performance critical function, or avoid -instrumenting code that contains constructs unsupported by given sanitizer. +The tracking issue for this feature is: [#96137] -The precise effect of this annotation depends on particular sanitizer in use. -For example, with `no_sanitize(thread)`, the thread sanitizer will no longer -instrument non-atomic store / load operations, but it will instrument atomic -operations to avoid reporting false positives and provide meaning full stack -traces. +[#96137]: https://github.com/rust-lang/rust/issues/96137 -## Examples +------------------------ +"##, + }, + Lint { + label: "sse4a_target_feature", + description: r##"# `sse4a_target_feature` -``` rust -#![feature(no_sanitize)] +The tracking issue for this feature is: [#44839] -#[no_sanitize(address)] -fn foo() { - // ... -} -``` +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ "##, }, Lint { - label: "plugin", - description: r##"# `plugin` + label: "staged_api", + description: r##"# `staged_api` -The tracking issue for this feature is: [#29597] +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -[#29597]: https://github.com/rust-lang/rust/issues/29597 +------------------------ +"##, + }, + Lint { + label: "start", + description: r##"# `start` +The tracking issue for this feature is: [#29633] -This feature is part of "compiler plugins." It will often be used with the -`rustc_private` feature. +[#29633]: https://github.com/rust-lang/rust/issues/29633 ------------------------ -`rustc` can load compiler plugins, which are user-provided libraries that -extend the compiler's behavior with new lint checks, etc. +Allows you to mark a function as the entry point of the executable, which is +necessary in `#![no_std]` environments. -A plugin is a dynamic library crate with a designated *registrar* function that -registers extensions with `rustc`. Other crates can load these extensions using -the crate attribute `#![plugin(...)]`. See the -`rustc_driver::plugin` documentation for more about the -mechanics of defining and loading a plugin. +The function marked `#[start]` is passed the command line parameters in the same +format as the C main function (aside from the integer types being used). +It has to be non-generic and have the following signature: -In the vast majority of cases, a plugin should *only* be used through -`#![plugin]` and not through an `extern crate` item. Linking a plugin would -pull in all of librustc_ast and librustc as dependencies of your crate. This is -generally unwanted unless you are building another plugin. +```rust,ignore (only-for-syntax-highlight) +# let _: +fn(isize, *const *const u8) -> isize +# ; +``` -The usual practice is to put compiler plugins in their own crate, separate from -any `macro_rules!` macros or ordinary Rust code meant to be used by consumers -of a library. +This feature should not be confused with the `start` *lang item* which is +defined by the `std` crate and is written `#[lang = "start"]`. -# Lint plugins +## Usage together with the `std` crate -Plugins can extend [Rust's lint -infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with -additional checks for code style, safety, etc. Now let's write a plugin -[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs) -that warns about any item named `lintme`. +`#[start]` can be used in combination with the `std` crate, in which case the +normal `main` function (which would get called from the `std` crate) won't be +used as an entry point. +The initialization code in `std` will be skipped this way. + +Example: -```rust,ignore (requires-stage-2) -#![feature(box_syntax, rustc_private)] +```rust +#![feature(start)] -extern crate rustc_ast; +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +``` -// Load rustc as a plugin to get macros -extern crate rustc_driver; -#[macro_use] -extern crate rustc_lint; -#[macro_use] -extern crate rustc_session; +Unwinding the stack past the `#[start]` function is currently considered +Undefined Behavior (for any unwinding implementation): -use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc_ast::ast; -declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); +```rust,ignore (UB) +#![feature(start)] -declare_lint_pass!(Pass => [TEST_LINT]); +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + std::panic::catch_unwind(|| { + panic!(); // panic safely gets caught or safely aborts execution + }); -impl EarlyLintPass for Pass { - fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { - if it.ident.name.as_str() == "lintme" { - cx.lint(TEST_LINT, |lint| { - lint.build("item is named 'lintme'").set_span(it.span).emit() - }); - } - } -} + panic!(); // UB! -#[no_mangle] -fn __rustc_plugin_registrar(reg: &mut Registry) { - reg.lint_store.register_lints(&[&TEST_LINT]); - reg.lint_store.register_early_pass(|| box Pass); + 0 } ``` +"##, + }, + Lint { + label: "std_internals", + description: r##"# `std_internals` -Then code like +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -```rust,ignore (requires-plugin) -#![feature(plugin)] -#![plugin(lint_plugin_test)] +------------------------ +"##, + }, + Lint { + label: "stdio_makes_pipe", + description: r##"# `stdio_makes_pipe` -fn lintme() { } -``` +The tracking issue for this feature is: [#98288] -will produce a compiler warning: +[#98288]: https://github.com/rust-lang/rust/issues/98288 -```txt -foo.rs:4:1: 4:16 warning: item is named 'lintme', #[warn(test_lint)] on by default -foo.rs:4 fn lintme() { } - ^~~~~~~~~~~~~~~ -``` +------------------------ +"##, + }, + Lint { + label: "stdsimd", + description: r##"# `stdsimd` -The components of a lint plugin are: +The tracking issue for this feature is: [#48556] -* one or more `declare_lint!` invocations, which define static `Lint` structs; +[#48556]: https://github.com/rust-lang/rust/issues/48556 -* a struct holding any state needed by the lint pass (here, none); +------------------------ +"##, + }, + Lint { + label: "step_trait", + description: r##"# `step_trait` -* a `LintPass` - implementation defining how to check each syntax element. A single - `LintPass` may call `span_lint` for several different `Lint`s, but should - register them all through the `get_lints` method. +The tracking issue for this feature is: [#42168] -Lint passes are syntax traversals, but they run at a late stage of compilation -where type information is available. `rustc`'s [built-in -lints](https://github.com/rust-lang/rust/blob/master/src/librustc_session/lint/builtin.rs) -mostly use the same infrastructure as lint plugins, and provide examples of how -to access type information. +[#42168]: https://github.com/rust-lang/rust/issues/42168 -Lints defined by plugins are controlled by the usual [attributes and compiler -flags](../../reference/attributes/diagnostics.md#lint-check-attributes), e.g. -`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the -first argument to `declare_lint!`, with appropriate case and punctuation -conversion. +------------------------ +"##, + }, + Lint { + label: "stmt_expr_attributes", + description: r##"# `stmt_expr_attributes` -You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`, -including those provided by plugins loaded by `foo.rs`. +The tracking issue for this feature is: [#15701] + +[#15701]: https://github.com/rust-lang/rust/issues/15701 + +------------------------ "##, }, Lint { - label: "print_internals", - description: r##"# `print_internals` + label: "str_internals", + description: r##"# `str_internals` This feature is internal to the Rust compiler and is not intended for general use. @@ -3701,163 +8187,181 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { - label: "profiler_runtime", - description: r##"# `profiler_runtime` + label: "str_split_inclusive_remainder", + description: r##"# `str_split_inclusive_remainder` -The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524). +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 ------------------------ "##, }, Lint { - label: "profiler_runtime_lib", - description: r##"# `profiler_runtime_lib` + label: "str_split_remainder", + description: r##"# `str_split_remainder` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 ------------------------ "##, }, Lint { - label: "raw_dylib", - description: r##"# `raw_dylib` + label: "str_split_whitespace_remainder", + description: r##"# `str_split_whitespace_remainder` -The tracking issue for this feature is: [#58713] +The tracking issue for this feature is: [#77998] -[#58713]: https://github.com/rust-lang/rust/issues/58713 +[#77998]: https://github.com/rust-lang/rust/issues/77998 ------------------------ +"##, + }, + Lint { + label: "strict_provenance", + description: r##"# `strict_provenance` -The `raw_dylib` feature allows you to link against the implementations of functions in an `extern` -block without, on Windows, linking against an import library. +The tracking issue for this feature is: [#95228] -```rust,ignore (partial-example) -#![feature(raw_dylib)] +[#95228]: https://github.com/rust-lang/rust/issues/95228 +----- -#[link(name="library", kind="raw-dylib")] -extern { - fn extern_function(x: i32); -} +The `strict_provenance` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints. +These lint on casts between integers and pointers, that are recommended against or invalid in the strict provenance model. +The same feature gate is also used for the experimental strict provenance API in `std` (actually `core`). + +## Example + +```rust +#![feature(strict_provenance)] +#![warn(fuzzy_provenance_casts)] fn main() { - unsafe { - extern_function(14); - } + let _dangling = 16_usize as *const u8; + //~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8` } ``` +"##, + }, + Lint { + label: "strict_provenance_atomic_ptr", + description: r##"# `strict_provenance_atomic_ptr` -## Limitations +The tracking issue for this feature is: [#99108] -Currently, this feature is only supported on `-windows-msvc` targets. Non-Windows platforms don't have import -libraries, and an incompatibility between LLVM and the BFD linker means that it is not currently supported on -`-windows-gnu` targets. +[#99108]: https://github.com/rust-lang/rust/issues/99108 -On the `i686-pc-windows-msvc` target, this feature supports only the `cdecl`, `stdcall`, `system`, and `fastcall` -calling conventions. +------------------------ "##, }, Lint { - label: "repr128", - description: r##"# `repr128` + label: "string_deref_patterns", + description: r##"# `string_deref_patterns` -The tracking issue for this feature is: [#56071] +The tracking issue for this feature is: [#87121] -[#56071]: https://github.com/rust-lang/rust/issues/56071 +[#87121]: https://github.com/rust-lang/rust/issues/87121 ------------------------ +"##, + }, + Lint { + label: "string_extend_from_within", + description: r##"# `string_extend_from_within` -The `repr128` feature adds support for `#[repr(u128)]` on `enum`s. +The tracking issue for this feature is: [#103806] -```rust -#![feature(repr128)] +[#103806]: https://github.com/rust-lang/rust/issues/103806 -#[repr(u128)] -enum Foo { - Bar(u64), -} -``` +------------------------ "##, }, Lint { - label: "rt", - description: r##"# `rt` + label: "string_remove_matches", + description: r##"# `string_remove_matches` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#72826] + +[#72826]: https://github.com/rust-lang/rust/issues/72826 ------------------------ "##, }, Lint { - label: "rustc_attrs", - description: r##"# `rustc_attrs` + label: "structural_match", + description: r##"# `structural_match` -This feature has no tracking issue, and is therefore internal to -the compiler, not being intended for general use. +The tracking issue for this feature is: [#31434] -Note: `rustc_attrs` enables many rustc-internal attributes and this page -only discuss a few of them. +[#31434]: https://github.com/rust-lang/rust/issues/31434 ------------------------ +"##, + }, + Lint { + label: "sync_unsafe_cell", + description: r##"# `sync_unsafe_cell` -The `rustc_attrs` feature allows debugging rustc type layouts by using -`#[rustc_layout(...)]` to debug layout at compile time (it even works -with `cargo check`) as an alternative to `rustc -Z print-type-sizes` -that is way more verbose. +The tracking issue for this feature is: [#95439] -Options provided by `#[rustc_layout(...)]` are `debug`, `size`, `align`, -`abi`. Note that it only works on sized types without generics. +[#95439]: https://github.com/rust-lang/rust/issues/95439 -## Examples +------------------------ +"##, + }, + Lint { + label: "target_feature_11", + description: r##"# `target_feature_11` -```rust,compile_fail -#![feature(rustc_attrs)] +The tracking issue for this feature is: [#69098] -#[rustc_layout(abi, size)] -pub enum X { - Y(u8, u8, u8), - Z(isize), -} -``` +[#69098]: https://github.com/rust-lang/rust/issues/69098 -When that is compiled, the compiler will error with something like +------------------------ +"##, + }, + Lint { + label: "tbm_target_feature", + description: r##"# `tbm_target_feature` -```text -error: abi: Aggregate { sized: true } - --> src/lib.rs:4:1 - | -4 | / pub enum T { -5 | | Y(u8, u8, u8), -6 | | Z(isize), -7 | | } - | |_^ +The tracking issue for this feature is: [#44839] -error: size: Size { raw: 16 } - --> src/lib.rs:4:1 - | -4 | / pub enum T { -5 | | Y(u8, u8, u8), -6 | | Z(isize), -7 | | } - | |_^ +[#44839]: https://github.com/rust-lang/rust/issues/44839 -error: aborting due to 2 previous errors -``` +------------------------ "##, }, Lint { - label: "sort_internals", - description: r##"# `sort_internals` + label: "tcp_linger", + description: r##"# `tcp_linger` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#88494] + +[#88494]: https://github.com/rust-lang/rust/issues/88494 ------------------------ "##, }, Lint { - label: "str_internals", - description: r##"# `str_internals` + label: "tcp_quickack", + description: r##"# `tcp_quickack` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#96256] + +[#96256]: https://github.com/rust-lang/rust/issues/96256 + +------------------------ +"##, + }, + Lint { + label: "tcplistener_into_incoming", + description: r##"# `tcplistener_into_incoming` + +The tracking issue for this feature is: [#88339] + +[#88339]: https://github.com/rust-lang/rust/issues/88339 ------------------------ "##, @@ -4022,6 +8526,57 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured However, the optimizer can still modify a testcase in an undesirable manner even when using either of the above. +"##, + }, + Lint { + label: "test_2018_feature", + description: r##"# `test_2018_feature` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "test_unstable_lint", + description: r##"# `test_unstable_lint` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "thin_box", + description: r##"# `thin_box` + +The tracking issue for this feature is: [#92791] + +[#92791]: https://github.com/rust-lang/rust/issues/92791 + +------------------------ +"##, + }, + Lint { + label: "thread_id_value", + description: r##"# `thread_id_value` + +The tracking issue for this feature is: [#67939] + +[#67939]: https://github.com/rust-lang/rust/issues/67939 + +------------------------ +"##, + }, + Lint { + label: "thread_local", + description: r##"# `thread_local` + +The tracking issue for this feature is: [#29594] + +[#29594]: https://github.com/rust-lang/rust/issues/29594 + +------------------------ "##, }, Lint { @@ -4030,6 +8585,28 @@ even when using either of the above. This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "thread_sleep_until", + description: r##"# `thread_sleep_until` + +The tracking issue for this feature is: [#113752] + +[#113752]: https://github.com/rust-lang/rust/issues/113752 + +------------------------ +"##, + }, + Lint { + label: "thread_spawn_unchecked", + description: r##"# `thread_spawn_unchecked` + +The tracking issue for this feature is: [#55132] + +[#55132]: https://github.com/rust-lang/rust/issues/55132 + ------------------------ "##, }, @@ -4072,8 +8649,19 @@ note: trace_macro = note: to `$crate :: io :: _print ( format_args ! ( concat ! ( "Hello, Rust!" , "\n" ) ) )` - Finished dev [unoptimized + debuginfo] target(s) in 0.60 secs -``` + Finished dev [unoptimized + debuginfo] target(s) in 0.60 secs +``` +"##, + }, + Lint { + label: "track_path", + description: r##"# `track_path` + +The tracking issue for this feature is: [#99515] + +[#99515]: https://github.com/rust-lang/rust/issues/99515 + +------------------------ "##, }, Lint { @@ -4143,6 +8731,28 @@ impl Bar for T {} let bar: &dyn Bar = &123; let foo: &dyn Foo = bar; ``` +"##, + }, + Lint { + label: "transmutability", + description: r##"# `transmutability` + +The tracking issue for this feature is: [#99571] + +[#99571]: https://github.com/rust-lang/rust/issues/99571 + +------------------------ +"##, + }, + Lint { + label: "transmute_generic_consts", + description: r##"# `transmute_generic_consts` + +The tracking issue for this feature is: [#109929] + +[#109929]: https://github.com/rust-lang/rust/issues/109929 + +------------------------ "##, }, Lint { @@ -4230,6 +8840,59 @@ example, it is unspecified whether `size_of::()` is equal to it is transparent). The Rust compiler is free to perform this optimization if possible, but is not required to, and different compiler versions may differ in their application of these optimizations. +"##, + }, + Lint { + label: "trivial_bounds", + description: r##"# `trivial_bounds` + +The tracking issue for this feature is: [#48214] + +[#48214]: https://github.com/rust-lang/rust/issues/48214 + +------------------------ +"##, + }, + Lint { + label: "trusted_len", + description: r##"# `trusted_len` + +The tracking issue for this feature is: [#37572] + +[#37572]: https://github.com/rust-lang/rust/issues/37572 + +------------------------ +"##, + }, + Lint { + label: "trusted_len_next_unchecked", + description: r##"# `trusted_len_next_unchecked` + +The tracking issue for this feature is: [#37572] + +[#37572]: https://github.com/rust-lang/rust/issues/37572 + +------------------------ +"##, + }, + Lint { + label: "trusted_random_access", + description: r##"# `trusted_random_access` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "trusted_step", + description: r##"# `trusted_step` + +The tracking issue for this feature is: [#85731] + +[#85731]: https://github.com/rust-lang/rust/issues/85731 + +------------------------ "##, }, Lint { @@ -4267,69 +8930,382 @@ assert!(result.is_err()); "##, }, Lint { - label: "type_changing_struct_update", - description: r##"# `type_changing_struct_update` + label: "try_find", + description: r##"# `try_find` + +The tracking issue for this feature is: [#63178] + +[#63178]: https://github.com/rust-lang/rust/issues/63178 + +------------------------ +"##, + }, + Lint { + label: "try_reserve_kind", + description: r##"# `try_reserve_kind` + +The tracking issue for this feature is: [#48043] + +[#48043]: https://github.com/rust-lang/rust/issues/48043 + +------------------------ +"##, + }, + Lint { + label: "try_trait_v2", + description: r##"# `try_trait_v2` + +The tracking issue for this feature is: [#84277] + +[#84277]: https://github.com/rust-lang/rust/issues/84277 + +------------------------ +"##, + }, + Lint { + label: "try_trait_v2_residual", + description: r##"# `try_trait_v2_residual` + +The tracking issue for this feature is: [#91285] + +[#91285]: https://github.com/rust-lang/rust/issues/91285 + +------------------------ +"##, + }, + Lint { + label: "try_trait_v2_yeet", + description: r##"# `try_trait_v2_yeet` + +The tracking issue for this feature is: [#96374] + +[#96374]: https://github.com/rust-lang/rust/issues/96374 + +------------------------ +"##, + }, + Lint { + label: "tuple_trait", + description: r##"# `tuple_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "type_alias_impl_trait", + description: r##"# `type_alias_impl_trait` + +The tracking issue for this feature is: [#63063] + +[#63063]: https://github.com/rust-lang/rust/issues/63063 + +------------------------ +"##, + }, + Lint { + label: "type_ascription", + description: r##"# `type_ascription` + +The tracking issue for this feature is: [#23416] + +[#23416]: https://github.com/rust-lang/rust/issues/23416 + +------------------------ +"##, + }, + Lint { + label: "type_changing_struct_update", + description: r##"# `type_changing_struct_update` + +The tracking issue for this feature is: [#86555] + +[#86555]: https://github.com/rust-lang/rust/issues/86555 + +------------------------ + +This implements [RFC2528]. When turned on, you can create instances of the same struct +that have different generic type or lifetime parameters. + +[RFC2528]: https://github.com/rust-lang/rfcs/blob/master/text/2528-type-changing-struct-update-syntax.md + +```rust +#![allow(unused_variables, dead_code)] +#![feature(type_changing_struct_update)] + +fn main () { + struct Foo { + field1: T, + field2: U, + } + + let base: Foo = Foo { + field1: String::from("hello"), + field2: 1234, + }; + let updated: Foo = Foo { + field1: 3.14, + ..base + }; +} +``` +"##, + }, + Lint { + label: "type_name_of_val", + description: r##"# `type_name_of_val` + +The tracking issue for this feature is: [#66359] + +[#66359]: https://github.com/rust-lang/rust/issues/66359 + +------------------------ +"##, + }, + Lint { + label: "type_privacy_lints", + description: r##"# `type_privacy_lints` + +The tracking issue for this feature is: [#48054] + +[#48054]: https://github.com/rust-lang/rust/issues/48054 + +------------------------ +"##, + }, + Lint { + label: "uefi_std", + description: r##"# `uefi_std` + +The tracking issue for this feature is: [#100499] + +[#100499]: https://github.com/rust-lang/rust/issues/100499 + +------------------------ +"##, + }, + Lint { + label: "unboxed_closures", + description: r##"# `unboxed_closures` + +The tracking issue for this feature is [#29625] + +See Also: [`fn_traits`](../library-features/fn-traits.md) + +[#29625]: https://github.com/rust-lang/rust/issues/29625 + +---- + +The `unboxed_closures` feature allows you to write functions using the `"rust-call"` ABI, +required for implementing the [`Fn*`] family of traits. `"rust-call"` functions must have +exactly one (non self) argument, a tuple representing the argument list. + +[`Fn*`]: ../../std/ops/trait.Fn.html + +```rust +#![feature(unboxed_closures)] + +extern "rust-call" fn add_args(args: (u32, u32)) -> u32 { + args.0 + args.1 +} + +fn main() {} +``` +"##, + }, + Lint { + label: "unchecked_math", + description: r##"# `unchecked_math` + +The tracking issue for this feature is: [#85122] + +[#85122]: https://github.com/rust-lang/rust/issues/85122 + +------------------------ +"##, + }, + Lint { + label: "unicode_internals", + description: r##"# `unicode_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "unique_rc_arc", + description: r##"# `unique_rc_arc` + +The tracking issue for this feature is: [#112566] + +[#112566]: https://github.com/rust-lang/rust/issues/112566 + +------------------------ +"##, + }, + Lint { + label: "unix_file_vectored_at", + description: r##"# `unix_file_vectored_at` + +The tracking issue for this feature is: [#89517] + +[#89517]: https://github.com/rust-lang/rust/issues/89517 + +------------------------ +"##, + }, + Lint { + label: "unix_set_mark", + description: r##"# `unix_set_mark` + +The tracking issue for this feature is: [#96467] + +[#96467]: https://github.com/rust-lang/rust/issues/96467 + +------------------------ +"##, + }, + Lint { + label: "unix_sigpipe", + description: r##"# `unix_sigpipe` + +The tracking issue for this feature is: [#97889] + +[#97889]: https://github.com/rust-lang/rust/issues/97889 + +--- + +The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants: +* `#[unix_sigpipe = "inherit"]` +* `#[unix_sigpipe = "sig_dfl"]` +* `#[unix_sigpipe = "sig_ign"]` + +## `#[unix_sigpipe = "inherit"]` + +Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`. + +## `#[unix_sigpipe = "sig_dfl"]` + +Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output. + +### Example + +```rust,no_run +#![feature(unix_sigpipe)] +#[unix_sigpipe = "sig_dfl"] +fn main() { loop { println!("hello world"); } } +``` + +```bash +% ./main | head -n 1 +hello world +``` + +## `#[unix_sigpipe = "sig_ign"]` + +Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers. + +This is what libstd has done by default since 2014. (However, see the note on child processes below.) + +### Example + +```rust,no_run +#![feature(unix_sigpipe)] +#[unix_sigpipe = "sig_ign"] +fn main() { loop { println!("hello world"); } } +``` + +```bash +% ./main | head -n 1 +hello world +thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +### Note on child processes + +When spawning child processes, the legacy Rust behavior if `#[unix_sigpipe]` is not specified is to +reset `SIGPIPE` to `SIG_DFL`. + +If `#[unix_sigpipe = "..."]` is specified, no matter what its value is, the signal disposition of +`SIGPIPE` is no longer reset. This means that the child inherits the parent's `SIGPIPE` behavior. +"##, + }, + Lint { + label: "unix_socket_ancillary_data", + description: r##"# `unix_socket_ancillary_data` -The tracking issue for this feature is: [#86555] +The tracking issue for this feature is: [#76915] -[#86555]: https://github.com/rust-lang/rust/issues/86555 +[#76915]: https://github.com/rust-lang/rust/issues/76915 ------------------------ +"##, + }, + Lint { + label: "unix_socket_peek", + description: r##"# `unix_socket_peek` -This implements [RFC2528]. When turned on, you can create instances of the same struct -that have different generic type or lifetime parameters. +The tracking issue for this feature is: [#76923] -[RFC2528]: https://github.com/rust-lang/rfcs/blob/master/text/2528-type-changing-struct-update-syntax.md +[#76923]: https://github.com/rust-lang/rust/issues/76923 -```rust -#![allow(unused_variables, dead_code)] -#![feature(type_changing_struct_update)] +------------------------ +"##, + }, + Lint { + label: "unnamed_fields", + description: r##"# `unnamed_fields` -fn main () { - struct Foo { - field1: T, - field2: U, - } +The tracking issue for this feature is: [#49804] - let base: Foo = Foo { - field1: String::from("hello"), - field2: 1234, - }; - let updated: Foo = Foo { - field1: 3.14, - ..base - }; -} -``` +[#49804]: https://github.com/rust-lang/rust/issues/49804 + +------------------------ "##, }, Lint { - label: "unboxed_closures", - description: r##"# `unboxed_closures` + label: "unsafe_cell_from_mut", + description: r##"# `unsafe_cell_from_mut` -The tracking issue for this feature is [#29625] +The tracking issue for this feature is: [#111645] -See Also: [`fn_traits`](../library-features/fn-traits.md) +[#111645]: https://github.com/rust-lang/rust/issues/111645 -[#29625]: https://github.com/rust-lang/rust/issues/29625 +------------------------ +"##, + }, + Lint { + label: "unsafe_pin_internals", + description: r##"# `unsafe_pin_internals` ----- +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -The `unboxed_closures` feature allows you to write functions using the `"rust-call"` ABI, -required for implementing the [`Fn*`] family of traits. `"rust-call"` functions must have -exactly one (non self) argument, a tuple representing the argument list. +------------------------ +"##, + }, + Lint { + label: "unsize", + description: r##"# `unsize` -[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html +The tracking issue for this feature is: [#18598] -```rust -#![feature(unboxed_closures)] +[#18598]: https://github.com/rust-lang/rust/issues/18598 -extern "rust-call" fn add_args(args: (u32, u32)) -> u32 { - args.0 + args.1 -} +------------------------ +"##, + }, + Lint { + label: "unsized_fn_params", + description: r##"# `unsized_fn_params` -fn main() {} -``` +The tracking issue for this feature is: [#48055] + +[#48055]: https://github.com/rust-lang/rust/issues/48055 + +------------------------ "##, }, Lint { @@ -4529,73 +9505,392 @@ impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized {} This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this: -```rust -#![feature(unsized_tuple_coercion)] +```rust +#![feature(unsized_tuple_coercion)] + +fn main() { + let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]); + let y : &([i32; 3], [i32]) = &x; + assert_eq!(y.1[0], 4); +} +``` + +[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md +"##, + }, + Lint { + label: "unwrap_infallible", + description: r##"# `unwrap_infallible` + +The tracking issue for this feature is: [#61695] + +[#61695]: https://github.com/rust-lang/rust/issues/61695 + +------------------------ +"##, + }, + Lint { + label: "update_panic_count", + description: r##"# `update_panic_count` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "used_with_arg", + description: r##"# `used_with_arg` + +The tracking issue for this feature is: [#93798] + +[#93798]: https://github.com/rust-lang/rust/issues/93798 + +------------------------ +"##, + }, + Lint { + label: "utf16_extra", + description: r##"# `utf16_extra` + +The tracking issue for this feature is: [#94919] + +[#94919]: https://github.com/rust-lang/rust/issues/94919 + +------------------------ +"##, + }, + Lint { + label: "utf16_extra_const", + description: r##"# `utf16_extra_const` + +The tracking issue for this feature is: [#94919] + +[#94919]: https://github.com/rust-lang/rust/issues/94919 + +------------------------ +"##, + }, + Lint { + label: "utf8_chunks", + description: r##"# `utf8_chunks` + +The tracking issue for this feature is: [#99543] + +[#99543]: https://github.com/rust-lang/rust/issues/99543 + +------------------------ +"##, + }, + Lint { + label: "variant_count", + description: r##"# `variant_count` + +The tracking issue for this feature is: [#73662] + +[#73662]: https://github.com/rust-lang/rust/issues/73662 + +------------------------ +"##, + }, + Lint { + label: "vec_into_raw_parts", + description: r##"# `vec_into_raw_parts` + +The tracking issue for this feature is: [#65816] + +[#65816]: https://github.com/rust-lang/rust/issues/65816 + +------------------------ +"##, + }, + Lint { + label: "vec_push_within_capacity", + description: r##"# `vec_push_within_capacity` + +The tracking issue for this feature is: [#100486] + +[#100486]: https://github.com/rust-lang/rust/issues/100486 + +------------------------ +"##, + }, + Lint { + label: "vec_split_at_spare", + description: r##"# `vec_split_at_spare` + +The tracking issue for this feature is: [#81944] + +[#81944]: https://github.com/rust-lang/rust/issues/81944 + +------------------------ +"##, + }, + Lint { + label: "waker_getters", + description: r##"# `waker_getters` + +The tracking issue for this feature is: [#87021] + +[#87021]: https://github.com/rust-lang/rust/issues/87021 + +------------------------ +"##, + }, + Lint { + label: "wasi_ext", + description: r##"# `wasi_ext` + +The tracking issue for this feature is: [#71213] + +[#71213]: https://github.com/rust-lang/rust/issues/71213 + +------------------------ +"##, + }, + Lint { + label: "wasm_abi", + description: r##"# `wasm_abi` + +The tracking issue for this feature is: [#83788] + +[#83788]: https://github.com/rust-lang/rust/issues/83788 + +------------------------ +"##, + }, + Lint { + label: "wasm_target_feature", + description: r##"# `wasm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "windows_by_handle", + description: r##"# `windows_by_handle` + +The tracking issue for this feature is: [#63010] + +[#63010]: https://github.com/rust-lang/rust/issues/63010 + +------------------------ +"##, + }, + Lint { + label: "windows_c", + description: r##"# `windows_c` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "windows_handle", + description: r##"# `windows_handle` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "windows_net", + description: r##"# `windows_net` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "windows_process_exit_code_from", + description: r##"# `windows_process_exit_code_from` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_async_pipes", + description: r##"# `windows_process_extensions_async_pipes` + +The tracking issue for this feature is: [#98289] + +[#98289]: https://github.com/rust-lang/rust/issues/98289 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_force_quotes", + description: r##"# `windows_process_extensions_force_quotes` + +The tracking issue for this feature is: [#82227] + +[#82227]: https://github.com/rust-lang/rust/issues/82227 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_main_thread_handle", + description: r##"# `windows_process_extensions_main_thread_handle` + +The tracking issue for this feature is: [#96723] + +[#96723]: https://github.com/rust-lang/rust/issues/96723 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_raw_attribute", + description: r##"# `windows_process_extensions_raw_attribute` + +The tracking issue for this feature is: [#114854] + +[#114854]: https://github.com/rust-lang/rust/issues/114854 + +------------------------ +"##, + }, + Lint { + label: "windows_stdio", + description: r##"# `windows_stdio` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ +"##, + }, + Lint { + label: "with_negative_coherence", + description: r##"# `with_negative_coherence` -fn main() { - let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]); - let y : &([i32; 3], [i32]) = &x; - assert_eq!(y.1[0], 4); -} -``` +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md +------------------------ "##, }, Lint { - label: "update_panic_count", - description: r##"# `update_panic_count` + label: "wrapping_int_impl", + description: r##"# `wrapping_int_impl` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#32463] + +[#32463]: https://github.com/rust-lang/rust/issues/32463 ------------------------ "##, }, Lint { - label: "windows_c", - description: r##"# `windows_c` + label: "wrapping_next_power_of_two", + description: r##"# `wrapping_next_power_of_two` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#32463] + +[#32463]: https://github.com/rust-lang/rust/issues/32463 ------------------------ "##, }, Lint { - label: "windows_handle", - description: r##"# `windows_handle` + label: "write_all_vectored", + description: r##"# `write_all_vectored` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#70436] + +[#70436]: https://github.com/rust-lang/rust/issues/70436 ------------------------ "##, }, Lint { - label: "windows_net", - description: r##"# `windows_net` + label: "yeet_desugar_details", + description: r##"# `yeet_desugar_details` -This feature is internal to the Rust compiler and is not intended for general use. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ "##, }, Lint { - label: "windows_stdio", - description: r##"# `windows_stdio` + label: "yeet_expr", + description: r##"# `yeet_expr` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#96373] + +[#96373]: https://github.com/rust-lang/rust/issues/96373 ------------------------ + +The `yeet_expr` feature adds support for `do yeet` expressions, +which can be used to early-exit from a function or `try` block. + +These are highly experimental, thus the placeholder syntax. + +```rust,edition2021 +#![feature(yeet_expr)] + +fn foo() -> Result { + do yeet 4; +} +assert_eq!(foo(), Err(4)); + +fn bar() -> Option { + do yeet; +} +assert_eq!(bar(), None); +``` "##, }, ]; pub const CLIPPY_LINTS: &[Lint] = &[ + Lint { + label: "clippy::absolute_paths", + description: r##"Checks for usage of items through absolute paths, like `std::env::current_dir`."##, + }, Lint { label: "clippy::absurd_extreme_comparisons", description: r##"Checks for comparisons where one side of the relation is either the minimum or maximum value for its type and warns if it involves a case that is always true or always false. Only integer and boolean types are checked."##, + }, + Lint { + label: "clippy::alloc_instead_of_core", + description: r##"Finds items imported through `alloc` when available through `core`."##, + }, + Lint { + label: "clippy::allow_attributes", + description: r##"Checks for usage of the `#[allow]` attribute and suggests replacing it with +the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) + +The expect attribute is still unstable and requires the `lint_reasons` +on nightly. It can be enabled by adding `#![feature(lint_reasons)]` to +the crate root. + +This lint only warns outer attributes (`#[allow]`), as inner attributes +(`#![allow]`) are usually used to enable or disable lints on a global scale."##, + }, + Lint { + label: "clippy::allow_attributes_without_reason", + description: r##"Checks for attributes that allow lints without a reason. + +(This requires the `lint_reasons` feature)"##, + }, + Lint { + label: "clippy::almost_complete_range", + description: r##"Checks for ranges which almost include the entire range of letters from 'a' to 'z' +or digits from '0' to '9', but don't because they're a half open range."##, }, Lint { label: "clippy::almost_swapped", @@ -4609,6 +9904,22 @@ constants which are defined in or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant."##, + }, + Lint { + label: "clippy::arc_with_non_send_sync", + description: r##". +This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`."##, + }, + Lint { + label: "clippy::arithmetic_side_effects", + description: r##"Checks any kind of arithmetic operation of any type. + +Operators like `+`, `-`, `*` or `<<` are usually capable of overflowing according to the [Rust +Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow), +or can panic (`/`, `%`). + +Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant +environments, allowed types and non-constant operations that won't overflow are ignored."##, }, Lint { label: "clippy::as_conversions", @@ -4617,15 +9928,27 @@ respectively, suggesting to use the predefined constant."##, Note that this lint is specialized in linting *every single* use of `as` regardless of whether good alternatives exist or not. If you want more precise lints for `as`, please consider using these separate lints: -`unnecessary_cast`, `cast_lossless/possible_truncation/possible_wrap/precision_loss/sign_loss`, +`unnecessary_cast`, `cast_lossless/cast_possible_truncation/cast_possible_wrap/cast_precision_loss/cast_sign_loss`, `fn_to_numeric_cast(_with_truncation)`, `char_lit_as_u8`, `ref_to_mut` and `ptr_as_ptr`. There is a good explanation the reason why this lint should work in this way and how it is useful [in this issue](https://github.com/rust-lang/rust-clippy/issues/5122)."##, }, + Lint { + label: "clippy::as_ptr_cast_mut", + description: r##"Checks for the result of a `&self`-taking `as_ptr` being cast to a mutable pointer"##, + }, + Lint { + label: "clippy::as_underscore", + description: r##"Checks for the usage of `as _` conversion using inferred type."##, + }, Lint { label: "clippy::assertions_on_constants", description: r##"Checks for `assert!(true)` and `assert!(false)` calls."##, }, + Lint { + label: "clippy::assertions_on_result_states", + description: r##"Checks for `assert!(r.is_ok())` or `assert!(r.is_err())` calls."##, + }, Lint { label: "clippy::assign_op_pattern", description: r##"Checks for `a = a op b` or `a = b commutative_op a` @@ -4639,16 +9962,19 @@ patterns."##, label: "clippy::async_yields_async", description: r##"Checks for async blocks that yield values of types that can themselves be awaited."##, + }, + Lint { + label: "clippy::await_holding_invalid_type", + description: r##"Allows users to configure types which should not be held across `await` +suspension points."##, }, Lint { label: "clippy::await_holding_lock", - description: r##"Checks for calls to await while holding a -non-async-aware MutexGuard."##, + description: r##"Checks for calls to await while holding a non-async-aware MutexGuard."##, }, Lint { label: "clippy::await_holding_refcell_ref", - description: r##"Checks for calls to await while holding a -`RefCell` `Ref` or `RefMut`."##, + description: r##"Checks for calls to await while holding a `RefCell` `Ref` or `RefMut`."##, }, Lint { label: "clippy::bad_bit_mask", @@ -4659,24 +9985,23 @@ The formula for detecting if an expression of the type `_ m {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: -|Comparison |Bit Op|Example |is always|Formula | -|------------|------|------------|---------|----------------------| -|`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -|`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -|`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -|`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -|`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -|`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` |"##, +|Comparison |Bit Op|Example |is always|Formula | +|------------|------|-------------|---------|----------------------| +|`==` or `!=`| `&` |`x & 2 == 3` |`false` |`c & m != c` | +|`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +|`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +|`==` or `!=`| `\\|` |`x \\| 1 == 0`|`false` |`c \\| m != c` | +|`<` or `>=`| `\\|` |`x \\| 1 < 1` |`false` |`m >= c` | +|`<=` or `>` | `\\|` |`x \\| 1 > 0` |`true` |`m > c` |"##, + }, + Lint { + label: "clippy::big_endian_bytes", + description: r##"Checks for the usage of the `to_be_bytes` method and/or the function `from_be_bytes`."##, }, Lint { label: "clippy::bind_instead_of_map", description: r##"Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or `_.or_else(|x| Err(y))`."##, - }, - Lint { - label: "clippy::blacklisted_name", - description: r##"Checks for usage of blacklisted names for variables, such -as `foo`."##, }, Lint { label: "clippy::blanket_clippy_restriction_lints", @@ -4697,6 +10022,18 @@ expression, statements or conditions that use closures with blocks."##, `x != true` and order comparisons such as `x < true` (or vice versa) and suggest using the variable directly."##, }, + Lint { + label: "clippy::bool_to_int_with_if", + description: r##"Instead of using an if statement to convert a bool to an int, +this lint suggests using a `from()` function or an `as` coercion."##, + }, + Lint { + label: "clippy::borrow_as_ptr", + description: r##"Checks for the usage of `&expr as *const T` or +`&mut expr as *mut T`, and suggest using `ptr::addr_of` or +`ptr::addr_of_mut` instead."##, + }, + Lint { label: "clippy::borrow_deref_ref", description: r##"Checks for `&*(&T)`."## }, Lint { label: "clippy::borrow_interior_mutable_const", description: r##"Checks if `const` items which is interior mutable (e.g., @@ -4704,13 +10041,18 @@ contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly."##, }, Lint { label: "clippy::borrowed_box", - description: r##"Checks for use of `&Box` anywhere in the code. + description: r##"Checks for usage of `&Box` anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, }, Lint { label: "clippy::box_collection", - description: r##"Checks for use of `Box` where T is a collection such as Vec anywhere in the code. + description: r##"Checks for usage of `Box` where T is a collection such as Vec anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, + }, + Lint { + label: "clippy::box_default", + description: r##"checks for `Box::new(T::default())`, which is better written as +`Box::::default()`."##, }, Lint { label: "clippy::boxed_local", @@ -4726,6 +10068,11 @@ moved out of the blocks."##, label: "clippy::builtin_type_shadow", description: r##"Warns if a generic shadows a built-in type."##, }, + Lint { + label: "clippy::bytes_count_to_len", + description: r##"It checks for `str::bytes().count()` and suggests replacing it with +`str::len()`."##, + }, Lint { label: "clippy::bytes_nth", description: r##"Checks for the use of `.bytes().nth()`."##, @@ -4739,24 +10086,43 @@ moved out of the blocks."##, label: "clippy::case_sensitive_file_extension_comparisons", description: r##"Checks for calls to `ends_with` with possible file extensions and suggests to use a case-insensitive approach instead."##, + }, + Lint { + label: "clippy::cast_abs_to_unsigned", + description: r##"Checks for usage of the `abs()` method that cast the result to unsigned."##, + }, + Lint { + label: "clippy::cast_enum_constructor", + description: r##"Checks for casts from an enum tuple constructor to an integer."##, + }, + Lint { + label: "clippy::cast_enum_truncation", + description: r##"Checks for casts from an enum type to an integral type which will definitely truncate the +value."##, }, Lint { label: "clippy::cast_lossless", description: r##"Checks for casts between numerical types that may be replaced by safe conversion functions."##, }, + Lint { + label: "clippy::cast_nan_to_int", + description: r##"Checks for a known NaN float being cast to an integer"##, + }, Lint { label: "clippy::cast_possible_truncation", description: r##"Checks for casts between numerical types that may truncate large values. This is expected behavior, so the cast is `Allow` by -default."##, +default. It suggests user either explicitly ignore the lint, +or use `try_from()` and handle the truncation, default, or panic explicitly."##, }, Lint { label: "clippy::cast_possible_wrap", description: r##"Checks for casts from an unsigned type to a signed type of -the same size. Performing such a cast is a 'no-op' for the compiler, -i.e., nothing is changed at the bit level, and the binary representation of -the value is reinterpreted. This can cause wrapping if the value is too big +the same size, or possibly smaller due to target dependent integers. +Performing such a cast is a 'no-op' for the compiler, i.e., nothing is +changed at the bit level, and the binary representation of the value is +reinterpreted. This can cause wrapping if the value is too big for the target signed type. However, the cast works as defined, so this lint is `Allow` by default."##, }, @@ -4775,10 +10141,6 @@ or any 64-bit integer to `f64`."##, description: r##"Checks for casts, using `as` or `pointer::cast`, from a less-strictly-aligned pointer to a more-strictly-aligned pointer"##, }, - Lint { - label: "clippy::cast_ref_to_mut", - description: r##"Checks for casts of `&T` to `&mut T` anywhere in the code."##, - }, Lint { label: "clippy::cast_sign_loss", description: r##"Checks for casts from a signed to an unsigned numerical @@ -4786,6 +10148,14 @@ type. In this case, negative values wrap around to large positive values, which can be quite surprising in practice. However, as the cast works as defined, this lint is `Allow` by default."##, }, + Lint { + label: "clippy::cast_slice_different_sizes", + description: r##"Checks for `as` casts between raw pointers to slices with differently sized elements."##, + }, + Lint { + label: "clippy::cast_slice_from_raw_parts", + description: r##"Checks for a raw slice being cast to a slice pointer"##, + }, Lint { label: "clippy::char_lit_as_u8", description: r##"Checks for expressions where a character literal is cast @@ -4806,8 +10176,8 @@ if it starts with a given char."##, description: r##"Checks for explicit bounds checking when casting."##, }, Lint { - label: "clippy::clone_double_ref", - description: r##"Checks for usage of `.clone()` on an `&&T`."##, + label: "clippy::clear_with_drain", + description: r##"Checks for usage of `.drain(..)` for the sole purpose of clearing a container."##, }, Lint { label: "clippy::clone_on_copy", @@ -4821,10 +10191,9 @@ function syntax instead (e.g., `Rc::clone(foo)`)."##, }, Lint { label: "clippy::cloned_instead_of_copied", - description: r##"Checks for usages of `cloned()` on an `Iterator` or `Option` where + description: r##"Checks for usage of `cloned()` on an `Iterator` or `Option` where `copied()` could be used instead."##, }, - Lint { label: "clippy::cmp_nan", description: r##"Checks for comparisons to NaN."## }, Lint { label: "clippy::cmp_null", description: r##"This lint checks for equality comparisons with `ptr::null`"##, @@ -4856,6 +10225,15 @@ without adding any branches. Note that this lint is not intended to find _all_ cases where nested match patterns can be merged, but only cases where merging would most likely make the code more readable."##, }, + Lint { + label: "clippy::collapsible_str_replace", + description: r##"Checks for consecutive calls to `str::replace` (2 or more) +that can be collapsed into a single call."##, + }, + Lint { + label: "clippy::collection_is_never_read", + description: r##"Checks for collections that are never queried."##, + }, Lint { label: "clippy::comparison_chain", description: r##"Checks comparison chains written with `if` that can be @@ -4871,6 +10249,10 @@ and suggests using `.is_empty()` where applicable."##, description: r##"Checks for types that implement `Copy` as well as `Iterator`."##, }, + Lint { + label: "clippy::crate_in_macro_def", + description: r##"Checks for usage of `crate` as opposed to `$crate` in a macro definition."##, + }, Lint { label: "clippy::create_dir", description: r##"Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead."##, @@ -4879,7 +10261,10 @@ and suggests using `.is_empty()` where applicable."##, label: "clippy::crosspointer_transmute", description: r##"Checks for transmutes between a type `T` and `*T`."##, }, - Lint { label: "clippy::dbg_macro", description: r##"Checks for usage of dbg!() macro."## }, + Lint { + label: "clippy::dbg_macro", + description: r##"Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro."##, + }, Lint { label: "clippy::debug_assert_with_mut_call", description: r##"Checks for function/method calls with a mutable @@ -4893,6 +10278,15 @@ parameter in `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!` macros." label: "clippy::declare_interior_mutable_const", description: r##"Checks for declaration of `const` items which is interior mutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.)."##, + }, + Lint { + label: "clippy::default_constructed_unit_structs", + description: r##"Checks for construction on unit struct using `default`."##, + }, + Lint { + label: "clippy::default_instead_of_iter_empty", + description: r##"It checks for `std::iter::Empty::default()` and suggests replacing it with +`std::iter::empty()`."##, }, Lint { label: "clippy::default_numeric_fallback", @@ -4909,6 +10303,10 @@ See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-in label: "clippy::default_trait_access", description: r##"Checks for literal calls to `Default::default()`."##, }, + Lint { + label: "clippy::default_union_representation", + description: r##"Displays a warning when a union is declared with the default representation (without a `#[repr(C)]` attribute)."##, + }, Lint { label: "clippy::deprecated_cfg_attr", description: r##"Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it @@ -4923,23 +10321,47 @@ field that is not a valid semantic version."##, label: "clippy::deref_addrof", description: r##"Checks for usage of `*&` and `*&mut` in expressions."##, }, + Lint { + label: "clippy::deref_by_slicing", + description: r##"Checks for slicing expressions which are equivalent to dereferencing the +value."##, + }, Lint { label: "clippy::derivable_impls", description: r##"Detects manual `std::default::Default` implementations that are identical to a derived implementation."##, }, Lint { - label: "clippy::derive_hash_xor_eq", - description: r##"Checks for deriving `Hash` but implementing `PartialEq` -explicitly or vice versa."##, + label: "clippy::derive_ord_xor_partial_ord", + description: r##"Lints against manual `PartialOrd` and `Ord` implementations for types with a derived `Ord` +or `PartialOrd` implementation."##, }, Lint { - label: "clippy::derive_ord_xor_partial_ord", - description: r##"Checks for deriving `Ord` but implementing `PartialOrd` -explicitly or vice versa."##, + label: "clippy::derive_partial_eq_without_eq", + description: r##"Checks for types that derive `PartialEq` and could implement `Eq`."##, + }, + Lint { + label: "clippy::derived_hash_with_manual_eq", + description: r##"Lints against manual `PartialEq` implementations for types with a derived `Hash` +implementation."##, + }, + Lint { + label: "clippy::disallowed_macros", + description: r##"Denies the configured macros in clippy.toml + +Note: Even though this lint is warn-by-default, it will only trigger if +macros are defined in the clippy.toml file."##, }, Lint { label: "clippy::disallowed_methods", - description: r##"Denies the configured methods and functions in clippy.toml"##, + description: r##"Denies the configured methods and functions in clippy.toml + +Note: Even though this lint is warn-by-default, it will only trigger if +methods are defined in the clippy.toml file."##, + }, + Lint { + label: "clippy::disallowed_names", + description: r##"Checks for usage of disallowed names for variables, such +as `foo`."##, }, Lint { label: "clippy::disallowed_script_idents", @@ -4958,12 +10380,20 @@ See also: [`non_ascii_idents`]. }, Lint { label: "clippy::disallowed_types", - description: r##"Denies the configured types in clippy.toml."##, + description: r##"Denies the configured types in clippy.toml. + +Note: Even though this lint is warn-by-default, it will only trigger if +types are defined in the clippy.toml file."##, }, Lint { label: "clippy::diverging_sub_expression", description: r##"Checks for diverging calls that are not match arms or statements."##, + }, + Lint { + label: "clippy::doc_link_with_quotes", + description: r##"Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks) +outside of code blocks"##, }, Lint { label: "clippy::doc_markdown", @@ -4989,14 +10419,19 @@ marked as `#[must_use]`."##, description: r##"Checks for unnecessary double parentheses."##, }, Lint { - label: "clippy::drop_copy", - description: r##"Checks for calls to `std::mem::drop` with a value -that derives the Copy trait"##, + label: "clippy::drain_collect", + description: r##"Checks for calls to `.drain()` that clear the collection, immediately followed by a call to `.collect()`. + +> Collection in this context refers to any type with a `drain` method: +> `Vec`, `VecDeque`, `BinaryHeap`, `HashSet`,`HashMap`, `String`"##, + }, + Lint { + label: "clippy::drop_non_drop", + description: r##"Checks for calls to `std::mem::drop` with a value that does not implement `Drop`."##, }, Lint { - label: "clippy::drop_ref", - description: r##"Checks for calls to `std::mem::drop` with a reference -instead of an owned value."##, + label: "clippy::duplicate_mod", + description: r##"Checks for files that are included as modules multiple times."##, }, Lint { label: "clippy::duplicate_underscore_argument", @@ -5013,6 +10448,10 @@ from other `Duration` methods."##, description: r##"Checks for usage of if expressions with an `else if` branch, but without a final `else` branch."##, }, + Lint { + label: "clippy::empty_drop", + description: r##"Checks for empty `Drop` implementations."##, + }, Lint { label: "clippy::empty_enum", description: r##"Checks for `enum`s with no variants. @@ -5021,11 +10460,19 @@ As of this writing, the `never_type` is still a nightly-only experimental API. Therefore, this lint is only triggered if the `never_type` is enabled."##, }, + Lint { + label: "clippy::empty_line_after_doc_comments", + description: r##"Checks for empty lines after documenation comments."##, + }, Lint { label: "clippy::empty_line_after_outer_attr", description: r##"Checks for empty lines after outer attributes"##, }, Lint { label: "clippy::empty_loop", description: r##"Checks for empty `loop` expressions."## }, + Lint { + label: "clippy::empty_structs_with_brackets", + description: r##"Finds structs without fields (a so-called empty struct) that are declared with brackets."##, + }, Lint { label: "clippy::enum_clike_unportable_variant", description: r##"Checks for C-like enumerations that are @@ -5052,10 +10499,18 @@ bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, description: r##"Checks for erasing operations, e.g., `x * 0`."##, }, Lint { - label: "clippy::eval_order_dependence", - description: r##"Checks for a read and a write to the same variable where -whether the read occurs before or after the write depends on the evaluation -order of sub-expressions."##, + label: "clippy::err_expect", + description: r##"Checks for `.err().expect()` calls on the `Result` type."##, + }, + Lint { + label: "clippy::error_impl_error", + description: r##"Checks for types named `Error` that implement `Error`."##, + }, + Lint { + label: "clippy::excessive_nesting", + description: r##"Checks for blocks which are nested beyond a certain threshold. + +Note: Even though this lint is warn-by-default, it will only trigger if a maximum nesting level is defined in the clippy.toml file."##, }, Lint { label: "clippy::excessive_precision", @@ -5072,8 +10527,7 @@ than that supported by the underlying type."##, }, Lint { label: "clippy::exit", - description: r##"`exit()` terminates the program and doesn't provide a -stack trace."##, + description: r##"Detects calls to the `exit()` function which terminates the program."##, }, Lint { label: "clippy::expect_fun_call", @@ -5082,13 +10536,17 @@ etc., and suggests to use `unwrap_or_else` instead"##, }, Lint { label: "clippy::expect_used", - description: r##"Checks for `.expect()` calls on `Option`s and `Result`s."##, + description: r##"Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s."##, }, Lint { label: "clippy::expl_impl_clone_on_copy", description: r##"Checks for explicit `Clone` implementations for `Copy` types."##, }, + Lint { + label: "clippy::explicit_auto_deref", + description: r##"Checks for dereferencing expressions which would be covered by auto-deref."##, + }, Lint { label: "clippy::explicit_counter_loop", description: r##"Checks `for` loops over slices with an explicit counter @@ -5126,6 +10584,10 @@ replaced with `(e)print!()` / `(e)println!()`"##, description: r##"Checks for lifetimes in generics that are never used anywhere else."##, }, + Lint { + label: "clippy::extra_unused_type_parameters", + description: r##"Checks for type parameters in generics that are never used anywhere else."##, + }, Lint { label: "clippy::fallible_impl_from", description: r##"Checks for impls of `From<..>` that contain `panic!()` or `unwrap()`"##, @@ -5143,6 +10605,10 @@ with Default::default()."##, label: "clippy::filter_map", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::filter_map_bool_then", + description: r##"Checks for usage of `bool::then` in `Iterator::filter_map`."##, + }, Lint { label: "clippy::filter_map_identity", description: r##"Checks for usage of `filter_map(|x| x)`."##, @@ -5162,7 +10628,7 @@ with Default::default()."##, }, Lint { label: "clippy::flat_map_option", - description: r##"Checks for usages of `Iterator::flat_map()` where `filter_map()` could be + description: r##"Checks for usage of `Iterator::flat_map()` where `filter_map()` could be used instead."##, }, Lint { label: "clippy::float_arithmetic", description: r##"Checks for float arithmetic."## }, @@ -5211,18 +10677,12 @@ store address."##, ignoring either the keys or values."##, }, Lint { - label: "clippy::for_loops_over_fallibles", - description: r##"Checks for `for` loops over `Option` or `Result` values."##, - }, - Lint { - label: "clippy::forget_copy", - description: r##"Checks for calls to `std::mem::forget` with a value that -derives the Copy trait"##, + label: "clippy::forget_non_drop", + description: r##"Checks for calls to `std::mem::forget` with a value that does not implement `Drop`."##, }, Lint { - label: "clippy::forget_ref", - description: r##"Checks for calls to `std::mem::forget` with a reference -instead of an owned value."##, + label: "clippy::format_collect", + description: r##"Checks for usage of `.map(|_| format!(..)).collect::()`."##, }, Lint { label: "clippy::format_in_format_args", @@ -5230,6 +10690,15 @@ instead of an owned value."##, formatting such as `format!` itself, `write!` or `println!`. Suggests inlining the `format!` call."##, }, + Lint { + label: "clippy::format_push_string", + description: r##"Detects cases where the result of a `format!` call is +appended to an existing `String`."##, + }, + Lint { + label: "clippy::four_forward_slashes", + description: r##"Checks for outer doc comments written with 4 forward slashes (`////`)."##, + }, Lint { label: "clippy::from_iter_instead_of_collect", description: r##"Checks for `from_iter()` function calls on types that implement the `FromIterator` @@ -5239,6 +10708,10 @@ trait."##, label: "clippy::from_over_into", description: r##"Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead."##, }, + Lint { + label: "clippy::from_raw_with_void_ptr", + description: r##"Checks if we're passing a `c_void` raw pointer to `{Box,Rc,Arc,Weak}::from_raw(_)`"##, + }, Lint { label: "clippy::from_str_radix_10", description: r##"Checks for function invocations of the form `primitive::from_str_radix(s, 10)`"##, @@ -5249,17 +10722,26 @@ trait."##, functions and methods to implement the `Send` marker trait. It is mostly used by library authors (public and internal) that target an audience where multithreaded executors are likely to be used for running these Futures."##, + }, + Lint { + label: "clippy::get_first", + description: r##"Checks for usage of `x.get(0)` instead of +`x.first()`."##, }, Lint { label: "clippy::get_last_with_len", - description: r##"Checks for using `x.get(x.len() - 1)` instead of + description: r##"Checks for usage of `x.get(x.len() - 1)` instead of `x.last()`."##, }, Lint { label: "clippy::get_unwrap", - description: r##"Checks for use of `.get().unwrap()` (or + description: r##"Checks for usage of `.get().unwrap()` (or `.get_mut().unwrap`) on a standard library type which implements `Index`"##, }, + Lint { + label: "clippy::host_endian_bytes", + description: r##"Checks for the usage of the `to_ne_bytes` method and/or the function `from_ne_bytes`."##, + }, Lint { label: "clippy::identity_op", description: r##"Checks for identity operations, e.g., `x + 0`."##, @@ -5285,12 +10767,20 @@ and the *else* part."##, }, Lint { label: "clippy::if_then_some_else_none", - description: r##"Checks for if-else that could be written to `bool::then`."##, + description: r##"Checks for if-else that could be written using either `bool::then` or `bool::then_some`."##, }, Lint { label: "clippy::ifs_same_cond", description: r##"Checks for consecutive `if`s with the same condition."##, }, + Lint { + label: "clippy::ignored_unit_patterns", + description: r##"Checks for usage of `_` in patterns of type `()`."##, + }, + Lint { + label: "clippy::impl_trait_in_params", + description: r##"Lints when `impl Trait` is being used in a function's parameters."##, + }, Lint { label: "clippy::implicit_clone", description: r##"Checks for the usage of `_.to_owned()`, `vec.to_vec()`, or similar when calling `_.clone()` would be clearer."##, @@ -5305,10 +10795,25 @@ algorithm (`SipHash`)."##, label: "clippy::implicit_return", description: r##"Checks for missing return statements at the end of a block."##, }, + Lint { + label: "clippy::implicit_saturating_add", + description: r##"Checks for implicit saturating addition."##, + }, Lint { label: "clippy::implicit_saturating_sub", description: r##"Checks for implicit saturating subtraction."##, }, + Lint { + label: "clippy::implied_bounds_in_impls", + description: r##"Looks for bounds in `impl Trait` in return position that are implied by other bounds. +This can happen when a trait is specified that another trait already has as a supertrait +(e.g. `fn() -> impl Deref + DerefMut` has an unnecessary `Deref` bound, +because `Deref` is a supertrait of `DerefMut`)"##, + }, + Lint { + label: "clippy::impossible_comparisons", + description: r##"Checks for double comparisons that can never succeed"##, + }, Lint { label: "clippy::imprecise_flops", description: r##"Looks for floating-point expressions that @@ -5343,10 +10848,10 @@ lint on constant `usize` indexing on arrays because that is handled by rustc's ` without changing the outcome. The basic structure can be seen in the following table: -|Comparison| Bit Op |Example |equals | -|----------|---------|-----------|-------| -|`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`| -|`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|"##, +|Comparison| Bit Op |Example |equals | +|----------|----------|------------|-------| +|`>` / `<=`|`\\|` / `^`|`x \\| 2 > 3`|`x > 3`| +|`<` / `>=`|`\\|` / `^`|`x ^ 1 < 4` |`x < 4`|"##, }, Lint { label: "clippy::inefficient_to_string", @@ -5370,6 +10875,12 @@ or tuple struct where a `let` will suffice."##, label: "clippy::inherent_to_string_shadow_display", description: r##"Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait."##, }, + Lint { + label: "clippy::init_numbered_fields", + description: r##"Checks for tuple structs initialized with field syntax. +It will however not lint if a base initializer is present. +The lint will also ignore code in macros."##, + }, Lint { label: "clippy::inline_always", description: r##"Checks for items annotated with `#[inline(always)]`, @@ -5395,21 +10906,17 @@ unless the annotated function is empty or simply panics."##, label: "clippy::int_plus_one", description: r##"Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block"##, }, - Lint { - label: "clippy::integer_arithmetic", - description: r##"Checks for integer arithmetic operations which could overflow or panic. - -Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable -of overflowing according to the [Rust -Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow), -or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is -attempted."##, - }, Lint { label: "clippy::integer_division", description: r##"Checks for division of integers"## }, Lint { label: "clippy::into_iter_on_ref", description: r##"Checks for `into_iter` calls on references which should be replaced by `iter` or `iter_mut`."##, + }, + Lint { + label: "clippy::into_iter_without_iter", + description: r##"This is the opposite of the `iter_without_into_iter` lint. +It looks for `IntoIterator for (&|&mut) Type` implementations without an inherent `iter` or `iter_mut` method +on the type or on any of the types in its `Deref` chain."##, }, Lint { label: "clippy::invalid_null_ptr_usage", @@ -5431,10 +10938,20 @@ necessary. Only integer types are checked."##, label: "clippy::invisible_characters", description: r##"Checks for invisible Unicode characters in the code."##, }, + Lint { + label: "clippy::is_digit_ascii_radix", + description: r##"Finds usages of [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit) that +can be replaced with [`is_ascii_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_digit) or +[`is_ascii_hexdigit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_hexdigit)."##, + }, Lint { label: "clippy::items_after_statements", description: r##"Checks for items declared after some statement in a block."##, }, + Lint { + label: "clippy::items_after_test_module", + description: r##"Triggers if an item is declared after the testing module marked with `#[cfg(test)]`."##, + }, Lint { label: "clippy::iter_cloned_collect", description: r##"Checks for the use of `.cloned().collect()` on slice to @@ -5444,6 +10961,11 @@ create a `Vec`."##, label: "clippy::iter_count", description: r##"Checks for the use of `.iter().count()`."##, }, + Lint { + label: "clippy::iter_kv_map", + description: r##"Checks for iterating a map (`HashMap` or `BTreeMap`) and +ignoring either the keys or values."##, + }, Lint { label: "clippy::iter_next_loop", description: r##"Checks for loops on `x.next()`."## }, Lint { label: "clippy::iter_next_slice", @@ -5455,16 +10977,45 @@ create a `Vec`."##, }, Lint { label: "clippy::iter_nth", - description: r##"Checks for use of `.iter().nth()` (and the related + description: r##"Checks for usage of `.iter().nth()` (and the related `.iter_mut().nth()`) on standard library types with *O*(1) element access."##, }, Lint { label: "clippy::iter_nth_zero", description: r##"Checks for the use of `iter.nth(0)`."##, }, + Lint { + label: "clippy::iter_on_empty_collections", + description: r##"Checks for calls to `iter`, `iter_mut` or `into_iter` on empty collections"##, + }, + Lint { + label: "clippy::iter_on_single_items", + description: r##"Checks for calls to `iter`, `iter_mut` or `into_iter` on collections containing a single item"##, + }, + Lint { + label: "clippy::iter_out_of_bounds", + description: r##"Looks for iterator combinator calls such as `.take(x)` or `.skip(x)` +where `x` is greater than the amount of items that an iterator will produce."##, + }, + Lint { + label: "clippy::iter_overeager_cloned", + description: r##"Checks for usage of `_.cloned().()` where call to `.cloned()` can be postponed."##, + }, Lint { label: "clippy::iter_skip_next", - description: r##"Checks for use of `.skip(x).next()` on iterators."##, + description: r##"Checks for usage of `.skip(x).next()` on iterators."##, + }, + Lint { + label: "clippy::iter_skip_zero", + description: r##"Checks for usage of `.skip(0)` on iterators."##, + }, + Lint { + label: "clippy::iter_with_drain", + description: r##"Checks for usage of `.drain(..)` on `Vec` and `VecDeque` for iteration."##, + }, + Lint { + label: "clippy::iter_without_into_iter", + description: r##"Looks for `iter` and `iter_mut` methods without an associated `IntoIterator for (&|&mut) Type` implementation."##, }, Lint { label: "clippy::iterator_step_by_zero", @@ -5490,11 +11041,30 @@ are too large."##, label: "clippy::large_enum_variant", description: r##"Checks for large size differences between variants on `enum`s."##, + }, + Lint { + label: "clippy::large_futures", + description: r##"It checks for the size of a `Future` created by `async fn` or `async {}`."##, + }, + Lint { + label: "clippy::large_include_file", + description: r##"Checks for the inclusion of large files via `include_bytes!()` +and `include_str!()`"##, }, Lint { label: "clippy::large_stack_arrays", description: r##"Checks for local arrays that may be too large."##, }, + Lint { + label: "clippy::large_stack_frames", + description: r##"Checks for functions that use a lot of stack space. + +This often happens when constructing a large type, such as an array with a lot of elements, +or constructing *many* smaller-but-still-large structs, or copying around a lot of large types. + +This lint is a more general version of [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/#large_stack_arrays) +that is intended to look at functions as a whole instead of only individual array expressions inside of a function."##, + }, Lint { label: "clippy::large_types_passed_by_value", description: r##"Checks for functions taking arguments by value, where @@ -5519,29 +11089,42 @@ just to compare to zero, and suggests using `.is_empty()` where applicable."##, returned."##, }, Lint { - label: "clippy::let_underscore_drop", - description: r##"Checks for `let _ = ` -where expr has a type that implements `Drop`"##, + label: "clippy::let_underscore_future", + description: r##"Checks for `let _ = ` where the resulting type of expr implements `Future`"##, }, Lint { label: "clippy::let_underscore_lock", - description: r##"Checks for `let _ = sync_lock`. -This supports `mutex` and `rwlock` in `std::sync` and `parking_lot`."##, + description: r##"Checks for `let _ = sync_lock`. This supports `mutex` and `rwlock` in +`parking_lot`. For `std` locks see the `rustc` lint +[`let_underscore_lock`](https://doc.rust-lang.org/nightly/rustc/lints/listing/deny-by-default.html#let-underscore-lock)"##, }, Lint { label: "clippy::let_underscore_must_use", description: r##"Checks for `let _ = ` where expr is `#[must_use]`"##, }, + Lint { + label: "clippy::let_underscore_untyped", + description: r##"Checks for `let _ = ` without a type annotation, and suggests to either provide one, +or remove the `let` keyword altogether."##, + }, Lint { label: "clippy::let_unit_value", description: r##"Checks for binding a unit value."## }, + Lint { + label: "clippy::let_with_type_underscore", + description: r##"Detects when a variable is declared with an explicit type of `_`."##, + }, + Lint { + label: "clippy::lines_filter_map_ok", + description: r##"Checks for usage of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)` +when `lines` has type `std::io::Lines`."##, + }, Lint { label: "clippy::linkedlist", description: r##"Checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`)."##, }, Lint { - label: "clippy::logic_bug", - description: r##"Checks for boolean expressions that contain terminals that -can be eliminated."##, + label: "clippy::little_endian_bytes", + description: r##"Checks for the usage of the `to_le_bytes` method and/or the function `from_le_bytes`."##, }, Lint { label: "clippy::lossy_float_literal", @@ -5564,11 +11147,28 @@ cannot be represented as the underlying type without loss."##, label: "clippy::manual_async_fn", description: r##"It checks for manual implementations of `async` functions."##, }, + Lint { + label: "clippy::manual_bits", + description: r##"Checks for usage of `std::mem::size_of::() * 8` when +`T::BITS` is available."##, + }, + Lint { + label: "clippy::manual_clamp", + description: r##"Identifies good opportunities for a clamp function from std or core, and suggests using it."##, + }, + Lint { + label: "clippy::manual_filter", + description: r##"Checks for usage of `match` which could be implemented using `filter`"##, + }, Lint { label: "clippy::manual_filter_map", description: r##"Checks for usage of `_.filter(_).map(_)` that can be written more simply as `filter_map(_)`."##, }, + Lint { + label: "clippy::manual_find", + description: r##"Checks for manual implementations of Iterator::find"##, + }, Lint { label: "clippy::manual_find_map", description: r##"Checks for usage of `_.find(_).map(_)` that can be written more simply @@ -5576,18 +11176,56 @@ as `find_map(_)`."##, }, Lint { label: "clippy::manual_flatten", - description: r##"Check for unnecessary `if let` usage in a for loop + description: r##"Checks for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the iterator element is used."##, + }, + Lint { + label: "clippy::manual_hash_one", + description: r##"Checks for cases where [`BuildHasher::hash_one`] can be used. + +[`BuildHasher::hash_one`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html#method.hash_one"##, + }, + Lint { + label: "clippy::manual_instant_elapsed", + description: r##"Lints subtraction between `Instant::now()` and another `Instant`."##, + }, + Lint { + label: "clippy::manual_is_ascii_check", + description: r##"Suggests to use dedicated built-in methods, +`is_ascii_(lowercase|uppercase|digit)` for checking on corresponding ascii range"##, + }, + Lint { + label: "clippy::manual_is_finite", + description: r##"Checks for manual `is_finite` reimplementations +(i.e., `x != ::INFINITY && x != ::NEG_INFINITY`)."##, + }, + Lint { + label: "clippy::manual_is_infinite", + description: r##"Checks for manual `is_infinite` reimplementations +(i.e., `x == ::INFINITY || x == ::NEG_INFINITY`)."##, + }, + Lint { + label: "clippy::manual_let_else", + description: r##"Warn of cases where `let...else` could be used"##, + }, + Lint { + label: "clippy::manual_main_separator_str", + description: r##"Checks for references on `std::path::MAIN_SEPARATOR.to_string()` used +to build a `&str`."##, }, Lint { label: "clippy::manual_map", - description: r##"Checks for usages of `match` which could be implemented using `map`"##, + description: r##"Checks for usage of `match` which could be implemented using `map`"##, }, Lint { label: "clippy::manual_memcpy", description: r##"Checks for for-loops that manually copy items between slices that could be optimized by having a memcpy."##, }, + Lint { + label: "clippy::manual_next_back", + description: r##"Checks for `.rev().next()` on a `DoubleEndedIterator`"##, + }, Lint { label: "clippy::manual_non_exhaustive", description: r##"Checks for manual implementations of the non-exhaustive pattern."##, @@ -5601,28 +11239,66 @@ slices that could be optimized by having a memcpy."##, description: r##"Checks for expressions like `x >= 3 && x < 8` that could be more readably expressed as `(3..8).contains(x)`."##, }, + Lint { + label: "clippy::manual_range_patterns", + description: r##"Looks for combined OR patterns that are all contained in a specific range, +e.g. `6 | 4 | 5 | 9 | 7 | 8` can be rewritten as `4..=9`."##, + }, + Lint { + label: "clippy::manual_rem_euclid", + description: r##"Checks for an expression like `((x % 4) + 4) % 4` which is a common manual reimplementation +of `x.rem_euclid(4)`."##, + }, + Lint { + label: "clippy::manual_retain", + description: r##"Checks for code to be replaced by `.retain()`."##, + }, Lint { label: "clippy::manual_saturating_arithmetic", description: r##"Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`."##, }, + Lint { + label: "clippy::manual_slice_size_calculation", + description: r##"When `a` is `&[T]`, detect `a.len() * size_of::()` and suggest `size_of_val(a)` +instead."##, + }, Lint { label: "clippy::manual_split_once", - description: r##"Checks for usages of `str::splitn(2, _)`"##, + description: r##"Checks for usage of `str::splitn(2, _)`"##, }, Lint { label: "clippy::manual_str_repeat", description: r##"Checks for manual implementations of `str::repeat`"##, }, + Lint { + label: "clippy::manual_string_new", + description: r##"Checks for usage of `` to create a `String`, such as `.to_string()`, `.to_owned()`, +`String::from()` and others."##, + }, Lint { label: "clippy::manual_strip", description: r##"Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using the pattern's length."##, }, - Lint { label: "clippy::manual_swap", description: r##"Checks for manual swapping."## }, + Lint { + label: "clippy::manual_swap", + description: r##"Checks for manual swapping. + +Note that the lint will not be emitted in const blocks, as the suggestion would not be applicable."##, + }, + Lint { + label: "clippy::manual_try_fold", + description: r##"Checks for usage of `Iterator::fold` with a type that implements `Try`."##, + }, Lint { label: "clippy::manual_unwrap_or", description: r##"Finds patterns that reimplement `Option::unwrap_or` or `Result::unwrap_or`."##, }, + Lint { + label: "clippy::manual_while_let_some", + description: r##"Looks for loops that check for emptiness of a `Vec` in the condition and pop an element +in the body as a separate operation."##, + }, Lint { label: "clippy::many_single_char_names", description: r##"Checks for too many variables whose name consists of a @@ -5640,7 +11316,7 @@ and suggests `cloned()` or `copied()` instead"##, }, Lint { label: "clippy::map_entry", - description: r##"Checks for uses of `contains_key` + `insert` on `HashMap` + description: r##"Checks for usage of `contains_key` + `insert` on `HashMap` or `BTreeMap`."##, }, Lint { @@ -5695,7 +11371,10 @@ instead. It also checks for `if let &foo = bar` blocks."##, }, Lint { label: "clippy::match_same_arms", - description: r##"Checks for `match` with identical arm bodies."##, + description: r##"Checks for `match` with identical arm bodies. + +Note: Does not lint on wildcards if the `non_exhaustive_omitted_patterns_lint` feature is +enabled and disallowed."##, }, Lint { label: "clippy::match_single_binding", @@ -5718,10 +11397,15 @@ and take drastic actions like `panic!`."##, label: "clippy::maybe_infinite_iter", description: r##"Checks for iteration that may be infinite."##, }, + Lint { + label: "clippy::maybe_misused_cfg", + description: r##"Checks for `#[cfg(features = ...)]` and suggests to replace it with +`#[cfg(feature = ...)]`."##, + }, Lint { label: "clippy::mem_forget", description: r##"Checks for usage of `std::mem::forget(t)` where `t` is -`Drop`."##, +`Drop` or has a field that implements `Drop`."##, }, Lint { label: "clippy::mem_replace_option_with_none", @@ -5737,6 +11421,13 @@ and take drastic actions like `panic!`."##, label: "clippy::mem_replace_with_uninit", description: r##"Checks for `mem::replace(&mut _, mem::uninitialized())` and `mem::replace(&mut _, mem::zeroed())`."##, + }, + Lint { + label: "clippy::min_ident_chars", + description: r##"Checks for idents which comprise of a single letter. + +Note: This lint can be very noisy when enabled; it may be desirable to only enable it +temporarily."##, }, Lint { label: "clippy::min_max", @@ -5751,18 +11442,38 @@ used to clamp values, but switched so that the result is constant."##, label: "clippy::mismatched_target_os", description: r##"Checks for cfg attributes having operating systems used in target family position."##, }, + Lint { + label: "clippy::mismatching_type_param_order", + description: r##"Checks for type parameters which are positioned inconsistently between +a type definition and impl block. Specifically, a parameter in an impl +block which has the same name as a parameter in the type def, but is in +a different place."##, + }, + Lint { + label: "clippy::misnamed_getters", + description: r##"Checks for getter methods that return a field that doesn't correspond +to the name of the method, when there is a field's whose name matches that of the method."##, + }, Lint { label: "clippy::misrefactored_assign_op", description: r##"Checks for `a op= a op b` or `a op= b op a` patterns."##, }, + Lint { + label: "clippy::missing_assert_message", + description: r##"Checks assertions without a custom panic message."##, + }, + Lint { + label: "clippy::missing_asserts_for_indexing", + description: r##"Checks for repeated slice indexing without asserting beforehand that the length +is greater than the largest index used to index into the slice."##, + }, Lint { label: "clippy::missing_const_for_fn", description: r##"Suggests the use of `const` in functions and methods where possible."##, }, Lint { label: "clippy::missing_docs_in_private_items", - description: r##"Warns if there is missing doc for any documentable item -(public or private)."##, + description: r##"Warns if there is missing doc for any private documentable item"##, }, Lint { label: "clippy::missing_enforced_import_renames", @@ -5774,6 +11485,10 @@ in the `enforce-import-renames` config option."##, description: r##"Checks the doc comments of publicly visible functions that return a `Result` type and warns if there is no `# Errors` section."##, }, + Lint { + label: "clippy::missing_fields_in_debug", + description: r##"Checks for manual [`core::fmt::Debug`](https://doc.rust-lang.org/core/fmt/trait.Debug.html) implementations that do not use all fields."##, + }, Lint { label: "clippy::missing_inline_in_public_items", description: r##"It lints if an exported function, method, trait method with default impl, @@ -5788,6 +11503,17 @@ may panic and warns if there is no `# Panics` section."##, label: "clippy::missing_safety_doc", description: r##"Checks for the doc comments of publicly visible unsafe functions and warns if there is no `# Safety` section."##, + }, + Lint { label: "clippy::missing_spin_loop", description: r##"Checks for empty spin loops"## }, + Lint { + label: "clippy::missing_trait_methods", + description: r##"Checks if a provided method is used implicitly by a trait +implementation. A usage example would be a wrapper where every method +should perform some operation before delegating to the inner type's +implementation. + +This lint should typically be enabled on a specific trait `impl` item +rather than globally."##, }, Lint { label: "clippy::mistyped_literal_suffixes", @@ -5797,10 +11523,16 @@ unsafe functions and warns if there is no `# Safety` section."##, label: "clippy::mixed_case_hex_literals", description: r##"Warns on hexadecimal literals with mixed-case letter digits."##, + }, + Lint { + label: "clippy::mixed_read_write_in_expression", + description: r##"Checks for a read and a write to the same variable where +whether the read occurs before or after the write depends on the evaluation +order of sub-expressions."##, }, Lint { label: "clippy::mod_module_files", - description: r##"Checks that module layout uses only self named module files, bans mod.rs files."##, + description: r##"Checks that module layout uses only self named module files, bans `mod.rs` files."##, }, Lint { label: "clippy::module_inception", @@ -5818,6 +11550,7 @@ containing module's name."##, description: r##"Checks for getting the remainder of a division by one or minus one."##, }, + Lint { label: "clippy::multi_assignments", description: r##"Checks for nested assignments."## }, Lint { label: "clippy::multiple_crate_versions", description: r##"Checks to see if multiple versions of a crate are being @@ -5827,6 +11560,10 @@ used."##, label: "clippy::multiple_inherent_impl", description: r##"Checks for multiple inherent implementations of a struct"##, }, + Lint { + label: "clippy::multiple_unsafe_ops_per_block", + description: r##"Checks for `unsafe` blocks that contain more than one unsafe operation."##, + }, Lint { label: "clippy::must_use_candidate", description: r##"Checks for public functions that have no @@ -5840,8 +11577,12 @@ unit-returning functions and methods."##, }, Lint { label: "clippy::mut_from_ref", - description: r##"This lint checks for functions that take immutable -references and return mutable ones."##, + description: r##"This lint checks for functions that take immutable references and return +mutable ones. This will not trigger if no unsafe code exists as there +are multiple safe functions which will do this transformation + +To be on the conservative side, if there's at least one mutable +reference with the output lifetime, this lint will not trigger."##, }, Lint { label: "clippy::mut_mut", @@ -5861,11 +11602,11 @@ references and return mutable ones."##, }, Lint { label: "clippy::mutex_atomic", - description: r##"Checks for usages of `Mutex` where an atomic will do."##, + description: r##"Checks for usage of `Mutex` where an atomic will do."##, }, Lint { label: "clippy::mutex_integer", - description: r##"Checks for usages of `Mutex` where `X` is an integral + description: r##"Checks for usage of `Mutex` where `X` is an integral type."##, }, Lint { label: "clippy::naive_bytecount", description: r##"Checks for naive byte counts"## }, @@ -5876,13 +11617,19 @@ specify the `Self`-type explicitly"##, }, Lint { label: "clippy::needless_bitwise_bool", - description: r##"Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using + description: r##"Checks for usage of bitwise and/or operators between booleans, where performance may be improved by using a lazy and."##, }, Lint { label: "clippy::needless_bool", description: r##"Checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggests using the condition directly."##, + }, + Lint { + label: "clippy::needless_bool_assign", + description: r##"Checks for expressions of the form `if c { x = true } else { x = false }` +(or vice versa) and suggest assigning the variable directly from the +condition."##, }, Lint { label: "clippy::needless_borrow", @@ -5891,8 +11638,13 @@ be dereferenced immediately by the compiler."##, }, Lint { label: "clippy::needless_borrowed_reference", - description: r##"Checks for bindings that destructure a reference and borrow the inner + description: r##"Checks for bindings that needlessly destructure a reference and borrow the inner value with `&ref`."##, + }, + Lint { + label: "clippy::needless_borrows_for_generic_args", + description: r##"Checks for borrow operations (`&`) that used as a generic argument to a +function when the borrowed value could be used."##, }, Lint { label: "clippy::needless_collect", @@ -5910,11 +11662,16 @@ rearrangement of code can make the code easier to understand."##, label: "clippy::needless_doctest_main", description: r##"Checks for `fn main() { .. }` in doctests"##, }, + Lint { label: "clippy::needless_else", description: r##"Checks for empty `else` branches."## }, Lint { label: "clippy::needless_for_each", description: r##"Checks for usage of `for_each` that would be more simply written as a `for` loop."##, }, + Lint { + label: "clippy::needless_if", + description: r##"Checks for empty `if` branches with no else branch."##, + }, Lint { label: "clippy::needless_late_init", description: r##"Checks for late initializations that can be replaced by a `let` statement @@ -5924,11 +11681,32 @@ with an initializer."##, label: "clippy::needless_lifetimes", description: r##"Checks for lifetime annotations which can be removed by relying on lifetime elision."##, + }, + Lint { + label: "clippy::needless_match", + description: r##"Checks for unnecessary `match` or match-like `if let` returns for `Option` and `Result` +when function signatures are the same."##, }, Lint { label: "clippy::needless_option_as_deref", - description: r##"Checks for no-op uses of Option::{as_deref,as_deref_mut}, + description: r##"Checks for no-op uses of `Option::{as_deref, as_deref_mut}`, for example, `Option<&T>::as_deref()` returns the same type."##, + }, + Lint { + label: "clippy::needless_option_take", + description: r##"Checks for calling `take` function after `as_ref`."##, + }, + Lint { + label: "clippy::needless_parens_on_range_literals", + description: r##"The lint checks for parenthesis on literals in range statements that are +superfluous."##, + }, + Lint { + label: "clippy::needless_pass_by_ref_mut", + description: r##"Check if a `&mut` function argument is actually used mutably. + +Be careful if the function is publicly reexported as it would break compatibility with +users of this function."##, }, Lint { label: "clippy::needless_pass_by_value", @@ -5936,6 +11714,10 @@ for example, `Option<&T>::as_deref()` returns the same type."##, consuming them in its body."##, }, + Lint { + label: "clippy::needless_pub_self", + description: r##"Checks for usage of `pub(self)` and `pub(in self)`."##, + }, Lint { label: "clippy::needless_question_mark", description: r##"Suggests alternatives for useless applications of `?` in terminating expressions"##, @@ -5945,13 +11727,25 @@ body."##, description: r##"Checks for looping over the range of `0..len` of some collection just to get the values by index."##, }, + Lint { + label: "clippy::needless_raw_string_hashes", + description: r##"Checks for raw string literals with an unnecessary amount of hashes around them."##, + }, + Lint { + label: "clippy::needless_raw_strings", + description: r##"Checks for raw string literals where a string literal can be used instead."##, + }, Lint { label: "clippy::needless_return", description: r##"Checks for return statements at the end of a block."##, }, + Lint { + label: "clippy::needless_return_with_question_mark", + description: r##"Checks for return statements on `Err` paired with the `?` operator."##, + }, Lint { label: "clippy::needless_splitn", - description: r##"Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same."##, + description: r##"Checks for usage of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same."##, }, Lint { label: "clippy::needless_update", @@ -5985,7 +11779,7 @@ This lint is not applied to structs marked with }, Lint { label: "clippy::new_without_default", - description: r##"Checks for types with a `fn new() -> Self` method and no + description: r##"Checks for public types with a `pub fn new() -> Self` method and no implementation of [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)."##, }, @@ -5993,14 +11787,34 @@ implementation of label: "clippy::no_effect", description: r##"Checks for statements which have no effect."##, }, + Lint { + label: "clippy::no_effect_replace", + description: r##"Checks for `replace` statements which have no effect."##, + }, Lint { label: "clippy::no_effect_underscore_binding", description: r##"Checks for binding to underscore prefixed variable without side-effects."##, }, + Lint { + label: "clippy::no_mangle_with_rust_abi", + description: r##"Checks for Rust ABI functions with the `#[no_mangle]` attribute."##, + }, Lint { label: "clippy::non_ascii_literal", description: r##"Checks for non-ASCII characters in string and char literals."##, }, + Lint { + label: "clippy::non_canonical_clone_impl", + description: r##"Checks for non-canonical implementations of `Clone` when `Copy` is already implemented."##, + }, + Lint { + label: "clippy::non_canonical_partial_ord_impl", + description: r##"Checks for non-canonical implementations of `PartialOrd` when `Ord` is already implemented."##, + }, + Lint { + label: "clippy::non_minimal_cfg", + description: r##"Checks for `any` and `all` combinators in `cfg` with only one condition."##, + }, Lint { label: "clippy::non_octal_unix_permissions", description: r##"Checks for non-octal values used to set Unix file permissions."##, @@ -6032,12 +11846,20 @@ that make no sense."##, description: r##"Checks for public functions that dereference raw pointer arguments but are not marked `unsafe`."##, }, + Lint { + label: "clippy::obfuscated_if_else", + description: r##"Checks for usage of `.then_some(..).unwrap_or(..)`"##, + }, Lint { label: "clippy::octal_escapes", description: r##"Checks for `\\0` escapes in string and byte literals that look like octal character escapes in C."##, }, Lint { label: "clippy::ok_expect", description: r##"Checks for usage of `ok().expect(..)`."## }, + Lint { + label: "clippy::only_used_in_recursion", + description: r##"Checks for arguments that are only used in recursion with no side-effects."##, + }, Lint { label: "clippy::op_ref", description: r##"Checks for arguments to `==` which have their address @@ -6046,7 +11868,7 @@ and suggests to dereference the other argument instead"##, }, Lint { label: "clippy::option_as_ref_deref", - description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str)."##, + description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or its aliases (such as String::as_str)."##, }, Lint { label: "clippy::option_env_unwrap", @@ -6059,7 +11881,8 @@ suggests usage of the `env!` macro."##, }, Lint { label: "clippy::option_if_let_else", - description: r##"Lints usage of `if let Some(v) = ... { y } else { x }` which is more + description: r##"Lints usage of `if let Some(v) = ... { y } else { x }` and +`match .. { Some(v) => y, None/_ => x }` which are more idiomatically done with `Option::map_or` (if the else bit is a pure expression) or `Option::map_or_else` (if the else bit is an impure expression)."##, @@ -6075,14 +11898,19 @@ or closure that returns the unit type `()`."##, }, Lint { label: "clippy::option_option", - description: r##"Checks for use of `Option>` in function signatures and type + description: r##"Checks for usage of `Option>` in function signatures and type definitions"##, }, Lint { label: "clippy::or_fun_call", description: r##"Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, -etc., and suggests to use `or_else`, `unwrap_or_else`, etc., or -`unwrap_or_default` instead."##, +`.or_insert(foo(..))` etc., and suggests to use `.or_else(|| foo(..))`, +`.unwrap_or_else(|| foo(..))`, `.unwrap_or_default()` or `.or_default()` +etc. instead."##, + }, + Lint { + label: "clippy::or_then_unwrap", + description: r##"Checks for `.or(…).unwrap()` calls to Options and Results."##, }, Lint { label: "clippy::out_of_bounds_indexing", @@ -6093,23 +11921,47 @@ index."##, label: "clippy::overflow_check_conditional", description: r##"Detects classic underflow/overflow checks."##, }, + Lint { + label: "clippy::overly_complex_bool_expr", + description: r##"Checks for boolean expressions that contain terminals that +can be eliminated."##, + }, Lint { label: "clippy::panic", description: r##"Checks for usage of `panic!`."## }, Lint { label: "clippy::panic_in_result_fn", - description: r##"Checks for usage of `panic!`, `unimplemented!`, `todo!`, `unreachable!` or assertions in a function of type result."##, + description: r##"Checks for usage of `panic!` or assertions in a function of type result."##, }, Lint { label: "clippy::panicking_unwrap", description: r##"Checks for calls of `unwrap[_err]()` that will always fail."##, }, + Lint { + label: "clippy::partial_pub_fields", + description: r##"Checks whether partial fields of a struct are public. + +Either make all fields of a type public, or make none of them public"##, + }, Lint { label: "clippy::partialeq_ne_impl", description: r##"Checks for manual re-implementations of `PartialEq::ne`."##, }, + Lint { + label: "clippy::partialeq_to_none", + description: r##"Checks for binary comparisons to a literal `Option::None`."##, + }, Lint { label: "clippy::path_buf_push_overwrite", description: r##"* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push) calls on `PathBuf` that can cause overwrites."##, + }, + Lint { + label: "clippy::path_ends_with_ext", + description: r##"Looks for calls to `Path::ends_with` calls where the argument looks like a file extension. + +By default, Clippy has a short list of known filenames that start with a dot +but aren't necessarily file extensions (e.g. the `.git` folder), which are allowed by default. +The `allowed-dotfiles` configuration can be used to allow additional +file extensions that Clippy should not lint."##, }, Lint { label: "clippy::pattern_type_mismatch", @@ -6132,6 +11984,10 @@ in a general way even outside of the various pattern matching mechanics. Of cour this lint can still be used to highlight areas of interest and ensure a good understanding of ownership semantics."##, }, + Lint { + label: "clippy::permissions_set_readonly_false", + description: r##"Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`."##, + }, Lint { label: "clippy::possible_missing_comma", description: r##"Checks for possible missing comma in an array. It lints if @@ -6146,6 +12002,11 @@ parentheses * a negative numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call"##, + }, + Lint { + label: "clippy::print_in_format_impl", + description: r##"Checks for usage of `println`, `print`, `eprintln` or `eprint` in an +implementation of a formatting trait."##, }, Lint { label: "clippy::print_literal", @@ -6173,15 +12034,19 @@ print a newline."##, }, Lint { label: "clippy::ptr_arg", - description: r##"This lint checks for function arguments of type `&String` -or `&Vec` unless the references are mutable. It will also suggest you -replace `.clone()` calls with the appropriate `.to_owned()`/`to_string()` -calls."##, + description: r##"This lint checks for function arguments of type `&String`, `&Vec`, +`&PathBuf`, and `Cow<_>`. It will also suggest you replace `.clone()` calls +with the appropriate `.to_owned()`/`to_string()` calls."##, }, Lint { label: "clippy::ptr_as_ptr", description: r##"Checks for `as` casts between raw pointers without changing its mutability, namely `*const T` to `*const U` and `*mut T` to `*mut U`."##, + }, + Lint { + label: "clippy::ptr_cast_constness", + description: r##"Checks for `as` casts between raw pointers which change its constness, namely `*const T` to +`*mut T` and `*mut T` to `*const T`."##, }, Lint { label: "clippy::ptr_eq", description: r##"Use `std::ptr::eq` when applicable"## }, Lint { @@ -6193,10 +12058,26 @@ namely `*const T` to `*const U` and `*mut T` to `*mut U`."##, label: "clippy::pub_enum_variant_names", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { label: "clippy::pub_use", description: r##"Restricts the usage of `pub use ...`"## }, + Lint { + label: "clippy::pub_with_shorthand", + description: r##"Checks for usage of `pub()` with `in`."##, + }, + Lint { + label: "clippy::pub_without_shorthand", + description: r##"Checks for usage of `pub()` without `in`. + +Note: As you cannot write a module's path in `pub()`, this will only trigger on +`pub(super)` and the like."##, + }, Lint { label: "clippy::question_mark", description: r##"Checks for expressions that could be replaced by the question mark operator."##, }, + Lint { + label: "clippy::question_mark_used", + description: r##"Checks for expressions that use the question mark operator and rejects them."##, + }, Lint { label: "clippy::range_minus_one", description: r##"Checks for inclusive ranges where 1 is subtracted from @@ -6220,10 +12101,49 @@ upper bound, e.g., `x..(y+1)`."##, label: "clippy::rc_buffer", description: r##"Checks for `Rc` and `Arc` when `T` is a mutable buffer type such as `String` or `Vec`."##, }, + Lint { + label: "clippy::rc_clone_in_vec_init", + description: r##"Checks for reference-counted pointers (`Arc`, `Rc`, `rc::Weak`, and `sync::Weak`) +in `vec![elem; len]`"##, + }, Lint { label: "clippy::rc_mutex", description: r##"Checks for `Rc>`."## }, + Lint { + label: "clippy::read_line_without_trim", + description: r##"Looks for calls to [`Stdin::read_line`] to read a line from the standard input +into a string, then later attempting to parse this string into a type without first trimming it, which will +always fail because the string has a trailing newline in it."##, + }, + Lint { + label: "clippy::read_zero_byte_vec", + description: r##"This lint catches reads into a zero-length `Vec`. +Especially in the case of a call to `with_capacity`, this lint warns that read +gets the number of bytes from the `Vec`'s length, not its capacity."##, + }, + Lint { + label: "clippy::readonly_write_lock", + description: r##"Looks for calls to `RwLock::write` where the lock is only used for reading."##, + }, + Lint { + label: "clippy::recursive_format_impl", + description: r##"Checks for format trait implementations (e.g. `Display`) with a recursive call to itself +which uses `self` as a parameter. +This is typically done indirectly with the `write!` macro or with `to_string()`."##, + }, Lint { label: "clippy::redundant_allocation", - description: r##"Checks for use of redundant allocations anywhere in the code."##, + description: r##"Checks for usage of redundant allocations anywhere in the code."##, + }, + Lint { + label: "clippy::redundant_as_str", + description: r##"Checks for usage of `as_str()` on a `String`` chained with a method available on the `String` itself."##, + }, + Lint { + label: "clippy::redundant_async_block", + description: r##"Checks for `async` block that only returns `await` on a future."##, + }, + Lint { + label: "clippy::redundant_at_rest_pattern", + description: r##"Checks for `[all @ ..]` patterns."##, }, Lint { label: "clippy::redundant_clone", @@ -6246,6 +12166,10 @@ are defined."##, description: r##"Checks for closures which only invoke a method on the closure argument and can be replaced by referencing the method directly."##, }, + Lint { + label: "clippy::redundant_comparisons", + description: r##"Checks for ineffective double comparisons against constants."##, + }, Lint { label: "clippy::redundant_else", description: r##"Checks for `else` blocks that can be removed without changing semantics."##, @@ -6259,6 +12183,14 @@ argument and can be replaced by referencing the method directly."##, description: r##"Checks for fields in struct literals where shorthands could be used."##, }, + Lint { + label: "clippy::redundant_guards", + description: r##"Checks for unnecessary guards in match expressions."##, + }, + Lint { + label: "clippy::redundant_locals", + description: r##"Checks for redundant redefinitions of local bindings."##, + }, Lint { label: "clippy::redundant_pattern", description: r##"Checks for patterns in the form `name @ _`."##, @@ -6283,18 +12215,21 @@ do not change the type."##, description: r##"Checks for constants and statics with an explicit `'static` lifetime."##, }, Lint { - label: "clippy::ref_binding_to_reference", - description: r##"Checks for `ref` bindings which create a reference to a reference."##, + label: "clippy::redundant_type_annotations", + description: r##"Warns about needless / redundant type annotations."##, }, Lint { - label: "clippy::ref_in_deref", - description: r##"Checks for references in expressions that use -auto dereference."##, + label: "clippy::ref_binding_to_reference", + description: r##"Checks for `ref` bindings which create a reference to a reference."##, }, Lint { label: "clippy::ref_option_ref", description: r##"Checks for usage of `&Option<&T>`."##, }, + Lint { + label: "clippy::ref_patterns", + description: r##"Checks for usages of the `ref` keyword."##, + }, Lint { label: "clippy::regex_macro", description: r##"Nothing. This lint has been deprecated."##, @@ -6313,10 +12248,19 @@ they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://gi label: "clippy::replace_consts", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::reserve_after_initialization", + description: r##"Informs the user about a more concise way to create a vector with a known capacity."##, + }, Lint { label: "clippy::rest_pat_in_fully_bound_structs", description: r##"Checks for unnecessary '..' pattern binding on struct when all fields are explicitly matched."##, }, + Lint { + label: "clippy::result_large_err", + description: r##"Checks for functions that return `Result` with an unusually large +`Err`-variant."##, + }, Lint { label: "clippy::result_map_or_into_option", description: r##"Checks for usage of `_.map_or(None, Some)`."##, @@ -6339,7 +12283,7 @@ implements `std::error::Error`."##, Lint { label: "clippy::reversed_empty_ranges", description: r##"Checks for range expressions `x..y` where both `x` and `y` -are constant and `x` is greater or equal to `y`."##, +are constant and `x` is greater to `y`. Also triggers if `x` is equal to `y` when they are conditions to a `for` loop."##, }, Lint { label: "clippy::same_functions_in_if_condition", @@ -6359,6 +12303,16 @@ one from a trait, another not from trait."##, label: "clippy::search_is_some", description: r##"Checks for an iterator or string search (such as `find()`, `position()`, or `rposition()`) followed by a call to `is_some()` or `is_none()`."##, + }, + Lint { + label: "clippy::seek_from_current", + description: r##"Checks an argument of `seek` method of `Seek` trait +and if it start seek from `SeekFrom::Current(0)`, suggests `stream_position` instead."##, + }, + Lint { + label: "clippy::seek_to_start_instead_of_rewind", + description: r##"Checks for jumps to the start of a stream that implements `Seek` +and uses the `seek` method providing `Start` as parameter."##, }, Lint { label: "clippy::self_assignment", @@ -6370,13 +12324,22 @@ one from a trait, another not from trait."##, }, Lint { label: "clippy::self_named_module_files", - description: r##"Checks that module layout uses only mod.rs files."##, + description: r##"Checks that module layout uses only `mod.rs` files."##, }, Lint { label: "clippy::semicolon_if_nothing_returned", description: r##"Looks for blocks of expressions and fires if the last expression returns `()` but is not followed by a semicolon."##, }, + Lint { + label: "clippy::semicolon_inside_block", + description: r##"Suggests moving the semicolon after a block to the inside of the block, after its last +expression."##, + }, + Lint { + label: "clippy::semicolon_outside_block", + description: r##"Suggests moving the semicolon from a block's final expression outside of the block."##, + }, Lint { label: "clippy::separated_literal_suffix", description: r##"Warns if literal suffixes are separated by an underscore. @@ -6419,15 +12382,43 @@ statement."##, implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation."##, + }, + Lint { + label: "clippy::should_panic_without_expect", + description: r##"Checks for `#[should_panic]` attributes without specifying the expected panic message."##, + }, + Lint { + label: "clippy::significant_drop_in_scrutinee", + description: r##"Checks for temporaries returned from function calls in a match scrutinee that have the +`clippy::has_significant_drop` attribute."##, + }, + Lint { + label: "clippy::significant_drop_tightening", + description: r##"Searches for elements marked with `#[clippy::has_significant_drop]` that could be early +dropped but are in fact dropped at the end of their scopes. In other words, enforces the +tightening of their possible lifetimes."##, }, Lint { label: "clippy::similar_names", - description: r##"Checks for names that are very similar and thus confusing."##, + description: r##"Checks for names that are very similar and thus confusing. + +Note: this lint looks for similar names throughout each +scope. To allow it, you need to allow it on the scope +level, not on the name that is reported."##, + }, + Lint { + label: "clippy::single_call_fn", + description: r##"Checks for functions that are only used once. Does not lint tests."##, }, Lint { label: "clippy::single_char_add_str", description: r##"Warns when using `push_str`/`insert_str` with a single-character string literal where `push`/`insert` with a `char` would work fine."##, + }, + Lint { + label: "clippy::single_char_lifetime_names", + description: r##"Checks for lifetimes with names which are one character +long."##, }, Lint { label: "clippy::single_char_pattern", @@ -6445,18 +12436,32 @@ where `push`/`insert` with a `char` would work fine."##, Lint { label: "clippy::single_match", description: r##"Checks for matches with a single arm where an `if let` -will usually suffice."##, +will usually suffice. + +This intentionally does not lint if there are comments +inside of the other arm, so as to allow the user to document +why having another explicit pattern with an empty body is necessary, +or because the comments need to be preserved for other reasons."##, }, Lint { label: "clippy::single_match_else", description: r##"Checks for matches with two arms where an `if let else` will usually suffice."##, }, + Lint { + label: "clippy::single_range_in_vec_init", + description: r##"Checks for `Vec` or array initializations that contain only one range."##, + }, Lint { label: "clippy::size_of_in_element_count", description: r##"Detects expressions where `size_of::` or `size_of_val::` is used as a count of elements of type `T`"##, + }, + Lint { + label: "clippy::size_of_ref", + description: r##"Checks for calls to `std::mem::size_of_val()` where the argument is +a reference to a reference."##, }, Lint { label: "clippy::skip_while_next", @@ -6469,9 +12474,17 @@ count of elements of type `T`"##, Lint { label: "clippy::stable_sort_primitive", description: r##"When sorting primitive values (integers, bools, chars, as well -as arrays, slices, and tuples of such items), it is better to +as arrays, slices, and tuples of such items), it is typically better to use an unstable sort than a stable sort."##, }, + Lint { + label: "clippy::std_instead_of_alloc", + description: r##"Finds items imported through `std` when available through `alloc`."##, + }, + Lint { + label: "clippy::std_instead_of_core", + description: r##"Finds items imported through `std` when available through `core`."##, + }, Lint { label: "clippy::str_to_string", description: r##"This lint checks for `.to_string()` method calls on values of type `&str`."##, @@ -6501,6 +12514,10 @@ match."##, description: r##"Checks for the `as_bytes` method called on string literals that contain only ASCII characters."##, }, + Lint { + label: "clippy::string_lit_chars_any", + description: r##"Checks for `.chars().any(|i| i == c)`."##, + }, Lint { label: "clippy::string_slice", description: r##"Checks for slice operations on strings"##, @@ -6532,9 +12549,18 @@ subtracting elements in an Add impl."##, }, Lint { label: "clippy::suspicious_assignment_formatting", - description: r##"Checks for use of the nonexistent `=*`, `=!` and `=-` + description: r##"Checks for usage of the non-existent `=*`, `=!` and `=-` operators."##, }, + Lint { + label: "clippy::suspicious_command_arg_space", + description: r##"Checks for `Command::arg()` invocations that look like they +should be multiple arguments instead, such as `arg(-t ext2)`."##, + }, + Lint { + label: "clippy::suspicious_doc_comments", + description: r##"Detects the use of outer doc comments (`///`, `/**`) followed by a bang (`!`): `///!`"##, + }, Lint { label: "clippy::suspicious_else_formatting", description: r##"Checks for formatting of `else`. It lints if the `else` @@ -6561,12 +12587,24 @@ of binary operators nearby."##, (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and related functions with either zero or one splits."##, }, + Lint { + label: "clippy::suspicious_to_owned", + description: r##"Checks for the usage of `_.to_owned()`, on a `Cow<'_, _>`."##, + }, Lint { label: "clippy::suspicious_unary_op_formatting", description: r##"Checks the formatting of a unary operator on the right hand side of a binary operator. It lints if there is no space between the binary and unary operators, but there is a space between the unary and its operand."##, }, + Lint { + label: "clippy::suspicious_xor_used_as_pow", + description: r##"Warns for a Bitwise XOR (`^`) operator being probably confused as a powering. It will not trigger if any of the numbers are not in decimal."##, + }, + Lint { + label: "clippy::swap_ptr_to_ref", + description: r##"Checks for calls to `core::mem::swap` where either parameter is derived from a pointer"##, + }, Lint { label: "clippy::tabs_in_doc_comments", description: r##"Checks doc comments for usage of tab characters."##, @@ -6577,12 +12615,13 @@ but there is a space between the unary and its operand."##, assign a value in it."##, }, Lint { - label: "clippy::to_digit_is_some", - description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##, + label: "clippy::tests_outside_test_module", + description: r##"Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module +(marked with `#[cfg(test)]`)."##, }, Lint { - label: "clippy::to_string_in_display", - description: r##"Checks for uses of `to_string()` in `Display` traits."##, + label: "clippy::to_digit_is_some", + description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##, }, Lint { label: "clippy::to_string_in_format_args", @@ -6610,7 +12649,7 @@ in a macro that does formatting."##, }, Lint { label: "clippy::trait_duplication_in_bounds", - description: r##"Checks for cases where generics are being used and multiple + description: r##"Checks for cases where generics or trait objects are being used and multiple syntax specifications for trait bounds are used simultaneously."##, }, Lint { @@ -6633,6 +12672,15 @@ syntax specifications for trait bounds are used simultaneously."##, label: "clippy::transmute_int_to_float", description: r##"Checks for transmutes from an integer to a float."##, }, + Lint { + label: "clippy::transmute_int_to_non_zero", + description: r##"Checks for transmutes from integers to `NonZero*` types, and suggests their `new_unchecked` +method instead."##, + }, + Lint { + label: "clippy::transmute_null_to_fn", + description: r##"Checks for null function pointer creation through transmute."##, + }, Lint { label: "clippy::transmute_num_to_bytes", description: r##"Checks for transmutes from a number to an array of `u8`"##, @@ -6646,6 +12694,11 @@ from a reference to a reference."##, label: "clippy::transmute_ptr_to_ref", description: r##"Checks for transmutes from a pointer to a reference."##, }, + Lint { + label: "clippy::transmute_undefined_repr", + description: r##"Checks for transmutes between types which do not have a representation defined relative to +each other."##, + }, Lint { label: "clippy::transmutes_expressible_as_ptr_casts", description: r##"Checks for transmutes that could be a pointer cast."##, @@ -6654,6 +12707,10 @@ from a reference to a reference."##, label: "clippy::transmuting_null", description: r##"Checks for transmute calls which would receive a null pointer."##, }, + Lint { + label: "clippy::trim_split_whitespace", + description: r##"Warns about calling `str::trim` (or variants) before `str::split_whitespace`."##, + }, Lint { label: "clippy::trivial_regex", description: r##"Checks for trivial [regex](https://crates.io/crates/regex) @@ -6665,25 +12722,51 @@ creation (with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`)."##, the argument type is `Copy` and small enough to be more efficient to always pass by value."##, }, - Lint { label: "clippy::try_err", description: r##"Checks for usages of `Err(x)?`."## }, + Lint { label: "clippy::try_err", description: r##"Checks for usage of `Err(x)?`."## }, + Lint { + label: "clippy::tuple_array_conversions", + description: r##"Checks for tuple<=>array conversions that are not done with `.into()`."##, + }, Lint { label: "clippy::type_complexity", description: r##"Checks for types used in structs, parameters and `let` declarations above a certain complexity threshold."##, }, + Lint { + label: "clippy::type_id_on_box", + description: r##"Looks for calls to ` as Any>::type_id`."##, + }, Lint { label: "clippy::type_repetition_in_bounds", description: r##"This lint warns about unnecessary type repetitions in trait bounds"##, }, Lint { - label: "clippy::undocumented_unsafe_blocks", - description: r##"Checks for `unsafe` blocks without a `// Safety: ` comment -explaining why the unsafe operations performed inside -the block are safe."##, + label: "clippy::unchecked_duration_subtraction", + description: r##"Lints subtraction between an [`Instant`] and a [`Duration`]."##, }, Lint { - label: "clippy::undropped_manually_drops", - description: r##"Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`."##, + label: "clippy::undocumented_unsafe_blocks", + description: r##"Checks for `unsafe` blocks and impls without a `// SAFETY: ` comment +explaining why the unsafe operations performed inside +the block are safe. + +Note the comment must appear on the line(s) preceding the unsafe block +with nothing appearing in between. The following is ok: +```rust +foo( + // SAFETY: + // This is a valid safety comment + unsafe { *x } +) +``` +But neither of these are: +```rust +// SAFETY: +// This is not a valid safety comment +foo( + /* SAFETY: Neither is this */ unsafe { *x }, +); +```"##, }, Lint { label: "clippy::unicode_not_nfc", @@ -6704,6 +12787,11 @@ that is not equal to its description: r##"Checks for `set_len()` call that creates `Vec` with uninitialized elements. This is commonly caused by calling `set_len()` right after allocating or reserving a buffer with `new()`, `default()`, `with_capacity()`, or `reserve()`."##, + }, + Lint { + label: "clippy::uninlined_format_args", + description: r##"Detect when a variable is not inlined in a format string, +and suggests to inline it."##, }, Lint { label: "clippy::unit_arg", @@ -6721,24 +12809,41 @@ comparisons (like `==` and `<`) and asserts."##, description: r##"Checks for functions that expect closures of type Fn(...) -> Ord where the implemented closure returns the unit type. The lint also suggests to remove the semi-colon at the end of the statement if present."##, + }, + Lint { + label: "clippy::unnecessary_box_returns", + description: r##"Checks for a return type containing a `Box` where `T` implements `Sized` + +The lint ignores `Box` where `T` is larger than `unnecessary_box_size`, +as returning a large `T` directly may be detrimental to performance."##, }, Lint { label: "clippy::unnecessary_cast", - description: r##"Checks for casts to the same type, casts of int literals to integer types -and casts of float literals to float types."##, + description: r##"Checks for casts to the same type, casts of int literals to integer types, casts of float +literals to float types and casts between raw pointers without changing type or constness."##, }, Lint { label: "clippy::unnecessary_filter_map", - description: r##"Checks for `filter_map` calls which could be replaced by `filter` or `map`. + description: r##"Checks for `filter_map` calls that could be replaced by `filter` or `map`. More specifically it checks if the closure provided is only performing one of the filter or map operations and suggests the appropriate option."##, + }, + Lint { + label: "clippy::unnecessary_find_map", + description: r##"Checks for `find_map` calls that could be replaced by `find` or `map`. More +specifically it checks if the closure provided is only performing one of the +find or map operations and suggests the appropriate option."##, }, Lint { label: "clippy::unnecessary_fold", - description: r##"Checks for using `fold` when a more succinct alternative exists. + description: r##"Checks for usage of `fold` when a more succinct alternative exists. Specifically, this checks for `fold`s which could be replaced by `any`, `all`, `sum` or `product`."##, }, + Lint { + label: "clippy::unnecessary_join", + description: r##"Checks for usage of `.collect::>().join()` on iterators."##, + }, Lint { label: "clippy::unnecessary_lazy_evaluations", description: r##"As the counterpart to `or_fun_call`, this lint looks for unnecessary @@ -6750,7 +12855,16 @@ simpler code: - `and_then` to `and` - `or_else` to `or` - `get_or_insert_with` to `get_or_insert` - - `ok_or_else` to `ok_or`"##, + - `ok_or_else` to `ok_or` + - `then` to `then_some` (for msrv >= 1.62.0)"##, + }, + Lint { + label: "clippy::unnecessary_literal_unwrap", + description: r##"Checks for `.unwrap()` related calls on `Result`s and `Option`s that are constructed."##, + }, + Lint { + label: "clippy::unnecessary_map_on_constructor", + description: r##"Suggest removing the use of a may (or map_err) method when an Option or Result is being construted."##, }, Lint { label: "clippy::unnecessary_mut_passed", @@ -6761,6 +12875,19 @@ requires an immutable reference."##, label: "clippy::unnecessary_operation", description: r##"Checks for expression statements that can be reduced to a sub-expression."##, + }, + Lint { + label: "clippy::unnecessary_owned_empty_strings", + description: r##"Detects cases of owned empty strings being passed as an argument to a function expecting `&str`"##, + }, + Lint { + label: "clippy::unnecessary_safety_comment", + description: r##"Checks for `// SAFETY: ` comments on safe code."##, + }, + Lint { + label: "clippy::unnecessary_safety_doc", + description: r##"Checks for the doc comments of publicly visible +safe functions and traits and warns if there is a `# Safety` section."##, }, Lint { label: "clippy::unnecessary_self_imports", @@ -6768,8 +12895,13 @@ sub-expression."##, }, Lint { label: "clippy::unnecessary_sort_by", - description: r##"Detects uses of `Vec::sort_by` passing in a closure + description: r##"Checks for usage of `Vec::sort_by` passing in a closure which compares the two arguments, either directly or indirectly."##, + }, + Lint { + label: "clippy::unnecessary_struct_initialization", + description: r##"Checks for initialization of a `struct` by copying a base without setting +any field."##, }, Lint { label: "clippy::unnecessary_to_owned", @@ -6854,10 +12986,24 @@ types have different ABI, size or alignment."##, label: "clippy::unused_collect", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::unused_format_specs", + description: r##"Detects [formatting parameters] that have no effect on the output of +`format!()`, `println!()` or similar macros."##, + }, Lint { label: "clippy::unused_io_amount", description: r##"Checks for unused written/read amount."##, }, + Lint { + label: "clippy::unused_peekable", + description: r##"Checks for the creation of a `peekable` iterator that is never `.peek()`ed"##, + }, + Lint { + label: "clippy::unused_rounding", + description: r##"Detects cases where a whole-number literal float is being rounded, using +the `floor`, `ceil`, or `round` methods."##, + }, Lint { label: "clippy::unused_self", description: r##"Checks methods that contain a `self` argument but don't use it"##, @@ -6876,13 +13022,17 @@ by nibble or byte."##, description: r##"Checks for functions of type `Result` that contain `expect()` or `unwrap()`"##, }, Lint { - label: "clippy::unwrap_or_else_default", - description: r##"Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and -`Result` values."##, + label: "clippy::unwrap_or_default", + description: r##"Checks for usages of the following functions with an argument that constructs a default value +(e.g., `Default::default` or `String::new`): +- `unwrap_or` +- `unwrap_or_else` +- `or_insert` +- `or_insert_with`"##, }, Lint { label: "clippy::unwrap_used", - description: r##"Checks for `.unwrap()` calls on `Option`s and on `Result`s."##, + description: r##"Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s."##, }, Lint { label: "clippy::upper_case_acronyms", @@ -6890,7 +13040,7 @@ by nibble or byte."##, }, Lint { label: "clippy::use_debug", - description: r##"Checks for use of `Debug` formatting. The purpose of this + description: r##"Checks for usage of `Debug` formatting. The purpose of this lint is to catch debugging remnants."##, }, Lint { @@ -6913,10 +13063,17 @@ types before and after the call are the same."##, description: r##"Checks for `extern crate` and `use` items annotated with lint attributes. -This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]`, -`#[allow(unreachable_pub)]`, `#[allow(clippy::wildcard_imports)]` and -`#[allow(clippy::enum_glob_use)]` on `use` items and `#[allow(unused_imports)]` on -`extern crate` items with a `#[macro_use]` attribute."##, +This lint permits lint attributes for lints emitted on the items themself. +For `use` items these lints are: +* deprecated +* unreachable_pub +* unused_imports +* clippy::enum_glob_use +* clippy::macro_use_imports +* clippy::wildcard_imports + +For `extern crate` items these lints are: +* `unused_imports` on items with `#[macro_use]`"##, }, Lint { label: "clippy::useless_conversion", @@ -6940,17 +13097,24 @@ and transmutes that could be a cast."##, }, Lint { label: "clippy::useless_vec", - description: r##"Checks for usage of `&vec![..]` when using `&[..]` would + description: r##"Checks for usage of `vec![..]` when using `[..]` would be possible."##, }, Lint { label: "clippy::vec_box", - description: r##"Checks for use of `Vec>` where T: Sized anywhere in the code. + description: r##"Checks for usage of `Vec>` where T: Sized anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, }, Lint { label: "clippy::vec_init_then_push", - description: r##"Checks for calls to `push` immediately after creating a new `Vec`."##, + description: r##"Checks for calls to `push` immediately after creating a new `Vec`. + +If the `Vec` is created using `with_capacity` this will only lint if the capacity is a +constant and the number of pushes is greater than or equal to the initial capacity. + +If the `Vec` is extended after the initial sequence of pushes and it was default initialized +then this will only lint after there were at least four pushes. This number may change in +the future."##, }, Lint { label: "clippy::vec_resize_to_zero", @@ -6963,7 +13127,7 @@ to `trailing_zeros`"##, }, Lint { label: "clippy::verbose_file_reads", - description: r##"Checks for use of File::read_to_end and File::read_to_string."##, + description: r##"Checks for usage of File::read_to_end and File::read_to_string."##, }, Lint { label: "clippy::vtable_address_comparisons", @@ -7020,18 +13184,19 @@ print a newline."##, }, Lint { label: "clippy::wrong_self_convention", - description: r##"Checks for methods with certain name prefixes and which -doesn't match how self is taken. The actual rules are: - -|Prefix |Postfix |`self` taken | `self` type | -|-------|------------|-----------------------|--------------| -|`as_` | none |`&self` or `&mut self` | any | -|`from_`| none | none | any | -|`into_`| none |`self` | any | -|`is_` | none |`&self` or none | any | -|`to_` | `_mut` |`&mut self` | any | -|`to_` | not `_mut` |`self` | `Copy` | -|`to_` | not `_mut` |`&self` | not `Copy` | + description: r##"Checks for methods with certain name prefixes or suffixes, and which +do not adhere to standard conventions regarding how `self` is taken. +The actual rules are: + +|Prefix |Postfix |`self` taken | `self` type | +|-------|------------|-------------------------------|--------------| +|`as_` | none |`&self` or `&mut self` | any | +|`from_`| none | none | any | +|`into_`| none |`self` | any | +|`is_` | none |`&mut self` or `&self` or none | any | +|`to_` | `_mut` |`&mut self` | any | +|`to_` | not `_mut` |`self` | `Copy` | +|`to_` | not `_mut` |`&self` | not `Copy` | Note: Clippy doesn't trigger methods with `to_` prefix in: - Traits definition. @@ -7086,15 +13251,18 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::complexity", - description: r##"lint group for: clippy::bind_instead_of_map, clippy::bool_comparison, clippy::borrowed_box, clippy::char_lit_as_u8, clippy::clone_on_copy, clippy::crosspointer_transmute, clippy::deprecated_cfg_attr, clippy::deref_addrof, clippy::derivable_impls, clippy::diverging_sub_expression, clippy::double_comparisons, clippy::double_parens, clippy::duration_subsec, clippy::explicit_counter_loop, clippy::explicit_write, clippy::extra_unused_lifetimes, clippy::filter_map_identity, clippy::filter_next, clippy::flat_map_identity, clippy::get_last_with_len, clippy::identity_op, clippy::inspect_for_each, clippy::int_plus_one, clippy::iter_count, clippy::manual_filter_map, clippy::manual_find_map, clippy::manual_flatten, clippy::manual_split_once, clippy::manual_strip, clippy::manual_swap, clippy::manual_unwrap_or, clippy::map_flatten, clippy::map_identity, clippy::match_as_ref, clippy::match_single_binding, clippy::needless_arbitrary_self_type, clippy::needless_bool, clippy::needless_borrowed_reference, clippy::needless_lifetimes, clippy::needless_option_as_deref, clippy::needless_question_mark, clippy::needless_splitn, clippy::needless_update, clippy::neg_cmp_op_on_partial_ord, clippy::no_effect, clippy::nonminimal_bool, clippy::option_as_ref_deref, clippy::option_filter_map, clippy::option_map_unit_fn, clippy::overflow_check_conditional, clippy::partialeq_ne_impl, clippy::precedence, clippy::ptr_offset_with_cast, clippy::range_zip_with_len, clippy::redundant_closure_call, clippy::redundant_slicing, clippy::ref_in_deref, clippy::repeat_once, clippy::result_map_unit_fn, clippy::search_is_some, clippy::short_circuit_statement, clippy::single_element_loop, clippy::skip_while_next, clippy::string_from_utf8_as_bytes, clippy::strlen_on_c_strings, clippy::temporary_assignment, clippy::too_many_arguments, clippy::transmute_bytes_to_str, clippy::transmute_float_to_int, clippy::transmute_int_to_bool, clippy::transmute_int_to_char, clippy::transmute_int_to_float, clippy::transmute_num_to_bytes, clippy::transmute_ptr_to_ref, clippy::transmutes_expressible_as_ptr_casts, clippy::type_complexity, clippy::unit_arg, clippy::unnecessary_cast, clippy::unnecessary_filter_map, clippy::unnecessary_operation, clippy::unnecessary_sort_by, clippy::unnecessary_unwrap, clippy::unneeded_wildcard_pattern, clippy::useless_asref, clippy::useless_conversion, clippy::useless_format, clippy::vec_box, clippy::while_let_loop, clippy::wildcard_in_or_patterns, clippy::zero_divided_by_zero, clippy::zero_prefixed_literal"##, + description: r##"lint group for: clippy::bind_instead_of_map, clippy::bool_comparison, clippy::borrow_deref_ref, clippy::borrowed_box, clippy::bytes_count_to_len, clippy::char_lit_as_u8, clippy::clone_on_copy, clippy::crosspointer_transmute, clippy::default_constructed_unit_structs, clippy::deprecated_cfg_attr, clippy::deref_addrof, clippy::derivable_impls, clippy::diverging_sub_expression, clippy::double_comparisons, clippy::double_parens, clippy::duration_subsec, clippy::excessive_nesting, clippy::explicit_auto_deref, clippy::explicit_counter_loop, clippy::explicit_write, clippy::extra_unused_lifetimes, clippy::extra_unused_type_parameters, clippy::filter_map_identity, clippy::filter_next, clippy::flat_map_identity, clippy::get_last_with_len, clippy::identity_op, clippy::inspect_for_each, clippy::int_plus_one, clippy::iter_count, clippy::iter_kv_map, clippy::let_with_type_underscore, clippy::manual_filter, clippy::manual_filter_map, clippy::manual_find, clippy::manual_find_map, clippy::manual_flatten, clippy::manual_hash_one, clippy::manual_main_separator_str, clippy::manual_range_patterns, clippy::manual_rem_euclid, clippy::manual_slice_size_calculation, clippy::manual_split_once, clippy::manual_strip, clippy::manual_swap, clippy::manual_unwrap_or, clippy::map_flatten, clippy::map_identity, clippy::match_as_ref, clippy::match_single_binding, clippy::needless_arbitrary_self_type, clippy::needless_bool, clippy::needless_bool_assign, clippy::needless_borrowed_reference, clippy::needless_if, clippy::needless_lifetimes, clippy::needless_match, clippy::needless_option_as_deref, clippy::needless_option_take, clippy::needless_question_mark, clippy::needless_splitn, clippy::needless_update, clippy::neg_cmp_op_on_partial_ord, clippy::no_effect, clippy::nonminimal_bool, clippy::only_used_in_recursion, clippy::option_as_ref_deref, clippy::option_filter_map, clippy::option_map_unit_fn, clippy::or_then_unwrap, clippy::overflow_check_conditional, clippy::partialeq_ne_impl, clippy::precedence, clippy::ptr_offset_with_cast, clippy::range_zip_with_len, clippy::redundant_as_str, clippy::redundant_async_block, clippy::redundant_at_rest_pattern, clippy::redundant_closure_call, clippy::redundant_guards, clippy::redundant_slicing, clippy::repeat_once, clippy::reserve_after_initialization, clippy::result_map_unit_fn, clippy::search_is_some, clippy::seek_from_current, clippy::seek_to_start_instead_of_rewind, clippy::short_circuit_statement, clippy::single_element_loop, clippy::skip_while_next, clippy::string_from_utf8_as_bytes, clippy::strlen_on_c_strings, clippy::temporary_assignment, clippy::too_many_arguments, clippy::transmute_bytes_to_str, clippy::transmute_float_to_int, clippy::transmute_int_to_bool, clippy::transmute_int_to_char, clippy::transmute_int_to_float, clippy::transmute_int_to_non_zero, clippy::transmute_num_to_bytes, clippy::transmute_ptr_to_ref, clippy::transmutes_expressible_as_ptr_casts, clippy::type_complexity, clippy::unit_arg, clippy::unnecessary_cast, clippy::unnecessary_filter_map, clippy::unnecessary_find_map, clippy::unnecessary_literal_unwrap, clippy::unnecessary_map_on_constructor, clippy::unnecessary_operation, clippy::unnecessary_sort_by, clippy::unnecessary_unwrap, clippy::unneeded_wildcard_pattern, clippy::unused_format_specs, clippy::useless_asref, clippy::useless_conversion, clippy::useless_format, clippy::useless_transmute, clippy::vec_box, clippy::while_let_loop, clippy::wildcard_in_or_patterns, clippy::zero_divided_by_zero, clippy::zero_prefixed_literal"##, }, children: &[ "clippy::bind_instead_of_map", "clippy::bool_comparison", + "clippy::borrow_deref_ref", "clippy::borrowed_box", + "clippy::bytes_count_to_len", "clippy::char_lit_as_u8", "clippy::clone_on_copy", "clippy::crosspointer_transmute", + "clippy::default_constructed_unit_structs", "clippy::deprecated_cfg_attr", "clippy::deref_addrof", "clippy::derivable_impls", @@ -7102,9 +13270,12 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::double_comparisons", "clippy::double_parens", "clippy::duration_subsec", + "clippy::excessive_nesting", + "clippy::explicit_auto_deref", "clippy::explicit_counter_loop", "clippy::explicit_write", "clippy::extra_unused_lifetimes", + "clippy::extra_unused_type_parameters", "clippy::filter_map_identity", "clippy::filter_next", "clippy::flat_map_identity", @@ -7113,9 +13284,18 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::inspect_for_each", "clippy::int_plus_one", "clippy::iter_count", + "clippy::iter_kv_map", + "clippy::let_with_type_underscore", + "clippy::manual_filter", "clippy::manual_filter_map", + "clippy::manual_find", "clippy::manual_find_map", "clippy::manual_flatten", + "clippy::manual_hash_one", + "clippy::manual_main_separator_str", + "clippy::manual_range_patterns", + "clippy::manual_rem_euclid", + "clippy::manual_slice_size_calculation", "clippy::manual_split_once", "clippy::manual_strip", "clippy::manual_swap", @@ -7126,29 +13306,41 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::match_single_binding", "clippy::needless_arbitrary_self_type", "clippy::needless_bool", + "clippy::needless_bool_assign", "clippy::needless_borrowed_reference", + "clippy::needless_if", "clippy::needless_lifetimes", + "clippy::needless_match", "clippy::needless_option_as_deref", + "clippy::needless_option_take", "clippy::needless_question_mark", "clippy::needless_splitn", "clippy::needless_update", "clippy::neg_cmp_op_on_partial_ord", "clippy::no_effect", "clippy::nonminimal_bool", + "clippy::only_used_in_recursion", "clippy::option_as_ref_deref", "clippy::option_filter_map", "clippy::option_map_unit_fn", + "clippy::or_then_unwrap", "clippy::overflow_check_conditional", "clippy::partialeq_ne_impl", "clippy::precedence", "clippy::ptr_offset_with_cast", "clippy::range_zip_with_len", + "clippy::redundant_as_str", + "clippy::redundant_async_block", + "clippy::redundant_at_rest_pattern", "clippy::redundant_closure_call", + "clippy::redundant_guards", "clippy::redundant_slicing", - "clippy::ref_in_deref", "clippy::repeat_once", + "clippy::reserve_after_initialization", "clippy::result_map_unit_fn", "clippy::search_is_some", + "clippy::seek_from_current", + "clippy::seek_to_start_instead_of_rewind", "clippy::short_circuit_statement", "clippy::single_element_loop", "clippy::skip_while_next", @@ -7161,6 +13353,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::transmute_int_to_bool", "clippy::transmute_int_to_char", "clippy::transmute_int_to_float", + "clippy::transmute_int_to_non_zero", "clippy::transmute_num_to_bytes", "clippy::transmute_ptr_to_ref", "clippy::transmutes_expressible_as_ptr_casts", @@ -7168,13 +13361,18 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::unit_arg", "clippy::unnecessary_cast", "clippy::unnecessary_filter_map", + "clippy::unnecessary_find_map", + "clippy::unnecessary_literal_unwrap", + "clippy::unnecessary_map_on_constructor", "clippy::unnecessary_operation", "clippy::unnecessary_sort_by", "clippy::unnecessary_unwrap", "clippy::unneeded_wildcard_pattern", + "clippy::unused_format_specs", "clippy::useless_asref", "clippy::useless_conversion", "clippy::useless_format", + "clippy::useless_transmute", "clippy::vec_box", "clippy::while_let_loop", "clippy::wildcard_in_or_patterns", @@ -7185,7 +13383,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::correctness", - description: r##"lint group for: clippy::absurd_extreme_comparisons, clippy::almost_swapped, clippy::approx_constant, clippy::async_yields_async, clippy::bad_bit_mask, clippy::cast_ref_to_mut, clippy::clone_double_ref, clippy::cmp_nan, clippy::deprecated_semver, clippy::derive_hash_xor_eq, clippy::derive_ord_xor_partial_ord, clippy::drop_copy, clippy::drop_ref, clippy::enum_clike_unportable_variant, clippy::eq_op, clippy::erasing_op, clippy::fn_address_comparisons, clippy::forget_copy, clippy::forget_ref, clippy::if_let_mutex, clippy::if_same_then_else, clippy::ifs_same_cond, clippy::ineffective_bit_mask, clippy::infinite_iter, clippy::inherent_to_string_shadow_display, clippy::inline_fn_without_body, clippy::invalid_null_ptr_usage, clippy::invalid_regex, clippy::invisible_characters, clippy::iter_next_loop, clippy::iterator_step_by_zero, clippy::let_underscore_lock, clippy::logic_bug, clippy::match_str_case_mismatch, clippy::mem_replace_with_uninit, clippy::min_max, clippy::mismatched_target_os, clippy::mistyped_literal_suffixes, clippy::modulo_one, clippy::mut_from_ref, clippy::never_loop, clippy::non_octal_unix_permissions, clippy::nonsensical_open_options, clippy::not_unsafe_ptr_arg_deref, clippy::option_env_unwrap, clippy::out_of_bounds_indexing, clippy::panicking_unwrap, clippy::possible_missing_comma, clippy::reversed_empty_ranges, clippy::self_assignment, clippy::serde_api_misuse, clippy::size_of_in_element_count, clippy::suspicious_splitn, clippy::to_string_in_display, clippy::transmuting_null, clippy::undropped_manually_drops, clippy::uninit_assumed_init, clippy::uninit_vec, clippy::unit_cmp, clippy::unit_hash, clippy::unit_return_expecting_ord, clippy::unsound_collection_transmute, clippy::unused_io_amount, clippy::useless_attribute, clippy::vec_resize_to_zero, clippy::vtable_address_comparisons, clippy::while_immutable_condition, clippy::wrong_transmute, clippy::zst_offset"##, + description: r##"lint group for: clippy::absurd_extreme_comparisons, clippy::almost_swapped, clippy::approx_constant, clippy::async_yields_async, clippy::bad_bit_mask, clippy::cast_slice_different_sizes, clippy::deprecated_semver, clippy::derive_ord_xor_partial_ord, clippy::derived_hash_with_manual_eq, clippy::enum_clike_unportable_variant, clippy::eq_op, clippy::erasing_op, clippy::fn_address_comparisons, clippy::if_let_mutex, clippy::if_same_then_else, clippy::ifs_same_cond, clippy::impossible_comparisons, clippy::ineffective_bit_mask, clippy::infinite_iter, clippy::inherent_to_string_shadow_display, clippy::inline_fn_without_body, clippy::invalid_null_ptr_usage, clippy::invalid_regex, clippy::invisible_characters, clippy::iter_next_loop, clippy::iter_skip_zero, clippy::iterator_step_by_zero, clippy::let_underscore_lock, clippy::match_str_case_mismatch, clippy::mem_replace_with_uninit, clippy::min_max, clippy::mismatched_target_os, clippy::mistyped_literal_suffixes, clippy::modulo_one, clippy::mut_from_ref, clippy::never_loop, clippy::non_octal_unix_permissions, clippy::nonsensical_open_options, clippy::not_unsafe_ptr_arg_deref, clippy::option_env_unwrap, clippy::out_of_bounds_indexing, clippy::overly_complex_bool_expr, clippy::panicking_unwrap, clippy::possible_missing_comma, clippy::read_line_without_trim, clippy::read_zero_byte_vec, clippy::recursive_format_impl, clippy::redundant_comparisons, clippy::redundant_locals, clippy::reversed_empty_ranges, clippy::self_assignment, clippy::serde_api_misuse, clippy::size_of_in_element_count, clippy::suspicious_splitn, clippy::transmute_null_to_fn, clippy::transmuting_null, clippy::uninit_assumed_init, clippy::uninit_vec, clippy::unit_cmp, clippy::unit_hash, clippy::unit_return_expecting_ord, clippy::unsound_collection_transmute, clippy::unused_io_amount, clippy::useless_attribute, clippy::vec_resize_to_zero, clippy::vtable_address_comparisons, clippy::while_immutable_condition, clippy::wrong_transmute, clippy::zst_offset"##, }, children: &[ "clippy::absurd_extreme_comparisons", @@ -7193,23 +13391,18 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::approx_constant", "clippy::async_yields_async", "clippy::bad_bit_mask", - "clippy::cast_ref_to_mut", - "clippy::clone_double_ref", - "clippy::cmp_nan", + "clippy::cast_slice_different_sizes", "clippy::deprecated_semver", - "clippy::derive_hash_xor_eq", "clippy::derive_ord_xor_partial_ord", - "clippy::drop_copy", - "clippy::drop_ref", + "clippy::derived_hash_with_manual_eq", "clippy::enum_clike_unportable_variant", "clippy::eq_op", "clippy::erasing_op", "clippy::fn_address_comparisons", - "clippy::forget_copy", - "clippy::forget_ref", "clippy::if_let_mutex", "clippy::if_same_then_else", "clippy::ifs_same_cond", + "clippy::impossible_comparisons", "clippy::ineffective_bit_mask", "clippy::infinite_iter", "clippy::inherent_to_string_shadow_display", @@ -7218,9 +13411,9 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::invalid_regex", "clippy::invisible_characters", "clippy::iter_next_loop", + "clippy::iter_skip_zero", "clippy::iterator_step_by_zero", "clippy::let_underscore_lock", - "clippy::logic_bug", "clippy::match_str_case_mismatch", "clippy::mem_replace_with_uninit", "clippy::min_max", @@ -7234,16 +13427,21 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::not_unsafe_ptr_arg_deref", "clippy::option_env_unwrap", "clippy::out_of_bounds_indexing", + "clippy::overly_complex_bool_expr", "clippy::panicking_unwrap", "clippy::possible_missing_comma", + "clippy::read_line_without_trim", + "clippy::read_zero_byte_vec", + "clippy::recursive_format_impl", + "clippy::redundant_comparisons", + "clippy::redundant_locals", "clippy::reversed_empty_ranges", "clippy::self_assignment", "clippy::serde_api_misuse", "clippy::size_of_in_element_count", "clippy::suspicious_splitn", - "clippy::to_string_in_display", + "clippy::transmute_null_to_fn", "clippy::transmuting_null", - "clippy::undropped_manually_drops", "clippy::uninit_assumed_init", "clippy::uninit_vec", "clippy::unit_cmp", @@ -7286,45 +13484,66 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::nursery", - description: r##"lint group for: clippy::branches_sharing_code, clippy::cognitive_complexity, clippy::debug_assert_with_mut_call, clippy::disallowed_methods, clippy::disallowed_types, clippy::empty_line_after_outer_attr, clippy::equatable_if_let, clippy::fallible_impl_from, clippy::future_not_send, clippy::imprecise_flops, clippy::index_refutable_slice, clippy::missing_const_for_fn, clippy::mutex_integer, clippy::non_send_fields_in_send_ty, clippy::nonstandard_macro_braces, clippy::option_if_let_else, clippy::path_buf_push_overwrite, clippy::redundant_pub_crate, clippy::string_lit_as_bytes, clippy::suboptimal_flops, clippy::suspicious_operation_groupings, clippy::trailing_empty_array, clippy::trivial_regex, clippy::use_self, clippy::useless_let_if_seq, clippy::useless_transmute"##, + description: r##"lint group for: clippy::as_ptr_cast_mut, clippy::branches_sharing_code, clippy::clear_with_drain, clippy::cognitive_complexity, clippy::collection_is_never_read, clippy::debug_assert_with_mut_call, clippy::derive_partial_eq_without_eq, clippy::empty_line_after_doc_comments, clippy::empty_line_after_outer_attr, clippy::equatable_if_let, clippy::fallible_impl_from, clippy::future_not_send, clippy::implied_bounds_in_impls, clippy::imprecise_flops, clippy::iter_on_empty_collections, clippy::iter_on_single_items, clippy::iter_with_drain, clippy::large_stack_frames, clippy::manual_clamp, clippy::missing_const_for_fn, clippy::mutex_integer, clippy::needless_collect, clippy::needless_pass_by_ref_mut, clippy::non_send_fields_in_send_ty, clippy::nonstandard_macro_braces, clippy::option_if_let_else, clippy::or_fun_call, clippy::path_buf_push_overwrite, clippy::readonly_write_lock, clippy::redundant_clone, clippy::redundant_pub_crate, clippy::significant_drop_in_scrutinee, clippy::significant_drop_tightening, clippy::string_lit_as_bytes, clippy::suboptimal_flops, clippy::suspicious_operation_groupings, clippy::trailing_empty_array, clippy::trait_duplication_in_bounds, clippy::transmute_undefined_repr, clippy::trivial_regex, clippy::tuple_array_conversions, clippy::type_repetition_in_bounds, clippy::unnecessary_struct_initialization, clippy::unused_peekable, clippy::unused_rounding, clippy::use_self, clippy::useless_let_if_seq"##, }, children: &[ + "clippy::as_ptr_cast_mut", "clippy::branches_sharing_code", + "clippy::clear_with_drain", "clippy::cognitive_complexity", + "clippy::collection_is_never_read", "clippy::debug_assert_with_mut_call", - "clippy::disallowed_methods", - "clippy::disallowed_types", + "clippy::derive_partial_eq_without_eq", + "clippy::empty_line_after_doc_comments", "clippy::empty_line_after_outer_attr", "clippy::equatable_if_let", "clippy::fallible_impl_from", "clippy::future_not_send", + "clippy::implied_bounds_in_impls", "clippy::imprecise_flops", - "clippy::index_refutable_slice", + "clippy::iter_on_empty_collections", + "clippy::iter_on_single_items", + "clippy::iter_with_drain", + "clippy::large_stack_frames", + "clippy::manual_clamp", "clippy::missing_const_for_fn", "clippy::mutex_integer", + "clippy::needless_collect", + "clippy::needless_pass_by_ref_mut", "clippy::non_send_fields_in_send_ty", "clippy::nonstandard_macro_braces", "clippy::option_if_let_else", + "clippy::or_fun_call", "clippy::path_buf_push_overwrite", + "clippy::readonly_write_lock", + "clippy::redundant_clone", "clippy::redundant_pub_crate", + "clippy::significant_drop_in_scrutinee", + "clippy::significant_drop_tightening", "clippy::string_lit_as_bytes", "clippy::suboptimal_flops", "clippy::suspicious_operation_groupings", "clippy::trailing_empty_array", + "clippy::trait_duplication_in_bounds", + "clippy::transmute_undefined_repr", "clippy::trivial_regex", + "clippy::tuple_array_conversions", + "clippy::type_repetition_in_bounds", + "clippy::unnecessary_struct_initialization", + "clippy::unused_peekable", + "clippy::unused_rounding", "clippy::use_self", "clippy::useless_let_if_seq", - "clippy::useless_transmute", ], }, LintGroup { lint: Lint { label: "clippy::pedantic", - description: r##"lint group for: clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::implicit_clone, clippy::implicit_hasher, clippy::implicit_saturating_sub, clippy::inconsistent_struct_constructor, clippy::inefficient_to_string, clippy::inline_always, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_not_returning_iterator, clippy::large_digit_groups, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::let_underscore_drop, clippy::let_unit_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_ok_or, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::no_effect_underscore_binding, clippy::option_option, clippy::ptr_as_ptr, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::similar_names, clippy::single_match_else, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::trait_duplication_in_bounds, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::type_repetition_in_bounds, clippy::unicode_not_nfc, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, + description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, }, children: &[ - "clippy::await_holding_lock", - "clippy::await_holding_refcell_ref", + "clippy::bool_to_int_with_if", + "clippy::borrow_as_ptr", "clippy::case_sensitive_file_extension_comparisons", "clippy::cast_lossless", "clippy::cast_possible_truncation", @@ -7336,6 +13555,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::cloned_instead_of_copied", "clippy::copy_iterator", "clippy::default_trait_access", + "clippy::doc_link_with_quotes", "clippy::doc_markdown", "clippy::empty_enum", "clippy::enum_glob_use", @@ -7349,24 +13569,29 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::fn_params_excessive_bools", "clippy::from_iter_instead_of_collect", "clippy::if_not_else", + "clippy::ignored_unit_patterns", "clippy::implicit_clone", "clippy::implicit_hasher", - "clippy::implicit_saturating_sub", "clippy::inconsistent_struct_constructor", + "clippy::index_refutable_slice", "clippy::inefficient_to_string", "clippy::inline_always", + "clippy::into_iter_without_iter", "clippy::invalid_upcast_comparisons", "clippy::items_after_statements", "clippy::iter_not_returning_iterator", + "clippy::iter_without_into_iter", "clippy::large_digit_groups", + "clippy::large_futures", "clippy::large_stack_arrays", "clippy::large_types_passed_by_value", - "clippy::let_underscore_drop", - "clippy::let_unit_value", "clippy::linkedlist", "clippy::macro_use_imports", "clippy::manual_assert", + "clippy::manual_instant_elapsed", + "clippy::manual_let_else", "clippy::manual_ok_or", + "clippy::manual_string_new", "clippy::many_single_char_names", "clippy::map_unwrap_or", "clippy::match_bool", @@ -7375,7 +13600,9 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::match_wild_err_arm", "clippy::match_wildcard_for_single_variants", "clippy::maybe_infinite_iter", + "clippy::mismatching_type_param_order", "clippy::missing_errors_doc", + "clippy::missing_fields_in_debug", "clippy::missing_panics_doc", "clippy::module_name_repetitions", "clippy::must_use_candidate", @@ -7385,27 +13612,35 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::needless_continue", "clippy::needless_for_each", "clippy::needless_pass_by_value", + "clippy::needless_raw_string_hashes", "clippy::no_effect_underscore_binding", + "clippy::no_mangle_with_rust_abi", "clippy::option_option", "clippy::ptr_as_ptr", + "clippy::ptr_cast_constness", "clippy::range_minus_one", "clippy::range_plus_one", "clippy::redundant_closure_for_method_calls", "clippy::redundant_else", "clippy::ref_binding_to_reference", "clippy::ref_option_ref", + "clippy::return_self_not_must_use", "clippy::same_functions_in_if_condition", "clippy::semicolon_if_nothing_returned", + "clippy::should_panic_without_expect", "clippy::similar_names", "clippy::single_match_else", + "clippy::stable_sort_primitive", "clippy::string_add_assign", "clippy::struct_excessive_bools", "clippy::too_many_lines", - "clippy::trait_duplication_in_bounds", "clippy::transmute_ptr_to_ptr", "clippy::trivially_copy_pass_by_ref", - "clippy::type_repetition_in_bounds", + "clippy::unchecked_duration_subtraction", "clippy::unicode_not_nfc", + "clippy::uninlined_format_args", + "clippy::unnecessary_box_returns", + "clippy::unnecessary_join", "clippy::unnecessary_wraps", "clippy::unnested_or_patterns", "clippy::unreadable_literal", @@ -7421,29 +13656,33 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::perf", - description: r##"lint group for: clippy::box_collection, clippy::boxed_local, clippy::cmp_owned, clippy::expect_fun_call, clippy::extend_with_drain, clippy::format_in_format_args, clippy::iter_nth, clippy::large_const_arrays, clippy::large_enum_variant, clippy::manual_memcpy, clippy::manual_str_repeat, clippy::map_entry, clippy::mutex_atomic, clippy::needless_collect, clippy::or_fun_call, clippy::redundant_allocation, clippy::redundant_clone, clippy::single_char_pattern, clippy::slow_vector_initialization, clippy::stable_sort_primitive, clippy::to_string_in_format_args, clippy::unnecessary_to_owned, clippy::useless_vec, clippy::vec_init_then_push"##, + description: r##"lint group for: clippy::box_collection, clippy::box_default, clippy::boxed_local, clippy::cmp_owned, clippy::collapsible_str_replace, clippy::drain_collect, clippy::expect_fun_call, clippy::extend_with_drain, clippy::format_collect, clippy::format_in_format_args, clippy::iter_nth, clippy::iter_overeager_cloned, clippy::large_const_arrays, clippy::large_enum_variant, clippy::manual_memcpy, clippy::manual_retain, clippy::manual_str_repeat, clippy::manual_try_fold, clippy::map_entry, clippy::missing_spin_loop, clippy::redundant_allocation, clippy::result_large_err, clippy::single_char_pattern, clippy::slow_vector_initialization, clippy::to_string_in_format_args, clippy::unnecessary_to_owned, clippy::useless_vec, clippy::vec_init_then_push"##, }, children: &[ "clippy::box_collection", + "clippy::box_default", "clippy::boxed_local", "clippy::cmp_owned", + "clippy::collapsible_str_replace", + "clippy::drain_collect", "clippy::expect_fun_call", "clippy::extend_with_drain", + "clippy::format_collect", "clippy::format_in_format_args", "clippy::iter_nth", + "clippy::iter_overeager_cloned", "clippy::large_const_arrays", "clippy::large_enum_variant", "clippy::manual_memcpy", + "clippy::manual_retain", "clippy::manual_str_repeat", + "clippy::manual_try_fold", "clippy::map_entry", - "clippy::mutex_atomic", - "clippy::needless_collect", - "clippy::or_fun_call", + "clippy::missing_spin_loop", "clippy::redundant_allocation", - "clippy::redundant_clone", + "clippy::result_large_err", "clippy::single_char_pattern", "clippy::slow_vector_initialization", - "clippy::stable_sort_primitive", "clippy::to_string_in_format_args", "clippy::unnecessary_to_owned", "clippy::useless_vec", @@ -7453,17 +13692,30 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::restriction", - description: r##"lint group for: clippy::as_conversions, clippy::clone_on_ref_ptr, clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, clippy::default_numeric_fallback, clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::exit, clippy::expect_used, clippy::filetype_is_file, clippy::float_arithmetic, clippy::float_cmp_const, clippy::fn_to_numeric_cast_any, clippy::get_unwrap, clippy::if_then_some_else_none, clippy::implicit_return, clippy::indexing_slicing, clippy::inline_asm_x86_att_syntax, clippy::inline_asm_x86_intel_syntax, clippy::integer_arithmetic, clippy::integer_division, clippy::let_underscore_must_use, clippy::lossy_float_literal, clippy::map_err_ignore, clippy::mem_forget, clippy::missing_docs_in_private_items, clippy::missing_enforced_import_renames, clippy::missing_inline_in_public_items, clippy::mod_module_files, clippy::modulo_arithmetic, clippy::multiple_inherent_impl, clippy::non_ascii_literal, clippy::panic, clippy::panic_in_result_fn, clippy::pattern_type_mismatch, clippy::print_stderr, clippy::print_stdout, clippy::rc_buffer, clippy::rc_mutex, clippy::rest_pat_in_fully_bound_structs, clippy::same_name_method, clippy::self_named_module_files, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::str_to_string, clippy::string_add, clippy::string_slice, clippy::string_to_string, clippy::todo, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_self_imports, clippy::unneeded_field_pattern, clippy::unreachable, clippy::unseparated_literal_suffix, clippy::unwrap_in_result, clippy::unwrap_used, clippy::use_debug, clippy::verbose_file_reads, clippy::wildcard_enum_match_arm"##, + description: r##"lint group for: clippy::absolute_paths, clippy::alloc_instead_of_core, clippy::allow_attributes, clippy::allow_attributes_without_reason, clippy::arithmetic_side_effects, clippy::as_conversions, clippy::as_underscore, clippy::assertions_on_result_states, clippy::big_endian_bytes, clippy::clone_on_ref_ptr, clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, clippy::default_numeric_fallback, clippy::default_union_representation, clippy::deref_by_slicing, clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::empty_drop, clippy::empty_structs_with_brackets, clippy::error_impl_error, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::exit, clippy::expect_used, clippy::filetype_is_file, clippy::float_arithmetic, clippy::float_cmp_const, clippy::fn_to_numeric_cast_any, clippy::format_push_string, clippy::get_unwrap, clippy::host_endian_bytes, clippy::if_then_some_else_none, clippy::impl_trait_in_params, clippy::implicit_return, clippy::indexing_slicing, clippy::inline_asm_x86_att_syntax, clippy::inline_asm_x86_intel_syntax, clippy::integer_division, clippy::large_include_file, clippy::let_underscore_must_use, clippy::let_underscore_untyped, clippy::little_endian_bytes, clippy::lossy_float_literal, clippy::map_err_ignore, clippy::mem_forget, clippy::min_ident_chars, clippy::missing_assert_message, clippy::missing_asserts_for_indexing, clippy::missing_docs_in_private_items, clippy::missing_enforced_import_renames, clippy::missing_inline_in_public_items, clippy::missing_trait_methods, clippy::mixed_read_write_in_expression, clippy::mod_module_files, clippy::modulo_arithmetic, clippy::multiple_inherent_impl, clippy::multiple_unsafe_ops_per_block, clippy::mutex_atomic, clippy::needless_raw_strings, clippy::non_ascii_literal, clippy::panic, clippy::panic_in_result_fn, clippy::partial_pub_fields, clippy::pattern_type_mismatch, clippy::print_stderr, clippy::print_stdout, clippy::pub_use, clippy::pub_with_shorthand, clippy::pub_without_shorthand, clippy::question_mark_used, clippy::rc_buffer, clippy::rc_mutex, clippy::redundant_type_annotations, clippy::ref_patterns, clippy::rest_pat_in_fully_bound_structs, clippy::same_name_method, clippy::self_named_module_files, clippy::semicolon_inside_block, clippy::semicolon_outside_block, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::single_call_fn, clippy::single_char_lifetime_names, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::str_to_string, clippy::string_add, clippy::string_lit_chars_any, clippy::string_slice, clippy::string_to_string, clippy::suspicious_xor_used_as_pow, clippy::tests_outside_test_module, clippy::todo, clippy::try_err, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_safety_comment, clippy::unnecessary_safety_doc, clippy::unnecessary_self_imports, clippy::unneeded_field_pattern, clippy::unreachable, clippy::unseparated_literal_suffix, clippy::unwrap_in_result, clippy::unwrap_used, clippy::use_debug, clippy::verbose_file_reads, clippy::wildcard_enum_match_arm"##, }, children: &[ + "clippy::absolute_paths", + "clippy::alloc_instead_of_core", + "clippy::allow_attributes", + "clippy::allow_attributes_without_reason", + "clippy::arithmetic_side_effects", "clippy::as_conversions", + "clippy::as_underscore", + "clippy::assertions_on_result_states", + "clippy::big_endian_bytes", "clippy::clone_on_ref_ptr", "clippy::create_dir", "clippy::dbg_macro", "clippy::decimal_literal_representation", "clippy::default_numeric_fallback", + "clippy::default_union_representation", + "clippy::deref_by_slicing", "clippy::disallowed_script_idents", "clippy::else_if_without_else", + "clippy::empty_drop", + "clippy::empty_structs_with_brackets", + "clippy::error_impl_error", "clippy::exhaustive_enums", "clippy::exhaustive_structs", "clippy::exit", @@ -7472,46 +13724,78 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::float_arithmetic", "clippy::float_cmp_const", "clippy::fn_to_numeric_cast_any", + "clippy::format_push_string", "clippy::get_unwrap", + "clippy::host_endian_bytes", "clippy::if_then_some_else_none", + "clippy::impl_trait_in_params", "clippy::implicit_return", "clippy::indexing_slicing", "clippy::inline_asm_x86_att_syntax", "clippy::inline_asm_x86_intel_syntax", - "clippy::integer_arithmetic", "clippy::integer_division", + "clippy::large_include_file", "clippy::let_underscore_must_use", + "clippy::let_underscore_untyped", + "clippy::little_endian_bytes", "clippy::lossy_float_literal", "clippy::map_err_ignore", "clippy::mem_forget", + "clippy::min_ident_chars", + "clippy::missing_assert_message", + "clippy::missing_asserts_for_indexing", "clippy::missing_docs_in_private_items", "clippy::missing_enforced_import_renames", "clippy::missing_inline_in_public_items", + "clippy::missing_trait_methods", + "clippy::mixed_read_write_in_expression", "clippy::mod_module_files", "clippy::modulo_arithmetic", "clippy::multiple_inherent_impl", + "clippy::multiple_unsafe_ops_per_block", + "clippy::mutex_atomic", + "clippy::needless_raw_strings", "clippy::non_ascii_literal", "clippy::panic", "clippy::panic_in_result_fn", + "clippy::partial_pub_fields", "clippy::pattern_type_mismatch", "clippy::print_stderr", "clippy::print_stdout", + "clippy::pub_use", + "clippy::pub_with_shorthand", + "clippy::pub_without_shorthand", + "clippy::question_mark_used", "clippy::rc_buffer", "clippy::rc_mutex", + "clippy::redundant_type_annotations", + "clippy::ref_patterns", "clippy::rest_pat_in_fully_bound_structs", "clippy::same_name_method", "clippy::self_named_module_files", + "clippy::semicolon_inside_block", + "clippy::semicolon_outside_block", "clippy::separated_literal_suffix", "clippy::shadow_reuse", "clippy::shadow_same", "clippy::shadow_unrelated", + "clippy::single_call_fn", + "clippy::single_char_lifetime_names", + "clippy::std_instead_of_alloc", + "clippy::std_instead_of_core", "clippy::str_to_string", "clippy::string_add", + "clippy::string_lit_chars_any", "clippy::string_slice", "clippy::string_to_string", + "clippy::suspicious_xor_used_as_pow", + "clippy::tests_outside_test_module", "clippy::todo", + "clippy::try_err", "clippy::undocumented_unsafe_blocks", "clippy::unimplemented", + "clippy::unnecessary_safety_comment", + "clippy::unnecessary_safety_doc", "clippy::unnecessary_self_imports", "clippy::unneeded_field_pattern", "clippy::unreachable", @@ -7526,12 +13810,11 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::style", - description: r##"lint group for: clippy::assertions_on_constants, clippy::assign_op_pattern, clippy::blacklisted_name, clippy::blocks_in_if_conditions, clippy::bool_assert_comparison, clippy::borrow_interior_mutable_const, clippy::builtin_type_shadow, clippy::bytes_nth, clippy::chars_last_cmp, clippy::chars_next_cmp, clippy::cmp_null, clippy::collapsible_else_if, clippy::collapsible_if, clippy::collapsible_match, clippy::comparison_chain, clippy::comparison_to_empty, clippy::declare_interior_mutable_const, clippy::double_must_use, clippy::double_neg, clippy::duplicate_underscore_argument, clippy::enum_variant_names, clippy::excessive_precision, clippy::field_reassign_with_default, clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation, clippy::for_kv_map, clippy::from_over_into, clippy::from_str_radix_10, clippy::inconsistent_digit_grouping, clippy::infallible_destructuring_match, clippy::inherent_to_string, clippy::into_iter_on_ref, clippy::iter_cloned_collect, clippy::iter_next_slice, clippy::iter_nth_zero, clippy::iter_skip_next, clippy::just_underscores_and_digits, clippy::len_without_is_empty, clippy::len_zero, clippy::let_and_return, clippy::main_recursion, clippy::manual_async_fn, clippy::manual_map, clippy::manual_non_exhaustive, clippy::manual_range_contains, clippy::manual_saturating_arithmetic, clippy::map_clone, clippy::map_collect_result_unit, clippy::match_like_matches_macro, clippy::match_overlapping_arm, clippy::match_ref_pats, clippy::match_result_ok, clippy::mem_replace_option_with_none, clippy::mem_replace_with_default, clippy::missing_safety_doc, clippy::mixed_case_hex_literals, clippy::module_inception, clippy::must_use_unit, clippy::mut_mutex_lock, clippy::needless_borrow, clippy::needless_doctest_main, clippy::needless_late_init, clippy::needless_range_loop, clippy::needless_return, clippy::neg_multiply, clippy::new_ret_no_self, clippy::new_without_default, clippy::ok_expect, clippy::op_ref, clippy::option_map_or_none, clippy::print_literal, clippy::print_with_newline, clippy::println_empty_string, clippy::ptr_arg, clippy::ptr_eq, clippy::question_mark, clippy::redundant_closure, clippy::redundant_field_names, clippy::redundant_pattern, clippy::redundant_pattern_matching, clippy::redundant_static_lifetimes, clippy::result_map_or_into_option, clippy::result_unit_err, clippy::same_item_push, clippy::self_named_constructors, clippy::should_implement_trait, clippy::single_char_add_str, clippy::single_component_path_imports, clippy::single_match, clippy::string_extend_chars, clippy::tabs_in_doc_comments, clippy::to_digit_is_some, clippy::toplevel_ref_arg, clippy::try_err, clippy::unnecessary_fold, clippy::unnecessary_lazy_evaluations, clippy::unnecessary_mut_passed, clippy::unsafe_removed_from_name, clippy::unused_unit, clippy::unusual_byte_groupings, clippy::unwrap_or_else_default, clippy::upper_case_acronyms, clippy::while_let_on_iterator, clippy::write_literal, clippy::write_with_newline, clippy::writeln_empty_string, clippy::wrong_self_convention, clippy::zero_ptr"##, + description: r##"lint group for: clippy::assertions_on_constants, clippy::assign_op_pattern, clippy::blocks_in_if_conditions, clippy::bool_assert_comparison, clippy::borrow_interior_mutable_const, clippy::builtin_type_shadow, clippy::bytes_nth, clippy::chars_last_cmp, clippy::chars_next_cmp, clippy::cmp_null, clippy::collapsible_else_if, clippy::collapsible_if, clippy::collapsible_match, clippy::comparison_chain, clippy::comparison_to_empty, clippy::declare_interior_mutable_const, clippy::default_instead_of_iter_empty, clippy::disallowed_macros, clippy::disallowed_methods, clippy::disallowed_names, clippy::disallowed_types, clippy::double_must_use, clippy::double_neg, clippy::duplicate_underscore_argument, clippy::enum_variant_names, clippy::err_expect, clippy::excessive_precision, clippy::field_reassign_with_default, clippy::filter_map_bool_then, clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation, clippy::for_kv_map, clippy::from_over_into, clippy::from_str_radix_10, clippy::get_first, clippy::implicit_saturating_add, clippy::implicit_saturating_sub, clippy::inconsistent_digit_grouping, clippy::infallible_destructuring_match, clippy::inherent_to_string, clippy::init_numbered_fields, clippy::into_iter_on_ref, clippy::is_digit_ascii_radix, clippy::items_after_test_module, clippy::iter_cloned_collect, clippy::iter_next_slice, clippy::iter_nth_zero, clippy::iter_skip_next, clippy::just_underscores_and_digits, clippy::len_without_is_empty, clippy::len_zero, clippy::let_and_return, clippy::let_unit_value, clippy::main_recursion, clippy::manual_async_fn, clippy::manual_bits, clippy::manual_is_ascii_check, clippy::manual_is_finite, clippy::manual_is_infinite, clippy::manual_map, clippy::manual_next_back, clippy::manual_non_exhaustive, clippy::manual_range_contains, clippy::manual_saturating_arithmetic, clippy::manual_while_let_some, clippy::map_clone, clippy::map_collect_result_unit, clippy::match_like_matches_macro, clippy::match_overlapping_arm, clippy::match_ref_pats, clippy::match_result_ok, clippy::mem_replace_option_with_none, clippy::mem_replace_with_default, clippy::missing_safety_doc, clippy::mixed_case_hex_literals, clippy::module_inception, clippy::must_use_unit, clippy::mut_mutex_lock, clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::needless_doctest_main, clippy::needless_else, clippy::needless_late_init, clippy::needless_parens_on_range_literals, clippy::needless_pub_self, clippy::needless_range_loop, clippy::needless_return, clippy::needless_return_with_question_mark, clippy::neg_multiply, clippy::new_ret_no_self, clippy::new_without_default, clippy::non_minimal_cfg, clippy::obfuscated_if_else, clippy::ok_expect, clippy::op_ref, clippy::option_map_or_none, clippy::partialeq_to_none, clippy::print_literal, clippy::print_with_newline, clippy::println_empty_string, clippy::ptr_arg, clippy::ptr_eq, clippy::question_mark, clippy::redundant_closure, clippy::redundant_field_names, clippy::redundant_pattern, clippy::redundant_pattern_matching, clippy::redundant_static_lifetimes, clippy::result_map_or_into_option, clippy::result_unit_err, clippy::same_item_push, clippy::self_named_constructors, clippy::should_implement_trait, clippy::single_char_add_str, clippy::single_component_path_imports, clippy::single_match, clippy::string_extend_chars, clippy::tabs_in_doc_comments, clippy::to_digit_is_some, clippy::toplevel_ref_arg, clippy::trim_split_whitespace, clippy::unnecessary_fold, clippy::unnecessary_lazy_evaluations, clippy::unnecessary_mut_passed, clippy::unnecessary_owned_empty_strings, clippy::unsafe_removed_from_name, clippy::unused_unit, clippy::unusual_byte_groupings, clippy::unwrap_or_default, clippy::upper_case_acronyms, clippy::while_let_on_iterator, clippy::write_literal, clippy::write_with_newline, clippy::writeln_empty_string, clippy::wrong_self_convention, clippy::zero_ptr"##, }, children: &[ "clippy::assertions_on_constants", "clippy::assign_op_pattern", - "clippy::blacklisted_name", "clippy::blocks_in_if_conditions", "clippy::bool_assert_comparison", "clippy::borrow_interior_mutable_const", @@ -7546,21 +13829,34 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::comparison_chain", "clippy::comparison_to_empty", "clippy::declare_interior_mutable_const", + "clippy::default_instead_of_iter_empty", + "clippy::disallowed_macros", + "clippy::disallowed_methods", + "clippy::disallowed_names", + "clippy::disallowed_types", "clippy::double_must_use", "clippy::double_neg", "clippy::duplicate_underscore_argument", "clippy::enum_variant_names", + "clippy::err_expect", "clippy::excessive_precision", "clippy::field_reassign_with_default", + "clippy::filter_map_bool_then", "clippy::fn_to_numeric_cast", "clippy::fn_to_numeric_cast_with_truncation", "clippy::for_kv_map", "clippy::from_over_into", "clippy::from_str_radix_10", + "clippy::get_first", + "clippy::implicit_saturating_add", + "clippy::implicit_saturating_sub", "clippy::inconsistent_digit_grouping", "clippy::infallible_destructuring_match", "clippy::inherent_to_string", + "clippy::init_numbered_fields", "clippy::into_iter_on_ref", + "clippy::is_digit_ascii_radix", + "clippy::items_after_test_module", "clippy::iter_cloned_collect", "clippy::iter_next_slice", "clippy::iter_nth_zero", @@ -7569,12 +13865,19 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::len_without_is_empty", "clippy::len_zero", "clippy::let_and_return", + "clippy::let_unit_value", "clippy::main_recursion", "clippy::manual_async_fn", + "clippy::manual_bits", + "clippy::manual_is_ascii_check", + "clippy::manual_is_finite", + "clippy::manual_is_infinite", "clippy::manual_map", + "clippy::manual_next_back", "clippy::manual_non_exhaustive", "clippy::manual_range_contains", "clippy::manual_saturating_arithmetic", + "clippy::manual_while_let_some", "clippy::map_clone", "clippy::map_collect_result_unit", "clippy::match_like_matches_macro", @@ -7589,16 +13892,24 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::must_use_unit", "clippy::mut_mutex_lock", "clippy::needless_borrow", + "clippy::needless_borrows_for_generic_args", "clippy::needless_doctest_main", + "clippy::needless_else", "clippy::needless_late_init", + "clippy::needless_parens_on_range_literals", + "clippy::needless_pub_self", "clippy::needless_range_loop", "clippy::needless_return", + "clippy::needless_return_with_question_mark", "clippy::neg_multiply", "clippy::new_ret_no_self", "clippy::new_without_default", + "clippy::non_minimal_cfg", + "clippy::obfuscated_if_else", "clippy::ok_expect", "clippy::op_ref", "clippy::option_map_or_none", + "clippy::partialeq_to_none", "clippy::print_literal", "clippy::print_with_newline", "clippy::println_empty_string", @@ -7622,14 +13933,15 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::tabs_in_doc_comments", "clippy::to_digit_is_some", "clippy::toplevel_ref_arg", - "clippy::try_err", + "clippy::trim_split_whitespace", "clippy::unnecessary_fold", "clippy::unnecessary_lazy_evaluations", "clippy::unnecessary_mut_passed", + "clippy::unnecessary_owned_empty_strings", "clippy::unsafe_removed_from_name", "clippy::unused_unit", "clippy::unusual_byte_groupings", - "clippy::unwrap_or_else_default", + "clippy::unwrap_or_default", "clippy::upper_case_acronyms", "clippy::while_let_on_iterator", "clippy::write_literal", @@ -7642,25 +13954,58 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::suspicious", - description: r##"lint group for: clippy::blanket_clippy_restriction_lints, clippy::empty_loop, clippy::eval_order_dependence, clippy::float_equality_without_abs, clippy::for_loops_over_fallibles, clippy::misrefactored_assign_op, clippy::mut_range_bound, clippy::mutable_key_type, clippy::octal_escapes, clippy::return_self_not_must_use, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_unary_op_formatting"##, + description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::iter_out_of_bounds, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::type_id_on_box"##, }, children: &[ + "clippy::almost_complete_range", + "clippy::arc_with_non_send_sync", + "clippy::await_holding_invalid_type", + "clippy::await_holding_lock", + "clippy::await_holding_refcell_ref", "clippy::blanket_clippy_restriction_lints", + "clippy::cast_abs_to_unsigned", + "clippy::cast_enum_constructor", + "clippy::cast_enum_truncation", + "clippy::cast_nan_to_int", + "clippy::cast_slice_from_raw_parts", + "clippy::crate_in_macro_def", + "clippy::drop_non_drop", + "clippy::duplicate_mod", "clippy::empty_loop", - "clippy::eval_order_dependence", "clippy::float_equality_without_abs", - "clippy::for_loops_over_fallibles", + "clippy::forget_non_drop", + "clippy::four_forward_slashes", + "clippy::from_raw_with_void_ptr", + "clippy::iter_out_of_bounds", + "clippy::let_underscore_future", + "clippy::lines_filter_map_ok", + "clippy::maybe_misused_cfg", + "clippy::misnamed_getters", "clippy::misrefactored_assign_op", + "clippy::multi_assignments", "clippy::mut_range_bound", "clippy::mutable_key_type", + "clippy::no_effect_replace", + "clippy::non_canonical_clone_impl", + "clippy::non_canonical_partial_ord_impl", "clippy::octal_escapes", - "clippy::return_self_not_must_use", + "clippy::path_ends_with_ext", + "clippy::permissions_set_readonly_false", + "clippy::print_in_format_impl", + "clippy::rc_clone_in_vec_init", + "clippy::single_range_in_vec_init", + "clippy::size_of_ref", "clippy::suspicious_arithmetic_impl", "clippy::suspicious_assignment_formatting", + "clippy::suspicious_command_arg_space", + "clippy::suspicious_doc_comments", "clippy::suspicious_else_formatting", "clippy::suspicious_map", "clippy::suspicious_op_assign_impl", + "clippy::suspicious_to_owned", "clippy::suspicious_unary_op_formatting", + "clippy::swap_ptr_to_ref", + "clippy::type_id_on_box", ], }, ]; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index e475c5cd66b68..04263d15d0a5a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -68,22 +68,29 @@ pub struct FirstSegmentUnresolved { pub enum NameToImport { /// Requires items with names that exactly match the given string, bool indicates case-sensitivity. Exact(String, bool), - /// Requires items with names that case-insensitively contain all letters from the string, + /// Requires items with names that match the given string by prefix, bool indicates case-sensitivity. + Prefix(String, bool), + /// Requires items with names contain all letters from the string, /// in the same order, but not necessary adjacent. - Fuzzy(String), + Fuzzy(String, bool), } impl NameToImport { pub fn exact_case_sensitive(s: String) -> NameToImport { NameToImport::Exact(s, true) } -} -impl NameToImport { + pub fn fuzzy(s: String) -> NameToImport { + // unless all chars are lowercase, we do a case sensitive search + let case_sensitive = s.chars().any(|c| c.is_uppercase()); + NameToImport::Fuzzy(s, case_sensitive) + } + pub fn text(&self) -> &str { match self { - NameToImport::Exact(text, _) => text.as_str(), - NameToImport::Fuzzy(text) => text.as_str(), + NameToImport::Prefix(text, _) + | NameToImport::Exact(text, _) + | NameToImport::Fuzzy(text, _) => text.as_str(), } } } @@ -165,7 +172,7 @@ impl ImportAssets { Some(Self { import_candidate: ImportCandidate::TraitMethod(TraitImportCandidate { receiver_ty, - assoc_item_name: NameToImport::Fuzzy(fuzzy_method_name), + assoc_item_name: NameToImport::fuzzy(fuzzy_method_name), }), module_with_candidate: module_with_method_call, candidate_node, @@ -213,9 +220,10 @@ impl ImportAssets { sema: &Semantics<'_, RootDatabase>, prefix_kind: PrefixKind, prefer_no_std: bool, + prefer_prelude: bool, ) -> Vec { let _p = profile::span("import_assets::search_for_imports"); - self.search_for(sema, Some(prefix_kind), prefer_no_std) + self.search_for(sema, Some(prefix_kind), prefer_no_std, prefer_prelude) } /// This may return non-absolute paths if a part of the returned path is already imported into scope. @@ -223,17 +231,36 @@ impl ImportAssets { &self, sema: &Semantics<'_, RootDatabase>, prefer_no_std: bool, + prefer_prelude: bool, ) -> Vec { let _p = profile::span("import_assets::search_for_relative_paths"); - self.search_for(sema, None, prefer_no_std) + self.search_for(sema, None, prefer_no_std, prefer_prelude) + } + + /// Requires imports to by prefix instead of fuzzily. + pub fn path_fuzzy_name_to_prefix(&mut self) { + if let ImportCandidate::Path(PathImportCandidate { name: to_import, .. }) = + &mut self.import_candidate + { + let (name, case_sensitive) = match to_import { + NameToImport::Fuzzy(name, case_sensitive) => { + (std::mem::take(name), *case_sensitive) + } + _ => return, + }; + *to_import = NameToImport::Prefix(name, case_sensitive); + } } - pub fn path_fuzzy_name_to_exact(&mut self, case_sensitive: bool) { + /// Requires imports to match exactly instead of fuzzily. + pub fn path_fuzzy_name_to_exact(&mut self) { if let ImportCandidate::Path(PathImportCandidate { name: to_import, .. }) = &mut self.import_candidate { - let name = match to_import { - NameToImport::Fuzzy(name) => std::mem::take(name), + let (name, case_sensitive) = match to_import { + NameToImport::Fuzzy(name, case_sensitive) => { + (std::mem::take(name), *case_sensitive) + } _ => return, }; *to_import = NameToImport::Exact(name, case_sensitive); @@ -245,6 +272,7 @@ impl ImportAssets { sema: &Semantics<'_, RootDatabase>, prefixed: Option, prefer_no_std: bool, + prefer_prelude: bool, ) -> Vec { let _p = profile::span("import_assets::search_for"); @@ -256,6 +284,7 @@ impl ImportAssets { &self.module_with_candidate, prefixed, prefer_no_std, + prefer_prelude, ) }; @@ -569,11 +598,18 @@ fn get_mod_path( module_with_candidate: &Module, prefixed: Option, prefer_no_std: bool, + prefer_prelude: bool, ) -> Option { if let Some(prefix_kind) = prefixed { - module_with_candidate.find_use_path_prefixed(db, item_to_search, prefix_kind, prefer_no_std) + module_with_candidate.find_use_path_prefixed( + db, + item_to_search, + prefix_kind, + prefer_no_std, + prefer_prelude, + ) } else { - module_with_candidate.find_use_path(db, item_to_search, prefer_no_std) + module_with_candidate.find_use_path(db, item_to_search, prefer_no_std, prefer_prelude) } } @@ -623,7 +659,7 @@ impl ImportCandidate { fuzzy_name: String, sema: &Semantics<'_, RootDatabase>, ) -> Option { - path_import_candidate(sema, qualifier, NameToImport::Fuzzy(fuzzy_name)) + path_import_candidate(sema, qualifier, NameToImport::fuzzy(fuzzy_name)) } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs index 9be1d36634934..a0cfd3836ddf0 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs @@ -9,7 +9,7 @@ use syntax::{ algo, ast::{ self, edit_in_place::Removable, make, AstNode, HasAttrs, HasModuleItem, HasVisibility, - PathSegmentKind, + PathSegmentKind, UseTree, }, ted, Direction, NodeOrToken, SyntaxKind, SyntaxNode, }; @@ -157,6 +157,29 @@ impl ImportScope { /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { + insert_use_with_alias_option(scope, path, cfg, None); +} + +pub fn insert_use_as_alias(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { + let text: &str = "use foo as _"; + let parse = syntax::SourceFile::parse(text); + let node = parse + .tree() + .syntax() + .descendants() + .find_map(UseTree::cast) + .expect("Failed to make ast node `Rename`"); + let alias = node.rename(); + + insert_use_with_alias_option(scope, path, cfg, alias); +} + +fn insert_use_with_alias_option( + scope: &ImportScope, + path: ast::Path, + cfg: &InsertUseConfig, + alias: Option, +) { let _p = profile::span("insert_use"); let mut mb = match cfg.granularity { ImportGranularity::Crate => Some(MergeBehavior::Crate), @@ -176,7 +199,8 @@ pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { } let use_item = - make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update(); + make::use_(None, make::use_tree(path.clone(), None, alias, false)).clone_for_update(); + // merge into existing imports if possible if let Some(mb) = mb { let filter = |it: &_| !(cfg.skip_glob_imports && ast::Use::is_simple_glob(it)); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs index b92e367f7e12a..01d2f1970c38e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs @@ -993,6 +993,46 @@ use foo::bar::qux; ); } +#[test] +fn insert_with_renamed_import_simple_use() { + check_with_config( + "use self::foo::Foo", + r#" +use self::foo::Foo as _; +"#, + r#" +use self::foo::Foo; +"#, + &InsertUseConfig { + granularity: ImportGranularity::Crate, + prefix_kind: hir::PrefixKind::BySelf, + enforce_granularity: true, + group: true, + skip_glob_imports: true, + }, + ); +} + +#[test] +fn insert_with_renamed_import_complex_use() { + check_with_config( + "use self::foo::Foo;", + r#" +use self::foo::{self, Foo as _, Bar}; +"#, + r#" +use self::foo::{self, Foo, Bar}; +"#, + &InsertUseConfig { + granularity: ImportGranularity::Crate, + prefix_kind: hir::PrefixKind::BySelf, + enforce_granularity: true, + group: true, + skip_glob_imports: true, + }, + ); +} + fn check_with_config( path: &str, ra_fixture_before: &str, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs index 27b6321f3a7a5..ff84e9ffaeec7 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs @@ -78,6 +78,10 @@ fn try_merge_trees_mut(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehav { lhs.split_prefix(&lhs_prefix); rhs.split_prefix(&rhs_prefix); + } else { + ted::replace(lhs.syntax(), rhs.syntax()); + // we can safely return here, in this case `recursive_merge` doesn't do anything + return Some(()); } recursive_merge(lhs, rhs, merge) } @@ -123,6 +127,13 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) // so they need to be handled explicitly .or_else(|| tree.star_token().map(|_| false)) }; + + if lhs_t.rename().and_then(|x| x.underscore_token()).is_some() { + ted::replace(lhs_t.syntax(), rhs_t.syntax()); + *lhs_t = rhs_t; + continue; + } + match (tree_contains_self(lhs_t), tree_contains_self(&rhs_t)) { (Some(true), None) => continue, (None, Some(true)) => { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs index 3f7a3ec2d0fd8..67ed44f08b7f7 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs @@ -31,26 +31,34 @@ pub fn items_with_name<'a>( ) }); + let prefix = matches!(name, NameToImport::Prefix(..)); let (mut local_query, mut external_query) = match name { - NameToImport::Exact(exact_name, case_sensitive) => { + NameToImport::Prefix(exact_name, case_sensitive) + | NameToImport::Exact(exact_name, case_sensitive) => { let mut local_query = symbol_index::Query::new(exact_name.clone()); - local_query.exact(); - - let external_query = import_map::Query::new(exact_name); - - ( - local_query, - if case_sensitive { external_query.case_sensitive() } else { external_query }, - ) + let mut external_query = import_map::Query::new(exact_name); + if prefix { + local_query.prefix(); + external_query = external_query.prefix(); + } else { + local_query.exact(); + external_query = external_query.exact(); + } + if case_sensitive { + local_query.case_sensitive(); + external_query = external_query.case_sensitive(); + } + (local_query, external_query) } - NameToImport::Fuzzy(fuzzy_search_string) => { + NameToImport::Fuzzy(fuzzy_search_string, case_sensitive) => { let mut local_query = symbol_index::Query::new(fuzzy_search_string.clone()); + local_query.fuzzy(); let mut external_query = import_map::Query::new(fuzzy_search_string.clone()) .fuzzy() .assoc_search_mode(assoc_item_search); - if fuzzy_search_string.to_lowercase() != fuzzy_search_string { + if case_sensitive { local_query.case_sensitive(); external_query = external_query.case_sensitive(); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs index fb75b5b458482..fa9339f30f206 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs @@ -277,6 +277,7 @@ impl Ctx<'_> { self.source_scope.db.upcast(), hir::ModuleDef::Trait(trait_ref), false, + true, )?; match make::ty_path(mod_path_to_ast(&found_path)) { ast::Type::PathType(path_ty) => Some(path_ty), @@ -311,8 +312,12 @@ impl Ctx<'_> { } } - let found_path = - self.target_module.find_use_path(self.source_scope.db.upcast(), def, false)?; + let found_path = self.target_module.find_use_path( + self.source_scope.db.upcast(), + def, + false, + true, + )?; let res = mod_path_to_ast(&found_path).clone_for_update(); if let Some(args) = path.segment().and_then(|it| it.generic_arg_list()) { if let Some(segment) = res.segment() { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 9c4f0ac8c9fc4..22438a203bd78 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -584,7 +584,7 @@ impl<'a> FindUsages<'a> { ) -> bool { match NameRefClass::classify(self.sema, name_ref) { Some(NameRefClass::Definition(Definition::SelfType(impl_))) - if impl_.self_ty(self.sema.db) == *self_ty => + if impl_.self_ty(self.sema.db).as_adt() == self_ty.as_adt() => { let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); let reference = FileReference { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs index 39763479c65a2..c7188f1f7943b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs @@ -140,10 +140,10 @@ impl SnippetEdit { .with_position() .map(|pos| { let (snippet, index) = match pos { - itertools::Position::First(it) | itertools::Position::Middle(it) => it, + (itertools::Position::First, it) | (itertools::Position::Middle, it) => it, // last/only snippet gets index 0 - itertools::Position::Last((snippet, _)) - | itertools::Position::Only((snippet, _)) => (snippet, 0), + (itertools::Position::Last, (snippet, _)) + | (itertools::Position::Only, (snippet, _)) => (snippet, 0), }; let range = match snippet { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs index f699f999baf76..3e89159c2c6e5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs @@ -43,13 +43,20 @@ use triomphe::Arc; use crate::RootDatabase; +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum SearchMode { + Fuzzy, + Exact, + Prefix, +} + #[derive(Debug)] pub struct Query { query: String, lowercased: String, only_types: bool, libs: bool, - exact: bool, + mode: SearchMode, case_sensitive: bool, limit: usize, } @@ -62,7 +69,7 @@ impl Query { lowercased, only_types: false, libs: false, - exact: false, + mode: SearchMode::Fuzzy, case_sensitive: false, limit: usize::max_value(), } @@ -76,8 +83,16 @@ impl Query { self.libs = true; } + pub fn fuzzy(&mut self) { + self.mode = SearchMode::Fuzzy; + } + pub fn exact(&mut self) { - self.exact = true; + self.mode = SearchMode::Exact; + } + + pub fn prefix(&mut self) { + self.mode = SearchMode::Prefix; } pub fn case_sensitive(&mut self) { @@ -329,13 +344,23 @@ impl Query { { continue; } - if self.exact { - if symbol.name != self.query { - continue; + let skip = match self.mode { + SearchMode::Fuzzy => { + self.case_sensitive + && self.query.chars().any(|c| !symbol.name.contains(c)) } - } else if self.case_sensitive - && self.query.chars().any(|c| !symbol.name.contains(c)) - { + SearchMode::Exact => symbol.name != self.query, + SearchMode::Prefix if self.case_sensitive => { + !symbol.name.starts_with(&self.query) + } + SearchMode::Prefix => symbol + .name + .chars() + .zip(self.lowercased.chars()) + .all(|(n, q)| n.to_lowercase().next() == Some(q)), + }; + + if skip { continue; } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs index c7d5f3613d4bc..c8cf87d3c2052 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs @@ -1,4 +1,5 @@ -//! Generates descriptors structure for unstable feature from Unstable Book +//! Generates descriptor structures for unstable features from the unstable book +//! and lints from rustc, rustdoc, and clippy. use std::{borrow::Cow, fs, path::Path}; use itertools::Itertools; @@ -6,6 +7,8 @@ use stdx::format_to; use test_utils::project_root; use xshell::{cmd, Shell}; +const DESTINATION: &str = "crates/ide-db/src/generated/lints.rs"; + /// This clones rustc repo, and so is not worth to keep up-to-date. We update /// manually by un-ignoring the test from time to time. #[test] @@ -14,11 +17,21 @@ fn sourcegen_lint_completions() { let sh = &Shell::new().unwrap(); let rust_repo = project_root().join("./target/rust"); - if !rust_repo.exists() { + if rust_repo.exists() { + cmd!(sh, "git -C {rust_repo} pull --rebase").run().unwrap(); + } else { cmd!(sh, "git clone --depth=1 https://github.com/rust-lang/rust {rust_repo}") .run() .unwrap(); } + // need submodules for Cargo to parse the workspace correctly + cmd!( + sh, + "git -C {rust_repo} submodule update --init --recursive --depth=1 -- + compiler library src/tools" + ) + .run() + .unwrap(); let mut contents = String::from( r" @@ -27,17 +40,28 @@ pub struct Lint { pub label: &'static str, pub description: &'static str, } + pub struct LintGroup { pub lint: Lint, pub children: &'static [&'static str], } + ", ); generate_lint_descriptor(sh, &mut contents); contents.push('\n'); - generate_feature_descriptor(&mut contents, &rust_repo.join("src/doc/unstable-book/src")); + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); + let unstable_book = project_root().join("./target/unstable-book-gen"); + cmd!( + sh, + "{cargo} run --manifest-path {rust_repo}/src/tools/unstable-book-gen/Cargo.toml -- + {rust_repo}/library {rust_repo}/compiler {rust_repo}/src {unstable_book}" + ) + .run() + .unwrap(); + generate_feature_descriptor(&mut contents, &unstable_book.join("src")); contents.push('\n'); let lints_json = project_root().join("./target/clippy_lints.json"); @@ -51,41 +75,60 @@ pub struct LintGroup { let contents = sourcegen::add_preamble("sourcegen_lints", sourcegen::reformat(contents)); - let destination = project_root().join("crates/ide_db/src/generated/lints.rs"); + let destination = project_root().join(DESTINATION); sourcegen::ensure_file_contents(destination.as_path(), &contents); } +/// Parses the output of `rustdoc -Whelp` and prints `Lint` and `LintGroup` constants into `buf`. +/// +/// As of writing, the output of `rustc -Whelp` (not rustdoc) has the following format: +/// +/// ```text +/// Lint checks provided by rustc: +/// +/// name default meaning +/// ---- ------- ------- +/// +/// ... +/// +/// Lint groups provided by rustc: +/// +/// name sub-lints +/// ---- --------- +/// +/// ... +/// ``` +/// +/// `rustdoc -Whelp` (and any other custom `rustc` driver) adds another two +/// tables after the `rustc` ones, with a different title but the same format. fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { - // FIXME: rustdoc currently requires an input file for -Whelp cc https://github.com/rust-lang/rust/pull/88831 - let file = project_root().join(file!()); - let stdout = cmd!(sh, "rustdoc -W help {file}").read().unwrap(); - let start_lints = stdout.find("---- ------- -------").unwrap(); - let start_lint_groups = stdout.find("---- ---------").unwrap(); - let start_lints_rustdoc = - stdout.find("Lint checks provided by plugins loaded by this crate:").unwrap(); - let start_lint_groups_rustdoc = - stdout.find("Lint groups provided by plugins loaded by this crate:").unwrap(); + let stdout = cmd!(sh, "rustdoc -Whelp").read().unwrap(); + let lints_pat = "---- ------- -------\n"; + let lint_groups_pat = "---- ---------\n"; + let lints = find_and_slice(&stdout, lints_pat); + let lint_groups = find_and_slice(lints, lint_groups_pat); + let lints_rustdoc = find_and_slice(lint_groups, lints_pat); + let lint_groups_rustdoc = find_and_slice(lints_rustdoc, lint_groups_pat); buf.push_str(r#"pub const DEFAULT_LINTS: &[Lint] = &["#); buf.push('\n'); - let lints = stdout[start_lints..].lines().skip(1).take_while(|l| !l.is_empty()).map(|line| { + let lints = lints.lines().take_while(|l| !l.is_empty()).map(|line| { let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); let (_default_level, description) = rest.trim().split_once(char::is_whitespace).unwrap(); (name.trim(), Cow::Borrowed(description.trim()), vec![]) }); - let lint_groups = - stdout[start_lint_groups..].lines().skip(1).take_while(|l| !l.is_empty()).map(|line| { - let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); - ( - name.trim(), - format!("lint group for: {}", lints.trim()).into(), - lints - .split_ascii_whitespace() - .map(|s| s.trim().trim_matches(',').replace('-', "_")) - .collect(), - ) - }); + let lint_groups = lint_groups.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); + ( + name.trim(), + format!("lint group for: {}", lints.trim()).into(), + lints + .split_ascii_whitespace() + .map(|s| s.trim().trim_matches(',').replace('-', "_")) + .collect(), + ) + }); let lints = lints .chain(lint_groups) @@ -94,7 +137,8 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { for (name, description, ..) in &lints { push_lint_completion(buf, &name.replace('-', "_"), description); } - buf.push_str("];\n"); + buf.push_str("];\n\n"); + buf.push_str(r#"pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &["#); for (name, description, children) in &lints { if !children.is_empty() { @@ -115,27 +159,23 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { buf.push_str(r#"pub const RUSTDOC_LINTS: &[Lint] = &["#); buf.push('\n'); - let lints_rustdoc = - stdout[start_lints_rustdoc..].lines().skip(2).take_while(|l| !l.is_empty()).map(|line| { - let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); - let (_default_level, description) = - rest.trim().split_once(char::is_whitespace).unwrap(); - (name.trim(), Cow::Borrowed(description.trim()), vec![]) - }); + let lints_rustdoc = lints_rustdoc.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); + let (_default_level, description) = rest.trim().split_once(char::is_whitespace).unwrap(); + (name.trim(), Cow::Borrowed(description.trim()), vec![]) + }); let lint_groups_rustdoc = - stdout[start_lint_groups_rustdoc..].lines().skip(2).take_while(|l| !l.is_empty()).map( - |line| { - let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); - ( - name.trim(), - format!("lint group for: {}", lints.trim()).into(), - lints - .split_ascii_whitespace() - .map(|s| s.trim().trim_matches(',').replace('-', "_")) - .collect(), - ) - }, - ); + lint_groups_rustdoc.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); + ( + name.trim(), + format!("lint group for: {}", lints.trim()).into(), + lints + .split_ascii_whitespace() + .map(|s| s.trim().trim_matches(',').replace('-', "_")) + .collect(), + ) + }); let lints_rustdoc = lints_rustdoc .chain(lint_groups_rustdoc) @@ -145,7 +185,7 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { for (name, description, ..) in &lints_rustdoc { push_lint_completion(buf, &name.replace('-', "_"), description) } - buf.push_str("];\n"); + buf.push_str("];\n\n"); buf.push_str(r#"pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &["#); for (name, description, children) in &lints_rustdoc { @@ -157,14 +197,24 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { buf.push_str("];\n"); } +#[track_caller] +fn find_and_slice<'a>(i: &'a str, p: &str) -> &'a str { + let idx = i.find(p).unwrap(); + &i[idx + p.len()..] +} + +/// Parses the unstable book `src_dir` and prints a constant with the list of +/// unstable features into `buf`. +/// +/// It does this by looking for all `.md` files in the `language-features` and +/// `library-features` directories, and using the file name as the feature +/// name, and the file contents as the feature description. fn generate_feature_descriptor(buf: &mut String, src_dir: &Path) { let mut features = ["language-features", "library-features"] .into_iter() .flat_map(|it| sourcegen::list_files(&src_dir.join(it))) - .filter(|path| { - // Get all `.md ` files - path.extension().unwrap_or_default().to_str().unwrap_or_default() == "md" - }) + // Get all `.md` files + .filter(|path| path.extension() == Some("md".as_ref())) .map(|path| { let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace('-', "_"); let doc = fs::read_to_string(path).unwrap(); @@ -196,7 +246,7 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) { let mut clippy_lints: Vec = Vec::new(); let mut clippy_groups: std::collections::BTreeMap> = Default::default(); - for line in file_content.lines().map(|line| line.trim()) { + for line in file_content.lines().map(str::trim) { if let Some(line) = line.strip_prefix(r#""id": ""#) { let clippy_lint = ClippyLint { id: line.strip_suffix(r#"","#).expect("should be suffixed by comma").into(), @@ -211,12 +261,19 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) { .push(clippy_lints.last().unwrap().id.clone()); } } else if let Some(line) = line.strip_prefix(r#""docs": ""#) { - let prefix_to_strip = r#" ### What it does"#; - let line = match line.strip_prefix(prefix_to_strip) { - Some(line) => line, + let header = "### What it does"; + let line = match line.find(header) { + Some(idx) => &line[idx + header.len()..], None => { - eprintln!("unexpected clippy prefix for {}", clippy_lints.last().unwrap().id); - continue; + let id = &clippy_lints.last().unwrap().id; + // these just don't have the common header + let allowed = ["allow_attributes", "read_line_without_trim"]; + if allowed.contains(&id.as_str()) { + line + } else { + eprintln!("\nunexpected clippy prefix for {id}, line={line:?}\n",); + continue; + } } }; // Only take the description, any more than this is a lot of additional data we would embed into the exe diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml index 14aa3940199ab..f4055024cc32c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml @@ -13,9 +13,9 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" -either = "1.7.0" -itertools = "0.10.5" -serde_json = "1.0.86" +either.workspace = true +itertools.workspace = true +serde_json.workspace = true once_cell = "1.17.0" # local deps diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs index 3b69640af9b81..9ed8199ae4d0c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs @@ -166,7 +166,7 @@ fn main() { check_diagnostics( r#" struct A { a: &'static str } -fn f(a: A) { let A { a: hello } = a; } +fn f(a: A) { let A { a: _hello } = a; } "#, ); check_diagnostics( @@ -181,12 +181,14 @@ fn f(a: A) { let A { 0: 0 } = a; } struct A { a: &'static str } fn f(a: A) { let A { a$0: a } = a; + _ = a; } "#, r#" struct A { a: &'static str } fn f(a: A) { let A { a } = a; + _ = a; } "#, ); @@ -196,12 +198,14 @@ fn f(a: A) { struct A { a: &'static str, b: &'static str } fn f(a: A) { let A { a$0: a, b } = a; + _ = (a, b); } "#, r#" struct A { a: &'static str, b: &'static str } fn f(a: A) { let A { a, b } = a; + _ = (a, b); } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs index 235062bf531fe..0f12e814ba39d 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -111,6 +111,31 @@ fn some_fn() { let what_aweird_formatting = 10; another_func(what_aweird_formatting); } +"#, + ); + + check_fix( + r#" +static S: i32 = M::A; + +mod $0M { + pub const A: i32 = 10; +} + +mod other { + use crate::M::A; +} +"#, + r#" +static S: i32 = m::A; + +mod m { + pub const A: i32 = 10; +} + +mod other { + use crate::m::A; +} "#, ); } @@ -175,10 +200,10 @@ fn NonSnakeCaseName() {} fn incorrect_function_params() { check_diagnostics( r#" -fn foo(SomeParam: u8) {} +fn foo(SomeParam: u8) { _ = SomeParam; } // ^^^^^^^^^ 💡 warn: Parameter `SomeParam` should have snake_case name, e.g. `some_param` -fn foo2(ok_param: &str, CAPS_PARAM: u8) {} +fn foo2(ok_param: &str, CAPS_PARAM: u8) { _ = (ok_param, CAPS_PARAM); } // ^^^^^^^^^^ 💡 warn: Parameter `CAPS_PARAM` should have snake_case name, e.g. `caps_param` "#, ); @@ -188,6 +213,7 @@ fn foo2(ok_param: &str, CAPS_PARAM: u8) {} fn incorrect_variable_names() { check_diagnostics( r#" +#[allow(unused)] fn foo() { let SOME_VALUE = 10; // ^^^^^^^^^^ 💡 warn: Variable `SOME_VALUE` should have snake_case name, e.g. `some_value` @@ -294,6 +320,7 @@ impl someStruct { // ^^^^^^^^ 💡 warn: Function `SomeFunc` should have snake_case name, e.g. `some_func` let WHY_VAR_IS_CAPS = 10; // ^^^^^^^^^^^^^^^ 💡 warn: Variable `WHY_VAR_IS_CAPS` should have snake_case name, e.g. `why_var_is_caps` + _ = WHY_VAR_IS_CAPS; } } "#, @@ -306,6 +333,7 @@ impl someStruct { r#" enum Option { Some, None } +#[allow(unused)] fn main() { match Option::None { None => (), @@ -322,6 +350,7 @@ fn main() { r#" enum Option { Some, None } +#[allow(unused)] fn main() { match Option::None { SOME_VAR @ None => (), @@ -349,7 +378,9 @@ enum E { } mod F { - fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {} + fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) { + _ = BAD_NAME_HI; + } } "#, ); @@ -395,7 +426,7 @@ fn qualify() { #[test] // Issue #8809. fn parenthesized_parameter() { - check_diagnostics(r#"fn f((O): _) {}"#) + check_diagnostics(r#"fn f((O): _) { _ = O; }"#) } #[test] @@ -472,7 +503,9 @@ mod CheckBadStyle { mod F { #![allow(non_snake_case)] - fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) {} + fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) { + _ = BAD_NAME_HI; + } } #[allow(non_snake_case, non_camel_case_types)] @@ -510,17 +543,20 @@ fn NonSnakeCaseName(some_var: u8) -> u8 { #[deny(nonstandard_style)] mod CheckNonstandardStyle { + //^^^^^^^^^^^^^^^^^^^^^ 💡 error: Module `CheckNonstandardStyle` should have snake_case name, e.g. `check_nonstandard_style` fn HiImABadFnName() {} //^^^^^^^^^^^^^^ 💡 error: Function `HiImABadFnName` should have snake_case name, e.g. `hi_im_abad_fn_name` } #[deny(warnings)] mod CheckBadStyle { + //^^^^^^^^^^^^^ 💡 error: Module `CheckBadStyle` should have snake_case name, e.g. `check_bad_style` struct fooo; //^^^^ 💡 error: Structure `fooo` should have CamelCase name, e.g. `Fooo` } mod F { + //^ 💡 warn: Module `F` should have snake_case name, e.g. `f` #![deny(non_snake_case)] fn CheckItWorksWithModAttr() {} //^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: Function `CheckItWorksWithModAttr` should have snake_case name, e.g. `check_it_works_with_mod_attr` @@ -563,12 +599,12 @@ fn main() { //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` fn BAZ() { //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` - let INNER_INNER = 42; - //^^^^^^^^^^^ 💡 warn: Variable `INNER_INNER` should have snake_case name, e.g. `inner_inner` + let _INNER_INNER = 42; + //^^^^^^^^^^^^ 💡 warn: Variable `_INNER_INNER` should have snake_case name, e.g. `_inner_inner` } - let INNER_LOCAL = 42; - //^^^^^^^^^^^ 💡 warn: Variable `INNER_LOCAL` should have snake_case name, e.g. `inner_local` + let _INNER_LOCAL = 42; + //^^^^^^^^^^^^ 💡 warn: Variable `_INNER_LOCAL` should have snake_case name, e.g. `_inner_local` } } "#, @@ -641,4 +677,30 @@ enum E { "#, ); } + + #[test] + fn module_name_inline() { + check_diagnostics( + r#" +mod M { + //^ 💡 warn: Module `M` should have snake_case name, e.g. `m` + mod IncorrectCase {} + //^^^^^^^^^^^^^ 💡 warn: Module `IncorrectCase` should have snake_case name, e.g. `incorrect_case` +} +"#, + ); + } + + #[test] + fn module_name_decl() { + check_diagnostics( + r#" +//- /Foo.rs + +//- /main.rs +mod Foo; + //^^^ 💡 warn: Module `Foo` should have snake_case name, e.g. `foo` +"#, + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs index a337e2660d6a6..659b74445f8fe 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs @@ -136,6 +136,7 @@ pub(crate) fn json_in_items( it, config.insert_use.prefix_kind, config.prefer_no_std, + config.prefer_prelude, ) { insert_use(&scope, mod_path_to_ast(&it), &config.insert_use); } @@ -148,6 +149,7 @@ pub(crate) fn json_in_items( it, config.insert_use.prefix_kind, config.prefer_no_std, + config.prefer_prelude, ) { insert_use(&scope, mod_path_to_ast(&it), &config.insert_use); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 8265e0b1c117a..06ba13bcc55c4 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -23,12 +23,7 @@ pub(crate) fn mismatched_tuple_struct_pat_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0023"), message, - invalid_args_range( - ctx, - d.expr_or_pat.clone().map(|it| it.either(Into::into, Into::into)), - d.expected, - d.found, - ), + invalid_args_range(ctx, d.expr_or_pat.clone().map(Into::into), d.expected, d.found), ) } @@ -131,7 +126,7 @@ fn f() { zero(); } fn simple_free_fn_one() { check_diagnostics( r#" -fn one(arg: u8) {} +fn one(_arg: u8) {} fn f() { one(); } //^^ error: expected 1 argument, found 0 "#, @@ -139,7 +134,7 @@ fn f() { one(); } check_diagnostics( r#" -fn one(arg: u8) {} +fn one(_arg: u8) {} fn f() { one(1); } "#, ); @@ -176,7 +171,7 @@ fn f() { check_diagnostics( r#" struct S; -impl S { fn method(&self, arg: u8) {} } +impl S { fn method(&self, _arg: u8) {} } fn f() { S.method(); @@ -187,7 +182,7 @@ impl S { fn method(&self, arg: u8) {} } check_diagnostics( r#" struct S; -impl S { fn method(&self, arg: u8) {} } +impl S { fn method(&self, _arg: u8) {} } fn f() { S::method(&S, 0); @@ -335,8 +330,8 @@ struct S; impl S { fn method(#[cfg(NEVER)] self) {} - fn method2(#[cfg(NEVER)] self, arg: u8) {} - fn method3(self, #[cfg(NEVER)] arg: u8) {} + fn method2(#[cfg(NEVER)] self, _arg: u8) {} + fn method3(self, #[cfg(NEVER)] _arg: u8) {} } extern "C" { @@ -365,8 +360,8 @@ fn main() { r#" #[rustc_legacy_const_generics(1, 3)] fn mixed( - a: u8, - b: i8, + _a: u8, + _b: i8, ) {} fn f() { @@ -376,8 +371,8 @@ fn f() { #[rustc_legacy_const_generics(1, 3)] fn b( - a: u8, - b: u8, + _a: u8, + _b: u8, ) {} fn g() { @@ -403,7 +398,7 @@ fn f( // ^^ error: this pattern has 0 fields, but the corresponding tuple struct has 2 fields S(e, f, .., g, d): S // ^^^^^^^^^ error: this pattern has 4 fields, but the corresponding tuple struct has 2 fields -) {} +) { _ = (a, b, c, d, e, f, g); } "#, ) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index acc31cd117adb..d7dca1083a076 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -39,7 +39,7 @@ pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingField d.field_list_parent_path .clone() .map(SyntaxNodePtr::from) - .unwrap_or_else(|| d.field_list_parent.clone().either(|it| it.into(), |it| it.into())), + .unwrap_or_else(|| d.field_list_parent.clone().into()), ); Diagnostic::new_with_syntax_node_ptr(ctx, DiagnosticCode::RustcHardError("E0063"), message, ptr) @@ -58,10 +58,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option ctx.sema.scope(ptr.to_node(&root).syntax()).map(|it| it.module()), - Either::Right(ptr) => ctx.sema.scope(ptr.to_node(&root).syntax()).map(|it| it.module()), - }; + let current_module = + ctx.sema.scope(d.field_list_parent.to_node(&root).syntax()).map(|it| it.module()); let build_text_edit = |parent_syntax, new_syntax: &SyntaxNode, old_syntax| { let edit = { @@ -87,9 +85,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option { - let field_list_parent = record_expr.to_node(&root); + match &d.field_list_parent.to_node(&root) { + Either::Left(field_list_parent) => { let missing_fields = ctx.sema.record_literal_missing_fields(&field_list_parent); let mut locals = FxHashMap::default(); @@ -125,6 +122,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option, d: &hir::MissingFields) -> Option { - let field_list_parent = record_pat.to_node(&root); + Either::Right(field_list_parent) => { let missing_fields = ctx.sema.record_pattern_missing_fields(&field_list_parent); let old_field_list = field_list_parent.record_pat_field_list()?; @@ -290,6 +287,7 @@ fn x(a: S) { struct S { s: u32 } fn x(a: S) { let S { ref s } = a; + _ = s; } ", ) @@ -626,7 +624,7 @@ struct TestStruct { one: i32, two: i64 } fn test_fn() { let one = 1; - let s = TestStruct{ one, two: 2 }; + let _s = TestStruct{ one, two: 2 }; } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs index 06b03d3d19891..ef6a273ed8e65 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs @@ -17,13 +17,31 @@ pub(crate) fn missing_match_arms( #[cfg(test)] mod tests { - use crate::tests::check_diagnostics; + use crate::{ + tests::{check_diagnostics, check_diagnostics_with_config}, + DiagnosticsConfig, + }; + #[track_caller] fn check_diagnostics_no_bails(ra_fixture: &str) { cov_mark::check_count!(validate_match_bailed_out, 0); crate::tests::check_diagnostics(ra_fixture) } + #[test] + fn empty_body() { + let mut config = DiagnosticsConfig::test_sample(); + config.disabled.insert("syntax-error".to_string()); + check_diagnostics_with_config( + config, + r#" +fn main() { + match 0; +} +"#, + ); + } + #[test] fn empty_tuple() { check_diagnostics_no_bails( @@ -564,6 +582,7 @@ fn bang(never: !) { r#" enum Option { Some(T), None } +#[allow(unused)] fn main() { // `Never` is deliberately not defined so that it's an uninferred type. match Option::::None { @@ -719,7 +738,7 @@ fn main() { r#" struct S { a: char} fn main(v: S) { - match v { S{ a } => {} } + match v { S{ a } => { _ = a; } } match v { S{ a: _x } => {} } match v { S{ a: 'a' } => {} } match v { S{..} => {} } @@ -901,7 +920,7 @@ enum E{ A, B } fn foo() { match &E::A { E::A => {} - x => {} + _x => {} } }", ); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs index 70b26009bae0b..0f695b2745a8a 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs @@ -100,9 +100,9 @@ mod tests { r#" fn main() { let x = &5 as *const usize; - unsafe { let y = *x; } - let z = *x; -} //^^💡 error: this operation is unsafe and requires an unsafe function or block + unsafe { let _y = *x; } + let _z = *x; +} //^^💡 error: this operation is unsafe and requires an unsafe function or block "#, ) } @@ -116,13 +116,13 @@ struct HasUnsafe; impl HasUnsafe { unsafe fn unsafe_fn(&self) { let x = &5 as *const usize; - let y = *x; + let _y = *x; } } unsafe fn unsafe_fn() { let x = &5 as *const usize; - let y = *x; + let _y = *x; } fn main() { @@ -152,10 +152,10 @@ struct Ty { static mut STATIC_MUT: Ty = Ty { a: 0 }; fn main() { - let x = STATIC_MUT.a; - //^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block + let _x = STATIC_MUT.a; + //^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block unsafe { - let x = STATIC_MUT.a; + let _x = STATIC_MUT.a; } } "#, @@ -187,13 +187,13 @@ fn main() { r#" fn main() { let x = &5 as *const usize; - let z = *x$0; + let _z = *x$0; } "#, r#" fn main() { let x = &5 as *const usize; - let z = unsafe { *x }; + let _z = unsafe { *x }; } "#, ); @@ -231,7 +231,7 @@ struct S(usize); impl S { unsafe fn func(&self) { let x = &self.0 as *const usize; - let z = *x; + let _z = *x; } } fn main() { @@ -244,7 +244,7 @@ struct S(usize); impl S { unsafe fn func(&self) { let x = &self.0 as *const usize; - let z = *x; + let _z = *x; } } fn main() { @@ -267,7 +267,7 @@ struct Ty { static mut STATIC_MUT: Ty = Ty { a: 0 }; fn main() { - let x = STATIC_MUT$0.a; + let _x = STATIC_MUT$0.a; } "#, r#" @@ -278,7 +278,7 @@ struct Ty { static mut STATIC_MUT: Ty = Ty { a: 0 }; fn main() { - let x = unsafe { STATIC_MUT.a }; + let _x = unsafe { STATIC_MUT.a }; } "#, ) @@ -382,16 +382,16 @@ fn main() { static mut STATIC_MUT: u8 = 0; fn main() { - let x; - x = STATIC_MUT$0; + let _x; + _x = STATIC_MUT$0; } "#, r#" static mut STATIC_MUT: u8 = 0; fn main() { - let x; - x = unsafe { STATIC_MUT }; + let _x; + _x = unsafe { STATIC_MUT }; } "#, ) @@ -405,14 +405,14 @@ fn main() { static mut STATIC_MUT: u8 = 0; fn main() { - let x = STATIC_MUT$0 + 1; + let _x = STATIC_MUT$0 + 1; } "#, r#" static mut STATIC_MUT: u8 = 0; fn main() { - let x = unsafe { STATIC_MUT } + 1; + let _x = unsafe { STATIC_MUT } + 1; } "#, ) @@ -425,14 +425,14 @@ fn main() { static mut STATIC_MUT: u8 = 0; fn main() { - let x = &STATIC_MUT$0; + let _x = &STATIC_MUT$0; } "#, r#" static mut STATIC_MUT: u8 = 0; fn main() { - let x = unsafe { &STATIC_MUT }; + let _x = unsafe { &STATIC_MUT }; } "#, ) @@ -445,14 +445,14 @@ fn main() { static mut STATIC_MUT: u8 = 0; fn main() { - let x = &&STATIC_MUT$0; + let _x = &&STATIC_MUT$0; } "#, r#" static mut STATIC_MUT: u8 = 0; fn main() { - let x = unsafe { &&STATIC_MUT }; + let _x = unsafe { &&STATIC_MUT }; } "#, ) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs index 3aa4aa97026a1..886aefeb575fb 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -29,6 +29,7 @@ fn main() { let a = &X; let b = *a; //^ error: cannot move `X` out of reference + _ = b; } "#, ); @@ -46,6 +47,7 @@ fn main() { let b = a.0; //^ error: cannot move `X` out of reference let y = a.1; + _ = (b, y); } "#, ); @@ -59,8 +61,8 @@ fn main() { struct X; fn main() { static S: X = X; - let s = S; - //^ error: cannot move `X` out of reference + let _s = S; + //^^ error: cannot move `X` out of reference } "#, ); @@ -165,7 +167,7 @@ enum X { fn main() { let x = &X::Bar; - let c = || match *x { + let _c = || match *x { X::Foo(t) => t, _ => 5, }; @@ -173,4 +175,19 @@ fn main() { "#, ); } + + #[test] + fn regression_15787() { + check_diagnostics( + r#" +//- minicore: coerce_unsized, slice, copy +fn foo(mut slice: &[u32]) -> usize { + slice = match slice { + [0, rest @ ..] | rest => rest, + }; + slice.len() +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs index d056e5c85cc00..1875111492c62 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs @@ -324,6 +324,7 @@ fn main() { let x_own = 2; let ref mut x_ref = x_own; //^^^^^^^^^^^^^ 💡 error: cannot mutate immutable variable `x_own` + _ = x_ref; } "#, ); @@ -331,7 +332,7 @@ fn main() { r#" struct Foo; impl Foo { - fn method(&mut self, x: i32) {} + fn method(&mut self, _x: i32) {} } fn main() { let x = Foo; @@ -391,6 +392,7 @@ fn main() { //^^^^^ 💡 warn: variable does not need to be mutable x = 7; //^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = y; } } } @@ -404,12 +406,14 @@ fn main() { // there would be no mutability error for locals in dead code. Rustc tries to // not emit `unused_mut` in this case, but since it works without `mut`, and // special casing it is not trivial, we emit it. + + // Update: now MIR based `unused-variable` is taking over `unused-mut` for the same reason. check_diagnostics( r#" fn main() { return; let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -419,7 +423,7 @@ fn main() { fn main() { loop {} let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -440,7 +444,7 @@ fn main(b: bool) { g(); } let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -454,7 +458,7 @@ fn main(b: bool) { return; } let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -536,6 +540,7 @@ fn main() { (k @ 5, ref mut t) if { continue; } => { //^^^^^^^^^ 💡 error: cannot mutate immutable variable `z` *t = 5; + _ = k; } _ => { let y = (1, 2); @@ -588,6 +593,7 @@ fn main() { b = 1; c = (2, 3); d = 3; + _ = (c, b, d); } } "#, @@ -600,6 +606,7 @@ fn main() { r#" fn f(mut x: i32) { //^^^^^ 💡 warn: variable does not need to be mutable + f(x + 2); } "#, ); @@ -615,8 +622,11 @@ fn f(x: i32) { r#" fn f((x, y): (i32, i32)) { let t = [0; 2]; - x = 5; - //^^^^^ 💡 error: cannot mutate immutable variable `x` + x = 5; + //^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = x; + _ = y; + _ = t; } "#, ); @@ -645,6 +655,7 @@ fn f(x: [(i32, u8); 10]) { //^^^^^ 💡 warn: variable does not need to be mutable a = 2; //^^^^^ 💡 error: cannot mutate immutable variable `a` + _ = b; } } "#, @@ -666,6 +677,7 @@ fn f(x: [(i32, u8); 10]) { //^^^^^ 💡 error: cannot mutate immutable variable `a` c = 2; //^^^^^ 💡 error: cannot mutate immutable variable `c` + _ = (b, d); } } } @@ -696,18 +708,18 @@ fn f() { fn overloaded_index() { check_diagnostics( r#" -//- minicore: index +//- minicore: index, copy use core::ops::{Index, IndexMut}; struct Foo; impl Index for Foo { type Output = (i32, u8); - fn index(&self, index: usize) -> &(i32, u8) { + fn index(&self, _index: usize) -> &(i32, u8) { &(5, 2) } } impl IndexMut for Foo { - fn index_mut(&mut self, index: usize) -> &mut (i32, u8) { + fn index_mut(&mut self, _index: usize) -> &mut (i32, u8) { &mut (5, 2) } } @@ -715,26 +727,32 @@ fn f() { let mut x = Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y = &x[2]; + _ = (x, y); let x = Foo; let y = &mut x[2]; //^💡 error: cannot mutate immutable variable `x` + _ = (x, y); let mut x = &mut Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y: &mut (i32, u8) = &mut x[2]; + _ = (x, y); let x = Foo; let ref mut y = x[7]; //^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let (ref mut y, _) = x[3]; //^ 💡 error: cannot mutate immutable variable `x` + _ = y; match x[10] { //^ 💡 error: cannot mutate immutable variable `x` - (ref y, _) => (), - (_, ref mut y) => (), + (ref y, 5) => _ = y, + (_, ref mut y) => _ = y, } let mut x = Foo; let mut i = 5; //^^^^^ 💡 warn: variable does not need to be mutable let y = &mut x[i]; + _ = y; } "#, ); @@ -744,7 +762,7 @@ fn f() { fn overloaded_deref() { check_diagnostics( r#" -//- minicore: deref_mut +//- minicore: deref_mut, copy use core::ops::{Deref, DerefMut}; struct Foo; @@ -763,21 +781,27 @@ fn f() { let mut x = Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y = &*x; + _ = (x, y); let x = Foo; let y = &mut *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let x = Foo; + //^ warn: unused variable let x = Foo; let y: &mut (i32, u8) = &mut x; //^^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let ref mut y = *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = y; let (ref mut y, _) = *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = y; match *x { //^^ 💡 error: cannot mutate immutable variable `x` - (ref y, _) => (), - (_, ref mut y) => (), + (ref y, 5) => _ = y, + (_, ref mut y) => _ = y, } } "#, @@ -866,6 +890,7 @@ pub fn test() { data: 0 } ); + _ = tree; } "#, ); @@ -925,6 +950,7 @@ fn fn_once(mut x: impl FnOnce(u8) -> u8) -> u8 { let x = X; let closure4 = || { x.mutate(); }; //^ 💡 error: cannot mutate immutable variable `x` + _ = (closure2, closure3, closure4); } "#, ); @@ -941,7 +967,9 @@ fn fn_once(mut x: impl FnOnce(u8) -> u8) -> u8 { z = 3; let mut k = z; //^^^^^ 💡 warn: variable does not need to be mutable + _ = k; }; + _ = (x, closure); } "#, ); @@ -958,6 +986,7 @@ fn f() { } } }; + _ = closure; } "#, ); @@ -972,7 +1001,8 @@ fn f() { let mut x = X; let c2 = || { x = X; x }; let mut x = X; - let c2 = move || { x = X; }; + let c3 = move || { x = X; }; + _ = (c1, c2, c3); } "#, ); @@ -1023,7 +1053,7 @@ fn x(t: &[u8]) { a = 2; //^^^^^ 💡 error: cannot mutate immutable variable `a` - + _ = b; } _ => {} } @@ -1079,6 +1109,7 @@ fn f() { let x = Box::new(5); let closure = || *x = 2; //^ 💡 error: cannot mutate immutable variable `x` + _ = closure; } "#, ); @@ -1156,6 +1187,7 @@ macro_rules! mac { fn main2() { let mut x = mac![]; //^^^^^ 💡 warn: variable does not need to be mutable + _ = x; } "#, ); @@ -1193,6 +1225,22 @@ fn foo(mut foo: Foo) { }; call_me(); } +"#, + ); + } + + #[test] + fn regression_15670() { + check_diagnostics( + r#" +//- minicore: fn + +pub struct A {} +pub unsafe fn foo(a: *mut A) { + let mut b = || -> *mut A { &mut *a }; + //^^^^^ 💡 warn: variable does not need to be mutable + let _ = b(); +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs index 290c16c9d247f..ee8a9c95793c1 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs @@ -13,7 +13,7 @@ use crate::{fix, Assist, Diagnostic, DiagnosticCode, DiagnosticsContext}; // // This diagnostic is triggered if created structure does not have field provided in record. pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Diagnostic { - let node = d.field.clone().map(|it| it.either(Into::into, Into::into)); + let node = d.field.clone().map(Into::into); if d.private { // FIXME: quickfix to add required visibility Diagnostic::new_with_syntax_node_ptr( @@ -35,15 +35,13 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Option> { // FIXME: quickfix for pattern - match &d.field.value { - Either::Left(ptr) => { - let root = ctx.sema.db.parse_or_expand(d.field.file_id); - missing_record_expr_field_fixes( - &ctx.sema, - d.field.file_id.original_file(ctx.sema.db), - &ptr.to_node(&root), - ) - } + let root = ctx.sema.db.parse_or_expand(d.field.file_id); + match &d.field.value.to_node(&root) { + Either::Left(node) => missing_record_expr_field_fixes( + &ctx.sema, + d.field.file_id.original_file(ctx.sema.db), + node, + ), _ => None, } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs index c44d28e77f6d9..a828b8b4fd292 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs @@ -1,5 +1,3 @@ -use either::Either; - use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; // Diagnostic: private-assoc-item @@ -28,13 +26,7 @@ pub(crate) fn private_assoc_item( }, name, ), - d.expr_or_pat.clone().map(|it| match it { - Either::Left(it) => it.into(), - Either::Right(it) => match it { - Either::Left(it) => it.into(), - Either::Right(it) => it.into(), - }, - }), + d.expr_or_pat.clone().map(Into::into), ) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs index 083ef3e8dc16f..d15233d15c2c5 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs @@ -74,8 +74,8 @@ mod tests { r#" //- minicore: iterators fn foo() { - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); -} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); +} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) "#, ); } @@ -117,7 +117,7 @@ fn foo() { fn foo() { let mut m = core::iter::repeat(()) .filter_map(|()| Some(92)); - let n = m.next(); + let _n = m.next(); } "#, ); @@ -148,22 +148,22 @@ fn foo() { fn foo() { #[allow(clippy::filter_map_next)] - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); } #[deny(clippy::filter_map_next)] fn foo() { - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); -} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: replace filter_map(..).next() with find_map(..) + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); +} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: replace filter_map(..).next() with find_map(..) fn foo() { - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); -} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); +} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) #[warn(clippy::filter_map_next)] fn foo() { - let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); -} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 warn: replace filter_map(..).next() with find_map(..) + let _m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); +} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 warn: replace filter_map(..).next() with find_map(..) "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs new file mode 100644 index 0000000000000..251a645292ed5 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs @@ -0,0 +1,129 @@ +use hir::InFile; +use syntax::ast; + +use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext, Severity}; + +// Diagnostic: trait-impl-incorrect-safety +// +// Diagnoses incorrect safety annotations of trait impls. +pub(crate) fn trait_impl_incorrect_safety( + ctx: &DiagnosticsContext<'_>, + d: &hir::TraitImplIncorrectSafety, +) -> Diagnostic { + Diagnostic::new( + DiagnosticCode::Ra("trait-impl-incorrect-safety", Severity::Error), + if d.should_be_safe { + "unsafe impl for safe trait" + } else { + "impl for unsafe trait needs to be unsafe" + }, + adjusted_display_range::( + ctx, + InFile { file_id: d.file_id, value: d.impl_.syntax_node_ptr() }, + &|impl_| { + if d.should_be_safe { + Some(match (impl_.unsafe_token(), impl_.impl_token()) { + (None, None) => return None, + (None, Some(t)) | (Some(t), None) => t.text_range(), + (Some(t1), Some(t2)) => t1.text_range().cover(t2.text_range()), + }) + } else { + impl_.impl_token().map(|t| t.text_range()) + } + }, + ), + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn simple() { + check_diagnostics( + r#" +trait Safe {} +unsafe trait Unsafe {} + + impl Safe for () {} + + impl Unsafe for () {} +//^^^^ error: impl for unsafe trait needs to be unsafe + + unsafe impl Safe for () {} +//^^^^^^^^^^^ error: unsafe impl for safe trait + + unsafe impl Unsafe for () {} +"#, + ); + } + + #[test] + fn drop_may_dangle() { + check_diagnostics( + r#" +#[lang = "drop"] +trait Drop {} +struct S; +struct L<'l>; + + impl Drop for S {} + + impl<#[may_dangle] T> Drop for S {} +//^^^^ error: impl for unsafe trait needs to be unsafe + + unsafe impl Drop for S {} +//^^^^^^^^^^^ error: unsafe impl for safe trait + + unsafe impl<#[may_dangle] T> Drop for S {} + + impl<'l> Drop for L<'l> {} + + impl<#[may_dangle] 'l> Drop for L<'l> {} +//^^^^ error: impl for unsafe trait needs to be unsafe + + unsafe impl<'l> Drop for L<'l> {} +//^^^^^^^^^^^ error: unsafe impl for safe trait + + unsafe impl<#[may_dangle] 'l> Drop for L<'l> {} +"#, + ); + } + + #[test] + fn negative() { + check_diagnostics( + r#" +trait Trait {} + + impl !Trait for () {} + + unsafe impl !Trait for () {} +//^^^^^^^^^^^ error: unsafe impl for safe trait + +unsafe trait UnsafeTrait {} + + impl !UnsafeTrait for () {} + + unsafe impl !UnsafeTrait for () {} +//^^^^^^^^^^^ error: unsafe impl for safe trait + +"#, + ); + } + + #[test] + fn inherent() { + check_diagnostics( + r#" +struct S; + + impl S {} + + unsafe impl S {} +//^^^^^^^^^^^ error: unsafe impl for safe trait +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs new file mode 100644 index 0000000000000..51923797ac91a --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs @@ -0,0 +1,115 @@ +use hir::InFile; +use itertools::Itertools; +use syntax::{ast, AstNode}; + +use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; + +// Diagnostic: trait-impl-missing-assoc_item +// +// Diagnoses missing trait items in a trait impl. +pub(crate) fn trait_impl_missing_assoc_item( + ctx: &DiagnosticsContext<'_>, + d: &hir::TraitImplMissingAssocItems, +) -> Diagnostic { + let missing = d.missing.iter().format_with(", ", |(name, item), f| { + f(&match *item { + hir::AssocItem::Function(_) => "`fn ", + hir::AssocItem::Const(_) => "`const ", + hir::AssocItem::TypeAlias(_) => "`type ", + })?; + f(&name.display(ctx.sema.db))?; + f(&"`") + }); + Diagnostic::new( + DiagnosticCode::RustcHardError("E0046"), + format!("not all trait items implemented, missing: {missing}"), + adjusted_display_range::( + ctx, + InFile { file_id: d.file_id, value: d.impl_.syntax_node_ptr() }, + &|impl_| impl_.trait_().map(|t| t.syntax().text_range()), + ), + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn trait_with_default_value() { + check_diagnostics( + r#" +trait Marker { + const FLAG: bool = false; +} +struct Foo; +impl Marker for Foo {} + "#, + ) + } + + #[test] + fn simple() { + check_diagnostics( + r#" +trait Trait { + const C: (); + type T; + fn f(); +} + +impl Trait for () { + const C: () = (); + type T = (); + fn f() {} +} + +impl Trait for () { + //^^^^^ error: not all trait items implemented, missing: `const C` + type T = (); + fn f() {} +} + +impl Trait for () { + //^^^^^ error: not all trait items implemented, missing: `const C`, `type T`, `fn f` +} + +"#, + ); + } + + #[test] + fn default() { + check_diagnostics( + r#" +trait Trait { + const C: (); + type T = (); + fn f() {} +} + +impl Trait for () { + const C: () = (); + type T = (); + fn f() {} +} + +impl Trait for () { + //^^^^^ error: not all trait items implemented, missing: `const C` + type T = (); + fn f() {} +} + +impl Trait for () { + //^^^^^ error: not all trait items implemented, missing: `const C` + type T = (); + } + +impl Trait for () { + //^^^^^ error: not all trait items implemented, missing: `const C` +} + +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs new file mode 100644 index 0000000000000..159d87d269de0 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs @@ -0,0 +1,106 @@ +use hir::InFile; + +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; + +// Diagnostic: trait-impl-orphan +// +// Only traits defined in the current crate can be implemented for arbitrary types +pub(crate) fn trait_impl_orphan( + ctx: &DiagnosticsContext<'_>, + d: &hir::TraitImplOrphan, +) -> Diagnostic { + Diagnostic::new_with_syntax_node_ptr( + ctx, + DiagnosticCode::RustcHardError("E0117"), + format!("only traits defined in the current crate can be implemented for arbitrary types"), + InFile::new(d.file_id, d.impl_.clone().into()), + ) + // Not yet checked for false positives + .experimental() +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn simple() { + check_diagnostics( + r#" +//- /foo.rs crate:foo +pub trait Foo {} +//- /bar.rs crate:bar +pub struct Bar; +//- /main.rs crate:main deps:foo,bar +struct LocalType; +trait LocalTrait {} + impl foo::Foo for bar::Bar {} +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: only traits defined in the current crate can be implemented for arbitrary types +impl foo::Foo for LocalType {} +impl LocalTrait for bar::Bar {} +"#, + ); + } + + #[test] + fn generics() { + check_diagnostics( + r#" +//- /foo.rs crate:foo +pub trait Foo {} +//- /bar.rs crate:bar +pub struct Bar(T); +//- /main.rs crate:main deps:foo,bar +struct LocalType; +trait LocalTrait {} + impl foo::Foo for bar::Bar {} +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: only traits defined in the current crate can be implemented for arbitrary types + + impl foo::Foo for bar::Bar> {} +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: only traits defined in the current crate can be implemented for arbitrary types + + impl foo::Foo> for bar::Bar {} + + impl foo::Foo>> for bar::Bar> {} +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: only traits defined in the current crate can be implemented for arbitrary types +"#, + ); + } + + #[test] + fn fundamental() { + check_diagnostics( + r#" +//- /foo.rs crate:foo +pub trait Foo {} +//- /bar.rs crate:bar +pub struct Bar(T); +#[lang = "owned_box"] +#[fundamental] +pub struct Box(T); +//- /main.rs crate:main deps:foo,bar +struct LocalType; + impl foo::Foo for bar::Box {} +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: only traits defined in the current crate can be implemented for arbitrary types + impl foo::Foo for &LocalType {} + impl foo::Foo for bar::Box {} +"#, + ); + } + + #[test] + fn dyn_object() { + check_diagnostics( + r#" +//- /foo.rs crate:foo +pub trait Foo {} +//- /bar.rs crate:bar +pub struct Bar; +//- /main.rs crate:main deps:foo,bar +trait LocalTrait {} +impl foo::Foo for dyn LocalTrait {} +impl foo::Foo for Bar {} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 15bd28c00dfd2..c92d92ceae8c8 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1,4 +1,3 @@ -use either::Either; use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, InFile, Type}; use ide_db::{famous_defs::FamousDefs, source_change::SourceChange}; use syntax::{ @@ -14,9 +13,11 @@ use crate::{adjusted_display_range, fix, Assist, Diagnostic, DiagnosticCode, Dia // This diagnostic is triggered when the type of an expression or pattern does not match // the expected type. pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Diagnostic { - let display_range = match &d.expr_or_pat { - Either::Left(expr) => { - adjusted_display_range::(ctx, expr.clone().map(|it| it.into()), &|expr| { + let display_range = match &d.expr_or_pat.value { + expr if ast::Expr::can_cast(expr.kind()) => adjusted_display_range::( + ctx, + InFile { file_id: d.expr_or_pat.file_id, value: expr.syntax_node_ptr() }, + &|expr| { let salient_token_range = match expr { ast::Expr::IfExpr(it) => it.if_token()?.text_range(), ast::Expr::LoopExpr(it) => it.loop_token()?.text_range(), @@ -32,10 +33,15 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) cov_mark::hit!(type_mismatch_range_adjustment); Some(salient_token_range) - }) - } - Either::Right(pat) => { - ctx.sema.diagnostics_display_range(pat.clone().map(|it| it.into())).range + }, + ), + pat => { + ctx.sema + .diagnostics_display_range(InFile { + file_id: d.expr_or_pat.file_id, + value: pat.syntax_node_ptr(), + }) + .range } }; let mut diag = Diagnostic::new( @@ -57,14 +63,12 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Option> { let mut fixes = Vec::new(); - match &d.expr_or_pat { - Either::Left(expr_ptr) => { - add_reference(ctx, d, expr_ptr, &mut fixes); - add_missing_ok_or_some(ctx, d, expr_ptr, &mut fixes); - remove_semicolon(ctx, d, expr_ptr, &mut fixes); - str_ref_to_owned(ctx, d, expr_ptr, &mut fixes); - } - Either::Right(_pat_ptr) => {} + if let Some(expr_ptr) = d.expr_or_pat.value.clone().cast::() { + let expr_ptr = &InFile { file_id: d.expr_or_pat.file_id, value: expr_ptr.clone() }; + add_reference(ctx, d, expr_ptr, &mut fixes); + add_missing_ok_or_some(ctx, d, expr_ptr, &mut fixes); + remove_semicolon(ctx, d, expr_ptr, &mut fixes); + str_ref_to_owned(ctx, d, expr_ptr, &mut fixes); } if fixes.is_empty() { @@ -205,7 +209,7 @@ fn main() { test(123); //^^^ 💡 error: expected &i32, found i32 } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, ); } @@ -217,13 +221,13 @@ fn test(arg: &i32) {} fn main() { test(123$0); } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, r#" fn main() { test(&123); } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, ); } @@ -235,13 +239,13 @@ fn test(arg: &i32) {} fn main() { test($0123); } -fn test(arg: &mut i32) {} +fn test(_arg: &mut i32) {} "#, r#" fn main() { test(&mut 123); } -fn test(arg: &mut i32) {} +fn test(_arg: &mut i32) {} "#, ); } @@ -254,13 +258,13 @@ fn test(arg: &mut i32) {} fn main() { test($0[1, 2, 3]); } -fn test(arg: &[i32]) {} +fn test(_arg: &[i32]) {} "#, r#" fn main() { test(&[1, 2, 3]); } -fn test(arg: &[i32]) {} +fn test(_arg: &[i32]) {} "#, ); } @@ -274,24 +278,26 @@ struct Foo; struct Bar; impl core::ops::Deref for Foo { type Target = Bar; + fn deref(&self) -> &Self::Target { loop {} } } fn main() { test($0Foo); } -fn test(arg: &Bar) {} +fn test(_arg: &Bar) {} "#, r#" struct Foo; struct Bar; impl core::ops::Deref for Foo { type Target = Bar; + fn deref(&self) -> &Self::Target { loop {} } } fn main() { test(&Foo); } -fn test(arg: &Bar) {} +fn test(_arg: &Bar) {} "#, ); } @@ -305,7 +311,7 @@ fn main() { } struct Test; impl Test { - fn call_by_ref(&self, arg: &i32) {} + fn call_by_ref(&self, _arg: &i32) {} } "#, r#" @@ -314,7 +320,7 @@ fn main() { } struct Test; impl Test { - fn call_by_ref(&self, arg: &i32) {} + fn call_by_ref(&self, _arg: &i32) {} } "#, ); @@ -345,7 +351,7 @@ macro_rules! thousand { 1000_u64 }; } -fn test(foo: &u64) {} +fn test(_foo: &u64) {} fn main() { test($0thousand!()); } @@ -356,7 +362,7 @@ macro_rules! thousand { 1000_u64 }; } -fn test(foo: &u64) {} +fn test(_foo: &u64) {} fn main() { test(&thousand!()); } @@ -369,12 +375,12 @@ fn main() { check_fix( r#" fn main() { - let test: &mut i32 = $0123; + let _test: &mut i32 = $0123; } "#, r#" fn main() { - let test: &mut i32 = &mut 123; + let _test: &mut i32 = &mut 123; } "#, ); @@ -411,7 +417,7 @@ fn div(x: i32, y: i32) -> Option { fn f() -> Rate { // FIXME: add some error loop {} } - fn run(t: Rate<5>) { + fn run(_t: Rate<5>) { } fn main() { run(f()) // FIXME: remove this error @@ -426,7 +432,7 @@ fn div(x: i32, y: i32) -> Option { check_diagnostics( r#" pub struct Rate(T); - fn run(t: Rate) { + fn run(_t: Rate) { } fn main() { run(Rate::<_, _, _>(5)); @@ -650,7 +656,7 @@ fn h() { r#" struct X(T); -fn foo(x: X) {} +fn foo(_x: X) {} fn test1() { // Unknown might be `i32`, so we should not emit type mismatch here. foo(X(42)); @@ -733,6 +739,21 @@ fn f() -> i32 { 0 } fn g() { return; } +"#, + ); + } + + #[test] + fn smoke_test_inner_items() { + check_diagnostics( + r#" +fn f() { + fn inner() -> i32 { + return; + // ^^^^^^ error: expected i32, found () + 0 + } +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs index 4af67227115d9..4e215a89d7932 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -142,8 +142,8 @@ fn t() -> T { loop {} } check_diagnostics( r#" fn main() { - let x = [(); _]; - let y: [(); 10] = [(); _]; + let _x = [(); _]; + let _y: [(); 10] = [(); _]; _ = 0; (_,) = (1,); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs new file mode 100644 index 0000000000000..28ccf474b40b2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs @@ -0,0 +1,111 @@ +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; + +// Diagnostic: unused-variables +// +// This diagnostic is triggered when a local variable is not used. +pub(crate) fn unused_variables( + ctx: &DiagnosticsContext<'_>, + d: &hir::UnusedVariable, +) -> Diagnostic { + let ast = d.local.primary_source(ctx.sema.db).syntax_ptr(); + Diagnostic::new_with_syntax_node_ptr( + ctx, + DiagnosticCode::RustcLint("unused_variables"), + "unused variable", + ast, + ) + .experimental() +} + +#[cfg(test)] +mod tests { + use crate::tests::check_diagnostics; + + #[test] + fn unused_variables_simple() { + check_diagnostics( + r#" +//- minicore: fn +struct Foo { f1: i32, f2: i64 } + +fn f(kkk: i32) {} + //^^^ warn: unused variable +fn main() { + let a = 2; + //^ warn: unused variable + let b = 5; + // note: `unused variable` implies `unused mut`, so we should not emit both at the same time. + let mut c = f(b); + //^^^^^ warn: unused variable + let (d, e) = (3, 5); + //^ warn: unused variable + let _ = e; + let f1 = 2; + let f2 = 5; + let f = Foo { f1, f2 }; + match f { + Foo { f1, f2 } => { + //^^ warn: unused variable + _ = f2; + } + } + let g = false; + if g {} + let h: fn() -> i32 = || 2; + let i = h(); + //^ warn: unused variable +} +"#, + ); + } + + #[test] + fn unused_self() { + check_diagnostics( + r#" +struct S { +} +impl S { + fn owned_self(self, u: i32) {} + //^ warn: unused variable + fn ref_self(&self, u: i32) {} + //^ warn: unused variable + fn ref_mut_self(&mut self, u: i32) {} + //^ warn: unused variable + fn owned_mut_self(mut self) {} + //^^^^^^^^ 💡 warn: variable does not need to be mutable + +} +"#, + ); + } + + #[test] + fn allow_unused_variables_for_identifiers_starting_with_underline() { + check_diagnostics( + r#" +fn main() { + let _x = 2; +} +"#, + ); + } + + #[test] + fn respect_lint_attributes_for_unused_variables() { + check_diagnostics( + r#" +fn main() { + #[allow(unused_variables)] + let x = 2; +} + +#[deny(unused)] +fn main2() { + let x = 2; + //^ error: unused variable +} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index ebe197a6790ec..6744895f3cd2e 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -44,6 +44,9 @@ mod handlers { pub(crate) mod private_assoc_item; pub(crate) mod private_field; pub(crate) mod replace_filter_map_next_with_find_map; + pub(crate) mod trait_impl_orphan; + pub(crate) mod trait_impl_incorrect_safety; + pub(crate) mod trait_impl_missing_assoc_item; pub(crate) mod typed_hole; pub(crate) mod type_mismatch; pub(crate) mod unimplemented_builtin_macro; @@ -56,6 +59,7 @@ mod handlers { pub(crate) mod unresolved_proc_macro; pub(crate) mod undeclared_label; pub(crate) mod unreachable_label; + pub(crate) mod unused_variables; // The handlers below are unusual, the implement the diagnostics as well. pub(crate) mod field_shorthand; @@ -224,6 +228,7 @@ pub struct DiagnosticsConfig { // FIXME: We may want to include a whole `AssistConfig` here pub insert_use: InsertUseConfig, pub prefer_no_std: bool, + pub prefer_prelude: bool, } impl DiagnosticsConfig { @@ -246,6 +251,7 @@ impl DiagnosticsConfig { skip_glob_imports: false, }, prefer_no_std: false, + prefer_prelude: true, } } } @@ -355,6 +361,9 @@ pub fn diagnostics( AnyDiagnostic::PrivateAssocItem(d) => handlers::private_assoc_item::private_assoc_item(&ctx, &d), AnyDiagnostic::PrivateField(d) => handlers::private_field::private_field(&ctx, &d), AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => handlers::replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d), + AnyDiagnostic::TraitImplIncorrectSafety(d) => handlers::trait_impl_incorrect_safety::trait_impl_incorrect_safety(&ctx, &d), + AnyDiagnostic::TraitImplMissingAssocItems(d) => handlers::trait_impl_missing_assoc_item::trait_impl_missing_assoc_item(&ctx, &d), + AnyDiagnostic::TraitImplOrphan(d) => handlers::trait_impl_orphan::trait_impl_orphan(&ctx, &d), AnyDiagnostic::TypedHole(d) => handlers::typed_hole::typed_hole(&ctx, &d), AnyDiagnostic::TypeMismatch(d) => handlers::type_mismatch::type_mismatch(&ctx, &d), AnyDiagnostic::UndeclaredLabel(d) => handlers::undeclared_label::undeclared_label(&ctx, &d), @@ -368,6 +377,7 @@ pub fn diagnostics( AnyDiagnostic::UnresolvedModule(d) => handlers::unresolved_module::unresolved_module(&ctx, &d), AnyDiagnostic::UnresolvedProcMacro(d) => handlers::unresolved_proc_macro::unresolved_proc_macro(&ctx, &d, config.proc_macros_enabled, config.proc_attr_macros_enabled), AnyDiagnostic::UnusedMut(d) => handlers::mutability_errors::unused_mut(&ctx, &d), + AnyDiagnostic::UnusedVariable(d) => handlers::unused_variables::unused_variables(&ctx, &d), AnyDiagnostic::BreakOutsideOfLoop(d) => handlers::break_outside_of_loop::break_outside_of_loop(&ctx, &d), AnyDiagnostic::MismatchedTupleStructPatArgCount(d) => handlers::mismatched_arg_count::mismatched_tuple_struct_pat_arg_count(&ctx, &d), }; diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs index ee0e0354906ed..c766a018bfd05 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs @@ -5,7 +5,7 @@ use expect_test::Expect; use ide_db::{ assists::AssistResolveStrategy, base_db::{fixture::WithFixture, SourceDatabaseExt}, - RootDatabase, + LineIndexDatabase, RootDatabase, }; use stdx::trim_indent; use test_utils::{assert_eq_text, extract_annotations, MiniCore}; @@ -43,7 +43,8 @@ fn check_nth_fix(nth: usize, ra_fixture_before: &str, ra_fixture_after: &str) { super::diagnostics(&db, &conf, &AssistResolveStrategy::All, file_position.file_id) .pop() .expect("no diagnostics"); - let fix = &diagnostic.fixes.expect("diagnostic misses fixes")[nth]; + let fix = + &diagnostic.fixes.expect(&format!("{:?} diagnostic misses fixes", diagnostic.code))[nth]; let actual = { let source_change = fix.source_change.as_ref().unwrap(); let file_id = *source_change.source_file_edits.keys().next().unwrap(); @@ -103,6 +104,7 @@ pub(crate) fn check_diagnostics(ra_fixture: &str) { pub(crate) fn check_diagnostics_with_config(config: DiagnosticsConfig, ra_fixture: &str) { let (db, files) = RootDatabase::with_many_files(ra_fixture); for file_id in files { + let line_index = db.line_index(file_id); let diagnostics = super::diagnostics(&db, &config, &AssistResolveStrategy::All, file_id); let expected = extract_annotations(&db.file_text(file_id)); @@ -136,8 +138,16 @@ pub(crate) fn check_diagnostics_with_config(config: DiagnosticsConfig, ra_fixtur } } if expected != actual { - let fneg = expected.iter().filter(|x| !actual.contains(x)).collect::>(); - let fpos = actual.iter().filter(|x| !expected.contains(x)).collect::>(); + let fneg = expected + .iter() + .filter(|x| !actual.contains(x)) + .map(|(range, s)| (line_index.line_col(range.start()), range, s)) + .collect::>(); + let fpos = actual + .iter() + .filter(|x| !expected.contains(x)) + .map(|(range, s)| (line_index.line_col(range.start()), range, s)) + .collect::>(); panic!("Diagnostic test failed.\nFalse negatives: {fneg:?}\nFalse positives: {fpos:?}"); } diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml index 70ed6dea5bf28..56b29f92b8293 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml @@ -14,7 +14,7 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" -itertools = "0.10.5" +itertools.workspace = true triomphe.workspace = true nohash-hasher.workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index 60fcbbbd39797..0312a0f11ebd8 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -651,7 +651,7 @@ impl Match { for (path, resolved_path) in &template.resolved_paths { if let hir::PathResolution::Def(module_def) = resolved_path.resolution { let mod_path = - module.find_use_path(sema.db, module_def, false).ok_or_else(|| { + module.find_use_path(sema.db, module_def, false, true).ok_or_else(|| { match_error!("Failed to render template path `{}` at match location") })?; self.rendered_template_paths.insert(path.clone(), mod_path); diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml index 2aee203c4ea54..d5c3439f95638 100644 --- a/src/tools/rust-analyzer/crates/ide/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml @@ -14,9 +14,9 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" crossbeam-channel = "0.5.5" -either = "1.7.0" -itertools = "0.10.5" -tracing = "0.1.35" +either.workspace = true +itertools.workspace = true +tracing.workspace = true oorandom = "11.1.3" pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.1", default-features = false } diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 37a177622162c..ac15b6aba6189 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -602,7 +602,17 @@ fn filename_and_frag_for_def( } Definition::Const(c) => format!("const.{}.html", c.name(db)?.display(db.upcast())), Definition::Static(s) => format!("static.{}.html", s.name(db).display(db.upcast())), - Definition::Macro(mac) => format!("macro.{}.html", mac.name(db).display(db.upcast())), + Definition::Macro(mac) => match mac.kind(db) { + hir::MacroKind::Declarative + | hir::MacroKind::BuiltIn + | hir::MacroKind::Attr + | hir::MacroKind::ProcMacro => { + format!("macro.{}.html", mac.name(db).display(db.upcast())) + } + hir::MacroKind::Derive => { + format!("derive.{}.html", mac.name(db).display(db.upcast())) + } + }, Definition::Field(field) => { let def = match field.parent_def(db) { hir::VariantDef::Struct(it) => Definition::Adt(it.into()), diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index 119a9c7c3f40a..3220774567750 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -14,12 +14,12 @@ pub struct ExpandedMacro { // Feature: Expand Macro Recursively // -// Shows the full macro expansion of the macro at current cursor. +// Shows the full macro expansion of the macro at the current caret position. // // |=== // | Editor | Action Name // -// | VS Code | **rust-analyzer: Expand macro recursively** +// | VS Code | **rust-analyzer: Expand macro recursively at caret** // |=== // // image::https://user-images.githubusercontent.com/48062697/113020648-b3973180-917a-11eb-84a9-ecb921293dc5.gif[] diff --git a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs index 3d89599c5832e..9b2ff070c74b1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs +++ b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs @@ -108,7 +108,7 @@ fn try_extend_selection( let node = shallowest_node(&node); - if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) { + if node.parent().is_some_and(|n| list_kinds.contains(&n.kind())) { if let Some(range) = extend_list_item(&node) { return Some(range); } diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs index 46a0464e9e6ea..a7f5ae92a4cac 100644 --- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs +++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs @@ -43,7 +43,7 @@ pub struct HighlightRelatedConfig { // // . if on an identifier, highlights all references to that identifier in the current file // .. additionally, if the identifier is a trait in a where clause, type parameter trait bound or use item, highlights all references to that trait's assoc items in the corresponding scope -// . if on an `async` or `await token, highlights all yield points for that async context +// . if on an `async` or `await` token, highlights all yield points for that async context // . if on a `return` or `fn` keyword, `?` character or `->` return type arrow, highlights all exit points for that context // . if on a `break`, `loop`, `while` or `for` token, highlights all break points for that loop or block context // . if on a `move` or `|` token that belongs to a closure, highlights all captures of the closure. diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 21934b9480efb..e0b64fe7988e5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -180,26 +180,24 @@ fn hover_simple( descended() .filter_map(|token| { let node = token.parent()?; - let class = IdentClass::classify_token(sema, token)?; - if let IdentClass::Operator(OperatorClass::Await(_)) = class { + match IdentClass::classify_node(sema, &node)? { // It's better for us to fall back to the keyword hover here, // rendering poll is very confusing - return None; + IdentClass::Operator(OperatorClass::Await(_)) => None, + + IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { + decl, + .. + }) => Some(vec![(Definition::ExternCrateDecl(decl), node)]), + + class => Some( + class + .definitions() + .into_iter() + .zip(iter::repeat(node)) + .collect::>(), + ), } - if let IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { - decl, - .. - }) = class - { - return Some(vec![(Definition::ExternCrateDecl(decl), node)]); - } - Some( - class - .definitions() - .into_iter() - .zip(iter::once(node).cycle()) - .collect::>(), - ) }) .flatten() .unique_by(|&(def, _)| def) diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index f72ce37d1d943..d0a02fd0dba2f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -402,10 +402,9 @@ pub(super) fn definition( |&it| it.layout(db), |_| { let var_def = it.parent_def(db); - let id = it.index(); match var_def { hir::VariantDef::Struct(s) => { - Adt::from(s).layout(db).ok().and_then(|layout| layout.field_offset(id)) + Adt::from(s).layout(db).ok().and_then(|layout| layout.field_offset(it)) } _ => None, } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 81d6db564ff5a..d3d492f3fdef0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -1136,7 +1136,9 @@ impl Thing { ``` ```rust - struct Thing + struct Thing { + x: u32, + } ``` "#]], ); @@ -1155,7 +1157,9 @@ impl Thing { ``` ```rust - struct Thing + struct Thing { + x: u32, + } ``` "#]], ); @@ -1174,7 +1178,9 @@ impl Thing { ``` ```rust - enum Thing + enum Thing { + A, + } ``` "#]], ); @@ -1193,7 +1199,9 @@ impl Thing { ``` ```rust - enum Thing + enum Thing { + A, + } ``` "#]], ); @@ -2005,7 +2013,10 @@ fn test_hover_layout_of_enum() { ``` ```rust - enum Foo // size = 16 (0x10), align = 8, niches = 254 + enum Foo { + Variant1(u8, u16), + Variant2(i32, u8, i64), + } // size = 16 (0x10), align = 8, niches = 254 ``` "#]], ); @@ -2346,7 +2357,7 @@ fn main() { let s$0t = S{ f1:0 }; } focus_range: 7..8, name: "S", kind: Struct, - description: "struct S", + description: "struct S {\n f1: u32,\n}", }, }, ], @@ -2379,7 +2390,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; } focus_range: 24..25, name: "S", kind: Struct, - description: "struct S", + description: "struct S {\n f1: T,\n}", }, }, HoverGotoTypeData { @@ -2392,7 +2403,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; } focus_range: 7..10, name: "Arg", kind: Struct, - description: "struct Arg", + description: "struct Arg(u32);", }, }, ], @@ -2438,7 +2449,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; } focus_range: 24..25, name: "S", kind: Struct, - description: "struct S", + description: "struct S {\n f1: T,\n}", }, }, HoverGotoTypeData { @@ -2451,7 +2462,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; } focus_range: 7..10, name: "Arg", kind: Struct, - description: "struct Arg", + description: "struct Arg(u32);", }, }, ], @@ -2487,7 +2498,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); } focus_range: 7..8, name: "A", kind: Struct, - description: "struct A", + description: "struct A(u32);", }, }, HoverGotoTypeData { @@ -2500,7 +2511,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); } focus_range: 22..23, name: "B", kind: Struct, - description: "struct B", + description: "struct B(u32);", }, }, HoverGotoTypeData { @@ -2514,7 +2525,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); } name: "C", kind: Struct, container_name: "M", - description: "pub struct C", + description: "pub struct C(u32);", }, }, ], @@ -2704,7 +2715,7 @@ fn main() { let s$0t = foo(); } focus_range: 39..41, name: "S1", kind: Struct, - description: "struct S1", + description: "struct S1 {}", }, }, HoverGotoTypeData { @@ -2717,7 +2728,7 @@ fn main() { let s$0t = foo(); } focus_range: 52..54, name: "S2", kind: Struct, - description: "struct S2", + description: "struct S2 {}", }, }, ], @@ -2808,7 +2819,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 36..37, name: "S", kind: Struct, - description: "struct S", + description: "struct S {}", }, }, ], @@ -2908,7 +2919,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 23..24, name: "S", kind: Struct, - description: "struct S", + description: "struct S {}", }, }, ], @@ -2945,7 +2956,7 @@ fn main() { let s$0t = foo(); } focus_range: 49..50, name: "B", kind: Struct, - description: "struct B", + description: "struct B {}", }, }, HoverGotoTypeData { @@ -3034,7 +3045,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 23..24, name: "S", kind: Struct, - description: "struct S", + description: "struct S {}", }, }, ], @@ -3082,7 +3093,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 50..51, name: "B", kind: Struct, - description: "struct B", + description: "struct B {}", }, }, HoverGotoTypeData { @@ -3108,7 +3119,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 65..66, name: "S", kind: Struct, - description: "struct S", + description: "struct S {}", }, }, ], @@ -3335,7 +3346,7 @@ struct S$0T(T); ``` ```rust - struct ST + struct ST(T); ``` "#]], ); @@ -3356,7 +3367,7 @@ struct S$0T(T); ``` ```rust - struct ST + struct ST(T); ``` "#]], ); @@ -3378,7 +3389,7 @@ struct S$0T(T); ``` ```rust - struct ST + struct ST(T); ``` "#]], ); @@ -5266,38 +5277,46 @@ pub fn foo() {} #[test] fn hover_feature() { check( - r#"#![feature(box_syntax$0)]"#, - expect![[r##" - *box_syntax* - ``` - box_syntax - ``` - ___ + r#"#![feature(intrinsics$0)]"#, + expect![[r#" + *intrinsics* + ``` + intrinsics + ``` + ___ - # `box_syntax` + # `intrinsics` - The tracking issue for this feature is: [#49733] + The tracking issue for this feature is: None. - [#49733]: https://github.com/rust-lang/rust/issues/49733 + Intrinsics are never intended to be stable directly, but intrinsics are often + exported in some sort of stable manner. Prefer using the stable interfaces to + the intrinsic directly when you can. - See also [`box_patterns`](box-patterns.md) + ------------------------ - ------------------------ - Currently the only stable way to create a `Box` is via the `Box::new` method. - Also it is not possible in stable Rust to destructure a `Box` in a match - pattern. The unstable `box` keyword can be used to create a `Box`. An example - usage would be: + These are imported as if they were FFI functions, with the special + `rust-intrinsic` ABI. For example, if one was in a freestanding + context, but wished to be able to `transmute` between types, and + perform efficient pointer arithmetic, one would import those functions + via a declaration like - ```rust - #![feature(box_syntax)] + ```rust + #![feature(intrinsics)] + #![allow(internal_features)] + # fn main() {} - fn main() { - let b = box 5; - } - ``` + extern "rust-intrinsic" { + fn transmute(x: T) -> U; - "##]], + fn arith_offset(dst: *const T, offset: isize) -> *const T; + } + ``` + + As with any other FFI functions, these are always `unsafe` to call. + + "#]], ) } @@ -5927,7 +5946,7 @@ pub struct Foo(i32); ``` ```rust - pub struct Foo // size = 4, align = 4 + pub struct Foo(i32); // size = 4, align = 4 ``` --- diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index a5d070fe76738..7ea9d4f1038b4 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -31,6 +31,7 @@ mod discriminant; mod fn_lifetime_fn; mod implicit_static; mod param_name; +mod implicit_drop; #[derive(Clone, Debug, PartialEq, Eq)] pub struct InlayHintsConfig { @@ -45,6 +46,7 @@ pub struct InlayHintsConfig { pub closure_return_type_hints: ClosureReturnTypeHints, pub closure_capture_hints: bool, pub binding_mode_hints: bool, + pub implicit_drop_hints: bool, pub lifetime_elision_hints: LifetimeElisionHints, pub param_names_for_lifetime_elision_hints: bool, pub hide_named_constructor_hints: bool, @@ -124,6 +126,7 @@ pub enum InlayKind { Lifetime, Parameter, Type, + Drop, } #[derive(Debug)] @@ -503,7 +506,10 @@ fn hints( ast::Item(it) => match it { // FIXME: record impl lifetimes so they aren't being reused in assoc item lifetime inlay hints ast::Item::Impl(_) => None, - ast::Item::Fn(it) => fn_lifetime_fn::hints(hints, config, it), + ast::Item::Fn(it) => { + implicit_drop::hints(hints, sema, config, &it); + fn_lifetime_fn::hints(hints, config, it) + }, // static type elisions ast::Item::Static(it) => implicit_static::hints(hints, config, Either::Left(it)), ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)), @@ -563,6 +569,7 @@ mod tests { use hir::ClosureStyle; use itertools::Itertools; use test_utils::extract_annotations; + use text_edit::{TextRange, TextSize}; use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode}; use crate::DiscriminantHints; @@ -590,6 +597,7 @@ mod tests { max_length: None, closing_brace_hints_min_lines: None, fields_to_resolve: InlayFieldsToResolve::empty(), + implicit_drop_hints: false, }; pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig { type_hints: true, @@ -629,6 +637,22 @@ mod tests { expect.assert_debug_eq(&inlay_hints) } + #[track_caller] + pub(super) fn check_expect_clear_loc( + config: InlayHintsConfig, + ra_fixture: &str, + expect: Expect, + ) { + let (analysis, file_id) = fixture::file(ra_fixture); + let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); + inlay_hints.iter_mut().flat_map(|hint| &mut hint.label.parts).for_each(|hint| { + if let Some(loc) = &mut hint.linked_location { + loc.range = TextRange::empty(TextSize::from(0)); + } + }); + expect.assert_debug_eq(&inlay_hints) + } + /// Computes inlay hints for the fixture, applies all the provided text edits and then runs /// expect test. #[track_caller] diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs index 12e46c0f88377..c9e9a2237867b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs @@ -78,7 +78,9 @@ mod tests { use expect_test::expect; use crate::{ - inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG}, + inlay_hints::tests::{ + check_expect, check_expect_clear_loc, check_with_config, DISABLED_CONFIG, TEST_CONFIG, + }, InlayHintsConfig, }; @@ -444,7 +446,7 @@ fn main() { #[test] fn shorten_iterator_chaining_hints() { - check_expect( + check_expect_clear_loc( InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG }, r#" //- minicore: iterators @@ -484,7 +486,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 0..0, }, ), tooltip: "", @@ -497,7 +499,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 0..0, }, ), tooltip: "", @@ -522,7 +524,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 0..0, }, ), tooltip: "", @@ -535,7 +537,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 0..0, }, ), tooltip: "", @@ -560,7 +562,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 0..0, }, ), tooltip: "", @@ -573,7 +575,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 0..0, }, ), tooltip: "", @@ -598,7 +600,7 @@ fn main() { file_id: FileId( 0, ), - range: 24..30, + range: 0..0, }, ), tooltip: "", diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs new file mode 100644 index 0000000000000..60f1f3496f6cd --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs @@ -0,0 +1,204 @@ +//! Implementation of "implicit drop" inlay hints: +//! ```no_run +//! fn main() { +//! let x = vec![2]; +//! if some_condition() { +//! /* drop(x) */return; +//! } +//! } +//! ``` +use hir::{ + db::{DefDatabase as _, HirDatabase as _}, + mir::{MirSpan, TerminatorKind}, + ChalkTyInterner, DefWithBody, Semantics, +}; +use ide_db::{base_db::FileRange, RootDatabase}; + +use syntax::{ + ast::{self, AstNode}, + match_ast, +}; + +use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind}; + +pub(super) fn hints( + acc: &mut Vec, + sema: &Semantics<'_, RootDatabase>, + config: &InlayHintsConfig, + def: &ast::Fn, +) -> Option<()> { + if !config.implicit_drop_hints { + return None; + } + + let def = sema.to_def(def)?; + let def: DefWithBody = def.into(); + + let source_map = sema.db.body_with_source_map(def.into()).1; + + let hir = sema.db.body(def.into()); + let mir = sema.db.mir_body(def.into()).ok()?; + + let local_to_binding = mir.local_to_binding_map(); + + for (_, bb) in mir.basic_blocks.iter() { + let terminator = bb.terminator.as_ref()?; + if let TerminatorKind::Drop { place, .. } = terminator.kind { + if !place.projection.is_empty() { + continue; // Ignore complex cases for now + } + if mir.locals[place.local].ty.adt_id(ChalkTyInterner).is_none() { + continue; // Arguably only ADTs have significant drop impls + } + let Some(binding) = local_to_binding.get(place.local) else { + continue; // Ignore temporary values + }; + let range = match terminator.span { + MirSpan::ExprId(e) => match source_map.expr_syntax(e) { + Ok(s) => { + let root = &s.file_syntax(sema.db); + let expr = s.value.to_node(root); + let expr = expr.syntax(); + match_ast! { + match expr { + ast::BlockExpr(x) => x.stmt_list().and_then(|x| x.r_curly_token()).map(|x| x.text_range()).unwrap_or_else(|| expr.text_range()), + _ => expr.text_range(), + } + } + } + Err(_) => continue, + }, + MirSpan::PatId(p) => match source_map.pat_syntax(p) { + Ok(s) => s.value.text_range(), + Err(_) => continue, + }, + MirSpan::Unknown => continue, + }; + let binding = &hir.bindings[*binding]; + let binding_source = binding + .definitions + .first() + .and_then(|d| source_map.pat_syntax(*d).ok()) + .and_then(|d| { + Some(FileRange { file_id: d.file_id.file_id()?, range: d.value.text_range() }) + }); + let name = binding.name.to_smol_str(); + if name.starts_with(" Option<()> { + let x = X; + let t_opt = Some(2); + let t = t_opt?; + //^^^^^^ drop(x) + Some(()) + } + //^ drop(x) +"#, + ); + } + + #[test] + fn if_let() { + check_with_config( + ONLY_DROP_CONFIG, + r#" + struct X; + fn f() { + let x = X; + if let X = x { + let y = X; + } + //^ drop(y) + } + //^ drop(x) +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index aee03d218adff..2320c95b4a1a3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -8,8 +8,9 @@ //! in this crate. // For proving that RootDatabase is RefUnwindSafe. -#![recursion_limit = "128"] #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#![recursion_limit = "128"] #[allow(unused)] macro_rules! eprintln { diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs index 2d0295692ac0b..f387bbf6b0143 100644 --- a/src/tools/rust-analyzer/crates/ide/src/references.rs +++ b/src/tools/rust-analyzer/crates/ide/src/references.rs @@ -683,6 +683,32 @@ enum Foo { ); } + #[test] + fn test_self() { + check( + r#" +struct S$0 { + t: PhantomData, +} + +impl S { + fn new() -> Self { + Self { + t: Default::default(), + } + } +} +"#, + expect![[r#" + S Struct FileId(0) 0..38 7..8 + + FileId(0) 48..49 + FileId(0) 71..75 + FileId(0) 86..90 + "#]], + ) + } + #[test] fn test_find_all_refs_two_modules() { check( diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index 2d528c642558d..07cdddd15f82e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -308,11 +308,7 @@ pub(crate) fn runnable_fn( sema: &Semantics<'_, RootDatabase>, def: hir::Function, ) -> Option { - let name = def.name(sema.db).to_smol_str(); - - let root = def.module(sema.db).krate().root_module(); - - let kind = if name == "main" && def.module(sema.db) == root { + let kind = if def.is_main(sema.db) { RunnableKind::Bin } else { let test_id = || { @@ -320,7 +316,9 @@ pub(crate) fn runnable_fn( let def: hir::ModuleDef = def.into(); def.canonical_path(sema.db) }; - canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name)) + canonical_path + .map(TestId::Path) + .unwrap_or(TestId::Name(def.name(sema.db).to_smol_str())) }; if def.is_test(sema.db) { @@ -587,6 +585,9 @@ mod tests { $0 fn main() {} +#[export_name = "main"] +fn __cortex_m_rt_main_trampoline() {} + #[test] fn test_foo() {} @@ -604,7 +605,7 @@ mod not_a_root { fn main() {} } "#, - &[TestMod, Bin, Test, Test, Test, Bench], + &[TestMod, Bin, Bin, Test, Test, Test, Bench], expect![[r#" [ Runnable { @@ -613,7 +614,7 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 0..190, + full_range: 0..253, name: "", kind: Module, }, @@ -642,8 +643,22 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 15..39, - focus_range: 26..34, + full_range: 15..76, + focus_range: 42..71, + name: "__cortex_m_rt_main_trampoline", + kind: Function, + }, + kind: Bin, + cfg: None, + }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 78..102, + focus_range: 89..97, name: "test_foo", kind: Function, }, @@ -663,8 +678,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 41..92, - focus_range: 73..87, + full_range: 104..155, + focus_range: 136..150, name: "test_full_path", kind: Function, }, @@ -684,8 +699,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 94..128, - focus_range: 115..123, + full_range: 157..191, + focus_range: 178..186, name: "test_foo", kind: Function, }, @@ -705,8 +720,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 130..152, - focus_range: 142..147, + full_range: 193..215, + focus_range: 205..210, name: "bench", kind: Function, }, @@ -1655,12 +1670,18 @@ macro_rules! gen2 { } } } +macro_rules! gen_main { + () => { + fn main() {} + } +} mod tests { gen!(); } gen2!(); +gen_main!(); "#, - &[TestMod, TestMod, Test, Test, TestMod], + &[TestMod, TestMod, Test, Test, TestMod, Bin], expect![[r#" [ Runnable { @@ -1669,7 +1690,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 0..237, + full_range: 0..315, name: "", kind: Module, }, @@ -1684,8 +1705,8 @@ gen2!(); file_id: FileId( 0, ), - full_range: 202..227, - focus_range: 206..211, + full_range: 267..292, + focus_range: 271..276, name: "tests", kind: Module, description: "mod tests", @@ -1701,7 +1722,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 218..225, + full_range: 283..290, name: "foo_test", kind: Function, }, @@ -1721,7 +1742,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 228..236, + full_range: 293..301, name: "foo_test2", kind: Function, }, @@ -1741,7 +1762,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 228..236, + full_range: 293..301, name: "tests2", kind: Module, description: "mod tests2", @@ -1751,6 +1772,19 @@ gen2!(); }, cfg: None, }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 302..314, + name: "main", + kind: Function, + }, + kind: Bin, + cfg: None, + }, ] "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index aabd26da289ca..b54874d59f8bc 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -118,6 +118,7 @@ impl StaticIndex<'_> { adjustment_hints: crate::AdjustmentHints::Never, adjustment_hints_mode: AdjustmentHintsMode::Prefix, adjustment_hints_hide_outside_unsafe: false, + implicit_drop_hints: false, hide_named_constructor_hints: false, hide_closure_initialization_hints: false, closure_style: hir::ClosureStyle::ImplFn, diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index bb01c81d66fbd..dd72484b3807c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs @@ -245,7 +245,7 @@ fn traverse( let mut macro_highlighter = MacroHighlighter::default(); // FIXME: these are not perfectly accurate, we determine them by the real file's syntax tree - // an an attribute nested in a macro call will not emit `inside_attribute` + // an attribute nested in a macro call will not emit `inside_attribute` let mut inside_attribute = false; let mut inside_macro_call = false; diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs index b40509715bafd..d21850bcff3ec 100644 --- a/src/tools/rust-analyzer/crates/ide/src/typing.rs +++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs @@ -47,7 +47,7 @@ struct ExtendedTextEdit { // - typing `=` between two expressions adds `;` when in statement position // - typing `=` to turn an assignment into an equality comparison removes `;` when in expression position // - typing `.` in a chain method call auto-indents -// - typing `{` in front of an expression inserts a closing `}` after the expression +// - typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression // - typing `{` in a use item adds a closing `}` in the right place // // VS Code:: diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs index 2f6332abd2597..3802978f4941e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs @@ -55,6 +55,7 @@ impl fmt::Display for RecursiveMemoryLayout { } } +#[derive(Copy, Clone)] enum FieldOrTupleIdx { Field(Field), TupleIdx(usize), @@ -71,13 +72,6 @@ impl FieldOrTupleIdx { FieldOrTupleIdx::TupleIdx(i) => format!(".{i}").to_owned(), } } - - fn index(&self) -> usize { - match *self { - FieldOrTupleIdx::Field(f) => f.index(), - FieldOrTupleIdx::TupleIdx(i) => i, - } - } } // Feature: View Memory Layout @@ -138,7 +132,10 @@ pub(crate) fn view_memory_layout( return; } - fields.sort_by_key(|(f, _)| layout.field_offset(f.index()).unwrap()); + fields.sort_by_key(|&(f, _)| match f { + FieldOrTupleIdx::Field(f) => layout.field_offset(f).unwrap_or(0), + FieldOrTupleIdx::TupleIdx(f) => layout.tuple_field_offset(f).unwrap_or(0), + }); let children_start = nodes.len(); nodes[parent_idx].children_start = children_start as i64; @@ -151,7 +148,10 @@ pub(crate) fn view_memory_layout( typename: child_ty.display(db).to_string(), size: child_layout.size(), alignment: child_layout.align(), - offset: layout.field_offset(field.index()).unwrap_or(0), + offset: match *field { + FieldOrTupleIdx::Field(f) => layout.field_offset(f).unwrap_or(0), + FieldOrTupleIdx::TupleIdx(f) => layout.tuple_field_offset(f).unwrap_or(0), + }, parent_idx: parent_idx as i64, children_start: -1, children_len: 0, diff --git a/src/tools/rust-analyzer/crates/intern/src/lib.rs b/src/tools/rust-analyzer/crates/intern/src/lib.rs index 2934d26674d7e..d784321c7c7af 100644 --- a/src/tools/rust-analyzer/crates/intern/src/lib.rs +++ b/src/tools/rust-analyzer/crates/intern/src/lib.rs @@ -33,13 +33,10 @@ impl Interned { // - if not, box it up, insert it, and return a clone // This needs to be atomic (locking the shard) to avoid races with other thread, which could // insert the same object between us looking it up and inserting it. - match shard.raw_entry_mut().from_key_hashed_nocheck(hash as u64, &obj) { + match shard.raw_entry_mut().from_key_hashed_nocheck(hash, &obj) { RawEntryMut::Occupied(occ) => Self { arc: occ.key().clone() }, RawEntryMut::Vacant(vac) => Self { - arc: vac - .insert_hashed_nocheck(hash as u64, Arc::new(obj), SharedValue::new(())) - .0 - .clone(), + arc: vac.insert_hashed_nocheck(hash, Arc::new(obj), SharedValue::new(())).0.clone(), }, } } @@ -54,13 +51,10 @@ impl Interned { // - if not, box it up, insert it, and return a clone // This needs to be atomic (locking the shard) to avoid races with other thread, which could // insert the same object between us looking it up and inserting it. - match shard.raw_entry_mut().from_key_hashed_nocheck(hash as u64, s) { + match shard.raw_entry_mut().from_key_hashed_nocheck(hash, s) { RawEntryMut::Occupied(occ) => Self { arc: occ.key().clone() }, RawEntryMut::Vacant(vac) => Self { - arc: vac - .insert_hashed_nocheck(hash as u64, Arc::from(s), SharedValue::new(())) - .0 - .clone(), + arc: vac.insert_hashed_nocheck(hash, Arc::from(s), SharedValue::new(())).0.clone(), }, } } diff --git a/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml b/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml index f041ca88ac08d..31b9f6c76d067 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml +++ b/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml @@ -11,13 +11,13 @@ authors.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.62" +anyhow.workspace = true crossbeam-channel = "0.5.5" -itertools = "0.10.5" -tracing = "0.1.35" +itertools.workspace = true +tracing.workspace = true ide.workspace = true -ide-db.workspace =true +ide-db.workspace = true proc-macro-api.workspace = true project-model.workspace = true tt.workspace = true diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 7a795dd62ab70..68b592ffaa4de 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -208,6 +208,7 @@ impl ProjectFolders { let entry = { let mut dirs = vfs::loader::Directories::default(); dirs.extensions.push("rs".into()); + dirs.extensions.push("toml".into()); dirs.include.extend(root.include); dirs.exclude.extend(root.exclude); for excl in global_excludes { diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml index 82105522ebdd9..adab1003d103b 100644 --- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml +++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml @@ -15,7 +15,7 @@ doctest = false cov-mark = "2.0.0-pre.1" rustc-hash = "1.1.0" smallvec.workspace = true -tracing = "0.1.35" +tracing.workspace = true # local deps syntax.workspace = true diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs index f2d89d3efe5ad..908048c990424 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander.rs @@ -119,7 +119,7 @@ enum Fragment { /// precedence. Note that this impl is different from the one currently in /// `rustc` -- `rustc` doesn't translate fragments into token trees at all. /// - /// At one point in time, we tried to to use "fake" delimiters here a-la + /// At one point in time, we tried to use "fake" delimiters here à la /// proc-macro delimiter=none. As we later discovered, "none" delimiters are /// tricky to handle in the parser, and rustc doesn't handle those either. Expr(tt::TokenTree), diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs index 9d886a1c979a9..a439c9c50d6c6 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs @@ -3,7 +3,7 @@ //! interface, although it contains some code to bridge `SyntaxNode`s and //! `TokenTree`s as well! //! -//! The tes for this functionality live in another crate: +//! The tests for this functionality live in another crate: //! `hir_def::macro_expansion_tests::mbe`. #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml index 09e62c35278e9..efb326323f915 100644 --- a/src/tools/rust-analyzer/crates/parser/Cargo.toml +++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml @@ -13,7 +13,7 @@ doctest = false [dependencies] drop_bomb = "0.1.5" -rustc_lexer.workspace = true +rustc-dependencies.workspace = true limit.workspace = true @@ -22,3 +22,6 @@ expect-test = "1.4.0" stdx.workspace = true sourcegen.workspace = true + +[features] +in-rust-tree = ["rustc-dependencies/in-rust-tree"] diff --git a/src/tools/rust-analyzer/crates/parser/src/event.rs b/src/tools/rust-analyzer/crates/parser/src/event.rs index 577eb0967b426..e38571dd3ec64 100644 --- a/src/tools/rust-analyzer/crates/parser/src/event.rs +++ b/src/tools/rust-analyzer/crates/parser/src/event.rs @@ -2,11 +2,6 @@ //! It is intended to be completely decoupled from the //! parser, so as to allow to evolve the tree representation //! and the parser algorithm independently. -//! -//! The `TreeSink` trait is the bridge between the parser and the -//! tree builder: the parser produces a stream of events like -//! `start node`, `finish node`, and `FileBuilder` converts -//! this stream to a real tree. use std::mem; use crate::{ diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs index 6a2a9adce15cb..19da297b58ccc 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs @@ -376,6 +376,16 @@ fn error_block(p: &mut Parser<'_>, message: &str) { m.complete(p, ERROR); } +// test_err top_level_let +// let ref foo: fn() = 1 + 3; +fn error_let_stmt(p: &mut Parser<'_>, message: &str) { + assert!(p.at(T![let])); + let m = p.start(); + p.error(message); + expressions::let_stmt(p, expressions::Semicolon::Optional); + m.complete(p, ERROR); +} + /// The `parser` passed this is required to at least consume one token if it returns `true`. /// If the `parser` returns false, parsing will stop. fn delimited( diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs index 1cbd1663230bd..e346ece2f94b6 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs @@ -59,7 +59,8 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) { attributes::outer_attrs(p); if p.at(T![let]) { - let_stmt(p, m, semicolon); + let_stmt(p, semicolon); + m.complete(p, LET_STMT); return; } @@ -109,54 +110,53 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) { m.complete(p, EXPR_STMT); } } +} - // test let_stmt - // fn f() { let x: i32 = 92; } - fn let_stmt(p: &mut Parser<'_>, m: Marker, with_semi: Semicolon) { - p.bump(T![let]); - patterns::pattern(p); - if p.at(T![:]) { - // test let_stmt_ascription - // fn f() { let x: i32; } - types::ascription(p); - } +// test let_stmt +// fn f() { let x: i32 = 92; } +pub(super) fn let_stmt(p: &mut Parser<'_>, with_semi: Semicolon) { + p.bump(T![let]); + patterns::pattern(p); + if p.at(T![:]) { + // test let_stmt_ascription + // fn f() { let x: i32; } + types::ascription(p); + } - let mut expr_after_eq: Option = None; - if p.eat(T![=]) { - // test let_stmt_init - // fn f() { let x = 92; } - expr_after_eq = expressions::expr(p); - } + let mut expr_after_eq: Option = None; + if p.eat(T![=]) { + // test let_stmt_init + // fn f() { let x = 92; } + expr_after_eq = expressions::expr(p); + } - if p.at(T![else]) { - // test_err let_else_right_curly_brace - // fn func() { let Some(_) = {Some(1)} else { panic!("h") };} - if let Some(expr) = expr_after_eq { - if BlockLike::is_blocklike(expr.kind()) { - p.error( - "right curly brace `}` before `else` in a `let...else` statement not allowed", - ) - } + if p.at(T![else]) { + // test_err let_else_right_curly_brace + // fn func() { let Some(_) = {Some(1)} else { panic!("h") };} + if let Some(expr) = expr_after_eq { + if BlockLike::is_blocklike(expr.kind()) { + p.error( + "right curly brace `}` before `else` in a `let...else` statement not allowed", + ) } - - // test let_else - // fn f() { let Some(x) = opt else { return }; } - let m = p.start(); - p.bump(T![else]); - block_expr(p); - m.complete(p, LET_ELSE); } - match with_semi { - Semicolon::Forbidden => (), - Semicolon::Optional => { - p.eat(T![;]); - } - Semicolon::Required => { - p.expect(T![;]); - } + // test let_else + // fn f() { let Some(x) = opt else { return }; } + let m = p.start(); + p.bump(T![else]); + block_expr(p); + m.complete(p, LET_ELSE); + } + + match with_semi { + Semicolon::Forbidden => (), + Semicolon::Optional => { + p.eat(T![;]); + } + Semicolon::Required => { + p.expect(T![;]); } - m.complete(p, LET_STMT); } } @@ -693,6 +693,17 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) { // We permit `.. }` on the left-hand side of a destructuring assignment. if !p.at(T!['}']) { expr(p); + + if p.at(T![,]) { + // test_err comma_after_functional_update_syntax + // fn foo() { + // S { ..x, }; + // S { ..x, a: 0 } + // } + + // Do not bump, so we can support additional fields after this comma. + p.error("cannot use a comma after the base struct"); + } } } T!['{'] => { diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs index 4e850b1f74df8..34fd3420f1c99 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs @@ -79,6 +79,7 @@ pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) { e.complete(p, ERROR); } EOF | T!['}'] => p.error("expected an item"), + T![let] => error_let_stmt(p, "expected an item"), _ => p.err_and_bump("expected an item"), } } diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs index 74eae9151a265..846da28cb0164 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs @@ -7,6 +7,9 @@ use super::*; // fn b(x: i32) {} // fn c(x: i32, ) {} // fn d(x: i32, y: ()) {} + +// test_err empty_param_slot +// fn f(y: i32, ,t: i32) {} pub(super) fn param_list_fn_def(p: &mut Parser<'_>) { list_(p, Flavor::FnDef); } @@ -71,7 +74,11 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) { if !p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) { p.error("expected value parameter"); m.abandon(p); - break; + if p.eat(T![,]) { + continue; + } else { + break; + } } param(p, m, flavor); if !p.at(T![,]) { diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index 36c52953a0246..b9e7566fdf9bc 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -8,8 +8,12 @@ //! Note that these tokens, unlike the tokens we feed into the parser, do //! include info about comments and whitespace. +use rustc_dependencies::lexer as rustc_lexer; + use std::ops; +use rustc_lexer::unescape::{EscapeError, Mode}; + use crate::{ SyntaxKind::{self, *}, T, @@ -253,30 +257,60 @@ impl<'a> Converter<'a> { rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { err = "Missing trailing `'` symbol to terminate the character literal"; + } else { + let text = &self.res.text[self.offset + 1..][..len - 1]; + let i = text.rfind('\'').unwrap(); + let text = &text[..i]; + if let Err(e) = rustc_lexer::unescape::unescape_char(text) { + err = error_to_diagnostic_message(e, Mode::Char); + } } CHAR } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { err = "Missing trailing `'` symbol to terminate the byte literal"; + } else { + let text = &self.res.text[self.offset + 2..][..len - 2]; + let i = text.rfind('\'').unwrap(); + let text = &text[..i]; + if let Err(e) = rustc_lexer::unescape::unescape_byte(text) { + err = error_to_diagnostic_message(e, Mode::Byte); + } } + BYTE } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { err = "Missing trailing `\"` symbol to terminate the string literal"; + } else { + let text = &self.res.text[self.offset + 1..][..len - 1]; + let i = text.rfind('"').unwrap(); + let text = &text[..i]; + err = unescape_string_error_message(text, Mode::Str); } STRING } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { err = "Missing trailing `\"` symbol to terminate the byte string literal"; + } else { + let text = &self.res.text[self.offset + 2..][..len - 2]; + let i = text.rfind('"').unwrap(); + let text = &text[..i]; + err = unescape_string_error_message(text, Mode::ByteStr); } BYTE_STRING } rustc_lexer::LiteralKind::CStr { terminated } => { if !terminated { err = "Missing trailing `\"` symbol to terminate the string literal"; + } else { + let text = &self.res.text[self.offset + 2..][..len - 2]; + let i = text.rfind('"').unwrap(); + let text = &text[..i]; + err = unescape_string_error_message(text, Mode::CStr); } C_STRING } @@ -304,3 +338,64 @@ impl<'a> Converter<'a> { self.push(syntax_kind, len, err); } } + +fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { + match error { + EscapeError::ZeroChars => "empty character literal", + EscapeError::MoreThanOneChar => "character literal may only contain one codepoint", + EscapeError::LoneSlash => "", + EscapeError::InvalidEscape if mode == Mode::Byte || mode == Mode::ByteStr => { + "unknown byte escape" + } + EscapeError::InvalidEscape => "unknown character escape", + EscapeError::BareCarriageReturn => "", + EscapeError::BareCarriageReturnInRawString => "", + EscapeError::EscapeOnlyChar if mode == Mode::Byte => "byte constant must be escaped", + EscapeError::EscapeOnlyChar => "character constant must be escaped", + EscapeError::TooShortHexEscape => "numeric character escape is too short", + EscapeError::InvalidCharInHexEscape => "invalid character in numeric character escape", + EscapeError::OutOfRangeHexEscape => "out of range hex escape", + EscapeError::NoBraceInUnicodeEscape => "incorrect unicode escape sequence", + EscapeError::InvalidCharInUnicodeEscape => "invalid character in unicode escape", + EscapeError::EmptyUnicodeEscape => "empty unicode escape", + EscapeError::UnclosedUnicodeEscape => "unterminated unicode escape", + EscapeError::LeadingUnderscoreUnicodeEscape => "invalid start of unicode escape", + EscapeError::OverlongUnicodeEscape => "overlong unicode escape", + EscapeError::LoneSurrogateUnicodeEscape => "invalid unicode character escape", + EscapeError::OutOfRangeUnicodeEscape => "invalid unicode character escape", + EscapeError::UnicodeEscapeInByte => "unicode escape in byte string", + EscapeError::NonAsciiCharInByte if mode == Mode::Byte => { + "non-ASCII character in byte literal" + } + EscapeError::NonAsciiCharInByte if mode == Mode::ByteStr => { + "non-ASCII character in byte string literal" + } + EscapeError::NonAsciiCharInByte => "non-ASCII character in raw byte string literal", + EscapeError::UnskippedWhitespaceWarning => "", + EscapeError::MultipleSkippedLinesWarning => "", + } +} + +fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str { + let mut error_message = ""; + match mode { + Mode::CStr => { + rustc_lexer::unescape::unescape_c_string(text, mode, &mut |_, res| { + if let Err(e) = res { + error_message = error_to_diagnostic_message(e, mode); + } + }); + } + Mode::ByteStr | Mode::Str => { + rustc_lexer::unescape::unescape_literal(text, mode, &mut |_, res| { + if let Err(e) = res { + error_message = error_to_diagnostic_message(e, mode); + } + }); + } + _ => { + // Other Modes are not supported yet or do not apply + } + } + error_message +} diff --git a/src/tools/rust-analyzer/crates/parser/src/lib.rs b/src/tools/rust-analyzer/crates/parser/src/lib.rs index c155e8aaf67b3..fcfd1a50719bd 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lib.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lib.rs @@ -19,6 +19,7 @@ #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] #![allow(rustdoc::private_intra_doc_links)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] mod lexed_str; mod token_set; diff --git a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs index 2c47e3d086d61..57005a6834c90 100644 --- a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs +++ b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs @@ -32,29 +32,27 @@ impl LexedStr<'_> { let kind = self.kind(i); if kind.is_trivia() { was_joint = false + } else if kind == SyntaxKind::IDENT { + let token_text = self.text(i); + let contextual_kw = + SyntaxKind::from_contextual_keyword(token_text).unwrap_or(SyntaxKind::IDENT); + res.push_ident(contextual_kw); } else { - if kind == SyntaxKind::IDENT { - let token_text = self.text(i); - let contextual_kw = SyntaxKind::from_contextual_keyword(token_text) - .unwrap_or(SyntaxKind::IDENT); - res.push_ident(contextual_kw); - } else { - if was_joint { + if was_joint { + res.was_joint(); + } + res.push(kind); + // Tag the token as joint if it is float with a fractional part + // we use this jointness to inform the parser about what token split + // event to emit when we encounter a float literal in a field access + if kind == SyntaxKind::FLOAT_NUMBER { + if !self.text(i).ends_with('.') { res.was_joint(); - } - res.push(kind); - // Tag the token as joint if it is float with a fractional part - // we use this jointness to inform the parser about what token split - // event to emit when we encounter a float literal in a field access - if kind == SyntaxKind::FLOAT_NUMBER { - if !self.text(i).ends_with('.') { - res.was_joint(); - } else { - was_joint = false; - } } else { - was_joint = true; + was_joint = false; } + } else { + was_joint = true; } } } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_char_literals.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_char_literals.rast new file mode 100644 index 0000000000000..7603c9099daad --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_char_literals.rast @@ -0,0 +1,86 @@ +BYTE "b''" error: empty character literal +WHITESPACE "\n" +BYTE "b'\\'" error: Missing trailing `'` symbol to terminate the byte literal +WHITESPACE "\n" +BYTE "b'\n'" error: byte constant must be escaped +WHITESPACE "\n" +BYTE "b'spam'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\x0ff'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\\"a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\na'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\ra'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\ta'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\\\a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\'a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\0a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\u{0}x'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{1F63b}}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\v'" error: unknown byte escape +WHITESPACE "\n" +BYTE "b'\\💩'" error: unknown byte escape +WHITESPACE "\n" +BYTE "b'\\●'" error: unknown byte escape +WHITESPACE "\n" +BYTE "b'\\\\\\r'" error: character literal may only contain one codepoint +WHITESPACE "\n" +BYTE "b'\\x'" error: numeric character escape is too short +WHITESPACE "\n" +BYTE "b'\\x0'" error: numeric character escape is too short +WHITESPACE "\n" +BYTE "b'\\xf'" error: numeric character escape is too short +WHITESPACE "\n" +BYTE "b'\\xa'" error: numeric character escape is too short +WHITESPACE "\n" +BYTE "b'\\xx'" error: invalid character in numeric character escape +WHITESPACE "\n" +BYTE "b'\\xы'" error: invalid character in numeric character escape +WHITESPACE "\n" +BYTE "b'\\x🦀'" error: invalid character in numeric character escape +WHITESPACE "\n" +BYTE "b'\\xtt'" error: invalid character in numeric character escape +WHITESPACE "\n" +BYTE "b'\\u'" error: incorrect unicode escape sequence +WHITESPACE "\n" +BYTE "b'\\u[0123]'" error: incorrect unicode escape sequence +WHITESPACE "\n" +BYTE "b'\\u{0x}'" error: invalid character in unicode escape +WHITESPACE "\n" +BYTE "b'\\u{'" error: unterminated unicode escape +WHITESPACE "\n" +BYTE "b'\\u{0000'" error: unterminated unicode escape +WHITESPACE "\n" +BYTE "b'\\u{}'" error: empty unicode escape +WHITESPACE "\n" +BYTE "b'\\u{_0000}'" error: invalid start of unicode escape +WHITESPACE "\n" +BYTE "b'\\u{0000000}'" error: overlong unicode escape +WHITESPACE "\n" +BYTE "b'\\u{FFFFFF}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{ffffff}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{ffffff}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{DC00}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{DDDD}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{DFFF}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{D800}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{DAAA}'" error: unicode escape in byte string +WHITESPACE "\n" +BYTE "b'\\u{DBFF}'" error: unicode escape in byte string +WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_char_literals.rs b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_char_literals.rs new file mode 100644 index 0000000000000..b2d06e490bd6f --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_char_literals.rs @@ -0,0 +1,44 @@ +b'' +b'\' +b' +' +b'spam' +b'\x0ff' +b'\"a' +b'\na' +b'\ra' +b'\ta' +b'\\a' +b'\'a' +b'\0a' +b'\u{0}x' +b'\u{1F63b}}' +b'\v' +b'\💩' +b'\●' +b'\\\r' +b'\x' +b'\x0' +b'\xf' +b'\xa' +b'\xx' +b'\xы' +b'\x🦀' +b'\xtt' +b'\u' +b'\u[0123]' +b'\u{0x}' +b'\u{' +b'\u{0000' +b'\u{}' +b'\u{_0000}' +b'\u{0000000}' +b'\u{FFFFFF}' +b'\u{ffffff}' +b'\u{ffffff}' +b'\u{DC00}' +b'\u{DDDD}' +b'\u{DFFF}' +b'\u{D800}' +b'\u{DAAA}' +b'\u{DBFF}' diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_strings.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_strings.rast new file mode 100644 index 0000000000000..e8d8ff8cefb42 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_strings.rast @@ -0,0 +1,28 @@ +BYTE_STRING "b\"\\💩\"" error: unknown byte escape +WHITESPACE "\n" +BYTE_STRING "b\"\\●\"" error: unknown byte escape +WHITESPACE "\n" +BYTE_STRING "b\"\\u{_0000}\"" error: invalid start of unicode escape +WHITESPACE "\n" +BYTE_STRING "b\"\\u{0000000}\"" error: overlong unicode escape +WHITESPACE "\n" +BYTE_STRING "b\"\\u{FFFFFF}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{ffffff}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{ffffff}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DC00}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DDDD}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DFFF}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{D800}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DAAA}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\u{DBFF}\"" error: unicode escape in byte string +WHITESPACE "\n" +BYTE_STRING "b\"\\xы\"" error: invalid character in numeric character escape +WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_strings.rs b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_strings.rs new file mode 100644 index 0000000000000..e74847137b1ea --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/byte_strings.rs @@ -0,0 +1,14 @@ +b"\💩" +b"\●" +b"\u{_0000}" +b"\u{0000000}" +b"\u{FFFFFF}" +b"\u{ffffff}" +b"\u{ffffff}" +b"\u{DC00}" +b"\u{DDDD}" +b"\u{DFFF}" +b"\u{D800}" +b"\u{DAAA}" +b"\u{DBFF}" +b"\xы" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/c_strings.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/c_strings.rast new file mode 100644 index 0000000000000..1b4424ba5c781 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/c_strings.rast @@ -0,0 +1,28 @@ +C_STRING "c\"\\💩\"" error: unknown character escape +WHITESPACE "\n" +C_STRING "c\"\\●\"" error: unknown character escape +WHITESPACE "\n" +C_STRING "c\"\\u{_0000}\"" error: invalid start of unicode escape +WHITESPACE "\n" +C_STRING "c\"\\u{0000000}\"" error: overlong unicode escape +WHITESPACE "\n" +C_STRING "c\"\\u{FFFFFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{ffffff}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{ffffff}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DC00}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DDDD}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DFFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{D800}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DAAA}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\u{DBFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +C_STRING "c\"\\xы\"" error: invalid character in numeric character escape +WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/c_strings.rs b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/c_strings.rs new file mode 100644 index 0000000000000..1b78ffc28a00d --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/c_strings.rs @@ -0,0 +1,14 @@ +c"\💩" +c"\●" +c"\u{_0000}" +c"\u{0000000}" +c"\u{FFFFFF}" +c"\u{ffffff}" +c"\u{ffffff}" +c"\u{DC00}" +c"\u{DDDD}" +c"\u{DFFF}" +c"\u{D800}" +c"\u{DAAA}" +c"\u{DBFF}" +c"\xы" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/char_literals.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/char_literals.rast new file mode 100644 index 0000000000000..b1e1364d4c2ce --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/char_literals.rast @@ -0,0 +1,92 @@ +CHAR "'hello'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "''" error: empty character literal +WHITESPACE "\n" +CHAR "'\n'" error: character constant must be escaped +WHITESPACE "\n" +CHAR "'spam'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\x0ff'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\\"a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\na'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\ra'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\ta'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\\\a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\'a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\0a'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\u{0}x'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\u{1F63b}}'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\v'" error: unknown character escape +WHITESPACE "\n" +CHAR "'\\💩'" error: unknown character escape +WHITESPACE "\n" +CHAR "'\\●'" error: unknown character escape +WHITESPACE "\n" +CHAR "'\\\\\\r'" error: character literal may only contain one codepoint +WHITESPACE "\n" +CHAR "'\\x'" error: numeric character escape is too short +WHITESPACE "\n" +CHAR "'\\x0'" error: numeric character escape is too short +WHITESPACE "\n" +CHAR "'\\xf'" error: numeric character escape is too short +WHITESPACE "\n" +CHAR "'\\xa'" error: numeric character escape is too short +WHITESPACE "\n" +CHAR "'\\xx'" error: invalid character in numeric character escape +WHITESPACE "\n" +CHAR "'\\xы'" error: invalid character in numeric character escape +WHITESPACE "\n" +CHAR "'\\x🦀'" error: invalid character in numeric character escape +WHITESPACE "\n" +CHAR "'\\xtt'" error: invalid character in numeric character escape +WHITESPACE "\n" +CHAR "'\\xff'" error: out of range hex escape +WHITESPACE "\n" +CHAR "'\\xFF'" error: out of range hex escape +WHITESPACE "\n" +CHAR "'\\x80'" error: out of range hex escape +WHITESPACE "\n" +CHAR "'\\u'" error: incorrect unicode escape sequence +WHITESPACE "\n" +CHAR "'\\u[0123]'" error: incorrect unicode escape sequence +WHITESPACE "\n" +CHAR "'\\u{0x}'" error: invalid character in unicode escape +WHITESPACE "\n" +CHAR "'\\u{'" error: unterminated unicode escape +WHITESPACE "\n" +CHAR "'\\u{0000'" error: unterminated unicode escape +WHITESPACE "\n" +CHAR "'\\u{}'" error: empty unicode escape +WHITESPACE "\n" +CHAR "'\\u{_0000}'" error: invalid start of unicode escape +WHITESPACE "\n" +CHAR "'\\u{0000000}'" error: overlong unicode escape +WHITESPACE "\n" +CHAR "'\\u{FFFFFF}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{ffffff}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{ffffff}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DC00}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DDDD}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DFFF}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{D800}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DAAA}'" error: invalid unicode character escape +WHITESPACE "\n" +CHAR "'\\u{DBFF}'" error: invalid unicode character escape +WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/char_literals.rs b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/char_literals.rs new file mode 100644 index 0000000000000..291f99d8020cf --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/char_literals.rs @@ -0,0 +1,47 @@ +'hello' +'' +' +' +'spam' +'\x0ff' +'\"a' +'\na' +'\ra' +'\ta' +'\\a' +'\'a' +'\0a' +'\u{0}x' +'\u{1F63b}}' +'\v' +'\💩' +'\●' +'\\\r' +'\x' +'\x0' +'\xf' +'\xa' +'\xx' +'\xы' +'\x🦀' +'\xtt' +'\xff' +'\xFF' +'\x80' +'\u' +'\u[0123]' +'\u{0x}' +'\u{' +'\u{0000' +'\u{}' +'\u{_0000}' +'\u{0000000}' +'\u{FFFFFF}' +'\u{ffffff}' +'\u{ffffff}' +'\u{DC00}' +'\u{DDDD}' +'\u{DFFF}' +'\u{D800}' +'\u{DAAA}' +'\u{DBFF}' diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/strings.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/strings.rast new file mode 100644 index 0000000000000..0cd1747208e4d --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/strings.rast @@ -0,0 +1,28 @@ +STRING "\"\\💩\"" error: unknown character escape +WHITESPACE "\n" +STRING "\"\\●\"" error: unknown character escape +WHITESPACE "\n" +STRING "\"\\u{_0000}\"" error: invalid start of unicode escape +WHITESPACE "\n" +STRING "\"\\u{0000000}\"" error: overlong unicode escape +WHITESPACE "\n" +STRING "\"\\u{FFFFFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{ffffff}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{ffffff}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DC00}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DDDD}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DFFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{D800}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DAAA}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\u{DBFF}\"" error: invalid unicode character escape +WHITESPACE "\n" +STRING "\"\\xы\"" error: invalid character in numeric character escape +WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/strings.rs b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/strings.rs new file mode 100644 index 0000000000000..2499516d3fa9f --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/err/strings.rs @@ -0,0 +1,14 @@ +"\💩" +"\●" +"\u{_0000}" +"\u{0000000}" +"\u{FFFFFF}" +"\u{ffffff}" +"\u{ffffff}" +"\u{DC00}" +"\u{DDDD}" +"\u{DFFF}" +"\u{D800}" +"\u{DAAA}" +"\u{DBFF}" +"\xы" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/byte_strings.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/byte_strings.rast index c848ac368e4f6..fd20ca57ac6c3 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/byte_strings.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/byte_strings.rast @@ -1,13 +1,9 @@ -BYTE "b''" -WHITESPACE " " BYTE "b'x'" WHITESPACE " " BYTE_STRING "b\"foo\"" WHITESPACE " " BYTE_STRING "br\"\"" WHITESPACE "\n" -BYTE "b''suf" -WHITESPACE " " BYTE_STRING "b\"\"ix" WHITESPACE " " BYTE_STRING "br\"\"br" @@ -17,6 +13,4 @@ WHITESPACE " " BYTE "b'\\\\'" WHITESPACE " " BYTE "b'\\''" -WHITESPACE " " -BYTE "b'hello'" WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/byte_strings.rs b/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/byte_strings.rs index b54930f5e699c..65460d02cb27c 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/byte_strings.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/byte_strings.rs @@ -1,3 +1,3 @@ -b'' b'x' b"foo" br"" -b''suf b""ix br""br -b'\n' b'\\' b'\'' b'hello' +b'x' b"foo" br"" +b""ix br""br +b'\n' b'\\' b'\'' diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/chars.rast b/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/chars.rast index 66e58cc298f40..07172a4ecc0ad 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/chars.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/chars.rast @@ -4,8 +4,6 @@ CHAR "' '" WHITESPACE " " CHAR "'0'" WHITESPACE " " -CHAR "'hello'" -WHITESPACE " " CHAR "'\\x7f'" WHITESPACE " " CHAR "'\\n'" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/chars.rs b/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/chars.rs index 454ee0a5f6172..15f52c113c119 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/chars.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/lexer/ok/chars.rs @@ -1 +1 @@ -'x' ' ' '0' 'hello' '\x7f' '\n' '\\' '\'' +'x' ' ' '0' '\x7f' '\n' '\\' '\'' diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast new file mode 100644 index 0000000000000..39e35a81ee27c --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast @@ -0,0 +1,41 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "f" + PARAM_LIST + L_PAREN "(" + PARAM + IDENT_PAT + NAME + IDENT "y" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "i32" + COMMA "," + WHITESPACE " " + COMMA "," + PARAM + IDENT_PAT + NAME + IDENT "t" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "i32" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + R_CURLY "}" + WHITESPACE "\n" +error 12: expected value parameter diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs new file mode 100644 index 0000000000000..0adf7b8d2f023 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs @@ -0,0 +1 @@ +fn f(y: i32, ,t: i32) {} diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast new file mode 100644 index 0000000000000..0e2fe5988d6aa --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast @@ -0,0 +1,66 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" + COMMA "," + WHITESPACE " " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n " + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE " " + DOT2 ".." + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" + COMMA "," + WHITESPACE " " + RECORD_EXPR_FIELD + NAME_REF + IDENT "a" + COLON ":" + WHITESPACE " " + LITERAL + INT_NUMBER "0" + WHITESPACE " " + R_CURLY "}" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" +error 22: cannot use a comma after the base struct +error 38: cannot use a comma after the base struct diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs new file mode 100644 index 0000000000000..14cf96719b464 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs @@ -0,0 +1,4 @@ +fn foo() { + S { ..x, }; + S { ..x, a: 0 } +} diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast new file mode 100644 index 0000000000000..5ddef5f3f03f6 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast @@ -0,0 +1,30 @@ +SOURCE_FILE + ERROR + LET_KW "let" + WHITESPACE " " + IDENT_PAT + REF_KW "ref" + WHITESPACE " " + NAME + IDENT "foo" + COLON ":" + WHITESPACE " " + FN_PTR_TYPE + FN_KW "fn" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + EQ "=" + WHITESPACE " " + BIN_EXPR + LITERAL + INT_NUMBER "1" + WHITESPACE " " + PLUS "+" + WHITESPACE " " + LITERAL + INT_NUMBER "3" + SEMICOLON ";" + WHITESPACE "\n" +error 0: expected an item diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs new file mode 100644 index 0000000000000..3d3e7dd56c71c --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs @@ -0,0 +1 @@ +let ref foo: fn() = 1 + 3; diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml index 4229f289130f9..2c2d2e8a94525 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml @@ -21,7 +21,7 @@ object = { version = "0.32.0", default-features = false, features = [ ] } serde.workspace = true serde_json = { workspace = true, features = ["unbounded_depth"] } -tracing = "0.1.37" +tracing.workspace = true triomphe.workspace = true memmap2 = "0.5.4" snap = "1.1.0" diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 84bd15efb8bee..58833cb7e9264 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -13,7 +13,7 @@ #![cfg(feature = "sysroot-abi")] #![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)] #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] -#![allow(unreachable_pub)] +#![allow(unreachable_pub, internal_features)] extern crate proc_macro; diff --git a/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml index 77b4afd7d7e13..12d7c07d3ed9e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true doctest = false [build-dependencies] -cargo_metadata = "0.15.0" +cargo_metadata.workspace = true proc-macro-test-impl = { path = "imp", version = "0.0.0" } diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml index 937834a82aefa..56ce9d11c085f 100644 --- a/src/tools/rust-analyzer/crates/profile/Cargo.toml +++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml @@ -14,8 +14,8 @@ doctest = false [dependencies] once_cell = "1.17.0" cfg-if = "1.0.0" -libc = "0.2.135" la-arena.workspace = true +libc.workspace = true countme = { version = "3.0.1", features = ["enable"] } jemalloc-ctl = { version = "0.5.0", package = "tikv-jemalloc-ctl", optional = true } diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml index 75977fc5b04fe..3e48de6456b0a 100644 --- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml +++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml @@ -12,16 +12,16 @@ rust-version.workspace = true doctest = false [dependencies] -tracing = "0.1.35" +anyhow.workspace = true +cargo_metadata.workspace = true rustc-hash = "1.1.0" -cargo_metadata = "0.15.0" semver = "1.0.14" serde_json.workspace = true serde.workspace = true +tracing.workspace = true triomphe.workspace = true -anyhow = "1.0.62" la-arena.workspace = true -itertools = "0.10.5" +itertools.workspace = true # local deps base-db.workspace = true diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs index fb0f3ab7d1742..68cd40c040b3d 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs @@ -73,6 +73,10 @@ impl WorkspaceBuildScripts { cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]); cmd.args(&config.extra_args); + if let Some(target_dir) = &config.target_dir { + cmd.arg("--target-dir").arg(target_dir); + } + // --all-targets includes tests, benches and examples in addition to the // default lib and bins. This is an independent concept from the --target // flag below. diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index e47808a2cc9fc..ca3d6e0596ca4 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -96,6 +96,8 @@ pub struct CargoConfig { pub extra_env: FxHashMap, pub invocation_strategy: InvocationStrategy, pub invocation_location: InvocationLocation, + /// Optional path to use instead of `target` when building + pub target_dir: Option, } pub type Package = Idx; diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs index 80897f7478cf9..931eba1157663 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs @@ -49,7 +49,7 @@ //! user explores them belongs to that extension (it's totally valid to change //! rust-project.json over time via configuration request!) -use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, Edition}; +use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, DependencyKind, Edition}; use la_arena::RawIdx; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::FxHashMap; @@ -135,6 +135,7 @@ impl ProjectJson { Dependency::new( dep_data.name, CrateId::from_raw(RawIdx::from(dep_data.krate as u32)), + DependencyKind::Normal, ) }) .collect::>(), diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 7815b9dda77f2..98f3063bb9829 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -249,3 +249,55 @@ fn crate_graph_dedup() { crate_graph.extend(regex_crate_graph, &mut regex_proc_macros); assert_eq!(crate_graph.iter().count(), 118); } + +#[test] +fn test_deduplicate_origin_dev() { + let path_map = &mut Default::default(); + let (mut crate_graph, _proc_macros) = + load_cargo_with_sysroot(path_map, "deduplication_crate_graph_A.json"); + crate_graph.sort_deps(); + let (crate_graph_1, mut _proc_macros_2) = + load_cargo_with_sysroot(path_map, "deduplication_crate_graph_B.json"); + + crate_graph.extend(crate_graph_1, &mut _proc_macros_2); + + let mut crates_named_p2 = vec![]; + for id in crate_graph.iter() { + let krate = &crate_graph[id]; + if let Some(name) = krate.display_name.as_ref() { + if name.to_string() == "p2" { + crates_named_p2.push(krate); + } + } + } + + assert!(crates_named_p2.len() == 1); + let p2 = crates_named_p2[0]; + assert!(p2.origin.is_local()); +} + +#[test] +fn test_deduplicate_origin_dev_rev() { + let path_map = &mut Default::default(); + let (mut crate_graph, _proc_macros) = + load_cargo_with_sysroot(path_map, "deduplication_crate_graph_B.json"); + crate_graph.sort_deps(); + let (crate_graph_1, mut _proc_macros_2) = + load_cargo_with_sysroot(path_map, "deduplication_crate_graph_A.json"); + + crate_graph.extend(crate_graph_1, &mut _proc_macros_2); + + let mut crates_named_p2 = vec![]; + for id in crate_graph.iter() { + let krate = &crate_graph[id]; + if let Some(name) = krate.display_name.as_ref() { + if name.to_string() == "p2" { + crates_named_p2.push(krate); + } + } + } + + assert!(crates_named_p2.len() == 1); + let p2 = crates_named_p2[0]; + assert!(p2.origin.is_local()); +} diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index e0209ca15a539..9333570354a0c 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -6,8 +6,8 @@ use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr, use anyhow::{format_err, Context}; use base_db::{ - CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env, - FileId, LangCrateOrigin, ProcMacroPaths, ReleaseChannel, TargetLayoutLoadResult, + CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, DependencyKind, + Edition, Env, FileId, LangCrateOrigin, ProcMacroPaths, ReleaseChannel, TargetLayoutLoadResult, }; use cfg::{CfgDiff, CfgOptions}; use paths::{AbsPath, AbsPathBuf}; @@ -834,7 +834,7 @@ fn project_json_to_crate_graph( for dep in &krate.deps { if let Some(&to) = crates.get(&dep.crate_id) { - add_dep(crate_graph, from, dep.name.clone(), to) + add_dep(crate_graph, from, dep.name.clone(), to, dep.kind().to_owned()) } } } @@ -979,7 +979,7 @@ fn cargo_to_crate_graph( // cargo metadata does not do any normalization, // so we do it ourselves currently let name = CrateName::normalize_dashes(&name); - add_dep(crate_graph, from, name, to); + add_dep(crate_graph, from, name, to, DependencyKind::Normal); } } } @@ -999,7 +999,17 @@ fn cargo_to_crate_graph( continue; } - add_dep(crate_graph, from, name.clone(), to) + add_dep( + crate_graph, + from, + name.clone(), + to, + match dep.kind { + DepKind::Normal => DependencyKind::Normal, + DepKind::Dev => DependencyKind::Dev, + DepKind::Build => DependencyKind::Build, + }, + ) } } } @@ -1187,7 +1197,17 @@ fn handle_rustc_crates( let name = CrateName::new(&dep.name).unwrap(); if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { - add_dep(crate_graph, from, name.clone(), to); + add_dep( + crate_graph, + from, + name.clone(), + to, + match dep.kind { + DepKind::Normal => DependencyKind::Normal, + DepKind::Dev => DependencyKind::Dev, + DepKind::Build => DependencyKind::Build, + }, + ); } } } @@ -1209,7 +1229,7 @@ fn handle_rustc_crates( // `rust_analyzer` thinks that it should use the one from the `rustc_source` // instead of the one from `crates.io` if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) { - add_dep(crate_graph, *from, name.clone(), to); + add_dep(crate_graph, *from, name.clone(), to, DependencyKind::Normal); } } } @@ -1308,7 +1328,14 @@ impl SysrootPublicDeps { /// Makes `from` depend on the public sysroot crates. fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) { for (name, krate, prelude) in &self.deps { - add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude); + add_dep_with_prelude( + crate_graph, + from, + name.clone(), + *krate, + *prelude, + DependencyKind::Normal, + ); } } } @@ -1363,7 +1390,7 @@ fn sysroot_to_crate_graph( for &to in sysroot[from].deps.iter() { let name = CrateName::new(&sysroot[to].name).unwrap(); if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) { - add_dep(crate_graph, from, name, to); + add_dep(crate_graph, from, name, to, DependencyKind::Normal); } } } @@ -1442,8 +1469,14 @@ fn handle_hack_cargo_workspace( .collect() } -fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) { - add_dep_inner(graph, from, Dependency::new(name, to)) +fn add_dep( + graph: &mut CrateGraph, + from: CrateId, + name: CrateName, + to: CrateId, + kind: DependencyKind, +) { + add_dep_inner(graph, from, Dependency::new(name, to, kind)) } fn add_dep_with_prelude( @@ -1452,12 +1485,20 @@ fn add_dep_with_prelude( name: CrateName, to: CrateId, prelude: bool, + kind: DependencyKind, ) { - add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude)) + add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude, kind)) } fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, prelude: bool) { - add_dep_with_prelude(crate_graph, from, CrateName::new("proc_macro").unwrap(), to, prelude); + add_dep_with_prelude( + crate_graph, + from, + CrateName::new("proc_macro").unwrap(), + to, + prelude, + DependencyKind::Normal, + ); } fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) { diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_A.json b/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_A.json new file mode 100644 index 0000000000000..b0fb5845cef76 --- /dev/null +++ b/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_A.json @@ -0,0 +1,140 @@ +{ + "packages": [ + { + "name": "p1", + "version": "0.1.0", + "id": "p1 0.1.0 (path+file:///example_project/p1)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "p2", + "source": null, + "req": "*", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": null, + "path": "$ROOT$example_project/p2" + } + ], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "p1", + "src_path": "$ROOT$example_project/p1/src/lib.rs", + "edition": "2021", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "$ROOT$example_project/p1/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "p2", + "version": "0.1.0", + "id": "p2 0.1.0 (path+file:///example_project/p2)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "p2", + "src_path": "$ROOT$example_project/p2/src/lib.rs", + "edition": "2021", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "$ROOT$example_project/p2/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + } + ], + "workspace_members": [ + "p1 0.1.0 (path+file:///example_project/p1)" + ], + "workspace_default_members": [ + "p1 0.1.0 (path+file:///example_project/p1)" + ], + "resolve": { + "nodes": [ + { + "id": "p1 0.1.0 (path+file:///example_project/p1)", + "dependencies": [ + "p2 0.1.0 (path+file:///example_project/p2)" + ], + "deps": [ + { + "name": "p2", + "pkg": "p2 0.1.0 (path+file:///example_project/p2)", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] + } + ], + "features": [] + }, + { + "id": "p2 0.1.0 (path+file:///example_project/p2)", + "dependencies": [], + "deps": [], + "features": [] + } + ], + "root": "p1 0.1.0 (path+file:///example_project/p1)" + }, + "target_directory": "$ROOT$example_project/p1/target", + "version": 1, + "workspace_root": "$ROOT$example_project/p1", + "metadata": null +} \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_B.json b/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_B.json new file mode 100644 index 0000000000000..b5d1e16e62e03 --- /dev/null +++ b/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_B.json @@ -0,0 +1,66 @@ +{ + "packages": [ + { + "name": "p2", + "version": "0.1.0", + "id": "p2 0.1.0 (path+file:///example_project/p2)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "p2", + "src_path": "$ROOT$example_project/p2/src/lib.rs", + "edition": "2021", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "$ROOT$example_project/p2/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + } + ], + "workspace_members": [ + "p2 0.1.0 (path+file:///example_project/p2)" + ], + "workspace_default_members": [ + "p2 0.1.0 (path+file:///example_project/p2)" + ], + "resolve": { + "nodes": [ + { + "id": "p2 0.1.0 (path+file:///example_project/p2)", + "dependencies": [], + "deps": [], + "features": [] + } + ], + "root": "p2 0.1.0 (path+file:///example_project/p2)" + }, + "target_directory": "$ROOT$example_project/p2/target", + "version": 1, + "workspace_root": "$ROOT$example_project/p2", + "metadata": null +} \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt index 727d39a3077cd..e98f016ca7df3 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt @@ -48,6 +48,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -112,6 +113,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -119,6 +121,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -183,6 +186,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -190,6 +194,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -254,6 +259,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -261,6 +267,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt index 727d39a3077cd..e98f016ca7df3 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt @@ -48,6 +48,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -112,6 +113,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -119,6 +121,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -183,6 +186,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -190,6 +194,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -254,6 +259,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -261,6 +267,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt index 89728babd82ef..7ecd53572e2f3 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt @@ -47,6 +47,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -110,6 +111,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -117,6 +119,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -180,6 +183,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -187,6 +191,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], @@ -250,6 +255,7 @@ name: CrateName( "hello_world", ), + kind: Normal, prelude: true, }, Dependency { @@ -257,6 +263,7 @@ name: CrateName( "libc", ), + kind: Normal, prelude: true, }, ], diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt index b7bf6cb2774ea..581a6afc148fa 100644 --- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt +++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt @@ -28,6 +28,7 @@ name: CrateName( "core", ), + kind: Normal, prelude: true, }, ], @@ -168,6 +169,7 @@ name: CrateName( "std", ), + kind: Normal, prelude: true, }, Dependency { @@ -175,6 +177,7 @@ name: CrateName( "core", ), + kind: Normal, prelude: true, }, ], @@ -249,6 +252,7 @@ name: CrateName( "alloc", ), + kind: Normal, prelude: true, }, Dependency { @@ -256,6 +260,7 @@ name: CrateName( "panic_unwind", ), + kind: Normal, prelude: true, }, Dependency { @@ -263,6 +268,7 @@ name: CrateName( "panic_abort", ), + kind: Normal, prelude: true, }, Dependency { @@ -270,6 +276,7 @@ name: CrateName( "core", ), + kind: Normal, prelude: true, }, Dependency { @@ -277,6 +284,7 @@ name: CrateName( "profiler_builtins", ), + kind: Normal, prelude: true, }, Dependency { @@ -284,6 +292,7 @@ name: CrateName( "unwind", ), + kind: Normal, prelude: true, }, Dependency { @@ -291,6 +300,7 @@ name: CrateName( "std_detect", ), + kind: Normal, prelude: true, }, Dependency { @@ -298,6 +308,7 @@ name: CrateName( "test", ), + kind: Normal, prelude: true, }, ], @@ -438,6 +449,7 @@ name: CrateName( "core", ), + kind: Normal, prelude: true, }, Dependency { @@ -445,6 +457,7 @@ name: CrateName( "alloc", ), + kind: Normal, prelude: true, }, Dependency { @@ -452,6 +465,7 @@ name: CrateName( "std", ), + kind: Normal, prelude: true, }, Dependency { @@ -459,6 +473,7 @@ name: CrateName( "test", ), + kind: Normal, prelude: false, }, Dependency { @@ -466,6 +481,7 @@ name: CrateName( "proc_macro", ), + kind: Normal, prelude: false, }, ], diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index 7410f0a3a668e..76f764460329b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -19,30 +19,26 @@ name = "rust-analyzer" path = "src/bin/main.rs" [dependencies] -anyhow = "1.0.62" +anyhow.workspace = true crossbeam-channel = "0.5.5" -dissimilar = "1.0.4" -itertools = "0.10.5" -scip = "0.1.1" +dissimilar.workspace = true +itertools.workspace = true +scip = "0.3.1" lsp-types = { version = "=0.94.0", features = ["proposed"] } parking_lot = "0.12.1" xflags = "0.3.0" oorandom = "11.1.3" +rayon.workspace = true rustc-hash = "1.1.0" serde_json = { workspace = true, features = ["preserve_order"] } serde.workspace = true -rayon = "1.6.1" num_cpus = "1.15.0" mimalloc = { version = "0.1.30", default-features = false, optional = true } lsp-server.workspace = true -tracing = "0.1.35" -tracing-subscriber = { version = "0.3.16", default-features = false, features = [ - "registry", - "fmt", - "tracing-log", -] } -tracing-log = "0.1.3" -tracing-tree = "0.2.1" +tracing.workspace = true +tracing-subscriber.workspace = true +tracing-log = "0.2.0" +tracing-tree.workspace = true triomphe.workspace = true nohash-hasher.workspace = true always-assert = "0.1.2" @@ -57,6 +53,7 @@ flycheck.workspace = true hir-def.workspace = true hir-ty.workspace = true hir.workspace = true +rustc-dependencies.workspace = true ide-db.workspace = true # This should only be used in CLI ide-ssr.workspace = true @@ -67,6 +64,7 @@ profile.workspace = true project-model.workspace = true stdx.workspace = true syntax.workspace = true +parser.workspace = true toolchain.workspace = true vfs-notify.workspace = true vfs.workspace = true @@ -79,7 +77,7 @@ jemallocator = { version = "0.5.0", package = "tikv-jemallocator", optional = tr [dev-dependencies] expect-test = "1.4.0" -xshell = "0.2.2" +xshell.workspace = true test-utils.workspace = true sourcegen.workspace = true @@ -89,4 +87,13 @@ mbe.workspace = true jemalloc = ["jemallocator", "profile/jemalloc"] force-always-assert = ["always-assert/force"] sysroot-abi = [] -in-rust-tree = ["sysroot-abi", "ide/in-rust-tree", "syntax/in-rust-tree"] +in-rust-tree = [ + "sysroot-abi", + "ide/in-rust-tree", + "syntax/in-rust-tree", + "parser/in-rust-tree", + "rustc-dependencies/in-rust-tree", + "hir/in-rust-tree", + "hir-def/in-rust-tree", + "hir-ty/in-rust-tree", +] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs index 2fa14fc7e283f..a7d0a0b0dfc47 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs @@ -3,6 +3,10 @@ //! Based on cli flags, either spawns an LSP server, or runs a batch analysis #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] +#[cfg(feature = "in-rust-tree")] +#[allow(unused_extern_crates)] +extern crate rustc_driver; mod logger; mod rustc_wrapper; @@ -190,6 +194,12 @@ fn run_server() -> anyhow::Result<()> { } }; + let mut is_visual_studio_code = false; + if let Some(client_info) = client_info { + tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); + is_visual_studio_code = client_info.name.starts_with("Visual Studio Code"); + } + let workspace_roots = workspace_folders .map(|workspaces| { workspaces @@ -201,7 +211,7 @@ fn run_server() -> anyhow::Result<()> { }) .filter(|workspaces| !workspaces.is_empty()) .unwrap_or_else(|| vec![root_path.clone()]); - let mut config = Config::new(root_path, capabilities, workspace_roots); + let mut config = Config::new(root_path, capabilities, workspace_roots, is_visual_studio_code); if let Some(json) = initialization_options { if let Err(e) = config.update(json) { use lsp_types::{ @@ -231,10 +241,6 @@ fn run_server() -> anyhow::Result<()> { connection.initialize_finish(initialize_id, initialize_result)?; - if let Some(client_info) = client_info { - tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); - } - if !config.has_linked_projects() && config.detached_files().is_empty() { config.rediscover_workspaces(); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index dcb3ca6581cb0..b4debba38c974 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -762,7 +762,8 @@ impl flags::AnalysisStats { group: true, skip_glob_imports: true, }, - prefer_no_std: Default::default(), + prefer_no_std: false, + prefer_prelude: true, }, ide::AssistResolveStrategy::All, file_id, @@ -782,6 +783,7 @@ impl flags::AnalysisStats { closure_return_type_hints: ide::ClosureReturnTypeHints::Always, closure_capture_hints: true, binding_mode_hints: true, + implicit_drop_hints: true, lifetime_elision_hints: ide::LifetimeElisionHints::Always, param_names_for_lifetime_elision_hints: true, hide_named_constructor_hints: false, @@ -846,9 +848,7 @@ fn location_csv_pat(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, pat_id: Pa Err(SyntheticSyntax) => return "synthetic,,".to_string(), }; let root = db.parse_or_expand(src.file_id); - let node = src.map(|e| { - e.either(|it| it.to_node(&root).syntax().clone(), |it| it.to_node(&root).syntax().clone()) - }); + let node = src.map(|e| e.to_node(&root).syntax().clone()); let original_range = node.as_ref().original_file_range(db); let path = vfs.file_path(original_range.file_id); let line_index = db.line_index(original_range.file_id); @@ -888,12 +888,7 @@ fn pat_syntax_range( let src = sm.pat_syntax(pat_id); if let Ok(src) = src { let root = db.parse_or_expand(src.file_id); - let node = src.map(|e| { - e.either( - |it| it.to_node(&root).syntax().clone(), - |it| it.to_node(&root).syntax().clone(), - ) - }); + let node = src.map(|e| e.to_node(&root).syntax().clone()); let original_range = node.as_ref().original_file_range(db); let path = vfs.file_path(original_range.file_id); let line_index = db.line_index(original_range.file_id); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs index 419440b6df7b6..fe5022f8606d1 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs @@ -131,6 +131,9 @@ xflags::xflags! { /// The output path where the SCIP file will be written to. Defaults to `index.scip`. optional --output path: PathBuf + + /// A path to an json configuration file that can be used to customize cargo behavior. + optional --config-path config_path: PathBuf } } } @@ -239,6 +242,7 @@ pub struct Scip { pub path: PathBuf, pub output: Option, + pub config_path: Option, } impl RustAnalyzer { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index 8c056fff000e6..30e11402cd8d0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -11,10 +11,8 @@ use ide::{ TokenStaticData, }; use ide_db::LineIndexDatabase; -use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice}; -use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource}; +use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice}; use scip::types as scip_types; -use std::env; use crate::{ cli::flags, @@ -25,8 +23,6 @@ impl flags::Scip { pub fn run(self) -> anyhow::Result<()> { eprintln!("Generating SCIP start..."); let now = Instant::now(); - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); let no_progress = &|s| (eprintln!("rust-analyzer: Loading {s}")); let load_cargo_config = LoadCargoConfig { @@ -34,14 +30,27 @@ impl flags::Scip { with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: true, }; - let path = vfs::AbsPathBuf::assert(env::current_dir()?.join(&self.path)); - let rootpath = path.normalize(); - let manifest = ProjectManifest::discover_single(&path)?; + let root = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(&self.path)).normalize(); - let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?; + let mut config = crate::config::Config::new( + root.clone(), + lsp_types::ClientCapabilities::default(), + /* workspace_roots = */ vec![], + /* is_visual_studio_code = */ false, + ); - let (host, vfs, _) = - load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?; + if let Some(p) = self.config_path { + let mut file = std::io::BufReader::new(std::fs::File::open(p)?); + let json = serde_json::from_reader(&mut file)?; + config.update(json)?; + } + let cargo_config = config.cargo(); + let (host, vfs, _) = load_workspace_at( + root.as_path().as_ref(), + &cargo_config, + &load_cargo_config, + &no_progress, + )?; let db = host.raw_database(); let analysis = host.analysis(); @@ -58,8 +67,7 @@ impl flags::Scip { .into(), project_root: format!( "file://{}", - path.normalize() - .as_os_str() + root.as_os_str() .to_str() .ok_or(anyhow::format_err!("Unable to normalize project_root path"))? ), @@ -80,7 +88,7 @@ impl flags::Scip { new_symbol }; - let relative_path = match get_relative_filepath(&vfs, &rootpath, file_id) { + let relative_path = match get_relative_filepath(&vfs, &root, file_id) { Some(relative_path) => relative_path, None => continue, }; @@ -125,6 +133,10 @@ impl flags::Scip { documentation: documentation.unwrap_or_default(), relationships: Vec::new(), special_fields: Default::default(), + kind: Default::default(), + display_name: String::new(), + signature_documentation: Default::default(), + enclosing_symbol: String::new(), }; symbols.push(symbol_info) @@ -139,6 +151,7 @@ impl flags::Scip { syntax_kind: Default::default(), diagnostics: Vec::new(), special_fields: Default::default(), + enclosing_range: Vec::new(), }); }); @@ -152,6 +165,7 @@ impl flags::Scip { occurrences, symbols, special_fields: Default::default(), + text: String::new(), }); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index ea3a21241cb6e..90d1d6b055594 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -91,6 +91,12 @@ config_data! { /// and should therefore include `--message-format=json` or a similar /// option. /// + /// If there are multiple linked projects/workspaces, this command is invoked for + /// each of them, with the working directory being the workspace root + /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten + /// by changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and + /// `#rust-analyzer.cargo.buildScripts.invocationLocation#`. + /// /// By default, a cargo invocation will be constructed for the configured /// targets and features, with the following base command line: /// @@ -182,9 +188,11 @@ config_data! { /// Cargo, you might also want to change /// `#rust-analyzer.cargo.buildScripts.overrideCommand#`. /// - /// If there are multiple linked projects, this command is invoked for - /// each of them, with the working directory being the project root - /// (i.e., the folder containing the `Cargo.toml`). + /// If there are multiple linked projects/workspaces, this command is invoked for + /// each of them, with the working directory being the workspace root + /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten + /// by changing `#rust-analyzer.cargo.check.invocationStrategy#` and + /// `#rust-analyzer.cargo.check.invocationLocation#`. /// /// An example command would be: /// @@ -209,6 +217,8 @@ config_data! { completion_autoself_enable: bool = "true", /// Whether to add parenthesis and argument snippets when completing function. completion_callable_snippets: CallableCompletionDef = "\"fill_arguments\"", + /// Whether to show full function/method signatures in completion docs. + completion_fullFunctionSignatures_enable: bool = "false", /// Maximum number of completions to return. If `None`, the limit is infinite. completion_limit: Option = "null", /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. @@ -342,7 +352,9 @@ config_data! { /// Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`. imports_merge_glob: bool = "true", /// Prefer to unconditionally use imports of the core and alloc crate, over the std crate. - imports_prefer_no_std: bool = "false", + imports_preferNoStd | imports_prefer_no_std: bool = "false", + /// Whether to prefer import paths containing a `prelude` module. + imports_preferPrelude: bool = "false", /// The path structure for newly inserted paths to use. imports_prefix: ImportPrefixDef = "\"plain\"", @@ -369,6 +381,8 @@ config_data! { inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = "false", /// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc). inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = "\"prefix\"", + /// Whether to show implicit drop hints. + inlayHints_implicitDrops_enable: bool = "false", /// Whether to show inlay type hints for elided lifetimes in function signatures. inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"", /// Whether to prefer using parameter names as the name for elided lifetime hints if possible. @@ -470,6 +484,14 @@ config_data! { /// tests or binaries. For example, it may be `--release`. runnables_extraArgs: Vec = "[]", + /// Optional path to a rust-analyzer specific target directory. + /// This prevents rust-analyzer's `cargo check` from locking the `Cargo.lock` + /// at the expense of duplicating build artifacts. + /// + /// Set to `true` to use a subdirectory of the existing target directory or + /// set to a path relative to the workspace to use that path. + rust_analyzerTargetDir: Option = "null", + /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private /// projects, or "discover" to try to automatically find it if the `rustc-dev` component /// is installed. @@ -565,6 +587,7 @@ pub struct Config { data: ConfigData, detached_files: Vec, snippets: Vec, + is_visual_studio_code: bool, } type ParallelCachePrimingNumThreads = u8; @@ -755,11 +778,14 @@ impl fmt::Display for ConfigError { } } +impl std::error::Error for ConfigError {} + impl Config { pub fn new( root_path: AbsPathBuf, caps: ClientCapabilities, workspace_roots: Vec, + is_visual_studio_code: bool, ) -> Self { Config { caps, @@ -769,6 +795,7 @@ impl Config { root_path, snippets: Default::default(), workspace_roots, + is_visual_studio_code, } } @@ -1094,7 +1121,8 @@ impl Config { ExprFillDefaultDef::Default => ExprFillDefaultMode::Default, }, insert_use: self.insert_use_config(), - prefer_no_std: self.data.imports_prefer_no_std, + prefer_no_std: self.data.imports_preferNoStd, + prefer_prelude: self.data.imports_preferPrelude, } } @@ -1248,6 +1276,7 @@ impl Config { run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(), extra_args: self.data.cargo_extraArgs.clone(), extra_env: self.data.cargo_extraEnv.clone(), + target_dir: self.target_dir_from_config(), } } @@ -1320,10 +1349,21 @@ impl Config { extra_args: self.check_extra_args(), extra_env: self.check_extra_env(), ansi_color_output: self.color_diagnostic_output(), + target_dir: self.target_dir_from_config(), }, } } + fn target_dir_from_config(&self) -> Option { + self.data.rust_analyzerTargetDir.as_ref().and_then(|target_dir| match target_dir { + TargetDirectory::UseSubdirectory(yes) if *yes => { + Some(PathBuf::from("target/rust-analyzer")) + } + TargetDirectory::UseSubdirectory(_) => None, + TargetDirectory::Directory(dir) => Some(dir.clone()), + }) + } + pub fn check_on_save(&self) -> bool { self.data.checkOnSave } @@ -1353,6 +1393,7 @@ impl Config { type_hints: self.data.inlayHints_typeHints_enable, parameter_hints: self.data.inlayHints_parameterHints_enable, chaining_hints: self.data.inlayHints_chainingHints_enable, + implicit_drop_hints: self.data.inlayHints_implicitDrops_enable, discriminant_hints: match self.data.inlayHints_discriminantHints_enable { DiscriminantHintsDef::Always => ide::DiscriminantHints::Always, DiscriminantHintsDef::Never => ide::DiscriminantHints::Never, @@ -1444,13 +1485,15 @@ impl Config { && completion_item_edit_resolve(&self.caps), enable_self_on_the_fly: self.data.completion_autoself_enable, enable_private_editable: self.data.completion_privateEditable_enable, + full_function_signatures: self.data.completion_fullFunctionSignatures_enable, callable: match self.data.completion_callable_snippets { CallableCompletionDef::FillArguments => Some(CallableSnippets::FillArguments), CallableCompletionDef::AddParentheses => Some(CallableSnippets::AddParentheses), CallableCompletionDef::None => None, }, insert_use: self.insert_use_config(), - prefer_no_std: self.data.imports_prefer_no_std, + prefer_no_std: self.data.imports_preferNoStd, + prefer_prelude: self.data.imports_preferPrelude, snippet_cap: SnippetCap::new(try_or_def!( self.caps .text_document @@ -1479,7 +1522,8 @@ impl Config { snippet_cap: SnippetCap::new(self.experimental("snippetTextEdit")), allowed: None, insert_use: self.insert_use_config(), - prefer_no_std: self.data.imports_prefer_no_std, + prefer_no_std: self.data.imports_preferNoStd, + prefer_prelude: self.data.imports_preferPrelude, assist_emit_must_use: self.data.assist_emitMustUse, } } @@ -1667,6 +1711,12 @@ impl Config { pub fn typing_autoclose_angle(&self) -> bool { self.data.typing_autoClosingAngleBrackets_enable } + + // FIXME: VSCode seems to work wrong sometimes, see https://github.com/microsoft/vscode/issues/193124 + // hence, distinguish it for now. + pub fn is_visual_studio_code(&self) -> bool { + self.is_visual_studio_code + } } // Deserialization definitions @@ -2015,6 +2065,14 @@ pub enum MemoryLayoutHoverRenderKindDef { Both, } +#[derive(Deserialize, Debug, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +#[serde(untagged)] +pub enum TargetDirectory { + UseSubdirectory(bool), + Directory(PathBuf), +} + macro_rules! _config_data { (struct $name:ident { $( @@ -2443,6 +2501,19 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json }, ], }, + "Option" => set! { + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "string" + }, + ], + }, _ => panic!("missing entry for {ty}: {default}"), } @@ -2555,8 +2626,12 @@ mod tests { #[test] fn proc_macro_srv_null() { - let mut config = - Config::new(AbsPathBuf::try_from(project_root()).unwrap(), Default::default(), vec![]); + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); config .update(serde_json::json!({ "procMacro_server": null, @@ -2567,8 +2642,12 @@ mod tests { #[test] fn proc_macro_srv_abs() { - let mut config = - Config::new(AbsPathBuf::try_from(project_root()).unwrap(), Default::default(), vec![]); + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); config .update(serde_json::json!({ "procMacro": {"server": project_root().display().to_string()} @@ -2579,8 +2658,12 @@ mod tests { #[test] fn proc_macro_srv_rel() { - let mut config = - Config::new(AbsPathBuf::try_from(project_root()).unwrap(), Default::default(), vec![]); + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); config .update(serde_json::json!({ "procMacro": {"server": "./server"} @@ -2591,4 +2674,67 @@ mod tests { Some(AbsPathBuf::try_from(project_root().join("./server")).unwrap()) ); } + + #[test] + fn cargo_target_dir_unset() { + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); + config + .update(serde_json::json!({ + "rust": { "analyzerTargetDir": null } + })) + .unwrap(); + assert_eq!(config.data.rust_analyzerTargetDir, None); + assert!( + matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == None) + ); + } + + #[test] + fn cargo_target_dir_subdir() { + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); + config + .update(serde_json::json!({ + "rust": { "analyzerTargetDir": true } + })) + .unwrap(); + assert_eq!( + config.data.rust_analyzerTargetDir, + Some(TargetDirectory::UseSubdirectory(true)) + ); + assert!( + matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("target/rust-analyzer"))) + ); + } + + #[test] + fn cargo_target_dir_relative_dir() { + let mut config = Config::new( + AbsPathBuf::try_from(project_root()).unwrap(), + Default::default(), + vec![], + false, + ); + config + .update(serde_json::json!({ + "rust": { "analyzerTargetDir": "other_folder" } + })) + .unwrap(); + assert_eq!( + config.data.rust_analyzerTargetDir, + Some(TargetDirectory::Directory(PathBuf::from("other_folder"))) + ); + assert!( + matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("other_folder"))) + ); + } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs index 731580557c29a..f8bc66ff8e74a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -538,7 +538,12 @@ mod tests { let (sender, _) = crossbeam_channel::unbounded(); let state = GlobalState::new( sender, - Config::new(workspace_root.to_path_buf(), ClientCapabilities::default(), Vec::new()), + Config::new( + workspace_root.to_path_buf(), + ClientCapabilities::default(), + Vec::new(), + false, + ), ); let snap = state.snapshot(); let mut actual = map_rust_diagnostic_to_lsp(&config, &diagnostic, workspace_root, &snap); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index b8a1a39be193d..06c27332d4406 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -4,6 +4,7 @@ use std::{ fs, io::Write as _, + path::PathBuf, process::{self, Stdio}, }; @@ -1995,7 +1996,25 @@ fn run_rustfmt( cmd } RustfmtConfig::CustomCommand { command, args } => { - let mut cmd = process::Command::new(command); + let cmd = PathBuf::from(&command); + let workspace = CargoTargetSpec::for_file(&snap, file_id)?; + let mut cmd = match workspace { + Some(spec) => { + // approach: if the command name contains a path separator, join it with the workspace root. + // however, if the path is absolute, joining will result in the absolute path being preserved. + // as a fallback, rely on $PATH-based discovery. + let cmd_path = + if cfg!(windows) && command.contains(&[std::path::MAIN_SEPARATOR, '/']) { + spec.workspace_root.join(cmd).into() + } else if command.contains(std::path::MAIN_SEPARATOR) { + spec.workspace_root.join(cmd).into() + } else { + cmd + }; + process::Command::new(cmd_path) + } + None => process::Command::new(cmd), + }; cmd.envs(snap.config.extra_env()); cmd.args(args); @@ -2003,6 +2022,8 @@ fn run_rustfmt( } }; + tracing::debug!(?command, "created format command"); + // try to chdir to the file so we can respect `rustfmt.toml` // FIXME: use `rustfmt --config-path` once // https://github.com/rust-lang/rustfmt/issues/4660 gets fixed diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index 5a11012b93cf1..b7e839ac2a5e2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -134,6 +134,7 @@ fn integrated_completion_benchmark() { enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: true, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), insert_use: InsertUseConfig { @@ -145,6 +146,7 @@ fn integrated_completion_benchmark() { }, snippets: Vec::new(), prefer_no_std: false, + prefer_prelude: true, limit: None, }; let position = @@ -173,6 +175,7 @@ fn integrated_completion_benchmark() { enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: true, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), insert_use: InsertUseConfig { @@ -184,6 +187,7 @@ fn integrated_completion_benchmark() { }, snippets: Vec::new(), prefer_no_std: false, + prefer_prelude: true, limit: None, }; let position = diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 23074493aeeea..fb366fd5cc41f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1,7 +1,7 @@ //! Conversion of rust-analyzer specific types to lsp_types equivalents. use std::{ iter::once, - path, + mem, path, sync::atomic::{AtomicU32, Ordering}, }; @@ -301,9 +301,11 @@ fn completion_item( if config.completion_label_details_support() { lsp_item.label_details = Some(lsp_types::CompletionItemLabelDetails { - detail: None, + detail: item.label_detail.as_ref().map(ToString::to_string), description: lsp_item.detail.clone(), }); + } else if let Some(label_detail) = item.label_detail { + lsp_item.label.push_str(label_detail.as_str()); } set_score(&mut lsp_item, max_relevance, item.relevance); @@ -443,15 +445,17 @@ pub(crate) fn inlay_hint( file_id: FileId, inlay_hint: InlayHint, ) -> Cancellable { + let is_visual_studio_code = snap.config.is_visual_studio_code(); let needs_resolve = inlay_hint.needs_resolve; let (label, tooltip, mut something_to_resolve) = inlay_hint_label(snap, fields_to_resolve, needs_resolve, inlay_hint.label)?; - let text_edits = if needs_resolve && fields_to_resolve.resolve_text_edits { - something_to_resolve |= inlay_hint.text_edit.is_some(); - None - } else { - inlay_hint.text_edit.map(|it| text_edit_vec(line_index, it)) - }; + let text_edits = + if !is_visual_studio_code && needs_resolve && fields_to_resolve.resolve_text_edits { + something_to_resolve |= inlay_hint.text_edit.is_some(); + None + } else { + inlay_hint.text_edit.map(|it| text_edit_vec(line_index, it)) + }; let data = if needs_resolve && something_to_resolve { Some(to_value(lsp_ext::InlayHintResolveData { file_id: file_id.0 }).unwrap()) } else { @@ -1121,13 +1125,20 @@ pub(crate) fn snippet_text_document_ops( pub(crate) fn snippet_workspace_edit( snap: &GlobalStateSnapshot, - source_change: SourceChange, + mut source_change: SourceChange, ) -> Cancellable { let mut document_changes: Vec = Vec::new(); - for op in source_change.file_system_edits { - let ops = snippet_text_document_ops(snap, op)?; - document_changes.extend_from_slice(&ops); + for op in &mut source_change.file_system_edits { + if let FileSystemEdit::CreateFile { dst, initial_contents } = op { + // replace with a placeholder to avoid cloneing the edit + let op = FileSystemEdit::CreateFile { + dst: dst.clone(), + initial_contents: mem::take(initial_contents), + }; + let ops = snippet_text_document_ops(snap, op)?; + document_changes.extend_from_slice(&ops); + } } for (file_id, (edit, snippet_edit)) in source_change.source_file_edits { let edit = snippet_text_document_edit( @@ -1139,6 +1150,12 @@ pub(crate) fn snippet_workspace_edit( )?; document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit)); } + for op in source_change.file_system_edits { + if !matches!(op, FileSystemEdit::CreateFile { .. }) { + let ops = snippet_text_document_ops(snap, op)?; + document_changes.extend_from_slice(&ops); + } + } let mut workspace_edit = lsp_ext::SnippetWorkspaceEdit { changes: None, document_changes: Some(document_changes), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 3fae08b82e27a..abe2191f40024 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -22,6 +22,7 @@ use ide_db::{ base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, ProcMacros}, FxHashMap, }; +use itertools::Itertools; use load_cargo::{load_proc_macro, ProjectFolders}; use proc_macro_api::ProcMacroServer; use project_model::{ProjectWorkspace, WorkspaceBuildScripts}; @@ -227,16 +228,12 @@ impl GlobalState { let mut i = 0; while i < workspaces.len() { if let Ok(w) = &workspaces[i] { - let dupes: Vec<_> = workspaces + let dupes: Vec<_> = workspaces[i + 1..] .iter() - .enumerate() - .skip(i + 1) - .filter_map(|(i, it)| { - it.as_ref().ok().filter(|ws| ws.eq_ignore_build_data(w)).map(|_| i) - }) + .positions(|it| it.as_ref().is_ok_and(|ws| ws.eq_ignore_build_data(w))) .collect(); dupes.into_iter().rev().for_each(|d| { - _ = workspaces.remove(d); + _ = workspaces.remove(d + i + 1); }); } i += 1; @@ -380,7 +377,6 @@ impl GlobalState { ws }) .collect::>(); - // Workspaces are the same, but we've updated build data. self.workspaces = Arc::new(workspaces); } else { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index d59914298991c..5cd02f7840460 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -984,6 +984,11 @@ fn main() {} //- /src/old_file.rs //- /src/old_folder/mod.rs +mod nested; + +//- /src/old_folder/nested.rs +struct foo; +use crate::old_folder::nested::foo as bar; //- /src/from_mod/mod.rs @@ -1080,6 +1085,27 @@ fn main() {} "newText": "new_folder" } ] + }, + { + "textDocument": { + "uri": format!("file://{}", tmp_dir_path.join("src").join("old_folder").join("nested.rs").to_str().unwrap().to_string().replace("C:\\", "/c:/").replace('\\', "/")), + "version": null + }, + "edits": [ + { + "range": { + "start": { + "line": 1, + "character": 11 + }, + "end": { + "line": 1, + "character": 21 + } + }, + "newText": "new_folder" + } + ] } ] }), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs index e49b5768fa46d..106b99cb9352f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs @@ -150,6 +150,7 @@ impl Project<'_> { ..Default::default() }, roots, + false, ); config.update(self.config).expect("invalid config"); config.rediscover_workspaces(); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs index 8b5c92c660238..45adbf5c573be 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -157,7 +157,6 @@ Apache-2.0 OR MIT Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT Apache-2.0/MIT BSD-3-Clause -BlueOak-1.0.0 OR MIT OR Apache-2.0 CC0-1.0 ISC MIT @@ -300,6 +299,8 @@ fn check_test_attrs(path: &Path, text: &str) { // This file. "slow-tests/tidy.rs", "test-utils/src/fixture.rs", + // Generated code from lints contains doc tests in string literals. + "ide-db/src/generated/lints.rs", ]; if text.contains("#[should_panic") && !need_panic.iter().any(|p| path.ends_with(p)) { panic!( @@ -315,7 +316,7 @@ fn check_trailing_ws(path: &Path, text: &str) { return; } for (line_number, line) in text.lines().enumerate() { - if line.chars().last().map(char::is_whitespace) == Some(true) { + if line.chars().last().is_some_and(char::is_whitespace) { panic!("Trailing whitespace in {} at line {}", path.display(), line_number + 1) } } diff --git a/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml b/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml new file mode 100644 index 0000000000000..cd7ec30593656 --- /dev/null +++ b/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "rustc-dependencies" +version = "0.0.0" +description = "TBD" + +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +ra-ap-rustc_lexer = { version = "0.20.0" } +ra-ap-rustc_parse_format = { version = "0.20.0", default-features = false } +ra-ap-rustc_index = { version = "0.20.0", default-features = false } +ra-ap-rustc_abi = { version = "0.20.0", default-features = false } + +[features] +in-rust-tree = [] diff --git a/src/tools/rust-analyzer/crates/rustc-dependencies/src/lib.rs b/src/tools/rust-analyzer/crates/rustc-dependencies/src/lib.rs new file mode 100644 index 0000000000000..13fcbc4919370 --- /dev/null +++ b/src/tools/rust-analyzer/crates/rustc-dependencies/src/lib.rs @@ -0,0 +1,48 @@ +//! A wrapper around rustc internal crates, which enables switching between compiler provided +//! ones and stable ones published in crates.io + +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_lexer; + +pub mod lexer { + #[cfg(not(feature = "in-rust-tree"))] + pub use ::ra_ap_rustc_lexer::*; + + #[cfg(feature = "in-rust-tree")] + pub use ::rustc_lexer::*; +} + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_parse_format; + +pub mod parse_format { + #[cfg(not(feature = "in-rust-tree"))] + pub use ::ra_ap_rustc_parse_format::*; + + #[cfg(feature = "in-rust-tree")] + pub use ::rustc_parse_format::*; +} + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_abi; + +pub mod abi { + #[cfg(not(feature = "in-rust-tree"))] + pub use ::ra_ap_rustc_abi::*; + + #[cfg(feature = "in-rust-tree")] + pub use ::rustc_abi::*; +} + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_index; + +pub mod index { + #[cfg(not(feature = "in-rust-tree"))] + pub use ::ra_ap_rustc_index::*; + + #[cfg(feature = "in-rust-tree")] + pub use ::rustc_index::*; +} diff --git a/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml b/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml index fb2b9ebef506d..0514af8e7839f 100644 --- a/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml +++ b/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml @@ -12,4 +12,4 @@ rust-version.workspace = true doctest = false [dependencies] -xshell = "0.2.2" +xshell.workspace = true diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml index 536f000a44b7a..35986799fdd4d 100644 --- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml @@ -12,10 +12,10 @@ rust-version.workspace = true doctest = false [dependencies] -libc = "0.2.135" backtrace = { version = "0.3.67", optional = true } always-assert = { version = "0.1.2", features = ["log"] } jod-thread = "0.1.2" +libc.workspace = true crossbeam-channel = "0.5.5" # Think twice before adding anything here diff --git a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs new file mode 100644 index 0000000000000..fd44e6c6d0f4c --- /dev/null +++ b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs @@ -0,0 +1,379 @@ +//! This file is a port of only the necessary features from https://github.com/chris-morgan/anymap version 1.0.0-beta.2 for use within rust-analyzer. +//! Copyright © 2014–2022 Chris Morgan. COPYING: https://github.com/chris-morgan/anymap/blob/master/COPYING" +//! Note that the license is changed from Blue Oak Model 1.0.0 or MIT or Apache-2.0 to MIT OR Apache-2.0 +//! +//! This implementation provides a safe and convenient store for one value of each type. +//! +//! Your starting point is [`Map`]. It has an example. +//! +//! # Cargo features +//! +//! This implementation has two independent features, each of which provides an implementation providing +//! types `Map`, `AnyMap`, `OccupiedEntry`, `VacantEntry`, `Entry` and `RawMap`: +//! +//! - **std** (default, *enabled* in this build): +//! an implementation using `std::collections::hash_map`, placed in the crate root +//! (e.g. `anymap::AnyMap`). + +#![warn(missing_docs, unused_results)] + +use core::convert::TryInto; +use core::hash::Hasher; + +/// A hasher designed to eke a little more speed out, given `TypeId`’s known characteristics. +/// +/// Specifically, this is a no-op hasher that expects to be fed a u64’s worth of +/// randomly-distributed bits. It works well for `TypeId` (eliminating start-up time, so that my +/// get_missing benchmark is ~30ns rather than ~900ns, and being a good deal faster after that, so +/// that my insert_and_get_on_260_types benchmark is ~12μs instead of ~21.5μs), but will +/// panic in debug mode and always emit zeros in release mode for any other sorts of inputs, so +/// yeah, don’t use it! 😀 +#[derive(Default)] +pub struct TypeIdHasher { + value: u64, +} + +impl Hasher for TypeIdHasher { + #[inline] + fn write(&mut self, bytes: &[u8]) { + // This expects to receive exactly one 64-bit value, and there’s no realistic chance of + // that changing, but I don’t want to depend on something that isn’t expressly part of the + // contract for safety. But I’m OK with release builds putting everything in one bucket + // if it *did* change (and debug builds panicking). + debug_assert_eq!(bytes.len(), 8); + let _ = bytes.try_into().map(|array| self.value = u64::from_ne_bytes(array)); + } + + #[inline] + fn finish(&self) -> u64 { + self.value + } +} + +use core::any::{Any, TypeId}; +use core::hash::BuildHasherDefault; +use core::marker::PhantomData; + +use ::std::collections::hash_map::{self, HashMap}; + +/// Raw access to the underlying `HashMap`. +/// +/// This alias is provided for convenience because of the ugly third generic parameter. +pub type RawMap = HashMap, BuildHasherDefault>; + +/// A collection containing zero or one values for any given type and allowing convenient, +/// type-safe access to those values. +/// +/// The type parameter `A` allows you to use a different value type; normally you will want +/// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices: +/// +/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with +/// that, you can only add types that implement `Clone` to the map. +/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map`) to add those +/// auto traits. +/// +/// Cumulatively, there are thus six forms of map: +/// +/// - [Map]<dyn [core::any::Any]>, +/// also spelled [`AnyMap`] for convenience. +/// - [Map]<dyn [core::any::Any] + Send> +/// - [Map]<dyn [core::any::Any] + Send + Sync> +/// - [Map]<dyn [CloneAny]> +/// - [Map]<dyn [CloneAny] + Send> +/// - [Map]<dyn [CloneAny] + Send + Sync> +/// +/// ## Example +/// +/// (Here using the [`AnyMap`] convenience alias; the first line could use +/// [anymap::Map][Map]::<[core::any::Any]>::new() instead if desired.) +/// +/// ```rust +#[doc = "let mut data = anymap::AnyMap::new();"] +/// assert_eq!(data.get(), None::<&i32>); +/// ``` +/// +/// Values containing non-static references are not permitted. +#[derive(Debug)] +pub struct Map { + raw: RawMap, +} + +/// The most common type of `Map`: just using `Any`; [Map]<dyn [Any]>. +/// +/// Why is this a separate type alias rather than a default value for `Map`? +/// `Map::new()` doesn’t seem to be happy to infer that it should go with the default +/// value. It’s a bit sad, really. Ah well, I guess this approach will do. +pub type AnyMap = Map; +impl Default for Map { + #[inline] + fn default() -> Map { + Map::new() + } +} + +impl Map { + /// Create an empty collection. + #[inline] + pub fn new() -> Map { + Map { raw: RawMap::with_hasher(Default::default()) } + } + + /// Returns a reference to the value stored in the collection for the type `T`, + /// if it exists. + #[inline] + pub fn get>(&self) -> Option<&T> { + self.raw.get(&TypeId::of::()).map(|any| unsafe { any.downcast_ref_unchecked::() }) + } + + /// Gets the entry for the given type in the collection for in-place manipulation + #[inline] + pub fn entry>(&mut self) -> Entry<'_, A, T> { + match self.raw.entry(TypeId::of::()) { + hash_map::Entry::Occupied(e) => { + Entry::Occupied(OccupiedEntry { inner: e, type_: PhantomData }) + } + hash_map::Entry::Vacant(e) => { + Entry::Vacant(VacantEntry { inner: e, type_: PhantomData }) + } + } + } +} + +/// A view into a single occupied location in an `Map`. +pub struct OccupiedEntry<'a, A: ?Sized + Downcast, V: 'a> { + inner: hash_map::OccupiedEntry<'a, TypeId, Box>, + type_: PhantomData, +} + +/// A view into a single empty location in an `Map`. +pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> { + inner: hash_map::VacantEntry<'a, TypeId, Box>, + type_: PhantomData, +} + +/// A view into a single location in an `Map`, which may be vacant or occupied. +pub enum Entry<'a, A: ?Sized + Downcast, V> { + /// An occupied Entry + Occupied(OccupiedEntry<'a, A, V>), + /// A vacant Entry + Vacant(VacantEntry<'a, A, V>), +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> Entry<'a, A, V> { + /// Ensures a value is in the entry by inserting the result of the default function if + /// empty, and returns a mutable reference to the value in the entry. + #[inline] + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Entry::Occupied(inner) => inner.into_mut(), + Entry::Vacant(inner) => inner.insert(default()), + } + } +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> OccupiedEntry<'a, A, V> { + /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// with a lifetime bound to the collection itself + #[inline] + pub fn into_mut(self) -> &'a mut V { + unsafe { self.inner.into_mut().downcast_mut_unchecked() } + } +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> VacantEntry<'a, A, V> { + /// Sets the value of the entry with the VacantEntry's key, + /// and returns a mutable reference to it + #[inline] + pub fn insert(self, value: V) -> &'a mut V { + unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Clone, Debug, PartialEq)] + struct A(i32); + #[derive(Clone, Debug, PartialEq)] + struct B(i32); + #[derive(Clone, Debug, PartialEq)] + struct C(i32); + #[derive(Clone, Debug, PartialEq)] + struct D(i32); + #[derive(Clone, Debug, PartialEq)] + struct E(i32); + #[derive(Clone, Debug, PartialEq)] + struct F(i32); + #[derive(Clone, Debug, PartialEq)] + struct J(i32); + + #[test] + fn test_varieties() { + fn assert_send() {} + fn assert_sync() {} + fn assert_debug() {} + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + } + + #[test] + fn type_id_hasher() { + use core::any::TypeId; + use core::hash::Hash; + fn verify_hashing_with(type_id: TypeId) { + let mut hasher = TypeIdHasher::default(); + type_id.hash(&mut hasher); + // SAFETY: u64 is valid for all bit patterns. + let _ = hasher.finish(); + } + // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c. + verify_hashing_with(TypeId::of::()); + verify_hashing_with(TypeId::of::<()>()); + verify_hashing_with(TypeId::of::()); + verify_hashing_with(TypeId::of::<&str>()); + verify_hashing_with(TypeId::of::>()); + } +} + +// impl some traits for dyn Any +use core::fmt; + +#[doc(hidden)] +pub trait CloneToAny { + /// Clone `self` into a new `Box` object. + fn clone_to_any(&self) -> Box; +} + +impl CloneToAny for T { + #[inline] + fn clone_to_any(&self) -> Box { + Box::new(self.clone()) + } +} + +macro_rules! impl_clone { + ($t:ty) => { + impl Clone for Box<$t> { + #[inline] + fn clone(&self) -> Box<$t> { + // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this + // approach, given that I used to do it in safe code, but then came a dodgy + // future-compatibility warning where_clauses_object_safety, which is spurious for + // auto traits but still super annoying (future-compatibility lints seem to mean + // your bin crate needs a corresponding allow!). Although I explained my plight¹ + // and it was all explained and agreed upon, no action has been taken. So I finally + // caved and worked around it by doing it this way, which matches what’s done for + // core::any², so it’s probably not *too* bad. + // + // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013 + // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616 + let clone: Box = (**self).clone_to_any(); + let raw: *mut dyn CloneAny = Box::into_raw(clone); + unsafe { Box::from_raw(raw as *mut $t) } + } + } + + impl fmt::Debug for $t { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(stringify!($t)) + } + } + }; +} + +/// Methods for downcasting from an `Any`-like trait object. +/// +/// This should only be implemented on trait objects for subtraits of `Any`, though you can +/// implement it for other types and it’ll work fine, so long as your implementation is correct. +pub trait Downcast { + /// Gets the `TypeId` of `self`. + fn type_id(&self) -> TypeId; + + // Note the bound through these downcast methods is 'static, rather than the inexpressible + // concept of Self-but-as-a-trait (where Self is `dyn Trait`). This is sufficient, exceeding + // TypeId’s requirements. Sure, you *can* do CloneAny.downcast_unchecked::() and the + // type system won’t protect you, but that doesn’t introduce any unsafety: the method is + // already unsafe because you can specify the wrong type, and if this were exposing safe + // downcasting, CloneAny.downcast::() would just return an error, which is just as + // correct. + // + // Now in theory we could also add T: ?Sized, but that doesn’t play nicely with the common + // implementation, so I’m doing without it. + + /// Downcast from `&Any` to `&T`, without checking the type matches. + /// + /// # Safety + /// + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + unsafe fn downcast_ref_unchecked(&self) -> &T; + + /// Downcast from `&mut Any` to `&mut T`, without checking the type matches. + /// + /// # Safety + /// + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T; +} + +/// A trait for the conversion of an object into a boxed trait object. +pub trait IntoBox: Any { + /// Convert self into the appropriate boxed form. + fn into_box(self) -> Box; +} + +macro_rules! implement { + ($any_trait:ident $(+ $auto_traits:ident)*) => { + impl Downcast for dyn $any_trait $(+ $auto_traits)* { + #[inline] + fn type_id(&self) -> TypeId { + self.type_id() + } + + #[inline] + unsafe fn downcast_ref_unchecked(&self) -> &T { + &*(self as *const Self as *const T) + } + + #[inline] + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + &mut *(self as *mut Self as *mut T) + } + } + + impl IntoBox for T { + #[inline] + fn into_box(self) -> Box { + Box::new(self) + } + } + } +} + +implement!(Any); +implement!(Any + Send); +implement!(Any + Send + Sync); + +/// [`Any`], but with cloning. +/// +/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`. +/// See [`core::any`] for more details on `Any` in general. +pub trait CloneAny: Any + CloneToAny {} +impl CloneAny for T {} +implement!(CloneAny); +implement!(CloneAny + Send); +implement!(CloneAny + Send + Sync); +impl_clone!(dyn CloneAny); +impl_clone!(dyn CloneAny + Send); +impl_clone!(dyn CloneAny + Send + Sync); diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs index 24990d6a0e714..f26c7f6dfc2d5 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs @@ -12,6 +12,7 @@ pub mod panic_context; pub mod non_empty_vec; pub mod rand; pub mod thread; +pub mod anymap; pub use always_assert::{always, never}; @@ -89,6 +90,57 @@ where words.join("_") } +// Taken from rustc. +pub fn to_camel_case(ident: &str) -> String { + ident + .trim_matches('_') + .split('_') + .filter(|component| !component.is_empty()) + .map(|component| { + let mut camel_cased_component = String::with_capacity(component.len()); + + let mut new_word = true; + let mut prev_is_lower_case = true; + + for c in component.chars() { + // Preserve the case if an uppercase letter follows a lowercase letter, so that + // `camelCase` is converted to `CamelCase`. + if prev_is_lower_case && c.is_uppercase() { + new_word = true; + } + + if new_word { + camel_cased_component.extend(c.to_uppercase()); + } else { + camel_cased_component.extend(c.to_lowercase()); + } + + prev_is_lower_case = c.is_lowercase(); + new_word = false; + } + + camel_cased_component + }) + .fold((String::new(), None), |(acc, prev): (_, Option), next| { + // separate two components with an underscore if their boundary cannot + // be distinguished using an uppercase/lowercase case distinction + let join = prev + .and_then(|prev| { + let f = next.chars().next()?; + let l = prev.chars().last()?; + Some(!char_has_case(l) && !char_has_case(f)) + }) + .unwrap_or(false); + (acc + if join { "_" } else { "" } + &next, Some(next)) + }) + .0 +} + +// Taken from rustc. +pub fn char_has_case(c: char) -> bool { + c.is_lowercase() || c.is_uppercase() +} + pub fn replace(buf: &mut String, from: char, to: &str) { if !buf.contains(from) { return; diff --git a/src/tools/rust-analyzer/crates/stdx/src/macros.rs b/src/tools/rust-analyzer/crates/stdx/src/macros.rs index 1a9982fa8b2a7..d71e418c89bc6 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/macros.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/macros.rs @@ -15,7 +15,12 @@ macro_rules! eprintln { macro_rules! format_to { ($buf:expr) => (); ($buf:expr, $lit:literal $($arg:tt)*) => { - { use ::std::fmt::Write as _; let _ = ::std::write!($buf, $lit $($arg)*); } + { + use ::std::fmt::Write as _; + // We can't do ::std::fmt::Write::write_fmt($buf, format_args!($lit $($arg)*)) + // unfortunately, as that loses out on autoref behavior. + _ = $buf.write_fmt(format_args!($lit $($arg)*)) + } }; } diff --git a/src/tools/rust-analyzer/crates/stdx/src/process.rs b/src/tools/rust-analyzer/crates/stdx/src/process.rs index e5aa343651876..bca0cbc36d1a7 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/process.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/process.rs @@ -23,7 +23,7 @@ pub fn streaming_output( let idx = if eof { data.len() } else { - match data.iter().rposition(|b| *b == b'\n') { + match data.iter().rposition(|&b| b == b'\n') { Some(i) => i + 1, None => return, } diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 5ee0c4792846a..3b55921dc759e 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -14,16 +14,16 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" -either = "1.7.0" -itertools = "0.10.5" +either.workspace = true +itertools.workspace = true rowan = "0.15.11" rustc-hash = "1.1.0" once_cell = "1.17.0" -indexmap = "2.0.0" +indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true -rustc_lexer.workspace = true +rustc-dependencies.workspace = true parser.workspace = true profile.workspace = true @@ -31,7 +31,7 @@ stdx.workspace = true text-edit.workspace = true [dev-dependencies] -rayon = "1.6.1" +rayon.workspace = true expect-test = "1.4.0" proc-macro2 = "1.0.47" quote = "1.0.20" @@ -41,4 +41,4 @@ test-utils.workspace = true sourcegen.workspace = true [features] -in-rust-tree = [] +in-rust-tree = ["rustc-dependencies/in-rust-tree"] diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 3603560d35c3a..c3010d090c6b9 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -36,7 +36,7 @@ PathSegment = '::'? NameRef | NameRef GenericArgList? | NameRef ParamList RetType? -| '<' PathType ('as' PathType)? '>' +| '<' Type ('as' PathType)? '>' GenericArgList = '::'? '<' (GenericArg (',' GenericArg)* ','?)? '>' diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs index a150d9e6c07d8..37d8212042da0 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs @@ -3,18 +3,17 @@ use std::iter::{empty, successors}; use parser::{SyntaxKind, T}; -use rowan::SyntaxElement; use crate::{ algo::{self, neighbor}, ast::{self, edit::IndentLevel, make, HasGenericParams}, ted::{self, Position}, - AstNode, AstToken, Direction, + AstNode, AstToken, Direction, SyntaxElement, SyntaxKind::{ATTR, COMMENT, WHITESPACE}, SyntaxNode, SyntaxToken, }; -use super::HasName; +use super::{HasArgList, HasName}; pub trait GenericParamsOwnerEdit: ast::HasGenericParams { fn get_or_create_generic_param_list(&self) -> ast::GenericParamList; @@ -224,7 +223,7 @@ pub trait AttrsOwnerEdit: ast::HasAttrs { let after_attrs_and_comments = node .children_with_tokens() .find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR)) - .map_or(Position::first_child_of(node), |it| Position::before(it)); + .map_or(Position::first_child_of(node), Position::before); ted::insert_all( after_attrs_and_comments, @@ -362,6 +361,24 @@ impl ast::PathSegment { } } +impl ast::MethodCallExpr { + pub fn get_or_create_generic_arg_list(&self) -> ast::GenericArgList { + if self.generic_arg_list().is_none() { + let generic_arg_list = make::turbofish_generic_arg_list(empty()).clone_for_update(); + + if let Some(arg_list) = self.arg_list() { + ted::insert_raw( + ted::Position::before(arg_list.syntax()), + generic_arg_list.syntax(), + ); + } else { + ted::append_child(self.syntax(), generic_arg_list.syntax()); + } + } + self.generic_arg_list().unwrap() + } +} + impl Removable for ast::UseTree { fn remove(&self) { for dir in [Direction::Next, Direction::Prev] { @@ -433,7 +450,9 @@ impl ast::UseTree { if &path == prefix && self.use_tree_list().is_none() { if self.star_token().is_some() { // path$0::* -> * - self.coloncolon_token().map(ted::remove); + if let Some(a) = self.coloncolon_token() { + ted::remove(a) + } ted::remove(prefix.syntax()); } else { // path$0 -> self @@ -460,7 +479,9 @@ impl ast::UseTree { for p in successors(parent.parent_path(), |it| it.parent_path()) { p.segment()?; } - prefix.parent_path().and_then(|p| p.coloncolon_token()).map(ted::remove); + if let Some(a) = prefix.parent_path().and_then(|p| p.coloncolon_token()) { + ted::remove(a) + } ted::remove(prefix.syntax()); Some(()) } @@ -555,7 +576,7 @@ impl ast::AssocItemList { None => (IndentLevel::single(), Position::last_child_of(self.syntax()), "\n"), }, }; - let elements: Vec> = vec![ + let elements: Vec = vec![ make::tokens::whitespace(&format!("{whitespace}{indent}")).into(), item.syntax().clone().into(), ]; @@ -625,6 +646,50 @@ impl ast::MatchArmList { } } +impl ast::LetStmt { + pub fn set_ty(&self, ty: Option) { + match ty { + None => { + if let Some(colon_token) = self.colon_token() { + ted::remove(colon_token); + } + + if let Some(existing_ty) = self.ty() { + if let Some(sibling) = existing_ty.syntax().prev_sibling_or_token() { + if sibling.kind() == SyntaxKind::WHITESPACE { + ted::remove(sibling); + } + } + + ted::remove(existing_ty.syntax()); + } + + // Remove any trailing ws + if let Some(last) = self.syntax().last_token().filter(|it| it.kind() == WHITESPACE) + { + last.detach(); + } + } + Some(new_ty) => { + if self.colon_token().is_none() { + ted::insert_raw( + Position::after( + self.pat().expect("let stmt should have a pattern").syntax(), + ), + make::token(T![:]), + ); + } + + if let Some(old_ty) = self.ty() { + ted::replace(old_ty.syntax(), new_ty.syntax()); + } else { + ted::insert(Position::after(self.colon_token().unwrap()), new_ty.syntax()); + } + } + } + } +} + impl ast::RecordExprFieldList { pub fn add_field(&self, field: ast::RecordExprField) { let is_multiline = self.syntax().text().contains_char('\n'); @@ -749,7 +814,7 @@ impl ast::VariantList { None => (IndentLevel::single(), Position::last_child_of(self.syntax())), }, }; - let elements: Vec> = vec![ + let elements: Vec = vec![ make::tokens::whitespace(&format!("{}{indent}", "\n")).into(), variant.syntax().clone().into(), ast::make::token(T![,]).into(), @@ -784,6 +849,53 @@ fn normalize_ws_between_braces(node: &SyntaxNode) -> Option<()> { Some(()) } +impl ast::IdentPat { + pub fn set_pat(&self, pat: Option) { + match pat { + None => { + if let Some(at_token) = self.at_token() { + // Remove `@ Pat` + let start = at_token.clone().into(); + let end = self + .pat() + .map(|it| it.syntax().clone().into()) + .unwrap_or_else(|| at_token.into()); + + ted::remove_all(start..=end); + + // Remove any trailing ws + if let Some(last) = + self.syntax().last_token().filter(|it| it.kind() == WHITESPACE) + { + last.detach(); + } + } + } + Some(pat) => { + if let Some(old_pat) = self.pat() { + // Replace existing pattern + ted::replace(old_pat.syntax(), pat.syntax()) + } else if let Some(at_token) = self.at_token() { + // Have an `@` token but not a pattern yet + ted::insert(ted::Position::after(at_token), pat.syntax()); + } else { + // Don't have an `@`, should have a name + let name = self.name().unwrap(); + + ted::insert_all( + ted::Position::after(name.syntax()), + vec![ + make::token(T![@]).into(), + make::tokens::single_space().into(), + pat.syntax().clone().into(), + ], + ) + } + } + } + } +} + pub trait HasVisibilityEdit: ast::HasVisibility { fn set_visibility(&self, visbility: ast::Visibility) { match self.visibility() { @@ -885,6 +997,65 @@ mod tests { ); } + #[test] + fn test_ident_pat_set_pat() { + #[track_caller] + fn check(before: &str, expected: &str, pat: Option) { + let pat = pat.map(|it| it.clone_for_update()); + + let ident_pat = ast_mut_from_text::(&format!("fn f() {{ {before} }}")); + ident_pat.set_pat(pat); + + let after = ast_mut_from_text::(&format!("fn f() {{ {expected} }}")); + assert_eq!(ident_pat.to_string(), after.to_string()); + } + + // replacing + check("let a @ _;", "let a @ ();", Some(make::tuple_pat([]).into())); + + // note: no trailing semicolon is added for the below tests since it + // seems to be picked up by the ident pat during error recovery? + + // adding + check("let a ", "let a @ ()", Some(make::tuple_pat([]).into())); + check("let a @ ", "let a @ ()", Some(make::tuple_pat([]).into())); + + // removing + check("let a @ ()", "let a", None); + check("let a @ ", "let a", None); + } + + #[test] + fn test_let_stmt_set_ty() { + #[track_caller] + fn check(before: &str, expected: &str, ty: Option) { + let ty = ty.map(|it| it.clone_for_update()); + + let let_stmt = ast_mut_from_text::(&format!("fn f() {{ {before} }}")); + let_stmt.set_ty(ty); + + let after = ast_mut_from_text::(&format!("fn f() {{ {expected} }}")); + assert_eq!(let_stmt.to_string(), after.to_string(), "{let_stmt:#?}\n!=\n{after:#?}"); + } + + // adding + check("let a;", "let a: ();", Some(make::ty_tuple([]))); + // no semicolon due to it being eaten during error recovery + check("let a:", "let a: ()", Some(make::ty_tuple([]))); + + // replacing + check("let a: u8;", "let a: ();", Some(make::ty_tuple([]))); + check("let a: u8 = 3;", "let a: () = 3;", Some(make::ty_tuple([]))); + check("let a: = 3;", "let a: () = 3;", Some(make::ty_tuple([]))); + + // removing + check("let a: u8;", "let a;", None); + check("let a:;", "let a;", None); + + check("let a: u8 = 3;", "let a = 3;", None); + check("let a: = 3;", "let a = 3;", None); + } + #[test] fn add_variant_to_empty_enum() { let variant = make::variant(make::name("Bar"), None).clone_for_update(); @@ -976,7 +1147,9 @@ enum Foo { fn check_add_variant(before: &str, expected: &str, variant: ast::Variant) { let enum_ = ast_mut_from_text::(before); - enum_.variant_list().map(|it| it.add_variant(variant)); + if let Some(it) = enum_.variant_list() { + it.add_variant(variant) + } let after = enum_.to_string(); assert_eq_text!(&trim_indent(expected.trim()), &trim_indent(after.trim())); } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index 7ba0d4dc656fc..6c86e591044a8 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -59,8 +59,9 @@ impl PathSegment { pub fn param_list(&self) -> Option { support::child(&self.syntax) } pub fn ret_type(&self) -> Option { support::child(&self.syntax) } pub fn l_angle_token(&self) -> Option { support::token(&self.syntax, T![<]) } - pub fn path_type(&self) -> Option { support::child(&self.syntax) } + pub fn ty(&self) -> Option { support::child(&self.syntax) } pub fn as_token(&self) -> Option { support::token(&self.syntax, T![as]) } + pub fn path_type(&self) -> Option { support::child(&self.syntax) } pub fn r_angle_token(&self) -> Option { support::token(&self.syntax, T![>]) } } @@ -1576,14 +1577,6 @@ impl RecordPatField { pub fn pat(&self) -> Option { support::child(&self.syntax) } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum GenericArg { - TypeArg(TypeArg), - AssocTypeArg(AssocTypeArg), - LifetimeArg(LifetimeArg), - ConstArg(ConstArg), -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Type { ArrayType(ArrayType), @@ -1602,6 +1595,14 @@ pub enum Type { TupleType(TupleType), } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum GenericArg { + TypeArg(TypeArg), + AssocTypeArg(AssocTypeArg), + LifetimeArg(LifetimeArg), + ConstArg(ConstArg), +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Expr { ArrayExpr(ArrayExpr), @@ -3319,41 +3320,6 @@ impl AstNode for RecordPatField { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } -impl From for GenericArg { - fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) } -} -impl From for GenericArg { - fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) } -} -impl From for GenericArg { - fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) } -} -impl From for GenericArg { - fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) } -} -impl AstNode for GenericArg { - fn can_cast(kind: SyntaxKind) -> bool { - matches!(kind, TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG) - } - fn cast(syntax: SyntaxNode) -> Option { - let res = match syntax.kind() { - TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }), - ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }), - LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }), - CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }), - _ => return None, - }; - Some(res) - } - fn syntax(&self) -> &SyntaxNode { - match self { - GenericArg::TypeArg(it) => &it.syntax, - GenericArg::AssocTypeArg(it) => &it.syntax, - GenericArg::LifetimeArg(it) => &it.syntax, - GenericArg::ConstArg(it) => &it.syntax, - } - } -} impl From for Type { fn from(node: ArrayType) -> Type { Type::ArrayType(node) } } @@ -3455,6 +3421,41 @@ impl AstNode for Type { } } } +impl From for GenericArg { + fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) } +} +impl From for GenericArg { + fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) } +} +impl From for GenericArg { + fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) } +} +impl From for GenericArg { + fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) } +} +impl AstNode for GenericArg { + fn can_cast(kind: SyntaxKind) -> bool { + matches!(kind, TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG) + } + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }), + ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }), + LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }), + CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + GenericArg::TypeArg(it) => &it.syntax, + GenericArg::AssocTypeArg(it) => &it.syntax, + GenericArg::LifetimeArg(it) => &it.syntax, + GenericArg::ConstArg(it) => &it.syntax, + } + } +} impl From for Expr { fn from(node: ArrayExpr) -> Expr { Expr::ArrayExpr(node) } } @@ -4340,12 +4341,12 @@ impl AstNode for AnyHasVisibility { } fn syntax(&self) -> &SyntaxNode { &self.syntax } } -impl std::fmt::Display for GenericArg { +impl std::fmt::Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for Type { +impl std::fmt::Display for GenericArg { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index 17e311c0c502f..ad63cc558629f 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -433,7 +433,6 @@ pub fn record_field( ast_from_text(&format!("struct S {{ {visibility}{name}: {ty}, }}")) } -// TODO pub fn block_expr( stmts: impl IntoIterator, tail_expr: Option, @@ -853,6 +852,10 @@ pub fn self_param() -> ast::SelfParam { ast_from_text("fn f(&self) { }") } +pub fn mut_self_param() -> ast::SelfParam { + ast_from_text("fn f(&mut self) { }") +} + pub fn ret_type(ty: ast::Type) -> ast::RetType { ast_from_text(&format!("fn f() -> {ty} {{ }}")) } @@ -938,6 +941,13 @@ pub fn lifetime_arg(lifetime: ast::Lifetime) -> ast::LifetimeArg { ast_from_text(&format!("const S: T<{lifetime}> = ();")) } +pub fn turbofish_generic_arg_list( + args: impl IntoIterator, +) -> ast::GenericArgList { + let args = args.into_iter().join(", "); + ast_from_text(&format!("const S: T::<{args}> = ();")) +} + pub(crate) fn generic_arg_list( args: impl IntoIterator, ) -> ast::GenericArgList { @@ -973,6 +983,11 @@ pub fn tuple_field(visibility: Option, ty: ast::Type) -> ast::T ast_from_text(&format!("struct f({visibility}{ty});")) } +pub fn variant_list(variants: impl IntoIterator) -> ast::VariantList { + let variants = variants.into_iter().join(", "); + ast_from_text(&format!("enum f {{ {variants} }}")) +} + pub fn variant(name: ast::Name, field_list: Option) -> ast::Variant { let field_list = match field_list { None => String::new(), @@ -1037,6 +1052,19 @@ pub fn struct_( ast_from_text(&format!("{visibility}struct {strukt_name}{type_params}{field_list}{semicolon}",)) } +pub fn enum_( + visibility: Option, + enum_name: ast::Name, + variant_list: ast::VariantList, +) -> ast::Enum { + let visibility = match visibility { + None => String::new(), + Some(it) => format!("{it} "), + }; + + ast_from_text(&format!("{visibility}enum {enum_name} {variant_list}")) +} + pub fn attr_outer(meta: ast::Meta) -> ast::Attr { ast_from_text(&format!("#[{meta}]")) } @@ -1105,7 +1133,7 @@ pub mod tokens { pub(super) static SOURCE_FILE: Lazy> = Lazy::new(|| { SourceFile::parse( - "const C: <()>::Item = ( true && true , true || true , 1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p)\n;\n\n", + "const C: <()>::Item = ( true && true , true || true , 1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p, { let a @ [] })\n;\n\n", ) }); @@ -1149,6 +1177,16 @@ pub mod tokens { lit.syntax().first_child_or_token().unwrap().into_token().unwrap() } + pub fn ident(text: &str) -> SyntaxToken { + assert_eq!(text.trim(), text); + let path: ast::Path = super::ext::ident_path(text); + path.syntax() + .descendants_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == IDENT) + .unwrap() + } + pub fn single_newline() -> SyntaxToken { let res = SOURCE_FILE .tree() diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index 691d0c618f381..be5b954ad345f 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -361,6 +361,15 @@ impl ast::Impl { } } +// [#15778](https://github.com/rust-lang/rust-analyzer/issues/15778) +impl ast::PathSegment { + pub fn qualifying_trait(&self) -> Option { + let mut path_types = support::children(self.syntax()); + let first = path_types.next()?; + path_types.next().or(Some(first)) + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum StructKind { Record(ast::RecordFieldList), diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs index 87fd51d703cff..8cc271d226c4e 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs @@ -2,6 +2,8 @@ use std::borrow::Cow; +use rustc_dependencies::lexer as rustc_lexer; + use rustc_lexer::unescape::{ unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode, }; diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs index 27c8a13e58d66..4939ab39049c0 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -19,6 +19,7 @@ //! [RFC]: //! [Swift]: +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] #[allow(unused)] @@ -74,7 +75,7 @@ pub use smol_str::SmolStr; #[derive(Debug, PartialEq, Eq)] pub struct Parse { green: GreenNode, - errors: Arc>, + errors: Arc<[SyntaxError]>, _ty: PhantomData T>, } @@ -86,7 +87,7 @@ impl Clone for Parse { impl Parse { fn new(green: GreenNode, errors: Vec) -> Parse { - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } pub fn syntax_node(&self) -> SyntaxNode { @@ -106,7 +107,7 @@ impl Parse { T::cast(self.syntax_node()).unwrap() } - pub fn ok(self) -> Result>> { + pub fn ok(self) -> Result> { if self.errors.is_empty() { Ok(self.tree()) } else { @@ -143,7 +144,7 @@ impl Parse { parsing::incremental_reparse(self.tree().syntax(), indel, self.errors.to_vec()).map( |(green_node, errors, _reparsed_range)| Parse { green: green_node, - errors: Arc::new(errors), + errors: errors.into(), _ty: PhantomData, }, ) @@ -167,7 +168,7 @@ impl SourceFile { errors.extend(validation::validate(&root)); assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE); - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } } @@ -181,29 +182,27 @@ impl ast::TokenTree { let kind = t.kind(); if kind.is_trivia() { was_joint = false + } else if kind == SyntaxKind::IDENT { + let token_text = t.text(); + let contextual_kw = + SyntaxKind::from_contextual_keyword(token_text).unwrap_or(SyntaxKind::IDENT); + parser_input.push_ident(contextual_kw); } else { - if kind == SyntaxKind::IDENT { - let token_text = t.text(); - let contextual_kw = SyntaxKind::from_contextual_keyword(token_text) - .unwrap_or(SyntaxKind::IDENT); - parser_input.push_ident(contextual_kw); - } else { - if was_joint { + if was_joint { + parser_input.was_joint(); + } + parser_input.push(kind); + // Tag the token as joint if it is float with a fractional part + // we use this jointness to inform the parser about what token split + // event to emit when we encounter a float literal in a field access + if kind == SyntaxKind::FLOAT_NUMBER { + if !t.text().ends_with('.') { parser_input.was_joint(); - } - parser_input.push(kind); - // Tag the token as joint if it is float with a fractional part - // we use this jointness to inform the parser about what token split - // event to emit when we encounter a float literal in a field access - if kind == SyntaxKind::FLOAT_NUMBER { - if !t.text().ends_with('.') { - parser_input.was_joint(); - } else { - was_joint = false; - } } else { - was_joint = true; + was_joint = false; } + } else { + was_joint = true; } } } @@ -276,7 +275,7 @@ impl ast::TokenTree { let (green, errors) = builder.finish_raw(); - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ptr.rs b/src/tools/rust-analyzer/crates/syntax/src/ptr.rs index 1d4a89201ae42..71762996cd7d1 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ptr.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ptr.rs @@ -73,6 +73,10 @@ impl AstPtr { Some(AstPtr { raw: self.raw, _ty: PhantomData }) } + pub fn kind(&self) -> parser::SyntaxKind { + self.raw.kind() + } + pub fn upcast(self) -> AstPtr where N: Into, @@ -84,6 +88,20 @@ impl AstPtr { pub fn try_from_raw(raw: SyntaxNodePtr) -> Option> { N::can_cast(raw.kind()).then_some(AstPtr { raw, _ty: PhantomData }) } + + pub fn wrap_left(self) -> AstPtr> + where + either::Either: AstNode, + { + AstPtr { raw: self.raw, _ty: PhantomData } + } + + pub fn wrap_right(self) -> AstPtr> + where + either::Either: AstNode, + { + AstPtr { raw: self.raw, _ty: PhantomData } + } } impl From> for SyntaxNodePtr { diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests.rs b/src/tools/rust-analyzer/crates/syntax/src/tests.rs index 168439053c27a..3010d77d827e1 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests.rs @@ -17,11 +17,11 @@ use crate::{ast, fuzz, AstNode, SourceFile, SyntaxError}; #[test] fn parse_smoke_test() { - let code = r##" + let code = r#" fn main() { println!("Hello, world!") } - "##; + "#; let parse = SourceFile::parse(code); // eprintln!("{:#?}", parse.syntax_node()); diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs b/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs index dc6c96343d61c..c2e921e4b6f3c 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs @@ -622,7 +622,7 @@ fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option> { } fn lower_rule(acc: &mut Vec, grammar: &Grammar, label: Option<&String>, rule: &Rule) { - if lower_seperated_list(acc, grammar, label, rule) { + if lower_separated_list(acc, grammar, label, rule) { return; } @@ -688,7 +688,7 @@ fn lower_rule(acc: &mut Vec, grammar: &Grammar, label: Option<&String>, r } // (T (',' T)* ','?) -fn lower_seperated_list( +fn lower_separated_list( acc: &mut Vec, grammar: &Grammar, label: Option<&String>, diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index e0ec6a242ffa7..2b1bbac08e528 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs @@ -5,7 +5,7 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{self, unescape_literal, Mode}; +use rustc_dependencies::lexer::unescape::{self, unescape_literal, Mode}; use crate::{ algo, diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml index 2b5b6f4956166..438b599ffaae5 100644 --- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml @@ -13,7 +13,7 @@ doctest = false [dependencies] # Avoid adding deps here, this crate is widely used in tests it should compile fast! -dissimilar = "1.0.4" +dissimilar = "1.0.7" text-size.workspace = true rustc-hash = "1.1.0" diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 573f56b003af4..ba5c86db0e2ea 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -44,7 +44,7 @@ //! panic: fmt //! phantom_data: //! pin: -//! pointee: +//! pointee: copy, send, sync, ord, hash, unpin //! range: //! result: //! send: sized @@ -54,6 +54,7 @@ //! sync: sized //! transmute: //! try: infallible +//! unpin: sized //! unsize: sized #![rustc_coherence_is_core] @@ -89,6 +90,11 @@ pub mod marker { pub trait Unsize {} // endregion:unsize + // region:unpin + #[lang = "unpin"] + pub auto trait Unpin {} + // endregion:unpin + // region:copy #[lang = "copy"] pub trait Copy: Clone {} @@ -387,9 +393,10 @@ pub mod ptr { // region:pointee #[lang = "pointee_trait"] + #[rustc_deny_explicit_impl(implement_via_object = false)] pub trait Pointee { #[lang = "metadata_type"] - type Metadata; + type Metadata: Copy + Send + Sync + Ord + Hash + Unpin; } // endregion:pointee // region:non_null @@ -489,7 +496,7 @@ pub mod ops { I: SliceIndex<[T]>, { type Output = I::Output; - fn index(&self, index: I) -> &I::Output { + fn index(&self, _index: I) -> &I::Output { loop {} } } @@ -497,7 +504,7 @@ pub mod ops { where I: SliceIndex<[T]>, { - fn index_mut(&mut self, index: I) -> &mut I::Output { + fn index_mut(&mut self, _index: I) -> &mut I::Output { loop {} } } @@ -507,7 +514,7 @@ pub mod ops { I: SliceIndex<[T]>, { type Output = I::Output; - fn index(&self, index: I) -> &I::Output { + fn index(&self, _index: I) -> &I::Output { loop {} } } @@ -515,7 +522,7 @@ pub mod ops { where I: SliceIndex<[T]>, { - fn index_mut(&mut self, index: I) -> &mut I::Output { + fn index_mut(&mut self, _index: I) -> &mut I::Output { loop {} } } @@ -863,17 +870,17 @@ pub mod fmt { pub struct DebugTuple; pub struct DebugStruct; impl Formatter<'_> { - pub fn debug_tuple(&mut self, name: &str) -> DebugTuple { + pub fn debug_tuple(&mut self, _name: &str) -> DebugTuple { DebugTuple } - pub fn debug_struct(&mut self, name: &str) -> DebugStruct { + pub fn debug_struct(&mut self, _name: &str) -> DebugStruct { DebugStruct } } impl DebugTuple { - pub fn field(&mut self, value: &dyn Debug) -> &mut Self { + pub fn field(&mut self, _value: &dyn Debug) -> &mut Self { self } @@ -883,7 +890,7 @@ pub mod fmt { } impl DebugStruct { - pub fn field(&mut self, name: &str, value: &dyn Debug) -> &mut Self { + pub fn field(&mut self, _name: &str, _value: &dyn Debug) -> &mut Self { self } @@ -996,7 +1003,7 @@ pub mod fmt { ($($t:ty)*) => { $( impl const Debug for $t { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, _f: &mut Formatter<'_>) -> Result { Ok(()) } } @@ -1012,7 +1019,7 @@ pub mod fmt { } impl Debug for [T] { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, _f: &mut Formatter<'_>) -> Result { Ok(()) } } @@ -1047,6 +1054,10 @@ pub mod option { Some(T), } + // region:copy + impl Copy for Option {} + // endregion:copy + impl Option { pub const fn unwrap(self) -> T { match self { @@ -1062,7 +1073,7 @@ pub mod option { } } - pub fn and(self, optb: Option) -> Option { + pub fn and(self, _optb: Option) -> Option { loop {} } pub fn unwrap_or(self, default: T) -> T { @@ -1080,25 +1091,25 @@ pub mod option { } // endregion:result // region:fn - pub fn and_then(self, f: F) -> Option + pub fn and_then(self, _f: F) -> Option where F: FnOnce(T) -> Option, { loop {} } - pub fn unwrap_or_else(self, f: F) -> T + pub fn unwrap_or_else(self, _f: F) -> T where F: FnOnce() -> T, { loop {} } - pub fn map_or(self, default: U, f: F) -> U + pub fn map_or(self, _default: U, _f: F) -> U where F: FnOnce(T) -> U, { loop {} } - pub fn map_or_else(self, default: D, f: F) -> U + pub fn map_or_else(self, _default: D, _f: F) -> U where D: FnOnce() -> U, F: FnOnce(T) -> U, @@ -1129,7 +1140,7 @@ pub mod pin { pointer: P, } impl

    Pin

    { - pub fn new(pointer: P) -> Pin

    { + pub fn new(_pointer: P) -> Pin

    { loop {} } } @@ -1226,7 +1237,7 @@ pub mod iter { mod sources { mod repeat { - pub fn repeat(elt: T) -> Repeat { + pub fn repeat(_elt: T) -> Repeat { loop {} } @@ -1266,7 +1277,7 @@ pub mod iter { fn take(self, n: usize) -> crate::iter::Take { loop {} } - fn filter_map(self, f: F) -> crate::iter::FilterMap + fn filter_map(self, _f: F) -> crate::iter::FilterMap where Self: Sized, F: FnMut(Self::Item) -> Option, @@ -1337,7 +1348,7 @@ mod panic { mod panicking { #[lang = "panic_fmt"] - pub const fn panic_fmt(fmt: crate::fmt::Arguments<'_>) -> ! { + pub const fn panic_fmt(_fmt: crate::fmt::Arguments<'_>) -> ! { loop {} } } diff --git a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml index 76d0ca5ccb601..4620cc72d0a22 100644 --- a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml +++ b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml @@ -12,5 +12,5 @@ rust-version.workspace = true doctest = false [dependencies] -itertools = "0.10.5" +itertools.workspace = true text-size.workspace = true diff --git a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml index 11055f0280ac2..fe6cb0a2c3fd9 100644 --- a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml +++ b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml @@ -12,10 +12,9 @@ rust-version.workspace = true doctest = false [dependencies] -tracing = "0.1.35" +tracing.workspace = true walkdir = "2.3.2" crossbeam-channel = "0.5.5" -# We demand 5.1.0 as any higher version pulls in a new windows-sys dupe notify = "6.1.1" stdx.workspace = true diff --git a/src/tools/rust-analyzer/crates/vfs/Cargo.toml b/src/tools/rust-analyzer/crates/vfs/Cargo.toml index c35785cf98c4a..11409f2eb8195 100644 --- a/src/tools/rust-analyzer/crates/vfs/Cargo.toml +++ b/src/tools/rust-analyzer/crates/vfs/Cargo.toml @@ -14,7 +14,7 @@ doctest = false [dependencies] rustc-hash = "1.1.0" fst = "0.4.7" -indexmap = "2.0.0" +indexmap.workspace = true nohash-hasher.workspace = true paths.workspace = true diff --git a/src/tools/rust-analyzer/docs/dev/guide.md b/src/tools/rust-analyzer/docs/dev/guide.md index 56a68ef043790..a5f1811bf24ad 100644 --- a/src/tools/rust-analyzer/docs/dev/guide.md +++ b/src/tools/rust-analyzer/docs/dev/guide.md @@ -272,7 +272,7 @@ several times, with different sets of `cfg`s enabled. The IDE-specific task of mapping source code into a semantic model is inherently imprecise for this reason and gets handled by the [`source_binder`]. -[`source_binder`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/source_binder.rs +[`source_binder`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/source_binder.rs The semantic interface is declared in the [`code_model_api`] module. Each entity is identified by an integer ID and has a bunch of methods which take a salsa database @@ -280,8 +280,8 @@ as an argument and returns other entities (which are also IDs). Internally, thes methods invoke various queries on the database to build the model on demand. Here's [the list of queries]. -[`code_model_api`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/hir/src/code_model_api.rs -[the list of queries]: https://github.com/rust-lang/rust-analyzer/blob/7e84440e25e19529e4ff8a66e521d1b06349c6ec/crates/hir/src/db.rs#L20-L106 +[`code_model_api`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/code_model_api.rs +[the list of queries]: https://github.com/rust-lang/rust-analyzer/blob/7e84440e25e19529e4ff8a66e521d1b06349c6ec/crates/ra_hir/src/db.rs#L20-L106 The first step of building the model is parsing the source code. diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 0801e988f5ce6..b66c9c943a161 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -57,8 +57,9 @@ export interface TextDocumentEdit { } ``` -When applying such code action or text edit, the editor should insert snippet, with tab stops and placeholder. -At the moment, rust-analyzer guarantees that only a single edit will have `InsertTextFormat.Snippet`. +When applying such code action or text edit, the editor should insert snippet, with tab stops and placeholders. +At the moment, rust-analyzer guarantees that only a single `TextDocumentEdit` will have edits which can be `InsertTextFormat.Snippet`. +Any additional `TextDocumentEdit`s will only have edits which are `InsertTextFormat.PlainText`. ### Example diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 71feed0f72ca0..8a2d080844352 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -57,6 +57,12 @@ build procedural macros. The command is required to output json and should therefore include `--message-format=json` or a similar option. +If there are multiple linked projects/workspaces, this command is invoked for +each of them, with the working directory being the workspace root +(i.e., the folder containing the `Cargo.toml`). This can be overwritten +by changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and +`#rust-analyzer.cargo.buildScripts.invocationLocation#`. + By default, a cargo invocation will be constructed for the configured targets and features, with the following base command line: @@ -206,9 +212,11 @@ If you're changing this because you're using some tool wrapping Cargo, you might also want to change `#rust-analyzer.cargo.buildScripts.overrideCommand#`. -If there are multiple linked projects, this command is invoked for -each of them, with the working directory being the project root -(i.e., the folder containing the `Cargo.toml`). +If there are multiple linked projects/workspaces, this command is invoked for +each of them, with the working directory being the workspace root +(i.e., the folder containing the `Cargo.toml`). This can be overwritten +by changing `#rust-analyzer.cargo.check.invocationStrategy#` and +`#rust-analyzer.cargo.check.invocationLocation#`. An example command would be: @@ -244,6 +252,11 @@ with `self` prefixed to them when inside a method. -- Whether to add parenthesis and argument snippets when completing function. -- +[[rust-analyzer.completion.fullFunctionSignatures.enable]]rust-analyzer.completion.fullFunctionSignatures.enable (default: `false`):: ++ +-- +Whether to show full function/method signatures in completion docs. +-- [[rust-analyzer.completion.limit]]rust-analyzer.completion.limit (default: `null`):: + -- @@ -480,11 +493,16 @@ Group inserted imports by the https://rust-analyzer.github.io/manual.html#auto-i -- Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`. -- -[[rust-analyzer.imports.prefer.no.std]]rust-analyzer.imports.prefer.no.std (default: `false`):: +[[rust-analyzer.imports.preferNoStd]]rust-analyzer.imports.preferNoStd (default: `false`):: + -- Prefer to unconditionally use imports of the core and alloc crate, over the std crate. -- +[[rust-analyzer.imports.preferPrelude]]rust-analyzer.imports.preferPrelude (default: `false`):: ++ +-- +Whether to prefer import paths containing a `prelude` module. +-- [[rust-analyzer.imports.prefix]]rust-analyzer.imports.prefix (default: `"plain"`):: + -- @@ -546,6 +564,11 @@ Whether to hide inlay hints for type adjustments outside of `unsafe` blocks. -- Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc). -- +[[rust-analyzer.inlayHints.implicitDrops.enable]]rust-analyzer.inlayHints.implicitDrops.enable (default: `false`):: ++ +-- +Whether to show implicit drop hints. +-- [[rust-analyzer.inlayHints.lifetimeElisionHints.enable]]rust-analyzer.inlayHints.lifetimeElisionHints.enable (default: `"never"`):: + -- @@ -744,6 +767,16 @@ Command to be executed instead of 'cargo' for runnables. Additional arguments to be passed to cargo for runnables such as tests or binaries. For example, it may be `--release`. -- +[[rust-analyzer.rust.analyzerTargetDir]]rust-analyzer.rust.analyzerTargetDir (default: `null`):: ++ +-- +Optional path to a rust-analyzer specific target directory. +This prevents rust-analyzer's `cargo check` from locking the `Cargo.lock` +at the expense of duplicating build artifacts. + +Set to `true` to use a subdirectory of the existing target directory or +set to a path relative to the workspace to use that path. +-- [[rust-analyzer.rustc.source]]rust-analyzer.rustc.source (default: `null`):: + -- diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc index 5dafd1a4c8c9d..9fc19a7d07450 100644 --- a/src/tools/rust-analyzer/docs/user/manual.adoc +++ b/src/tools/rust-analyzer/docs/user/manual.adoc @@ -174,7 +174,7 @@ $ rustup component add rust-analyzer The `rust-analyzer` binary can be installed from the repos or AUR (Arch User Repository): -- https://www.archlinux.org/packages/community/x86_64/rust-analyzer/[`rust-analyzer`] (built from latest tagged source) +- https://www.archlinux.org/packages/extra/x86_64/rust-analyzer/[`rust-analyzer`] (built from latest tagged source) - https://aur.archlinux.org/packages/rust-analyzer-git[`rust-analyzer-git`] (latest Git version) Install it with pacman, for example: @@ -237,7 +237,7 @@ To use `rust-analyzer`, you need to install and enable one of the two popular LS ==== Eglot -Eglot is the more minimalistic and lightweight LSP client for Emacs, integrates well with existing Emacs functionality and will be built into Emacs starting from release 29. +Eglot is the more minimalistic and lightweight LSP client for Emacs, integrates well with existing Emacs functionality and is built into Emacs starting from release 29. After installing Eglot, e.g. via `M-x package-install` (not needed from Emacs 29), you can enable it via the `M-x eglot` command or load it automatically in `rust-mode` via @@ -246,6 +246,15 @@ After installing Eglot, e.g. via `M-x package-install` (not needed from Emacs 29 (add-hook 'rust-mode-hook 'eglot-ensure) ---- +To enable clippy, you will need to configure the initialization options to pass the `check.command` setting. + +[source,emacs-lisp] +---- +(add-to-list 'eglot-server-programs + '((rust-ts-mode rust-mode) . + ("rust-analyzer" :initializationOptions (:check (:command "clippy"))))) +---- + For more detailed instructions and options see the https://joaotavora.github.io/eglot[Eglot manual] (also available from Emacs via `M-x info`) and the https://github.com/joaotavora/eglot/blob/master/README.md[Eglot readme]. @@ -555,6 +564,11 @@ There is a package named `ra_ap_rust_analyzer` available on https://crates.io/cr For more details, see https://github.com/rust-lang/rust-analyzer/blob/master/.github/workflows/publish.yml[the publish workflow]. +=== Zed + +https://zed.dev[Zed] has native `rust-analyzer` support. +If the LSP binary is not available, Zed can install it when opening a Rust file. + == Troubleshooting Start with looking at the rust-analyzer version. @@ -932,7 +946,7 @@ Or it is possible to specify vars more granularly: "rust-analyzer.runnables.extraEnv": [ { // "mask": null, // null mask means that this rule will be applied for all runnables - env: { + "env": { "APP_ID": "1", "APP_DATA": "asdf" } @@ -954,7 +968,7 @@ If needed, you can set different values for different platforms: "rust-analyzer.runnables.extraEnv": [ { "platform": "win32", // windows only - env: { + "env": { "APP_DATA": "windows specific data" } }, diff --git a/src/tools/rust-analyzer/editors/code/language-configuration.json b/src/tools/rust-analyzer/editors/code/language-configuration.json index 51f0e65f4fd39..1c348b63f1a23 100644 --- a/src/tools/rust-analyzer/editors/code/language-configuration.json +++ b/src/tools/rust-analyzer/editors/code/language-configuration.json @@ -18,7 +18,8 @@ { "open": "[", "close": "]" }, { "open": "(", "close": ")" }, { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "/*", "close": " */" } + { "open": "/*", "close": " */" }, + { "open": "`", "close": "`", "notIn": ["string"] } ], "autoCloseBefore": ";:.,=}])> \n\t", "surroundingPairs": [ @@ -27,7 +28,8 @@ ["(", ")"], ["<", ">"], ["\"", "\""], - ["'", "'"] + ["'", "'"], + ["`", "`"] ], "indentationRules": { "increaseIndentPattern": "^.*\\{[^}\"']*$|^.*\\([^\\)\"']*$", diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json index 20fe781ae9e40..1c94f13d74517 100644 --- a/src/tools/rust-analyzer/editors/code/package-lock.json +++ b/src/tools/rust-analyzer/editors/code/package-lock.json @@ -18,7 +18,7 @@ "devDependencies": { "@tsconfig/strictest": "^2.0.1", "@types/node": "~16.11.7", - "@types/vscode": "~1.75", + "@types/vscode": "~1.78.1", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "@vscode/test-electron": "^2.3.3", @@ -32,7 +32,7 @@ "typescript": "^5.1.6" }, "engines": { - "vscode": "^1.75.0" + "vscode": "^1.78.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -565,9 +565,9 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.75.1", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.1.tgz", - "integrity": "sha512-emg7wdsTFzdi+elvoyoA+Q8keEautdQHyY5LNmHVM4PTpY8JgOTVADrGVyXGepJ6dVW2OS5/xnLUWh+nZxvdiA==", + "version": "1.78.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.78.1.tgz", + "integrity": "sha512-wEA+54axejHu7DhcUfnFBan1IqFD1gBDxAFz8LoX06NbNDMRJv/T6OGthOs52yZccasKfN588EyffHWABkR0fg==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 233e7bf44b166..cfaf421327753 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -17,6 +17,7 @@ "rust" ], "categories": [ + "Formatters", "Programming Languages" ], "capabilities": { @@ -26,7 +27,7 @@ } }, "engines": { - "vscode": "^1.75.0" + "vscode": "^1.78.0" }, "enabledApiProposals": [], "scripts": { @@ -53,7 +54,7 @@ "devDependencies": { "@tsconfig/strictest": "^2.0.1", "@types/node": "~16.11.7", - "@types/vscode": "~1.75", + "@types/vscode": "~1.78.1", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "@vscode/test-electron": "^2.3.3", @@ -155,7 +156,7 @@ }, { "command": "rust-analyzer.expandMacro", - "title": "Expand macro recursively", + "title": "Expand macro recursively at caret", "category": "rust-analyzer" }, { @@ -208,11 +209,6 @@ "title": "Rebuild proc macros and build scripts", "category": "rust-analyzer" }, - { - "command": "rust-analyzer.addProject", - "title": "Add current file's crate to workspace", - "category": "rust-analyzer" - }, { "command": "rust-analyzer.restartServer", "title": "Restart server", @@ -248,6 +244,11 @@ "title": "Open Docs", "category": "rust-analyzer" }, + { + "command": "rust-analyzer.openExternalDocs", + "title": "Open External Docs", + "category": "rust-analyzer" + }, { "command": "rust-analyzer.openCargoToml", "title": "Open Cargo.toml", @@ -260,12 +261,12 @@ }, { "command": "rust-analyzer.moveItemUp", - "title": "Move item up", + "title": "Move Item Up", "category": "rust-analyzer" }, { "command": "rust-analyzer.moveItemDown", - "title": "Move item down", + "title": "Move Item Down", "category": "rust-analyzer" }, { @@ -371,6 +372,19 @@ ], "markdownDescription": "Problem matchers to use for `rust-analyzer.run` command, eg `[\"$rustc\", \"$rust-panic\"]`." }, + "rust-analyzer.statusBar.clickAction": { + "type": "string", + "enum": [ + "stopServer", + "openLogs" + ], + "enumDescriptions": [ + "Stop Server", + "Open Logs" + ], + "default": "openLogs", + "markdownDescription": "Action to run when clicking the extension status bar item." + }, "rust-analyzer.server.path": { "type": [ "null", @@ -467,7 +481,7 @@ "type": "boolean" }, "rust-analyzer.diagnostics.useRustcErrorCode": { - "markdownDescription": "Whether to use the rustc error code.", + "markdownDescription": "Whether to show diagnostics using the original rustc error code. If this is false, all rustc diagnostics will have the code 'rustc(Click for full compiler diagnostics)'", "default": false, "type": "boolean" }, @@ -484,6 +498,11 @@ "default": true, "type": "boolean" }, + "rust-analyzer.showRequestFailedErrorNotification": { + "markdownDescription": "Whether to show error notifications for failing requests.", + "default": true, + "type": "boolean" + }, "rust-analyzer.showDependenciesExplorer": { "markdownDescription": "Whether to show the dependencies view.", "default": true, @@ -557,7 +576,7 @@ ] }, "rust-analyzer.cargo.buildScripts.overrideCommand": { - "markdownDescription": "Override the command rust-analyzer uses to run build scripts and\nbuild procedural macros. The command is required to output json\nand should therefore include `--message-format=json` or a similar\noption.\n\nBy default, a cargo invocation will be constructed for the configured\ntargets and features, with the following base command line:\n\n```bash\ncargo check --quiet --workspace --message-format=json --all-targets\n```\n.", + "markdownDescription": "Override the command rust-analyzer uses to run build scripts and\nbuild procedural macros. The command is required to output json\nand should therefore include `--message-format=json` or a similar\noption.\n\nIf there are multiple linked projects/workspaces, this command is invoked for\neach of them, with the working directory being the workspace root\n(i.e., the folder containing the `Cargo.toml`). This can be overwritten\nby changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and\n`#rust-analyzer.cargo.buildScripts.invocationLocation#`.\n\nBy default, a cargo invocation will be constructed for the configured\ntargets and features, with the following base command line:\n\n```bash\ncargo check --quiet --workspace --message-format=json --all-targets\n```\n.", "default": null, "type": [ "null", @@ -746,7 +765,7 @@ ] }, "rust-analyzer.check.overrideCommand": { - "markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option\n(if your client supports the `colorDiagnosticOutput` experimental\ncapability, you can use `--message-format=json-diagnostic-rendered-ansi`).\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.", + "markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option\n(if your client supports the `colorDiagnosticOutput` experimental\ncapability, you can use `--message-format=json-diagnostic-rendered-ansi`).\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects/workspaces, this command is invoked for\neach of them, with the working directory being the workspace root\n(i.e., the folder containing the `Cargo.toml`). This can be overwritten\nby changing `#rust-analyzer.cargo.check.invocationStrategy#` and\n`#rust-analyzer.cargo.check.invocationLocation#`.\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.", "default": null, "type": [ "null", @@ -799,6 +818,11 @@ "Do no snippet completions for callables." ] }, + "rust-analyzer.completion.fullFunctionSignatures.enable": { + "markdownDescription": "Whether to show full function/method signatures in completion docs.", + "default": false, + "type": "boolean" + }, "rust-analyzer.completion.limit": { "markdownDescription": "Maximum number of completions to return. If `None`, the limit is infinite.", "default": null, @@ -1105,11 +1129,16 @@ "default": true, "type": "boolean" }, - "rust-analyzer.imports.prefer.no.std": { + "rust-analyzer.imports.preferNoStd": { "markdownDescription": "Prefer to unconditionally use imports of the core and alloc crate, over the std crate.", "default": false, "type": "boolean" }, + "rust-analyzer.imports.preferPrelude": { + "markdownDescription": "Whether to prefer import paths containing a `prelude` module.", + "default": false, + "type": "boolean" + }, "rust-analyzer.imports.prefix": { "markdownDescription": "The path structure for newly inserted paths to use.", "default": "plain", @@ -1235,6 +1264,11 @@ "Show prefix or postfix depending on which uses less parenthesis, preferring postfix." ] }, + "rust-analyzer.inlayHints.implicitDrops.enable": { + "markdownDescription": "Whether to show implicit drop hints.", + "default": false, + "type": "boolean" + }, "rust-analyzer.inlayHints.lifetimeElisionHints.enable": { "markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.", "default": "never", @@ -1470,6 +1504,21 @@ "type": "string" } }, + "rust-analyzer.rust.analyzerTargetDir": { + "markdownDescription": "Optional path to a rust-analyzer specific target directory.\nThis prevents rust-analyzer's `cargo check` from locking the `Cargo.lock`\nat the expense of duplicating build artifacts.\n\nSet to `true` to use a subdirectory of the existing target directory or\nset to a path relative to the workspace to use that path.", + "default": null, + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "string" + } + ] + }, "rust-analyzer.rustc.source": { "markdownDescription": "Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private\nprojects, or \"discover\" to try to automatically find it if the `rustc-dev` component\nis installed.\n\nAny project which uses rust-analyzer with the rustcPrivate\ncrates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.\n\nThis option does not take effect until rust-analyzer is restarted.", "default": null, @@ -1616,7 +1665,7 @@ "message": 3 }, { - "regexp": "^[\\s->=]*(.*?):(\\d*):(\\d*)\\s*$", + "regexp": "^[\\s->=]*(.*?):([1-9]\\d*):([1-9]\\d*)\\s*$", "file": 1, "line": 2, "column": 3 diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts index ba8546763ec83..c27a446b38043 100644 --- a/src/tools/rust-analyzer/editors/code/src/client.ts +++ b/src/tools/rust-analyzer/editors/code/src/client.ts @@ -10,6 +10,7 @@ import { type Config, prepareVSCodeConfig } from "./config"; import { randomUUID } from "crypto"; import { sep as pathSeparator } from "path"; import { unwrapUndefinable } from "./undefinable"; +import { RaLanguageClient } from "./lang_client"; export interface Env { [name: string]: string; @@ -363,7 +364,7 @@ export async function createClient( }, }; - const client = new lc.LanguageClient( + const client = new RaLanguageClient( "rust-analyzer", "Rust Analyzer Language Server", serverOptions, @@ -389,6 +390,7 @@ class ExperimentalFeatures implements lc.StaticFeature { serverStatusNotification: true, colorDiagnosticOutput: true, openServerLogs: true, + localDocs: true, commands: { commands: [ "rust-analyzer.runSingle", diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts index 245557b1e88ad..3d33d255ad491 100644 --- a/src/tools/rust-analyzer/editors/code/src/commands.ts +++ b/src/tools/rust-analyzer/editors/code/src/commands.ts @@ -21,6 +21,7 @@ import type { LanguageClient } from "vscode-languageclient/node"; import { LINKED_COMMANDS } from "./client"; import type { DependencyId } from "./dependencies_provider"; import { unwrapUndefinable } from "./undefinable"; +import { log } from "./util"; export * from "./ast_inspector"; export * from "./run"; @@ -869,28 +870,6 @@ export function rebuildProcMacros(ctx: CtxInit): Cmd { return async () => ctx.client.sendRequest(ra.rebuildProcMacros); } -export function addProject(ctx: CtxInit): Cmd { - return async () => { - const extensionName = ctx.config.discoverProjectRunner; - // this command shouldn't be enabled in the first place if this isn't set. - if (!extensionName) { - return; - } - - const command = `${extensionName}.discoverWorkspaceCommand`; - const project: JsonProject = await vscode.commands.executeCommand(command); - - ctx.addToDiscoveredWorkspaces([project]); - - // this is a workaround to avoid needing writing the `rust-project.json` into - // a workspace-level VS Code-specific settings folder. We'd like to keep the - // `rust-project.json` entirely in-memory. - await ctx.client?.sendNotification(lc.DidChangeConfigurationNotification.type, { - settings: "", - }); - }; -} - async function showReferencesImpl( client: LanguageClient | undefined, uri: string, @@ -947,10 +926,51 @@ export function openDocs(ctx: CtxInit): Cmd { const position = editor.selection.active; const textDocument = { uri: editor.document.uri.toString() }; - const doclink = await client.sendRequest(ra.openDocs, { position, textDocument }); + const docLinks = await client.sendRequest(ra.openDocs, { position, textDocument }); + log.debug(docLinks); + + let fileType = vscode.FileType.Unknown; + if (docLinks.local !== undefined) { + try { + fileType = (await vscode.workspace.fs.stat(vscode.Uri.parse(docLinks.local))).type; + } catch (e) { + log.debug("stat() threw error. Falling back to web version", e); + } + } + + let docLink = fileType & vscode.FileType.File ? docLinks.local : docLinks.web; + if (docLink) { + // instruct vscode to handle the vscode-remote link directly + if (docLink.startsWith("vscode-remote://")) { + docLink = docLink.replace("vscode-remote://", "vscode://vscode-remote/"); + } + const docUri = vscode.Uri.parse(docLink); + await vscode.env.openExternal(docUri); + } + }; +} + +export function openExternalDocs(ctx: CtxInit): Cmd { + return async () => { + const editor = vscode.window.activeTextEditor; + if (!editor) { + return; + } + const client = ctx.client; + + const position = editor.selection.active; + const textDocument = { uri: editor.document.uri.toString() }; + + const docLinks = await client.sendRequest(ra.openDocs, { position, textDocument }); - if (doclink != null) { - await vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(doclink)); + let docLink = docLinks.web; + if (docLink) { + // instruct vscode to handle the vscode-remote link directly + if (docLink.startsWith("vscode-remote://")) { + docLink = docLink.replace("vscode-remote://", "vscode://vscode-remote/"); + } + const docUri = vscode.Uri.parse(docLink); + await vscode.env.openExternal(docUri); } }; } diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index 9821aee6f92b0..987d936943a1c 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -329,6 +329,10 @@ export class Config { get showDependenciesExplorer() { return this.get("showDependenciesExplorer"); } + + get statusBarClickAction() { + return this.get("statusBar.clickAction"); + } } // the optional `cb?` parameter is meant to be used to add additional diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts index 904efa4d5eb00..63ae386c8ad17 100644 --- a/src/tools/rust-analyzer/editors/code/src/ctx.ts +++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts @@ -1,5 +1,5 @@ import * as vscode from "vscode"; -import type * as lc from "vscode-languageclient/node"; +import * as lc from "vscode-languageclient/node"; import * as ra from "./lsp_ext"; import { Config, prepareVSCodeConfig } from "./config"; @@ -22,6 +22,7 @@ import { import { execRevealDependency } from "./commands"; import { PersistentState } from "./persistent_state"; import { bootstrap } from "./bootstrap"; +import type { RustAnalyzerExtensionApi } from "./main"; // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if // only those are in use. We use "Empty" to represent these scenarios @@ -64,7 +65,7 @@ export type CtxInit = Ctx & { readonly client: lc.LanguageClient; }; -export class Ctx { +export class Ctx implements RustAnalyzerExtensionApi { readonly statusBar: vscode.StatusBarItem; config: Config; readonly workspace: Workspace; @@ -189,8 +190,11 @@ export class Ctx { if (this.config.discoverProjectRunner) { const command = `${this.config.discoverProjectRunner}.discoverWorkspaceCommand`; log.info(`running command: ${command}`); - const project: JsonProject = await vscode.commands.executeCommand(command); - this.addToDiscoveredWorkspaces([project]); + const uris = vscode.workspace.textDocuments + .filter(isRustDocument) + .map((document) => document.uri); + const projects: JsonProject[] = await vscode.commands.executeCommand(command, uris); + this.setWorkspaces(projects); } if (this.workspace.kind === "Detached Files") { @@ -342,15 +346,17 @@ export class Ctx { return this._serverPath; } - addToDiscoveredWorkspaces(workspaces: JsonProject[]) { - for (const workspace of workspaces) { - const index = this.config.discoveredWorkspaces.indexOf(workspace); - if (~index) { - this.config.discoveredWorkspaces[index] = workspace; - } else { - this.config.discoveredWorkspaces.push(workspace); - } - } + setWorkspaces(workspaces: JsonProject[]) { + this.config.discoveredWorkspaces = workspaces; + } + + async notifyRustAnalyzer(): Promise { + // this is a workaround to avoid needing writing the `rust-project.json` into + // a workspace-level VS Code-specific settings folder. We'd like to keep the + // `rust-project.json` entirely in-memory. + await this.client?.sendNotification(lc.DidChangeConfigurationNotification.type, { + settings: "", + }); } private updateCommands(forceDisable?: "disable") { @@ -400,7 +406,11 @@ export class Ctx { statusBar.tooltip.appendText(status.message ?? "Ready"); statusBar.color = undefined; statusBar.backgroundColor = undefined; - statusBar.command = "rust-analyzer.openLogs"; + if (this.config.statusBarClickAction === "stopServer") { + statusBar.command = "rust-analyzer.stopServer"; + } else { + statusBar.command = "rust-analyzer.openLogs"; + } this.dependencies?.refresh(); break; case "warning": diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts index e817d680eaeff..06034e1648077 100644 --- a/src/tools/rust-analyzer/editors/code/src/debug.ts +++ b/src/tools/rust-analyzer/editors/code/src/debug.ts @@ -3,7 +3,7 @@ import * as vscode from "vscode"; import * as path from "path"; import type * as ra from "./lsp_ext"; -import { Cargo, getRustcId, getSysroot } from "./toolchain"; +import { Cargo, type ExecutableInfo, getRustcId, getSysroot } from "./toolchain"; import type { Ctx } from "./ctx"; import { prepareEnv } from "./run"; import { unwrapUndefinable } from "./undefinable"; @@ -12,6 +12,7 @@ const debugOutput = vscode.window.createOutputChannel("Debug"); type DebugConfigProvider = ( config: ra.Runnable, executable: string, + cargoWorkspace: string, env: Record, sourceFileMap?: Record, ) => vscode.DebugConfiguration; @@ -130,7 +131,7 @@ async function getDebugConfiguration( } const env = prepareEnv(runnable, ctx.config.runnablesExtraEnv); - const executable = await getDebugExecutable(runnable, env); + const { executable, workspace: cargoWorkspace } = await getDebugExecutableInfo(runnable, env); let sourceFileMap = debugOptions.sourceFileMap; if (sourceFileMap === "auto") { // let's try to use the default toolchain @@ -142,7 +143,13 @@ async function getDebugConfiguration( } const provider = unwrapUndefinable(knownEngines[debugEngine.id]); - const debugConfig = provider(runnable, simplifyPath(executable), env, sourceFileMap); + const debugConfig = provider( + runnable, + simplifyPath(executable), + cargoWorkspace, + env, + sourceFileMap, + ); if (debugConfig.type in debugOptions.engineSettings) { const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type]; for (var key in settingsMap) { @@ -164,20 +171,21 @@ async function getDebugConfiguration( return debugConfig; } -async function getDebugExecutable( +async function getDebugExecutableInfo( runnable: ra.Runnable, env: Record, -): Promise { +): Promise { const cargo = new Cargo(runnable.args.workspaceRoot || ".", debugOutput, env); - const executable = await cargo.executableFromArgs(runnable.args.cargoArgs); + const executableInfo = await cargo.executableInfoFromArgs(runnable.args.cargoArgs); // if we are here, there were no compilation errors. - return executable; + return executableInfo; } function getLldbDebugConfig( runnable: ra.Runnable, executable: string, + cargoWorkspace: string, env: Record, sourceFileMap?: Record, ): vscode.DebugConfiguration { @@ -187,7 +195,7 @@ function getLldbDebugConfig( name: runnable.label, program: executable, args: runnable.args.executableArgs, - cwd: runnable.args.workspaceRoot, + cwd: cargoWorkspace || runnable.args.workspaceRoot, sourceMap: sourceFileMap, sourceLanguages: ["rust"], env, @@ -197,6 +205,7 @@ function getLldbDebugConfig( function getCppvsDebugConfig( runnable: ra.Runnable, executable: string, + cargoWorkspace: string, env: Record, sourceFileMap?: Record, ): vscode.DebugConfiguration { @@ -206,7 +215,7 @@ function getCppvsDebugConfig( name: runnable.label, program: executable, args: runnable.args.executableArgs, - cwd: runnable.args.workspaceRoot, + cwd: cargoWorkspace || runnable.args.workspaceRoot, sourceFileMap, env, }; diff --git a/src/tools/rust-analyzer/editors/code/src/lang_client.ts b/src/tools/rust-analyzer/editors/code/src/lang_client.ts new file mode 100644 index 0000000000000..09d64efc048ae --- /dev/null +++ b/src/tools/rust-analyzer/editors/code/src/lang_client.ts @@ -0,0 +1,26 @@ +import * as lc from "vscode-languageclient/node"; +import * as vscode from "vscode"; + +export class RaLanguageClient extends lc.LanguageClient { + override handleFailedRequest( + type: lc.MessageSignature, + token: vscode.CancellationToken | undefined, + error: any, + defaultValue: T, + showNotification?: boolean | undefined, + ): T { + const showError = vscode.workspace + .getConfiguration("rust-analyzer") + .get("showRequestFailedErrorNotification"); + if ( + !showError && + error instanceof lc.ResponseError && + error.code === lc.ErrorCodes.InternalError + ) { + // Don't show notification for internal errors, these are emitted by r-a when a request fails. + showNotification = false; + } + + return super.handleFailedRequest(type, token, error, defaultValue, showNotification); + } +} diff --git a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts index bb7896973f178..f959a76639e03 100644 --- a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts +++ b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts @@ -74,8 +74,8 @@ export interface FetchDependencyListParams {} export interface FetchDependencyListResult { crates: { - name: string | undefined; - version: string | undefined; + name?: string; + version?: string; path: string; }[]; } @@ -135,7 +135,11 @@ export const onEnter = new lc.RequestType( "experimental/openCargoToml", ); -export const openDocs = new lc.RequestType( +export interface DocsUrls { + local?: string; + web?: string; +} +export const openDocs = new lc.RequestType( "experimental/externalDocs", ); export const parentModule = new lc.RequestType< diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts index ee5e5b1b80c84..3073353674ce5 100644 --- a/src/tools/rust-analyzer/editors/code/src/main.ts +++ b/src/tools/rust-analyzer/editors/code/src/main.ts @@ -9,8 +9,12 @@ import { setContextValue } from "./util"; const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; +// This API is not stable and may break in between minor releases. export interface RustAnalyzerExtensionApi { readonly client?: lc.LanguageClient; + + setWorkspaces(workspaces: JsonProject[]): void; + notifyRustAnalyzer(): Promise; } export async function deactivate() { @@ -152,7 +156,6 @@ function createCommands(): Record { shuffleCrateGraph: { enabled: commands.shuffleCrateGraph }, reloadWorkspace: { enabled: commands.reloadWorkspace }, rebuildProcMacros: { enabled: commands.rebuildProcMacros }, - addProject: { enabled: commands.addProject }, matchingBrace: { enabled: commands.matchingBrace }, joinLines: { enabled: commands.joinLines }, parentModule: { enabled: commands.parentModule }, @@ -170,6 +173,7 @@ function createCommands(): Record { debug: { enabled: commands.debug }, newDebugConfig: { enabled: commands.newDebugConfig }, openDocs: { enabled: commands.openDocs }, + openExternalDocs: { enabled: commands.openExternalDocs }, openCargoToml: { enabled: commands.openCargoToml }, peekTests: { enabled: commands.peekTests }, moveItemUp: { enabled: commands.moveItemUp }, diff --git a/src/tools/rust-analyzer/editors/code/src/toolchain.ts b/src/tools/rust-analyzer/editors/code/src/toolchain.ts index 58e5fc747a190..1037e513aa106 100644 --- a/src/tools/rust-analyzer/editors/code/src/toolchain.ts +++ b/src/tools/rust-analyzer/editors/code/src/toolchain.ts @@ -9,11 +9,17 @@ import { unwrapUndefinable } from "./undefinable"; interface CompilationArtifact { fileName: string; + workspace: string; name: string; kind: string; isTest: boolean; } +export interface ExecutableInfo { + executable: string; + workspace: string; +} + export interface ArtifactSpec { cargoArgs: string[]; filter?: (artifacts: CompilationArtifact[]) => CompilationArtifact[]; @@ -68,6 +74,7 @@ export class Cargo { artifacts.push({ fileName: message.executable, name: message.target.name, + workspace: message.manifest_path.replace(/\/Cargo\.toml$/, ""), kind: message.target.kind[0], isTest: message.profile.test, }); @@ -86,7 +93,7 @@ export class Cargo { return spec.filter?.(artifacts) ?? artifacts; } - async executableFromArgs(args: readonly string[]): Promise { + async executableInfoFromArgs(args: readonly string[]): Promise { const artifacts = await this.getArtifacts(Cargo.artifactSpec(args)); if (artifacts.length === 0) { @@ -96,7 +103,10 @@ export class Cargo { } const artifact = unwrapUndefinable(artifacts[0]); - return artifact.fileName; + return { + executable: artifact.fileName, + workspace: artifact.workspace, + }; } private async runCargo( diff --git a/src/tools/rust-analyzer/editors/code/tsconfig.json b/src/tools/rust-analyzer/editors/code/tsconfig.json index ee353c28dd670..c74284a00d964 100644 --- a/src/tools/rust-analyzer/editors/code/tsconfig.json +++ b/src/tools/rust-analyzer/editors/code/tsconfig.json @@ -2,14 +2,14 @@ "extends": "@tsconfig/strictest/tsconfig.json", "compilerOptions": { "esModuleInterop": false, - "module": "commonjs", - "moduleResolution": "node16", - "target": "es2021", + "module": "CommonJS", + "moduleResolution": "Node16", + "target": "ES2021", "outDir": "out", - "lib": ["es2021"], + "lib": ["ES2021"], "sourceMap": true, "rootDir": ".", - "newLine": "LF", + "newLine": "lf", // FIXME: https://github.com/rust-lang/rust-analyzer/issues/15253 "exactOptionalPropertyTypes": false diff --git a/src/tools/rust-analyzer/lib/line-index/Cargo.toml b/src/tools/rust-analyzer/lib/line-index/Cargo.toml index 6c0d06f471780..b7b4a01818ea7 100644 --- a/src/tools/rust-analyzer/lib/line-index/Cargo.toml +++ b/src/tools/rust-analyzer/lib/line-index/Cargo.toml @@ -7,5 +7,5 @@ repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/line-in edition = "2021" [dependencies] -text-size = "1.1.0" +text-size = "1.1.1" nohash-hasher = "0.2.0" diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml index 7ec3247e943aa..be1573913ff24 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml +++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml @@ -8,9 +8,10 @@ edition = "2021" [dependencies] log = "0.4.17" -serde_json = "1.0.96" -serde = { version = "1.0.156", features = ["derive"] } +serde_json = "1.0.108" +serde = { version = "1.0.192", features = ["derive"] } crossbeam-channel = "0.5.6" [dev-dependencies] lsp-types = "=0.94" +ctrlc = "3.4.1" diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs b/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs index affab60a22783..b190c0af73d73 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs @@ -17,7 +17,7 @@ use std::{ net::{TcpListener, TcpStream, ToSocketAddrs}, }; -use crossbeam_channel::{Receiver, Sender}; +use crossbeam_channel::{Receiver, RecvTimeoutError, Sender}; pub use crate::{ error::{ExtractError, ProtocolError}, @@ -113,11 +113,62 @@ impl Connection { /// } /// ``` pub fn initialize_start(&self) -> Result<(RequestId, serde_json::Value), ProtocolError> { - loop { - break match self.receiver.recv() { - Ok(Message::Request(req)) if req.is_initialize() => Ok((req.id, req.params)), + self.initialize_start_while(|| true) + } + + /// Starts the initialization process by waiting for an initialize as described in + /// [`Self::initialize_start`] as long as `running` returns + /// `true` while the return value can be changed through a sig handler such as `CTRL + C`. + /// + /// # Example + /// + /// ```rust + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// use std::sync::Arc; + /// # use std::error::Error; + /// # use lsp_types::{ClientCapabilities, InitializeParams, ServerCapabilities}; + /// # use lsp_server::{Connection, Message, Request, RequestId, Response}; + /// # fn main() -> Result<(), Box> { + /// let running = Arc::new(AtomicBool::new(true)); + /// # running.store(true, Ordering::SeqCst); + /// let r = running.clone(); + /// + /// ctrlc::set_handler(move || { + /// r.store(false, Ordering::SeqCst); + /// }).expect("Error setting Ctrl-C handler"); + /// + /// let (connection, io_threads) = Connection::stdio(); + /// + /// let res = connection.initialize_start_while(|| running.load(Ordering::SeqCst)); + /// # assert!(res.is_err()); + /// + /// # Ok(()) + /// # } + /// ``` + pub fn initialize_start_while( + &self, + running: C, + ) -> Result<(RequestId, serde_json::Value), ProtocolError> + where + C: Fn() -> bool, + { + while running() { + let msg = match self.receiver.recv_timeout(std::time::Duration::from_secs(1)) { + Ok(msg) => msg, + Err(RecvTimeoutError::Timeout) => { + continue; + } + Err(e) => { + return Err(ProtocolError(format!( + "expected initialize request, got error: {e}" + ))) + } + }; + + match msg { + Message::Request(req) if req.is_initialize() => return Ok((req.id, req.params)), // Respond to non-initialize requests with ServerNotInitialized - Ok(Message::Request(req)) => { + Message::Request(req) => { let resp = Response::new_err( req.id.clone(), ErrorCode::ServerNotInitialized as i32, @@ -126,15 +177,18 @@ impl Connection { self.sender.send(resp.into()).unwrap(); continue; } - Ok(Message::Notification(n)) if !n.is_exit() => { + Message::Notification(n) if !n.is_exit() => { continue; } - Ok(msg) => Err(ProtocolError(format!("expected initialize request, got {msg:?}"))), - Err(e) => { - Err(ProtocolError(format!("expected initialize request, got error: {e}"))) + msg => { + return Err(ProtocolError(format!("expected initialize request, got {msg:?}"))); } }; } + + return Err(ProtocolError(String::from( + "Initialization has been aborted during initialization", + ))); } /// Finishes the initialization process by sending an `InitializeResult` to the client @@ -156,6 +210,51 @@ impl Connection { } } + /// Finishes the initialization process as described in [`Self::initialize_finish`] as + /// long as `running` returns `true` while the return value can be changed through a sig + /// handler such as `CTRL + C`. + pub fn initialize_finish_while( + &self, + initialize_id: RequestId, + initialize_result: serde_json::Value, + running: C, + ) -> Result<(), ProtocolError> + where + C: Fn() -> bool, + { + let resp = Response::new_ok(initialize_id, initialize_result); + self.sender.send(resp.into()).unwrap(); + + while running() { + let msg = match self.receiver.recv_timeout(std::time::Duration::from_secs(1)) { + Ok(msg) => msg, + Err(RecvTimeoutError::Timeout) => { + continue; + } + Err(e) => { + return Err(ProtocolError(format!( + "expected initialized notification, got error: {e}", + ))); + } + }; + + match msg { + Message::Notification(n) if n.is_initialized() => { + return Ok(()); + } + msg => { + return Err(ProtocolError(format!( + r#"expected initialized notification, got: {msg:?}"# + ))); + } + } + } + + return Err(ProtocolError(String::from( + "Initialization has been aborted during initialization", + ))); + } + /// Initialize the connection. Sends the server capabilities /// to the client and returns the serialized client capabilities /// on success. If more fine-grained initialization is required use @@ -198,6 +297,58 @@ impl Connection { Ok(params) } + /// Initialize the connection as described in [`Self::initialize`] as long as `running` returns + /// `true` while the return value can be changed through a sig handler such as `CTRL + C`. + /// + /// # Example + /// + /// ```rust + /// use std::sync::atomic::{AtomicBool, Ordering}; + /// use std::sync::Arc; + /// # use std::error::Error; + /// # use lsp_types::ServerCapabilities; + /// # use lsp_server::{Connection, Message, Request, RequestId, Response}; + /// + /// # fn main() -> Result<(), Box> { + /// let running = Arc::new(AtomicBool::new(true)); + /// # running.store(true, Ordering::SeqCst); + /// let r = running.clone(); + /// + /// ctrlc::set_handler(move || { + /// r.store(false, Ordering::SeqCst); + /// }).expect("Error setting Ctrl-C handler"); + /// + /// let (connection, io_threads) = Connection::stdio(); + /// + /// let server_capabilities = serde_json::to_value(&ServerCapabilities::default()).unwrap(); + /// let initialization_params = connection.initialize_while( + /// server_capabilities, + /// || running.load(Ordering::SeqCst) + /// ); + /// + /// # assert!(initialization_params.is_err()); + /// # Ok(()) + /// # } + /// ``` + pub fn initialize_while( + &self, + server_capabilities: serde_json::Value, + running: C, + ) -> Result + where + C: Fn() -> bool, + { + let (id, params) = self.initialize_start_while(&running)?; + + let initialize_data = serde_json::json!({ + "capabilities": server_capabilities, + }); + + self.initialize_finish_while(id, initialize_data, running)?; + + Ok(params) + } + /// If `req` is `Shutdown`, respond to it and return `true`, otherwise return `false` pub fn handle_shutdown(&self, req: &Request) -> Result { if !req.is_shutdown() { diff --git a/src/tools/rust-analyzer/rust-bors.toml b/src/tools/rust-analyzer/rust-bors.toml new file mode 100644 index 0000000000000..c31ba66c50f47 --- /dev/null +++ b/src/tools/rust-analyzer/rust-bors.toml @@ -0,0 +1 @@ +timeout = 3600 diff --git a/src/tools/rust-analyzer/triagebot.toml b/src/tools/rust-analyzer/triagebot.toml index f0cd35399752f..95eed3ee172c0 100644 --- a/src/tools/rust-analyzer/triagebot.toml +++ b/src/tools/rust-analyzer/triagebot.toml @@ -11,5 +11,10 @@ allow-unauthenticated = [ new_pr = true [no-merges] -exclude_labels = ["sync"] +exclude_titles = [ # exclude syncs from subtree in rust-lang/rust + "Sync from downstream", + "sync from downstream", + "Sync from rust", + "sync from rust", +] labels = ["has-merge-commits", "S-waiting-on-author"] diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml index 7a34617e2558c..1c785b60a3d8f 100644 --- a/src/tools/rust-analyzer/xtask/Cargo.toml +++ b/src/tools/rust-analyzer/xtask/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" rust-version.workspace = true [dependencies] -anyhow = "1.0.62" +anyhow.workspace = true flate2 = "1.0.24" write-json = "0.1.2" -xshell = "0.2.2" +xshell.workspace = true xflags = "0.3.0" time = { version = "0.3", default-features = false } zip = { version = "0.6", default-features = false, features = ["deflate", "time"] } diff --git a/src/tools/rust-installer/Cargo.toml b/src/tools/rust-installer/Cargo.toml index 471f2b5ac73ed..cdd867c5f1577 100644 --- a/src/tools/rust-installer/Cargo.toml +++ b/src/tools/rust-installer/Cargo.toml @@ -16,7 +16,6 @@ rayon = "1.0" tar = "0.4.38" walkdir = "2" xz2 = "0.1.4" -num_cpus = "1" [dependencies.clap] features = ["derive"] diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index c7e6dd3615e94..6e630a80454ad 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -122,7 +122,31 @@ function checkNeededFields(fullPath, expected, error_text, queryName, position) } function valueCheck(fullPath, expected, result, error_text, queryName) { - if (Array.isArray(expected)) { + if (Array.isArray(expected) && result instanceof Map) { + const expected_set = new Set(); + for (const [key, expected_value] of expected) { + expected_set.add(key); + checkNeededFields(fullPath, expected_value, error_text, queryName, key); + if (result.has(key)) { + valueCheck( + fullPath + "[" + key + "]", + expected_value, + result.get(key), + error_text, + queryName + ); + } else { + error_text.push(`${queryName}==> EXPECTED has extra key in map from field ` + + `\`${fullPath}\` (key ${key}): \`${JSON.stringify(expected_value)}\``); + } + } + for (const [key, result_value] of result.entries()) { + if (!expected_set.has(key)) { + error_text.push(`${queryName}==> EXPECTED missing key in map from field ` + + `\`${fullPath}\` (key ${key}): \`${JSON.stringify(result_value)}\``); + } + } + } else if (Array.isArray(expected)) { let i; for (i = 0; i < expected.length; ++i) { checkNeededFields(fullPath, expected[i], error_text, queryName, i); @@ -153,6 +177,9 @@ function valueCheck(fullPath, expected, result, error_text, queryName) { } let result_v = result[key]; if (result_v !== null && key === "error") { + if (!result_v.forEach) { + throw result_v; + } result_v.forEach((value, index) => { value = value.split(" ").join(" "); if (index % 2 === 1) { diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml index 00e0ed37a84a3..032b9b548104b 100644 --- a/src/tools/rustfmt/Cargo.toml +++ b/src/tools/rustfmt/Cargo.toml @@ -43,7 +43,7 @@ diff = "0.1" dirs = "4.0" getopts = "0.2" ignore = "0.4" -itertools = "0.10" +itertools = "0.11" lazy_static = "1.4" regex = "1.7" serde = { version = "1.0.160", features = ["derive"] } diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index 16b8ce7a916a4..c1ce87eadcb99 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -29,7 +29,7 @@ pub(crate) fn rewrite_closure( binder: &ast::ClosureBinder, constness: ast::Const, capture: ast::CaptureBy, - is_async: &ast::Async, + coro_kind: &Option, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -40,7 +40,7 @@ pub(crate) fn rewrite_closure( debug!("rewrite_closure {:?}", body); let (prefix, extra_offset) = rewrite_closure_fn_decl( - binder, constness, capture, is_async, movability, fn_decl, body, span, context, shape, + binder, constness, capture, coro_kind, movability, fn_decl, body, span, context, shape, )?; // 1 = space between `|...|` and body. let body_shape = shape.offset_left(extra_offset)?; @@ -233,7 +233,7 @@ fn rewrite_closure_fn_decl( binder: &ast::ClosureBinder, constness: ast::Const, capture: ast::CaptureBy, - asyncness: &ast::Async, + coro_kind: &Option, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -263,8 +263,12 @@ fn rewrite_closure_fn_decl( } else { "" }; - let is_async = if asyncness.is_async() { "async " } else { "" }; - let mover = if capture == ast::CaptureBy::Value { + let coro = match coro_kind { + Some(ast::CoroutineKind::Async { .. }) => "async ", + Some(ast::CoroutineKind::Gen { .. }) => "gen ", + None => "", + }; + let mover = if matches!(capture, ast::CaptureBy::Value { .. }) { "move " } else { "" @@ -272,7 +276,7 @@ fn rewrite_closure_fn_decl( // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. let nested_shape = shape - .shrink_left(binder.len() + const_.len() + immovable.len() + is_async.len() + mover.len())? + .shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len())? .sub_width(4)?; // 1 = | @@ -310,7 +314,7 @@ fn rewrite_closure_fn_decl( .tactic(tactic) .preserve_newline(true); let list_str = write_list(&item_vec, &fmt)?; - let mut prefix = format!("{binder}{const_}{immovable}{is_async}{mover}|{list_str}|"); + let mut prefix = format!("{binder}{const_}{immovable}{coro}{mover}|{list_str}|"); if !ret_str.is_empty() { if prefix.contains('\n') { @@ -339,7 +343,7 @@ pub(crate) fn rewrite_last_closure( ref binder, constness, capture_clause, - ref asyncness, + ref coro_kind, movability, ref fn_decl, ref body, @@ -360,7 +364,7 @@ pub(crate) fn rewrite_last_closure( binder, constness, capture_clause, - asyncness, + coro_kind, movability, fn_decl, body, diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 8c2262fde811e..4515c27be374a 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -212,7 +212,7 @@ pub(crate) fn format_expr( &cl.binder, cl.constness, cl.capture_clause, - &cl.asyncness, + &cl.coro_kind, cl.movability, &cl.fn_decl, &cl.body, @@ -368,7 +368,7 @@ pub(crate) fn format_expr( } } ast::ExprKind::Gen(capture_by, ref block, ref kind) => { - let mover = if capture_by == ast::CaptureBy::Value { + let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) { "move " } else { "" @@ -1933,7 +1933,7 @@ fn rewrite_unary_op( shape: Shape, ) -> Option { // For some reason, an UnOp is not spanned like BinOp! - rewrite_unary_prefix(context, ast::UnOp::to_string(op), expr, shape) + rewrite_unary_prefix(context, op.as_str(), expr, shape) } pub(crate) enum RhsAssignKind<'ast> { diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index edb5a5b629a8f..4dff65f8cd0a6 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -287,7 +287,7 @@ pub(crate) struct FnSig<'a> { decl: &'a ast::FnDecl, generics: &'a ast::Generics, ext: ast::Extern, - is_async: Cow<'a, ast::Async>, + coro_kind: Cow<'a, Option>, constness: ast::Const, defaultness: ast::Defaultness, unsafety: ast::Unsafe, @@ -302,7 +302,7 @@ impl<'a> FnSig<'a> { ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, - is_async: Cow::Borrowed(&method_sig.header.asyncness), + coro_kind: Cow::Borrowed(&method_sig.header.coro_kind), constness: method_sig.header.constness, defaultness: ast::Defaultness::Final, ext: method_sig.header.ext, @@ -328,7 +328,7 @@ impl<'a> FnSig<'a> { generics, ext: fn_sig.header.ext, constness: fn_sig.header.constness, - is_async: Cow::Borrowed(&fn_sig.header.asyncness), + coro_kind: Cow::Borrowed(&fn_sig.header.coro_kind), defaultness, unsafety: fn_sig.header.unsafety, visibility: vis, @@ -343,7 +343,8 @@ impl<'a> FnSig<'a> { result.push_str(&*format_visibility(context, self.visibility)); result.push_str(format_defaultness(self.defaultness)); result.push_str(format_constness(self.constness)); - result.push_str(format_async(&self.is_async)); + self.coro_kind + .map(|coro_kind| result.push_str(format_coro(&coro_kind))); result.push_str(format_unsafety(self.unsafety)); result.push_str(&format_extern( self.ext, diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs index 95b0ed16db8c6..ef509b568372d 100644 --- a/src/tools/rustfmt/src/matches.rs +++ b/src/tools/rustfmt/src/matches.rs @@ -223,7 +223,7 @@ fn rewrite_match_arm( ) -> Option { let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { - let (_, body) = flatten_arm_body(context, &arm.body, None); + let (_, body) = flatten_arm_body(context, arm.body.as_deref()?, None); // `arm.span()` does not include trailing comma, add it manually. return Some(format!( "{}{}", @@ -246,7 +246,7 @@ fn rewrite_match_arm( }; // Patterns - let pat_shape = match &arm.body.kind { + let pat_shape = match &arm.body.as_ref()?.kind { ast::ExprKind::Block(_, Some(label)) => { // Some block with a label ` => 'label: {` // 7 = ` => : {` @@ -280,10 +280,10 @@ fn rewrite_match_arm( false, )?; - let arrow_span = mk_sp(arm.pat.span.hi(), arm.body.span().lo()); + let arrow_span = mk_sp(arm.pat.span.hi(), arm.body.as_ref()?.span().lo()); rewrite_match_body( context, - &arm.body, + arm.body.as_ref()?, &lhs_str, shape, guard_str.contains('\n'), diff --git a/src/tools/rustfmt/src/pairs.rs b/src/tools/rustfmt/src/pairs.rs index 07c0519373910..bfc2ffed3834e 100644 --- a/src/tools/rustfmt/src/pairs.rs +++ b/src/tools/rustfmt/src/pairs.rs @@ -339,7 +339,7 @@ impl FlattenPair for ast::Expr { if let Some(pop) = stack.pop() { match pop.kind { ast::ExprKind::Binary(op, _, ref rhs) => { - separators.push(op.node.to_string()); + separators.push(op.node.as_str()); node = rhs; } _ => unreachable!(), diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 33f3b4b8a21a5..8504999b8ff51 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -40,7 +40,9 @@ pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { fn is_short_pattern_inner(pat: &ast::Pat) -> bool { match pat.kind { - ast::PatKind::Rest | ast::PatKind::Wild | ast::PatKind::Lit(_) => true, + ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Lit(_) => { + true + } ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), ast::PatKind::Struct(..) | ast::PatKind::MacCall(..) @@ -193,6 +195,7 @@ impl Rewrite for Pat { None } } + PatKind::Never => None, PatKind::Range(ref lhs, ref rhs, ref end_kind) => { let infix = match end_kind.node { RangeEnd::Included(RangeSyntax::DotDotDot) => "...", diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 2136cfeae1af1..5960b14449948 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -97,7 +97,12 @@ impl Spanned for ast::Arm { } else { self.attrs[0].span.lo() }; - span_with_attrs_lo_hi!(self, lo, self.body.span.hi()) + let hi = if let Some(body) = &self.body { + body.span.hi() + } else { + self.pat.span.hi() + }; + span_with_attrs_lo_hi!(self, lo, hi) } } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 127aff913e37e..8ca2715037115 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -546,7 +546,7 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::Maybe => poly_trait_ref .rewrite(context, shape.offset_left(1)?) .map(|s| format!("?{}", s)), - ast::TraitBoundModifier::MaybeConst => poly_trait_ref + ast::TraitBoundModifier::MaybeConst(_) => poly_trait_ref .rewrite(context, shape.offset_left(7)?) .map(|s| format!("~const {}", s)), ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index fd49030bf1b4a..5805e417c04ad 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -75,10 +75,10 @@ pub(crate) fn format_visibility( } #[inline] -pub(crate) fn format_async(is_async: &ast::Async) -> &'static str { - match is_async { - ast::Async::Yes { .. } => "async ", - ast::Async::No => "", +pub(crate) fn format_coro(coro_kind: &ast::CoroutineKind) -> &'static str { + match coro_kind { + ast::CoroutineKind::Async { .. } => "async ", + ast::CoroutineKind::Gen { .. } => "gen ", } } diff --git a/src/tools/suggest-tests/src/lib.rs b/src/tools/suggest-tests/src/lib.rs index 44cd3c7f6a84d..1c1d9d0333ddb 100644 --- a/src/tools/suggest-tests/src/lib.rs +++ b/src/tools/suggest-tests/src/lib.rs @@ -33,13 +33,15 @@ pub fn get_suggestions>(modified_files: &[T]) -> Vec { let mut suggestions = Vec::new(); // static suggestions - for sug in STATIC_SUGGESTIONS.iter() { - let glob = Pattern::new(&sug.0).expect("Found invalid glob pattern!"); - - for file in modified_files { - if glob.matches(file.as_ref()) { - suggestions.extend_from_slice(&sug.1); - } + for (globs, sugs) in STATIC_SUGGESTIONS.iter() { + let globs = globs + .iter() + .map(|glob| Pattern::new(glob).expect("Found invalid glob pattern!")) + .collect::>(); + let matches_some_glob = |file: &str| globs.iter().any(|glob| glob.matches(file)); + + if modified_files.iter().map(AsRef::as_ref).any(matches_some_glob) { + suggestions.extend_from_slice(sugs); } } diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs index 0b541b60cba98..8e3625c244916 100644 --- a/src/tools/suggest-tests/src/main.rs +++ b/src/tools/suggest-tests/src/main.rs @@ -1,10 +1,17 @@ use std::process::ExitCode; -use build_helper::git::get_git_modified_files; +use build_helper::git::{get_git_modified_files, GitConfig}; use suggest_tests::get_suggestions; fn main() -> ExitCode { - let modified_files = get_git_modified_files(None, &Vec::new()); + let modified_files = get_git_modified_files( + &GitConfig { + git_repository: &env("SUGGEST_TESTS_GIT_REPOSITORY"), + nightly_branch: &env("SUGGEST_TESTS_NIGHTLY_BRANCH"), + }, + None, + &Vec::new(), + ); let modified_files = match modified_files { Ok(Some(files)) => files, Ok(None) => { @@ -25,3 +32,13 @@ fn main() -> ExitCode { ExitCode::SUCCESS } + +fn env(key: &str) -> String { + match std::env::var(key) { + Ok(var) => var, + Err(err) => { + eprintln!("suggest-tests: failed to read environment variable {key}: {err}"); + std::process::exit(1); + } + } +} diff --git a/src/tools/suggest-tests/src/static_suggestions.rs b/src/tools/suggest-tests/src/static_suggestions.rs index a84e78254f269..fbd265ea42a2e 100644 --- a/src/tools/suggest-tests/src/static_suggestions.rs +++ b/src/tools/suggest-tests/src/static_suggestions.rs @@ -2,23 +2,34 @@ use crate::{sug, Suggestion}; // FIXME: perhaps this could use `std::lazy` when it is stablizied macro_rules! static_suggestions { - ($( $glob:expr => [ $( $suggestion:expr ),* ] ),*) => { - pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy)>> - = ::once_cell::unsync::Lazy::new(|| vec![ $( ($glob, vec![ $($suggestion),* ]) ),*]); + ($( [ $( $glob:expr ),* $(,)? ] => [ $( $suggestion:expr ),* $(,)? ] ),* $(,)? ) => { + pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy, Vec)>> + = ::once_cell::unsync::Lazy::new(|| vec![ $( (vec![ $($glob),* ], vec![ $($suggestion),* ]) ),*]); } } static_suggestions! { - "*.md" => [ - sug!("test", 0, ["linkchecker"]) + ["*.md"] => [ + sug!("test", 0, ["linkchecker"]), ], - "compiler/*" => [ + ["compiler/*"] => [ sug!("check"), - sug!("test", 1, ["tests/ui", "tests/run-make"]) + sug!("test", 1, ["tests/ui", "tests/run-make"]), ], - "src/librustdoc/*" => [ - sug!("test", 1, ["rustdoc"]) - ] + ["compiler/rustc_mir_transform/*"] => [ + sug!("test", 1, ["mir-opt"]), + ], + + [ + "compiler/rustc_mir_transform/src/coverage/*", + "compiler/rustc_codegen_llvm/src/coverageinfo/*", + ] => [ + sug!("test", 1, ["coverage"]), + ], + + ["src/librustdoc/*"] => [ + sug!("test", 1, ["rustdoc"]), + ], } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 5e6dfaca702b8..b38d543647710 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -16,6 +16,7 @@ const LICENSES: &[&str] = &[ "Apache-2.0 OR MIT", "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license "Apache-2.0/MIT", + "BSD-2-Clause OR Apache-2.0 OR MIT", // zerocopy "ISC", "MIT / Apache-2.0", "MIT OR Apache-2.0 OR LGPL-2.1-or-later", // r-efi, r-efi-alloc @@ -121,15 +122,14 @@ const EXCEPTIONS_CARGO: ExceptionList = &[ ("similar", "Apache-2.0"), ("sized-chunks", "MPL-2.0+"), ("subtle", "BSD-3-Clause"), + ("supports-hyperlinks", "Apache-2.0"), ("unicode-bom", "Apache-2.0"), // tidy-alphabetical-end ]; const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[ // tidy-alphabetical-start - ("anymap", "BlueOak-1.0.0 OR MIT OR Apache-2.0"), // BlueOak is not acceptable, but we use it under MIT OR Apache-2 .0 ("dissimilar", "Apache-2.0"), - ("instant", "BSD-3-Clause"), ("notify", "CC0-1.0"), ("pulldown-cmark-to-cmark", "Apache-2.0"), ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 @@ -228,7 +228,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "ena", "equivalent", "errno", - "errno-dragonfly", "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", @@ -247,7 +246,10 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "hashbrown", "hermit-abi", "icu_list", + "icu_list_data", "icu_locid", + "icu_locid_transform", + "icu_locid_transform_data", "icu_provider", "icu_provider_adapters", "icu_provider_macros", @@ -287,6 +289,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "perf-event-open-sys", "pin-project-lite", "polonius-engine", + "portable-atomic", // dependency for platforms doesn't support `AtomicU64` in std "ppv-lite86", "proc-macro-hack", "proc-macro2", @@ -369,6 +372,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "unicode-security", "unicode-width", "unicode-xid", + "unwinding", "valuable", "version_check", "wasi", @@ -390,6 +394,34 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "yansi-term", // this is a false-positive: it's only used by rustfmt, but because it's enabled through a feature, tidy thinks it's used by rustc as well. "yoke", "yoke-derive", + "zerocopy", + "zerocopy-derive", + "zerofrom", + "zerofrom-derive", + "zerovec", + "zerovec-derive", + // tidy-alphabetical-end +]; + +// These crates come from ICU4X and are licensed under the unicode license. +// It currently doesn't have an SPDX identifier, so they cannot put one there. +// See https://github.com/unicode-org/icu4x/pull/3875 +// FIXME: This should be removed once ICU4X crates update. +const ICU4X_UNICODE_LICENSE_DEPENDENCIES: &[&str] = &[ + // tidy-alphabetical-start + "icu_list", + "icu_list_data", + "icu_locid", + "icu_locid_transform", + "icu_locid_transform_data", + "icu_provider", + "icu_provider_adapters", + "icu_provider_macros", + "litemap", + "tinystr", + "writeable", + "yoke", + "yoke-derive", "zerofrom", "zerofrom-derive", "zerovec", @@ -459,7 +491,6 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ /// to the cargo executable. pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { let mut checked_runtime_licenses = false; - let mut rust_metadata = None; for &(workspace, exceptions, permitted_deps) in WORKSPACES { if !root.join(workspace).join("Cargo.lock").exists() { @@ -483,15 +514,6 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { let runtime_ids = compute_runtime_crates(&metadata); check_runtime_license_exceptions(&metadata, runtime_ids, bad); checked_runtime_licenses = true; - rust_metadata = Some(metadata); - } else if workspace == "src/tools/cargo" { - check_rustfix( - rust_metadata - .as_ref() - .expect("The root workspace should be the first to be checked"), - &metadata, - bad, - ); } } @@ -589,6 +611,10 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba let license = match &pkg.license { Some(license) => license, None => { + if ICU4X_UNICODE_LICENSE_DEPENDENCIES.contains(&pkg.name.as_str()) { + // See the comment on ICU4X_UNICODE_LICENSE_DEPENDENCIES. + continue; + } tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id); continue; } @@ -716,33 +742,3 @@ fn deps_of_filtered<'a>( deps_of_filtered(metadata, &dep.pkg, result, filter); } } - -fn direct_deps_of<'a>( - metadata: &'a Metadata, - pkg_id: &'a PackageId, -) -> impl Iterator { - let resolve = metadata.resolve.as_ref().unwrap(); - let node = resolve.nodes.iter().find(|n| &n.id == pkg_id).unwrap(); - node.deps.iter().map(|dep| pkg_from_id(metadata, &dep.pkg)) -} - -fn check_rustfix(rust_metadata: &Metadata, cargo_metadata: &Metadata, bad: &mut bool) { - let cargo = pkg_from_name(cargo_metadata, "cargo"); - let cargo_rustfix = - direct_deps_of(cargo_metadata, &cargo.id).find(|p| p.name == "rustfix").unwrap(); - - let compiletest = pkg_from_name(rust_metadata, "compiletest"); - let compiletest_rustfix = - direct_deps_of(rust_metadata, &compiletest.id).find(|p| p.name == "rustfix").unwrap(); - - if cargo_rustfix.version != compiletest_rustfix.version { - tidy_error!( - bad, - "cargo's rustfix version {} does not match compiletest's rustfix version {}\n\ - rustfix should be kept in sync, update the cargo side first, and then update \ - compiletest along with cargo.", - cargo_rustfix.version, - compiletest_rustfix.version - ); - } -} diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 11480e2be603c..cb40c6e3a386f 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -427,9 +427,12 @@ pub fn check(path: &Path, bad: &mut bool) { "copyright notices attributed to the Rust Project Developers are deprecated" ); } - if is_unexplained_ignore(&extension, line) { - err(UNEXPLAINED_IGNORE_DOCTEST_INFO); + if !file.components().any(|c| c.as_os_str() == "rustc_baked_icu_data") { + if is_unexplained_ignore(&extension, line) { + err(UNEXPLAINED_IGNORE_DOCTEST_INFO); + } } + if filename.ends_with(".cpp") && line.contains("llvm_unreachable") { err(LLVM_UNREACHABLE_INFO); } diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 7e24793adee0e..40149f8f1c3b6 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,8 +10,8 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1854; -const ROOT_ENTRY_LIMIT: usize = 867; +const ISSUES_ENTRY_LIMIT: usize = 1852; +const ROOT_ENTRY_LIMIT: usize = 866; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/src/version b/src/version index 7c7053aa2388a..32a6ce3c719b4 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.75.0 +1.76.0 diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs index 4e296f3ade58b..4aeecf92d8659 100644 --- a/tests/assembly/asm/loongarch-type.rs +++ b/tests/assembly/asm/loongarch-type.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 16.0 // assembly-output: emit-asm // compile-flags: --target loongarch64-unknown-linux-gnu // needs-llvm-components: loongarch @@ -42,7 +41,7 @@ extern "C" { // Hack to avoid function merging extern "Rust" { - fn dont_merge(s: &str); + fn dont_merge(s: &str); } // CHECK-LABEL: sym_fn: diff --git a/tests/assembly/stack-protector/stack-protector-target-support.rs b/tests/assembly/stack-protector/stack-protector-target-support.rs index e5cbace80b1e2..6d87fd1912b09 100644 --- a/tests/assembly/stack-protector/stack-protector-target-support.rs +++ b/tests/assembly/stack-protector/stack-protector-target-support.rs @@ -2,7 +2,7 @@ // targets, with the exception of nvptx64-nvidia-cuda // // revisions: r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 -// revisions: r24 r25 r26 r27 r28 r29 r30 r31 r32 r33 r34 r35 r36 r37 r38 r39 r40 r41 r42 r43 r44 +// revisions: r24 r25 r26 r27 r28 r29 r30 r31 r32 r33 r35 r36 r37 r38 r39 r40 r41 r42 r43 r44 // revisions: r45 r46 r47 r48 r49 r50 r51 r52 r53 r54 r55 r56 r57 r58 r59 r60 r61 r62 r63 r64 r65 // revisions: r66 r67 r68 r69 r70 r71 r72 r73 r74 r75 r76 r77 r78 r79 r80 r81 r82 r83 r84 // assembly-output: emit-asm @@ -72,8 +72,7 @@ // [r32] needs-llvm-components: arm // [r33] compile-flags: --target armv7-unknown-linux-musleabihf // [r33] needs-llvm-components: arm -// [r34] compile-flags: --target asmjs-unknown-emscripten -// [r34] needs-llvm-components: webassembly + // [r35] compile-flags: --target i586-pc-windows-msvc // [r35] needs-llvm-components: x86 // [r36] compile-flags: --target i586-unknown-linux-gnu @@ -162,7 +161,7 @@ // [r77] needs-llvm-components: x86 // [r78] compile-flags:--target x86_64-linux-android // [r78] needs-llvm-components: x86 -// [r79] compile-flags:--target x86_64-sun-solaris +// [r79] compile-flags:--target x86_64-pc-solaris // [r79] needs-llvm-components: x86 // [r80] compile-flags:--target x86_64-unknown-freebsd // [r80] needs-llvm-components: x86 diff --git a/tests/assembly/thin-lto.rs b/tests/assembly/thin-lto.rs new file mode 100644 index 0000000000000..deb8fd21d14f0 --- /dev/null +++ b/tests/assembly/thin-lto.rs @@ -0,0 +1,8 @@ +// compile-flags: -O -C lto=thin -C prefer-dynamic=no +// only-x86_64-unknown-linux-gnu +// assembly-output: emit-asm + +// CHECK: main + +pub fn main() { +} diff --git a/tests/assembly/x86-stack-probes.rs b/tests/assembly/x86-stack-probes.rs index c7141fb208a0d..64a4efc0e1881 100644 --- a/tests/assembly/x86-stack-probes.rs +++ b/tests/assembly/x86-stack-probes.rs @@ -1,4 +1,3 @@ -// min-llvm-version: 16 // revisions: x86_64 i686 // assembly-output: emit-asm //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu diff --git a/tests/assembly/x86_64-function-return.rs b/tests/assembly/x86_64-function-return.rs new file mode 100644 index 0000000000000..0fcaca2d49109 --- /dev/null +++ b/tests/assembly/x86_64-function-return.rs @@ -0,0 +1,30 @@ +// Test that the function return is (not) converted into a jump to the thunk +// when the `-Zfunction-return={keep,thunk-extern}` flag is (not) set. + +// revisions: unset keep thunk-extern keep-thunk-extern thunk-extern-keep +// assembly-output: emit-asm +// compile-flags: -O +// [keep] compile-flags: -Zfunction-return=keep +// [thunk-extern] compile-flags: -Zfunction-return=thunk-extern +// [keep-thunk-extern] compile-flags: -Zfunction-return=keep -Zfunction-return=thunk-extern +// [thunk-extern-keep] compile-flags: -Zfunction-return=thunk-extern -Zfunction-return=keep +// only-x86_64 +// ignore-x86_64-apple-darwin Symbol is called `___x86_return_thunk` (Darwin's extra underscore) +// ignore-sgx Tests incompatible with LVI mitigations + +#![crate_type = "lib"] + +// CHECK-LABEL: foo: +#[no_mangle] +pub unsafe fn foo() { + // unset: ret + // unset-NOT: jmp __x86_return_thunk + // keep: ret + // keep-NOT: jmp __x86_return_thunk + // thunk-extern: jmp __x86_return_thunk + // thunk-extern-NOT: ret + // keep-thunk-extern: jmp __x86_return_thunk + // keep-thunk-extern-NOT: ret + // thunk-extern-keep: ret + // thunk-extern-keep-NOT: jmp __x86_return_thunk +} diff --git a/tests/codegen/ascii-char.rs b/tests/codegen/ascii-char.rs index 4167becf5e9a9..711ffe7e1a588 100644 --- a/tests/codegen/ascii-char.rs +++ b/tests/codegen/ascii-char.rs @@ -14,7 +14,7 @@ pub fn unwrap_digit_from_remainder(v: u32) -> AsciiChar { // CHECK: %[[R:.+]] = urem i32 %v, 10 // CHECK-NEXT: %[[T:.+]] = trunc i32 %[[R]] to i8 - // CHECK-NEXT: %[[D:.+]] = or i8 %[[T]], 48 + // CHECK-NEXT: %[[D:.+]] = or{{( disjoint)?}} i8 %[[T]], 48 // CHECK-NEXT: ret i8 %[[D]] // CHECK-NOT: icmp diff --git a/tests/codegen/cross-crate-inlining/always-inline.rs b/tests/codegen/cross-crate-inlining/always-inline.rs new file mode 100644 index 0000000000000..f3f08bf116aee --- /dev/null +++ b/tests/codegen/cross-crate-inlining/always-inline.rs @@ -0,0 +1,13 @@ +// compile-flags: -O +// aux-build:always.rs + +#![crate_type = "lib"] + +extern crate always; + +// Check that we inline a cross-crate call, even though it isn't a leaf +#[no_mangle] +pub fn outer() -> String { + // CHECK-NOT: call {{.*}}stem_fn + always::stem_fn() +} diff --git a/tests/codegen/cross-crate-inlining/auxiliary/always.rs b/tests/codegen/cross-crate-inlining/auxiliary/always.rs new file mode 100644 index 0000000000000..3670307ec8134 --- /dev/null +++ b/tests/codegen/cross-crate-inlining/auxiliary/always.rs @@ -0,0 +1,20 @@ +// compile-flags: -O -Zcross-crate-inline-threshold=always + +#![crate_type = "lib"] + +// This function *looks* like it contains a call, but that call will be optimized out by MIR +// optimizations. +pub fn leaf_fn() -> String { + String::new() +} + +// This function contains a call, even after MIR optimizations. It is only eligible for +// cross-crate-inlining with "always". +pub fn stem_fn() -> String { + inner() +} + +#[inline(never)] +fn inner() -> String { + String::from("test") +} diff --git a/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs b/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs new file mode 100644 index 0000000000000..963f087f22d4d --- /dev/null +++ b/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs @@ -0,0 +1,20 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +// This function *looks* like it contains a call, but that call will be optimized out by MIR +// optimizations. +pub fn leaf_fn() -> String { + String::new() +} + +// This function contains a call, even after MIR optimizations. It is only eligible for +// cross-crate-inlining with "always". +pub fn stem_fn() -> String { + inner() +} + +#[inline(never)] +fn inner() -> String { + String::from("test") +} diff --git a/tests/codegen/cross-crate-inlining/auxiliary/never.rs b/tests/codegen/cross-crate-inlining/auxiliary/never.rs new file mode 100644 index 0000000000000..e222a6dea3871 --- /dev/null +++ b/tests/codegen/cross-crate-inlining/auxiliary/never.rs @@ -0,0 +1,20 @@ +// compile-flags: -O -Zcross-crate-inline-threshold=never + +#![crate_type = "lib"] + +// This function *looks* like it contains a call, but that call will be optimized out by MIR +// optimizations. +pub fn leaf_fn() -> String { + String::new() +} + +// This function contains a call, even after MIR optimizations. It is only eligible for +// cross-crate-inlining with "always". +pub fn stem_fn() -> String { + inner() +} + +#[inline(never)] +fn inner() -> String { + String::from("test") +} diff --git a/tests/codegen/cross-crate-inlining/leaf-inlining.rs b/tests/codegen/cross-crate-inlining/leaf-inlining.rs new file mode 100644 index 0000000000000..73b1a520b06cf --- /dev/null +++ b/tests/codegen/cross-crate-inlining/leaf-inlining.rs @@ -0,0 +1,20 @@ +// compile-flags: -O -Zcross-crate-inline-threshold=yes +// aux-build:leaf.rs + +#![crate_type = "lib"] + +extern crate leaf; + +// Check that we inline a leaf cross-crate call +#[no_mangle] +pub fn leaf_outer() -> String { + // CHECK-NOT: call {{.*}}leaf_fn + leaf::leaf_fn() +} + +// Check that we do not inline a non-leaf cross-crate call +#[no_mangle] +pub fn stem_outer() -> String { + // CHECK: call {{.*}}stem_fn + leaf::stem_fn() +} diff --git a/tests/codegen/cross-crate-inlining/never-inline.rs b/tests/codegen/cross-crate-inlining/never-inline.rs new file mode 100644 index 0000000000000..4e7bc3e5154cb --- /dev/null +++ b/tests/codegen/cross-crate-inlining/never-inline.rs @@ -0,0 +1,13 @@ +// compile-flags: -O +// aux-build:never.rs + +#![crate_type = "lib"] + +extern crate never; + +// Check that we do not inline a cross-crate call, even though it is a leaf +#[no_mangle] +pub fn outer() -> String { + // CHECK: call {{.*}}leaf_fn + never::leaf_fn() +} diff --git a/tests/codegen/ehcontguard_disabled.rs b/tests/codegen/ehcontguard_disabled.rs new file mode 100644 index 0000000000000..7773384e5ead4 --- /dev/null +++ b/tests/codegen/ehcontguard_disabled.rs @@ -0,0 +1,10 @@ +// compile-flags: + +#![crate_type = "lib"] + +// A basic test function. +pub fn test() { +} + +// Ensure the module flag ehcontguard is not present +// CHECK-NOT: !"ehcontguard" diff --git a/tests/codegen/ehcontguard_enabled.rs b/tests/codegen/ehcontguard_enabled.rs new file mode 100644 index 0000000000000..03aaa342b9678 --- /dev/null +++ b/tests/codegen/ehcontguard_enabled.rs @@ -0,0 +1,10 @@ +// compile-flags: -Z ehcont-guard + +#![crate_type = "lib"] + +// A basic test function. +pub fn test() { +} + +// Ensure the module flag ehcontguard=1 is present +// CHECK: !"ehcontguard", i32 1 diff --git a/tests/codegen/function-return.rs b/tests/codegen/function-return.rs new file mode 100644 index 0000000000000..d832d19ac3923 --- /dev/null +++ b/tests/codegen/function-return.rs @@ -0,0 +1,28 @@ +// Test that the `fn_ret_thunk_extern` function attribute is (not) emitted when +// the `-Zfunction-return={keep,thunk-extern}` flag is (not) set. + +// revisions: unset keep thunk-extern keep-thunk-extern thunk-extern-keep +// needs-llvm-components: x86 +// compile-flags: --target x86_64-unknown-linux-gnu +// [keep] compile-flags: -Zfunction-return=keep +// [thunk-extern] compile-flags: -Zfunction-return=thunk-extern +// [keep-thunk-extern] compile-flags: -Zfunction-return=keep -Zfunction-return=thunk-extern +// [thunk-extern-keep] compile-flags: -Zfunction-return=thunk-extern -Zfunction-return=keep + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[no_mangle] +pub fn foo() { + // CHECK: @foo() unnamed_addr #0 + + // unset-NOT: fn_ret_thunk_extern + // keep-NOT: fn_ret_thunk_extern + // thunk-extern: attributes #0 = { {{.*}}fn_ret_thunk_extern{{.*}} } + // keep-thunk-extern: attributes #0 = { {{.*}}fn_ret_thunk_extern{{.*}} } + // thunk-extern-keep-NOT: fn_ret_thunk_extern +} diff --git a/tests/codegen/issues/issue-101048.rs b/tests/codegen/issues/issue-101048.rs index efa4db93ec212..e4712cf9cb3f6 100644 --- a/tests/codegen/issues/issue-101048.rs +++ b/tests/codegen/issues/issue-101048.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 16 #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs index 2cbe99942cba3..58fcd75a8f2de 100644 --- a/tests/codegen/issues/issue-101082.rs +++ b/tests/codegen/issues/issue-101082.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 16 // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-101814.rs b/tests/codegen/issues/issue-101814.rs index 13796352c0285..63a8cebcb608a 100644 --- a/tests/codegen/issues/issue-101814.rs +++ b/tests/codegen/issues/issue-101814.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 16 // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-103132.rs b/tests/codegen/issues/issue-103132.rs index cc87d7cd2b9da..521d424c2696b 100644 --- a/tests/codegen/issues/issue-103132.rs +++ b/tests/codegen/issues/issue-103132.rs @@ -1,5 +1,4 @@ // compile-flags: -O -C overflow-checks -// min-llvm-version: 16 #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-103327.rs b/tests/codegen/issues/issue-103327.rs index cee00faccc811..021f1ca0c3af0 100644 --- a/tests/codegen/issues/issue-103327.rs +++ b/tests/codegen/issues/issue-103327.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 16 #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-103840.rs b/tests/codegen/issues/issue-103840.rs index da64692d27d92..f19d7031bb386 100644 --- a/tests/codegen/issues/issue-103840.rs +++ b/tests/codegen/issues/issue-103840.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 16.0 #![crate_type = "lib"] pub fn foo(t: &mut Vec) { diff --git a/tests/codegen/issues/issue-116878.rs b/tests/codegen/issues/issue-116878.rs new file mode 100644 index 0000000000000..d5f679459f731 --- /dev/null +++ b/tests/codegen/issues/issue-116878.rs @@ -0,0 +1,13 @@ +// no-system-llvm +// compile-flags: -O +// ignore-debug: the debug assertions get in the way +#![crate_type = "lib"] + +/// Make sure no bounds checks are emitted after a `get_unchecked`. +// CHECK-LABEL: @unchecked_slice_no_bounds_check +#[no_mangle] +pub unsafe fn unchecked_slice_no_bounds_check(s: &[u8]) -> u8 { + let a = *s.get_unchecked(1); + // CHECK-NOT: panic_bounds_check + a + s[0] +} diff --git a/tests/codegen/issues/issue-75978.rs b/tests/codegen/issues/issue-75978.rs index f335e92c3dc44..abfafc35f0b47 100644 --- a/tests/codegen/issues/issue-75978.rs +++ b/tests/codegen/issues/issue-75978.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 16 #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-99960.rs b/tests/codegen/issues/issue-99960.rs index e9c9367fa64b6..ad0315a8227ec 100644 --- a/tests/codegen/issues/issue-99960.rs +++ b/tests/codegen/issues/issue-99960.rs @@ -1,5 +1,4 @@ // compile-flags: -O -// min-llvm-version: 16 #![crate_type = "lib"] diff --git a/tests/codegen/llvm_module_flags.rs b/tests/codegen/llvm_module_flags.rs new file mode 100644 index 0000000000000..acc035086de20 --- /dev/null +++ b/tests/codegen/llvm_module_flags.rs @@ -0,0 +1,7 @@ +// Test for -Z llvm_module_flags +// compile-flags: -Z llvm_module_flag=foo:u32:123:error -Z llvm_module_flag=bar:u32:42:max + +fn main() {} + +// CHECK: !{i32 1, !"foo", i32 123} +// CHECK: !{i32 7, !"bar", i32 42} diff --git a/tests/codegen/sanitizer/cfi-normalize-integers.rs b/tests/codegen/sanitizer/cfi-normalize-integers.rs index 9663aa54c28d6..d3cece4c7b6f2 100644 --- a/tests/codegen/sanitizer/cfi-normalize-integers.rs +++ b/tests/codegen/sanitizer/cfi-normalize-integers.rs @@ -6,78 +6,41 @@ #![crate_type="lib"] extern crate core; -use core::ffi::*; pub fn foo0(_: bool) { } // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} -pub fn foo1(_: bool, _: c_uchar) { } +pub fn foo1(_: bool, _: bool) { } // CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} -pub fn foo2(_: bool, _: c_uchar, _: c_uchar) { } +pub fn foo2(_: bool, _: bool, _: bool) { } // CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} -pub fn foo3(_: isize) { } +pub fn foo3(_: char) { } // CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} -pub fn foo4(_: isize, _: c_long) { } +pub fn foo4(_: char, _: char) { } // CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} -pub fn foo5(_: isize, _: c_long, _: c_longlong) { } +pub fn foo5(_: char, _: char, _: char) { } // CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} -pub fn foo6(_: usize) { } +pub fn foo6(_: isize) { } // CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} -pub fn foo7(_: usize, _: c_ulong) { } +pub fn foo7(_: isize, _: isize) { } // CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} -pub fn foo8(_: usize, _: c_ulong, _: c_ulonglong) { } +pub fn foo8(_: isize, _: isize, _: isize) { } // CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} -pub fn foo9(_: c_schar) { } +pub fn foo9(_: (), _: usize) { } // CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} -pub fn foo10(_: c_char, _: c_schar) { } +pub fn foo10(_: (), _: usize, _: usize) { } // CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} -pub fn foo11(_: c_char, _: c_schar, _: c_schar) { } +pub fn foo11(_: (), _: usize, _: usize, _: usize) { } // CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} -pub fn foo12(_: c_int) { } -// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} -pub fn foo13(_: c_int, _: c_int) { } -// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} -pub fn foo14(_: c_int, _: c_int, _: c_int) { } -// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} -pub fn foo15(_: c_short) { } -// CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}} -pub fn foo16(_: c_short, _: c_short) { } -// CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]] !type !{{[0-9]+}} -pub fn foo17(_: c_short, _: c_short, _: c_short) { } -// CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]] !type !{{[0-9]+}} -pub fn foo18(_: c_uint) { } -// CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]] !type !{{[0-9]+}} -pub fn foo19(_: c_uint, _: c_uint) { } -// CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]] !type !{{[0-9]+}} -pub fn foo20(_: c_uint, _: c_uint, _: c_uint) { } -// CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]] !type !{{[0-9]+}} -pub fn foo21(_: c_ushort) { } -// CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]] !type !{{[0-9]+}} -pub fn foo22(_: c_ushort, _: c_ushort) { } -// CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]] !type !{{[0-9]+}} -pub fn foo23(_: c_ushort, _: c_ushort, _: c_ushort) { } -// CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]] !type !{{[0-9]+}} // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvu2u8E.normalized"} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu2u8S_E.normalized"} // CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu2u8S_S_E.normalized"} -// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}E.normalized"} -// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}{{u3i32|u3i64|S_}}E.normalized"} -// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}{{u3i32|u3i64|S_}}{{u3i64|S_|S0_}}E.normalized"} -// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}E.normalized"} -// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}{{u3u32|u3u64|S_}}E.normalized"} -// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}{{u3u32|u3u64|S_}}{{u3u64|S_|S0_}}E.normalized"} -// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu2i8E.normalized"} -// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFv{{u2i8S_|u2u8u2i8}}E.normalized"} -// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFv{{u2i8S_S_|u2u8u2i8S0_}}E.normalized"} -// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}E.normalized"} -// CHECK: ![[TYPE13]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}S_E.normalized"} -// CHECK: ![[TYPE14]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64}}S_S_E.normalized"} -// CHECK: ![[TYPE15]] = !{i64 0, !"_ZTSFvu3i16E.normalized"} -// CHECK: ![[TYPE16]] = !{i64 0, !"_ZTSFvu3i16S_E.normalized"} -// CHECK: ![[TYPE17]] = !{i64 0, !"_ZTSFvu3i16S_S_E.normalized"} -// CHECK: ![[TYPE18]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}E.normalized"} -// CHECK: ![[TYPE19]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}S_E.normalized"} -// CHECK: ![[TYPE20]] = !{i64 0, !"_ZTSFv{{u3u16|u3u32|u3u64}}S_S_E.normalized"} -// CHECK: ![[TYPE21]] = !{i64 0, !"_ZTSFvu3u16E.normalized"} -// CHECK: ![[TYPE22]] = !{i64 0, !"_ZTSFvu3u16S_E.normalized"} -// CHECK: ![[TYPE23]] = !{i64 0, !"_ZTSFvu3u16S_S_E.normalized"} +// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3u32E.normalized"} +// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3u32S_E.normalized"} +// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3u32S_S_E.normalized"} +// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64|u4i128}}E.normalized"} +// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64|u4i128}}S_E.normalized"} +// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFv{{u3i16|u3i32|u3i64|u4i128}}S_S_E.normalized"} +// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvv{{u3u16|u3u32|u3u64|u4u128}}E.normalized"} +// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvv{{u3u16|u3u32|u3u64|u4u128}}S_E.normalized"} +// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvv{{u3u16|u3u32|u3u64|u4u128}}S_S_E.normalized"} diff --git a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs index 29d50d8df24ae..18d315c9598bf 100644 --- a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs +++ b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs @@ -6,10 +6,8 @@ //[aarch64] needs-llvm-components: aarch64 //[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf //[riscv64imac] needs-llvm-components: riscv -//[riscv64imac] min-llvm-version: 16 //[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf //[riscv64gc] needs-llvm-components: riscv -//[riscv64gc] min-llvm-version: 16 //[x86_64] compile-flags: --target x86_64-unknown-none //[x86_64] needs-llvm-components: x86 diff --git a/tests/codegen/simd/simd-wide-sum.rs b/tests/codegen/simd/simd-wide-sum.rs index 6e7d3d9316a77..109d538134388 100644 --- a/tests/codegen/simd/simd-wide-sum.rs +++ b/tests/codegen/simd/simd-wide-sum.rs @@ -10,7 +10,7 @@ #![crate_type = "lib"] #![feature(portable_simd)] -use std::simd::{Simd, SimdUint}; +use std::simd::prelude::*; const N: usize = 16; #[no_mangle] diff --git a/tests/codegen/simd/unpadded-simd.rs b/tests/codegen/simd/unpadded-simd.rs index eb44dbd931352..797bca38ffa1d 100644 --- a/tests/codegen/simd/unpadded-simd.rs +++ b/tests/codegen/simd/unpadded-simd.rs @@ -5,10 +5,15 @@ #![crate_type = "lib"] #![feature(repr_simd)] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] #[repr(simd)] pub struct int16x4_t(pub i16, pub i16, pub i16, pub i16); -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t); + // CHECK: %int16x4x2_t = type { <4 x i16>, <4 x i16> } +#[no_mangle] +fn takes_int16x4x2_t(t: int16x4x2_t) -> int16x4x2_t { + t +} diff --git a/tests/codegen/slice-iter-fold.rs b/tests/codegen/slice-iter-fold.rs index 9391c176130a4..a55425cb6bbc6 100644 --- a/tests/codegen/slice-iter-fold.rs +++ b/tests/codegen/slice-iter-fold.rs @@ -1,6 +1,5 @@ // ignore-debug: the debug assertions get in the way // compile-flags: -O -// min-llvm-version: 16 #![crate_type = "lib"] // CHECK-LABEL: @slice_fold_to_last diff --git a/tests/codegen/stack-probes-call.rs b/tests/codegen/stack-probes-call.rs deleted file mode 100644 index a18fd41c28c0e..0000000000000 --- a/tests/codegen/stack-probes-call.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Check the "probe-stack" attribute for targets with `StackProbeType::Call`, -// or `StackProbeType::InlineOrCall` when running on older LLVM. - -// compile-flags: -C no-prepopulate-passes -// revisions: i686 x86_64 -//[i686] compile-flags: --target i686-unknown-linux-gnu -//[i686] needs-llvm-components: x86 -//[i686] ignore-llvm-version: 16 - 99 -//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -//[x86_64] needs-llvm-components: x86 -//[x86_64] ignore-llvm-version: 16 - 99 - -#![crate_type = "rlib"] -#![feature(no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - -#[no_mangle] -pub fn foo() { -// CHECK: @foo() unnamed_addr #0 -// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} } -} diff --git a/tests/codegen/stack-probes-inline.rs b/tests/codegen/stack-probes-inline.rs index a6b781de531fd..058c363969f08 100644 --- a/tests/codegen/stack-probes-inline.rs +++ b/tests/codegen/stack-probes-inline.rs @@ -13,10 +13,8 @@ //[s390x] needs-llvm-components: systemz //[i686] compile-flags: --target i686-unknown-linux-gnu //[i686] needs-llvm-components: x86 -//[i686] min-llvm-version: 16 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu //[x86_64] needs-llvm-components: x86 -//[x86_64] min-llvm-version: 16 #![crate_type = "rlib"] #![feature(no_core, lang_items)] diff --git a/tests/codegen/thin-lto.rs b/tests/codegen/thin-lto.rs new file mode 100644 index 0000000000000..7991cad7a0ca8 --- /dev/null +++ b/tests/codegen/thin-lto.rs @@ -0,0 +1,7 @@ +// compile-flags: -O -C lto=thin -C prefer-dynamic=no +// only-x86_64-unknown-linux-gnu + +// CHECK: main + +pub fn main() { +} diff --git a/tests/codegen/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs index aca9bec77dfeb..eded894c6d085 100644 --- a/tests/codegen/unchecked_shifts.rs +++ b/tests/codegen/unchecked_shifts.rs @@ -31,7 +31,7 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { #[no_mangle] pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 { // CHECK-NOT: assume - // CHECK: %[[EXT:.+]] = zext i32 %b to i64 + // CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i32 %b to i64 // CHECK: shl i64 %a, %[[EXT]] a.unchecked_shl(b) } @@ -63,7 +63,7 @@ pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 { #[no_mangle] pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 { // CHECK-NOT: assume - // CHECK: %[[EXT:.+]] = zext i32 %b to i64 + // CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i32 %b to i64 // CHECK: ashr i64 %a, %[[EXT]] a.unchecked_shr(b) } diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs index d68067ceb19f7..5cf7add836dfb 100644 --- a/tests/codegen/vec-in-place.rs +++ b/tests/codegen/vec-in-place.rs @@ -1,6 +1,5 @@ // ignore-debug: the debug assertions get in the way // compile-flags: -O -Z merge-functions=disabled -// min-llvm-version: 16 #![crate_type = "lib"] // Ensure that trivial casts of vec elements are O(1) diff --git a/tests/codegen/vec-reserve-extend.rs b/tests/codegen/vec-reserve-extend.rs new file mode 100644 index 0000000000000..d95220104c229 --- /dev/null +++ b/tests/codegen/vec-reserve-extend.rs @@ -0,0 +1,14 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @should_reserve_once +#[no_mangle] +pub fn should_reserve_once(v: &mut Vec) { + // CHECK: tail call void @llvm.assume + v.try_reserve(3).unwrap(); + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}do_reserve_and_handle + // CHECK-NOT: call {{.*}}__rust_alloc( + v.extend([1, 2, 3]); +} diff --git a/tests/coverage-map/README.md b/tests/coverage-map/README.md deleted file mode 100644 index 60d1352cd64f1..0000000000000 --- a/tests/coverage-map/README.md +++ /dev/null @@ -1,13 +0,0 @@ -The tests in `./status-quo` were copied from `tests/run-coverage` in order to -capture the current behavior of the instrumentor on non-trivial programs. -The actual mappings have not been closely inspected. - -## Maintenance note - -These tests can be sensitive to small changes in MIR spans or MIR control flow, -especially in HIR-to-MIR lowering or MIR optimizations. - -If you haven't touched the coverage code directly, and the `run-coverage` test -suite still works, then it should usually be OK to just `--bless` these -coverage mapping tests as necessary, without worrying too much about the exact -changes. diff --git a/tests/coverage-map/if.cov-map b/tests/coverage-map/if.cov-map deleted file mode 100644 index 3cedb5ffbecb1..0000000000000 --- a/tests/coverage-map/if.cov-map +++ /dev/null @@ -1,15 +0,0 @@ -Function name: if::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12) -- Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6) -- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) - = (c0 - c1) -- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2) - = (c1 + (c0 - c1)) - diff --git a/tests/coverage-map/if.rs b/tests/coverage-map/if.rs deleted file mode 100644 index ed3f69bdc98d2..0000000000000 --- a/tests/coverage-map/if.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags: --edition=2021 - -fn main() { - let cond = std::env::args().len() == 1; - if cond { - println!("true"); - } - println!("done"); -} diff --git a/tests/coverage-map/status-quo/sort_groups.rs b/tests/coverage-map/status-quo/sort_groups.rs deleted file mode 100644 index f89f9f3ec61fa..0000000000000 --- a/tests/coverage-map/status-quo/sort_groups.rs +++ /dev/null @@ -1,23 +0,0 @@ -// compile-flags: --edition=2021 - -// Demonstrate that `sort_subviews.py` can sort instantiation groups into a -// predictable order, while preserving their heterogeneous contents. - -fn main() { - let cond = std::env::args().len() > 1; - generic_fn::<()>(cond); - generic_fn::<&'static str>(!cond); - if false { - generic_fn::(cond); - } - generic_fn::(cond); - other_fn(); -} - -fn generic_fn(cond: bool) { - if cond { - println!("{}", std::any::type_name::()); - } -} - -fn other_fn() {} diff --git a/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs b/tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs similarity index 100% rename from tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs rename to tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage similarity index 100% rename from tests/run-coverage-rustdoc/doctest.coverage rename to tests/coverage-run-rustdoc/doctest.coverage diff --git a/tests/run-coverage-rustdoc/doctest.rs b/tests/coverage-run-rustdoc/doctest.rs similarity index 100% rename from tests/run-coverage-rustdoc/doctest.rs rename to tests/coverage-run-rustdoc/doctest.rs diff --git a/tests/coverage/README.md b/tests/coverage/README.md new file mode 100644 index 0000000000000..c72aa69c0ce07 --- /dev/null +++ b/tests/coverage/README.md @@ -0,0 +1,16 @@ +The tests in this directory are shared by two different test modes, and can be +run in multiple different ways: + +- `./x.py test coverage-map` (compiles to LLVM IR and checks coverage mappings) +- `./x.py test coverage-run` (runs a test binary and checks its coverage report) +- `./x.py test coverage` (runs both `coverage-map` and `coverage-run`) + +## Maintenance note + +These tests can be sensitive to small changes in MIR spans or MIR control flow, +especially in HIR-to-MIR lowering or MIR optimizations. + +If you haven't touched the coverage code directly, and the tests still pass in +`coverage-run` mode, then it should usually be OK to just re-bless the mappings +as necessary with `./x.py test coverage-map --bless`, without worrying too much +about the exact changes. diff --git a/tests/coverage-map/status-quo/abort.cov-map b/tests/coverage/abort.cov-map similarity index 100% rename from tests/coverage-map/status-quo/abort.cov-map rename to tests/coverage/abort.cov-map diff --git a/tests/run-coverage/abort.coverage b/tests/coverage/abort.coverage similarity index 100% rename from tests/run-coverage/abort.coverage rename to tests/coverage/abort.coverage diff --git a/tests/coverage-map/status-quo/abort.rs b/tests/coverage/abort.rs similarity index 100% rename from tests/coverage-map/status-quo/abort.rs rename to tests/coverage/abort.rs diff --git a/tests/coverage-map/status-quo/assert.cov-map b/tests/coverage/assert.cov-map similarity index 100% rename from tests/coverage-map/status-quo/assert.cov-map rename to tests/coverage/assert.cov-map diff --git a/tests/run-coverage/assert.coverage b/tests/coverage/assert.coverage similarity index 100% rename from tests/run-coverage/assert.coverage rename to tests/coverage/assert.coverage diff --git a/tests/coverage-map/status-quo/assert.rs b/tests/coverage/assert.rs similarity index 100% rename from tests/coverage-map/status-quo/assert.rs rename to tests/coverage/assert.rs diff --git a/tests/coverage-map/status-quo/async.cov-map b/tests/coverage/async.cov-map similarity index 91% rename from tests/coverage-map/status-quo/async.cov-map rename to tests/coverage/async.cov-map index 598791537ad6e..e4354a1af8773 100644 --- a/tests/coverage-map/status-quo/async.cov-map +++ b/tests/coverage/async.cov-map @@ -74,28 +74,28 @@ Number of file 0 mappings: 6 = ((c0 + c1) - c1) Function name: async::executor::block_on::VTABLE::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 72, 11, 00, 33] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 72, 11, 00, 31] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 114, 17) to (start + 0, 51) +- Code(Counter(0)) at (prev + 114, 17) to (start + 0, 49) Function name: async::executor::block_on::VTABLE::{closure#1} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 73, 11, 00, 33] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 73, 11, 00, 31] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 115, 17) to (start + 0, 51) +- Code(Counter(0)) at (prev + 115, 17) to (start + 0, 49) Function name: async::executor::block_on::VTABLE::{closure#2} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 74, 11, 00, 33] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 74, 11, 00, 31] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 116, 17) to (start + 0, 51) +- Code(Counter(0)) at (prev + 116, 17) to (start + 0, 49) Function name: async::executor::block_on::VTABLE::{closure#3} Raw bytes (9): 0x[01, 01, 00, 01, 01, 75, 11, 00, 13] @@ -197,12 +197,12 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 38, 1) to (start + 0, 19) Function name: async::i::{closure#0} -Raw bytes (78): 0x[01, 01, 02, 19, 07, 1d, 21, 0e, 01, 26, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (78): 0x[01, 01, 02, 07, 21, 19, 1d, 0e, 01, 26, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 -- expression 0 operands: lhs = Counter(6), rhs = Expression(1, Add) -- expression 1 operands: lhs = Counter(7), rhs = Counter(8) +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(8) +- expression 1 operands: lhs = Counter(6), rhs = Counter(7) Number of file 0 mappings: 14 - Code(Counter(0)) at (prev + 38, 19) to (start + 4, 12) - Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10) @@ -218,15 +218,15 @@ Number of file 0 mappings: 14 - Code(Counter(7)) at (prev + 0, 36) to (start + 0, 38) - Code(Counter(8)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) - = (c6 + (c7 + c8)) + = ((c6 + c7) + c8) Function name: async::j -Raw bytes (53): 0x[01, 01, 02, 05, 07, 09, 0d, 09, 01, 31, 01, 13, 0c, 05, 14, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 02, 07, 0d, 05, 09, 09, 01, 31, 01, 13, 0c, 05, 14, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 -- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) -- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 49, 1) to (start + 19, 12) - Code(Counter(1)) at (prev + 20, 9) to (start + 0, 10) @@ -237,7 +237,7 @@ Number of file 0 mappings: 9 - Code(Counter(2)) at (prev + 0, 30) to (start + 0, 32) - Code(Counter(3)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) - = (c1 + (c2 + c3)) + = ((c1 + c2) + c3) Function name: async::j::c Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 33, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 0a, 0d, 00, 0e, 07, 02, 05, 00, 06] @@ -283,22 +283,22 @@ Number of file 0 mappings: 5 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::l -Raw bytes (37): 0x[01, 01, 04, 01, 07, 09, 05, 09, 0f, 05, 02, 05, 01, 53, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] +Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 53, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) -- expression 1 operands: lhs = Counter(2), rhs = Counter(1) -- expression 2 operands: lhs = Counter(2), rhs = Expression(3, Add) -- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(3, Add), rhs = Expression(0, Sub) +- expression 3 operands: lhs = Counter(2), rhs = Counter(1) Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 83, 1) to (start + 1, 12) - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16) - = (c0 - (c2 + c1)) + = (c0 - (c1 + c2)) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16) - Code(Counter(2)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(2, Add)) at (prev + 2, 1) to (start + 0, 2) - = (c2 + (c1 + (c0 - (c2 + c1)))) + = ((c2 + c1) + (c0 - (c1 + c2))) Function name: async::m Raw bytes (9): 0x[01, 01, 00, 01, 01, 5b, 01, 00, 19] diff --git a/tests/run-coverage/async.coverage b/tests/coverage/async.coverage similarity index 100% rename from tests/run-coverage/async.coverage rename to tests/coverage/async.coverage diff --git a/tests/coverage-map/status-quo/async.rs b/tests/coverage/async.rs similarity index 100% rename from tests/coverage-map/status-quo/async.rs rename to tests/coverage/async.rs diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage/async2.cov-map similarity index 93% rename from tests/coverage-map/status-quo/async2.cov-map rename to tests/coverage/async2.cov-map index cc7aed9aee3a4..23f26ee4e5f66 100644 --- a/tests/coverage-map/status-quo/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -78,28 +78,28 @@ Number of file 0 mappings: 6 = ((c0 + c1) - c1) Function name: async2::executor::block_on::VTABLE::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 2b, 11, 00, 33] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2b, 11, 00, 31] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 43, 17) to (start + 0, 51) +- Code(Counter(0)) at (prev + 43, 17) to (start + 0, 49) Function name: async2::executor::block_on::VTABLE::{closure#1} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 11, 00, 33] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 11, 00, 31] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 44, 17) to (start + 0, 51) +- Code(Counter(0)) at (prev + 44, 17) to (start + 0, 49) Function name: async2::executor::block_on::VTABLE::{closure#2} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 11, 00, 33] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 11, 00, 31] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 45, 17) to (start + 0, 51) +- Code(Counter(0)) at (prev + 45, 17) to (start + 0, 49) Function name: async2::executor::block_on::VTABLE::{closure#3} Raw bytes (9): 0x[01, 01, 00, 01, 01, 2e, 11, 00, 13] diff --git a/tests/run-coverage/async2.coverage b/tests/coverage/async2.coverage similarity index 100% rename from tests/run-coverage/async2.coverage rename to tests/coverage/async2.coverage diff --git a/tests/coverage-map/status-quo/async2.rs b/tests/coverage/async2.rs similarity index 100% rename from tests/coverage-map/status-quo/async2.rs rename to tests/coverage/async2.rs diff --git a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs b/tests/coverage/auxiliary/inline_always_with_dead_code.rs similarity index 100% rename from tests/run-coverage/auxiliary/inline_always_with_dead_code.rs rename to tests/coverage/auxiliary/inline_always_with_dead_code.rs diff --git a/tests/coverage/auxiliary/macro_name_span_helper.rs b/tests/coverage/auxiliary/macro_name_span_helper.rs new file mode 100644 index 0000000000000..6797c081d938b --- /dev/null +++ b/tests/coverage/auxiliary/macro_name_span_helper.rs @@ -0,0 +1,10 @@ +// edition: 2021 + +#[macro_export] +macro_rules! macro_that_defines_a_function { + (fn $name:ident () $body:tt) => { + fn $name () -> () $body + } +} + +// Non-executable comment. diff --git a/tests/run-coverage/auxiliary/unused_mod_helper.rs b/tests/coverage/auxiliary/unused_mod_helper.rs similarity index 100% rename from tests/run-coverage/auxiliary/unused_mod_helper.rs rename to tests/coverage/auxiliary/unused_mod_helper.rs diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs similarity index 100% rename from tests/run-coverage/auxiliary/used_crate.rs rename to tests/coverage/auxiliary/used_crate.rs diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/coverage/auxiliary/used_inline_crate.rs similarity index 100% rename from tests/run-coverage/auxiliary/used_inline_crate.rs rename to tests/coverage/auxiliary/used_inline_crate.rs diff --git a/tests/coverage-map/status-quo/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map similarity index 100% rename from tests/coverage-map/status-quo/bad_counter_ids.cov-map rename to tests/coverage/bad_counter_ids.cov-map diff --git a/tests/run-coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage similarity index 100% rename from tests/run-coverage/bad_counter_ids.coverage rename to tests/coverage/bad_counter_ids.coverage diff --git a/tests/coverage-map/status-quo/bad_counter_ids.rs b/tests/coverage/bad_counter_ids.rs similarity index 100% rename from tests/coverage-map/status-quo/bad_counter_ids.rs rename to tests/coverage/bad_counter_ids.rs diff --git a/tests/coverage-map/status-quo/closure.cov-map b/tests/coverage/closure.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure.cov-map rename to tests/coverage/closure.cov-map diff --git a/tests/run-coverage/closure.coverage b/tests/coverage/closure.coverage similarity index 100% rename from tests/run-coverage/closure.coverage rename to tests/coverage/closure.coverage diff --git a/tests/coverage-map/status-quo/closure.rs b/tests/coverage/closure.rs similarity index 100% rename from tests/coverage-map/status-quo/closure.rs rename to tests/coverage/closure.rs diff --git a/tests/coverage-map/status-quo/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_bug.cov-map rename to tests/coverage/closure_bug.cov-map diff --git a/tests/run-coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage similarity index 100% rename from tests/run-coverage/closure_bug.coverage rename to tests/coverage/closure_bug.coverage diff --git a/tests/coverage-map/status-quo/closure_bug.rs b/tests/coverage/closure_bug.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_bug.rs rename to tests/coverage/closure_bug.rs diff --git a/tests/coverage-map/status-quo/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_macro.cov-map rename to tests/coverage/closure_macro.cov-map diff --git a/tests/run-coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage similarity index 100% rename from tests/run-coverage/closure_macro.coverage rename to tests/coverage/closure_macro.coverage diff --git a/tests/coverage-map/status-quo/closure_macro.rs b/tests/coverage/closure_macro.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_macro.rs rename to tests/coverage/closure_macro.rs diff --git a/tests/coverage-map/status-quo/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_macro_async.cov-map rename to tests/coverage/closure_macro_async.cov-map diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage similarity index 100% rename from tests/run-coverage/closure_macro_async.coverage rename to tests/coverage/closure_macro_async.coverage diff --git a/tests/coverage-map/status-quo/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_macro_async.rs rename to tests/coverage/closure_macro_async.rs diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage/conditions.cov-map similarity index 98% rename from tests/coverage-map/status-quo/conditions.cov-map rename to tests/coverage/conditions.cov-map index 7600d2d96bdfe..cfee55ed31a4a 100644 --- a/tests/coverage-map/status-quo/conditions.cov-map +++ b/tests/coverage/conditions.cov-map @@ -1,5 +1,5 @@ Function name: conditions::main -Raw bytes (784): 0x[01, 01, 8e, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, b7, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, b2, 04, 0d, b7, 04, 09, 05, 00, 45, 00, 83, 01, 49, 45, 00, 7e, 31, 83, 01, 49, 45, 00, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, 76, 51, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, a7, 01, 55, 4d, 51, a3, 01, 59, a7, 01, 55, 4d, 51, 49, 9f, 01, a3, 01, 59, a7, 01, 55, 4d, 51, 61, 00, e3, 01, 65, 61, 00, de, 01, 2d, e3, 01, 65, 61, 00, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, d6, 01, 6d, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, 8b, 02, 71, 69, 6d, 87, 02, 75, 8b, 02, 71, 69, 6d, ff, 01, 00, 65, 83, 02, 87, 02, 75, 8b, 02, 71, 69, 6d, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 79, 00, d7, 02, 7d, 79, 00, d2, 02, 29, d7, 02, 7d, 79, 00, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, ca, 02, 85, 01, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, f3, 03, 89, 01, 81, 01, 85, 01, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, da, 03, 19, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 9b, 04, 1d, 15, 19, 97, 04, 21, 9b, 04, 1d, 15, 19, 8f, 04, 9f, 04, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, a3, 04, ae, 04, a7, 04, ab, 04, 25, 29, 2d, 31, b2, 04, 0d, b7, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, b7, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b2, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, ae, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 7e, 02, 0f, 00, 1c, 7a, 01, 0c, 00, 19, 76, 00, 1d, 00, 2a, 72, 00, 2e, 00, 3c, a3, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 9f, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9b, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e3, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, de, 01, 03, 11, 00, 1e, da, 01, 01, 10, 00, 1d, d6, 01, 00, 21, 00, 2e, d2, 01, 00, 32, 00, 40, 87, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 83, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, fb, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, e7, 03, 02, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d2, 02, 02, 0f, 00, 1c, ce, 02, 01, 0c, 00, 19, ca, 02, 00, 1d, 00, 2a, c6, 02, 00, 2e, 00, 3c, ef, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, eb, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 8f, 04, 05, 09, 00, 0a, e7, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, e2, 03, 02, 0f, 00, 1c, de, 03, 01, 0c, 00, 19, da, 03, 00, 1d, 00, 2a, d6, 03, 00, 2e, 00, 3c, 97, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 93, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 8b, 04, 02, 01, 00, 02] +Raw bytes (784): 0x[01, 01, 8e, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, b7, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, b2, 04, 0d, b7, 04, 09, 05, 00, 45, 00, 83, 01, 49, 45, 00, 7e, 31, 83, 01, 49, 45, 00, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, 76, 51, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, a7, 01, 55, 4d, 51, a3, 01, 59, a7, 01, 55, 4d, 51, 49, 9f, 01, a3, 01, 59, a7, 01, 55, 4d, 51, 61, 00, e3, 01, 65, 61, 00, de, 01, 2d, e3, 01, 65, 61, 00, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, d6, 01, 6d, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, 8b, 02, 71, 69, 6d, 87, 02, 75, 8b, 02, 71, 69, 6d, ff, 01, 00, 65, 83, 02, 87, 02, 75, 8b, 02, 71, 69, 6d, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 79, 00, d7, 02, 7d, 79, 00, d2, 02, 29, d7, 02, 7d, 79, 00, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, ca, 02, 85, 01, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, f3, 03, 89, 01, 81, 01, 85, 01, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, da, 03, 19, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 9b, 04, 1d, 15, 19, 97, 04, 21, 9b, 04, 1d, 15, 19, 8f, 04, 9f, 04, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, a3, 04, ae, 04, a7, 04, 31, ab, 04, 2d, 25, 29, b2, 04, 0d, b7, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, b7, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b2, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, ae, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 7e, 02, 0f, 00, 1c, 7a, 01, 0c, 00, 19, 76, 00, 1d, 00, 2a, 72, 00, 2e, 00, 3c, a3, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 9f, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9b, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e3, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, de, 01, 03, 11, 00, 1e, da, 01, 01, 10, 00, 1d, d6, 01, 00, 21, 00, 2e, d2, 01, 00, 32, 00, 40, 87, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 83, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, fb, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, e7, 03, 02, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d2, 02, 02, 0f, 00, 1c, ce, 02, 01, 0c, 00, 19, ca, 02, 00, 1d, 00, 2a, c6, 02, 00, 2e, 00, 3c, ef, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, eb, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 8f, 04, 05, 09, 00, 0a, e7, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, e2, 03, 02, 0f, 00, 1c, de, 03, 01, 0c, 00, 19, da, 03, 00, 1d, 00, 2a, d6, 03, 00, 2e, 00, 3c, 97, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 93, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 8b, 04, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 142 @@ -139,9 +139,9 @@ Number of expressions: 142 - expression 133 operands: lhs = Expression(134, Add), rhs = Counter(7) - expression 134 operands: lhs = Counter(5), rhs = Counter(6) - expression 135 operands: lhs = Expression(136, Add), rhs = Expression(139, Sub) -- expression 136 operands: lhs = Expression(137, Add), rhs = Expression(138, Add) -- expression 137 operands: lhs = Counter(9), rhs = Counter(10) -- expression 138 operands: lhs = Counter(11), rhs = Counter(12) +- expression 136 operands: lhs = Expression(137, Add), rhs = Counter(12) +- expression 137 operands: lhs = Expression(138, Add), rhs = Counter(11) +- expression 138 operands: lhs = Counter(9), rhs = Counter(10) - expression 139 operands: lhs = Expression(140, Sub), rhs = Counter(3) - expression 140 operands: lhs = Expression(141, Add), rhs = Counter(2) - expression 141 operands: lhs = Counter(1), rhs = Zero @@ -255,5 +255,5 @@ Number of file 0 mappings: 68 = (((c5 + c6) + c7) + c8) - Code(Counter(9)) at (prev + 2, 9) to (start + 0, 15) - Code(Expression(130, Add)) at (prev + 2, 1) to (start + 0, 2) - = ((c4 + (((c5 + c6) + c7) + c8)) + (((c9 + c10) + (c11 + c12)) + (((c1 + Zero) - c2) - c3))) + = ((c4 + (((c5 + c6) + c7) + c8)) + ((((c9 + c10) + c11) + c12) + (((c1 + Zero) - c2) - c3))) diff --git a/tests/run-coverage/conditions.coverage b/tests/coverage/conditions.coverage similarity index 100% rename from tests/run-coverage/conditions.coverage rename to tests/coverage/conditions.coverage diff --git a/tests/coverage-map/status-quo/conditions.rs b/tests/coverage/conditions.rs similarity index 100% rename from tests/coverage-map/status-quo/conditions.rs rename to tests/coverage/conditions.rs diff --git a/tests/coverage-map/status-quo/continue.cov-map b/tests/coverage/continue.cov-map similarity index 73% rename from tests/coverage-map/status-quo/continue.cov-map rename to tests/coverage/continue.cov-map index 82f3d7c609529..810694d7f6623 100644 --- a/tests/coverage-map/status-quo/continue.cov-map +++ b/tests/coverage/continue.cov-map @@ -1,26 +1,26 @@ Function name: continue::main -Raw bytes (210): 0x[01, 01, 1c, 01, 07, 05, 09, 03, 0d, 0d, 1f, 11, 15, 1b, 19, 0d, 1f, 11, 15, 19, 33, 1d, 21, 2f, 25, 19, 33, 1d, 21, 25, 47, 29, 2d, 43, 31, 25, 47, 29, 2d, 31, 5f, 35, 39, 57, 3d, 31, 5f, 35, 39, 35, 39, 3d, 41, 6b, 45, 3d, 41, 49, 45, 1e, 01, 03, 01, 03, 12, 03, 04, 0e, 00, 13, 0a, 01, 0f, 00, 16, 05, 02, 11, 00, 19, 09, 02, 12, 04, 0e, 1b, 06, 0e, 00, 13, 16, 01, 0f, 00, 16, 15, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 15, 03, 09, 00, 0e, 2f, 02, 0e, 00, 13, 2a, 01, 0f, 00, 16, 1d, 01, 15, 02, 0e, 21, 04, 11, 00, 19, 1d, 03, 09, 00, 0e, 43, 02, 0e, 00, 13, 3e, 01, 0c, 00, 13, 29, 01, 0d, 00, 15, 2d, 01, 0a, 01, 0e, 57, 03, 0e, 00, 13, 52, 01, 0f, 00, 16, 39, 01, 16, 02, 0e, 35, 03, 12, 02, 0e, 5f, 04, 09, 00, 0e, 6b, 02, 0e, 00, 13, 66, 01, 0f, 00, 16, 41, 01, 16, 02, 0e, 49, 04, 11, 00, 16, 41, 03, 09, 00, 0e, 6f, 02, 0d, 01, 02] +Raw bytes (210): 0x[01, 01, 1c, 07, 09, 01, 05, 03, 0d, 1f, 15, 0d, 11, 1b, 19, 1f, 15, 0d, 11, 33, 21, 19, 1d, 2f, 25, 33, 21, 19, 1d, 47, 2d, 25, 29, 43, 31, 47, 2d, 25, 29, 31, 5f, 35, 39, 57, 3d, 31, 5f, 35, 39, 35, 39, 3d, 41, 6b, 45, 3d, 41, 49, 45, 1e, 01, 03, 01, 03, 12, 03, 04, 0e, 00, 13, 0a, 01, 0f, 00, 16, 05, 02, 11, 00, 19, 09, 02, 12, 04, 0e, 1b, 06, 0e, 00, 13, 16, 01, 0f, 00, 16, 15, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 15, 03, 09, 00, 0e, 2f, 02, 0e, 00, 13, 2a, 01, 0f, 00, 16, 1d, 01, 15, 02, 0e, 21, 04, 11, 00, 19, 1d, 03, 09, 00, 0e, 43, 02, 0e, 00, 13, 3e, 01, 0c, 00, 13, 29, 01, 0d, 00, 15, 2d, 01, 0a, 01, 0e, 57, 03, 0e, 00, 13, 52, 01, 0f, 00, 16, 39, 01, 16, 02, 0e, 35, 03, 12, 02, 0e, 5f, 04, 09, 00, 0e, 6b, 02, 0e, 00, 13, 66, 01, 0f, 00, 16, 41, 01, 16, 02, 0e, 49, 04, 11, 00, 16, 41, 03, 09, 00, 0e, 6f, 02, 0d, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 28 -- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) -- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(2) +- expression 1 operands: lhs = Counter(0), rhs = Counter(1) - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) -- expression 3 operands: lhs = Counter(3), rhs = Expression(7, Add) -- expression 4 operands: lhs = Counter(4), rhs = Counter(5) +- expression 3 operands: lhs = Expression(7, Add), rhs = Counter(5) +- expression 4 operands: lhs = Counter(3), rhs = Counter(4) - expression 5 operands: lhs = Expression(6, Add), rhs = Counter(6) -- expression 6 operands: lhs = Counter(3), rhs = Expression(7, Add) -- expression 7 operands: lhs = Counter(4), rhs = Counter(5) -- expression 8 operands: lhs = Counter(6), rhs = Expression(12, Add) -- expression 9 operands: lhs = Counter(7), rhs = Counter(8) +- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(5) +- expression 7 operands: lhs = Counter(3), rhs = Counter(4) +- expression 8 operands: lhs = Expression(12, Add), rhs = Counter(8) +- expression 9 operands: lhs = Counter(6), rhs = Counter(7) - expression 10 operands: lhs = Expression(11, Add), rhs = Counter(9) -- expression 11 operands: lhs = Counter(6), rhs = Expression(12, Add) -- expression 12 operands: lhs = Counter(7), rhs = Counter(8) -- expression 13 operands: lhs = Counter(9), rhs = Expression(17, Add) -- expression 14 operands: lhs = Counter(10), rhs = Counter(11) +- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(8) +- expression 12 operands: lhs = Counter(6), rhs = Counter(7) +- expression 13 operands: lhs = Expression(17, Add), rhs = Counter(11) +- expression 14 operands: lhs = Counter(9), rhs = Counter(10) - expression 15 operands: lhs = Expression(16, Add), rhs = Counter(12) -- expression 16 operands: lhs = Counter(9), rhs = Expression(17, Add) -- expression 17 operands: lhs = Counter(10), rhs = Counter(11) +- expression 16 operands: lhs = Expression(17, Add), rhs = Counter(11) +- expression 17 operands: lhs = Counter(9), rhs = Counter(10) - expression 18 operands: lhs = Counter(12), rhs = Expression(23, Add) - expression 19 operands: lhs = Counter(13), rhs = Counter(14) - expression 20 operands: lhs = Expression(21, Add), rhs = Counter(15) @@ -34,29 +34,29 @@ Number of expressions: 28 Number of file 0 mappings: 30 - Code(Counter(0)) at (prev + 3, 1) to (start + 3, 18) - Code(Expression(0, Add)) at (prev + 4, 14) to (start + 0, 19) - = (c0 + (c1 + c2)) + = ((c0 + c1) + c2) - Code(Expression(2, Sub)) at (prev + 1, 15) to (start + 0, 22) - = ((c0 + (c1 + c2)) - c3) + = (((c0 + c1) + c2) - c3) - Code(Counter(1)) at (prev + 2, 17) to (start + 0, 25) - Code(Counter(2)) at (prev + 2, 18) to (start + 4, 14) - Code(Expression(6, Add)) at (prev + 6, 14) to (start + 0, 19) - = (c3 + (c4 + c5)) + = ((c3 + c4) + c5) - Code(Expression(5, Sub)) at (prev + 1, 15) to (start + 0, 22) - = ((c3 + (c4 + c5)) - c6) + = (((c3 + c4) + c5) - c6) - Code(Counter(5)) at (prev + 1, 22) to (start + 2, 14) - Code(Counter(4)) at (prev + 4, 17) to (start + 0, 25) - Code(Counter(5)) at (prev + 3, 9) to (start + 0, 14) - Code(Expression(11, Add)) at (prev + 2, 14) to (start + 0, 19) - = (c6 + (c7 + c8)) + = ((c6 + c7) + c8) - Code(Expression(10, Sub)) at (prev + 1, 15) to (start + 0, 22) - = ((c6 + (c7 + c8)) - c9) + = (((c6 + c7) + c8) - c9) - Code(Counter(7)) at (prev + 1, 21) to (start + 2, 14) - Code(Counter(8)) at (prev + 4, 17) to (start + 0, 25) - Code(Counter(7)) at (prev + 3, 9) to (start + 0, 14) - Code(Expression(16, Add)) at (prev + 2, 14) to (start + 0, 19) - = (c9 + (c10 + c11)) + = ((c9 + c10) + c11) - Code(Expression(15, Sub)) at (prev + 1, 12) to (start + 0, 19) - = ((c9 + (c10 + c11)) - c12) + = (((c9 + c10) + c11) - c12) - Code(Counter(10)) at (prev + 1, 13) to (start + 0, 21) - Code(Counter(11)) at (prev + 1, 10) to (start + 1, 14) - Code(Expression(21, Add)) at (prev + 3, 14) to (start + 0, 19) diff --git a/tests/run-coverage/continue.coverage b/tests/coverage/continue.coverage similarity index 100% rename from tests/run-coverage/continue.coverage rename to tests/coverage/continue.coverage diff --git a/tests/coverage-map/status-quo/continue.rs b/tests/coverage/continue.rs similarity index 100% rename from tests/coverage-map/status-quo/continue.rs rename to tests/coverage/continue.rs diff --git a/tests/coverage-map/status-quo/coroutine.cov-map b/tests/coverage/coroutine.cov-map similarity index 91% rename from tests/coverage-map/status-quo/coroutine.cov-map rename to tests/coverage/coroutine.cov-map index 2f4936d9ab88c..8dd03acc2f4dd 100644 --- a/tests/coverage-map/status-quo/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -14,12 +14,12 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: coroutine::main -Raw bytes (65): 0x[01, 01, 08, 05, 07, 09, 0d, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] +Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 01, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 -- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) -- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(4), rhs = Counter(5) - expression 3 operands: lhs = Expression(7, Sub), rhs = Counter(6) - expression 4 operands: lhs = Counter(4), rhs = Counter(5) @@ -31,7 +31,7 @@ Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) - Code(Counter(4)) at (prev + 1, 43) to (start + 0, 45) - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 53) - = (c1 + (c2 + c3)) + = ((c1 + c2) + c3) - Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46) - Code(Expression(7, Sub)) at (prev + 1, 34) to (start + 0, 39) = (c4 - c5) diff --git a/tests/run-coverage/coroutine.coverage b/tests/coverage/coroutine.coverage similarity index 100% rename from tests/run-coverage/coroutine.coverage rename to tests/coverage/coroutine.coverage diff --git a/tests/coverage-map/status-quo/coroutine.rs b/tests/coverage/coroutine.rs similarity index 100% rename from tests/coverage-map/status-quo/coroutine.rs rename to tests/coverage/coroutine.rs diff --git a/tests/coverage-map/status-quo/dead_code.cov-map b/tests/coverage/dead_code.cov-map similarity index 100% rename from tests/coverage-map/status-quo/dead_code.cov-map rename to tests/coverage/dead_code.cov-map diff --git a/tests/run-coverage/dead_code.coverage b/tests/coverage/dead_code.coverage similarity index 100% rename from tests/run-coverage/dead_code.coverage rename to tests/coverage/dead_code.coverage diff --git a/tests/coverage-map/status-quo/dead_code.rs b/tests/coverage/dead_code.rs similarity index 100% rename from tests/coverage-map/status-quo/dead_code.rs rename to tests/coverage/dead_code.rs diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage/drop_trait.cov-map similarity index 100% rename from tests/coverage-map/status-quo/drop_trait.cov-map rename to tests/coverage/drop_trait.cov-map diff --git a/tests/run-coverage/drop_trait.coverage b/tests/coverage/drop_trait.coverage similarity index 100% rename from tests/run-coverage/drop_trait.coverage rename to tests/coverage/drop_trait.coverage diff --git a/tests/coverage-map/status-quo/drop_trait.rs b/tests/coverage/drop_trait.rs similarity index 100% rename from tests/coverage-map/status-quo/drop_trait.rs rename to tests/coverage/drop_trait.rs diff --git a/tests/coverage-map/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map similarity index 100% rename from tests/coverage-map/fn_sig_into_try.cov-map rename to tests/coverage/fn_sig_into_try.cov-map diff --git a/tests/run-coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage similarity index 100% rename from tests/run-coverage/fn_sig_into_try.coverage rename to tests/coverage/fn_sig_into_try.coverage diff --git a/tests/coverage-map/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs similarity index 100% rename from tests/coverage-map/fn_sig_into_try.rs rename to tests/coverage/fn_sig_into_try.rs diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage/generics.cov-map similarity index 100% rename from tests/coverage-map/status-quo/generics.cov-map rename to tests/coverage/generics.cov-map diff --git a/tests/run-coverage/generics.coverage b/tests/coverage/generics.coverage similarity index 100% rename from tests/run-coverage/generics.coverage rename to tests/coverage/generics.coverage diff --git a/tests/coverage-map/status-quo/generics.rs b/tests/coverage/generics.rs similarity index 100% rename from tests/coverage-map/status-quo/generics.rs rename to tests/coverage/generics.rs diff --git a/tests/coverage-map/status-quo/if.cov-map b/tests/coverage/if.cov-map similarity index 100% rename from tests/coverage-map/status-quo/if.cov-map rename to tests/coverage/if.cov-map diff --git a/tests/run-coverage/if.coverage b/tests/coverage/if.coverage similarity index 100% rename from tests/run-coverage/if.coverage rename to tests/coverage/if.coverage diff --git a/tests/coverage-map/status-quo/if.rs b/tests/coverage/if.rs similarity index 100% rename from tests/coverage-map/status-quo/if.rs rename to tests/coverage/if.rs diff --git a/tests/coverage-map/status-quo/if_else.cov-map b/tests/coverage/if_else.cov-map similarity index 100% rename from tests/coverage-map/status-quo/if_else.cov-map rename to tests/coverage/if_else.cov-map diff --git a/tests/run-coverage/if_else.coverage b/tests/coverage/if_else.coverage similarity index 100% rename from tests/run-coverage/if_else.coverage rename to tests/coverage/if_else.coverage diff --git a/tests/coverage-map/status-quo/if_else.rs b/tests/coverage/if_else.rs similarity index 100% rename from tests/coverage-map/status-quo/if_else.rs rename to tests/coverage/if_else.rs diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map similarity index 100% rename from tests/coverage-map/status-quo/inline-dead.cov-map rename to tests/coverage/inline-dead.cov-map diff --git a/tests/run-coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage similarity index 100% rename from tests/run-coverage/inline-dead.coverage rename to tests/coverage/inline-dead.coverage diff --git a/tests/coverage-map/status-quo/inline-dead.rs b/tests/coverage/inline-dead.rs similarity index 100% rename from tests/coverage-map/status-quo/inline-dead.rs rename to tests/coverage/inline-dead.rs diff --git a/tests/coverage-map/status-quo/inline.cov-map b/tests/coverage/inline.cov-map similarity index 96% rename from tests/coverage-map/status-quo/inline.cov-map rename to tests/coverage/inline.cov-map index 72b10fd0cc278..001c333ae6d90 100644 --- a/tests/coverage-map/status-quo/inline.cov-map +++ b/tests/coverage/inline.cov-map @@ -15,12 +15,12 @@ Number of file 0 mappings: 5 = ((c0 + c1) - c1) Function name: inline::error -Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 20) Function name: inline::length:: Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] diff --git a/tests/run-coverage/inline.coverage b/tests/coverage/inline.coverage similarity index 99% rename from tests/run-coverage/inline.coverage rename to tests/coverage/inline.coverage index 6efd9a0830b4f..68a2e408306d5 100644 --- a/tests/run-coverage/inline.coverage +++ b/tests/coverage/inline.coverage @@ -50,5 +50,5 @@ LL| |#[inline(always)] LL| 0|fn error() { LL| 0| panic!("error"); - LL| 0|} + LL| |} diff --git a/tests/coverage-map/status-quo/inline.rs b/tests/coverage/inline.rs similarity index 100% rename from tests/coverage-map/status-quo/inline.rs rename to tests/coverage/inline.rs diff --git a/tests/coverage-map/status-quo/inner_items.cov-map b/tests/coverage/inner_items.cov-map similarity index 100% rename from tests/coverage-map/status-quo/inner_items.cov-map rename to tests/coverage/inner_items.cov-map diff --git a/tests/run-coverage/inner_items.coverage b/tests/coverage/inner_items.coverage similarity index 100% rename from tests/run-coverage/inner_items.coverage rename to tests/coverage/inner_items.coverage diff --git a/tests/coverage-map/status-quo/inner_items.rs b/tests/coverage/inner_items.rs similarity index 100% rename from tests/coverage-map/status-quo/inner_items.rs rename to tests/coverage/inner_items.rs diff --git a/tests/coverage-map/status-quo/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-83601.cov-map rename to tests/coverage/issue-83601.cov-map diff --git a/tests/run-coverage/issue-83601.coverage b/tests/coverage/issue-83601.coverage similarity index 100% rename from tests/run-coverage/issue-83601.coverage rename to tests/coverage/issue-83601.coverage diff --git a/tests/coverage-map/status-quo/issue-83601.rs b/tests/coverage/issue-83601.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-83601.rs rename to tests/coverage/issue-83601.rs diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-84561.cov-map rename to tests/coverage/issue-84561.cov-map diff --git a/tests/run-coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage similarity index 100% rename from tests/run-coverage/issue-84561.coverage rename to tests/coverage/issue-84561.coverage diff --git a/tests/coverage-map/status-quo/issue-84561.rs b/tests/coverage/issue-84561.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-84561.rs rename to tests/coverage/issue-84561.rs diff --git a/tests/coverage/issue-85461.cov-map b/tests/coverage/issue-85461.cov-map new file mode 100644 index 0000000000000..d1c449b9a355e --- /dev/null +++ b/tests/coverage/issue-85461.cov-map @@ -0,0 +1,8 @@ +Function name: issue_85461::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) + diff --git a/tests/run-coverage/issue-85461.coverage b/tests/coverage/issue-85461.coverage similarity index 100% rename from tests/run-coverage/issue-85461.coverage rename to tests/coverage/issue-85461.coverage diff --git a/tests/run-coverage/issue-85461.rs b/tests/coverage/issue-85461.rs similarity index 100% rename from tests/run-coverage/issue-85461.rs rename to tests/coverage/issue-85461.rs diff --git a/tests/coverage-map/status-quo/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-93054.cov-map rename to tests/coverage/issue-93054.cov-map diff --git a/tests/run-coverage/issue-93054.coverage b/tests/coverage/issue-93054.coverage similarity index 100% rename from tests/run-coverage/issue-93054.coverage rename to tests/coverage/issue-93054.coverage diff --git a/tests/coverage-map/status-quo/issue-93054.rs b/tests/coverage/issue-93054.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-93054.rs rename to tests/coverage/issue-93054.rs diff --git a/tests/coverage-map/status-quo/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map similarity index 100% rename from tests/coverage-map/status-quo/lazy_boolean.cov-map rename to tests/coverage/lazy_boolean.cov-map diff --git a/tests/run-coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage similarity index 100% rename from tests/run-coverage/lazy_boolean.coverage rename to tests/coverage/lazy_boolean.coverage diff --git a/tests/coverage-map/status-quo/lazy_boolean.rs b/tests/coverage/lazy_boolean.rs similarity index 100% rename from tests/coverage-map/status-quo/lazy_boolean.rs rename to tests/coverage/lazy_boolean.rs diff --git a/tests/coverage-map/long_and_wide.cov-map b/tests/coverage/long_and_wide.cov-map similarity index 100% rename from tests/coverage-map/long_and_wide.cov-map rename to tests/coverage/long_and_wide.cov-map diff --git a/tests/coverage/long_and_wide.coverage b/tests/coverage/long_and_wide.coverage new file mode 100644 index 0000000000000..d7d29ca40cddd --- /dev/null +++ b/tests/coverage/long_and_wide.coverage @@ -0,0 +1,151 @@ + LL| |// compile-flags: --edition=2021 + LL| |// ignore-tidy-linelength + LL| | + LL| |// This file deliberately contains line and column numbers larger than 127, + LL| |// to verify that `coverage-dump`'s ULEB128 parser can handle them. + LL| | + LL| 1|fn main() { + LL| 1| wide_function(); + LL| 1| long_function(); + LL| 1| far_function(); + LL| 1|} + LL| | + LL| |#[rustfmt::skip] + LL| 1|fn wide_function() { /* */ (); } + LL| | + LL| 1|fn long_function() { + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1|} + LL| | + LL| 1|fn far_function() {} + diff --git a/tests/coverage-map/long_and_wide.rs b/tests/coverage/long_and_wide.rs similarity index 100% rename from tests/coverage-map/long_and_wide.rs rename to tests/coverage/long_and_wide.rs diff --git a/tests/coverage-map/status-quo/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map similarity index 100% rename from tests/coverage-map/status-quo/loop_break_value.cov-map rename to tests/coverage/loop_break_value.cov-map diff --git a/tests/run-coverage/loop_break_value.coverage b/tests/coverage/loop_break_value.coverage similarity index 100% rename from tests/run-coverage/loop_break_value.coverage rename to tests/coverage/loop_break_value.coverage diff --git a/tests/coverage-map/status-quo/loop_break_value.rs b/tests/coverage/loop_break_value.rs similarity index 100% rename from tests/coverage-map/status-quo/loop_break_value.rs rename to tests/coverage/loop_break_value.rs diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map similarity index 68% rename from tests/coverage-map/status-quo/loops_branches.cov-map rename to tests/coverage/loops_branches.cov-map index 813583a9de751..8dc35321133b8 100644 --- a/tests/coverage-map/status-quo/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map @@ -1,5 +1,5 @@ Function name: ::fmt -Raw bytes (249): 0x[01, 01, 31, 05, 00, 00, 02, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, bf, 01, c3, 01, 0d, 00, 11, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, b2, 01, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, 00, ae, 01, b2, 01, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, ab, 01, 11, 00, ae, 01, b2, 01, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, 25, a3, 01, a6, 01, 19, ab, 01, 11, 00, ae, 01, b2, 01, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, b6, 01, 03, 0d, 00, 0e, bb, 01, 00, 12, 00, 17, b6, 01, 01, 10, 00, 14, b2, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, ae, 01, 01, 12, 00, 13, ab, 01, 01, 11, 00, 22, a6, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 9f, 01, 01, 05, 00, 06] +Raw bytes (249): 0x[01, 01, 31, 05, 00, 00, 02, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, bf, 01, c3, 01, 0d, 00, 11, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, b2, 01, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, 00, ae, 01, b2, 01, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, ab, 01, 11, 00, ae, 01, b2, 01, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, a3, 01, 19, 25, a6, 01, ab, 01, 11, 00, ae, 01, b2, 01, 00, b6, 01, 00, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 00, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, b6, 01, 03, 0d, 00, 0e, bb, 01, 00, 12, 00, 17, b6, 01, 01, 10, 00, 14, b2, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, ae, 01, 01, 12, 00, 13, ab, 01, 01, 11, 00, 22, a6, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 9f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 49 @@ -42,8 +42,8 @@ Number of expressions: 49 - expression 36 operands: lhs = Expression(47, Add), rhs = Expression(48, Add) - expression 37 operands: lhs = Counter(3), rhs = Zero - expression 38 operands: lhs = Counter(4), rhs = Zero -- expression 39 operands: lhs = Counter(9), rhs = Expression(40, Add) -- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(6) +- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(6) +- expression 40 operands: lhs = Counter(9), rhs = Expression(41, Sub) - expression 41 operands: lhs = Expression(42, Add), rhs = Counter(4) - expression 42 operands: lhs = Zero, rhs = Expression(43, Sub) - expression 43 operands: lhs = Expression(44, Sub), rhs = Zero @@ -82,10 +82,10 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 20) to (start + 1, 14) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) - Code(Expression(39, Add)) at (prev + 1, 5) to (start + 0, 6) - = (c9 + (((Zero + (((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - Zero)) - c4) + c6)) + = ((c9 + ((Zero + (((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - Zero)) - c4)) + c6) Function name: ::fmt -Raw bytes (253): 0x[01, 01, 33, 01, 00, 02, 00, 00, 0e, 02, 00, bf, 01, 19, c3, 01, c7, 01, 00, 0d, 00, 15, c3, 01, c7, 01, 00, 0d, 00, 15, bf, 01, 19, c3, 01, c7, 01, 00, 0d, 00, 15, ba, 01, 00, bf, 01, 19, c3, 01, c7, 01, 00, 0d, 00, 15, b6, 01, 00, ba, 01, 00, bf, 01, 19, c3, 01, c7, 01, 00, 0d, 00, 15, 00, b2, 01, b6, 01, 00, ba, 01, 00, bf, 01, 19, c3, 01, c7, 01, 00, 0d, 00, 15, af, 01, 15, 00, b2, 01, b6, 01, 00, ba, 01, 00, bf, 01, 19, c3, 01, c7, 01, 00, 0d, 00, 15, aa, 01, cb, 01, af, 01, 15, 00, b2, 01, b6, 01, 00, ba, 01, 00, bf, 01, 19, c3, 01, c7, 01, 00, 0d, 00, 15, 19, 25, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 0e, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, ba, 01, 02, 0d, 00, 0e, bf, 01, 00, 12, 00, 17, ba, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, b6, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b2, 01, 01, 12, 00, 13, af, 01, 01, 11, 00, 22, aa, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, a7, 01, 01, 05, 00, 06] +Raw bytes (253): 0x[01, 01, 33, 01, 00, 02, 00, 00, 0e, 02, 00, c3, 01, 19, c7, 01, cb, 01, 00, 0d, 00, 15, c7, 01, cb, 01, 00, 0d, 00, 15, c3, 01, 19, c7, 01, cb, 01, 00, 0d, 00, 15, be, 01, 00, c3, 01, 19, c7, 01, cb, 01, 00, 0d, 00, 15, ba, 01, 00, be, 01, 00, c3, 01, 19, c7, 01, cb, 01, 00, 0d, 00, 15, 00, b6, 01, ba, 01, 00, be, 01, 00, c3, 01, 19, c7, 01, cb, 01, 00, 0d, 00, 15, b3, 01, 15, 00, b6, 01, ba, 01, 00, be, 01, 00, c3, 01, 19, c7, 01, cb, 01, 00, 0d, 00, 15, ab, 01, 25, ae, 01, 19, b3, 01, 15, 00, b6, 01, ba, 01, 00, be, 01, 00, c3, 01, 19, c7, 01, cb, 01, 00, 0d, 00, 15, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 0e, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, be, 01, 02, 0d, 00, 0e, c3, 01, 00, 12, 00, 17, be, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, ba, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b6, 01, 01, 12, 00, 13, b3, 01, 01, 11, 00, 22, ae, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, a7, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 51 @@ -93,53 +93,53 @@ Number of expressions: 51 - expression 1 operands: lhs = Expression(0, Sub), rhs = Zero - expression 2 operands: lhs = Zero, rhs = Expression(3, Sub) - expression 3 operands: lhs = Expression(0, Sub), rhs = Zero -- expression 4 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 5 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 4 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 5 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) - expression 6 operands: lhs = Zero, rhs = Counter(3) - expression 7 operands: lhs = Zero, rhs = Counter(5) -- expression 8 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 8 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) - expression 9 operands: lhs = Zero, rhs = Counter(3) - expression 10 operands: lhs = Zero, rhs = Counter(5) -- expression 11 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 12 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 11 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 12 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) - expression 13 operands: lhs = Zero, rhs = Counter(3) - expression 14 operands: lhs = Zero, rhs = Counter(5) -- expression 15 operands: lhs = Expression(46, Sub), rhs = Zero -- expression 16 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 17 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 15 operands: lhs = Expression(47, Sub), rhs = Zero +- expression 16 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 17 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) - expression 18 operands: lhs = Zero, rhs = Counter(3) - expression 19 operands: lhs = Zero, rhs = Counter(5) -- expression 20 operands: lhs = Expression(45, Sub), rhs = Zero -- expression 21 operands: lhs = Expression(46, Sub), rhs = Zero -- expression 22 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 23 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 20 operands: lhs = Expression(46, Sub), rhs = Zero +- expression 21 operands: lhs = Expression(47, Sub), rhs = Zero +- expression 22 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 23 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) - expression 24 operands: lhs = Zero, rhs = Counter(3) - expression 25 operands: lhs = Zero, rhs = Counter(5) -- expression 26 operands: lhs = Zero, rhs = Expression(44, Sub) -- expression 27 operands: lhs = Expression(45, Sub), rhs = Zero -- expression 28 operands: lhs = Expression(46, Sub), rhs = Zero -- expression 29 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 30 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 26 operands: lhs = Zero, rhs = Expression(45, Sub) +- expression 27 operands: lhs = Expression(46, Sub), rhs = Zero +- expression 28 operands: lhs = Expression(47, Sub), rhs = Zero +- expression 29 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 30 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) - expression 31 operands: lhs = Zero, rhs = Counter(3) - expression 32 operands: lhs = Zero, rhs = Counter(5) -- expression 33 operands: lhs = Expression(43, Add), rhs = Counter(5) -- expression 34 operands: lhs = Zero, rhs = Expression(44, Sub) -- expression 35 operands: lhs = Expression(45, Sub), rhs = Zero -- expression 36 operands: lhs = Expression(46, Sub), rhs = Zero -- expression 37 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 38 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) +- expression 33 operands: lhs = Expression(44, Add), rhs = Counter(5) +- expression 34 operands: lhs = Zero, rhs = Expression(45, Sub) +- expression 35 operands: lhs = Expression(46, Sub), rhs = Zero +- expression 36 operands: lhs = Expression(47, Sub), rhs = Zero +- expression 37 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 38 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) - expression 39 operands: lhs = Zero, rhs = Counter(3) - expression 40 operands: lhs = Zero, rhs = Counter(5) -- expression 41 operands: lhs = Expression(42, Sub), rhs = Expression(50, Add) -- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(5) -- expression 43 operands: lhs = Zero, rhs = Expression(44, Sub) -- expression 44 operands: lhs = Expression(45, Sub), rhs = Zero +- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(9) +- expression 42 operands: lhs = Expression(43, Sub), rhs = Counter(6) +- expression 43 operands: lhs = Expression(44, Add), rhs = Counter(5) +- expression 44 operands: lhs = Zero, rhs = Expression(45, Sub) - expression 45 operands: lhs = Expression(46, Sub), rhs = Zero -- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(6) -- expression 47 operands: lhs = Expression(48, Add), rhs = Expression(49, Add) -- expression 48 operands: lhs = Zero, rhs = Counter(3) -- expression 49 operands: lhs = Zero, rhs = Counter(5) -- expression 50 operands: lhs = Counter(6), rhs = Counter(9) +- expression 46 operands: lhs = Expression(47, Sub), rhs = Zero +- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(6) +- expression 48 operands: lhs = Expression(49, Add), rhs = Expression(50, Add) +- expression 49 operands: lhs = Zero, rhs = Counter(3) +- expression 50 operands: lhs = Zero, rhs = Counter(5) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 34, 5) to (start + 1, 17) - Code(Zero) at (prev + 1, 18) to (start + 1, 10) @@ -152,26 +152,26 @@ Number of file 0 mappings: 20 - Code(Expression(2, Add)) at (prev + 1, 13) to (start + 0, 30) = (Zero + ((c0 - Zero) - Zero)) - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31) -- Code(Expression(46, Sub)) at (prev + 2, 13) to (start + 0, 14) +- Code(Expression(47, Sub)) at (prev + 2, 13) to (start + 0, 14) = (((Zero + c3) + (Zero + c5)) - c6) -- Code(Expression(47, Add)) at (prev + 0, 18) to (start + 0, 23) +- Code(Expression(48, Add)) at (prev + 0, 18) to (start + 0, 23) = ((Zero + c3) + (Zero + c5)) -- Code(Expression(46, Sub)) at (prev + 1, 16) to (start + 0, 21) +- Code(Expression(47, Sub)) at (prev + 1, 16) to (start + 0, 21) = (((Zero + c3) + (Zero + c5)) - c6) - Code(Zero) at (prev + 0, 22) to (start + 1, 14) -- Code(Expression(45, Sub)) at (prev + 2, 20) to (start + 0, 25) +- Code(Expression(46, Sub)) at (prev + 2, 20) to (start + 0, 25) = ((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) -- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 19) +- Code(Expression(45, Sub)) at (prev + 1, 18) to (start + 0, 19) = (((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Zero) -- Code(Expression(43, Add)) at (prev + 1, 17) to (start + 0, 34) +- Code(Expression(44, Add)) at (prev + 1, 17) to (start + 0, 34) = (Zero + (((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Zero)) -- Code(Expression(42, Sub)) at (prev + 0, 34) to (start + 0, 35) +- Code(Expression(43, Sub)) at (prev + 0, 34) to (start + 0, 35) = ((Zero + (((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Zero)) - c5) - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) - Code(Expression(41, Add)) at (prev + 1, 5) to (start + 0, 6) - = (((Zero + (((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Zero)) - c5) + (c6 + c9)) + = ((((Zero + (((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Zero)) - c5) + c6) + c9) Function name: loops_branches::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 01, 05, 02] diff --git a/tests/run-coverage/loops_branches.coverage b/tests/coverage/loops_branches.coverage similarity index 100% rename from tests/run-coverage/loops_branches.coverage rename to tests/coverage/loops_branches.coverage diff --git a/tests/coverage-map/status-quo/loops_branches.rs b/tests/coverage/loops_branches.rs similarity index 100% rename from tests/coverage-map/status-quo/loops_branches.rs rename to tests/coverage/loops_branches.rs diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map new file mode 100644 index 0000000000000..b84628fc788ce --- /dev/null +++ b/tests/coverage/macro_name_span.cov-map @@ -0,0 +1,16 @@ +Function name: macro_name_span::affected_function +Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 1b, 00, 20] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 6, 27) to (start + 0, 32) + +Function name: macro_name_span::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 0b, 01, 02, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2) + diff --git a/tests/coverage/macro_name_span.coverage b/tests/coverage/macro_name_span.coverage new file mode 100644 index 0000000000000..cadf7024657e3 --- /dev/null +++ b/tests/coverage/macro_name_span.coverage @@ -0,0 +1,39 @@ +$DIR/auxiliary/macro_name_span_helper.rs: + LL| |// edition: 2021 + LL| | + LL| |#[macro_export] + LL| |macro_rules! macro_that_defines_a_function { + LL| | (fn $name:ident () $body:tt) => { + LL| 1| fn $name () -> () $body + LL| | } + LL| |} + LL| | + LL| |// Non-executable comment. + +$DIR/macro_name_span.rs: + LL| |// edition: 2021 + LL| | + LL| |// Regression test for . + LL| |// Under some circumstances, the heuristics that detect macro name spans can + LL| |// get confused and produce incorrect spans beyond the bounds of the span + LL| |// being processed. + LL| | + LL| |// aux-build: macro_name_span_helper.rs + LL| |extern crate macro_name_span_helper; + LL| | + LL| 1|fn main() { + LL| 1| affected_function(); + LL| 1|} + LL| | + LL| |macro_rules! macro_with_an_unreasonably_and_egregiously_long_name { + LL| | () => { + LL| | println!("hello"); + LL| | }; + LL| |} + LL| | + LL| |macro_name_span_helper::macro_that_defines_a_function! { + LL| | fn affected_function() { + LL| | macro_with_an_unreasonably_and_egregiously_long_name!(); + LL| | } + LL| |} + diff --git a/tests/coverage/macro_name_span.rs b/tests/coverage/macro_name_span.rs new file mode 100644 index 0000000000000..5d15977c498f7 --- /dev/null +++ b/tests/coverage/macro_name_span.rs @@ -0,0 +1,25 @@ +// edition: 2021 + +// Regression test for . +// Under some circumstances, the heuristics that detect macro name spans can +// get confused and produce incorrect spans beyond the bounds of the span +// being processed. + +// aux-build: macro_name_span_helper.rs +extern crate macro_name_span_helper; + +fn main() { + affected_function(); +} + +macro_rules! macro_with_an_unreasonably_and_egregiously_long_name { + () => { + println!("hello"); + }; +} + +macro_name_span_helper::macro_that_defines_a_function! { + fn affected_function() { + macro_with_an_unreasonably_and_egregiously_long_name!(); + } +} diff --git a/tests/coverage-map/status-quo/match_or_pattern.cov-map b/tests/coverage/match_or_pattern.cov-map similarity index 100% rename from tests/coverage-map/status-quo/match_or_pattern.cov-map rename to tests/coverage/match_or_pattern.cov-map diff --git a/tests/run-coverage/match_or_pattern.coverage b/tests/coverage/match_or_pattern.coverage similarity index 100% rename from tests/run-coverage/match_or_pattern.coverage rename to tests/coverage/match_or_pattern.coverage diff --git a/tests/coverage-map/status-quo/match_or_pattern.rs b/tests/coverage/match_or_pattern.rs similarity index 100% rename from tests/coverage-map/status-quo/match_or_pattern.rs rename to tests/coverage/match_or_pattern.rs diff --git a/tests/coverage-map/status-quo/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map similarity index 100% rename from tests/coverage-map/status-quo/nested_loops.cov-map rename to tests/coverage/nested_loops.cov-map diff --git a/tests/run-coverage/nested_loops.coverage b/tests/coverage/nested_loops.coverage similarity index 100% rename from tests/run-coverage/nested_loops.coverage rename to tests/coverage/nested_loops.coverage diff --git a/tests/coverage-map/status-quo/nested_loops.rs b/tests/coverage/nested_loops.rs similarity index 100% rename from tests/coverage-map/status-quo/nested_loops.rs rename to tests/coverage/nested_loops.rs diff --git a/tests/coverage-map/status-quo/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map similarity index 100% rename from tests/coverage-map/status-quo/no_cov_crate.cov-map rename to tests/coverage/no_cov_crate.cov-map diff --git a/tests/run-coverage/no_cov_crate.coverage b/tests/coverage/no_cov_crate.coverage similarity index 100% rename from tests/run-coverage/no_cov_crate.coverage rename to tests/coverage/no_cov_crate.coverage diff --git a/tests/coverage-map/status-quo/no_cov_crate.rs b/tests/coverage/no_cov_crate.rs similarity index 100% rename from tests/coverage-map/status-quo/no_cov_crate.rs rename to tests/coverage/no_cov_crate.rs diff --git a/tests/coverage-map/status-quo/overflow.cov-map b/tests/coverage/overflow.cov-map similarity index 89% rename from tests/coverage-map/status-quo/overflow.cov-map rename to tests/coverage/overflow.cov-map index bfffd9b2ab515..39a5c05f879ad 100644 --- a/tests/coverage-map/status-quo/overflow.cov-map +++ b/tests/coverage/overflow.cov-map @@ -1,5 +1,5 @@ Function name: overflow::main -Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0f, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 10, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -12,7 +12,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 27) +- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 27) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) = (c0 + (c1 + (c2 + c3))) - Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26) @@ -27,14 +27,14 @@ Number of file 0 mappings: 9 - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) Function name: overflow::might_overflow -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 18) +- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 18) - Code(Counter(1)) at (prev + 1, 19) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/run-coverage/overflow.coverage b/tests/coverage/overflow.coverage similarity index 98% rename from tests/run-coverage/overflow.coverage rename to tests/coverage/overflow.coverage index cee076e88cd43..4f8dffc0c4814 100644 --- a/tests/run-coverage/overflow.coverage +++ b/tests/coverage/overflow.coverage @@ -1,4 +1,5 @@ LL| |#![allow(unused_assignments)] + LL| |// compile-flags: -Coverflow-checks=yes LL| |// failure-status: 101 LL| | LL| 4|fn might_overflow(to_add: u32) -> u32 { diff --git a/tests/coverage-map/status-quo/overflow.rs b/tests/coverage/overflow.rs similarity index 98% rename from tests/coverage-map/status-quo/overflow.rs rename to tests/coverage/overflow.rs index bbb65c1b35df6..1c40771b27478 100644 --- a/tests/coverage-map/status-quo/overflow.rs +++ b/tests/coverage/overflow.rs @@ -1,4 +1,5 @@ #![allow(unused_assignments)] +// compile-flags: -Coverflow-checks=yes // failure-status: 101 fn might_overflow(to_add: u32) -> u32 { diff --git a/tests/coverage-map/status-quo/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map similarity index 100% rename from tests/coverage-map/status-quo/panic_unwind.cov-map rename to tests/coverage/panic_unwind.cov-map diff --git a/tests/run-coverage/panic_unwind.coverage b/tests/coverage/panic_unwind.coverage similarity index 100% rename from tests/run-coverage/panic_unwind.coverage rename to tests/coverage/panic_unwind.coverage diff --git a/tests/coverage-map/status-quo/panic_unwind.rs b/tests/coverage/panic_unwind.rs similarity index 100% rename from tests/coverage-map/status-quo/panic_unwind.rs rename to tests/coverage/panic_unwind.rs diff --git a/tests/coverage-map/status-quo/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map similarity index 100% rename from tests/coverage-map/status-quo/partial_eq.cov-map rename to tests/coverage/partial_eq.cov-map diff --git a/tests/run-coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage similarity index 100% rename from tests/run-coverage/partial_eq.coverage rename to tests/coverage/partial_eq.coverage diff --git a/tests/coverage-map/status-quo/partial_eq.rs b/tests/coverage/partial_eq.rs similarity index 100% rename from tests/coverage-map/status-quo/partial_eq.rs rename to tests/coverage/partial_eq.rs diff --git a/tests/coverage-map/status-quo/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map similarity index 100% rename from tests/coverage-map/status-quo/simple_loop.cov-map rename to tests/coverage/simple_loop.cov-map diff --git a/tests/run-coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage similarity index 100% rename from tests/run-coverage/simple_loop.coverage rename to tests/coverage/simple_loop.coverage diff --git a/tests/coverage-map/status-quo/simple_loop.rs b/tests/coverage/simple_loop.rs similarity index 100% rename from tests/coverage-map/status-quo/simple_loop.rs rename to tests/coverage/simple_loop.rs diff --git a/tests/coverage-map/status-quo/simple_match.cov-map b/tests/coverage/simple_match.cov-map similarity index 100% rename from tests/coverage-map/status-quo/simple_match.cov-map rename to tests/coverage/simple_match.cov-map diff --git a/tests/run-coverage/simple_match.coverage b/tests/coverage/simple_match.coverage similarity index 100% rename from tests/run-coverage/simple_match.coverage rename to tests/coverage/simple_match.coverage diff --git a/tests/coverage-map/status-quo/simple_match.rs b/tests/coverage/simple_match.rs similarity index 100% rename from tests/coverage-map/status-quo/simple_match.rs rename to tests/coverage/simple_match.rs diff --git a/tests/coverage-map/status-quo/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map similarity index 70% rename from tests/coverage-map/status-quo/sort_groups.cov-map rename to tests/coverage/sort_groups.cov-map index db027f3dc3249..3cbda6fbe1ab8 100644 --- a/tests/coverage-map/status-quo/sort_groups.cov-map +++ b/tests/coverage/sort_groups.cov-map @@ -28,6 +28,21 @@ Number of file 0 mappings: 4 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = (c1 + (c0 - c1)) +Function name: sort_groups::generic_fn:: +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) +- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + Function name: sort_groups::generic_fn:: Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] Number of files: 1 @@ -44,19 +59,19 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: sort_groups::main -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 06, 01, 04, 0d, 00, 04, 0e, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 13) -- Code(Zero) at (prev + 4, 14) to (start + 2, 6) +- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35) +- Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) - = (c0 - Zero) + = (c0 - c1) - Code(Expression(1, Add)) at (prev + 1, 5) to (start + 2, 2) - = (Zero + (c0 - Zero)) + = (c1 + (c0 - c1)) Function name: sort_groups::other_fn Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 11] diff --git a/tests/run-coverage/sort_groups.coverage b/tests/coverage/sort_groups.coverage similarity index 97% rename from tests/run-coverage/sort_groups.coverage rename to tests/coverage/sort_groups.coverage index 8733bf48a9c8d..c70d7b3b28253 100644 --- a/tests/run-coverage/sort_groups.coverage +++ b/tests/coverage/sort_groups.coverage @@ -7,7 +7,7 @@ LL| 1| let cond = std::env::args().len() > 1; LL| 1| generic_fn::<()>(cond); LL| 1| generic_fn::<&'static str>(!cond); - LL| 1| if false { + LL| 1| if std::hint::black_box(false) { LL| 0| generic_fn::(cond); LL| 1| } LL| 1| generic_fn::(cond); diff --git a/tests/run-coverage/sort_groups.rs b/tests/coverage/sort_groups.rs similarity index 93% rename from tests/run-coverage/sort_groups.rs rename to tests/coverage/sort_groups.rs index f89f9f3ec61fa..5adbbc6a87d1f 100644 --- a/tests/run-coverage/sort_groups.rs +++ b/tests/coverage/sort_groups.rs @@ -7,7 +7,7 @@ fn main() { let cond = std::env::args().len() > 1; generic_fn::<()>(cond); generic_fn::<&'static str>(!cond); - if false { + if std::hint::black_box(false) { generic_fn::(cond); } generic_fn::(cond); diff --git a/tests/coverage-map/status-quo/test_harness.cov-map b/tests/coverage/test_harness.cov-map similarity index 100% rename from tests/coverage-map/status-quo/test_harness.cov-map rename to tests/coverage/test_harness.cov-map diff --git a/tests/run-coverage/test_harness.coverage b/tests/coverage/test_harness.coverage similarity index 100% rename from tests/run-coverage/test_harness.coverage rename to tests/coverage/test_harness.coverage diff --git a/tests/coverage-map/status-quo/test_harness.rs b/tests/coverage/test_harness.rs similarity index 100% rename from tests/coverage-map/status-quo/test_harness.rs rename to tests/coverage/test_harness.rs diff --git a/tests/coverage/thin-lto.cov-map b/tests/coverage/thin-lto.cov-map new file mode 100644 index 0000000000000..7e84e398f8454 --- /dev/null +++ b/tests/coverage/thin-lto.cov-map @@ -0,0 +1,8 @@ +Function name: thin_lto::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 3, 1) to (start + 1, 2) + diff --git a/tests/coverage/thin-lto.coverage b/tests/coverage/thin-lto.coverage new file mode 100644 index 0000000000000..21abb5dce04e1 --- /dev/null +++ b/tests/coverage/thin-lto.coverage @@ -0,0 +1,5 @@ + LL| |// compile-flags: -O -C lto=thin -C prefer-dynamic=no + LL| | + LL| 1|pub fn main() { + LL| 1|} + diff --git a/tests/coverage/thin-lto.rs b/tests/coverage/thin-lto.rs new file mode 100644 index 0000000000000..050aac2631971 --- /dev/null +++ b/tests/coverage/thin-lto.rs @@ -0,0 +1,4 @@ +// compile-flags: -O -C lto=thin -C prefer-dynamic=no + +pub fn main() { +} diff --git a/tests/coverage-map/status-quo/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map similarity index 100% rename from tests/coverage-map/status-quo/tight_inf_loop.cov-map rename to tests/coverage/tight_inf_loop.cov-map diff --git a/tests/run-coverage/tight_inf_loop.coverage b/tests/coverage/tight_inf_loop.coverage similarity index 100% rename from tests/run-coverage/tight_inf_loop.coverage rename to tests/coverage/tight_inf_loop.coverage diff --git a/tests/coverage-map/status-quo/tight_inf_loop.rs b/tests/coverage/tight_inf_loop.rs similarity index 100% rename from tests/coverage-map/status-quo/tight_inf_loop.rs rename to tests/coverage/tight_inf_loop.rs diff --git a/tests/coverage-map/trivial.cov-map b/tests/coverage/trivial.cov-map similarity index 100% rename from tests/coverage-map/trivial.cov-map rename to tests/coverage/trivial.cov-map diff --git a/tests/coverage/trivial.coverage b/tests/coverage/trivial.coverage new file mode 100644 index 0000000000000..4f417979ef97d --- /dev/null +++ b/tests/coverage/trivial.coverage @@ -0,0 +1,4 @@ + LL| |// compile-flags: --edition=2021 + LL| | + LL| 1|fn main() {} + diff --git a/tests/coverage-map/trivial.rs b/tests/coverage/trivial.rs similarity index 100% rename from tests/coverage-map/trivial.rs rename to tests/coverage/trivial.rs diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map similarity index 96% rename from tests/coverage-map/status-quo/try_error_result.cov-map rename to tests/coverage/try_error_result.cov-map index 8367103a21a4e..a9a18a180dddf 100644 --- a/tests/coverage-map/status-quo/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -59,7 +59,7 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: try_error_result::test1 -Raw bytes (77): 0x[01, 01, 09, 01, 07, 05, 09, 03, 0d, 1d, 11, 16, 1d, 03, 0d, 1f, 0d, 11, 23, 15, 19, 0b, 01, 0c, 01, 02, 17, 03, 07, 09, 00, 0e, 16, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 0e, 01, 0d, 00, 2a, 15, 00, 2a, 00, 2b, 12, 04, 0d, 00, 2a, 19, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 1b, 01, 01, 00, 02] +Raw bytes (77): 0x[01, 01, 09, 01, 07, 05, 09, 03, 0d, 1d, 11, 16, 1d, 03, 0d, 1f, 0d, 23, 19, 11, 15, 0b, 01, 0c, 01, 02, 17, 03, 07, 09, 00, 0e, 16, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 0e, 01, 0d, 00, 2a, 15, 00, 2a, 00, 2b, 12, 04, 0d, 00, 2a, 19, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 1b, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -70,8 +70,8 @@ Number of expressions: 9 - expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(7) - expression 5 operands: lhs = Expression(0, Add), rhs = Counter(3) - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3) -- expression 7 operands: lhs = Counter(4), rhs = Expression(8, Add) -- expression 8 operands: lhs = Counter(5), rhs = Counter(6) +- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(6) +- expression 8 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 11 - Code(Counter(0)) at (prev + 12, 1) to (start + 2, 23) - Code(Expression(0, Add)) at (prev + 7, 9) to (start + 0, 14) @@ -88,10 +88,10 @@ Number of file 0 mappings: 11 - Code(Counter(6)) at (prev + 0, 42) to (start + 0, 43) - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) - Code(Expression(6, Add)) at (prev + 1, 1) to (start + 0, 2) - = ((c4 + (c5 + c6)) + c3) + = (((c4 + c5) + c6) + c3) Function name: try_error_result::test2 -Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, 11, c7, 01, cb, 01, db, 01, 15, cf, 01, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3c, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] +Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3c, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 59 @@ -143,9 +143,9 @@ Number of expressions: 59 - expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(15) - expression 46 operands: lhs = Counter(19), rhs = Counter(14) - expression 47 operands: lhs = Expression(48, Add), rhs = Counter(3) -- expression 48 operands: lhs = Counter(4), rhs = Expression(49, Add) -- expression 49 operands: lhs = Expression(50, Add), rhs = Expression(54, Add) -- expression 50 operands: lhs = Counter(5), rhs = Expression(51, Add) +- expression 48 operands: lhs = Expression(49, Add), rhs = Expression(54, Add) +- expression 49 operands: lhs = Expression(50, Add), rhs = Expression(51, Add) +- expression 50 operands: lhs = Counter(4), rhs = Counter(5) - expression 51 operands: lhs = Expression(52, Add), rhs = Expression(53, Add) - expression 52 operands: lhs = Counter(6), rhs = Counter(7) - expression 53 operands: lhs = Counter(8), rhs = Counter(9) @@ -216,5 +216,5 @@ Number of file 0 mappings: 40 = ((c19 - c14) - c15) - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) - Code(Expression(47, Add)) at (prev + 1, 1) to (start + 0, 2) - = ((c4 + ((c5 + ((c6 + c7) + (c8 + c9))) + ((c10 + c11) + ((c12 + c13) + (c14 + c15))))) + c3) + = ((((c4 + c5) + ((c6 + c7) + (c8 + c9))) + ((c10 + c11) + ((c12 + c13) + (c14 + c15)))) + c3) diff --git a/tests/run-coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage similarity index 100% rename from tests/run-coverage/try_error_result.coverage rename to tests/coverage/try_error_result.coverage diff --git a/tests/coverage-map/status-quo/try_error_result.rs b/tests/coverage/try_error_result.rs similarity index 100% rename from tests/coverage-map/status-quo/try_error_result.rs rename to tests/coverage/try_error_result.rs diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage/unreachable.cov-map similarity index 58% rename from tests/coverage-map/unreachable.cov-map rename to tests/coverage/unreachable.cov-map index 495419820c1f5..55d124a16f592 100644 --- a/tests/coverage-map/unreachable.cov-map +++ b/tests/coverage/unreachable.cov-map @@ -1,24 +1,24 @@ Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 27, 00, 49] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 27, 00, 47] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 39) to (start + 0, 73) +- Code(Counter(0)) at (prev + 15, 39) to (start + 0, 71) Function name: unreachable::unreachable_function -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 01, 25] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 37) Function name: unreachable::unreachable_intrinsic -Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 01, 2c] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 22, 1) to (start + 1, 44) diff --git a/tests/run-coverage/unreachable.coverage b/tests/coverage/unreachable.coverage similarity index 98% rename from tests/run-coverage/unreachable.coverage rename to tests/coverage/unreachable.coverage index fa0ac9ccfa1c8..7015bb90aa38d 100644 --- a/tests/run-coverage/unreachable.coverage +++ b/tests/coverage/unreachable.coverage @@ -16,12 +16,12 @@ LL| | LL| 0|fn unreachable_function() { LL| 0| unsafe { unreachable_unchecked() } - LL| 0|} + LL| |} LL| | LL| |// Use an intrinsic to more reliably trigger unreachable-propagation. LL| 0|fn unreachable_intrinsic() { LL| 0| unsafe { std::intrinsics::unreachable() } - LL| 0|} + LL| |} LL| | LL| |#[coverage(off)] LL| |fn main() { diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage/unreachable.rs similarity index 100% rename from tests/coverage-map/unreachable.rs rename to tests/coverage/unreachable.rs diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage/unused.cov-map similarity index 100% rename from tests/coverage-map/status-quo/unused.cov-map rename to tests/coverage/unused.cov-map diff --git a/tests/run-coverage/unused.coverage b/tests/coverage/unused.coverage similarity index 100% rename from tests/run-coverage/unused.coverage rename to tests/coverage/unused.coverage diff --git a/tests/coverage-map/status-quo/unused.rs b/tests/coverage/unused.rs similarity index 100% rename from tests/coverage-map/status-quo/unused.rs rename to tests/coverage/unused.rs diff --git a/tests/coverage/unused_mod.cov-map b/tests/coverage/unused_mod.cov-map new file mode 100644 index 0000000000000..241cb2610ffc0 --- /dev/null +++ b/tests/coverage/unused_mod.cov-map @@ -0,0 +1,16 @@ +Function name: unused_mod::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 04, 01, 02, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2) + +Function name: unused_mod::unused_module::never_called_function (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 02, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 2, 1) to (start + 2, 2) + diff --git a/tests/run-coverage/unused_mod.coverage b/tests/coverage/unused_mod.coverage similarity index 100% rename from tests/run-coverage/unused_mod.coverage rename to tests/coverage/unused_mod.coverage diff --git a/tests/run-coverage/unused_mod.rs b/tests/coverage/unused_mod.rs similarity index 100% rename from tests/run-coverage/unused_mod.rs rename to tests/coverage/unused_mod.rs diff --git a/tests/coverage/uses_crate.cov-map b/tests/coverage/uses_crate.cov-map new file mode 100644 index 0000000000000..9c06eab700507 --- /dev/null +++ b/tests/coverage/uses_crate.cov-map @@ -0,0 +1,40 @@ +Function name: used_crate::used_from_bin_crate_and_lib_crate_generic_function::> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 27, 1) to (start + 2, 2) + +Function name: used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) + +Function name: used_crate::used_only_from_bin_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) + +Function name: used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) + +Function name: uses_crate::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 07, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 12, 1) to (start + 7, 2) + diff --git a/tests/run-coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage similarity index 100% rename from tests/run-coverage/uses_crate.coverage rename to tests/coverage/uses_crate.coverage diff --git a/tests/run-coverage/uses_crate.rs b/tests/coverage/uses_crate.rs similarity index 100% rename from tests/run-coverage/uses_crate.rs rename to tests/coverage/uses_crate.rs diff --git a/tests/coverage/uses_inline_crate.cov-map b/tests/coverage/uses_inline_crate.cov-map new file mode 100644 index 0000000000000..6b621825c8861 --- /dev/null +++ b/tests/coverage/uses_inline_crate.cov-map @@ -0,0 +1,55 @@ +Function name: used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 44, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_inline_function +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 20, 1) to (start + 6, 15) +- Code(Counter(1)) at (prev + 6, 16) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + (c0 - c1)) + +Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2) + +Function name: uses_inline_crate::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 0a, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 12, 1) to (start + 10, 2) + diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/coverage/uses_inline_crate.coverage similarity index 100% rename from tests/run-coverage/uses_inline_crate.coverage rename to tests/coverage/uses_inline_crate.coverage diff --git a/tests/run-coverage/uses_inline_crate.rs b/tests/coverage/uses_inline_crate.rs similarity index 100% rename from tests/run-coverage/uses_inline_crate.rs rename to tests/coverage/uses_inline_crate.rs diff --git a/tests/coverage-map/status-quo/while.cov-map b/tests/coverage/while.cov-map similarity index 100% rename from tests/coverage-map/status-quo/while.cov-map rename to tests/coverage/while.cov-map diff --git a/tests/run-coverage/while.coverage b/tests/coverage/while.coverage similarity index 100% rename from tests/run-coverage/while.coverage rename to tests/coverage/while.coverage diff --git a/tests/coverage-map/status-quo/while.rs b/tests/coverage/while.rs similarity index 100% rename from tests/coverage-map/status-quo/while.rs rename to tests/coverage/while.rs diff --git a/tests/coverage-map/status-quo/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map similarity index 100% rename from tests/coverage-map/status-quo/while_early_ret.cov-map rename to tests/coverage/while_early_ret.cov-map diff --git a/tests/run-coverage/while_early_ret.coverage b/tests/coverage/while_early_ret.coverage similarity index 100% rename from tests/run-coverage/while_early_ret.coverage rename to tests/coverage/while_early_ret.coverage diff --git a/tests/coverage-map/status-quo/while_early_ret.rs b/tests/coverage/while_early_ret.rs similarity index 100% rename from tests/coverage-map/status-quo/while_early_ret.rs rename to tests/coverage/while_early_ret.rs diff --git a/tests/coverage-map/status-quo/yield.cov-map b/tests/coverage/yield.cov-map similarity index 100% rename from tests/coverage-map/status-quo/yield.cov-map rename to tests/coverage/yield.cov-map diff --git a/tests/run-coverage/yield.coverage b/tests/coverage/yield.coverage similarity index 100% rename from tests/run-coverage/yield.coverage rename to tests/coverage/yield.coverage diff --git a/tests/coverage-map/status-quo/yield.rs b/tests/coverage/yield.rs similarity index 100% rename from tests/coverage-map/status-quo/yield.rs rename to tests/coverage/yield.rs diff --git a/tests/incremental/commandline-args.rs b/tests/incremental/commandline-args.rs index 35b7183db7fac..e17e6feae0745 100644 --- a/tests/incremental/commandline-args.rs +++ b/tests/incremental/commandline-args.rs @@ -1,7 +1,6 @@ // Test that changing a tracked commandline argument invalidates // the cache while changing an untracked one doesn't. -// ignore-asmjs wasm2js does not support source maps yet // revisions:rpass1 rpass2 rpass3 rpass4 // compile-flags: -Z query-dep-graph diff --git a/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs index 2529e531e30ad..cc9831fff96d5 100644 --- a/tests/incremental/delayed_span_bug.rs +++ b/tests/incremental/delayed_span_bug.rs @@ -1,8 +1,8 @@ // revisions: cfail1 cfail2 // should-ice -// error-pattern: delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)] +// error-pattern: delayed span bug triggered by #[rustc_error(span_delayed_bug_from_inside_query)] #![feature(rustc_attrs)] -#[rustc_error(delay_span_bug_from_inside_query)] +#[rustc_error(span_delayed_bug_from_inside_query)] fn main() {} diff --git a/tests/incremental/remapped_paths_cc/main.rs b/tests/incremental/remapped_paths_cc/main.rs index b01f02444eae8..12411a928799f 100644 --- a/tests/incremental/remapped_paths_cc/main.rs +++ b/tests/incremental/remapped_paths_cc/main.rs @@ -2,7 +2,6 @@ // compile-flags: -Z query-dep-graph -g // aux-build:extern_crate.rs -// ignore-asmjs wasm2js does not support source maps yet // This test case makes sure that we detect if paths emitted into debuginfo // are changed, even when the change happens in an external crate. diff --git a/tests/incremental/span_hash_stable/main.rs b/tests/incremental/span_hash_stable/main.rs index 367416430f86b..f1d7de1455938 100644 --- a/tests/incremental/span_hash_stable/main.rs +++ b/tests/incremental/span_hash_stable/main.rs @@ -3,7 +3,6 @@ // the spans and this test makes sure that we handle them correctly by hashing // file:line:column instead of raw byte offset. -// ignore-asmjs wasm2js does not support source maps yet // revisions:rpass1 rpass2 // compile-flags: -g -Z query-dep-graph diff --git a/tests/incremental/spans_in_type_debuginfo.rs b/tests/incremental/spans_in_type_debuginfo.rs index f5cae15a4bc7c..8ed469db6e633 100644 --- a/tests/incremental/spans_in_type_debuginfo.rs +++ b/tests/incremental/spans_in_type_debuginfo.rs @@ -1,7 +1,6 @@ // Test that moving a type definition within a source file does not affect // re-compilation. -// ignore-asmjs wasm2js does not support source maps yet // revisions:rpass1 rpass2 // compile-flags: -Z query-dep-graph -g diff --git a/tests/incremental/spans_significant_w_debuginfo.rs b/tests/incremental/spans_significant_w_debuginfo.rs index 38ab28461911b..a036d3e69fe4a 100644 --- a/tests/incremental/spans_significant_w_debuginfo.rs +++ b/tests/incremental/spans_significant_w_debuginfo.rs @@ -3,7 +3,6 @@ // revisions:rpass1 rpass2 -// ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g -Z query-dep-graph #![feature(rustc_attrs)] diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 396e4a378f6f6..111dd8e97f9a4 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -14,7 +14,7 @@ Static, ), source_info: SourceInfo { - span: $DIR/async_await.rs:16:9: 16:14 (#8), + span: $DIR/async_await.rs:16:5: 16:14 (#9), scope: scope[0], }, ignore_for_traits: false, @@ -32,7 +32,7 @@ Static, ), source_info: SourceInfo { - span: $DIR/async_await.rs:17:9: 17:14 (#10), + span: $DIR/async_await.rs:17:5: 17:14 (#11), scope: scope[0], }, ignore_for_traits: false, diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs index 9e442e0f98a94..a83a6c07461f4 100644 --- a/tests/mir-opt/building/custom/terminators.rs +++ b/tests/mir-opt/building/custom/terminators.rs @@ -13,7 +13,7 @@ fn ident(t: T) -> T { fn direct_call(x: i32) -> i32 { mir!( { - Call(RET = ident(x), retblock) + Call(RET = ident(x), retblock, UnwindContinue()) } retblock = { @@ -27,7 +27,7 @@ fn direct_call(x: i32) -> i32 { fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 { mir!( { - Call(RET = f(x), retblock) + Call(RET = f(x), retblock, UnwindContinue()) } retblock = { @@ -49,7 +49,7 @@ impl<'a> Drop for WriteOnDrop<'a> { fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - Drop(a, retblock) + Drop(a, retblock, UnwindContinue()) } retblock = { @@ -64,7 +64,7 @@ fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - Drop(b, retblock) + Drop(b, retblock, UnwindContinue()) } retblock = { diff --git a/tests/mir-opt/building/custom/unwind_action.rs b/tests/mir-opt/building/custom/unwind_action.rs new file mode 100644 index 0000000000000..e3c4ffac358ad --- /dev/null +++ b/tests/mir-opt/building/custom/unwind_action.rs @@ -0,0 +1,68 @@ +// compile-flags: --crate-type=lib +// edition:2021 +// needs-unwind +#![feature(custom_mir, core_intrinsics)] +use core::intrinsics::mir::*; + +// CHECK-LABEL: fn a() +// CHECK: bb0: { +// CHECK-NEXT: a() -> [return: bb1, unwind unreachable]; +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn a() { + mir!( + { + Call(RET = a(), bb1, UnwindUnreachable()) + } + bb1 = { + Return() + } + ) +} + +// CHECK-LABEL: fn b() +// CHECK: bb0: { +// CHECK-NEXT: b() -> [return: bb1, unwind continue]; +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn b() { + mir!( + { + Call(RET = b(), bb1, UnwindContinue()) + } + bb1 = { + Return() + } + ) +} + +// CHECK-LABEL: fn c() +// CHECK: bb0: { +// CHECK-NEXT: c() -> [return: bb1, unwind terminate(abi)]; +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn c() { + mir!( + { + Call(RET = c(), bb1, UnwindTerminate(ReasonAbi)) + } + bb1 = { + Return() + } + ) +} + +// CHECK-LABEL: fn d() +// CHECK: bb0: { +// CHECK-NEXT: d() -> [return: bb1, unwind: bb2]; +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn d() { + mir!( + { + Call(RET = d(), bb1, UnwindCleanup(bb2)) + } + bb1 = { + Return() + } + bb2 (cleanup) = { + UnwindResume() + } + ) +} diff --git a/tests/mir-opt/building/custom/unwind_terminate.rs b/tests/mir-opt/building/custom/unwind_terminate.rs new file mode 100644 index 0000000000000..efdf2ddb1d02e --- /dev/null +++ b/tests/mir-opt/building/custom/unwind_terminate.rs @@ -0,0 +1,34 @@ +// compile-flags: --crate-type=lib +// edition:2021 +#![feature(custom_mir, core_intrinsics)] +use core::intrinsics::mir::*; + +// CHECK-LABEL: fn f() +// CHECK: bb1 (cleanup): { +// CHECK-NEXT: terminate(abi); +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn f() { + mir!( + { + Return() + } + bb1(cleanup) = { + UnwindTerminate(ReasonAbi) + } + ) +} + +// CHECK-LABEL: fn g() +// CHECK: bb1 (cleanup): { +// CHECK-NEXT: terminate(cleanup); +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn g() { + mir!( + { + Return() + } + bb1(cleanup) = { + UnwindTerminate(ReasonInCleanup) + } + ) +} diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir index 1946c70e47642..b99b0b99559a5 100644 --- a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir @@ -52,7 +52,7 @@ fn full_tested_match() -> () { bb5: { StorageLive(_6); _6 = &((_2 as Some).0: i32); - _4 = &shallow _2; + _4 = &fake _2; StorageLive(_7); _7 = guard() -> [return: bb6, unwind: bb12]; } diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir index b6175b0515683..d1d86b55d686f 100644 --- a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir @@ -58,7 +58,7 @@ fn full_tested_match2() -> () { bb5: { StorageLive(_6); _6 = &((_2 as Some).0: i32); - _4 = &shallow _2; + _4 = &fake _2; StorageLive(_7); _7 = guard() -> [return: bb6, unwind: bb12]; } diff --git a/tests/mir-opt/building/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match_false_edges.main.built.after.mir index 0b57d1b97e15d..1d4fe67f350ca 100644 --- a/tests/mir-opt/building/match_false_edges.main.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.main.built.after.mir @@ -78,7 +78,7 @@ fn main() -> () { bb8: { StorageLive(_7); _7 = &((_2 as Some).0: i32); - _5 = &shallow _2; + _5 = &fake _2; StorageLive(_8); _8 = guard() -> [return: bb9, unwind: bb20]; } @@ -120,7 +120,7 @@ fn main() -> () { bb14: { StorageLive(_11); _11 = &((_2 as Some).0: i32); - _5 = &shallow _2; + _5 = &fake _2; StorageLive(_12); StorageLive(_13); _13 = (*_11); diff --git a/tests/mir-opt/building/while_storage.rs b/tests/mir-opt/building/while_storage.rs new file mode 100644 index 0000000000000..b06c1639c3f3d --- /dev/null +++ b/tests/mir-opt/building/while_storage.rs @@ -0,0 +1,60 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// Test that we correctly generate StorageDead statements for while loop +// conditions on all branches +// compile-flags: -Zmir-opt-level=0 + +fn get_bool(c: bool) -> bool { + c +} + +// EMIT_MIR while_storage.while_loop.PreCodegen.after.mir +fn while_loop(c: bool) { + // CHECK-LABEL: fn while_loop( + // CHECK: bb0: { + // CHECK-NEXT: goto -> bb1; + // CHECK: bb1: { + // CHECK-NEXT: StorageLive(_3); + // CHECK-NEXT: StorageLive(_2); + // CHECK-NEXT: _2 = _1; + // CHECK-NEXT: _3 = get_bool(move _2) -> [return: bb2, unwind + // CHECK: bb2: { + // CHECK-NEXT: switchInt(move _3) -> [0: bb3, otherwise: bb4]; + // CHECK: bb3: { + // CHECK-NEXT: StorageDead(_2); + // CHECK-NEXT: StorageLive(_9); + // CHECK-NEXT: _0 = const (); + // CHECK-NEXT: StorageDead(_9); + // CHECK-NEXT: goto -> bb8; + // CHECK: bb4: { + // CHECK-NEXT: StorageDead(_2); + // CHECK-NEXT: StorageLive(_5); + // CHECK-NEXT: StorageLive(_4); + // CHECK-NEXT: _4 = _1; + // CHECK-NEXT: _5 = get_bool(move _4) -> [return: bb5, unwind + // CHECK: bb5: { + // CHECK-NEXT: switchInt(move _5) -> [0: bb6, otherwise: bb7]; + // CHECK: bb6: { + // CHECK-NEXT: StorageDead(_4); + // CHECK-NEXT: _6 = const (); + // CHECK-NEXT: StorageDead(_5); + // CHECK-NEXT: StorageDead(_3); + // CHECK-NEXT: goto -> bb1; + // CHECK: bb7: { + // CHECK-NEXT: StorageDead(_4); + // CHECK-NEXT: _0 = const (); + // CHECK-NEXT: StorageDead(_5); + // CHECK-NEXT: goto -> bb8; + // CHECK: bb8: { + // CHECK-NEXT: StorageDead(_3); + // CHECK-NEXT: return; + + while get_bool(c) { + if get_bool(c) { + break; + } + } +} + +fn main() { + while_loop(false); +} diff --git a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir new file mode 100644 index 0000000000000..26c82edf2d5fd --- /dev/null +++ b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-abort.mir @@ -0,0 +1,70 @@ +// MIR for `while_loop` after PreCodegen + +fn while_loop(_1: bool) -> () { + debug c => _1; + let mut _0: (); + let mut _2: bool; + let mut _3: bool; + let mut _4: bool; + let mut _5: bool; + let mut _6: (); + let mut _7: !; + let mut _8: !; + let _9: (); + let mut _10: !; + + bb0: { + goto -> bb1; + } + + bb1: { + StorageLive(_3); + StorageLive(_2); + _2 = _1; + _3 = get_bool(move _2) -> [return: bb2, unwind unreachable]; + } + + bb2: { + switchInt(move _3) -> [0: bb3, otherwise: bb4]; + } + + bb3: { + StorageDead(_2); + StorageLive(_9); + _0 = const (); + StorageDead(_9); + goto -> bb8; + } + + bb4: { + StorageDead(_2); + StorageLive(_5); + StorageLive(_4); + _4 = _1; + _5 = get_bool(move _4) -> [return: bb5, unwind unreachable]; + } + + bb5: { + switchInt(move _5) -> [0: bb6, otherwise: bb7]; + } + + bb6: { + StorageDead(_4); + _6 = const (); + StorageDead(_5); + StorageDead(_3); + goto -> bb1; + } + + bb7: { + StorageDead(_4); + _0 = const (); + StorageDead(_5); + goto -> bb8; + } + + bb8: { + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..1bb72074846e7 --- /dev/null +++ b/tests/mir-opt/building/while_storage.while_loop.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,70 @@ +// MIR for `while_loop` after PreCodegen + +fn while_loop(_1: bool) -> () { + debug c => _1; + let mut _0: (); + let mut _2: bool; + let mut _3: bool; + let mut _4: bool; + let mut _5: bool; + let mut _6: (); + let mut _7: !; + let mut _8: !; + let _9: (); + let mut _10: !; + + bb0: { + goto -> bb1; + } + + bb1: { + StorageLive(_3); + StorageLive(_2); + _2 = _1; + _3 = get_bool(move _2) -> [return: bb2, unwind continue]; + } + + bb2: { + switchInt(move _3) -> [0: bb3, otherwise: bb4]; + } + + bb3: { + StorageDead(_2); + StorageLive(_9); + _0 = const (); + StorageDead(_9); + goto -> bb8; + } + + bb4: { + StorageDead(_2); + StorageLive(_5); + StorageLive(_4); + _4 = _1; + _5 = get_bool(move _4) -> [return: bb5, unwind continue]; + } + + bb5: { + switchInt(move _5) -> [0: bb6, otherwise: bb7]; + } + + bb6: { + StorageDead(_4); + _6 = const (); + StorageDead(_5); + StorageDead(_3); + goto -> bb1; + } + + bb7: { + StorageDead(_4); + _0 = const (); + StorageDead(_5); + goto -> bb8; + } + + bb8: { + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index f20bfef8c794c..9cc4c7c4d7613 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -18,19 +18,19 @@ fn main() -> () { } ALLOC9 (static: FOO, size: 8, align: 4) { - ╾ALLOC0╼ 03 00 00 00 │ ╾──╼.... + ╾ALLOC0╼ 03 00 00 00 │ ╾──╼.... } ALLOC0 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾ALLOC2╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ 03 00 00 00 │ ....*...╾──╼.... + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾ALLOC2╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ 03 00 00 00 │ ....*...╾──╼.... } ALLOC1 (size: 0, align: 4) {} ALLOC2 (size: 16, align: 4) { - ╾ALLOC4╼ 03 00 00 00 ╾ALLOC5╼ 03 00 00 00 │ ╾──╼....╾──╼.... + ╾ALLOC4╼ 03 00 00 00 ╾ALLOC5╼ 03 00 00 00 │ ╾──╼....╾──╼.... } ALLOC4 (size: 3, align: 1) { @@ -42,8 +42,8 @@ ALLOC5 (size: 3, align: 1) { } ALLOC3 (size: 24, align: 4) { - 0x00 │ ╾ALLOC6╼ 03 00 00 00 ╾ALLOC7╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾ALLOC8╼ 04 00 00 00 │ ╾──╼.... + 0x00 │ ╾ALLOC6╼ 03 00 00 00 ╾ALLOC7╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾ALLOC8╼ 04 00 00 00 │ ╾──╼.... } ALLOC6 (size: 3, align: 1) { diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index 263cae2f3ea5c..faa9d20f2d5cb 100644 --- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -18,22 +18,22 @@ fn main() -> () { } ALLOC9 (static: FOO, size: 16, align: 8) { - ╾ALLOC0╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾ALLOC0╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } ALLOC0 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ │ ....░░░░╾──────╼ + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾ALLOC2╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ │ ....*...╾──────╼ + 0x20 │ ╾ALLOC2╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } ALLOC1 (size: 0, align: 8) {} ALLOC2 (size: 32, align: 8) { - 0x00 │ ╾ALLOC4╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾ALLOC5╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x00 │ ╾ALLOC4╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾ALLOC5╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } ALLOC4 (size: 3, align: 1) { @@ -45,9 +45,9 @@ ALLOC5 (size: 3, align: 1) { } ALLOC3 (size: 48, align: 8) { - 0x00 │ ╾ALLOC6╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾ALLOC7╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾ALLOC8╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x00 │ ╾ALLOC6╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾ALLOC7╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾ALLOC8╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } ALLOC6 (size: 3, align: 1) { diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index 713abb264a704..898835b46e46f 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -18,19 +18,19 @@ fn main() -> () { } ALLOC9 (static: FOO, size: 8, align: 4) { - ╾ALLOC0╼ 03 00 00 00 │ ╾──╼.... + ╾ALLOC0╼ 03 00 00 00 │ ╾──╼.... } ALLOC0 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾ALLOC2╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ 03 00 00 00 │ ....*...╾──╼.... + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾ALLOC2╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ 03 00 00 00 │ ....*...╾──╼.... } ALLOC1 (size: 0, align: 4) {} ALLOC2 (size: 8, align: 4) { - ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ } ALLOC4 (size: 1, align: 1) { @@ -42,7 +42,7 @@ ALLOC5 (size: 1, align: 1) { } ALLOC3 (size: 12, align: 4) { - ╾ALLOC6+0x3╼ ╾ALLOC7╼ ╾ALLOC8+0x2╼ │ ╾──╼╾──╼╾──╼ + ╾ALLOC6+0x3╼ ╾ALLOC7╼ ╾ALLOC8+0x2╼ │ ╾──╼╾──╼╾──╼ } ALLOC6 (size: 4, align: 1) { diff --git a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index e9d61ef120c78..f5352c2aebb36 100644 --- a/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -18,21 +18,21 @@ fn main() -> () { } ALLOC9 (static: FOO, size: 16, align: 8) { - ╾ALLOC0╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾ALLOC0╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } ALLOC0 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ │ ....░░░░╾──────╼ + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC1╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾ALLOC2╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ │ ....*...╾──────╼ + 0x20 │ ╾ALLOC2╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾ALLOC3╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } ALLOC1 (size: 0, align: 8) {} ALLOC2 (size: 16, align: 8) { - ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ } ALLOC4 (size: 1, align: 1) { @@ -44,8 +44,8 @@ ALLOC5 (size: 1, align: 1) { } ALLOC3 (size: 24, align: 8) { - 0x00 │ ╾ALLOC6+0x3╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾ALLOC8+0x2╼ │ ╾──────╼ + 0x00 │ ╾ALLOC6+0x3╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾ALLOC8+0x2╼ │ ╾──────╼ } ALLOC6 (size: 4, align: 1) { diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index c18c067c72e7b..624047f5b6f2f 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -18,12 +18,12 @@ fn main() -> () { } ALLOC4 (static: FOO, size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } ALLOC0 (size: 168, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾ALLOC1╼ │ ............╾──╼ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾ALLOC1╼ │ ............╾──╼ 0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ @@ -31,7 +31,7 @@ ALLOC0 (size: 168, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾ALLOC2╼ 00 00 │ ..........╾──╼.. - 0x90 │ ╾ALLOC3+0x63╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ + 0x90 │ ╾ALLOC3+0x63╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index 6af0e3cbd94cb..cdd4758e153c0 100644 --- a/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/tests/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -18,12 +18,12 @@ fn main() -> () { } ALLOC2 (static: FOO, size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } ALLOC0 (size: 180, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──ALLOC3── │ ............╾─── + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾ALLOC3 (8 ptr bytes) │ ............╾─── 0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ @@ -31,7 +31,7 @@ ALLOC0 (size: 180, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ - 0x90 │ ─────ALLOC4─────╼ 00 00 ╾ALLOC1+0x63╼ │ ─────╼..╾──────╼ + 0x90 │ ─────ALLOC4─────╼ 00 00 ╾ALLOC1+0x63╼ │ ─────╼..╾──────╼ 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0xb0 │ 00 00 00 00 │ .... } diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index f5d822520a70a..87c07279552f4 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -4,6 +4,12 @@ fn main() -> () { let mut _0: (); let _1: u8; + let mut _5: u8; + let mut _6: u8; + let mut _7: u8; + let mut _8: u8; + let mut _14: u32; + let mut _15: u32; scope 1 { - debug x => _1; + debug x => const 1_u8; @@ -19,34 +25,23 @@ scope 4 { - debug sum => _4; + debug sum => const 6_u8; - let _5: &str; + let _9: &str; scope 5 { -- debug s => _5; +- debug s => _9; + debug s => const "hello, world!"; - let _8: bool; - let _9: bool; - let _10: u32; + let _10: (bool, bool, u32); scope 6 { -- debug ((f: (bool, bool, u32)).0: bool) => _8; -- debug ((f: (bool, bool, u32)).1: bool) => _9; -- debug ((f: (bool, bool, u32)).2: u32) => _10; -+ debug ((f: (bool, bool, u32)).0: bool) => const true; -+ debug ((f: (bool, bool, u32)).1: bool) => const false; -+ debug ((f: (bool, bool, u32)).2: u32) => const 123_u32; - let _6: std::option::Option; + debug f => _10; + let _11: std::option::Option; scope 7 { -- debug o => _6; -+ debug o => const Option::::Some(99_u16); - let _11: u32; - let _12: u32; + debug o => _11; + let _12: Point; scope 8 { -- debug ((p: Point).0: u32) => _11; -- debug ((p: Point).1: u32) => _12; -+ debug ((p: Point).0: u32) => const 32_u32; -+ debug ((p: Point).1: u32) => const 32_u32; - let _7: u32; +- debug p => _12; ++ debug p => const Point {{ x: 32_u32, y: 32_u32 }}; + let _13: u32; scope 9 { -- debug a => _7; +- debug a => _13; + debug a => const 64_u32; } } @@ -59,37 +54,57 @@ } bb0: { + StorageLive(_1); _1 = const 1_u8; + StorageLive(_2); _2 = const 2_u8; + StorageLive(_3); _3 = const 3_u8; StorageLive(_4); - _4 = const 6_u8; StorageLive(_5); - _5 = const "hello, world!"; - StorageLive(_8); - StorageLive(_9); - StorageLive(_10); - _8 = const true; - _9 = const false; - _10 = const 123_u32; StorageLive(_6); - _6 = const Option::::Some(99_u16); - _11 = const 32_u32; - _12 = const 32_u32; + _6 = const 1_u8; StorageLive(_7); - _7 = const 64_u32; + _7 = const 2_u8; + _5 = const 3_u8; StorageDead(_7); StorageDead(_6); + StorageLive(_8); + _8 = const 3_u8; + _4 = const 6_u8; StorageDead(_8); - StorageDead(_9); - StorageDead(_10); StorageDead(_5); + StorageLive(_9); + _9 = const "hello, world!"; + StorageLive(_10); + _10 = (const true, const false, const 123_u32); + StorageLive(_11); + _11 = Option::::Some(const 99_u16); + StorageLive(_12); + _12 = const Point {{ x: 32_u32, y: 32_u32 }}; + StorageLive(_13); + StorageLive(_14); + _14 = const 32_u32; + StorageLive(_15); + _15 = const 32_u32; + _13 = const 64_u32; + StorageDead(_15); + StorageDead(_14); + _0 = const (); + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); + StorageDead(_10); + StorageDead(_9); StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + StorageDead(_1); return; } } - ALLOC0 (size: 4, align: 2) { - 01 00 63 00 │ ..c. + ALLOC0 (size: 8, align: 4) { + 20 00 00 00 20 00 00 00 │ ... ... } diff --git a/tests/mir-opt/const_debuginfo.rs b/tests/mir-opt/const_debuginfo.rs index d8ae08a0723ce..0e5ac4b8bd60d 100644 --- a/tests/mir-opt/const_debuginfo.rs +++ b/tests/mir-opt/const_debuginfo.rs @@ -1,12 +1,23 @@ -// skip-filecheck -// compile-flags: -C overflow-checks=no -Zunsound-mir-opts +// unit-test: ConstDebugInfo +// compile-flags: -C overflow-checks=no -Zmir-enable-passes=+ConstProp struct Point { x: u32, y: u32, } +// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => const 1_u8; + // CHECK: debug y => const 2_u8; + // CHECK: debug z => const 3_u8; + // CHECK: debug sum => const 6_u8; + // CHECK: debug s => const "hello, world!"; + // CHECK: debug f => {{_.*}}; + // CHECK: debug o => {{_.*}}; + // CHECK: debug p => const Point + // CHECK: debug a => const 64_u32; let x = 1u8; let y = 2u8; let z = 3u8; @@ -21,5 +32,3 @@ fn main() { let p = Point { x: 32, y: 32 }; let a = p.x + p.y; } - -// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff diff --git a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff similarity index 100% rename from tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff rename to tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff diff --git a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff similarity index 100% rename from tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff rename to tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff diff --git a/tests/mir-opt/const_prop/indirect_mutation.rs b/tests/mir-opt/const_prop/indirect_mutation.rs new file mode 100644 index 0000000000000..ec9da6e8e5c5e --- /dev/null +++ b/tests/mir-opt/const_prop/indirect_mutation.rs @@ -0,0 +1,41 @@ +// unit-test: ConstProp +// Check that we do not propagate past an indirect mutation. +#![feature(raw_ref_op)] + +// EMIT_MIR indirect_mutation.foo.ConstProp.diff +fn foo() { + // CHECK-LABEL: fn foo( + // CHECK: debug u => _1; + // CHECK: debug y => _3; + // CHECK: _1 = (const 1_i32,); + // CHECK: _2 = &mut (_1.0: i32); + // CHECK: (*_2) = const 5_i32; + // CHECK: _4 = (_1.0: i32); + // CHECK: _3 = Eq(move _4, const 5_i32); + + let mut u = (1,); + *&mut u.0 = 5; + let y = { u.0 } == 5; +} + +// EMIT_MIR indirect_mutation.bar.ConstProp.diff +fn bar() { + // CHECK-LABEL: fn bar( + // CHECK: debug v => _1; + // CHECK: debug y => _4; + // CHECK: _3 = &raw mut (_1.0: i32); + // CHECK: (*_3) = const 5_i32; + // CHECK: _5 = (_1.0: i32); + // CHECK: _4 = Eq(move _5, const 5_i32); + + let mut v = (1,); + unsafe { + *&raw mut v.0 = 5; + } + let y = { v.0 } == 5; +} + +fn main() { + foo(); + bar(); +} diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff index b30deb2a4d43b..11cdf9e09db0c 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff @@ -8,7 +8,7 @@ let mut _3: u8; scope 1 { } - scope 2 (inlined ::add) { + scope 2 (inlined #[track_caller] ::add) { debug self => _2; debug other => _3; let mut _4: (u8, bool); diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff index 47c51196c02ac..181a2f287d66a 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff @@ -8,7 +8,7 @@ let mut _3: u8; scope 1 { } - scope 2 (inlined ::add) { + scope 2 (inlined #[track_caller] ::add) { debug self => _2; debug other => _3; let mut _4: (u8, bool); diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 8a5289d589914..2571c3856f462 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -2,7 +2,7 @@ // unit-test: ConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs b/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs new file mode 100644 index 0000000000000..4cf6d7c139643 --- /dev/null +++ b/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs @@ -0,0 +1,26 @@ +// unit-test: ConstProp +// compile-flags: -O + +// Regression test for https://github.com/rust-lang/rust/issues/118328 + +#![allow(unused_assignments)] + +struct SizeOfConst(std::marker::PhantomData); +impl SizeOfConst { + const SIZE: usize = std::mem::size_of::(); +} + +// EMIT_MIR overwrite_with_const_with_params.size_of.ConstProp.diff +fn size_of() -> usize { + // CHECK-LABEL: fn size_of( + // CHECK: _1 = const 0_usize; + // CHECK-NEXT: _1 = const _; + // CHECK-NEXT: _0 = _1; + let mut a = 0; + a = SizeOfConst::::SIZE; + a +} + +fn main() { + assert_eq!(size_of::(), std::mem::size_of::()); +} diff --git a/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.ConstProp.diff b/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.ConstProp.diff new file mode 100644 index 0000000000000..ad8318832d63b --- /dev/null +++ b/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.ConstProp.diff @@ -0,0 +1,20 @@ +- // MIR for `size_of` before ConstProp ++ // MIR for `size_of` after ConstProp + + fn size_of() -> usize { + let mut _0: usize; + let mut _1: usize; + scope 1 { + debug a => _1; + } + + bb0: { + StorageLive(_1); + _1 = const 0_usize; + _1 = const _; + _0 = _1; + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/const_prop_miscompile.rs b/tests/mir-opt/const_prop_miscompile.rs deleted file mode 100644 index 00696535ac159..0000000000000 --- a/tests/mir-opt/const_prop_miscompile.rs +++ /dev/null @@ -1,24 +0,0 @@ -// skip-filecheck -// unit-test: ConstProp -#![feature(raw_ref_op)] - -// EMIT_MIR const_prop_miscompile.foo.ConstProp.diff -fn foo() { - let mut u = (1,); - *&mut u.0 = 5; - let y = { u.0 } == 5; -} - -// EMIT_MIR const_prop_miscompile.bar.ConstProp.diff -fn bar() { - let mut v = (1,); - unsafe { - *&raw mut v.0 = 5; - } - let y = { v.0 } == 5; -} - -fn main() { - foo(); - bar(); -} diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index c6b8ad3571f3d..a44e65164af01 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -22,11 +22,11 @@ fn f() -> bool { let b = a; // We cannot propagate the place `a`. let r2 = &b; - Call(RET = cmp_ref(r1, r2), next) + Call(RET = cmp_ref(r1, r2), next, UnwindContinue()) } next = { // But we can propagate the value `a`. - Call(RET = opaque(b), ret) + Call(RET = opaque(b), ret, UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/copy-prop/calls.rs b/tests/mir-opt/copy-prop/calls.rs index 2970f5f0b8d42..bc6760707ccca 100644 --- a/tests/mir-opt/copy-prop/calls.rs +++ b/tests/mir-opt/copy-prop/calls.rs @@ -26,7 +26,7 @@ fn multiple_edges(t: bool) -> u8 { match t { true => bbt, _ => ret } } bbt = { - Call(x = dummy(13), ret) + Call(x = dummy(13), ret, UnwindContinue()) } ret = { // `x` is not assigned on the `bb0 -> ret` edge, diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs index 2077874ee9a76..8593d9fa9aba2 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.rs +++ b/tests/mir-opt/copy-prop/custom_move_arg.rs @@ -14,11 +14,11 @@ struct NotCopy(bool); fn f(_1: NotCopy) { mir!({ let _2 = _1; - Call(RET = opaque(Move(_1)), bb1) + Call(RET = opaque(Move(_1)), bb1, UnwindContinue()) } bb1 = { let _3 = Move(_2); - Call(RET = opaque(_3), bb2) + Call(RET = opaque(_3), bb2, UnwindContinue()) } bb2 = { Return() diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs index 8629d535bcf75..438a90dddd0cb 100644 --- a/tests/mir-opt/copy-prop/move_projection.rs +++ b/tests/mir-opt/copy-prop/move_projection.rs @@ -18,10 +18,10 @@ fn f(a: Foo) -> bool { let b = a; // This is a move out of a copy, so must become a copy of `a.0`. let c = Move(b.0); - Call(RET = opaque(Move(a)), bb1) + Call(RET = opaque(Move(a)), bb1, UnwindContinue()) } bb1 = { - Call(RET = opaque(Move(c)), ret) + Call(RET = opaque(Move(c)), ret, UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff index 9bfd46231c40e..8363783e64e0d 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-abort.diff @@ -28,16 +28,16 @@ scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { debug ptr => _6; - scope 14 (inlined ptr::mut_ptr::::is_null) { + scope 14 (inlined std::ptr::mut_ptr::::is_null) { debug self => _6; let mut _9: *mut u8; scope 15 { - scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _9; - scope 17 (inlined ptr::mut_ptr::::addr) { + scope 17 (inlined std::ptr::mut_ptr::::addr) { debug self => _9; scope 18 { - scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _9; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff index dba50b1428eba..19326b6a93355 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.32bit.panic-unwind.diff @@ -28,16 +28,16 @@ scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { debug ptr => _6; - scope 14 (inlined ptr::mut_ptr::::is_null) { + scope 14 (inlined std::ptr::mut_ptr::::is_null) { debug self => _6; let mut _9: *mut u8; scope 15 { - scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _9; - scope 17 (inlined ptr::mut_ptr::::addr) { + scope 17 (inlined std::ptr::mut_ptr::::addr) { debug self => _9; scope 18 { - scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _9; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff index 33fe4628d83e5..0d1e2430ce34b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-abort.diff @@ -28,16 +28,16 @@ scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { debug ptr => _6; - scope 14 (inlined ptr::mut_ptr::::is_null) { + scope 14 (inlined std::ptr::mut_ptr::::is_null) { debug self => _6; let mut _9: *mut u8; scope 15 { - scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _9; - scope 17 (inlined ptr::mut_ptr::::addr) { + scope 17 (inlined std::ptr::mut_ptr::::addr) { debug self => _9; scope 18 { - scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _9; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff index b2d561911de52..35f1e5ba796ef 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.ConstProp.64bit.panic-unwind.diff @@ -28,16 +28,16 @@ scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { debug ptr => _6; - scope 14 (inlined ptr::mut_ptr::::is_null) { + scope 14 (inlined std::ptr::mut_ptr::::is_null) { debug self => _6; let mut _9: *mut u8; scope 15 { - scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _9; - scope 17 (inlined ptr::mut_ptr::::addr) { + scope 17 (inlined std::ptr::mut_ptr::::addr) { debug self => _9; scope 18 { - scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _9; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 1751b0de2f1b1..ddfe2e8c83119 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -28,16 +28,16 @@ scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { debug ptr => _6; - scope 14 (inlined ptr::mut_ptr::::is_null) { + scope 14 (inlined std::ptr::mut_ptr::::is_null) { debug self => _6; let mut _9: *mut u8; scope 15 { - scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _9; - scope 17 (inlined ptr::mut_ptr::::addr) { + scope 17 (inlined std::ptr::mut_ptr::::addr) { debug self => _9; scope 18 { - scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _9; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 858a9d33ddffe..861295faa5a16 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -28,16 +28,16 @@ scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { debug ptr => _6; - scope 14 (inlined ptr::mut_ptr::::is_null) { + scope 14 (inlined std::ptr::mut_ptr::::is_null) { debug self => _6; let mut _9: *mut u8; scope 15 { - scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _9; - scope 17 (inlined ptr::mut_ptr::::addr) { + scope 17 (inlined std::ptr::mut_ptr::::addr) { debug self => _9; scope 18 { - scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _9; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 517070420754e..cbb639edc53a6 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -28,16 +28,16 @@ scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { debug ptr => _6; - scope 14 (inlined ptr::mut_ptr::::is_null) { + scope 14 (inlined std::ptr::mut_ptr::::is_null) { debug self => _6; let mut _9: *mut u8; scope 15 { - scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _9; - scope 17 (inlined ptr::mut_ptr::::addr) { + scope 17 (inlined std::ptr::mut_ptr::::addr) { debug self => _9; scope 18 { - scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _9; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 9141a6c67bee0..656846e9f976c 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -28,16 +28,16 @@ scope 12 { scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { debug ptr => _6; - scope 14 (inlined ptr::mut_ptr::::is_null) { + scope 14 (inlined std::ptr::mut_ptr::::is_null) { debug self => _6; let mut _9: *mut u8; scope 15 { - scope 16 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _9; - scope 17 (inlined ptr::mut_ptr::::addr) { + scope 17 (inlined std::ptr::mut_ptr::::addr) { debug self => _9; scope 18 { - scope 19 (inlined ptr::mut_ptr::::cast::<()>) { + scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _9; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index d502b19823995..053981abea3ec 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -118,7 +118,7 @@ } ALLOC2 (static: RC, size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index 5d69572b50744..d862bd93ff577 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -118,7 +118,7 @@ } ALLOC2 (static: RC, size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff index 2d4591ea2d3d8..09fc48043b9c8 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff @@ -8,7 +8,7 @@ let mut _3: u8; scope 1 { } - scope 2 (inlined ::add) { + scope 2 (inlined #[track_caller] ::add) { debug self => _2; debug other => _3; let mut _4: (u8, bool); diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index e99ac782a2ff0..c0b26080f56fe 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -8,7 +8,7 @@ let mut _3: u8; scope 1 { } - scope 2 (inlined ::add) { + scope 2 (inlined #[track_caller] ::add) { debug self => _2; debug other => _3; let mut _4: (u8, bool); diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff index cc96cbef2f519..9b0093c454e17 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-abort.diff @@ -30,7 +30,7 @@ StorageLive(_4); StorageLive(_5); _5 = _3; - _4 = ptr::mut_ptr::::add(move _5, const 1_usize) -> [return: bb1, unwind unreachable]; + _4 = std::ptr::mut_ptr::::add(move _5, const 1_usize) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff index ebeb8619d7300..635a214251bcc 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.panic-unwind.diff @@ -30,7 +30,7 @@ StorageLive(_4); StorageLive(_5); _5 = _3; - _4 = ptr::mut_ptr::::add(move _5, const 1_usize) -> [return: bb1, unwind continue]; + _4 = std::ptr::mut_ptr::::add(move _5, const 1_usize) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 8499d0a89c37c..0f461f515fdd0 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -220,11 +220,11 @@ } ALLOC5 (static: BIG_STAT, size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } ALLOC0 (size: 20, align: 4) { - 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ 02 00 00 00 │ ....#...╾──╼.... + 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ 02 00 00 00 │ ....#...╾──╼.... 0x10 │ 00 00 a4 42 │ ...B } @@ -233,11 +233,11 @@ } ALLOC4 (static: SMALL_STAT, size: 4, align: 4) { - ╾ALLOC2╼ │ ╾──╼ + ╾ALLOC2╼ │ ╾──╼ } ALLOC2 (size: 20, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ 01 00 00 00 │ ....░░░░╾──╼.... + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ 01 00 00 00 │ ....░░░░╾──╼.... 0x10 │ 00 00 10 41 │ ...A } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index 01ec3f623d1af..3c40ec8bfb450 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -220,11 +220,11 @@ } ALLOC5 (static: BIG_STAT, size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } ALLOC0 (size: 32, align: 8) { - 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ │ ....#...╾──────╼ + 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ │ ....#...╾──────╼ 0x10 │ 02 00 00 00 00 00 00 00 00 00 a4 42 __ __ __ __ │ ...........B░░░░ } @@ -233,11 +233,11 @@ } ALLOC4 (static: SMALL_STAT, size: 8, align: 8) { - ╾ALLOC2╼ │ ╾──────╼ + ╾ALLOC2╼ │ ╾──────╼ } ALLOC2 (size: 32, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ │ ....░░░░╾──────╼ + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ │ ....░░░░╾──────╼ 0x10 │ 01 00 00 00 00 00 00 00 00 00 10 41 __ __ __ __ │ ...........A░░░░ } diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index dcd15fb2b09ec..b2eb64756f9ac 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -28,7 +28,7 @@ struct Packed { fn move_packed(packed: Packed) { mir!( { - Call(RET = use_both(0, packed.y), ret) + Call(RET = use_both(0, packed.y), ret, UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index 8896f5ff345b2..c9ad06a9da266 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.rs +++ b/tests/mir-opt/dead-store-elimination/cycle.rs @@ -20,7 +20,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) { mir!( let condition: bool; { - Call(condition = cond(), bb1) + Call(condition = cond(), bb1, UnwindContinue()) } bb1 = { match condition { true => bb2, _ => ret } @@ -30,7 +30,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) { z = y; y = x; x = temp; - Call(condition = cond(), bb1) + Call(condition = cond(), bb1, UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 10a66ced026e4..6e082acdbd393 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -529,31 +529,31 @@ fn duplicate_slice() -> (bool, bool) { // CHECK: [[a:_.*]] = (const "a",); // CHECK: [[au:_.*]] = ([[a]].0: &str) as u128 (Transmute); let a = ("a",); - Call(au = transmute::<_, u128>(a.0), bb1) + Call(au = transmute::<_, u128>(a.0), bb1, UnwindContinue()) } bb1 = { // CHECK: [[c:_.*]] = identity::<&str>(([[a]].0: &str)) - Call(c = identity(a.0), bb2) + Call(c = identity(a.0), bb2, UnwindContinue()) } bb2 = { // CHECK: [[cu:_.*]] = [[c]] as u128 (Transmute); - Call(cu = transmute::<_, u128>(c), bb3) + Call(cu = transmute::<_, u128>(c), bb3, UnwindContinue()) } bb3 = { // This slice is different from `a.0`. Hence `bu` is not `au`. // CHECK: [[b:_.*]] = const "a"; // CHECK: [[bu:_.*]] = [[b]] as u128 (Transmute); let b = "a"; - Call(bu = transmute::<_, u128>(b), bb4) + Call(bu = transmute::<_, u128>(b), bb4, UnwindContinue()) } bb4 = { // This returns a copy of `b`, which is not `a`. // CHECK: [[d:_.*]] = identity::<&str>([[b]]) - Call(d = identity(b), bb5) + Call(d = identity(b), bb5, UnwindContinue()) } bb5 = { // CHECK: [[du:_.*]] = [[d]] as u128 (Transmute); - Call(du = transmute::<_, u128>(d), bb6) + Call(du = transmute::<_, u128>(d), bb6, UnwindContinue()) } bb6 = { // `direct` must not fold to `true`, as `indirect` will not. diff --git a/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-abort.diff b/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-abort.diff index 217c8b802caac..3ffe2ee0c0b94 100644 --- a/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-abort.diff @@ -69,58 +69,58 @@ + } + + bb2: { ++ _4 = <() as F>::call() -> [return: bb1, unwind unreachable]; ++ } ++ ++ bb3: { + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); -+ _3 = <() as F>::call() -> [return: bb3, unwind unreachable]; ++ _3 = <() as F>::call() -> [return: bb2, unwind unreachable]; + } + -+ bb3: { -+ _4 = <() as F>::call() -> [return: bb1, unwind unreachable]; ++ bb4: { ++ _7 = <() as E>::call() -> [return: bb3, unwind unreachable]; + } + -+ bb4: { ++ bb5: { + StorageDead(_10); + StorageDead(_9); + StorageDead(_8); -+ _6 = <() as E>::call() -> [return: bb5, unwind unreachable]; ++ _6 = <() as E>::call() -> [return: bb4, unwind unreachable]; + } + -+ bb5: { -+ _7 = <() as E>::call() -> [return: bb2, unwind unreachable]; ++ bb6: { ++ _10 = <() as D>::call() -> [return: bb5, unwind unreachable]; + } + -+ bb6: { ++ bb7: { + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); -+ _9 = <() as D>::call() -> [return: bb7, unwind unreachable]; ++ _9 = <() as D>::call() -> [return: bb6, unwind unreachable]; + } + -+ bb7: { -+ _10 = <() as D>::call() -> [return: bb4, unwind unreachable]; ++ bb8: { ++ _13 = <() as C>::call() -> [return: bb7, unwind unreachable]; + } + -+ bb8: { ++ bb9: { + StorageDead(_16); + StorageDead(_15); + StorageDead(_14); -+ _12 = <() as C>::call() -> [return: bb9, unwind unreachable]; ++ _12 = <() as C>::call() -> [return: bb8, unwind unreachable]; + } + -+ bb9: { -+ _13 = <() as C>::call() -> [return: bb6, unwind unreachable]; ++ bb10: { ++ _16 = <() as B>::call() -> [return: bb9, unwind unreachable]; + } + -+ bb10: { ++ bb11: { + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); -+ _15 = <() as B>::call() -> [return: bb11, unwind unreachable]; -+ } -+ -+ bb11: { -+ _16 = <() as B>::call() -> [return: bb8, unwind unreachable]; ++ _15 = <() as B>::call() -> [return: bb10, unwind unreachable]; + } + + bb12: { @@ -128,7 +128,7 @@ + } + + bb13: { -+ _19 = <() as A>::call() -> [return: bb10, unwind unreachable]; ++ _19 = <() as A>::call() -> [return: bb11, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-unwind.diff index 0a4ce40c529d9..3f334779e18f8 100644 --- a/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/exponential_runtime.main.Inline.panic-unwind.diff @@ -69,58 +69,58 @@ + } + + bb2: { ++ _4 = <() as F>::call() -> [return: bb1, unwind continue]; ++ } ++ ++ bb3: { + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); -+ _3 = <() as F>::call() -> [return: bb3, unwind continue]; ++ _3 = <() as F>::call() -> [return: bb2, unwind continue]; + } + -+ bb3: { -+ _4 = <() as F>::call() -> [return: bb1, unwind continue]; ++ bb4: { ++ _7 = <() as E>::call() -> [return: bb3, unwind continue]; + } + -+ bb4: { ++ bb5: { + StorageDead(_10); + StorageDead(_9); + StorageDead(_8); -+ _6 = <() as E>::call() -> [return: bb5, unwind continue]; ++ _6 = <() as E>::call() -> [return: bb4, unwind continue]; + } + -+ bb5: { -+ _7 = <() as E>::call() -> [return: bb2, unwind continue]; ++ bb6: { ++ _10 = <() as D>::call() -> [return: bb5, unwind continue]; + } + -+ bb6: { ++ bb7: { + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); -+ _9 = <() as D>::call() -> [return: bb7, unwind continue]; ++ _9 = <() as D>::call() -> [return: bb6, unwind continue]; + } + -+ bb7: { -+ _10 = <() as D>::call() -> [return: bb4, unwind continue]; ++ bb8: { ++ _13 = <() as C>::call() -> [return: bb7, unwind continue]; + } + -+ bb8: { ++ bb9: { + StorageDead(_16); + StorageDead(_15); + StorageDead(_14); -+ _12 = <() as C>::call() -> [return: bb9, unwind continue]; ++ _12 = <() as C>::call() -> [return: bb8, unwind continue]; + } + -+ bb9: { -+ _13 = <() as C>::call() -> [return: bb6, unwind continue]; ++ bb10: { ++ _16 = <() as B>::call() -> [return: bb9, unwind continue]; + } + -+ bb10: { ++ bb11: { + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); -+ _15 = <() as B>::call() -> [return: bb11, unwind continue]; -+ } -+ -+ bb11: { -+ _16 = <() as B>::call() -> [return: bb8, unwind continue]; ++ _15 = <() as B>::call() -> [return: bb10, unwind continue]; + } + + bb12: { @@ -128,7 +128,7 @@ + } + + bb13: { -+ _19 = <() as A>::call() -> [return: bb10, unwind continue]; ++ _19 = <() as A>::call() -> [return: bb11, unwind continue]; } } diff --git a/tests/mir-opt/inline/indirect_destination.rs b/tests/mir-opt/inline/indirect_destination.rs new file mode 100644 index 0000000000000..2842e23366e00 --- /dev/null +++ b/tests/mir-opt/inline/indirect_destination.rs @@ -0,0 +1,42 @@ +// Test for inlining with an indirect destination place. +// +// unit-test: Inline +// edition: 2021 +// needs-unwind +#![crate_type = "lib"] +#![feature(custom_mir, core_intrinsics)] +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "initial")] +// CHECK-LABEL: fn f( +// CHECK: bb1: { +// CHECK-NEXT: StorageLive([[A:.*]]); +// CHECK-NEXT: [[A]] = &mut (*_1); +// CHECK-NEXT: StorageLive([[B:.*]]); +// CHECK-NEXT: [[B]] = const 42_u8; +// CHECK-NEXT: (*[[A]]) = move [[B]]; +// CHECK-NEXT: StorageDead([[B]]); +// CHECK-NEXT: StorageDead([[A]]); +// CHECK-NEXT: goto -> bb1; +// CHECK-NEXT: } +pub fn f(a: *mut u8) { + mir! { + { + Goto(bb1) + } + bb1 = { + Call(*a = g(), bb1, UnwindUnreachable()) + } + } +} + +#[custom_mir(dialect = "runtime", phase = "initial")] +#[inline(always)] +fn g() -> u8 { + mir! { + { + RET = 42; + Return() + } + } +} diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 40eeda5390879..42dd7ba55cf45 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -50,20 +50,20 @@ bb1: { - _3 = &mut _4; - _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind unreachable]; -+ StorageDead(_7); -+ StorageDead(_6); -+ StorageDead(_5); -+ StorageDead(_2); -+ drop(_4) -> [return: bb2, unwind unreachable]; ++ StorageDead(_4); ++ _0 = const (); ++ StorageDead(_1); ++ return; } bb2: { - StorageDead(_3); - _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; -+ StorageDead(_4); -+ _0 = const (); -+ StorageDead(_1); -+ return; ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_5); ++ StorageDead(_2); ++ drop(_4) -> [return: bb1, unwind unreachable]; } bb3: { @@ -90,7 +90,7 @@ + bb6: { + _1 = CoroutineState::::Yielded(move _8); + discriminant((*_6)) = 3; -+ goto -> bb1; ++ goto -> bb2; + } + + bb7: { @@ -102,7 +102,7 @@ + StorageDead(_8); + _1 = CoroutineState::::Complete(_5); + discriminant((*_6)) = 1; -+ goto -> bb1; ++ goto -> bb2; + } + + bb9: { diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index fdb42bf3d8a0e..7b8958c13fc5d 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -34,18 +34,10 @@ StorageLive(_3); StorageLive(_4); - _4 = g() -> [return: bb1, unwind continue]; -- } -- -- bb1: { + _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; - _3 = &mut _4; -- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind: bb5]; -- } -- -- bb2: { ++ _3 = &mut _4; + _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: move _3 }; - StorageDead(_3); -- _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; ++ StorageDead(_3); + StorageLive(_5); + _5 = const false; + StorageLive(_6); @@ -55,40 +47,50 @@ + switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; } + bb1: { +- _3 = &mut _4; +- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind: bb5]; ++ StorageDead(_4); ++ _0 = const (); ++ StorageDead(_1); ++ return; + } + +- bb2: { +- StorageDead(_3); +- _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; ++ bb2 (cleanup): { ++ drop(_4) -> [return: bb3, unwind terminate(cleanup)]; + } + - bb3: { -+ bb1: { -+ StorageDead(_7); -+ StorageDead(_6); -+ StorageDead(_5); - StorageDead(_2); +- StorageDead(_2); - drop(_4) -> [return: bb4, unwind: bb6]; -+ drop(_4) -> [return: bb2, unwind: bb4]; ++ bb3 (cleanup): { ++ resume; } -- bb4: { -+ bb2: { - StorageDead(_4); - _0 = const (); - StorageDead(_1); - return; + bb4: { +- StorageDead(_4); +- _0 = const (); +- StorageDead(_1); +- return; ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_5); ++ StorageDead(_2); ++ drop(_4) -> [return: bb1, unwind: bb3]; } - bb5 (cleanup): { - drop(_4) -> [return: bb6, unwind terminate(cleanup)]; -+ bb3 (cleanup): { -+ drop(_4) -> [return: bb4, unwind terminate(cleanup)]; - } - -- bb6 (cleanup): { -+ bb4 (cleanup): { - resume; -+ } -+ + bb5: { + StorageLive(_8); + switchInt(_5) -> [0: bb6, otherwise: bb7]; -+ } -+ + } + +- bb6 (cleanup): { +- resume; + bb6: { + _8 = const 13_i32; + goto -> bb8; @@ -102,11 +104,11 @@ + bb8: { + _1 = CoroutineState::::Yielded(move _8); + discriminant((*_6)) = 3; -+ goto -> bb1; ++ goto -> bb4; + } + + bb9: { -+ assert(const false, "coroutine resumed after completion") -> [success: bb9, unwind: bb3]; ++ assert(const false, "coroutine resumed after completion") -> [success: bb9, unwind: bb2]; + } + + bb10: { @@ -114,7 +116,7 @@ + StorageDead(_8); + _1 = CoroutineState::::Complete(_5); + discriminant((*_6)) = 1; -+ goto -> bb1; ++ goto -> bb4; + } + + bb11: { diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff deleted file mode 100644 index b90e0505c54e2..0000000000000 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff +++ /dev/null @@ -1,209 +0,0 @@ -- // MIR for `main` before Inline -+ // MIR for `main` after Inline - - fn main() -> () { - let mut _0: (); - let _1: std::boxed::Box>; - let mut _2: std::vec::Vec; - scope 1 { - debug _x => _1; - } -+ scope 2 (inlined Vec::::new) { -+ let mut _3: alloc::raw_vec::RawVec; -+ } -+ scope 3 (inlined Box::>::new) { -+ debug x => _2; -+ let mut _4: usize; -+ let mut _5: usize; -+ let mut _6: *mut u8; -+ let mut _7: *const std::vec::Vec; -+ scope 4 { -+ scope 5 (inlined alloc::alloc::exchange_malloc) { -+ debug size => _4; -+ debug align => _5; -+ let _8: std::alloc::Layout; -+ let mut _9: std::result::Result, std::alloc::AllocError>; -+ let mut _10: isize; -+ let mut _12: !; -+ scope 6 { -+ debug layout => _8; -+ let _11: std::ptr::NonNull<[u8]>; -+ let mut _13: &std::alloc::Global; -+ scope 8 { -+ debug ptr => _11; -+ scope 18 (inlined NonNull::<[u8]>::as_mut_ptr) { -+ debug self => _11; -+ let mut _15: std::ptr::NonNull; -+ scope 19 (inlined NonNull::<[u8]>::as_non_null_ptr) { -+ debug self => _11; -+ let mut _16: *mut u8; -+ let mut _17: *mut [u8]; -+ scope 20 { -+ scope 21 (inlined NonNull::<[u8]>::as_ptr) { -+ debug self => _11; -+ let mut _18: *const [u8]; -+ } -+ scope 22 (inlined ptr::mut_ptr::::as_mut_ptr) { -+ debug self => _17; -+ } -+ scope 23 (inlined NonNull::::new_unchecked) { -+ debug ptr => _16; -+ let mut _19: *const u8; -+ scope 24 { -+ scope 25 (inlined NonNull::::new_unchecked::runtime::) { -+ debug ptr => _16; -+ scope 26 (inlined ptr::mut_ptr::::is_null) { -+ debug self => _16; -+ let mut _20: *mut u8; -+ scope 27 { -+ scope 28 (inlined ptr::mut_ptr::::is_null::runtime_impl) { -+ debug ptr => _20; -+ scope 29 (inlined ptr::mut_ptr::::addr) { -+ debug self => _20; -+ scope 30 { -+ scope 31 (inlined ptr::mut_ptr::::cast::<()>) { -+ debug self => _20; -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ scope 32 (inlined NonNull::::as_ptr) { -+ debug self => _15; -+ let mut _21: *const u8; -+ } -+ } -+ } -+ scope 17 (inlined ::allocate) { -+ debug self => const _; -+ debug layout => _8; -+ } -+ } -+ scope 7 { -+ scope 9 (inlined Layout::from_size_align_unchecked) { -+ debug size => _4; -+ debug align => _5; -+ let mut _14: std::ptr::Alignment; -+ scope 10 { -+ scope 11 (inlined std::ptr::Alignment::new_unchecked) { -+ debug align => _5; -+ scope 12 { -+ scope 14 (inlined std::ptr::Alignment::new_unchecked::runtime) { -+ debug align => _5; -+ scope 15 (inlined core::num::::is_power_of_two) { -+ debug self => _5; -+ scope 16 (inlined core::num::::count_ones) { -+ debug self => _5; -+ } -+ } -+ } -+ } -+ scope 13 { -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } - - bb0: { - StorageLive(_1); - StorageLive(_2); -- _2 = Vec::::new() -> [return: bb1, unwind unreachable]; -+ StorageLive(_3); -+ _3 = const _; -+ _2 = Vec:: { buf: move _3, len: const 0_usize }; -+ StorageDead(_3); -+ StorageLive(_4); -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ _4 = SizeOf(std::vec::Vec); -+ _5 = AlignOf(std::vec::Vec); -+ StorageLive(_8); -+ StorageLive(_10); -+ StorageLive(_11); -+ StorageLive(_12); -+ StorageLive(_13); -+ StorageLive(_14); -+ _14 = _5 as std::ptr::Alignment (Transmute); -+ _8 = Layout { size: _4, align: move _14 }; -+ StorageDead(_14); -+ StorageLive(_9); -+ _13 = const _; -+ _9 = std::alloc::Global::alloc_impl(move _13, _8, const false) -> [return: bb5, unwind unreachable]; - } - - bb1: { -- _1 = Box::>::new(move _2) -> [return: bb2, unwind unreachable]; -+ StorageDead(_1); -+ return; - } - - bb2: { -+ _12 = handle_alloc_error(move _8) -> unwind unreachable; -+ } -+ -+ bb3: { -+ unreachable; -+ } -+ -+ bb4: { -+ _11 = ((_9 as Ok).0: std::ptr::NonNull<[u8]>); -+ StorageLive(_15); -+ StorageLive(_16); -+ StorageLive(_17); -+ StorageLive(_18); -+ _18 = (_11.0: *const [u8]); -+ _17 = move _18 as *mut [u8] (PtrToPtr); -+ StorageDead(_18); -+ _16 = _17 as *mut u8 (PtrToPtr); -+ StorageDead(_17); -+ StorageLive(_19); -+ StorageLive(_20); -+ _19 = _16 as *const u8 (PointerCoercion(MutToConstPointer)); -+ _15 = NonNull:: { pointer: _19 }; -+ StorageDead(_20); -+ StorageDead(_19); -+ StorageDead(_16); -+ StorageLive(_21); -+ _21 = (_15.0: *const u8); -+ _6 = move _21 as *mut u8 (PtrToPtr); -+ StorageDead(_21); -+ StorageDead(_15); -+ StorageDead(_9); -+ StorageDead(_13); -+ StorageDead(_12); -+ StorageDead(_11); -+ StorageDead(_10); -+ StorageDead(_8); -+ _1 = ShallowInitBox(move _6, std::vec::Vec); -+ _7 = (((_1.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); -+ (*_7) = move _2; -+ StorageDead(_7); -+ StorageDead(_6); -+ StorageDead(_5); -+ StorageDead(_4); - StorageDead(_2); - _0 = const (); -- drop(_1) -> [return: bb3, unwind unreachable]; -+ drop(_1) -> [return: bb1, unwind unreachable]; - } - -- bb3: { -- StorageDead(_1); -- return; -+ bb5: { -+ _10 = discriminant(_9); -+ switchInt(move _10) -> [0: bb4, 1: bb2, otherwise: bb3]; - } - } - diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff deleted file mode 100644 index f9c637caa18a8..0000000000000 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ /dev/null @@ -1,222 +0,0 @@ -- // MIR for `main` before Inline -+ // MIR for `main` after Inline - - fn main() -> () { - let mut _0: (); - let _1: std::boxed::Box>; - let mut _2: std::vec::Vec; - scope 1 { - debug _x => _1; - } -+ scope 2 (inlined Vec::::new) { -+ let mut _3: alloc::raw_vec::RawVec; -+ } -+ scope 3 (inlined Box::>::new) { -+ debug x => _2; -+ let mut _4: usize; -+ let mut _5: usize; -+ let mut _6: *mut u8; -+ let mut _7: *const std::vec::Vec; -+ scope 4 { -+ scope 5 (inlined alloc::alloc::exchange_malloc) { -+ debug size => _4; -+ debug align => _5; -+ let _8: std::alloc::Layout; -+ let mut _9: std::result::Result, std::alloc::AllocError>; -+ let mut _10: isize; -+ let mut _12: !; -+ scope 6 { -+ debug layout => _8; -+ let _11: std::ptr::NonNull<[u8]>; -+ let mut _13: &std::alloc::Global; -+ scope 8 { -+ debug ptr => _11; -+ scope 18 (inlined NonNull::<[u8]>::as_mut_ptr) { -+ debug self => _11; -+ let mut _15: std::ptr::NonNull; -+ scope 19 (inlined NonNull::<[u8]>::as_non_null_ptr) { -+ debug self => _11; -+ let mut _16: *mut u8; -+ let mut _17: *mut [u8]; -+ scope 20 { -+ scope 21 (inlined NonNull::<[u8]>::as_ptr) { -+ debug self => _11; -+ let mut _18: *const [u8]; -+ } -+ scope 22 (inlined ptr::mut_ptr::::as_mut_ptr) { -+ debug self => _17; -+ } -+ scope 23 (inlined NonNull::::new_unchecked) { -+ debug ptr => _16; -+ let mut _19: *const u8; -+ scope 24 { -+ scope 25 (inlined NonNull::::new_unchecked::runtime::) { -+ debug ptr => _16; -+ scope 26 (inlined ptr::mut_ptr::::is_null) { -+ debug self => _16; -+ let mut _20: *mut u8; -+ scope 27 { -+ scope 28 (inlined ptr::mut_ptr::::is_null::runtime_impl) { -+ debug ptr => _20; -+ scope 29 (inlined ptr::mut_ptr::::addr) { -+ debug self => _20; -+ scope 30 { -+ scope 31 (inlined ptr::mut_ptr::::cast::<()>) { -+ debug self => _20; -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ scope 32 (inlined NonNull::::as_ptr) { -+ debug self => _15; -+ let mut _21: *const u8; -+ } -+ } -+ } -+ scope 17 (inlined ::allocate) { -+ debug self => const _; -+ debug layout => _8; -+ } -+ } -+ scope 7 { -+ scope 9 (inlined Layout::from_size_align_unchecked) { -+ debug size => _4; -+ debug align => _5; -+ let mut _14: std::ptr::Alignment; -+ scope 10 { -+ scope 11 (inlined std::ptr::Alignment::new_unchecked) { -+ debug align => _5; -+ scope 12 { -+ scope 14 (inlined std::ptr::Alignment::new_unchecked::runtime) { -+ debug align => _5; -+ scope 15 (inlined core::num::::is_power_of_two) { -+ debug self => _5; -+ scope 16 (inlined core::num::::count_ones) { -+ debug self => _5; -+ } -+ } -+ } -+ } -+ scope 13 { -+ } -+ } -+ } -+ } -+ } -+ } -+ } -+ } - - bb0: { - StorageLive(_1); - StorageLive(_2); -- _2 = Vec::::new() -> [return: bb1, unwind continue]; -+ StorageLive(_3); -+ _3 = const _; -+ _2 = Vec:: { buf: move _3, len: const 0_usize }; -+ StorageDead(_3); -+ StorageLive(_4); -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ _4 = SizeOf(std::vec::Vec); -+ _5 = AlignOf(std::vec::Vec); -+ StorageLive(_8); -+ StorageLive(_10); -+ StorageLive(_11); -+ StorageLive(_12); -+ StorageLive(_13); -+ StorageLive(_14); -+ _14 = _5 as std::ptr::Alignment (Transmute); -+ _8 = Layout { size: _4, align: move _14 }; -+ StorageDead(_14); -+ StorageLive(_9); -+ _13 = const _; -+ _9 = std::alloc::Global::alloc_impl(move _13, _8, const false) -> [return: bb7, unwind: bb3]; - } - - bb1: { -- _1 = Box::>::new(move _2) -> [return: bb2, unwind: bb4]; -+ StorageDead(_1); -+ return; - } - -- bb2: { -- StorageDead(_2); -- _0 = const (); -- drop(_1) -> [return: bb3, unwind: bb4]; -+ bb2 (cleanup): { -+ resume; - } - -- bb3: { -- StorageDead(_1); -- return; -+ bb3 (cleanup): { -+ drop(_2) -> [return: bb2, unwind terminate(cleanup)]; - } - -- bb4 (cleanup): { -- resume; -+ bb4: { -+ _12 = handle_alloc_error(move _8) -> bb3; -+ } -+ -+ bb5: { -+ unreachable; -+ } -+ -+ bb6: { -+ _11 = ((_9 as Ok).0: std::ptr::NonNull<[u8]>); -+ StorageLive(_15); -+ StorageLive(_16); -+ StorageLive(_17); -+ StorageLive(_18); -+ _18 = (_11.0: *const [u8]); -+ _17 = move _18 as *mut [u8] (PtrToPtr); -+ StorageDead(_18); -+ _16 = _17 as *mut u8 (PtrToPtr); -+ StorageDead(_17); -+ StorageLive(_19); -+ StorageLive(_20); -+ _19 = _16 as *const u8 (PointerCoercion(MutToConstPointer)); -+ _15 = NonNull:: { pointer: _19 }; -+ StorageDead(_20); -+ StorageDead(_19); -+ StorageDead(_16); -+ StorageLive(_21); -+ _21 = (_15.0: *const u8); -+ _6 = move _21 as *mut u8 (PtrToPtr); -+ StorageDead(_21); -+ StorageDead(_15); -+ StorageDead(_9); -+ StorageDead(_13); -+ StorageDead(_12); -+ StorageDead(_11); -+ StorageDead(_10); -+ StorageDead(_8); -+ _1 = ShallowInitBox(move _6, std::vec::Vec); -+ _7 = (((_1.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); -+ (*_7) = move _2; -+ StorageDead(_7); -+ StorageDead(_6); -+ StorageDead(_5); -+ StorageDead(_4); -+ StorageDead(_2); -+ _0 = const (); -+ drop(_1) -> [return: bb1, unwind: bb2]; -+ } -+ -+ bb7: { -+ _10 = discriminant(_9); -+ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; - } - } - diff --git a/tests/mir-opt/inline/inline_into_box_place.rs b/tests/mir-opt/inline/inline_into_box_place.rs deleted file mode 100644 index 65f8e2916b630..0000000000000 --- a/tests/mir-opt/inline/inline_into_box_place.rs +++ /dev/null @@ -1,11 +0,0 @@ -// ignore-endian-big -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// ignore-debug MIR alignment checks in std alter the diff, breaking the test -// compile-flags: -Zmir-opt-level=4 -Zinline-mir-hint-threshold=200 - -// EMIT_MIR inline_into_box_place.main.Inline.diff -fn main() { - // CHECK-LABEL: fn main( - // CHECK: (inlined Box::>::new) - let _x: Box> = Box::new(Vec::new()); -} diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index f17c9ba3f9fc4..f50603a66a56f 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -60,16 +60,6 @@ } bb1: { - StorageDead(_12); - StorageDead(_11); - StorageDead(_10); - StorageDead(_4); - _5 = discriminant(_3); -- switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; -+ goto -> bb2; - } - - bb2: { StorageLive(_9); _9 = ((_3 as Continue).0: i32); _2 = _9; @@ -77,14 +67,14 @@ _0 = Result::::Ok(move _2); StorageDead(_2); StorageDead(_3); - goto -> bb5; + goto -> bb4; } - bb3: { + bb2: { unreachable; } - bb4: { + bb3: { StorageLive(_6); _6 = ((_3 as Break).0: std::result::Result); StorageLive(_8); @@ -100,20 +90,30 @@ StorageDead(_6); StorageDead(_2); StorageDead(_3); - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { return; } + bb5: { + StorageDead(_12); + StorageDead(_11); + StorageDead(_10); + StorageDead(_4); + _5 = discriminant(_3); +- switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; ++ goto -> bb1; + } + bb6: { _12 = move ((_4 as Err).0: i32); StorageLive(_13); _13 = Result::::Err(move _12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); -- goto -> bb1; +- goto -> bb5; + goto -> bb9; } @@ -124,7 +124,7 @@ bb8: { _11 = move ((_4 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(move _11); - goto -> bb1; + goto -> bb5; + } + + bb9: { @@ -133,7 +133,7 @@ + StorageDead(_10); + StorageDead(_4); + _5 = discriminant(_3); -+ goto -> bb4; ++ goto -> bb3; } } diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index f17c9ba3f9fc4..f50603a66a56f 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -60,16 +60,6 @@ } bb1: { - StorageDead(_12); - StorageDead(_11); - StorageDead(_10); - StorageDead(_4); - _5 = discriminant(_3); -- switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; -+ goto -> bb2; - } - - bb2: { StorageLive(_9); _9 = ((_3 as Continue).0: i32); _2 = _9; @@ -77,14 +67,14 @@ _0 = Result::::Ok(move _2); StorageDead(_2); StorageDead(_3); - goto -> bb5; + goto -> bb4; } - bb3: { + bb2: { unreachable; } - bb4: { + bb3: { StorageLive(_6); _6 = ((_3 as Break).0: std::result::Result); StorageLive(_8); @@ -100,20 +90,30 @@ StorageDead(_6); StorageDead(_2); StorageDead(_3); - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { return; } + bb5: { + StorageDead(_12); + StorageDead(_11); + StorageDead(_10); + StorageDead(_4); + _5 = discriminant(_3); +- switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; ++ goto -> bb1; + } + bb6: { _12 = move ((_4 as Err).0: i32); StorageLive(_13); _13 = Result::::Err(move _12); _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); -- goto -> bb1; +- goto -> bb5; + goto -> bb9; } @@ -124,7 +124,7 @@ bb8: { _11 = move ((_4 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(move _11); - goto -> bb1; + goto -> bb5; + } + + bb9: { @@ -133,7 +133,7 @@ + StorageDead(_10); + StorageDead(_4); + _5 = discriminant(_3); -+ goto -> bb4; ++ goto -> bb3; } } diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index 852dcd0db0112..66e5c5d3c11cb 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -52,19 +52,19 @@ fn identity(x: Result) -> Result { // CHECK: [[x:_.*]] = _1; // CHECK: switchInt(move {{_.*}}) -> [0: bb8, 1: bb6, otherwise: bb7]; // CHECK: bb1: { - // CHECK: goto -> bb2; - // CHECK: bb2: { // CHECK: {{_.*}} = (([[controlflow:_.*]] as Continue).0: i32); // CHECK: _0 = Result::::Ok( - // CHECK: goto -> bb5; - // CHECK: bb3: { + // CHECK: goto -> bb4; + // CHECK: bb2: { // CHECK: unreachable; - // CHECK: bb4: { + // CHECK: bb3: { // CHECK: {{_.*}} = (([[controlflow]] as Break).0: std::result::Result); // CHECK: _0 = Result::::Err( - // CHECK: goto -> bb5; - // CHECK: bb5: { + // CHECK: goto -> bb4; + // CHECK: bb4: { // CHECK: return; + // CHECK: bb5: { + // CHECK: goto -> bb1; // CHECK: bb6: { // CHECK: {{_.*}} = move (([[x]] as Err).0: i32); // CHECK: [[controlflow]] = ControlFlow::, i32>::Break( @@ -74,9 +74,9 @@ fn identity(x: Result) -> Result { // CHECK: bb8: { // CHECK: {{_.*}} = move (([[x]] as Ok).0: i32); // CHECK: [[controlflow]] = ControlFlow::, i32>::Continue( - // CHECK: goto -> bb1; + // CHECK: goto -> bb5; // CHECK: bb9: { - // CHECK: goto -> bb4; + // CHECK: goto -> bb3; Ok(x?) } diff --git a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.panic-abort.diff deleted file mode 100644 index 194478560e929..0000000000000 --- a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.panic-abort.diff +++ /dev/null @@ -1,48 +0,0 @@ -- // MIR for `option_payload` before LowerIntrinsics -+ // MIR for `option_payload` after LowerIntrinsics - - fn option_payload(_1: &Option, _2: &Option) -> () { - debug o => _1; - debug p => _2; - let mut _0: (); - let mut _4: *const std::option::Option; - let mut _6: *const std::option::Option; - scope 1 { - let _3: *const usize; - scope 2 { - debug _x => _3; - let _5: *const std::string::String; - scope 3 { - debug _y => _5; - } - } - } - - bb0: { - StorageLive(_3); - StorageLive(_4); - _4 = &raw const (*_1); -- _3 = option_payload_ptr::(move _4) -> [return: bb1, unwind unreachable]; -+ _3 = &raw const (((*_4) as Some).0: usize); -+ goto -> bb1; - } - - bb1: { - StorageDead(_4); - StorageLive(_5); - StorageLive(_6); - _6 = &raw const (*_2); -- _5 = option_payload_ptr::(move _6) -> [return: bb2, unwind unreachable]; -+ _5 = &raw const (((*_6) as Some).0: std::string::String); -+ goto -> bb2; - } - - bb2: { - StorageDead(_6); - _0 = const (); - StorageDead(_5); - StorageDead(_3); - return; - } - } - diff --git a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.panic-unwind.diff deleted file mode 100644 index 194478560e929..0000000000000 --- a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.panic-unwind.diff +++ /dev/null @@ -1,48 +0,0 @@ -- // MIR for `option_payload` before LowerIntrinsics -+ // MIR for `option_payload` after LowerIntrinsics - - fn option_payload(_1: &Option, _2: &Option) -> () { - debug o => _1; - debug p => _2; - let mut _0: (); - let mut _4: *const std::option::Option; - let mut _6: *const std::option::Option; - scope 1 { - let _3: *const usize; - scope 2 { - debug _x => _3; - let _5: *const std::string::String; - scope 3 { - debug _y => _5; - } - } - } - - bb0: { - StorageLive(_3); - StorageLive(_4); - _4 = &raw const (*_1); -- _3 = option_payload_ptr::(move _4) -> [return: bb1, unwind unreachable]; -+ _3 = &raw const (((*_4) as Some).0: usize); -+ goto -> bb1; - } - - bb1: { - StorageDead(_4); - StorageLive(_5); - StorageLive(_6); - _6 = &raw const (*_2); -- _5 = option_payload_ptr::(move _6) -> [return: bb2, unwind unreachable]; -+ _5 = &raw const (((*_6) as Some).0: std::string::String); -+ goto -> bb2; - } - - bb2: { - StorageDead(_6); - _0 = const (); - StorageDead(_5); - StorageDead(_3); - return; - } - } - diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs index 913605cc2b2b6..cba2bc18d867b 100644 --- a/tests/mir-opt/lower_intrinsics.rs +++ b/tests/mir-opt/lower_intrinsics.rs @@ -222,18 +222,6 @@ pub fn write_via_move_string(r: &mut String, v: String) { pub enum Never {} -// EMIT_MIR lower_intrinsics.option_payload.LowerIntrinsics.diff -pub fn option_payload(o: &Option, p: &Option) { - // CHECK-LABEL: fn option_payload( - // CHECK: {{_.*}} = &raw const (((*{{_.*}}) as Some).0: usize); - // CHECK: {{_.*}} = &raw const (((*{{_.*}}) as Some).0: std::string::String); - - unsafe { - let _x = core::intrinsics::option_payload_ptr(o); - let _y = core::intrinsics::option_payload_ptr(p); - } -} - // EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff pub unsafe fn ptr_offset(p: *const i32, d: isize) -> *const i32 { // CHECK-LABEL: fn ptr_offset( diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 2989582d03827..b4bd45ba597f2 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -80,8 +80,8 @@ _6 = &(_2.1: bool); StorageLive(_8); _8 = &(_2.2: std::string::String); -- _3 = &shallow (_2.0: bool); -- _4 = &shallow (_2.1: bool); +- _3 = &fake (_2.0: bool); +- _4 = &fake (_2.1: bool); StorageLive(_9); StorageLive(_10); _10 = _1; @@ -137,8 +137,8 @@ _6 = &(_2.0: bool); StorageLive(_8); _8 = &(_2.2: std::string::String); -- _3 = &shallow (_2.0: bool); -- _4 = &shallow (_2.1: bool); +- _3 = &fake (_2.0: bool); +- _4 = &fake (_2.1: bool); StorageLive(_12); StorageLive(_13); _13 = _1; diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 2989582d03827..b4bd45ba597f2 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -80,8 +80,8 @@ _6 = &(_2.1: bool); StorageLive(_8); _8 = &(_2.2: std::string::String); -- _3 = &shallow (_2.0: bool); -- _4 = &shallow (_2.1: bool); +- _3 = &fake (_2.0: bool); +- _4 = &fake (_2.1: bool); StorageLive(_9); StorageLive(_10); _10 = _1; @@ -137,8 +137,8 @@ _6 = &(_2.0: bool); StorageLive(_8); _8 = &(_2.2: std::string::String); -- _3 = &shallow (_2.0: bool); -- _4 = &shallow (_2.1: bool); +- _3 = &fake (_2.0: bool); +- _4 = &fake (_2.1: bool); StorageLive(_12); StorageLive(_13); _13 = _1; diff --git a/tests/mir-opt/match_test.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/match_test.main.SimplifyCfg-initial.after.mir index 90ec3ab49ad00..ebb2f70a47587 100644 --- a/tests/mir-opt/match_test.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/match_test.main.SimplifyCfg-initial.after.mir @@ -68,7 +68,7 @@ fn main() -> () { } bb9: { - _8 = &shallow _1; + _8 = &fake _1; StorageLive(_9); _9 = _2; switchInt(move _9) -> [0: bb11, otherwise: bb10]; diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 50189d192ceb2..d5628dc7a6eae 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -69,7 +69,7 @@ bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): ptr::alignment::AlignmentEnum32) }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; StorageDead(_10); StorageDead(_2); StorageLive(_3); @@ -78,7 +78,7 @@ StorageLive(_6); _9 = const _; - _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind unreachable]; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index 6966762a1b84f..d28059458ae9b 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -67,7 +67,7 @@ bb4: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): ptr::alignment::AlignmentEnum32) }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; StorageDead(_10); StorageDead(_2); StorageLive(_3); @@ -76,7 +76,7 @@ StorageLive(_6); _9 = const _; - _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb5, unwind continue]; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index 08a185bad9cdb..d139fc73e210a 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -69,7 +69,7 @@ bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): ptr::alignment::AlignmentEnum64) }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; StorageDead(_10); StorageDead(_2); StorageLive(_3); @@ -78,7 +78,7 @@ StorageLive(_6); _9 = const _; - _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind unreachable]; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index 6501cb85e8a02..63db9553b3766 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -67,7 +67,7 @@ bb4: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): ptr::alignment::AlignmentEnum64) }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; StorageDead(_10); StorageDead(_2); StorageLive(_3); @@ -76,7 +76,7 @@ StorageLive(_6); _9 = const _; - _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb5, unwind continue]; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 49f685cfacdcc..73a3be7f30176 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -30,7 +30,7 @@ fn int_range(_1: usize, _2: usize) -> () { scope 7 { } } - scope 8 (inlined cmp::impls::::lt) { + scope 8 (inlined std::cmp::impls::::lt) { debug self => _6; debug other => _7; let mut _8: usize; diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir index 630babaa821a3..713d6cc558acc 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir @@ -24,16 +24,16 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { debug src => _1; scope 7 (inlined intrinsics::is_aligned_and_not_null::) { debug ptr => _1; - scope 8 (inlined ptr::const_ptr::::is_null) { + scope 8 (inlined std::ptr::const_ptr::::is_null) { debug self => _1; let mut _3: *const u8; scope 9 { - scope 10 (inlined ptr::const_ptr::::is_null::runtime_impl) { + scope 10 (inlined std::ptr::const_ptr::::is_null::runtime_impl) { debug ptr => _3; - scope 11 (inlined ptr::const_ptr::::addr) { + scope 11 (inlined std::ptr::const_ptr::::addr) { debug self => _3; scope 12 { - scope 13 (inlined ptr::const_ptr::::cast::<()>) { + scope 13 (inlined std::ptr::const_ptr::::cast::<()>) { debug self => _3; } } @@ -41,7 +41,7 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { } } } - scope 14 (inlined ptr::const_ptr::::is_aligned) { + scope 14 (inlined std::ptr::const_ptr::::is_aligned) { debug self => _1; scope 15 (inlined align_of::) { } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index 91c3731f4923f..cd734b10fea4f 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -33,7 +33,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { scope 7 { } } - scope 8 (inlined cmp::impls::::lt) { + scope 8 (inlined std::cmp::impls::::lt) { debug self => _7; debug other => _8; let mut _9: u32; diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index f76de02c9d1e4..3342da545aecc 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -33,7 +33,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { scope 7 { } } - scope 8 (inlined cmp::impls::::lt) { + scope 8 (inlined std::cmp::impls::::lt) { debug self => _7; debug other => _8; let mut _9: u32; diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir index a7824f36d505d..6ed3d73b11d3c 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir @@ -17,7 +17,7 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { scope 4 { } } - scope 5 (inlined cmp::impls::::lt) { + scope 5 (inlined std::cmp::impls::::lt) { debug self => _2; debug other => _3; let mut _4: u32; diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir index 83c9e6c1af26a..a030647deae38 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir @@ -17,7 +17,7 @@ fn range_iter_next(_1: &mut std::ops::Range) -> Option { scope 4 { } } - scope 5 (inlined cmp::impls::::lt) { + scope 5 (inlined std::cmp::impls::::lt) { debug self => _2; debug other => _3; let mut _4: u32; diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index 548767dca0d0a..05f16cdacceff 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -30,48 +30,48 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:8:25: 8:39}, _2 debug b => _6; debug c => _8; debug d => _10; - scope 2 (inlined cmp::impls::::le) { + scope 2 (inlined std::cmp::impls::::le) { debug self => _11; debug other => _13; let mut _14: &usize; let mut _15: &usize; - scope 3 (inlined cmp::impls::::le) { + scope 3 (inlined std::cmp::impls::::le) { debug self => _14; debug other => _15; let mut _16: usize; let mut _17: usize; } } - scope 4 (inlined cmp::impls::::le) { + scope 4 (inlined std::cmp::impls::::le) { debug self => _19; debug other => _21; let mut _22: &usize; let mut _23: &usize; - scope 5 (inlined cmp::impls::::le) { + scope 5 (inlined std::cmp::impls::::le) { debug self => _22; debug other => _23; let mut _24: usize; let mut _25: usize; } } - scope 6 (inlined cmp::impls::::le) { + scope 6 (inlined std::cmp::impls::::le) { debug self => _27; debug other => _29; let mut _30: &usize; let mut _31: &usize; - scope 7 (inlined cmp::impls::::le) { + scope 7 (inlined std::cmp::impls::::le) { debug self => _30; debug other => _31; let mut _32: usize; let mut _33: usize; } } - scope 8 (inlined cmp::impls::::le) { + scope 8 (inlined std::cmp::impls::::le) { debug self => _35; debug other => _37; let mut _38: &usize; let mut _39: &usize; - scope 9 (inlined cmp::impls::::le) { + scope 9 (inlined std::cmp::impls::::le) { debug self => _38; debug other => _39; let mut _40: usize; diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir index 8590c9d3b8375..e4d9060d4cf51 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir @@ -20,33 +20,30 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { debug self => _2; debug slice => _5; let mut _6: *mut u32; + let mut _9: &[&str]; scope 5 { - debug this => _2; - scope 6 { - scope 7 (inlined >::get_unchecked_mut::runtime::) { - debug this => _2; - debug slice => _5; - scope 8 (inlined ptr::mut_ptr::::len) { - debug self => _5; - let mut _9: *const [u32]; - scope 9 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _9; - scope 10 { - } - } - } - } - scope 11 (inlined ptr::mut_ptr::::as_mut_ptr) { - debug self => _5; + scope 10 (inlined std::ptr::mut_ptr::::as_mut_ptr) { + debug self => _5; + } + scope 11 (inlined std::ptr::mut_ptr::::add) { + debug self => _6; + debug count => _2; + scope 12 { } - scope 12 (inlined ptr::mut_ptr::::add) { - debug self => _6; - debug count => _2; - scope 13 { - } + } + } + scope 6 (inlined std::ptr::mut_ptr::::len) { + debug self => _5; + let mut _10: *const [u32]; + scope 7 (inlined std::ptr::metadata::<[u32]>) { + debug ptr => _10; + scope 8 { } } } + scope 9 (inlined Arguments::<'_>::new_const) { + debug pieces => _9; + } } } } @@ -73,10 +70,12 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_9); + StorageLive(_10); StorageLive(_6); _6 = _5 as *mut u32 (PtrToPtr); _7 = Offset(_6, _2); StorageDead(_6); + StorageDead(_10); StorageDead(_9); StorageDead(_5); _8 = &mut (*_7); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir index 8590c9d3b8375..e4d9060d4cf51 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir @@ -20,33 +20,30 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { debug self => _2; debug slice => _5; let mut _6: *mut u32; + let mut _9: &[&str]; scope 5 { - debug this => _2; - scope 6 { - scope 7 (inlined >::get_unchecked_mut::runtime::) { - debug this => _2; - debug slice => _5; - scope 8 (inlined ptr::mut_ptr::::len) { - debug self => _5; - let mut _9: *const [u32]; - scope 9 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _9; - scope 10 { - } - } - } - } - scope 11 (inlined ptr::mut_ptr::::as_mut_ptr) { - debug self => _5; + scope 10 (inlined std::ptr::mut_ptr::::as_mut_ptr) { + debug self => _5; + } + scope 11 (inlined std::ptr::mut_ptr::::add) { + debug self => _6; + debug count => _2; + scope 12 { } - scope 12 (inlined ptr::mut_ptr::::add) { - debug self => _6; - debug count => _2; - scope 13 { - } + } + } + scope 6 (inlined std::ptr::mut_ptr::::len) { + debug self => _5; + let mut _10: *const [u32]; + scope 7 (inlined std::ptr::metadata::<[u32]>) { + debug ptr => _10; + scope 8 { } } } + scope 9 (inlined Arguments::<'_>::new_const) { + debug pieces => _9; + } } } } @@ -73,10 +70,12 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_9); + StorageLive(_10); StorageLive(_6); _6 = _5 as *mut u32 (PtrToPtr); _7 = Offset(_6, _2); StorageDead(_6); + StorageDead(_10); StorageDead(_9); StorageDead(_5); _8 = &mut (*_7); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index 729841ec5ea8a..0d95f81c37c54 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -19,56 +19,51 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug slice => _5; let mut _7: *mut u32; let mut _8: *mut u32; + let mut _14: &[&str]; scope 4 { - debug ((this: std::ops::Range).0: usize) => _3; - debug ((this: std::ops::Range).1: usize) => _4; + let _6: usize; scope 5 { - let _6: usize; - scope 6 { - debug new_len => _6; - scope 11 (inlined ptr::mut_ptr::::as_mut_ptr) { - debug self => _5; + debug new_len => _6; + scope 10 (inlined std::ptr::mut_ptr::::as_mut_ptr) { + debug self => _5; + } + scope 11 (inlined std::ptr::mut_ptr::::add) { + debug self => _7; + debug count => _3; + scope 12 { } - scope 12 (inlined ptr::mut_ptr::::add) { - debug self => _7; - debug count => _3; - scope 13 { - } + } + scope 13 (inlined slice_from_raw_parts_mut::) { + debug data => _8; + debug len => _6; + let mut _9: *mut (); + scope 14 (inlined std::ptr::mut_ptr::::cast::<()>) { + debug self => _8; } - scope 14 (inlined slice_from_raw_parts_mut::) { - debug data => _8; - debug len => _6; - let mut _9: *mut (); - scope 15 (inlined ptr::mut_ptr::::cast::<()>) { - debug self => _8; - } - scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { - debug data_address => _9; - debug metadata => _6; - let mut _10: *const (); - let mut _11: std::ptr::metadata::PtrComponents<[u32]>; - let mut _12: std::ptr::metadata::PtrRepr<[u32]>; - scope 17 { - } + scope 15 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { + debug data_address => _9; + debug metadata => _6; + let mut _10: *const (); + let mut _11: std::ptr::metadata::PtrComponents<[u32]>; + let mut _12: std::ptr::metadata::PtrRepr<[u32]>; + scope 16 { } } } - scope 7 (inlined as SliceIndex<[T]>>::get_unchecked_mut::runtime::) { - debug ((this: std::ops::Range).0: usize) => _3; - debug ((this: std::ops::Range).1: usize) => _4; - debug slice => _5; - scope 8 (inlined ptr::mut_ptr::::len) { - debug self => _5; - let mut _14: *const [u32]; - scope 9 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _14; - scope 10 { - } - } - } + } + } + scope 6 (inlined std::ptr::mut_ptr::::len) { + debug self => _5; + let mut _15: *const [u32]; + scope 7 (inlined std::ptr::metadata::<[u32]>) { + debug ptr => _15; + scope 8 { } } } + scope 9 (inlined Arguments::<'_>::new_const) { + debug pieces => _14; + } } } } @@ -78,8 +73,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> _4 = move (_2.1: usize); StorageLive(_5); _5 = &raw mut (*_1); - StorageLive(_6); StorageLive(_14); + StorageLive(_6); + StorageLive(_15); _6 = SubUnchecked(_4, _3); StorageLive(_8); StorageLive(_7); @@ -92,16 +88,17 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_11); StorageLive(_10); _10 = _9 as *const () (PointerCoercion(MutToConstPointer)); - _11 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 }; + _11 = std::ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 }; StorageDead(_10); - _12 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 }; + _12 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 }; StorageDead(_11); _13 = (_12.1: *mut [u32]); StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageDead(_14); + StorageDead(_15); StorageDead(_6); + StorageDead(_14); StorageDead(_5); _0 = &mut (*_13); return; diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 729841ec5ea8a..0d95f81c37c54 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -19,56 +19,51 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> debug slice => _5; let mut _7: *mut u32; let mut _8: *mut u32; + let mut _14: &[&str]; scope 4 { - debug ((this: std::ops::Range).0: usize) => _3; - debug ((this: std::ops::Range).1: usize) => _4; + let _6: usize; scope 5 { - let _6: usize; - scope 6 { - debug new_len => _6; - scope 11 (inlined ptr::mut_ptr::::as_mut_ptr) { - debug self => _5; + debug new_len => _6; + scope 10 (inlined std::ptr::mut_ptr::::as_mut_ptr) { + debug self => _5; + } + scope 11 (inlined std::ptr::mut_ptr::::add) { + debug self => _7; + debug count => _3; + scope 12 { } - scope 12 (inlined ptr::mut_ptr::::add) { - debug self => _7; - debug count => _3; - scope 13 { - } + } + scope 13 (inlined slice_from_raw_parts_mut::) { + debug data => _8; + debug len => _6; + let mut _9: *mut (); + scope 14 (inlined std::ptr::mut_ptr::::cast::<()>) { + debug self => _8; } - scope 14 (inlined slice_from_raw_parts_mut::) { - debug data => _8; - debug len => _6; - let mut _9: *mut (); - scope 15 (inlined ptr::mut_ptr::::cast::<()>) { - debug self => _8; - } - scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { - debug data_address => _9; - debug metadata => _6; - let mut _10: *const (); - let mut _11: std::ptr::metadata::PtrComponents<[u32]>; - let mut _12: std::ptr::metadata::PtrRepr<[u32]>; - scope 17 { - } + scope 15 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { + debug data_address => _9; + debug metadata => _6; + let mut _10: *const (); + let mut _11: std::ptr::metadata::PtrComponents<[u32]>; + let mut _12: std::ptr::metadata::PtrRepr<[u32]>; + scope 16 { } } } - scope 7 (inlined as SliceIndex<[T]>>::get_unchecked_mut::runtime::) { - debug ((this: std::ops::Range).0: usize) => _3; - debug ((this: std::ops::Range).1: usize) => _4; - debug slice => _5; - scope 8 (inlined ptr::mut_ptr::::len) { - debug self => _5; - let mut _14: *const [u32]; - scope 9 (inlined std::ptr::metadata::<[u32]>) { - debug ptr => _14; - scope 10 { - } - } - } + } + } + scope 6 (inlined std::ptr::mut_ptr::::len) { + debug self => _5; + let mut _15: *const [u32]; + scope 7 (inlined std::ptr::metadata::<[u32]>) { + debug ptr => _15; + scope 8 { } } } + scope 9 (inlined Arguments::<'_>::new_const) { + debug pieces => _14; + } } } } @@ -78,8 +73,9 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> _4 = move (_2.1: usize); StorageLive(_5); _5 = &raw mut (*_1); - StorageLive(_6); StorageLive(_14); + StorageLive(_6); + StorageLive(_15); _6 = SubUnchecked(_4, _3); StorageLive(_8); StorageLive(_7); @@ -92,16 +88,17 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageLive(_11); StorageLive(_10); _10 = _9 as *const () (PointerCoercion(MutToConstPointer)); - _11 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 }; + _11 = std::ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 }; StorageDead(_10); - _12 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 }; + _12 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 }; StorageDead(_11); _13 = (_12.1: *mut [u32]); StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageDead(_14); + StorageDead(_15); StorageDead(_6); + StorageDead(_14); StorageDead(_5); _0 = &mut (*_13); return; diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 89009864c3293..c58b630a0c365 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -45,16 +45,16 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { debug ptr => _9; - scope 16 (inlined ptr::mut_ptr::::is_null) { + scope 16 (inlined std::ptr::mut_ptr::::is_null) { debug self => _9; let mut _24: *mut u8; scope 17 { - scope 18 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _24; - scope 19 (inlined ptr::mut_ptr::::addr) { + scope 19 (inlined std::ptr::mut_ptr::::addr) { debug self => _24; scope 20 { - scope 21 (inlined ptr::mut_ptr::::cast::<()>) { + scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _24; } } @@ -71,7 +71,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 10 { } } - scope 11 (inlined ptr::const_ptr::::add) { + scope 11 (inlined std::ptr::const_ptr::::add) { debug self => _4; debug count => _6; scope 12 { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 3d76bab7ce70e..1a805f0fd8dc8 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -45,16 +45,16 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { debug ptr => _9; - scope 16 (inlined ptr::mut_ptr::::is_null) { + scope 16 (inlined std::ptr::mut_ptr::::is_null) { debug self => _9; let mut _24: *mut u8; scope 17 { - scope 18 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _24; - scope 19 (inlined ptr::mut_ptr::::addr) { + scope 19 (inlined std::ptr::mut_ptr::::addr) { debug self => _24; scope 20 { - scope 21 (inlined ptr::mut_ptr::::cast::<()>) { + scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _24; } } @@ -71,7 +71,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 10 { } } - scope 11 (inlined ptr::const_ptr::::add) { + scope 11 (inlined std::ptr::const_ptr::::add) { debug self => _4; debug count => _6; scope 12 { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 146fa57a0b188..09075eed6a9cd 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -42,16 +42,16 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { debug ptr => _9; - scope 16 (inlined ptr::mut_ptr::::is_null) { + scope 16 (inlined std::ptr::mut_ptr::::is_null) { debug self => _9; let mut _22: *mut u8; scope 17 { - scope 18 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _22; - scope 19 (inlined ptr::mut_ptr::::addr) { + scope 19 (inlined std::ptr::mut_ptr::::addr) { debug self => _22; scope 20 { - scope 21 (inlined ptr::mut_ptr::::cast::<()>) { + scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _22; } } @@ -68,7 +68,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 10 { } } - scope 11 (inlined ptr::const_ptr::::add) { + scope 11 (inlined std::ptr::const_ptr::::add) { debug self => _4; debug count => _6; scope 12 { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index e8586cec981c3..47b84746468a0 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -42,16 +42,16 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { debug ptr => _9; - scope 16 (inlined ptr::mut_ptr::::is_null) { + scope 16 (inlined std::ptr::mut_ptr::::is_null) { debug self => _9; let mut _22: *mut u8; scope 17 { - scope 18 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _22; - scope 19 (inlined ptr::mut_ptr::::addr) { + scope 19 (inlined std::ptr::mut_ptr::::addr) { debug self => _22; scope 20 { - scope 21 (inlined ptr::mut_ptr::::cast::<()>) { + scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _22; } } @@ -68,7 +68,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 10 { } } - scope 11 (inlined ptr::const_ptr::::add) { + scope 11 (inlined std::ptr::const_ptr::::add) { debug self => _4; debug count => _6; scope 12 { diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index ac1de7b4c9041..db6922968ae9c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -39,7 +39,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 8 { } } - scope 9 (inlined cmp::impls::::lt) { + scope 9 (inlined std::cmp::impls::::lt) { debug self => _7; debug other => _8; let mut _9: usize; diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 3c49ecf95a10c..81d1832eebba2 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -39,7 +39,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 8 { } } - scope 9 (inlined cmp::impls::::lt) { + scope 9 (inlined std::cmp::impls::::lt) { debug self => _7; debug other => _8; let mut _9: usize; diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index f3760463fe0c3..5ed7ca5e2b86f 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -47,16 +47,16 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { debug ptr => _9; - scope 16 (inlined ptr::mut_ptr::::is_null) { + scope 16 (inlined std::ptr::mut_ptr::::is_null) { debug self => _9; let mut _24: *mut u8; scope 17 { - scope 18 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _24; - scope 19 (inlined ptr::mut_ptr::::addr) { + scope 19 (inlined std::ptr::mut_ptr::::addr) { debug self => _24; scope 20 { - scope 21 (inlined ptr::mut_ptr::::cast::<()>) { + scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _24; } } @@ -73,7 +73,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 10 { } } - scope 11 (inlined ptr::const_ptr::::add) { + scope 11 (inlined std::ptr::const_ptr::::add) { debug self => _4; debug count => _6; scope 12 { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index e63f8b89308cf..bbb979d23b36a 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -47,16 +47,16 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 14 { scope 15 (inlined NonNull::::new_unchecked::runtime::) { debug ptr => _9; - scope 16 (inlined ptr::mut_ptr::::is_null) { + scope 16 (inlined std::ptr::mut_ptr::::is_null) { debug self => _9; let mut _24: *mut u8; scope 17 { - scope 18 (inlined ptr::mut_ptr::::is_null::runtime_impl) { + scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { debug ptr => _24; - scope 19 (inlined ptr::mut_ptr::::addr) { + scope 19 (inlined std::ptr::mut_ptr::::addr) { debug self => _24; scope 20 { - scope 21 (inlined ptr::mut_ptr::::cast::<()>) { + scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { debug self => _24; } } @@ -73,7 +73,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 10 { } } - scope 11 (inlined ptr::const_ptr::::add) { + scope 11 (inlined std::ptr::const_ptr::::add) { debug self => _4; debug count => _6; scope 12 { diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 36134e019ad06..1b9c8fe15c25e 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -695,7 +695,7 @@ fn multiple_storage() { // As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s // pointer address is the address of `x`, so do nothing. let y = *z; - Call(RET = opaque(y), retblock) + Call(RET = opaque(y), retblock, UnwindContinue()) } retblock = { @@ -723,7 +723,7 @@ fn dominate_storage() { } bb1 = { let c = *r; - Call(RET = opaque(c), bb2) + Call(RET = opaque(c), bb2, UnwindContinue()) } bb2 = { StorageDead(x); @@ -759,18 +759,18 @@ fn maybe_dead(m: bool) { bb1 = { StorageDead(x); StorageDead(y); - Call(RET = opaque(u), bb2) + Call(RET = opaque(u), bb2, UnwindContinue()) } bb2 = { // As `x` may be `StorageDead`, `a` may be dangling, so we do nothing. let z = *a; - Call(RET = opaque(z), bb3) + Call(RET = opaque(z), bb3, UnwindContinue()) } bb3 = { // As `y` may be `StorageDead`, `b` may be dangling, so we do nothing. // This implies that we also do not substitute `b` in `bb0`. let t = *b; - Call(RET = opaque(t), retblock) + Call(RET = opaque(t), retblock, UnwindContinue()) } retblock = { Return() diff --git a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff index 61329bb75d13e..54da6ee659f95 100644 --- a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff +++ b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-abort.diff @@ -33,10 +33,10 @@ } bb4: { -- _4 = &shallow _1; -- _5 = &shallow (*((_1 as Some).0: &&i32)); -- _6 = &shallow ((_1 as Some).0: &&i32); -- _7 = &shallow (*(*((_1 as Some).0: &&i32))); +- _4 = &fake _1; +- _5 = &fake (*((_1 as Some).0: &&i32)); +- _6 = &fake ((_1 as Some).0: &&i32); +- _7 = &fake (*(*((_1 as Some).0: &&i32))); + nop; + nop; + nop; diff --git a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff index 61329bb75d13e..54da6ee659f95 100644 --- a/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff +++ b/tests/mir-opt/remove_fake_borrows.match_guard.CleanupPostBorrowck.panic-unwind.diff @@ -33,10 +33,10 @@ } bb4: { -- _4 = &shallow _1; -- _5 = &shallow (*((_1 as Some).0: &&i32)); -- _6 = &shallow ((_1 as Some).0: &&i32); -- _7 = &shallow (*(*((_1 as Some).0: &&i32))); +- _4 = &fake _1; +- _5 = &fake (*((_1 as Some).0: &&i32)); +- _6 = &fake ((_1 as Some).0: &&i32); +- _7 = &fake (*(*((_1 as Some).0: &&i32))); + nop; + nop; + nop; diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir index 566b6af95baad..9c4d6da296d43 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir @@ -75,7 +75,7 @@ fn array_casts() -> () { StorageLive(_6); StorageLive(_7); _7 = _2; - _6 = ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind unreachable]; + _6 = std::ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind unreachable]; } bb1: { @@ -101,7 +101,7 @@ fn array_casts() -> () { StorageLive(_16); StorageLive(_17); _17 = _9; - _16 = ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind unreachable]; + _16 = std::ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index d0d3176320bab..ca064ab2b8fdb 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -75,7 +75,7 @@ fn array_casts() -> () { StorageLive(_6); StorageLive(_7); _7 = _2; - _6 = ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind continue]; + _6 = std::ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind continue]; } bb1: { @@ -101,7 +101,7 @@ fn array_casts() -> () { StorageLive(_16); StorageLive(_17); _17 = _9; - _16 = ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind continue]; + _16 = std::ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index fe4b33001fc4c..d287b20c4ead0 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -52,29 +52,21 @@ StorageLive(_10); StorageLive(_11); _9 = discriminant(_1); - switchInt(move _9) -> [0: bb6, 1: bb5, otherwise: bb3]; + switchInt(move _9) -> [0: bb6, 1: bb5, otherwise: bb2]; } bb1: { - StorageDead(_11); - StorageDead(_10); - StorageDead(_9); - _5 = discriminant(_3); - switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; - } - - bb2: { _8 = ((_3 as Continue).0: i32); _0 = Result::::Ok(_8); StorageDead(_3); return; } - bb3: { + bb2: { unreachable; } - bb4: { + bb3: { _6 = ((_3 as Break).0: std::result::Result); _13 = ((_6 as Err).0: i32); _0 = Result::::Err(move _13); @@ -82,19 +74,27 @@ return; } + bb4: { + StorageDead(_11); + StorageDead(_10); + StorageDead(_9); + _5 = discriminant(_3); + switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + bb5: { _11 = ((_1 as Err).0: i32); StorageLive(_12); _12 = Result::::Err(move _11); _3 = ControlFlow::, i32>::Break(move _12); StorageDead(_12); - goto -> bb1; + goto -> bb4; } bb6: { _10 = ((_1 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(move _10); - goto -> bb1; + goto -> bb4; } } diff --git a/tests/mir-opt/while_storage.rs b/tests/mir-opt/while_storage.rs deleted file mode 100644 index 3a3d451ee8d71..0000000000000 --- a/tests/mir-opt/while_storage.rs +++ /dev/null @@ -1,21 +0,0 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// Test that we correctly generate StorageDead statements for while loop -// conditions on all branches - -fn get_bool(c: bool) -> bool { - c -} - -// EMIT_MIR while_storage.while_loop.PreCodegen.after.mir -fn while_loop(c: bool) { - while get_bool(c) { - if get_bool(c) { - break; - } - } -} - -fn main() { - while_loop(false); -} diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir deleted file mode 100644 index 21c4b92cf0458..0000000000000 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-abort.mir +++ /dev/null @@ -1,16 +0,0 @@ -// MIR for `while_loop` after PreCodegen - -fn while_loop(_1: bool) -> () { - debug c => _1; - let mut _0: (); - scope 1 (inlined get_bool) { - debug c => _1; - } - scope 2 (inlined get_bool) { - debug c => _1; - } - - bb0: { - return; - } -} diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir deleted file mode 100644 index 21c4b92cf0458..0000000000000 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.panic-unwind.mir +++ /dev/null @@ -1,16 +0,0 @@ -// MIR for `while_loop` after PreCodegen - -fn while_loop(_1: bool) -> () { - debug c => _1; - let mut _0: (); - scope 1 (inlined get_bool) { - debug c => _1; - } - scope 2 (inlined get_bool) { - debug c => _1; - } - - bb0: { - return; - } -} diff --git a/tests/run-coverage/abort.rs b/tests/run-coverage/abort.rs deleted file mode 100644 index 98264bdc1afe5..0000000000000 --- a/tests/run-coverage/abort.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![feature(c_unwind)] -#![allow(unused_assignments)] - -extern "C" fn might_abort(should_abort: bool) { - if should_abort { - println!("aborting..."); - panic!("panics and aborts"); - } else { - println!("Don't Panic"); - } -} - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown < 5 { - might_abort(false); - } - // See discussion (below the `Notes` section) on coverage results for the closing brace. - if countdown < 5 { might_abort(false); } // Counts for different regions on one line. - // For the following example, the closing brace is the last character on the line. - // This shows the character after the closing brace is highlighted, even if that next - // character is a newline. - if countdown < 5 { might_abort(false); } - countdown -= 1; - } - Ok(()) -} - -// Notes: -// 1. Compare this program and its coverage results to those of the similar tests -// `panic_unwind.rs` and `try_error_result.rs`. -// 2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`. -// 3. The test does not invoke the abort. By executing to a successful completion, the coverage -// results show where the program did and did not execute. -// 4. If the program actually aborted, the coverage counters would not be saved (which "works as -// intended"). Coverage results would show no executed coverage regions. -// 6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status -// (on Linux at least). - -/* - -Expect the following coverage results: - -```text - 16| 11| while countdown > 0 { - 17| 10| if countdown < 5 { - 18| 4| might_abort(false); - 19| 6| } -``` - -This is actually correct. - -The condition `countdown < 5` executed 10 times (10 loop iterations). - -It evaluated to `true` 4 times, and executed the `might_abort()` call. - -It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit -`else`, the coverage implementation injects a counter, at the character immediately after the `if`s -closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the -non-true condition. - -As another example of why this is important, say the condition was `countdown < 50`, which is always -`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called. -The closing brace would have a count of `0`, highlighting the missed coverage. -*/ diff --git a/tests/run-coverage/assert.rs b/tests/run-coverage/assert.rs deleted file mode 100644 index 85e6662a6adc8..0000000000000 --- a/tests/run-coverage/assert.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 101 - -fn might_fail_assert(one_plus_one: u32) { - println!("does 1 + 1 = {}?", one_plus_one); - assert_eq!(1 + 1, one_plus_one, "the argument was wrong"); -} - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown == 1 { - might_fail_assert(3); - } else if countdown < 5 { - might_fail_assert(2); - } - countdown -= 1; - } - Ok(()) -} - -// Notes: -// 1. Compare this program and its coverage results to those of the very similar test -// `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`. -// 2. This test confirms the coverage generated when a program passes or fails an `assert!()` or -// related `assert_*!()` macro. -// 3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce -// conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to -// `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails). -// 4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test -// (and in many other coverage tests). The `Assert` terminator is typically generated by the -// Rust compiler to check for runtime failures, such as numeric overflows. diff --git a/tests/run-coverage/async.rs b/tests/run-coverage/async.rs deleted file mode 100644 index efd9e62d64e1d..0000000000000 --- a/tests/run-coverage/async.rs +++ /dev/null @@ -1,128 +0,0 @@ -#![allow(unused_assignments, dead_code)] - -// compile-flags: --edition=2018 -C opt-level=1 - -async fn c(x: u8) -> u8 { - if x == 8 { - 1 - } else { - 0 - } -} - -async fn d() -> u8 { 1 } - -async fn e() -> u8 { 1 } // unused function; executor does not block on `g()` - -async fn f() -> u8 { 1 } - -async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()` - -pub async fn g(x: u8) { - match x { - y if e().await == y => (), - y if f().await == y => (), - _ => (), - } -} - -async fn h(x: usize) { // The function signature is counted when called, but the body is not - // executed (not awaited) so the open brace has a `0` count (at least when - // displayed with `llvm-cov show` in color-mode). - match x { - y if foo().await[y] => (), - _ => (), - } -} - -async fn i(x: u8) { // line coverage is 1, but there are 2 regions: - // (a) the function signature, counted when the function is called; and - // (b) the open brace for the function body, counted once when the body is - // executed asynchronously. - match x { - y if c(x).await == y + 1 => { d().await; } - y if f().await == y + 1 => (), - _ => (), - } -} - -fn j(x: u8) { - // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`. - fn c(x: u8) -> u8 { - if x == 8 { - 1 // This line appears covered, but the 1-character expression span covering the `1` - // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because - // `fn j()` executes the open brace for the function body, followed by the function's - // first executable statement, `match x`. Inner function declarations are not - // "visible" to the MIR for `j()`, so the code region counts all lines between the - // open brace and the first statement as executed, which is, in a sense, true. - // `llvm-cov show` overcomes this kind of situation by showing the actual counts - // of the enclosed coverages, (that is, the `1` expression was not executed, and - // accurately displays a `0`). - } else { - 0 - } - } - fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed - fn f() -> u8 { 1 } - match x { - y if c(x) == y + 1 => { d(); } - y if f() == y + 1 => (), - _ => (), - } -} - -fn k(x: u8) { // unused function - match x { - 1 => (), - 2 => (), - _ => (), - } -} - -fn l(x: u8) { - match x { - 1 => (), - 2 => (), - _ => (), - } -} - -async fn m(x: u8) -> u8 { x - 1 } - -fn main() { - let _ = g(10); - let _ = h(9); - let mut future = Box::pin(i(8)); - j(7); - l(6); - let _ = m(5); - executor::block_on(future.as_mut()); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unsafe { unreachable_unchecked() }, // clone - |_| unsafe { unreachable_unchecked() }, // wake - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/run-coverage/async2.rs b/tests/run-coverage/async2.rs deleted file mode 100644 index 2884ff297affd..0000000000000 --- a/tests/run-coverage/async2.rs +++ /dev/null @@ -1,57 +0,0 @@ -// compile-flags: --edition=2018 - -fn non_async_func() { - println!("non_async_func was covered"); - let b = true; - if b { - println!("non_async_func println in block"); - } -} - -async fn async_func() { - println!("async_func was covered"); - let b = true; - if b { - println!("async_func println in block"); - } -} - -async fn async_func_just_println() { - println!("async_func_just_println was covered"); -} - -fn main() { - println!("codecovsample::main"); - - non_async_func(); - - executor::block_on(async_func()); - executor::block_on(async_func_just_println()); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unsafe { unreachable_unchecked() }, // clone - |_| unsafe { unreachable_unchecked() }, // wake - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/run-coverage/bad_counter_ids.rs b/tests/run-coverage/bad_counter_ids.rs deleted file mode 100644 index ef5460102b70c..0000000000000 --- a/tests/run-coverage/bad_counter_ids.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3 - -// Regression test for . -// -// If some coverage counters were removed by MIR optimizations, we need to take -// care not to refer to those counter IDs in coverage mappings, and instead -// replace them with a constant zero value. If we don't, `llvm-cov` might see -// a too-large counter ID and silently discard the entire function from its -// coverage reports. - -#[derive(Debug, PartialEq, Eq)] -struct Foo(u32); - -fn eq_good() { - println!("a"); - assert_eq!(Foo(1), Foo(1)); -} - -fn eq_good_message() { - println!("b"); - assert_eq!(Foo(1), Foo(1), "message b"); -} - -fn ne_good() { - println!("c"); - assert_ne!(Foo(1), Foo(3)); -} - -fn ne_good_message() { - println!("d"); - assert_ne!(Foo(1), Foo(3), "message d"); -} - -fn eq_bad() { - println!("e"); - assert_eq!(Foo(1), Foo(3)); -} - -fn eq_bad_message() { - println!("f"); - assert_eq!(Foo(1), Foo(3), "message f"); -} - -fn ne_bad() { - println!("g"); - assert_ne!(Foo(1), Foo(1)); -} - -fn ne_bad_message() { - println!("h"); - assert_ne!(Foo(1), Foo(1), "message h"); -} - -#[coverage(off)] -fn main() { - eq_good(); - eq_good_message(); - ne_good(); - ne_good_message(); - - assert!(std::panic::catch_unwind(eq_bad).is_err()); - assert!(std::panic::catch_unwind(eq_bad_message).is_err()); - assert!(std::panic::catch_unwind(ne_bad).is_err()); - assert!(std::panic::catch_unwind(ne_bad_message).is_err()); -} diff --git a/tests/run-coverage/closure.rs b/tests/run-coverage/closure.rs deleted file mode 100644 index 16a2c4e33bd48..0000000000000 --- a/tests/run-coverage/closure.rs +++ /dev/null @@ -1,220 +0,0 @@ -#![allow(unused_assignments, unused_variables)] -// compile-flags: -C opt-level=2 - -// This test used to be sensitive to certain coverage-specific hacks in -// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by -// . - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - let is_false = !is_true; - - let mut some_string = Some(String::from("the string content")); - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 1".to_owned() - } - ) - ); - - some_string = Some(String::from("the string content")); - let - a - = - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 2".to_owned() - }; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - a - ) - ); - - some_string = None; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 3".to_owned() - } - ) - ); - - some_string = None; - let - a - = - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 4".to_owned() - }; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - a - ) - ); - - let - quote_closure - = - |val| - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - format!("'{}'", val) - }; - println!( - "Repeated, quoted string: {:?}" - , - std::iter::repeat("repeat me") - .take(5) - .map - ( - quote_closure - ) - .collect::>() - ); - - let - _unused_closure - = - | - mut countdown - | - { - if is_false { - countdown = 10; - } - "closure should be unused".to_owned() - }; - - let mut countdown = 10; - let _short_unused_closure = | _unused_arg: u8 | countdown += 1; - - - let short_used_covered_closure_macro = | used_arg: u8 | println!("called"); - let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called"); - let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called"); - - - - - let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") }; - - let _shortish_unused_closure = | _unused_arg: u8 | { - println!("not called") - }; - - let _as_short_unused_closure = | - _unused_arg: u8 - | { println!("not called") }; - - let _almost_as_short_unused_closure = | - _unused_arg: u8 - | { println!("not called") } - ; - - - - - - let _short_unused_closure_line_break_no_block = | _unused_arg: u8 | -println!("not called") - ; - - let _short_unused_closure_line_break_no_block2 = - | _unused_arg: u8 | - println!( - "not called" - ) - ; - - let short_used_not_covered_closure_line_break_no_block_embedded_branch = - | _unused_arg: u8 | - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - ; - - let short_used_not_covered_closure_line_break_block_embedded_branch = - | _unused_arg: u8 | - { - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - } - ; - - let short_used_covered_closure_line_break_no_block_embedded_branch = - | _unused_arg: u8 | - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - ; - - let short_used_covered_closure_line_break_block_embedded_branch = - | _unused_arg: u8 | - { - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - } - ; - - if is_false { - short_used_not_covered_closure_macro(0); - short_used_not_covered_closure_line_break_no_block_embedded_branch(0); - short_used_not_covered_closure_line_break_block_embedded_branch(0); - } - short_used_covered_closure_macro(0); - short_used_covered_closure_line_break_no_block_embedded_branch(0); - short_used_covered_closure_line_break_block_embedded_branch(0); -} diff --git a/tests/run-coverage/closure_bug.rs b/tests/run-coverage/closure_bug.rs deleted file mode 100644 index 739bc5f0b51c9..0000000000000 --- a/tests/run-coverage/closure_bug.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Regression test for #115930. -// All of these closures are identical, and should produce identical output in -// the coverage report. However, an unstable sort was causing them to be treated -// inconsistently when preparing coverage spans. - -fn main() { - let truthy = std::env::args().len() == 1; - - let a - = - | - | - if truthy { true } else { false }; - - a(); - if truthy { a(); } - - let b - = - | - | - if truthy { true } else { false }; - - b(); - if truthy { b(); } - - let c - = - | - | - if truthy { true } else { false }; - - c(); - if truthy { c(); } - - let d - = - | - | - if truthy { true } else { false }; - - d(); - if truthy { d(); } -} diff --git a/tests/run-coverage/closure_macro.rs b/tests/run-coverage/closure_macro.rs deleted file mode 100644 index 9b289141c2e54..0000000000000 --- a/tests/run-coverage/closure_macro.rs +++ /dev/null @@ -1,40 +0,0 @@ -// compile-flags: --edition=2018 -#![feature(coverage_attribute)] - -macro_rules! bail { - ($msg:literal $(,)?) => { - if $msg.len() > 0 { - println!("no msg"); - } else { - println!($msg); - } - return Err(String::from($msg)); - }; -} - -macro_rules! on_error { - ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros - let message = format!($error_message, e); - if message.len() > 0 { - println!("{}", message); - Ok(String::from("ok")) - } else { - bail!("error"); - } - }) - }; -} - -fn load_configuration_files() -> Result { - Ok(String::from("config")) -} - -pub fn main() -> Result<(), String> { - println!("Starting service"); - let config = on_error!(load_configuration_files(), "Error loading configs: {}")?; - - let startup_delay_duration = String::from("arg"); - let _ = (config, startup_delay_duration); - Ok(()) -} diff --git a/tests/run-coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs deleted file mode 100644 index b4275599e5991..0000000000000 --- a/tests/run-coverage/closure_macro_async.rs +++ /dev/null @@ -1,77 +0,0 @@ -// compile-flags: --edition=2018 -#![feature(coverage_attribute)] - -macro_rules! bail { - ($msg:literal $(,)?) => { - if $msg.len() > 0 { - println!("no msg"); - } else { - println!($msg); - } - return Err(String::from($msg)); - }; -} - -macro_rules! on_error { - ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros - let message = format!($error_message, e); - if message.len() > 0 { - println!("{}", message); - Ok(String::from("ok")) - } else { - bail!("error"); - } - }) - }; -} - -fn load_configuration_files() -> Result { - Ok(String::from("config")) -} - -pub async fn test() -> Result<(), String> { - println!("Starting service"); - let config = on_error!(load_configuration_files(), "Error loading configs: {}")?; - - let startup_delay_duration = String::from("arg"); - let _ = (config, startup_delay_duration); - Ok(()) -} - -#[coverage(off)] -fn main() { - executor::block_on(test()).unwrap(); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // clone - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // wake - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - #[coverage(off)] - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/run-coverage/conditions.rs b/tests/run-coverage/conditions.rs deleted file mode 100644 index fa7f2a116c21e..0000000000000 --- a/tests/run-coverage/conditions.rs +++ /dev/null @@ -1,86 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - let mut countdown = 0; - if true { - countdown = 10; - } - - const B: u32 = 100; - let x = if countdown > 7 { - countdown -= 4; - B - } else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - countdown - } else { - return; - }; - - let mut countdown = 0; - if true { - countdown = 10; - } - - if countdown > 7 { - countdown -= 4; - } else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - } else { - return; - } - - if true { - let mut countdown = 0; - if true { - countdown = 10; - } - - if countdown > 7 { - countdown -= 4; - } - else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - } else { - return; - } - } - - let mut countdown = 0; - if true { - countdown = 1; - } - - let z = if countdown > 7 { - countdown -= 4; - } else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - } else { - let should_be_reachable = countdown; - println!("reached"); - return; - }; - - let w = if countdown > 7 { - countdown -= 4; - } else if countdown > 2 { - if countdown < 1 || countdown > 5 || countdown != 9 { - countdown = 0; - } - countdown -= 5; - } else { - return; - }; -} diff --git a/tests/run-coverage/continue.rs b/tests/run-coverage/continue.rs deleted file mode 100644 index 624aa98341b80..0000000000000 --- a/tests/run-coverage/continue.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - let is_true = std::env::args().len() == 1; - - let mut x = 0; - for _ in 0..10 { - match is_true { - true => { - continue; - } - _ => { - x = 1; - } - } - x = 3; - } - for _ in 0..10 { - match is_true { - false => { - x = 1; - } - _ => { - continue; - } - } - x = 3; - } - for _ in 0..10 { - match is_true { - true => { - x = 1; - } - _ => { - continue; - } - } - x = 3; - } - for _ in 0..10 { - if is_true { - continue; - } - x = 3; - } - for _ in 0..10 { - match is_true { - false => { - x = 1; - } - _ => { - let _ = x; - } - } - x = 3; - } - for _ in 0..10 { - match is_true { - false => { - x = 1; - } - _ => { - break; - } - } - x = 3; - } - let _ = x; -} diff --git a/tests/run-coverage/coroutine.rs b/tests/run-coverage/coroutine.rs deleted file mode 100644 index 86d19af6f4f08..0000000000000 --- a/tests/run-coverage/coroutine.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![feature(coroutines, coroutine_trait)] - -use std::ops::{Coroutine, CoroutineState}; -use std::pin::Pin; - -// The following implementation of a function called from a `yield` statement -// (apparently requiring the Result and the `String` type or constructor) -// creates conditions where the `coroutine::StateTransform` MIR transform will -// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic -// to handle this condition, and still report dead block coverage. -fn get_u32(val: bool) -> Result { - if val { Ok(1) } else { Err(String::from("some error")) } -} - -fn main() { - let is_true = std::env::args().len() == 1; - let mut coroutine = || { - yield get_u32(is_true); - return "foo"; - }; - - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(Ok(1)) => {} - _ => panic!("unexpected return from resume"), - } - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Complete("foo") => {} - _ => panic!("unexpected return from resume"), - } -} diff --git a/tests/run-coverage/dead_code.rs b/tests/run-coverage/dead_code.rs deleted file mode 100644 index 3492712a6f98e..0000000000000 --- a/tests/run-coverage/dead_code.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![allow(dead_code, unused_assignments, unused_variables)] - -pub fn unused_pub_fn_not_in_library() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true { - countdown = 10; - } -} - -fn unused_fn() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true { - countdown = 10; - } -} - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true { - countdown = 10; - } -} diff --git a/tests/run-coverage/drop_trait.rs b/tests/run-coverage/drop_trait.rs deleted file mode 100644 index 7b062719c6b02..0000000000000 --- a/tests/run-coverage/drop_trait.rs +++ /dev/null @@ -1,33 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -struct Firework { - strength: i32, -} - -impl Drop for Firework { - fn drop(&mut self) { - println!("BOOM times {}!!!", self.strength); - } -} - -fn main() -> Result<(), u8> { - let _firecracker = Firework { strength: 1 }; - - let _tnt = Firework { strength: 100 }; - - if true { - println!("Exiting with error..."); - return Err(1); - } - - let _ = Firework { strength: 1000 }; - - Ok(()) -} - -// Expected program output: -// Exiting with error... -// BOOM times 100!!! -// BOOM times 1!!! -// Error: 1 diff --git a/tests/run-coverage/fn_sig_into_try.rs b/tests/run-coverage/fn_sig_into_try.rs deleted file mode 100644 index 92850c8a188fc..0000000000000 --- a/tests/run-coverage/fn_sig_into_try.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 - -// Regression test for inconsistent handling of function signature spans that -// are followed by code using the `?` operator. -// -// For each of these similar functions, the line containing the function -// signature should be handled in the same way. - -fn a() -> Option -{ - Some(7i32); - Some(0) -} - -fn b() -> Option -{ - Some(7i32)?; - Some(0) -} - -fn c() -> Option -{ - let _ = Some(7i32)?; - Some(0) -} - -fn d() -> Option -{ - let _: () = (); - Some(7i32)?; - Some(0) -} - -#[coverage(off)] -fn main() { - a(); - b(); - c(); - d(); -} diff --git a/tests/run-coverage/generics.rs b/tests/run-coverage/generics.rs deleted file mode 100644 index bf4c2d8d68532..0000000000000 --- a/tests/run-coverage/generics.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -struct Firework where T: Copy + std::fmt::Display { - strength: T, -} - -impl Firework where T: Copy + std::fmt::Display { - #[inline(always)] - fn set_strength(&mut self, new_strength: T) { - self.strength = new_strength; - } -} - -impl Drop for Firework where T: Copy + std::fmt::Display { - #[inline(always)] - fn drop(&mut self) { - println!("BOOM times {}!!!", self.strength); - } -} - -fn main() -> Result<(), u8> { - let mut firecracker = Firework { strength: 1 }; - firecracker.set_strength(2); - - let mut tnt = Firework { strength: 100.1 }; - tnt.set_strength(200.1); - tnt.set_strength(300.3); - - if true { - println!("Exiting with error..."); - return Err(1); - } - - let _ = Firework { strength: 1000 }; - - Ok(()) -} - -// Expected program output: -// Exiting with error... -// BOOM times 100!!! -// BOOM times 1!!! -// Error: 1 diff --git a/tests/run-coverage/if.rs b/tests/run-coverage/if.rs deleted file mode 100644 index 8ad5042ff7baf..0000000000000 --- a/tests/run-coverage/if.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let - is_true - = - std::env::args().len() - == - 1 - ; - let - mut - countdown - = - 0 - ; - if - is_true - { - countdown - = - 10 - ; - } -} diff --git a/tests/run-coverage/if_else.rs b/tests/run-coverage/if_else.rs deleted file mode 100644 index 3244e1e3afd2b..0000000000000 --- a/tests/run-coverage/if_else.rs +++ /dev/null @@ -1,40 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if - is_true - { - countdown - = - 10 - ; - } - else // Note coverage region difference without semicolon - { - countdown - = - 100 - } - - if - is_true - { - countdown - = - 10 - ; - } - else - { - countdown - = - 100 - ; - } -} diff --git a/tests/run-coverage/inline-dead.rs b/tests/run-coverage/inline-dead.rs deleted file mode 100644 index 854fa06296752..0000000000000 --- a/tests/run-coverage/inline-dead.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Regression test for issue #98833. -// compile-flags: -Zinline-mir -Cdebug-assertions=off - -fn main() { - println!("{}", live::()); - - let f = |x: bool| { - debug_assert!( - x - ); - }; - f(false); -} - -#[inline] -fn live() -> u32 { - if B { - dead() - } else { - 0 - } -} - -#[inline] -fn dead() -> u32 { - 42 -} diff --git a/tests/run-coverage/inline.rs b/tests/run-coverage/inline.rs deleted file mode 100644 index 9cfab9ddbadf2..0000000000000 --- a/tests/run-coverage/inline.rs +++ /dev/null @@ -1,51 +0,0 @@ -// compile-flags: -Zinline-mir - -use std::fmt::Display; - -fn main() { - permutations(&['a', 'b', 'c']); -} - -#[inline(always)] -fn permutations(xs: &[T]) { - let mut ys = xs.to_owned(); - permutate(&mut ys, 0); -} - -fn permutate(xs: &mut [T], k: usize) { - let n = length(xs); - if k == n { - display(xs); - } else if k < n { - for i in k..n { - swap(xs, i, k); - permutate(xs, k + 1); - swap(xs, i, k); - } - } else { - error(); - } -} - -fn length(xs: &[T]) -> usize { - xs.len() -} - -#[inline] -fn swap(xs: &mut [T], i: usize, j: usize) { - let t = xs[i]; - xs[i] = xs[j]; - xs[j] = t; -} - -fn display(xs: &[T]) { - for x in xs { - print!("{}", x); - } - println!(); -} - -#[inline(always)] -fn error() { - panic!("error"); -} diff --git a/tests/run-coverage/inner_items.rs b/tests/run-coverage/inner_items.rs deleted file mode 100644 index bcb62b3031cd9..0000000000000 --- a/tests/run-coverage/inner_items.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![allow(unused_assignments, unused_variables, dead_code)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - if is_true { - countdown = 10; - } - - mod in_mod { - const IN_MOD_CONST: u32 = 1000; - } - - fn in_func(a: u32) { - let b = 1; - let c = a + b; - println!("c = {}", c) - } - - struct InStruct { - in_struct_field: u32, - } - - const IN_CONST: u32 = 1234; - - trait InTrait { - fn trait_func(&mut self, incr: u32); - - fn default_trait_func(&mut self) { - in_func(IN_CONST); - self.trait_func(IN_CONST); - } - } - - impl InTrait for InStruct { - fn trait_func(&mut self, incr: u32) { - self.in_struct_field += incr; - in_func(self.in_struct_field); - } - } - - type InType = String; - - if is_true { - in_func(countdown); - } - - let mut val = InStruct { - in_struct_field: 101, - }; - - val.default_trait_func(); -} diff --git a/tests/run-coverage/issue-83601.rs b/tests/run-coverage/issue-83601.rs deleted file mode 100644 index 0b72a81947cc7..0000000000000 --- a/tests/run-coverage/issue-83601.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Shows that rust-lang/rust/83601 is resolved - -#[derive(Debug, PartialEq, Eq)] -struct Foo(u32); - -fn main() { - let bar = Foo(1); - assert_eq!(bar, Foo(1)); - let baz = Foo(0); - assert_ne!(baz, Foo(1)); - println!("{:?}", Foo(1)); - println!("{:?}", bar); - println!("{:?}", baz); -} diff --git a/tests/run-coverage/issue-84561.rs b/tests/run-coverage/issue-84561.rs deleted file mode 100644 index facf5b5b4cfbe..0000000000000 --- a/tests/run-coverage/issue-84561.rs +++ /dev/null @@ -1,182 +0,0 @@ -// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results. - -// failure-status: 101 -#[derive(PartialEq, Eq)] -struct Foo(u32); -fn test3() { - let is_true = std::env::args().len() == 1; - let bar = Foo(1); - assert_eq!(bar, Foo(1)); - let baz = Foo(0); - assert_ne!(baz, Foo(1)); - println!("{:?}", Foo(1)); - println!("{:?}", bar); - println!("{:?}", baz); - - assert_eq!(Foo(1), Foo(1)); - assert_ne!(Foo(0), Foo(1)); - assert_eq!(Foo(2), Foo(2)); - let bar = Foo(0); - assert_ne!(bar, Foo(3)); - assert_ne!(Foo(0), Foo(4)); - assert_eq!(Foo(3), Foo(3), "with a message"); - println!("{:?}", bar); - println!("{:?}", Foo(1)); - - assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" }); - assert_ne!( - Foo(0) - , - Foo(5) - , - "{}" - , - if - is_true - { - "true message" - } else { - "false message" - } - ); - - let is_true = std::env::args().len() == 1; - - assert_eq!( - Foo(1), - Foo(1) - ); - assert_ne!( - Foo(0), - Foo(1) - ); - assert_eq!( - Foo(2), - Foo(2) - ); - let bar = Foo(1); - assert_ne!( - bar, - Foo(3) - ); - if is_true { - assert_ne!( - Foo(0), - Foo(4) - ); - } else { - assert_eq!( - Foo(3), - Foo(3) - ); - } - if is_true { - assert_ne!( - Foo(0), - Foo(4), - "with a message" - ); - } else { - assert_eq!( - Foo(3), - Foo(3), - "with a message" - ); - } - assert_ne!( - if is_true { - Foo(0) - } else { - Foo(1) - }, - Foo(5) - ); - assert_ne!( - Foo(5), - if is_true { - Foo(0) - } else { - Foo(1) - } - ); - assert_ne!( - if is_true { - assert_eq!( - Foo(3), - Foo(3) - ); - Foo(0) - } else { - assert_ne!( - if is_true { - Foo(0) - } else { - Foo(1) - }, - Foo(5) - ); - Foo(1) - }, - Foo(5), - "with a message" - ); - assert_eq!( - Foo(1), - Foo(3), - "this assert should fail" - ); - assert_eq!( - Foo(3), - Foo(3), - "this assert should not be reached" - ); -} - -impl std::fmt::Debug for Foo { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "try and succeed")?; - Ok(()) - } -} - -static mut DEBUG_LEVEL_ENABLED: bool = false; - -macro_rules! debug { - ($($arg:tt)+) => ( - if unsafe { DEBUG_LEVEL_ENABLED } { - println!($($arg)+); - } - ); -} - -fn test1() { - debug!("debug is enabled"); - debug!("debug is enabled"); - let _ = 0; - debug!("debug is enabled"); - unsafe { - DEBUG_LEVEL_ENABLED = true; - } - debug!("debug is enabled"); -} - -macro_rules! call_debug { - ($($arg:tt)+) => ( - fn call_print(s: &str) { - print!("{}", s); - } - - call_print("called from call_debug: "); - debug!($($arg)+); - ); -} - -fn test2() { - call_debug!("debug is enabled"); -} - -fn main() { - test1(); - test2(); - test3(); -} diff --git a/tests/run-coverage/issue-93054.rs b/tests/run-coverage/issue-93054.rs deleted file mode 100644 index da546cfeef854..0000000000000 --- a/tests/run-coverage/issue-93054.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![allow(dead_code, unreachable_code)] - -// Regression test for #93054: Functions using uninhabited types often only have a single, -// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. -// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. - -// compile-flags: --edition=2021 - -enum Never {} - -impl Never { - fn foo(self) { - match self {} - make().map(|never| match never {}); - } - - fn bar(&self) { - match *self {} - } -} - -async fn foo2(never: Never) { - match never {} -} - -fn make() -> Option { - None -} - -fn main() {} diff --git a/tests/run-coverage/lazy_boolean.rs b/tests/run-coverage/lazy_boolean.rs deleted file mode 100644 index bb6219e851c8a..0000000000000 --- a/tests/run-coverage/lazy_boolean.rs +++ /dev/null @@ -1,61 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let (mut a, mut b, mut c) = (0, 0, 0); - if is_true { - a = 1; - b = 10; - c = 100; - } - let - somebool - = - a < b - || - b < c - ; - let - somebool - = - b < a - || - b < c - ; - let somebool = a < b && b < c; - let somebool = b < a && b < c; - - if - ! - is_true - { - a = 2 - ; - } - - if - is_true - { - b = 30 - ; - } - else - { - c = 400 - ; - } - - if !is_true { - a = 2; - } - - if is_true { - b = 30; - } else { - c = 400; - } -} diff --git a/tests/run-coverage/loop_break_value.rs b/tests/run-coverage/loop_break_value.rs deleted file mode 100644 index dbc4fad7a2316..0000000000000 --- a/tests/run-coverage/loop_break_value.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - let result - = - loop - { - break - 10 - ; - } - ; -} diff --git a/tests/run-coverage/loops_branches.rs b/tests/run-coverage/loops_branches.rs deleted file mode 100644 index f3a343bcc1f42..0000000000000 --- a/tests/run-coverage/loops_branches.rs +++ /dev/null @@ -1,60 +0,0 @@ -#![allow(unused_assignments, unused_variables, while_true)] - -// This test confirms that (1) unexecuted infinite loops are handled correctly by the -// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped. - -struct DebugTest; - -impl std::fmt::Debug for DebugTest { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - if true { - if false { - while true {} - } - write!(f, "cool")?; - } else { - } - - for i in 0..10 { - if true { - if false { - while true {} - } - write!(f, "cool")?; - } else { - } - } - Ok(()) - } -} - -struct DisplayTest; - -impl std::fmt::Display for DisplayTest { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - if false { - } else { - if false { - while true {} - } - write!(f, "cool")?; - } - for i in 0..10 { - if false { - } else { - if false { - while true {} - } - write!(f, "cool")?; - } - } - Ok(()) - } -} - -fn main() { - let debug_test = DebugTest; - println!("{:?}", debug_test); - let display_test = DisplayTest; - println!("{}", display_test); -} diff --git a/tests/run-coverage/match_or_pattern.rs b/tests/run-coverage/match_or_pattern.rs deleted file mode 100644 index ab7aee51d1bc4..0000000000000 --- a/tests/run-coverage/match_or_pattern.rs +++ /dev/null @@ -1,43 +0,0 @@ -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut a: u8 = 0; - let mut b: u8 = 0; - if is_true { - a = 2; - b = 0; - } - match (a, b) { - // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`. - // This test confirms a fix for Issue #79569. - (0 | 1, 2 | 3) => {} - _ => {} - } - if is_true { - a = 0; - b = 0; - } - match (a, b) { - (0 | 1, 2 | 3) => {} - _ => {} - } - if is_true { - a = 2; - b = 2; - } - match (a, b) { - (0 | 1, 2 | 3) => {} - _ => {} - } - if is_true { - a = 0; - b = 2; - } - match (a, b) { - (0 | 1, 2 | 3) => {} - _ => {} - } -} diff --git a/tests/run-coverage/nested_loops.rs b/tests/run-coverage/nested_loops.rs deleted file mode 100644 index 4c7c784279650..0000000000000 --- a/tests/run-coverage/nested_loops.rs +++ /dev/null @@ -1,25 +0,0 @@ -fn main() { - let is_true = std::env::args().len() == 1; - let mut countdown = 10; - - 'outer: while countdown > 0 { - let mut a = 100; - let mut b = 100; - for _ in 0..50 { - if a < 30 { - break; - } - a -= 5; - b -= 5; - if b < 90 { - a -= 10; - if is_true { - break 'outer; - } else { - a -= 2; - } - } - } - countdown -= 1; - } -} diff --git a/tests/run-coverage/no_cov_crate.rs b/tests/run-coverage/no_cov_crate.rs deleted file mode 100644 index e12e4bc55e3e4..0000000000000 --- a/tests/run-coverage/no_cov_crate.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Enables `coverage(off)` on the entire crate -#![feature(coverage_attribute)] - -#[coverage(off)] -fn do_not_add_coverage_1() { - println!("called but not covered"); -} - -fn do_not_add_coverage_2() { - #![coverage(off)] - println!("called but not covered"); -} - -#[coverage(off)] -#[allow(dead_code)] -fn do_not_add_coverage_not_called() { - println!("not called and not covered"); -} - -fn add_coverage_1() { - println!("called and covered"); -} - -fn add_coverage_2() { - println!("called and covered"); -} - -#[allow(dead_code)] -fn add_coverage_not_called() { - println!("not called but covered"); -} - -// FIXME: These test-cases illustrate confusing results of nested functions. -// See https://github.com/rust-lang/rust/issues/93319 -mod nested_fns { - #[coverage(off)] - pub fn outer_not_covered(is_true: bool) { - fn inner(is_true: bool) { - if is_true { - println!("called and covered"); - } else { - println!("absolutely not covered"); - } - } - println!("called but not covered"); - inner(is_true); - } - - pub fn outer(is_true: bool) { - println!("called and covered"); - inner_not_covered(is_true); - - #[coverage(off)] - fn inner_not_covered(is_true: bool) { - if is_true { - println!("called but not covered"); - } else { - println!("absolutely not covered"); - } - } - } - - pub fn outer_both_covered(is_true: bool) { - println!("called and covered"); - inner(is_true); - - fn inner(is_true: bool) { - if is_true { - println!("called and covered"); - } else { - println!("absolutely not covered"); - } - } - } -} - -fn main() { - let is_true = std::env::args().len() == 1; - - do_not_add_coverage_1(); - do_not_add_coverage_2(); - add_coverage_1(); - add_coverage_2(); - - nested_fns::outer_not_covered(is_true); - nested_fns::outer(is_true); - nested_fns::outer_both_covered(is_true); -} diff --git a/tests/run-coverage/overflow.rs b/tests/run-coverage/overflow.rs deleted file mode 100644 index bbb65c1b35df6..0000000000000 --- a/tests/run-coverage/overflow.rs +++ /dev/null @@ -1,63 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 101 - -fn might_overflow(to_add: u32) -> u32 { - if to_add > 5 { - println!("this will probably overflow"); - } - let add_to = u32::MAX - 5; - println!("does {} + {} overflow?", add_to, to_add); - let result = to_add + add_to; - println!("continuing after overflow check"); - result -} - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown == 1 { - let result = might_overflow(10); - println!("Result: {}", result); - } else if countdown < 5 { - let result = might_overflow(1); - println!("Result: {}", result); - } - countdown -= 1; - } - Ok(()) -} - -// Notes: -// 1. Compare this program and its coverage results to those of the very similar test `assert.rs`, -// and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`. -// 2. This test confirms the coverage generated when a program passes or fails a -// compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case). -// 3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`, -// compiler-generated assertion failures are assumed to be a symptom of a program bug, not -// expected behavior. To simplify the coverage graphs and keep instrumented programs as -// small and fast as possible, `Assert` terminators are assumed to always succeed, and -// therefore are considered "non-branching" terminators. So, an `Assert` terminator does not -// get its own coverage counter. -// 4. After an unhandled panic or failed Assert, coverage results may not always be intuitive. -// In this test, the final count for the statements after the `if` block in `might_overflow()` -// is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending -// on the MIR graph and the structure of the code, this count could have been 3 (which might -// have been valid for the overflowed add `+`, but should have been 4 for the lines before -// the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented -// via StatementKind::Counter at the end of the block, but (as in the case in this test), -// a CounterKind::Expression is always evaluated. In this case, the expression was based on -// a `Counter` incremented as part of the evaluation of the `if` expression, which was -// executed, and counted, 4 times, before reaching the overflow add. - -// If the program did not overflow, the coverage for `might_overflow()` would look like this: -// -// 4| |fn might_overflow(to_add: u32) -> u32 { -// 5| 4| if to_add > 5 { -// 6| 0| println!("this will probably overflow"); -// 7| 4| } -// 8| 4| let add_to = u32::MAX - 5; -// 9| 4| println!("does {} + {} overflow?", add_to, to_add); -// 10| 4| let result = to_add + add_to; -// 11| 4| println!("continuing after overflow check"); -// 12| 4| result -// 13| 4|} diff --git a/tests/run-coverage/panic_unwind.rs b/tests/run-coverage/panic_unwind.rs deleted file mode 100644 index 638d2eb6aaaf8..0000000000000 --- a/tests/run-coverage/panic_unwind.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 101 - -fn might_panic(should_panic: bool) { - if should_panic { - println!("panicking..."); - panic!("panics"); - } else { - println!("Don't Panic"); - } -} - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while countdown > 0 { - if countdown == 1 { - might_panic(true); - } else if countdown < 5 { - might_panic(false); - } - countdown -= 1; - } - Ok(()) -} - -// Notes: -// 1. Compare this program and its coverage results to those of the similar tests `abort.rs` and -// `try_error_result.rs`. -// 2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the -// normal program exit cleanup, including writing out the current values of the coverage -// counters. diff --git a/tests/run-coverage/partial_eq.rs b/tests/run-coverage/partial_eq.rs deleted file mode 100644 index dd8b42c18cea9..0000000000000 --- a/tests/run-coverage/partial_eq.rs +++ /dev/null @@ -1,46 +0,0 @@ -// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the -// structure of this test. - -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Version { - major: usize, - minor: usize, - patch: usize, -} - -impl Version { - pub fn new(major: usize, minor: usize, patch: usize) -> Self { - Self { - major, - minor, - patch, - } - } -} - -fn main() { - let version_3_2_1 = Version::new(3, 2, 1); - let version_3_3_0 = Version::new(3, 3, 0); - - println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0); -} - -/* - -This test verifies a bug was fixed that otherwise generated this error: - -thread 'rustc' panicked at 'No counters provided the source_hash for function: - Instance { - def: Item(WithOptConstParam { - did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp), - const_param_did: None - }), - args: [] - }' -The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage -without a code region associated with any `Counter`. Code regions were associated with at least -one expression, which is allowed, but the `function_source_hash` was only passed to the codegen -(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the -`function_source_hash` without a code region, if necessary. - -*/ diff --git a/tests/run-coverage/simple_loop.rs b/tests/run-coverage/simple_loop.rs deleted file mode 100644 index 6f7f23475b826..0000000000000 --- a/tests/run-coverage/simple_loop.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![allow(unused_assignments)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 0; - - if - is_true - { - countdown - = - 10 - ; - } - - loop - { - if - countdown - == - 0 - { - break - ; - } - countdown - -= - 1 - ; - } -} diff --git a/tests/run-coverage/simple_match.rs b/tests/run-coverage/simple_match.rs deleted file mode 100644 index be99e59a82685..0000000000000 --- a/tests/run-coverage/simple_match.rs +++ /dev/null @@ -1,43 +0,0 @@ -#![allow(unused_assignments, unused_variables)] - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - - let mut countdown = 1; - if is_true { - countdown = 0; - } - - for - _ - in - 0..2 - { - let z - ; - match - countdown - { - x - if - x - < - 1 - => - { - z = countdown - ; - let y = countdown - ; - countdown = 10 - ; - } - _ - => - {} - } - } -} diff --git a/tests/run-coverage/test_harness.rs b/tests/run-coverage/test_harness.rs deleted file mode 100644 index 12a755734c198..0000000000000 --- a/tests/run-coverage/test_harness.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Verify that the entry point injected by the test harness doesn't cause -// weird artifacts in the coverage report (e.g. issue #10749). - -// compile-flags: --test - -#[allow(dead_code)] -fn unused() {} - -#[test] -fn my_test() {} diff --git a/tests/run-coverage/tight_inf_loop.rs b/tests/run-coverage/tight_inf_loop.rs deleted file mode 100644 index cef99027aaa4f..0000000000000 --- a/tests/run-coverage/tight_inf_loop.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - if false { - loop {} - } -} diff --git a/tests/run-coverage/try_error_result.rs b/tests/run-coverage/try_error_result.rs deleted file mode 100644 index 557cbf22bfad4..0000000000000 --- a/tests/run-coverage/try_error_result.rs +++ /dev/null @@ -1,118 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -fn call(return_error: bool) -> Result<(), ()> { - if return_error { - Err(()) - } else { - Ok(()) - } -} - -fn test1() -> Result<(), ()> { - let mut - countdown = 10 - ; - for - _ - in - 0..10 - { - countdown - -= 1 - ; - if - countdown < 5 - { - call(/*return_error=*/ true)?; - call(/*return_error=*/ false)?; - } - else - { - call(/*return_error=*/ false)?; - } - } - Ok(()) -} - -struct Thing1; -impl Thing1 { - fn get_thing_2(&self, return_error: bool) -> Result { - if return_error { - Err(()) - } else { - Ok(Thing2 {}) - } - } -} - -struct Thing2; -impl Thing2 { - fn call(&self, return_error: bool) -> Result { - if return_error { - Err(()) - } else { - Ok(57) - } - } -} - -fn test2() -> Result<(), ()> { - let thing1 = Thing1{}; - let mut - countdown = 10 - ; - for - _ - in - 0..10 - { - countdown - -= 1 - ; - if - countdown < 5 - { - thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); - thing1 - . - get_thing_2(/*return_error=*/ false) - ? - . - call(/*return_error=*/ true) - . - expect_err( - "call should fail" - ); - let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; - assert_eq!(val, 57); - let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?; - assert_eq!(val, 57); - } - else - { - let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?; - assert_eq!(val, 57); - let val = thing1 - .get_thing_2(/*return_error=*/ false)? - .call(/*return_error=*/ false)?; - assert_eq!(val, 57); - let val = thing1 - .get_thing_2(/*return_error=*/ false) - ? - .call(/*return_error=*/ false) - ? - ; - assert_eq!(val, 57); - } - } - Ok(()) -} - -fn main() -> Result<(), ()> { - test1().expect_err("test1 should fail"); - test2() - ? - ; - Ok(()) -} diff --git a/tests/run-coverage/unreachable.rs b/tests/run-coverage/unreachable.rs deleted file mode 100644 index 6385bfa160d7d..0000000000000 --- a/tests/run-coverage/unreachable.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![feature(core_intrinsics)] -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 - -// -// If we instrument a function for coverage, but all of its counter-increment -// statements are removed by MIR optimizations, LLVM will think it isn't -// instrumented and it will disappear from coverage maps and coverage reports. -// Most MIR opts won't cause this because they tend not to remove statements -// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends -// with `TerminatorKind::Unreachable`. - -use std::hint::{black_box, unreachable_unchecked}; - -static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() }; - -fn unreachable_function() { - unsafe { unreachable_unchecked() } -} - -// Use an intrinsic to more reliably trigger unreachable-propagation. -fn unreachable_intrinsic() { - unsafe { std::intrinsics::unreachable() } -} - -#[coverage(off)] -fn main() { - if black_box(false) { - UNREACHABLE_CLOSURE(); - } - if black_box(false) { - unreachable_function(); - } - if black_box(false) { - unreachable_intrinsic(); - } -} diff --git a/tests/run-coverage/unused.rs b/tests/run-coverage/unused.rs deleted file mode 100644 index d985af135470e..0000000000000 --- a/tests/run-coverage/unused.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)] - -fn foo(x: T) { - let mut i = 0; - while i < 10 { - i != 0 || i != 0; - i += 1; - } -} - -fn unused_template_func(x: T) { - let mut i = 0; - while i < 10 { - i != 0 || i != 0; - i += 1; - } -} - -fn unused_func(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn unused_func2(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn unused_func3(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn main() -> Result<(), u8> { - foo::(0); - foo::(0.0); - Ok(()) -} diff --git a/tests/run-coverage/while.rs b/tests/run-coverage/while.rs deleted file mode 100644 index 781b90b35663e..0000000000000 --- a/tests/run-coverage/while.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let num = 9; - while num >= 10 { - } -} diff --git a/tests/run-coverage/while_early_ret.rs b/tests/run-coverage/while_early_ret.rs deleted file mode 100644 index b2f0eee2cc0f4..0000000000000 --- a/tests/run-coverage/while_early_ret.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -fn main() -> Result<(), u8> { - let mut countdown = 10; - while - countdown - > - 0 - { - if - countdown - < - 5 - { - return - if - countdown - > - 8 - { - Ok(()) - } - else - { - Err(1) - } - ; - } - countdown - -= - 1 - ; - } - Ok(()) -} - -// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and -// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux -// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program -// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical -// to the coverage test for early returns, but this is a limitation that should be fixed. diff --git a/tests/run-coverage/yield.rs b/tests/run-coverage/yield.rs deleted file mode 100644 index b7e2ba31b59c1..0000000000000 --- a/tests/run-coverage/yield.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![feature(coroutines, coroutine_trait)] -#![allow(unused_assignments)] - -use std::ops::{Coroutine, CoroutineState}; -use std::pin::Pin; - -fn main() { - let mut coroutine = || { - yield 1; - return "foo"; - }; - - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(1) => {} - _ => panic!("unexpected value from resume"), - } - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Complete("foo") => {} - _ => panic!("unexpected value from resume"), - } - - let mut coroutine = || { - yield 1; - yield 2; - yield 3; - return "foo"; - }; - - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(1) => {} - _ => panic!("unexpected value from resume"), - } - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(2) => {} - _ => panic!("unexpected value from resume"), - } -} diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/run-make-fulldeps/issue-19371/foo.rs index 1a94649163b2b..a0bbe3851e82f 100644 --- a/tests/run-make-fulldeps/issue-19371/foo.rs +++ b/tests/run-make-fulldeps/issue-19371/foo.rs @@ -69,9 +69,8 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { interface::run_compiler(config, |compiler| { let linker = compiler.enter(|queries| { queries.global_ctxt()?.enter(|tcx| tcx.analysis(()))?; - let ongoing_codegen = queries.ongoing_codegen()?; - queries.linker(ongoing_codegen) + queries.codegen_and_build_linker() }); - linker.unwrap().link().unwrap(); + linker.unwrap().link(&compiler.sess, &*compiler.codegen_backend).unwrap(); }); } diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs index 5df4c558ee17f..9cbe9e5900abd 100644 --- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs @@ -61,7 +61,7 @@ impl rustc_driver::Callbacks for CompilerCalls { compiler: &Compiler, queries: &'tcx Queries<'tcx>, ) -> Compilation { - compiler.session().abort_if_errors(); + compiler.sess.abort_if_errors(); queries.global_ctxt().unwrap().enter(|tcx| { // Collect definition ids of MIR bodies. let hir = tcx.hir(); diff --git a/tests/run-make/compressed-debuginfo/Makefile b/tests/run-make/compressed-debuginfo/Makefile index f9e4927d008e4..d2f24dde00d7b 100644 --- a/tests/run-make/compressed-debuginfo/Makefile +++ b/tests/run-make/compressed-debuginfo/Makefile @@ -2,7 +2,6 @@ include ../tools.mk # only-linux -# min-llvm-version: 16.0 # # This tests debuginfo-compression. diff --git a/tests/run-make/emit-to-stdout/emit-link.stderr b/tests/run-make/emit-to-stdout/emit-link.stderr index a9d856503e629..0553b22a45ef3 100644 --- a/tests/run-make/emit-to-stdout/emit-link.stderr +++ b/tests/run-make/emit-to-stdout/emit-link.stderr @@ -1,4 +1,4 @@ error: option `-o` or `--emit` is used to write binary output type `link` to stdout, but stdout is a tty -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/run-make/emit-to-stdout/emit-llvm-bc.stderr b/tests/run-make/emit-to-stdout/emit-llvm-bc.stderr index 7b53bd16e7a54..a50148f9ea808 100644 --- a/tests/run-make/emit-to-stdout/emit-llvm-bc.stderr +++ b/tests/run-make/emit-to-stdout/emit-llvm-bc.stderr @@ -1,4 +1,4 @@ error: option `-o` or `--emit` is used to write binary output type `llvm-bc` to stdout, but stdout is a tty -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/run-make/emit-to-stdout/emit-metadata.stderr b/tests/run-make/emit-to-stdout/emit-metadata.stderr index ee1e52937b987..27ad5d5292167 100644 --- a/tests/run-make/emit-to-stdout/emit-metadata.stderr +++ b/tests/run-make/emit-to-stdout/emit-metadata.stderr @@ -1,4 +1,4 @@ error: option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/run-make/emit-to-stdout/emit-multiple-types.stderr b/tests/run-make/emit-to-stdout/emit-multiple-types.stderr index b8a683cd9ebe6..4f74cb8409a68 100644 --- a/tests/run-make/emit-to-stdout/emit-multiple-types.stderr +++ b/tests/run-make/emit-to-stdout/emit-multiple-types.stderr @@ -1,4 +1,4 @@ error: can't use option `-o` or `--emit` to write multiple output types to stdout -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/run-make/emit-to-stdout/emit-obj.stderr b/tests/run-make/emit-to-stdout/emit-obj.stderr index b130353084415..9bbcea010511c 100644 --- a/tests/run-make/emit-to-stdout/emit-obj.stderr +++ b/tests/run-make/emit-to-stdout/emit-obj.stderr @@ -1,4 +1,4 @@ error: option `-o` or `--emit` is used to write binary output type `obj` to stdout, but stdout is a tty -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/run-make/jobserver-error/Makefile b/tests/run-make/jobserver-error/Makefile index 4a1699cc74080..a7601b8671563 100644 --- a/tests/run-make/jobserver-error/Makefile +++ b/tests/run-make/jobserver-error/Makefile @@ -1,9 +1,15 @@ include ../tools.mk # only-linux -# ignore-test: This test randomly fails, see https://github.com/rust-lang/rust/issues/110321 +# ignore-cross-compile -# Test compiler behavior in case: `jobserver-auth` points to correct pipe which is not jobserver. +# Test compiler behavior in case environment specifies wrong jobserver. all: - bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3&1 | diff jobserver.stderr - + bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr - + bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3&1 | diff not_a_pipe.stderr - + +# This test randomly fails, see https://github.com/rust-lang/rust/issues/110321 +disabled: + bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3< <(cat /dev/null)' 2>&1 | diff poisoned_pipe.stderr - + diff --git a/tests/run-make/jobserver-error/cannot_open_fd.stderr b/tests/run-make/jobserver-error/cannot_open_fd.stderr new file mode 100644 index 0000000000000..343de5cd52c3b --- /dev/null +++ b/tests/run-make/jobserver-error/cannot_open_fd.stderr @@ -0,0 +1,6 @@ +warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,3"`: cannot open file descriptor 3 from the jobserver environment variable value: Bad file descriptor (os error 9) + | + = note: the build environment is likely misconfigured + +error: no input filename given + diff --git a/tests/run-make/jobserver-error/not_a_pipe.stderr b/tests/run-make/jobserver-error/not_a_pipe.stderr new file mode 100644 index 0000000000000..536c04576b9b9 --- /dev/null +++ b/tests/run-make/jobserver-error/not_a_pipe.stderr @@ -0,0 +1,4 @@ +warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,3"`: file descriptor 3 from the jobserver environment variable value is not a pipe + | + = note: the build environment is likely misconfigured + diff --git a/tests/run-make/jobserver-error/jobserver.stderr b/tests/run-make/jobserver-error/poisoned_pipe.stderr similarity index 64% rename from tests/run-make/jobserver-error/jobserver.stderr rename to tests/run-make/jobserver-error/poisoned_pipe.stderr index d18e15a262889..d129db9bc6764 100644 --- a/tests/run-make/jobserver-error/jobserver.stderr +++ b/tests/run-make/jobserver-error/poisoned_pipe.stderr @@ -1,4 +1,4 @@ error: failed to acquire jobserver token: early EOF on jobserver pipe -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/run-make/no-builtins-lto/Makefile b/tests/run-make/no-builtins-lto/Makefile index c8f05d9918b91..c7be4836466db 100644 --- a/tests/run-make/no-builtins-lto/Makefile +++ b/tests/run-make/no-builtins-lto/Makefile @@ -1,9 +1,15 @@ include ../tools.mk +# only-x86_64 + +# We want to check that `no_builtins` is correctly participating in LTO. +# First, verify that the `foo::foo` symbol can be found when linking. +# Next, verify that `memcpy` can be customized using `no_builtins` under LTO. +# Others will use the built-in memcpy. + all: - # Compile a `#![no_builtins]` rlib crate - $(RUSTC) no_builtins.rs - # Build an executable that depends on that crate using LTO. The no_builtins crate doesn't - # participate in LTO, so its rlib must be explicitly linked into the final binary. Verify this by - # grepping the linker arguments. - $(RUSTC) main.rs -C lto --print link-args | $(CGREP) 'libno_builtins.rlib' + $(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 foo.rs + $(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 no_builtins.rs + $(RUSTC) main.rs -C lto -C opt-level=2 -C debuginfo=0 -C save-temps -C metadata=1 -C codegen-units=1 + "$(LLVM_BIN_DIR)"/llvm-dis $(TMPDIR)/main.main.*-cgu.0.rcgu.lto.input.bc -o $(TMPDIR)/lto.ll + cat "$(TMPDIR)"/lto.ll | "$(LLVM_FILECHECK)" filecheck.lto.txt diff --git a/tests/run-make/no-builtins-lto/filecheck.lto.txt b/tests/run-make/no-builtins-lto/filecheck.lto.txt new file mode 100644 index 0000000000000..79dc3a51501db --- /dev/null +++ b/tests/run-make/no-builtins-lto/filecheck.lto.txt @@ -0,0 +1,17 @@ +CHECK: define{{.*}} void @bar +CHECK-NEXT: call void @no_builtins +CHECK-NEXT: call void @llvm.memcpy + +CHECK: define{{.*}} i32 @main +CHECK: call void @bar + +CHECK: define{{.*}} void @foo +CHECK-NEXT: call void @llvm.memcpy + +CHECK: define{{.*}} void @no_builtins +CHECK-SAME: #[[ATTR:[0-9]+]] { +CHECK: call void @foo +CHECK-NEXT: call{{.*}} @memcpy + +CHECK: attributes #[[ATTR]] +CHECK-SAME: no-builtins diff --git a/tests/run-make/no-builtins-lto/foo.rs b/tests/run-make/no-builtins-lto/foo.rs new file mode 100644 index 0000000000000..f09ac40b152a2 --- /dev/null +++ b/tests/run-make/no-builtins-lto/foo.rs @@ -0,0 +1,33 @@ +#![feature(lang_items, no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[inline(never)] +#[no_mangle] +pub unsafe fn foo(dest: *mut u8, src: *const u8) { + // should call `@llvm.memcpy`. + memcpy(dest, src, 1024); +} + +#[no_mangle] +#[inline(never)] +pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, _n: usize) -> *mut u8 { + *dest = 0; + return src as *mut u8; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for *mut u8 {} +impl Copy for *const u8 {} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} diff --git a/tests/run-make/no-builtins-lto/main.rs b/tests/run-make/no-builtins-lto/main.rs index 890c999c8ccf7..4421a2afbce68 100644 --- a/tests/run-make/no-builtins-lto/main.rs +++ b/tests/run-make/no-builtins-lto/main.rs @@ -1,3 +1,29 @@ +#![feature(no_core, start, lang_items)] +#![no_std] +// We use `no_core` to reduce the LTO products is small enough. +#![no_core] + extern crate no_builtins; +extern crate foo; + +#[cfg_attr(unix, link(name = "c"))] +#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))] +extern "C" {} + +#[start] +fn main(_: isize, p: *const *const u8) -> isize { + // Make sure the symbols are retained. + unsafe { bar(*p as *mut u8, *p); } + 0 +} + +#[no_mangle] +#[inline(never)] +pub unsafe extern "C" fn bar(dest: *mut u8, src: *const u8) { + no_builtins::no_builtins(dest, src); + // should call `@llvm.memcpy` + foo::memcpy(dest, src, 1024); +} -fn main() {} +#[lang = "eh_personality"] +fn eh_personality() {} diff --git a/tests/run-make/no-builtins-lto/no_builtins.rs b/tests/run-make/no-builtins-lto/no_builtins.rs index 5d001031a57fa..33ed68e3aee3d 100644 --- a/tests/run-make/no-builtins-lto/no_builtins.rs +++ b/tests/run-make/no-builtins-lto/no_builtins.rs @@ -1,2 +1,15 @@ +#![feature(lang_items, no_core)] +#![no_std] +#![no_core] #![crate_type = "lib"] #![no_builtins] + +extern crate foo; + +#[no_mangle] +pub unsafe fn no_builtins(dest: *mut u8, src: *const u8) { + // There should be no "undefined reference to `foo::foo'". + foo::foo(dest, src); + // should call `@memcpy` instead of `@llvm.memcpy`. + foo::memcpy(dest, src, 1024); +} diff --git a/tests/run-make/no-builtins-symbols/Makefile b/tests/run-make/no-builtins-symbols/Makefile new file mode 100644 index 0000000000000..4bb35c1d48659 --- /dev/null +++ b/tests/run-make/no-builtins-symbols/Makefile @@ -0,0 +1,7 @@ +include ../tools.mk + +# only-x86_64-unknown-linux-gnu + +all: + $(RUSTC) main.rs -o $(TMPDIR)/main + [ "$$("$(LLVM_BIN_DIR)"/llvm-nm -U $(TMPDIR)/main | grep -c __fixunssfti)" -eq "0" ] diff --git a/tests/run-make/pass-linker-flags/rs.rs b/tests/run-make/no-builtins-symbols/main.rs similarity index 100% rename from tests/run-make/pass-linker-flags/rs.rs rename to tests/run-make/no-builtins-symbols/main.rs diff --git a/tests/run-make/overwrite-input/file.stderr b/tests/run-make/overwrite-input/file.stderr index 9936962b4ee37..c13a270b067f4 100644 --- a/tests/run-make/overwrite-input/file.stderr +++ b/tests/run-make/overwrite-input/file.stderr @@ -2,5 +2,5 @@ warning: ignoring --out-dir flag due to -o flag error: the input file "main.rs" would be overwritten by the generated executable -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/run-make/overwrite-input/folder.stderr b/tests/run-make/overwrite-input/folder.stderr index 81b1e7367c75a..6e51cb812ceb1 100644 --- a/tests/run-make/overwrite-input/folder.stderr +++ b/tests/run-make/overwrite-input/folder.stderr @@ -2,5 +2,5 @@ warning: ignoring --out-dir flag due to -o flag error: the generated executable for the input file "main.rs" conflicts with the existing directory "." -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/run-make/overwrite-input/main.stderr b/tests/run-make/overwrite-input/main.stderr index 9936962b4ee37..c13a270b067f4 100644 --- a/tests/run-make/overwrite-input/main.stderr +++ b/tests/run-make/overwrite-input/main.stderr @@ -2,5 +2,5 @@ warning: ignoring --out-dir flag due to -o flag error: the input file "main.rs" would be overwritten by the generated executable -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/run-make/pass-linker-flags-flavor/Makefile b/tests/run-make/pass-linker-flags-flavor/Makefile new file mode 100644 index 0000000000000..1bb05d0f97478 --- /dev/null +++ b/tests/run-make/pass-linker-flags-flavor/Makefile @@ -0,0 +1,11 @@ +# only-linux + +include ../tools.mk + +all: + $(RUSTC) empty.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) empty.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg:+verbatim=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) empty.rs -Z unstable-options -C linker-flavor=ld -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*"a2".*d1.*"a3"' + $(RUSTC) attribute.rs -Z unstable-options -C linker-flavor=gnu-cc --print link-args | $(CGREP) -e 'l1.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) --cfg 'feature="verbatim"' attribute.rs -Z unstable-options -C linker-flavor=gnu-cc --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) attribute.rs -C linker-flavor=ld --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*"a2".*d1.*"a3"' diff --git a/tests/run-make/pass-linker-flags-flavor/attribute.rs b/tests/run-make/pass-linker-flags-flavor/attribute.rs new file mode 100644 index 0000000000000..d099165301bd3 --- /dev/null +++ b/tests/run-make/pass-linker-flags-flavor/attribute.rs @@ -0,0 +1,12 @@ +#![feature(link_arg_attribute)] + +#[link(kind = "static", name = "l1")] +#[cfg_attr(feature = "verbatim", link(kind = "link-arg", name = "a1", modifiers = "+verbatim"))] +#[cfg_attr(not(feature = "verbatim"), link(kind = "link-arg", name = "a1"))] +#[link(kind = "static", name = "l2")] +#[link(kind = "link-arg", name = "a2")] +#[link(kind = "dylib", name = "d1")] +#[link(kind = "link-arg", name = "a3")] +extern "C" {} + +fn main() {} diff --git a/tests/run-make/pass-linker-flags-flavor/empty.rs b/tests/run-make/pass-linker-flags-flavor/empty.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/pass-linker-flags-flavor/empty.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/pass-linker-flags-from-dep/Makefile b/tests/run-make/pass-linker-flags-from-dep/Makefile index b57389bb7d491..48b3b26ce81e6 100644 --- a/tests/run-make/pass-linker-flags-from-dep/Makefile +++ b/tests/run-make/pass-linker-flags-from-dep/Makefile @@ -4,7 +4,9 @@ all: # Build deps $(RUSTC) native_dep_1.rs --crate-type=staticlib $(RUSTC) native_dep_2.rs --crate-type=staticlib - $(RUSTC) rust_dep.rs -l static:-bundle=native_dep_1 -l link-arg=some_flag -l static:-bundle=native_dep_2 --crate-type=lib -Z unstable-options + $(RUSTC) rust_dep_flag.rs -l static:-bundle=native_dep_1 -l link-arg=some_flag -l static:-bundle=native_dep_2 --crate-type=lib -Z unstable-options + $(RUSTC) rust_dep_attr.rs --crate-type=lib # Check sequence of linker args - $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep.rlib --crate-type=bin --print link-args | $(CGREP) -e 'native_dep_1.*some_flag.*native_dep_2' + $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep_flag.rlib --crate-type=bin --print link-args | $(CGREP) -e 'native_dep_1.*some_flag.*native_dep_2' + $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep_attr.rlib --crate-type=bin --print link-args | $(CGREP) -e 'native_dep_1.*some_flag.*native_dep_2' diff --git a/tests/run-make/pass-linker-flags-from-dep/rust_dep_attr.rs b/tests/run-make/pass-linker-flags-from-dep/rust_dep_attr.rs new file mode 100644 index 0000000000000..ac5888ce610b3 --- /dev/null +++ b/tests/run-make/pass-linker-flags-from-dep/rust_dep_attr.rs @@ -0,0 +1,14 @@ +#![feature(link_arg_attribute)] + +#[link(kind = "static", name = "native_dep_1", modifiers = "-bundle")] +#[link(kind = "link-arg", name = "some_flag")] +#[link(kind = "static", name = "native_dep_2", modifiers = "-bundle")] +extern "C" { + pub fn foo(); +} + +pub fn f() { + unsafe { + foo(); + } +} diff --git a/tests/run-make/pass-linker-flags-from-dep/rust_dep.rs b/tests/run-make/pass-linker-flags-from-dep/rust_dep_flag.rs similarity index 100% rename from tests/run-make/pass-linker-flags-from-dep/rust_dep.rs rename to tests/run-make/pass-linker-flags-from-dep/rust_dep_flag.rs diff --git a/tests/run-make/pass-linker-flags/Makefile b/tests/run-make/pass-linker-flags/Makefile index 6ddbcbb1b08e6..226943e93bdc0 100644 --- a/tests/run-make/pass-linker-flags/Makefile +++ b/tests/run-make/pass-linker-flags/Makefile @@ -1,4 +1,5 @@ include ../tools.mk all: - $(RUSTC) rs.rs -Z unstable-options -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*a1.*l2.*a2.*d1.*a3' + $(RUSTC) empty.rs -Z unstable-options -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*a1.*l2.*a2.*d1.*a3' + $(RUSTC) attribute.rs --print link-args | $(CGREP) -e 'l1.*a1.*l2.*a2.*d1.*a3' diff --git a/tests/run-make/pass-linker-flags/attribute.rs b/tests/run-make/pass-linker-flags/attribute.rs new file mode 100644 index 0000000000000..6f784c01ff2a1 --- /dev/null +++ b/tests/run-make/pass-linker-flags/attribute.rs @@ -0,0 +1,11 @@ +#![feature(link_arg_attribute)] + +#[link(kind = "static", name = "l1")] +#[link(kind = "link-arg", name = "a1")] +#[link(kind = "static", name = "l2")] +#[link(kind = "link-arg", name = "a2")] +#[link(kind = "dylib", name = "d1")] +#[link(kind = "link-arg", name = "a3")] +extern "C" {} + +fn main() {} diff --git a/tests/run-make/pass-linker-flags/empty.rs b/tests/run-make/pass-linker-flags/empty.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/pass-linker-flags/empty.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/unknown-mod-stdin/unknown-mod.stderr b/tests/run-make/unknown-mod-stdin/unknown-mod.stderr index 81ff83938378c..bdbaa3817093c 100644 --- a/tests/run-make/unknown-mod-stdin/unknown-mod.stderr +++ b/tests/run-make/unknown-mod-stdin/unknown-mod.stderr @@ -7,6 +7,6 @@ error[E0583]: file not found for module `unknown` = help: to create the module `unknown`, create file "unknown.rs" or "unknown/mod.rs" = note: if there is a `mod unknown` elsewhere in the crate already, import it with `use crate::...` instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0583`. diff --git a/tests/run-make/valid-print-requests/valid-print-requests.stderr b/tests/run-make/valid-print-requests/valid-print-requests.stderr index 4f57550c29a7b..22bb102f9c989 100644 --- a/tests/run-make/valid-print-requests/valid-print-requests.stderr +++ b/tests/run-make/valid-print-requests/valid-print-requests.stderr @@ -1,2 +1,2 @@ -error: unknown print request `uwu`. Valid print requests are: `crate-name`, `file-names`, `sysroot`, `target-libdir`, `cfg`, `calling-conventions`, `target-list`, `target-cpus`, `target-features`, `relocation-models`, `code-models`, `tls-models`, `native-static-libs`, `stack-protector-strategies`, `target-spec-json`, `all-target-specs-json`, `link-args`, `split-debuginfo`, `deployment-target` +error: unknown print request `uwu`. Valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` diff --git a/tests/run-make/wasm-spurious-import/Makefile b/tests/run-make/wasm-builtins-import/Makefile similarity index 100% rename from tests/run-make/wasm-spurious-import/Makefile rename to tests/run-make/wasm-builtins-import/Makefile diff --git a/tests/run-make/wasm-spurious-import/main.rs b/tests/run-make/wasm-builtins-import/main.rs similarity index 61% rename from tests/run-make/wasm-spurious-import/main.rs rename to tests/run-make/wasm-builtins-import/main.rs index fcbead5e28bd2..5eb99df6ff74c 100644 --- a/tests/run-make/wasm-spurious-import/main.rs +++ b/tests/run-make/wasm-builtins-import/main.rs @@ -8,7 +8,8 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! { #[no_mangle] pub fn multer(a: i128, b: i128) -> i128 { - // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported - // panic function in case of a bug. We verify that no imports exist in our verifier. + // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported function + // such as panic or __multi3 (externally defined) in case of a bug. We verify that + // no imports exist in our verifier. a * b } diff --git a/tests/run-make/wasm-spurious-import/verify.js b/tests/run-make/wasm-builtins-import/verify.js similarity index 100% rename from tests/run-make/wasm-spurious-import/verify.js rename to tests/run-make/wasm-builtins-import/verify.js diff --git a/tests/rustdoc-gui/font-weight.goml b/tests/rustdoc-gui/font-weight.goml index 6fad128dab8c3..602b8d6f5b34c 100644 --- a/tests/rustdoc-gui/font-weight.goml +++ b/tests/rustdoc-gui/font-weight.goml @@ -2,7 +2,7 @@ go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html" assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"}) assert-css: ( - "//*[@class='structfield small-section-header']//a[text()='Alias']", + "//*[@class='structfield section-header']//a[text()='Alias']", {"font-weight": "400"}, ) assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"}) diff --git a/tests/rustdoc-gui/headers-color.goml b/tests/rustdoc-gui/headers-color.goml index a7ac94c4943cc..19185818f407e 100644 --- a/tests/rustdoc-gui/headers-color.goml +++ b/tests/rustdoc-gui/headers-color.goml @@ -31,7 +31,7 @@ define-function: ( ALL, ) go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" - assert-css: (".small-section-header a", {"color": |color|}, ALL) + assert-css: (".section-header a", {"color": |color|}, ALL) go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" // We select headings (h2, h3, h...). assert-css: (".docblock > :not(p) > a", {"color": |headings_color|}, ALL) diff --git a/tests/rustdoc-gui/item-decl-comment-highlighting.goml b/tests/rustdoc-gui/item-decl-comment-highlighting.goml new file mode 100644 index 0000000000000..60772693d6c5c --- /dev/null +++ b/tests/rustdoc-gui/item-decl-comment-highlighting.goml @@ -0,0 +1,73 @@ +// This test checks that comments in item declarations are highlighted. +go-to: "file://" + |DOC_PATH| + "/test_docs/private/enum.Enum.html" +show-text: true + +define-function: ( + "check-item-decl-comment", + (theme, url, comment_color), + block { + go-to: |url| + set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".item-decl .comment", {"color": |comment_color|}, ALL) + } +) + +define-function: ( + "check-items-for-theme", + (theme, comment_color), + block { + call-function: ("check-item-decl-comment", { + "theme": |theme|, + "url": "file://" + |DOC_PATH| + "/test_docs/private/enum.Enum.html", + "comment_color": |comment_color|, + }) + call-function: ("check-item-decl-comment", { + "theme": |theme|, + "url": "file://" + |DOC_PATH| + "/test_docs/private/struct.Struct.html", + "comment_color": |comment_color|, + }) + call-function: ("check-item-decl-comment", { + "theme": |theme|, + "url": "file://" + |DOC_PATH| + "/test_docs/private/struct.Tuple.html", + "comment_color": |comment_color|, + }) + call-function: ("check-item-decl-comment", { + "theme": |theme|, + "url": "file://" + |DOC_PATH| + "/test_docs/private/union.Union.html", + "comment_color": |comment_color|, + }) + call-function: ("check-item-decl-comment", { + "theme": |theme|, + "url": "file://" + |DOC_PATH| + "/proc_macro_test/macro.make_answer.html", + "comment_color": |comment_color|, + }) + call-function: ("check-item-decl-comment", { + "theme": |theme|, + "url": "file://" + |DOC_PATH| + "/proc_macro_test/derive.HelperAttr.html", + "comment_color": |comment_color|, + }) + } +) + +call-function: ( + "check-items-for-theme", + { + "theme": "ayu", + "comment_color": "#788797", + } +) +call-function: ( + "check-items-for-theme", + { + "theme": "dark", + "comment_color": "#8d8d8b", + } +) +call-function: ( + "check-items-for-theme", + { + "theme": "light", + "comment_color": "#8e908c", + } +) diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index 030ff8f8a3e70..b46d4255ee519 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -8,7 +8,22 @@ assert-size: (".item-info", {"width": 840}) assert-size: (".item-info .stab", {"width": 289}) assert-position: (".item-info .stab", {"x": 245}) +// We check that the display of the feature elements is not broken. It serves as regression +// test for . +set-window-size: (850, 800) +store-position: ( + "//*[@class='stab portability']//code[text()='Win32_System']", + {"x": first_line_x, "y": first_line_y}, +) +store-position: ( + "//*[@class='stab portability']//code[text()='Win32_System_Diagnostics']", + {"x": second_line_x, "y": second_line_y}, +) +assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272 +assert: |first_line_y| != |second_line_y| && |first_line_y| == 688 && |second_line_y| == 711 + // Now we ensure that they're not rendered on the same line. +set-window-size: (1100, 800) go-to: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html" // We first ensure that there are two item info on the trait. assert-count: ("#main-content > .item-info .stab", 2) diff --git a/tests/rustdoc-gui/search-tab.goml b/tests/rustdoc-gui/search-tab.goml index db1605ff220a1..b52bb0688c1b5 100644 --- a/tests/rustdoc-gui/search-tab.goml +++ b/tests/rustdoc-gui/search-tab.goml @@ -80,7 +80,7 @@ set-window-size: (851, 600) // Check the size and count in tabs assert-text: ("#search-tabs > button:nth-child(1) > .count", " (25) ") -assert-text: ("#search-tabs > button:nth-child(2) > .count", " (5)  ") +assert-text: ("#search-tabs > button:nth-child(2) > .count", " (6)  ") assert-text: ("#search-tabs > button:nth-child(3) > .count", " (0)  ") store-property: ("#search-tabs > button:nth-child(1)", {"offsetWidth": buttonWidth}) assert-property: ("#search-tabs > button:nth-child(2)", {"offsetWidth": |buttonWidth|}) diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml index 92b9045b734d7..0d72e670cf435 100644 --- a/tests/rustdoc-gui/sidebar-source-code.goml +++ b/tests/rustdoc-gui/sidebar-source-code.goml @@ -73,7 +73,7 @@ assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']" // Only "another_folder" should be "open" in "lib2". assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']" // All other trees should be collapsed. -assert-count: ("//*[@id='src-sidebar']/details[not(text()='lib2') and not(@open)]", 10) +assert-count: ("//*[@id='src-sidebar']/details[not(text()='lib2') and not(@open)]", 11) // We now switch to mobile mode. set-window-size: (600, 600) diff --git a/tests/rustdoc-gui/src/lib2/Cargo.toml b/tests/rustdoc-gui/src/lib2/Cargo.toml index 8bca77ff834d8..6c4ca27d5502b 100644 --- a/tests/rustdoc-gui/src/lib2/Cargo.toml +++ b/tests/rustdoc-gui/src/lib2/Cargo.toml @@ -6,6 +6,13 @@ edition = "2018" [lib] path = "lib.rs" +[features] +Win32 = ["Win32_System"] +Win32_System = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics = ["Win32_System_Diagnostics_Debug"] +Win32_System_Diagnostics_Debug = [] +default = ["Win32"] + [dependencies] implementors = { path = "./implementors" } http = { path = "./http" } diff --git a/tests/rustdoc-gui/src/lib2/lib.rs b/tests/rustdoc-gui/src/lib2/lib.rs index a2a3c31878ba5..b467b04405233 100644 --- a/tests/rustdoc-gui/src/lib2/lib.rs +++ b/tests/rustdoc-gui/src/lib2/lib.rs @@ -1,6 +1,7 @@ // ignore-tidy-linelength #![feature(doc_cfg)] +#![feature(doc_auto_cfg)] pub mod another_folder; pub mod another_mod; @@ -28,6 +29,14 @@ impl Foo { /// Some documentation /// # A Heading pub fn a_method(&self) {} + + #[cfg(all( + feature = "Win32", + feature = "Win32_System", + feature = "Win32_System_Diagnostics", + feature = "Win32_System_Diagnostics_Debug" + ))] + pub fn lot_of_features() {} } #[doc(cfg(feature = "foo-method"))] diff --git a/tests/rustdoc-gui/src/proc_macro_test/Cargo.lock b/tests/rustdoc-gui/src/proc_macro_test/Cargo.lock new file mode 100644 index 0000000000000..eae9d75367f75 --- /dev/null +++ b/tests/rustdoc-gui/src/proc_macro_test/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "proc_macro_test" +version = "0.1.0" diff --git a/tests/rustdoc-gui/src/proc_macro_test/Cargo.toml b/tests/rustdoc-gui/src/proc_macro_test/Cargo.toml new file mode 100644 index 0000000000000..768ced65184e8 --- /dev/null +++ b/tests/rustdoc-gui/src/proc_macro_test/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "proc_macro_test" +version = "0.1.0" +edition = "2021" + +[lib] +path = "lib.rs" +proc-macro = true diff --git a/tests/rustdoc-gui/src/proc_macro_test/lib.rs b/tests/rustdoc-gui/src/proc_macro_test/lib.rs new file mode 100644 index 0000000000000..8a6c62df87c4b --- /dev/null +++ b/tests/rustdoc-gui/src/proc_macro_test/lib.rs @@ -0,0 +1,11 @@ +use proc_macro::TokenStream; + +#[proc_macro] +pub fn make_answer(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() +} + +#[proc_macro_derive(HelperAttr, attributes(helper))] +pub fn derive_helper_attr(_item: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs index c7d115bdb98c3..0bc777230bf1b 100644 --- a/tests/rustdoc-gui/src/test_docs/lib.rs +++ b/tests/rustdoc-gui/src/test_docs/lib.rs @@ -593,3 +593,21 @@ pub mod foreign_impl_order { fn f(&mut self, fg: [u8; 3]) {} } } + +pub mod private { + pub struct Tuple(u32, u8); + pub struct Struct { + a: u8, + } + + pub union Union { + a: u8, + b: u16, + } + + pub enum Enum { + A, + #[doc(hidden)] + B, + } +} diff --git a/tests/rustdoc-gui/where-whitespace.goml b/tests/rustdoc-gui/where-whitespace.goml index 69e6c3356a405..da104fa40116f 100644 --- a/tests/rustdoc-gui/where-whitespace.goml +++ b/tests/rustdoc-gui/where-whitespace.goml @@ -3,15 +3,15 @@ go-to: "file://" + |DOC_PATH| + "/lib2/trait.Whitespace.html" show-text: true // First, we check in the trait definition if the where clause is "on its own" (not on the same // line than "pub trait Whitespace"). -compare-elements-position-false: (".item-decl code", ".where.fmt-newline", ("y")) +compare-elements-position-false: (".item-decl code", "div.where", ("y")) // And that the code following it isn't on the same line either. -compare-elements-position-false: (".item-decl .fn", ".where.fmt-newline", ("y")) +compare-elements-position-false: (".item-decl .fn", "div.where", ("y")) go-to: "file://" + |DOC_PATH| + "/lib2/struct.WhereWhitespace.html" // We make the screen a bit wider to ensure that the trait impl is on one line. set-window-size: (915, 915) -compare-elements-position-false: ("#method\.new .fn", "#method\.new .where.fmt-newline", ("y")) +compare-elements-position-false: ("#method\.new .fn", "#method\.new div.where", ("y")) // We ensure that both the trait name and the struct name are on the same line in // "impl Whitespace<&K> for WhereWhitespace". compare-elements-position: ( @@ -22,6 +22,6 @@ compare-elements-position: ( // And we now check that the where condition isn't on the same line. compare-elements-position-false: ( "#trait-implementations-list .impl h3 .trait", - "#trait-implementations-list .impl h3 .where.fmt-newline", + "#trait-implementations-list .impl h3 div.where", ("y"), ) diff --git a/tests/rustdoc-js-std/iterator-type-signatures.js b/tests/rustdoc-js-std/iterator-type-signatures.js new file mode 100644 index 0000000000000..c18ffc1651c15 --- /dev/null +++ b/tests/rustdoc-js-std/iterator-type-signatures.js @@ -0,0 +1,29 @@ +// ignore-order + +const FILTER_CRATE = "std"; + +const EXPECTED = [ + { + 'query': 'iterator -> option', + 'others': [ + { 'path': 'std::iter::Iterator', 'name': 'max' }, + { 'path': 'std::iter::Iterator', 'name': 'min' }, + { 'path': 'std::iter::Iterator', 'name': 'last' }, + { 'path': 'std::iter::Iterator', 'name': 'next' }, + ], + }, + { + 'query': 'iterator, usize -> option', + 'others': [ + { 'path': 'std::iter::Iterator', 'name': 'nth' }, + ], + }, + { + // Something should be done so that intoiterator is considered a match + // for plain iterator. + 'query': 'iterator, intoiterator -> ordering', + 'others': [ + { 'path': 'std::iter::Iterator', 'name': 'cmp' }, + ], + }, +]; diff --git a/tests/rustdoc-js-std/keyword.js b/tests/rustdoc-js-std/keyword.js index b85ba34138bae..1837b1e71f782 100644 --- a/tests/rustdoc-js-std/keyword.js +++ b/tests/rustdoc-js-std/keyword.js @@ -3,7 +3,7 @@ const EXPECTED = { 'query': 'fn', 'others': [ - { 'path': 'std', 'name': 'fn', ty: 15 }, // 15 is for primitive types - { 'path': 'std', 'name': 'fn', ty: 21 }, // 21 is for keywords + { 'path': 'std', 'name': 'fn', ty: 1 }, // 1 is for primitive types + { 'path': 'std', 'name': 'fn', ty: 0 }, // 0 is for keywords ], }; diff --git a/tests/rustdoc-js-std/macro-check.js b/tests/rustdoc-js-std/macro-check.js index c22b1753fd71b..37d5e7dae62e3 100644 --- a/tests/rustdoc-js-std/macro-check.js +++ b/tests/rustdoc-js-std/macro-check.js @@ -3,7 +3,7 @@ const EXPECTED = { 'query': 'panic', 'others': [ - { 'path': 'std', 'name': 'panic', ty: 14 }, // 15 is for macros - { 'path': 'std', 'name': 'panic', ty: 0 }, // 0 is for modules + { 'path': 'std', 'name': 'panic', ty: 16 }, // 16 is for macros + { 'path': 'std', 'name': 'panic', ty: 2 }, // 2 is for modules ], }; diff --git a/tests/rustdoc-js-std/parser-bindings.js b/tests/rustdoc-js-std/parser-bindings.js new file mode 100644 index 0000000000000..c4909c6242d75 --- /dev/null +++ b/tests/rustdoc-js-std/parser-bindings.js @@ -0,0 +1,245 @@ +const PARSED = [ + { + query: 'A', + elems: [ + { + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + bindings: [ + [ + 'b', + [ + { + name: "c", + fullPath: ["c"], + pathWithoutLast: [], + pathLast: "c", + generics: [], + typeFilter: -1, + }, + ] + ], + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'A', + returned: [], + userQuery: 'a', + error: null, + }, + { + query: 'A', + elems: [ + { + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + bindings: [ + [ + 'b', + [{ + name: "c", + fullPath: ["c"], + pathWithoutLast: [], + pathLast: "c", + generics: [], + typeFilter: -1, + }] + ], + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'A', + returned: [], + userQuery: 'a', + error: null, + }, + { + query: 'A', + elems: [ + { + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + bindings: [ + [ + 'b', + [{ + name: "never", + fullPath: ["never"], + pathWithoutLast: [], + pathLast: "never", + generics: [], + typeFilter: 1, + }] + ], + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'A', + returned: [], + userQuery: 'a', + error: null, + }, + { + query: 'A', + elems: [ + { + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + bindings: [ + [ + 'b', + [{ + name: "[]", + fullPath: ["[]"], + pathWithoutLast: [], + pathLast: "[]", + generics: [], + typeFilter: 1, + }] + ], + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'A', + returned: [], + userQuery: 'a', + error: null, + }, + { + query: 'A', + elems: [ + { + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + bindings: [ + [ + 'b', + [{ + name: "[]", + fullPath: ["[]"], + pathWithoutLast: [], + pathLast: "[]", + generics: [ + { + name: "never", + fullPath: ["never"], + pathWithoutLast: [], + pathLast: "never", + generics: [], + typeFilter: 1, + }, + ], + typeFilter: 1, + }] + ], + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'A', + returned: [], + userQuery: 'a', + error: null, + }, + { + query: 'A', + elems: [], + foundElems: 0, + original: 'A', + returned: [], + userQuery: 'a', + error: "Cannot write `=` twice in a binding", + }, + { + query: 'A', + elems: [], + foundElems: 0, + original: 'A', + returned: [], + userQuery: 'a', + error: "Unexpected `>` after `=`", + }, + { + query: 'B=C', + elems: [], + foundElems: 0, + original: 'B=C', + returned: [], + userQuery: 'b=c', + error: "Type parameter `=` must be within generics list", + }, + { + query: '[B=C]', + elems: [], + foundElems: 0, + original: '[B=C]', + returned: [], + userQuery: '[b=c]', + error: "Type parameter `=` cannot be within slice `[]`", + }, + { + query: 'A=C>', + elems: [ + { + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + bindings: [ + [ + 'b', + [ + { + name: "c", + fullPath: ["c"], + pathWithoutLast: [], + pathLast: "c", + generics: [], + typeFilter: -1, + }, + { + name: "x", + fullPath: ["x"], + pathWithoutLast: [], + pathLast: "x", + generics: [], + typeFilter: -1, + }, + ], + ], + ], + typeFilter: -1, + }, + ], + foundElems: 1, + original: 'A=C>', + returned: [], + userQuery: 'a=c>', + error: null, + }, +]; diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js index b32bfea5439aa..f9f9c4f4de8c6 100644 --- a/tests/rustdoc-js-std/parser-errors.js +++ b/tests/rustdoc-js-std/parser-errors.js @@ -17,6 +17,15 @@ const PARSED = [ userQuery: "->

    ", error: "Found generics without a path", }, + { + query: '-> *', + elems: [], + foundElems: 0, + original: "-> *", + returned: [], + userQuery: "-> *", + error: "Unexpected `*`", + }, { query: 'a<"P">', elems: [], @@ -143,6 +152,24 @@ const PARSED = [ userQuery: "a::::b", error: "Unexpected `::::`", }, + { + query: "a:: ::b", + elems: [], + foundElems: 0, + original: "a:: ::b", + returned: [], + userQuery: "a:: ::b", + error: "Unexpected `:: ::`", + }, + { + query: "a::\t::b", + elems: [], + foundElems: 0, + original: "a:: ::b", + returned: [], + userQuery: "a:: ::b", + error: "Unexpected `:: ::`", + }, { query: "a::b::", elems: [], @@ -303,7 +330,7 @@ const PARSED = [ original: '->a<>b', returned: [], userQuery: '->a<>b', - error: 'Expected `,` after `>`, found `b`', + error: 'Expected `,` or `=` after `>`, found `b`', }, { query: "a<->", @@ -314,24 +341,6 @@ const PARSED = [ userQuery: 'a<->', error: 'Unexpected `-` after `<`', }, - { - query: "a:: a", - elems: [], - foundElems: 0, - original: 'a:: a', - returned: [], - userQuery: 'a:: a', - error: 'Unexpected `:: `', - }, - { - query: "a ::a", - elems: [], - foundElems: 0, - original: 'a ::a', - returned: [], - userQuery: 'a ::a', - error: 'Unexpected ` ::`', - }, { query: "a:", elems: [], diff --git a/tests/rustdoc-js-std/parser-filter.js b/tests/rustdoc-js-std/parser-filter.js index 3b9cc5b1bf092..a1dd0ea3b5a99 100644 --- a/tests/rustdoc-js-std/parser-filter.js +++ b/tests/rustdoc-js-std/parser-filter.js @@ -7,7 +7,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "foo", generics: [], - typeFilter: 5, + typeFilter: 7, }], foundElems: 1, original: "fn:foo", @@ -23,7 +23,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "foo", generics: [], - typeFilter: 4, + typeFilter: 6, }], foundElems: 1, original: "enum : foo", @@ -48,7 +48,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "macro", generics: [], - typeFilter: 14, + typeFilter: 16, }], foundElems: 1, original: "macro!", @@ -64,7 +64,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "mac", generics: [], - typeFilter: 14, + typeFilter: 16, }], foundElems: 1, original: "macro:mac!", @@ -80,7 +80,7 @@ const PARSED = [ pathWithoutLast: ["a"], pathLast: "mac", generics: [], - typeFilter: 14, + typeFilter: 16, }], foundElems: 1, original: "a::mac!", @@ -99,7 +99,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "foo", generics: [], - typeFilter: 5, + typeFilter: 7, }], userQuery: "-> fn:foo", error: null, @@ -121,10 +121,10 @@ const PARSED = [ pathWithoutLast: [], pathLast: "bar", generics: [], - typeFilter: 5, + typeFilter: 7, } ], - typeFilter: 5, + typeFilter: 7, }], userQuery: "-> fn:foo", error: null, @@ -146,7 +146,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "bar", generics: [], - typeFilter: 5, + typeFilter: 7, }, { name: "baz::fuzz", @@ -154,10 +154,10 @@ const PARSED = [ pathWithoutLast: ["baz"], pathLast: "fuzz", generics: [], - typeFilter: 4, + typeFilter: 6, }, ], - typeFilter: 5, + typeFilter: 7, }], userQuery: "-> fn:foo", error: null, diff --git a/tests/rustdoc-js-std/parser-ident.js b/tests/rustdoc-js-std/parser-ident.js index f65a7ce6692b0..cc79c58f1da3a 100644 --- a/tests/rustdoc-js-std/parser-ident.js +++ b/tests/rustdoc-js-std/parser-ident.js @@ -13,7 +13,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "never", generics: [], - typeFilter: 15, + typeFilter: 1, }, ], typeFilter: -1, @@ -32,7 +32,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "never", generics: [], - typeFilter: 15, + typeFilter: 1, }], foundElems: 1, original: "!", @@ -48,7 +48,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "a", generics: [], - typeFilter: 14, + typeFilter: 16, }], foundElems: 1, original: "a!", diff --git a/tests/rustdoc-js-std/parser-paths.js b/tests/rustdoc-js-std/parser-paths.js index 8d4dedf3f46c8..774e5d028cc2c 100644 --- a/tests/rustdoc-js-std/parser-paths.js +++ b/tests/rustdoc-js-std/parser-paths.js @@ -15,6 +15,54 @@ const PARSED = [ userQuery: "a::b", error: null, }, + { + query: "a:: a", + elems: [{ + name: "a:: a", + fullPath: ["a", "a"], + pathWithoutLast: ["a"], + pathLast: "a", + generics: [], + typeFilter: -1, + }], + foundElems: 1, + original: 'a:: a', + returned: [], + userQuery: 'a:: a', + error: null, + }, + { + query: "a ::a", + elems: [{ + name: "a ::a", + fullPath: ["a", "a"], + pathWithoutLast: ["a"], + pathLast: "a", + generics: [], + typeFilter: -1, + }], + foundElems: 1, + original: 'a ::a', + returned: [], + userQuery: 'a ::a', + error: null, + }, + { + query: "a :: a", + elems: [{ + name: "a :: a", + fullPath: ["a", "a"], + pathWithoutLast: ["a"], + pathLast: "a", + generics: [], + typeFilter: -1, + }], + foundElems: 1, + original: 'a :: a', + returned: [], + userQuery: 'a :: a', + error: null, + }, { query: 'A::B,C', elems: [ diff --git a/tests/rustdoc-js-std/parser-returned.js b/tests/rustdoc-js-std/parser-returned.js index 6ea86609115bf..44e517c49b59c 100644 --- a/tests/rustdoc-js-std/parser-returned.js +++ b/tests/rustdoc-js-std/parser-returned.js @@ -89,7 +89,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "never", generics: [], - typeFilter: 15, + typeFilter: 1, }], userQuery: "-> !", error: null, diff --git a/tests/rustdoc-js-std/parser-separators.js b/tests/rustdoc-js-std/parser-separators.js index 00c489b51a6a2..7f95f61b006bb 100644 --- a/tests/rustdoc-js-std/parser-separators.js +++ b/tests/rustdoc-js-std/parser-separators.js @@ -5,7 +5,7 @@ const PARSED = [ query: 'aaaaaa b', elems: [ { - name: 'aaaaaa\tb', + name: 'aaaaaa b', fullPath: ['aaaaaa', 'b'], pathWithoutLast: ['aaaaaa'], pathLast: 'b', @@ -14,9 +14,9 @@ const PARSED = [ }, ], foundElems: 1, - original: "aaaaaa b", + original: "aaaaaa b", returned: [], - userQuery: "aaaaaa b", + userQuery: "aaaaaa b", error: null, }, { @@ -40,9 +40,9 @@ const PARSED = [ }, ], foundElems: 2, - original: "aaaaaa, b", + original: "aaaaaa, b", returned: [], - userQuery: "aaaaaa, b", + userQuery: "aaaaaa, b", error: null, }, { @@ -93,7 +93,7 @@ const PARSED = [ query: 'a\tb', elems: [ { - name: 'a\tb', + name: 'a b', fullPath: ['a', 'b'], pathWithoutLast: ['a'], pathLast: 'b', @@ -102,9 +102,9 @@ const PARSED = [ }, ], foundElems: 1, - original: "a\tb", + original: "a b", returned: [], - userQuery: "a\tb", + userQuery: "a b", error: null, }, { @@ -176,7 +176,7 @@ const PARSED = [ pathLast: 'a', generics: [ { - name: 'b\tc', + name: 'b c', fullPath: ['b', 'c'], pathWithoutLast: ['b'], pathLast: 'c', @@ -187,9 +187,9 @@ const PARSED = [ }, ], foundElems: 1, - original: "a", + original: "a", returned: [], - userQuery: "a", + userQuery: "a", error: null, }, ]; diff --git a/tests/rustdoc-js-std/parser-slice-array.js b/tests/rustdoc-js-std/parser-slice-array.js index c22b7870dbf88..239391bed4208 100644 --- a/tests/rustdoc-js-std/parser-slice-array.js +++ b/tests/rustdoc-js-std/parser-slice-array.js @@ -43,16 +43,16 @@ const PARSED = [ pathWithoutLast: [], pathLast: "[]", generics: [], - typeFilter: 15, + typeFilter: 1, }, ], - typeFilter: 15, + typeFilter: 1, }, ], - typeFilter: 15, + typeFilter: 1, }, ], - typeFilter: 15, + typeFilter: 1, }, ], foundElems: 1, @@ -70,7 +70,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "[]", generics: [], - typeFilter: 15, + typeFilter: 1, }, { name: "u8", @@ -105,7 +105,7 @@ const PARSED = [ typeFilter: -1, }, ], - typeFilter: 15, + typeFilter: 1, }, ], foundElems: 1, @@ -140,7 +140,7 @@ const PARSED = [ typeFilter: -1, }, ], - typeFilter: 15, + typeFilter: 1, }, ], foundElems: 1, @@ -176,7 +176,7 @@ const PARSED = [ typeFilter: -1, }, ], - typeFilter: 15, + typeFilter: 1, }, ], foundElems: 1, @@ -194,7 +194,7 @@ const PARSED = [ pathWithoutLast: [], pathLast: "[]", generics: [], - typeFilter: 15, + typeFilter: 1, }, ], foundElems: 1, @@ -284,7 +284,7 @@ const PARSED = [ typeFilter: -1, }, ], - typeFilter: 15, + typeFilter: 1, }, ], foundElems: 1, diff --git a/tests/rustdoc-js-std/parser-weird-queries.js b/tests/rustdoc-js-std/parser-weird-queries.js index 720ef66c16525..ba68c9717c51a 100644 --- a/tests/rustdoc-js-std/parser-weird-queries.js +++ b/tests/rustdoc-js-std/parser-weird-queries.js @@ -92,9 +92,9 @@ const PARSED = [ query: 'mod\t:', elems: [], foundElems: 0, - original: 'mod\t:', + original: 'mod :', returned: [], - userQuery: 'mod\t:', + userQuery: 'mod :', error: "Unexpected `:` (expected path after type filter `mod:`)", }, ]; diff --git a/tests/rustdoc-js-std/simd-type-signatures.js b/tests/rustdoc-js-std/simd-type-signatures.js index 5c7cf372bce14..c07f15dcbe8b1 100644 --- a/tests/rustdoc-js-std/simd-type-signatures.js +++ b/tests/rustdoc-js-std/simd-type-signatures.js @@ -13,27 +13,27 @@ const EXPECTED = [ { 'path': 'std::simd::prelude::Simd', 'name': 'simd_max', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+LANES%3E/method.simd_max' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+N%3E/method.simd_max' }, { 'path': 'std::simd::prelude::Simd', 'name': 'simd_min', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+LANES%3E/method.simd_min' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+N%3E/method.simd_min' }, { 'path': 'std::simd::prelude::Simd', 'name': 'simd_clamp', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+LANES%3E/method.simd_clamp' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci16,+N%3E/method.simd_clamp' }, { 'path': 'std::simd::prelude::Simd', 'name': 'saturating_add', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci16,+LANES%3E/method.saturating_add' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci16,+N%3E/method.saturating_add' }, { 'path': 'std::simd::prelude::Simd', 'name': 'saturating_sub', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci16,+LANES%3E/method.saturating_sub' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci16,+N%3E/method.saturating_sub' }, ], }, @@ -43,27 +43,27 @@ const EXPECTED = [ { 'path': 'std::simd::prelude::Simd', 'name': 'simd_max', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+LANES%3E/method.simd_max' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+N%3E/method.simd_max' }, { 'path': 'std::simd::prelude::Simd', 'name': 'simd_min', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+LANES%3E/method.simd_min' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+N%3E/method.simd_min' }, { 'path': 'std::simd::prelude::Simd', 'name': 'simd_clamp', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+LANES%3E/method.simd_clamp' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdOrd-for-Simd%3Ci8,+N%3E/method.simd_clamp' }, { 'path': 'std::simd::prelude::Simd', 'name': 'saturating_add', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci8,+LANES%3E/method.saturating_add' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci8,+N%3E/method.saturating_add' }, { 'path': 'std::simd::prelude::Simd', 'name': 'saturating_sub', - 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci8,+LANES%3E/method.saturating_sub' + 'href': '../std/simd/prelude/struct.Simd.html#impl-SimdInt-for-Simd%3Ci8,+N%3E/method.saturating_sub' }, ], }, diff --git a/tests/rustdoc-js/assoc-type-backtrack.js b/tests/rustdoc-js/assoc-type-backtrack.js new file mode 100644 index 0000000000000..493e1a9910d18 --- /dev/null +++ b/tests/rustdoc-js/assoc-type-backtrack.js @@ -0,0 +1,163 @@ +// exact-check + +const EXPECTED = [ + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' }, + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' }, + ], + }, + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' }, + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' }, + ], + }, + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'fold' }, + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'fold' }, + ], + }, + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [], + }, + { + 'query': 'mytrait, mytrait2 -> T', + 'correction': null, + 'others': [], + }, + { + 'query': 'mytrait -> Option', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'next' }, + ], + }, + { + 'query': 'mytrait -> Option', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyTrait', 'name': 'next' }, + ], + }, + { + 'query': 'mytrait -> Option', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'next' }, + ], + }, + { + 'query': 'mytrait -> Option', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::Cloned', 'name': 'next' }, + ], + }, + // The first two define the base case. + { + 'query': 'myintofuture> -> myfuture', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future' }, + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' }, + ], + }, + { + 'query': 'myintofuture>, myintofuture> -> myfuture', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' }, + ], + }, + // Unboxings of the one-argument case. + { + 'query': 'myfuture -> myfuture', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future' }, + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' }, + ], + }, + { + 'query': 'myintofuture> -> myfuture', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future' }, + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' }, + ], + }, + // Invalid unboxing of the one-argument case. + // If you unbox one of the myfutures, you need to unbox both of them. + { + 'query': 'myintofuture -> myfuture', + 'correction': null, + 'others': [], + }, + // Unboxings of the two-argument case. + { + 'query': 'myintofuture, myintofuture -> t', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' }, + ], + }, + { + 'query': 'myintofuture, myintofuture -> myfuture', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' }, + ], + }, + { + 'query': 'myintofuture, myintofuture -> myfuture', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' }, + ], + }, + { + 'query': 'myfuture, myfuture -> myfuture', + 'correction': null, + 'others': [ + { 'path': 'assoc_type_backtrack::MyIntoFuture', 'name': 'into_future_2' }, + ], + }, + // Invalid unboxings of the two-argument case. + // If you unbox one of the myfutures, you need to unbox all of them. + { + 'query': 'myintofuture, myintofuture> -> myfuture', + 'correction': null, + 'others': [], + }, + { + 'query': 'myintofuture>, myintofuture -> myfuture', + 'correction': null, + 'others': [], + }, + { + 'query': 'myintofuture>, myintofuture> -> t', + 'correction': null, + 'others': [], + }, + // different generics don't match up either + { + 'query': 'myintofuture>, myintofuture> -> myfuture', + 'correction': null, + 'others': [], + }, + { + 'query': 'myintofuture -> myfuture', + 'correction': null, + 'others': [], + }, +]; diff --git a/tests/rustdoc-js/assoc-type-backtrack.rs b/tests/rustdoc-js/assoc-type-backtrack.rs new file mode 100644 index 0000000000000..c3cdd78c6e1c4 --- /dev/null +++ b/tests/rustdoc-js/assoc-type-backtrack.rs @@ -0,0 +1,38 @@ +pub trait MyTrait2 { + type Output; +} + +pub trait MyTrait { + type Item; + fn next(&mut self) -> Option; + fn fold(self, init: B, f: F) -> B where + Self: Sized, + F: MyTrait2<(B, Self::Item), Output=B>; +} + +pub struct Cloned(I); + +impl<'a, T, I> MyTrait for Cloned where + T: 'a + Clone, + I: MyTrait +{ + type Item = T; + fn next(&mut self) -> Option { loop {} } + fn fold(self, init: B, f: F) -> B where + Self: Sized, + F: MyTrait2<(B, Self::Item), Output=B> + { + loop {} + } +} + +pub trait MyFuture { + type Output; +} + +pub trait MyIntoFuture { + type Output; + type Fut: MyFuture; + fn into_future(self) -> Self::Fut; + fn into_future_2(self, other: Self) -> Self::Fut; +} diff --git a/tests/rustdoc-js/assoc-type-loop.js b/tests/rustdoc-js/assoc-type-loop.js new file mode 100644 index 0000000000000..f0192371ab41a --- /dev/null +++ b/tests/rustdoc-js/assoc-type-loop.js @@ -0,0 +1,9 @@ +// Crash reduction of +// https://github.com/rust-lang/rust/issues/118242 + +const EXPECTED = [ + { + 'query': 't', + 'correction': null, + }, +]; diff --git a/tests/rustdoc-js/assoc-type-loop.rs b/tests/rustdoc-js/assoc-type-loop.rs new file mode 100644 index 0000000000000..f123c83f50fdf --- /dev/null +++ b/tests/rustdoc-js/assoc-type-loop.rs @@ -0,0 +1,35 @@ +#![crate_name="foo"] + +// reduced from sqlx 0.7.3 +use std::future::Future; +use std::pin::Pin; +use std::ops::{Deref, DerefMut}; +pub enum Error {} +pub trait Acquire<'c> { + type Database: Database; + type Connection: Deref::Connection> + DerefMut + Send; +} +pub trait Database { + type Connection: Connection; +} +pub trait Connection { + type Database: Database; + type Options: ConnectionOptions; + fn begin( + &mut self + ) -> Pin, Error>> + Send + '_>> + where + Self: Sized; +} +pub trait ConnectionOptions { + type Connection: Connection; +} +pub struct Transaction<'c, DB: Database> { + _db: &'c DB, +} +impl<'t, 'c, DB: Database> Acquire<'t> for &'t mut Transaction<'c, DB> + where ::Connection: Send +{ + type Database = DB; + type Connection = &'t mut ::Connection; +} diff --git a/tests/rustdoc-js/assoc-type.js b/tests/rustdoc-js/assoc-type.js new file mode 100644 index 0000000000000..cc3afaa17c07d --- /dev/null +++ b/tests/rustdoc-js/assoc-type.js @@ -0,0 +1,45 @@ +// exact-check + +const EXPECTED = [ + // if I just use generics, then the generics version + // and the type binding version both show up + { + 'query': 'iterator -> u32', + 'correction': null, + 'others': [ + { 'path': 'assoc_type', 'name': 'my_fn' }, + { 'path': 'assoc_type::my', 'name': 'other_fn' }, + ], + }, + { + 'query': 'iterator', + 'correction': null, + 'in_args': [ + { 'path': 'assoc_type', 'name': 'my_fn' }, + { 'path': 'assoc_type::my', 'name': 'other_fn' }, + ], + }, + // if I write an explicit binding, only it shows up + { + 'query': 'iterator -> u32', + 'correction': null, + 'others': [ + { 'path': 'assoc_type', 'name': 'my_fn' }, + ], + }, + // case insensitivity + { + 'query': 'iterator -> u32', + 'correction': null, + 'others': [ + { 'path': 'assoc_type', 'name': 'my_fn' }, + ], + }, + // wrong binding name, no result + { + 'query': 'iterator -> u32', + 'correction': null, + 'in_args': [], + 'others': [], + }, +]; diff --git a/tests/rustdoc-js/assoc-type.rs b/tests/rustdoc-js/assoc-type.rs new file mode 100644 index 0000000000000..e12e73cb546df --- /dev/null +++ b/tests/rustdoc-js/assoc-type.rs @@ -0,0 +1,12 @@ +pub fn my_fn>(_x: X) -> u32 { + 3 +} + +pub struct Something; + +pub mod my { + pub trait Iterator {} + pub fn other_fn>(_: X) -> u32 { + 3 + } +} diff --git a/tests/rustdoc-js/gat.js b/tests/rustdoc-js/gat.js new file mode 100644 index 0000000000000..7cb6a85d135f9 --- /dev/null +++ b/tests/rustdoc-js/gat.js @@ -0,0 +1,57 @@ +// exact-check + +const EXPECTED = [ + { + 'query': 'foo=u8> -> u32', + 'correction': null, + 'in_args': [], + 'others': [ + { 'path': 'gat', 'name': 'sample' }, + ], + }, + { + 'query': 'foo=u8> -> !', + 'correction': null, + 'in_args': [], + 'others': [ + { 'path': 'gat', 'name': 'synergy' }, + ], + }, + { + 'query': 'foo=u8>', + 'correction': null, + 'in_args': [ + { 'path': 'gat', 'name': 'sample' }, + { 'path': 'gat', 'name': 'synergy' }, + ], + }, + { + 'query': 'foo=u32>', + 'correction': null, + 'in_args': [ + { 'path': 'gat', 'name': 'consider' }, + ], + }, + { + // This one is arguably a bug, because the way rustdoc + // stores GATs in the search index is sloppy, but it's + // precise enough to match most of the samples in the + // GAT initiative repo + 'query': 'foo=u8>', + 'correction': null, + 'in_args': [ + { 'path': 'gat', 'name': 'consider' }, + ], + }, + { + // This one is arguably a bug, because the way rustdoc + // stores GATs in the search index is sloppy, but it's + // precise enough to match most of the samples in the + // GAT initiative repo + 'query': 'foo=T>', + 'correction': null, + 'in_args': [ + { 'path': 'gat', 'name': 'integrate' }, + ], + }, +]; diff --git a/tests/rustdoc-js/gat.rs b/tests/rustdoc-js/gat.rs new file mode 100644 index 0000000000000..b4861cc683ff3 --- /dev/null +++ b/tests/rustdoc-js/gat.rs @@ -0,0 +1,8 @@ +pub trait Foo { + type Assoc; +} + +pub fn sample = u8>>(_: X) -> u32 { loop {} } +pub fn synergy(_: impl Foo = u8>) -> ! { loop {} } +pub fn consider(_: impl Foo = u32>) -> bool { loop {} } +pub fn integrate(_: impl Foo = T>) -> T { loop {} } diff --git a/tests/rustdoc-js/generics2.js b/tests/rustdoc-js/generics2.js new file mode 100644 index 0000000000000..f08704349a444 --- /dev/null +++ b/tests/rustdoc-js/generics2.js @@ -0,0 +1,22 @@ +// exact-check + +const EXPECTED = [ + { + 'query': 'outside, outside -> outside', + 'others': [], + }, + { + 'query': 'outside, outside -> outside', + 'others': [], + }, + { + 'query': 'outside, outside -> outside', + 'others': [], + }, + { + 'query': 'outside, outside -> outside', + 'others': [ + {"path": "generics2", "name": "should_match_3"} + ], + }, +]; diff --git a/tests/rustdoc-js/generics2.rs b/tests/rustdoc-js/generics2.rs new file mode 100644 index 0000000000000..1177ade683164 --- /dev/null +++ b/tests/rustdoc-js/generics2.rs @@ -0,0 +1,13 @@ +pub struct Outside(T); + +pub fn no_match(a: Outside, b: Outside) -> (Outside, Outside) { + unimplemented!(); +} + +pub fn no_match_2(a: Outside, b: Outside) -> (Outside, Outside) { + unimplemented!(); +} + +pub fn should_match_3(a: Outside, b: Outside) -> (Outside, Outside) { + unimplemented!(); +} diff --git a/tests/rustdoc-js/never-search.js b/tests/rustdoc-js/never-search.js index ed24d693133ba..9f18370c2f511 100644 --- a/tests/rustdoc-js/never-search.js +++ b/tests/rustdoc-js/never-search.js @@ -43,4 +43,14 @@ const EXPECTED = [ { 'path': 'never_search', 'name': 'box_uninteresting' }, ], }, + { + 'query': 'box', + 'in_args': [], + 'returned': [], + }, + { + 'query': 'box', + 'in_args': [], + 'returned': [], + }, ]; diff --git a/tests/rustdoc-js/trait-methods.js b/tests/rustdoc-js/trait-methods.js new file mode 100644 index 0000000000000..dafad5e43784f --- /dev/null +++ b/tests/rustdoc-js/trait-methods.js @@ -0,0 +1,12 @@ +// exact-check + +const EXPECTED = [ + { + 'query': 'mytrait -> option', + 'correction': null, + 'in_args': [], + 'others': [ + { 'path': 'trait_methods::MyTrait', 'name': 'next' }, + ], + }, +]; diff --git a/tests/rustdoc-js/trait-methods.rs b/tests/rustdoc-js/trait-methods.rs new file mode 100644 index 0000000000000..c88f5edfd55b7 --- /dev/null +++ b/tests/rustdoc-js/trait-methods.rs @@ -0,0 +1,4 @@ +pub trait MyTrait { + type Item; + fn next(&mut self) -> Option; +} diff --git a/tests/rustdoc-json/doc_hidden_failure.rs b/tests/rustdoc-json/doc_hidden_failure.rs index 0d2c6b2209bd1..e2ce66c99e4c7 100644 --- a/tests/rustdoc-json/doc_hidden_failure.rs +++ b/tests/rustdoc-json/doc_hidden_failure.rs @@ -1,8 +1,5 @@ // Regression test for . -#![feature(no_core)] -#![no_core] - mod auto { mod action_row { pub struct ActionRowBuilder; diff --git a/tests/rustdoc-json/enums/field_hidden.rs b/tests/rustdoc-json/enums/field_hidden.rs index f240985805790..74d96248d5c7f 100644 --- a/tests/rustdoc-json/enums/field_hidden.rs +++ b/tests/rustdoc-json/enums/field_hidden.rs @@ -1,11 +1,5 @@ // Regression test for . -#![no_core] -#![feature(no_core, lang_items)] - -#[lang = "sized"] -trait Sized {} - // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null] diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs index 777161c4e4ba2..68483683464bf 100644 --- a/tests/rustdoc-json/enums/kind.rs +++ b/tests/rustdoc-json/enums/kind.rs @@ -1,11 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - pub enum Foo { // @set Unit = "$.index[*][?(@.name=='Unit')].id" // @is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"' diff --git a/tests/rustdoc-json/enums/tuple_fields_hidden.rs b/tests/rustdoc-json/enums/tuple_fields_hidden.rs index 34a4f4aec5384..53cdf83ffa687 100644 --- a/tests/rustdoc-json/enums/tuple_fields_hidden.rs +++ b/tests/rustdoc-json/enums/tuple_fields_hidden.rs @@ -1,9 +1,3 @@ -#![feature(no_core, lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - // @set 1.1.0 = "$.index[*][?(@.docs=='1.1.0')].id" // @set 2.1.0 = "$.index[*][?(@.docs=='2.1.0')].id" // @set 2.1.1 = "$.index[*][?(@.docs=='2.1.1')].id" diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs index 49990ec53315f..bec89530b0524 100644 --- a/tests/rustdoc-json/enums/use_glob.rs +++ b/tests/rustdoc-json/enums/use_glob.rs @@ -1,8 +1,5 @@ // Regression test for -#![feature(no_core)] -#![no_core] - // @set Color = "$.index[*][?(@.name == 'Color')].id" pub enum Color { Red, diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs index 8190e1cbe81d3..c7e0c21f1ef49 100644 --- a/tests/rustdoc-json/enums/use_variant.rs +++ b/tests/rustdoc-json/enums/use_variant.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - // @set AlwaysNone = "$.index[*][?(@.name == 'AlwaysNone')].id" pub enum AlwaysNone { // @set None = "$.index[*][?(@.name == 'None')].id" diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs index 3b82561ec7df2..8b3a8c0a74eb6 100644 --- a/tests/rustdoc-json/fn_pointer/generics.rs +++ b/tests/rustdoc-json/fn_pointer/generics.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 // @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"' // @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\" diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs index d6ea343b9911a..eef9ae99eb023 100644 --- a/tests/rustdoc-json/fns/extern_c_variadic.rs +++ b/tests/rustdoc-json/fns/extern_c_variadic.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - extern "C" { // @is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false pub fn not_variadic(_: i32); diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs index 539d17f831ebf..2f6cf3bf65a1d 100644 --- a/tests/rustdoc-json/fns/generic_args.rs +++ b/tests/rustdoc-json/fns/generic_args.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @set foo = "$.index[*][?(@.name=='Foo')].id" pub trait Foo {} diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs index 27d842066f4e2..8e82efef4beb1 100644 --- a/tests/rustdoc-json/fns/generic_returns.rs +++ b/tests/rustdoc-json/fns/generic_returns.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @count "$.index[*][?(@.name=='generic_returns')].inner.module.items[*]" 2 // @set foo = "$.index[*][?(@.name=='Foo')].id" diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs index 5239a6f21f534..44dc6d854aa3d 100644 --- a/tests/rustdoc-json/fns/generics.rs +++ b/tests/rustdoc-json/fns/generics.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @set wham_id = "$.index[*][?(@.name=='Wham')].id" pub trait Wham {} diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs index 9cfe649243f82..56d6e7a49dbd3 100644 --- a/tests/rustdoc-json/generic-associated-types/gats.rs +++ b/tests/rustdoc-json/generic-associated-types/gats.rs @@ -1,14 +1,5 @@ // ignore-tidy-linelength -#![no_core] -#![feature(lang_items, no_core, arbitrary_self_types)] - -#[lang = "sized"] -pub trait Sized {} - -#[lang = "receiver"] -pub trait Receiver {} - pub trait Display {} pub trait LendingIterator { diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs index f37ce0abb4144..7de1ed78f2ff0 100644 --- a/tests/rustdoc-json/glob_import.rs +++ b/tests/rustdoc-json/glob_import.rs @@ -1,13 +1,10 @@ // This is a regression test for . -#![feature(no_core)] #![no_std] -#![no_core] // @has "$.index[*][?(@.name=='glob')]" // @has "$.index[*][?(@.inner.import)].inner.import.name" \"*\" - mod m1 { pub fn f() {} } diff --git a/tests/rustdoc-json/impls/impl_item_visibility.rs b/tests/rustdoc-json/impls/impl_item_visibility.rs index efa54d91dcaac..d3c15cd23e448 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - pub struct Foo; /// impl Foo priv @@ -9,18 +6,16 @@ impl Foo { } // @!has '$.index[*][?(@.docs=="impl Foo priv")]' - /// impl Foo pub impl Foo { pub fn qux() {} } // @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' - /// impl Foo hidden impl Foo { #[doc(hidden)] - pub fn __quazl(){} + pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? // @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs index 3c6fefc4ca29f..fa3a36df8563b 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs @@ -1,6 +1,4 @@ // compile-flags: --document-hidden-items -#![feature(no_core)] -#![no_core] pub struct Foo; @@ -11,18 +9,16 @@ impl Foo { // FIXME(#111564): Is this the right behaviour? // @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"' - /// impl Foo pub impl Foo { pub fn qux() {} } // @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' - /// impl Foo hidden impl Foo { #[doc(hidden)] - pub fn __quazl(){} + pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? // @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs index b98d1e4167ced..7c68a2412f36a 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs @@ -1,6 +1,4 @@ // compile-flags: --document-private-items -#![feature(no_core)] -#![no_core] pub struct Foo; @@ -10,18 +8,16 @@ impl Foo { } // @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"' - /// impl Foo pub impl Foo { pub fn qux() {} } // @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' - /// impl Foo hidden impl Foo { #[doc(hidden)] - pub fn __quazl(){} + pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? // @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs index d2b0665dcafac..3da03df2546ca 100644 --- a/tests/rustdoc-json/impls/import_from_private.rs +++ b/tests/rustdoc-json/impls/import_from_private.rs @@ -1,14 +1,12 @@ // https://github.com/rust-lang/rust/issues/100252 -#![feature(no_core)] -#![no_core] - mod bar { - // @set baz = "$.index[*][?(@.inner.struct)].id" + // @set baz = "$.index[*][?(@.name == 'Baz')].id" pub struct Baz; - // @set impl = "$.index[*][?(@.inner.impl)].id" + // @set impl = "$.index[*][?(@.docs == 'impl')].id" + /// impl impl Baz { - // @set doit = "$.index[*][?(@.inner.function)].id" + // @set doit = "$.index[*][?(@.name == 'doit')].id" pub fn doit() {} } } @@ -18,5 +16,5 @@ pub use bar::Baz; // @is "$.index[*].inner.module.items[*]" $import // @is "$.index[*].inner.import.id" $baz -// @is "$.index[*].inner.struct.impls[*]" $impl -// @is "$.index[*].inner.impl.items[*]" $doit +// @has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl +// @is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs index d2ac316d47d4d..7857626d66ed0 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs @@ -1,7 +1,5 @@ -#![feature(no_core)] -#![no_core] - -// @count "$.index[*][?(@.inner.impl)]" 1 +// @has "$.index[*][?(@.docs=='Here')]" +// @!has "$.index[*][?(@.docs=='Not Here')]" // @!has "$.index[*][?(@.name == 'HiddenPubStruct')]" // @has "$.index[*][?(@.name == 'NotHiddenPubStruct')]" // @has "$.index[*][?(@.name=='PubTrait')]" @@ -11,5 +9,7 @@ pub trait PubTrait {} pub struct HiddenPubStruct; pub struct NotHiddenPubStruct; +/// Not Here impl PubTrait for HiddenPubStruct {} +/// Here impl PubTrait for NotHiddenPubStruct {} diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs index fcd27ca4b7c57..836f1fe87da33 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs @@ -1,8 +1,5 @@ // compile-flags: --document-hidden-items -#![feature(no_core)] -#![no_core] - // @has "$.index[*][?(@.name == 'HiddenPubStruct')]" // @has "$.index[*][?(@.inner.impl)]" // @has "$.index[*][?(@.name=='PubTrait')]" diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs index 141c54a57dd11..97db9c93a0f22 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs @@ -1,21 +1,21 @@ -#![feature(no_core)] -#![no_core] - -// @count "$.index[*][?(@.inner.impl)]" 1 -// @!has "$.index[*][?(@.name == 'HiddenPubStruct')]" -// @has "$.index[*][?(@.name == 'NotHiddenPubStruct')]" // @has "$.index[*][?(@.name=='PubTrait')]" pub trait PubTrait {} #[doc(hidden)] pub mod hidden { + // @!has "$.index[*][?(@.name == 'HiddenPubStruct')]" pub struct HiddenPubStruct; + // @!has "$.index[*][?(@.docs == 'Not Here')]" + /// Not Here impl crate::PubTrait for HiddenPubStruct {} } pub mod not_hidden { + // @has "$.index[*][?(@.name == 'NotHiddenPubStruct')]" pub struct NotHiddenPubStruct; + // @has "$.index[*][?(@.docs == 'Here')]" + /// Here impl crate::PubTrait for NotHiddenPubStruct {} } diff --git a/tests/rustdoc-json/impls/local_for_local.rs b/tests/rustdoc-json/impls/local_for_local.rs index 37a720003295a..015e89c228109 100644 --- a/tests/rustdoc-json/impls/local_for_local.rs +++ b/tests/rustdoc-json/impls/local_for_local.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - // @set struct = "$.index[*][?(@.name=='Struct')].id" pub struct Struct; // @set trait = "$.index[*][?(@.name=='Trait')].id" @@ -9,7 +6,7 @@ pub trait Trait {} /// impl impl Trait for Struct {} -// @is "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl +// @has "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl // @is "$.index[*][?(@.name=='Trait')].inner.trait.implementations[*]" $impl // @is "$.index[*][?(@.docs=='impl')].inner.impl.trait.id" $trait // @is "$.index[*][?(@.docs=='impl')].inner.impl.for.resolved_path.id" $struct diff --git a/tests/rustdoc-json/impls/local_for_local_primitive.rs b/tests/rustdoc-json/impls/local_for_local_primitive.rs index 769dd3f0a2c02..acc3a879fe1c9 100644 --- a/tests/rustdoc-json/impls/local_for_local_primitive.rs +++ b/tests/rustdoc-json/impls/local_for_local_primitive.rs @@ -1,6 +1,4 @@ -#![feature(no_core)] #![feature(rustc_attrs)] -#![no_core] // @set Local = "$.index[*][?(@.name=='Local')].id" pub trait Local {} diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs index dc28258a8b674..419b0b4fcab11 100644 --- a/tests/rustdoc-json/lifetime/longest.rs +++ b/tests/rustdoc-json/lifetime/longest.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].name" \"\'a\" // @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind" '{"lifetime": {"outlives": []}}' // @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind" '{"lifetime": {"outlives": []}}' @@ -26,5 +23,9 @@ // @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\" pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str { - if l.len() > r.len() { l } else { r } + if l.len() > r.len() { + l + } else { + r + } } diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs index 6e105b382b001..549e4c200dca7 100644 --- a/tests/rustdoc-json/lifetime/outlives.rs +++ b/tests/rustdoc-json/lifetime/outlives.rs @@ -1,8 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - // @count "$.index[*][?(@.name=='foo')].inner.function.generics.params[*]" 3 // @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates" [] // @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\" diff --git a/tests/rustdoc-json/methods/abi.rs b/tests/rustdoc-json/methods/abi.rs index b8279298c1e71..917e9e0790c9c 100644 --- a/tests/rustdoc-json/methods/abi.rs +++ b/tests/rustdoc-json/methods/abi.rs @@ -1,8 +1,6 @@ // ignore-tidy-linelength #![feature(abi_vectorcall)] -#![feature(no_core)] -#![no_core] // @has "$.index[*][?(@.name=='Foo')]" pub struct Foo; diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs index cabee0b1caa5a..d925fcd522150 100644 --- a/tests/rustdoc-json/non_lifetime_binders.rs +++ b/tests/rustdoc-json/non_lifetime_binders.rs @@ -3,18 +3,9 @@ #![feature(non_lifetime_binders)] #![allow(incomplete_features)] -#![no_core] -#![feature(lang_items, no_core)] - -#[lang = "sized"] -pub trait Sized {} - pub trait Trait {} -#[lang = "phantom_data"] -struct PhantomData; - -pub struct Wrapper(PhantomData); +pub struct Wrapper(std::marker::PhantomData); // @count "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2 // @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\" diff --git a/tests/rustdoc-json/primitives/primitive_overloading.rs b/tests/rustdoc-json/primitives/primitive_overloading.rs index 81e0acdc6e93e..50e23fc06d3ea 100644 --- a/tests/rustdoc-json/primitives/primitive_overloading.rs +++ b/tests/rustdoc-json/primitives/primitive_overloading.rs @@ -3,14 +3,10 @@ // Regression test for . #![feature(rustc_attrs)] -#![feature(no_core)] - -#![no_core] // @has "$.index[*][?(@.name=='usize')]" // @has "$.index[*][?(@.name=='prim')]" #[rustc_doc_primitive = "usize"] /// This is the built-in type `usize`. -mod prim { -} +mod prim {} diff --git a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs index 37ca279b352ca..a8f5500d6297e 100644 --- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs +++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs @@ -1,8 +1,5 @@ //! Regression test for -#![feature(no_core)] -#![no_core] - #![crate_name = "export_extern_crate_as_self"] // ignore-tidy-linelength diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs index dee35ba78dc45..9a75f4c0cf38f 100644 --- a/tests/rustdoc-json/reexport/glob_collision.rs +++ b/tests/rustdoc-json/reexport/glob_collision.rs @@ -1,8 +1,5 @@ // Regression test for https://github.com/rust-lang/rust/issues/100973 -#![feature(no_core)] -#![no_core] - // @set m1 = "$.index[*][?(@.name == 'm1' && @.inner.module)].id" // @is "$.index[*][?(@.name == 'm1')].inner.module.items" [] // @is "$.index[*][?(@.name == 'm1')].inner.module.is_stripped" true diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs index 78edfaf0aa8d7..ed0c4a420d489 100644 --- a/tests/rustdoc-json/reexport/glob_extern.rs +++ b/tests/rustdoc-json/reexport/glob_extern.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true" mod mod1 { extern "C" { diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs index ae4e87d23bc54..11ea5aa3522b2 100644 --- a/tests/rustdoc-json/reexport/glob_private.rs +++ b/tests/rustdoc-json/reexport/glob_private.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true" mod mod1 { // @is "$.index[*][?(@.name=='mod2')].inner.module.is_stripped" "true" diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs index f81445bd48da8..a4133e2f0c7d6 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - // @!has "$.index[*][?(@.name=='foo')]" mod foo { // @has "$.index[*][?(@.name=='Foo')]" diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs index c5c41b25f7ec0..37f7b26fc8595 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -1,6 +1,3 @@ -#![feature(no_core)] -#![no_core] - pub mod foo { // @set bar_id = "$.index[*][?(@.name=='Bar')].id" // @ismany "$.index[*][?(@.name=='foo')].inner.module.items[*]" $bar_id diff --git a/tests/rustdoc-json/reexport/macro.rs b/tests/rustdoc-json/reexport/macro.rs index ac0632b98a95a..be09cb47629dc 100644 --- a/tests/rustdoc-json/reexport/macro.rs +++ b/tests/rustdoc-json/reexport/macro.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @set repro_id = "$.index[*][?(@.name=='repro')].id" #[macro_export] macro_rules! repro { diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs index 1c49f213d1a71..bc072be81a311 100644 --- a/tests/rustdoc-json/reexport/mod_not_included.rs +++ b/tests/rustdoc-json/reexport/mod_not_included.rs @@ -1,8 +1,5 @@ // Regression test for https://github.com/rust-lang/rust/issues/101103 -#![feature(no_core)] -#![no_core] - mod m1 { pub fn x() {} } diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs index 8c8152bd16c3b..d7b7662355784 100644 --- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs +++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs @@ -4,12 +4,8 @@ // Test for the ICE in https://github.com/rust-lang/rust/issues/83057 // An external type re-exported with different attributes shouldn't cause an error -#![no_core] -#![feature(no_core)] - extern crate pub_struct as foo; #[doc(inline)] - // @set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id" // @set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id" /// Hack A diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs index cdcbf2a2bc86c..e6f037eb4b38e 100644 --- a/tests/rustdoc-json/reexport/private_two_names.rs +++ b/tests/rustdoc-json/reexport/private_two_names.rs @@ -3,9 +3,6 @@ // Test for the ICE in https://github.com/rust-lang/rust/issues/83720 // A pub-in-private type re-exported under two different names shouldn't cause an error -#![no_core] -#![feature(no_core)] - // @!has "$.index[*][?(@.name=='style')]" mod style { // @set color_struct_id = "$.index[*][?(@.inner.struct && @.name=='Color')].id" diff --git a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs index a2a25d08448a3..15d194ef5d925 100644 --- a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs +++ b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs @@ -1,15 +1,13 @@ // Regression test for -#![feature(no_core)] -#![no_core] - mod repeat_n { #[doc(hidden)] + /// not here pub struct RepeatN {} } +/// not here pub use repeat_n::RepeatN; // @count "$.index[*][?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0 -// @!has "$.index[*][?(@.kind=='struct')]" -// @!has "$.index[*][?(@.kind=='import')]" +// @!has "$.index[*][?(@.docs == 'not here')]" diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs new file mode 100644 index 0000000000000..1b6ff5fadca17 --- /dev/null +++ b/tests/rustdoc-json/reexport/reexport_of_hidden.rs @@ -0,0 +1,10 @@ +// compile-flags: --document-hidden-items + +// @has "$.index[*].inner[?(@.import.name=='UsedHidden')]" +// @has "$.index[*][?(@.name=='Hidden')]" +pub mod submodule { + #[doc(hidden)] + pub struct Hidden {} +} + +pub use submodule::Hidden as UsedHidden; diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs index 9114460231dc8..3924282a49e5e 100644 --- a/tests/rustdoc-json/reexport/rename_private.rs +++ b/tests/rustdoc-json/reexport/rename_private.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @!has "$.index[*][?(@.name=='inner')]" mod inner { // @has "$.index[*][?(@.name=='Public')]" diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs index d0fd314bd8c99..636937874483a 100644 --- a/tests/rustdoc-json/reexport/rename_public.rs +++ b/tests/rustdoc-json/reexport/rename_public.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @set inner_id = "$.index[*][?(@.name=='inner')].id" pub mod inner { // @set public_id = "$.index[*][?(@.name=='Public')].id" diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs index 6a765b733016e..42ba6c40019a6 100644 --- a/tests/rustdoc-json/reexport/same_name_different_types.rs +++ b/tests/rustdoc-json/reexport/same_name_different_types.rs @@ -1,8 +1,5 @@ // Regression test for . -#![feature(no_core)] -#![no_core] - pub mod nested { // @set foo_struct = "$.index[*][?(@.docs == 'Foo the struct')].id" diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index a00547dc34811..1e1710e1c0865 100644 --- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -2,9 +2,7 @@ // Regression test for . -#![feature(no_core)] #![no_std] -#![no_core] mod inner { // @set trait_id = "$.index[*][?(@.name=='Trait')].id" diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs index 462efee51bf40..2ca8c7fa6be6c 100644 --- a/tests/rustdoc-json/reexport/simple_private.rs +++ b/tests/rustdoc-json/reexport/simple_private.rs @@ -1,6 +1,4 @@ // edition:2018 -#![no_core] -#![feature(no_core)] // @!has "$.index[*][?(@.name=='inner')]" mod inner { diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs index 1373f96f87f07..04611eeb95cae 100644 --- a/tests/rustdoc-json/reexport/simple_public.rs +++ b/tests/rustdoc-json/reexport/simple_public.rs @@ -1,8 +1,5 @@ // edition:2018 -#![no_core] -#![feature(no_core)] - // @set inner_id = "$.index[*][?(@.name=='inner')].id" pub mod inner { diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs index 0ce81b5e59fa6..a9301b3fe4f30 100644 --- a/tests/rustdoc-json/return_private.rs +++ b/tests/rustdoc-json/return_private.rs @@ -1,9 +1,6 @@ // Regression test for . // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - mod secret { pub struct Secret; } diff --git a/tests/rustdoc-json/stripped_modules.rs b/tests/rustdoc-json/stripped_modules.rs index d2664b49e9c29..d5ab1173d9248 100644 --- a/tests/rustdoc-json/stripped_modules.rs +++ b/tests/rustdoc-json/stripped_modules.rs @@ -1,6 +1,3 @@ -#![no_core] -#![feature(no_core)] - // @!has "$.index[*][?(@.name=='no_pub_inner')]" mod no_pub_inner { fn priv_inner() {} diff --git a/tests/rustdoc-json/traits/implementors.rs b/tests/rustdoc-json/traits/implementors.rs index 7d351ad61be24..c27553c754488 100644 --- a/tests/rustdoc-json/traits/implementors.rs +++ b/tests/rustdoc-json/traits/implementors.rs @@ -1,19 +1,18 @@ -#![feature(no_core)] -#![no_core] - -// @set wham = "$.index[*][?(@.name=='Wham')].id" -// @count "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" 1 -// @set gmWham = "$.index[*][?(@.name=='Wham')].inner.trait.implementations[0]" pub trait Wham {} - -// @count "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" 1 -// @is "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[0]" $gmWham -// @set gm = "$.index[*][?(@.name=='Wham')].id" - -// jsonpath_lib isnt expressive enough (for now) to get the "impl" item, so we -// just check it isn't pointing to the type, but when you port to jsondocck-ng -// check what the impl item is -// @!is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[0]" $gm pub struct GeorgeMichael {} +/// Wham for George Michael impl Wham for GeorgeMichael {} + +// Find IDs. +// @set wham = "$.index[*][?(@.name=='Wham')].id" +// @set gmWham = "$.index[*][?(@.docs=='Wham for George Michael')].id" +// @set gm = "$.index[*][?(@.name=='GeorgeMichael')].id" + +// Both struct and trait point to impl. +// @has "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" $gmWham +// @is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" $gmWham + +// Impl points to both struct and trait. +// @is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.trait.id" $wham +// @is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.for.resolved_path.id" $gm diff --git a/tests/rustdoc-json/traits/private_supertrait.rs b/tests/rustdoc-json/traits/private_supertrait.rs index 49238e5e88be4..67b5a858ab76f 100644 --- a/tests/rustdoc-json/traits/private_supertrait.rs +++ b/tests/rustdoc-json/traits/private_supertrait.rs @@ -1,9 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - - // @!has "$.index[*][?(@.name == 'sealed')]" mod sealed { // @set sealed_id = "$.index[*][?(@.name=='Sealed')].id" diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs index 2123ac40427ea..bbae3557cf9cf 100644 --- a/tests/rustdoc-json/traits/supertrait.rs +++ b/tests/rustdoc-json/traits/supertrait.rs @@ -1,9 +1,5 @@ // ignore-tidy-linelength -#![feature(no_core)] -#![feature(lang_items)] -#![no_core] - // @set loud_id = "$.index[*][?(@.name=='Loud')].id" pub trait Loud {} diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs index 64c6c53ce4721..f860314795193 100644 --- a/tests/rustdoc-json/type/inherent_associated_type.rs +++ b/tests/rustdoc-json/type/inherent_associated_type.rs @@ -1,8 +1,6 @@ // ignore-tidy-linelength #![feature(inherent_associated_types)] -#![feature(no_core)] #![allow(incomplete_features)] -#![no_core] // @set OwnerMetadata = '$.index[*][?(@.name=="OwnerMetadata")].id' pub struct OwnerMetadata; diff --git a/tests/rustdoc-ui/apit-46976.rs b/tests/rustdoc-ui/apit-46976.rs new file mode 100644 index 0000000000000..c17688e3b1d74 --- /dev/null +++ b/tests/rustdoc-ui/apit-46976.rs @@ -0,0 +1,4 @@ +// check-pass +// https://github.com/rust-lang/rust/issues/46976 + +pub fn ice(f: impl Fn()) {} diff --git a/tests/rustdoc/auxiliary/issue-36031.rs b/tests/rustdoc-ui/auxiliary/issue-36031.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-36031.rs rename to tests/rustdoc-ui/auxiliary/issue-36031.rs diff --git a/tests/rustdoc/auxiliary/issue-40936.rs b/tests/rustdoc-ui/auxiliary/issue-40936.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-40936.rs rename to tests/rustdoc-ui/auxiliary/issue-40936.rs diff --git a/tests/rustdoc/auxiliary/issue-48414.rs b/tests/rustdoc-ui/auxiliary/issue-48414.rs similarity index 100% rename from tests/rustdoc/auxiliary/issue-48414.rs rename to tests/rustdoc-ui/auxiliary/issue-48414.rs diff --git a/tests/rustdoc-ui/bounded-hr-lifetime.stderr b/tests/rustdoc-ui/bounded-hr-lifetime.stderr index 580f70c974290..d7c4e8c380c53 100644 --- a/tests/rustdoc-ui/bounded-hr-lifetime.stderr +++ b/tests/rustdoc-ui/bounded-hr-lifetime.stderr @@ -4,5 +4,5 @@ error: lifetime bounds cannot be used in this context LL | for<'a: 'b + 'c> &'a (): std::fmt::Debug, | ^^ ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc/issue-48414.rs b/tests/rustdoc-ui/circular-intra-doc-link-48414.rs similarity index 79% rename from tests/rustdoc/issue-48414.rs rename to tests/rustdoc-ui/circular-intra-doc-link-48414.rs index b35743d887bf3..46367ccaef9a6 100644 --- a/tests/rustdoc/issue-48414.rs +++ b/tests/rustdoc-ui/circular-intra-doc-link-48414.rs @@ -1,4 +1,7 @@ // aux-build:issue-48414.rs +// check-pass + +// https://github.com/rust-lang/rust/issues/48414 // ICE when resolving paths for a trait that linked to another trait, when both were in an external // crate diff --git a/tests/rustdoc-ui/const-evalutation-ice.stderr b/tests/rustdoc-ui/const-evalutation-ice.stderr index 5d9c16c076529..e1cb3323856d1 100644 --- a/tests/rustdoc-ui/const-evalutation-ice.stderr +++ b/tests/rustdoc-ui/const-evalutation-ice.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | pub const N: usize = 0 - (mem::size_of::() != 400) as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/rustdoc-ui/const_arg_in_type_position.stderr b/tests/rustdoc-ui/const_arg_in_type_position.stderr index ea05920dea79b..5345f77fd392e 100644 --- a/tests/rustdoc-ui/const_arg_in_type_position.stderr +++ b/tests/rustdoc-ui/const_arg_in_type_position.stderr @@ -4,6 +4,6 @@ error[E0747]: constant provided when a type was expected LL | fn foo() -> Array { | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0747`. diff --git a/tests/rustdoc-ui/diagnostic-width.stderr b/tests/rustdoc-ui/diagnostic-width.stderr index 1a00d10d3fc6f..c1cc4898ac584 100644 --- a/tests/rustdoc-ui/diagnostic-width.stderr +++ b/tests/rustdoc-ui/diagnostic-width.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | ...ny(rustdoc::bare_url... | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doc-alias-assoc-const.stderr b/tests/rustdoc-ui/doc-alias-assoc-const.stderr index cbca40e1364fa..cd3ad4ab393a5 100644 --- a/tests/rustdoc-ui/doc-alias-assoc-const.stderr +++ b/tests/rustdoc-ui/doc-alias-assoc-const.stderr @@ -4,5 +4,5 @@ error: `#[doc(alias = "...")]` isn't allowed on associated constant in trait imp LL | #[doc(alias = "CONST_BAZ")] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doc-alias-same-name.stderr b/tests/rustdoc-ui/doc-alias-same-name.stderr index 5ba09a2eae1c7..a9da75c0171c0 100644 --- a/tests/rustdoc-ui/doc-alias-same-name.stderr +++ b/tests/rustdoc-ui/doc-alias-same-name.stderr @@ -4,5 +4,5 @@ error: `#[doc(alias = "...")]` is the same as the item's name LL | #[doc(alias = "Foo")] | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/doctest-edition.stderr b/tests/rustdoc-ui/doctest/doctest-edition.stderr index 8a3329aa3ed9a..1e9ebd88c2e35 100644 --- a/tests/rustdoc-ui/doctest/doctest-edition.stderr +++ b/tests/rustdoc-ui/doctest/doctest-edition.stderr @@ -18,5 +18,5 @@ help: mark blocks that do not contain Rust code as text LL | //! ```text | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout index 61468b6c7457b..e288f8dfce652 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout @@ -13,7 +13,7 @@ LL | struct S {}; // unexpected semicolon after struct def | = help: braced struct declarations are not followed by a semicolon -error: aborting due to previous error +error: aborting due to 1 previous error Couldn't compile the test. diff --git a/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.stdout b/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.stdout index bacbb47b5f9ff..11355c232fe10 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-missing-codes.stdout @@ -13,7 +13,7 @@ LL | let x: () = 5i32; | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. Some expected error codes were not found: ["E0004"] diff --git a/tests/rustdoc-ui/doctest/failed-doctest-output-windows.stdout b/tests/rustdoc-ui/doctest/failed-doctest-output-windows.stdout index f4bfb94e98cae..1b37249dd60f9 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-output-windows.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-output-windows.stdout @@ -12,7 +12,7 @@ error[E0425]: cannot find value `no` in this scope LL | no | ^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. Couldn't compile the test. diff --git a/tests/rustdoc-ui/doctest/failed-doctest-output.stdout b/tests/rustdoc-ui/doctest/failed-doctest-output.stdout index 840c9c5084c23..7b0cf9a432d4c 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-output.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-output.stdout @@ -12,7 +12,7 @@ error[E0425]: cannot find value `no` in this scope LL | no | ^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. Couldn't compile the test. diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.stderr b/tests/rustdoc-ui/doctest/nocapture-fail.stderr index b65b622c1ed4b..c6a5785a24fe4 100644 --- a/tests/rustdoc-ui/doctest/nocapture-fail.stderr +++ b/tests/rustdoc-ui/doctest/nocapture-fail.stderr @@ -14,5 +14,5 @@ LL | Input: 123 LL ~ } } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/private-item-doc-test.stderr b/tests/rustdoc-ui/doctest/private-item-doc-test.stderr index 5df6132987c9f..5177057c7284d 100644 --- a/tests/rustdoc-ui/doctest/private-item-doc-test.stderr +++ b/tests/rustdoc-ui/doctest/private-item-doc-test.stderr @@ -14,5 +14,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::private_doc_tests)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/private-public-item-doc-test.stderr b/tests/rustdoc-ui/doctest/private-public-item-doc-test.stderr index f50dbd1844e7a..38b8dd652d3ed 100644 --- a/tests/rustdoc-ui/doctest/private-public-item-doc-test.stderr +++ b/tests/rustdoc-ui/doctest/private-public-item-doc-test.stderr @@ -14,5 +14,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::private_doc_tests)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/test-compile-fail1.stderr b/tests/rustdoc-ui/doctest/test-compile-fail1.stderr index 72915e46becd3..02f4d8d754f9b 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail1.stderr +++ b/tests/rustdoc-ui/doctest/test-compile-fail1.stderr @@ -9,6 +9,6 @@ error[E0428]: the name `f` is defined multiple times | = note: `f` must be defined only once in the value namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/rustdoc-ui/doctest/test-compile-fail2.stderr b/tests/rustdoc-ui/doctest/test-compile-fail2.stderr index cee5b63cf5097..f0ad40eb6ca81 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail2.stderr +++ b/tests/rustdoc-ui/doctest/test-compile-fail2.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `` 3 | fail | ^^^^ expected one of `!` or `::` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr index fab801b3beaea..1ed4554225116 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr +++ b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr @@ -4,6 +4,6 @@ error[E0765]: unterminated double quote string 3 | "fail | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0765`. diff --git a/tests/rustdoc-ui/doctest/unparseable-doc-test.stdout b/tests/rustdoc-ui/doctest/unparseable-doc-test.stdout index 2641c66f25e77..0574dc8b28207 100644 --- a/tests/rustdoc-ui/doctest/unparseable-doc-test.stdout +++ b/tests/rustdoc-ui/doctest/unparseable-doc-test.stdout @@ -11,7 +11,7 @@ error[E0765]: unterminated double quote string LL | "unterminated | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0765`. Couldn't compile the test. diff --git a/tests/rustdoc-ui/error-in-impl-trait/README.md b/tests/rustdoc-ui/error-in-impl-trait/README.md index 1176a4a8c4cf8..d969ab10ef5ea 100644 --- a/tests/rustdoc-ui/error-in-impl-trait/README.md +++ b/tests/rustdoc-ui/error-in-impl-trait/README.md @@ -1,5 +1,5 @@ Each of these needs to be in a separate file, -because the `delay_span_bug` ICE in rustdoc won't be triggerred +because the `span_delayed_bug` ICE in rustdoc won't be triggerred if even a single other error was emitted. However, conceptually they are all testing basically the same thing. diff --git a/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-2.stderr b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-2.stderr index edb5dfd4d55e2..69e2eebcdd86b 100644 --- a/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-2.stderr +++ b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-2.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | V(Box), | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.stderr b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.stderr index aff7402bc91c6..c169ca670a63d 100644 --- a/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.stderr +++ b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type-impl-trait-return.stderr @@ -11,6 +11,6 @@ help: insert some indirection (e.g., a `DEF_ID`) to break the cycle LL | This(Box), | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `DEF_ID`. diff --git a/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type.stderr b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type.stderr index 349a569414cc1..bd5de384cdeea 100644 --- a/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type.stderr +++ b/tests/rustdoc-ui/error-in-impl-trait/infinite-recursive-type.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | V(Box), | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr b/tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr index 0864159c8e222..0b982cd9fd3d6 100644 --- a/tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr +++ b/tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr @@ -7,6 +7,6 @@ LL | #![doc(cfg_hide(test))] = note: see issue #43781 for more information = help: add `#![feature(doc_cfg_hide)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/rustdoc/issue-34423.rs b/tests/rustdoc-ui/hidden-trait-method-34423.rs similarity index 62% rename from tests/rustdoc/issue-34423.rs rename to tests/rustdoc-ui/hidden-trait-method-34423.rs index b429bf8c9ba73..f3107d2379c9a 100644 --- a/tests/rustdoc/issue-34423.rs +++ b/tests/rustdoc-ui/hidden-trait-method-34423.rs @@ -1,3 +1,6 @@ +// check-pass +// https://github.com/rust-lang/rust/issues/34423 + pub struct Foo; pub trait Bar { diff --git a/tests/rustdoc-ui/infinite-recursive-type.stderr b/tests/rustdoc-ui/infinite-recursive-type.stderr index 9e2c3ff164209..cc914de6d1ebc 100644 --- a/tests/rustdoc-ui/infinite-recursive-type.stderr +++ b/tests/rustdoc-ui/infinite-recursive-type.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | V(Box), | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/rustdoc/issue-36031.rs b/tests/rustdoc-ui/inherent-assoc-consts-36031.rs similarity index 69% rename from tests/rustdoc/issue-36031.rs rename to tests/rustdoc-ui/inherent-assoc-consts-36031.rs index af1b32fd22b17..755fc1cfdff29 100644 --- a/tests/rustdoc/issue-36031.rs +++ b/tests/rustdoc-ui/inherent-assoc-consts-36031.rs @@ -1,7 +1,10 @@ // aux-build:issue-36031.rs +// check-pass // build-aux-docs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/36031 + #![crate_name = "foo"] extern crate issue_36031; diff --git a/tests/rustdoc-ui/intra-doc/alias-ice.stderr b/tests/rustdoc-ui/intra-doc/alias-ice.stderr index 5e7ffeeb8a219..a38df98433d00 100644 --- a/tests/rustdoc-ui/intra-doc/alias-ice.stderr +++ b/tests/rustdoc-ui/intra-doc/alias-ice.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.stderr b/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.stderr index 04594ad414250..7ce677e863bc7 100644 --- a/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.stderr +++ b/tests/rustdoc-ui/intra-doc/assoc-item-not-in-scope.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/crate-nonexistent.stderr b/tests/rustdoc-ui/intra-doc/crate-nonexistent.stderr index a69b1c52ac557..5dc6101796049 100644 --- a/tests/rustdoc-ui/intra-doc/crate-nonexistent.stderr +++ b/tests/rustdoc-ui/intra-doc/crate-nonexistent.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.stderr b/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.stderr index 3e08354a61dea..ace20a5fe972e 100644 --- a/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.stderr +++ b/tests/rustdoc-ui/intra-doc/deny-intra-link-resolution-failure.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/field-ice.stderr b/tests/rustdoc-ui/intra-doc/field-ice.stderr index f45a3ca615bbe..cc0ada873af51 100644 --- a/tests/rustdoc-ui/intra-doc/field-ice.stderr +++ b/tests/rustdoc-ui/intra-doc/field-ice.stderr @@ -14,5 +14,5 @@ help: to link to the field, remove the disambiguator LL | /// [`Foo::bar`] | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr b/tests/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr index c43cda3eb7e94..b952517022b75 100644 --- a/tests/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr +++ b/tests/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr @@ -14,5 +14,5 @@ help: to link to the associated constant, prefix with `const@` LL | //! [const@u8::MIN] | ~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.stderr index a8dc91204c083..9d16219be2f7d 100644 --- a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.stderr +++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-4.stderr @@ -18,5 +18,5 @@ help: to link to the associated type, prefix with `type@` LL | /// [`type@Struct::Trait`] | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.stderr index 7430044ac3f1b..f7dabed29796d 100644 --- a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.stderr +++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-5.stderr @@ -18,5 +18,5 @@ help: to link to the trait, prefix with `trait@` LL | /// [`trait@u32::MAX`] | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.stderr index fe2d8cafa3026..baf23e94f45fa 100644 --- a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.stderr +++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-6.stderr @@ -18,5 +18,5 @@ help: to link to the primitive type, prefix with `prim@` LL | /// [`prim@u32::MAX`] | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.stderr index 1d302ff42e86f..542352754761e 100644 --- a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.stderr +++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-7.stderr @@ -18,5 +18,5 @@ help: to link to the associated type, prefix with `type@` LL | /// [`type@u32::MAX`] | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.stderr b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.stderr index efed0e2ce0ff5..a2641c2517072 100644 --- a/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.stderr +++ b/tests/rustdoc-ui/intra-doc/issue-108653-associated-items-8.stderr @@ -18,5 +18,5 @@ help: to link to the associated type, prefix with `type@` LL | /// [`type@u32::MAX`] | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/pub-export-lint.stderr b/tests/rustdoc-ui/intra-doc/pub-export-lint.stderr index 81ef799617ccd..b037b7933ca7e 100644 --- a/tests/rustdoc-ui/intra-doc/pub-export-lint.stderr +++ b/tests/rustdoc-ui/intra-doc/pub-export-lint.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/reference-links.stderr b/tests/rustdoc-ui/intra-doc/reference-links.stderr index c98a2fd7ce690..2a30359238ae2 100644 --- a/tests/rustdoc-ui/intra-doc/reference-links.stderr +++ b/tests/rustdoc-ui/intra-doc/reference-links.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/span-ice-55723.stderr b/tests/rustdoc-ui/intra-doc/span-ice-55723.stderr index e8ee40ad4e874..765f26c484553 100644 --- a/tests/rustdoc-ui/intra-doc/span-ice-55723.stderr +++ b/tests/rustdoc-ui/intra-doc/span-ice-55723.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr index 14f560618521d..8315c73a639f8 100644 --- a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr +++ b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr @@ -6,6 +6,6 @@ LL | use unresolved_crate::module::Name; | = help: consider adding `extern crate unresolved_crate` to use the `unresolved_crate` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/rustdoc-ui/intra-doc/unused-extern-crate.stderr b/tests/rustdoc-ui/intra-doc/unused-extern-crate.stderr index 815324563cb67..f9f135a922b8b 100644 --- a/tests/rustdoc-ui/intra-doc/unused-extern-crate.stderr +++ b/tests/rustdoc-ui/intra-doc/unused-extern-crate.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/invalid-keyword.stderr b/tests/rustdoc-ui/invalid-keyword.stderr index 8658e3825782d..82faaaab47f30 100644 --- a/tests/rustdoc-ui/invalid-keyword.stderr +++ b/tests/rustdoc-ui/invalid-keyword.stderr @@ -4,5 +4,5 @@ error: `foo df` is not a valid identifier LL | #[doc(keyword = "foo df")] | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/invalid_associated_const.stderr b/tests/rustdoc-ui/invalid_associated_const.stderr index 1a8863fb18f5d..9c6ae0f76c6e0 100644 --- a/tests/rustdoc-ui/invalid_associated_const.stderr +++ b/tests/rustdoc-ui/invalid_associated_const.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | type A: S = 34>; | ^^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/rustdoc-ui/issue-102467.stderr b/tests/rustdoc-ui/issue-102467.stderr index a337293f7a055..4a769f94cf265 100644 --- a/tests/rustdoc-ui/issue-102467.stderr +++ b/tests/rustdoc-ui/issue-102467.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | type A: S = 34>; | ^^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr b/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr index 9aeb3389e2d31..d056dde00ea01 100644 --- a/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr +++ b/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr @@ -21,6 +21,6 @@ LL | | } | |_^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/rustdoc-ui/issues/issue-102986.stderr b/tests/rustdoc-ui/issues/issue-102986.stderr index 3a573726c9727..996eb41c492b0 100644 --- a/tests/rustdoc-ui/issues/issue-102986.stderr +++ b/tests/rustdoc-ui/issues/issue-102986.stderr @@ -9,6 +9,6 @@ help: consider replacing `typeof(...)` with an actual type LL | y: (&'static str,), | ~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0516`. diff --git a/tests/rustdoc-ui/issues/issue-105334.stderr b/tests/rustdoc-ui/issues/issue-105334.stderr index e163bb4db9ee6..d992b219b3bc2 100644 --- a/tests/rustdoc-ui/issues/issue-105334.stderr +++ b/tests/rustdoc-ui/issues/issue-105334.stderr @@ -4,6 +4,6 @@ error[E0747]: constant provided when a type was expected LL | impl Vec< br##"*.."## > {} | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0747`. diff --git a/tests/rustdoc-ui/issues/issue-105737.stderr b/tests/rustdoc-ui/issues/issue-105737.stderr index 2dd9beb17da9b..2c63c345e46a5 100644 --- a/tests/rustdoc-ui/issues/issue-105737.stderr +++ b/tests/rustdoc-ui/issues/issue-105737.stderr @@ -7,6 +7,6 @@ LL | impl Vec {} = help: `lol` is a function item, not a type = help: function item types cannot be named directly -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0747`. diff --git a/tests/rustdoc-ui/issues/issue-106213.stderr b/tests/rustdoc-ui/issues/issue-106213.stderr index 0a4ff69bafb34..fa79fe2e71c10 100644 --- a/tests/rustdoc-ui/issues/issue-106213.stderr +++ b/tests/rustdoc-ui/issues/issue-106213.stderr @@ -4,6 +4,6 @@ error[E0224]: at least one trait is required for an object type LL | fn use_avx() -> dyn { | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0224`. diff --git a/tests/rustdoc-ui/issues/issue-106226.stderr b/tests/rustdoc-ui/issues/issue-106226.stderr index 1c973dab61d89..4d063b461883a 100644 --- a/tests/rustdoc-ui/issues/issue-106226.stderr +++ b/tests/rustdoc-ui/issues/issue-106226.stderr @@ -4,6 +4,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | type F = [_; ()]; | ^ not allowed in type signatures -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/rustdoc-ui/issues/issue-107918.rs b/tests/rustdoc-ui/issues/issue-107918.rs index 13788df0fc996..0ddb3dc921501 100644 --- a/tests/rustdoc-ui/issues/issue-107918.rs +++ b/tests/rustdoc-ui/issues/issue-107918.rs @@ -1,7 +1,7 @@ // aux-build:panic-handler.rs // compile-flags: --document-private-items // build-pass -// ignore-windows +// only-linux #![no_std] #![no_main] diff --git a/tests/rustdoc-ui/issues/issue-61592-2.stderr b/tests/rustdoc-ui/issues/issue-61592-2.stderr index 1b7f8bb552c0c..de376ad809e88 100644 --- a/tests/rustdoc-ui/issues/issue-61592-2.stderr +++ b/tests/rustdoc-ui/issues/issue-61592-2.stderr @@ -7,6 +7,6 @@ LL | #[doc = "baz"] LL | pub use foo::Foo as _; | ---------------------- anonymous import -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0780`. diff --git a/tests/rustdoc-ui/issues/issue-61592.stderr b/tests/rustdoc-ui/issues/issue-61592.stderr index 9c9c9106f8ac3..0b96b65930974 100644 --- a/tests/rustdoc-ui/issues/issue-61592.stderr +++ b/tests/rustdoc-ui/issues/issue-61592.stderr @@ -6,6 +6,6 @@ LL | #[doc(inline)] LL | pub use foo::Foo as _; | ---------------------- anonymous import -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0780`. diff --git a/tests/rustdoc-ui/issues/issue-61732.stderr b/tests/rustdoc-ui/issues/issue-61732.stderr index d16ec6a853a5c..f351f52d1e15c 100644 --- a/tests/rustdoc-ui/issues/issue-61732.stderr +++ b/tests/rustdoc-ui/issues/issue-61732.stderr @@ -6,6 +6,6 @@ LL | pub(in crate::r#mod) fn main() {} | = help: consider adding `extern crate r#mod` to use the `r#mod` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/rustdoc-ui/issues/issue-79465.stderr b/tests/rustdoc-ui/issues/issue-79465.stderr index d187a2e664a25..e7b433268e8d9 100644 --- a/tests/rustdoc-ui/issues/issue-79465.stderr +++ b/tests/rustdoc-ui/issues/issue-79465.stderr @@ -4,6 +4,6 @@ error[E0220]: associated type `A` not found for `T` LL | pub fn f1(x: T::A) {} | ^ associated type `A` not found -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0220`. diff --git a/tests/rustdoc-ui/issues/issue-79467.stderr b/tests/rustdoc-ui/issues/issue-79467.stderr index 561513a432bb5..cb030a3113fbd 100644 --- a/tests/rustdoc-ui/issues/issue-79467.stderr +++ b/tests/rustdoc-ui/issues/issue-79467.stderr @@ -4,6 +4,6 @@ error[E0224]: at least one trait is required for an object type LL | dyn 'static: 'static + Copy, | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0224`. diff --git a/tests/rustdoc-ui/issues/issue-79494.stderr b/tests/rustdoc-ui/issues/issue-79494.stderr index 7ed5ed3824716..abcd69d3aaef2 100644 --- a/tests/rustdoc-ui/issues/issue-79494.stderr +++ b/tests/rustdoc-ui/issues/issue-79494.stderr @@ -7,6 +7,6 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; = note: source type: `usize` (64 bits) = note: target type: `&[u8]` (128 bits) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/rustdoc-ui/issues/issue-81662-shortness.stdout b/tests/rustdoc-ui/issues/issue-81662-shortness.stdout index 748113be3a26d..6313dde32c57d 100644 --- a/tests/rustdoc-ui/issues/issue-81662-shortness.stdout +++ b/tests/rustdoc-ui/issues/issue-81662-shortness.stdout @@ -6,7 +6,7 @@ failures: ---- $DIR/issue-81662-shortness.rs - foo (line 6) stdout ---- $DIR/issue-81662-shortness.rs:7:1: error[E0425]: cannot find function `foo` in this scope -error: aborting due to previous error +error: aborting due to 1 previous error Couldn't compile the test. failures: diff --git a/tests/rustdoc-ui/issues/issue-96287.stderr b/tests/rustdoc-ui/issues/issue-96287.stderr index c4809a311fc8b..62d81534a9875 100644 --- a/tests/rustdoc-ui/issues/issue-96287.stderr +++ b/tests/rustdoc-ui/issues/issue-96287.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `V` LL | pub type Foo = impl Trait; | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0220`. diff --git a/tests/rustdoc-ui/lints/deny-missing-docs-macro.stderr b/tests/rustdoc-ui/lints/deny-missing-docs-macro.stderr index 0867b08183e2d..24597f09db675 100644 --- a/tests/rustdoc-ui/lints/deny-missing-docs-macro.stderr +++ b/tests/rustdoc-ui/lints/deny-missing-docs-macro.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(missing_docs)] | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/lints/doc-spotlight.stderr b/tests/rustdoc-ui/lints/doc-spotlight.stderr index 58612327ff93e..5d93b4132fce8 100644 --- a/tests/rustdoc-ui/lints/doc-spotlight.stderr +++ b/tests/rustdoc-ui/lints/doc-spotlight.stderr @@ -15,5 +15,5 @@ LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr index b8a08e9431276..f188240062dbc 100644 --- a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr +++ b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unknown_lints)] | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr index fb3a5e415dfee..3a748335ea8e4 100644 --- a/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr +++ b/tests/rustdoc-ui/lints/no-crate-level-doc-lint.stderr @@ -8,5 +8,5 @@ note: the lint level is defined here LL | #![deny(rustdoc::missing_crate_level_docs)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/mismatched_arg_count.stderr b/tests/rustdoc-ui/mismatched_arg_count.stderr index 7e88ce954acae..857bbda2ef471 100644 --- a/tests/rustdoc-ui/mismatched_arg_count.stderr +++ b/tests/rustdoc-ui/mismatched_arg_count.stderr @@ -12,6 +12,6 @@ note: type alias defined here, with 1 lifetime parameter: `'a` LL | type Alias<'a, T> = >::Assoc; | ^^^^^ -- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/rustdoc/issue-46271.rs b/tests/rustdoc-ui/nested-extern-crate-46271.rs similarity index 54% rename from tests/rustdoc/issue-46271.rs rename to tests/rustdoc-ui/nested-extern-crate-46271.rs index b38ef20c551fb..d2ac38f3e4559 100644 --- a/tests/rustdoc/issue-46271.rs +++ b/tests/rustdoc-ui/nested-extern-crate-46271.rs @@ -1,5 +1,8 @@ +// check-pass // hopefully this doesn't cause an ICE +// https://github.com/rust-lang/rust/issues/46271 + pub fn foo() { extern crate std; } diff --git a/tests/rustdoc/issue-47639.rs b/tests/rustdoc-ui/nested-macro-rules-47639.rs similarity index 57% rename from tests/rustdoc/issue-47639.rs rename to tests/rustdoc-ui/nested-macro-rules-47639.rs index 4b3456b86c5e6..210b1e79cd2f5 100644 --- a/tests/rustdoc/issue-47639.rs +++ b/tests/rustdoc-ui/nested-macro-rules-47639.rs @@ -1,4 +1,7 @@ +// check-pass // This should not ICE + +// https://github.com/rust-lang/rust/issues/47639 pub fn test() { macro_rules! foo { () => () diff --git a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr index 34b20a0b32ce1..01034018e22df 100644 --- a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr +++ b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | impl Allocator for DefaultAllocator { | ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/rustdoc-ui/proc_macro_bug.stderr b/tests/rustdoc-ui/proc_macro_bug.stderr index 5b048097c4964..77bdf201924f9 100644 --- a/tests/rustdoc-ui/proc_macro_bug.stderr +++ b/tests/rustdoc-ui/proc_macro_bug.stderr @@ -4,5 +4,5 @@ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `p LL | #[proc_macro_derive(DeriveA)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/rustc-check-passes.stderr b/tests/rustdoc-ui/rustc-check-passes.stderr index 83f4e87c6edeb..58d61c0213ec6 100644 --- a/tests/rustdoc-ui/rustc-check-passes.stderr +++ b/tests/rustdoc-ui/rustc-check-passes.stderr @@ -4,6 +4,6 @@ error[E0636]: the feature `rustdoc_internals` has already been declared LL | #![feature(rustdoc_internals)] | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0636`. diff --git a/tests/rustdoc/issue-40936.rs b/tests/rustdoc-ui/super-glob-40936.rs similarity index 59% rename from tests/rustdoc/issue-40936.rs rename to tests/rustdoc-ui/super-glob-40936.rs index 4d2e4c17b1f9e..a06e977b10a59 100644 --- a/tests/rustdoc/issue-40936.rs +++ b/tests/rustdoc-ui/super-glob-40936.rs @@ -1,6 +1,9 @@ // aux-build:issue-40936.rs +// check-pass // build-aux-docs +// https://github.com/rust-lang/rust/issues/40936 + #![crate_name = "foo"] extern crate issue_40936; diff --git a/tests/rustdoc-ui/track-diagnostics.stderr b/tests/rustdoc-ui/track-diagnostics.stderr index 39418d359288b..131adfd588c25 100644 --- a/tests/rustdoc-ui/track-diagnostics.stderr +++ b/tests/rustdoc-ui/track-diagnostics.stderr @@ -5,6 +5,6 @@ LL | const S: A = B; | ^ expected `A`, found `B` -Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/rustdoc-ui/tuple-variadic-check.stderr b/tests/rustdoc-ui/tuple-variadic-check.stderr index d127fb858d176..51fb87214fd74 100644 --- a/tests/rustdoc-ui/tuple-variadic-check.stderr +++ b/tests/rustdoc-ui/tuple-variadic-check.stderr @@ -4,5 +4,5 @@ error: `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn LL | #[doc(fake_variadic)] | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs index e960e9f59e9cf..e813fba47179d 100644 --- a/tests/rustdoc-ui/unescaped_backticks.rs +++ b/tests/rustdoc-ui/unescaped_backticks.rs @@ -190,7 +190,7 @@ pub fn complicated_markdown() {} pub mod mir {} pub mod rustc { - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to + /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg to //~^ ERROR unescaped backtick /// ensure it gets used. pub fn ty_error_with_message() {} diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr index 2b4e491b1fe9c..bd21dcb6e1af9 100644 --- a/tests/rustdoc-ui/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/unescaped_backticks.stderr @@ -64,19 +64,19 @@ LL | /// `cfg=... and not `#[cfg_attr]\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:193:91 + --> $DIR/unescaped_backticks.rs:193:93 | -LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to - | ^ +LL | /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg to + | ^ | help: the closing backtick of an inline code may be missing | -LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to - | + +LL | /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg` to + | + help: if you meant to use a literal backtick, escape it | -LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given \`msg to - | + +LL | /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given \`msg to + | + error: unescaped backtick --> $DIR/unescaped_backticks.rs:202:34 diff --git a/tests/rustdoc/async-fn-opaque-item.rs b/tests/rustdoc/async-fn-opaque-item.rs index a73e84f3fdc4e..2c030824fe7ba 100644 --- a/tests/rustdoc/async-fn-opaque-item.rs +++ b/tests/rustdoc/async-fn-opaque-item.rs @@ -9,7 +9,7 @@ // Checking there is only a "Functions" header and no "Opaque types". // @has async_fn_opaque_item/index.html -// @count - '//*[@class="small-section-header"]' 1 -// @has - '//*[@class="small-section-header"]' 'Functions' +// @count - '//*[@class="section-header"]' 1 +// @has - '//*[@class="section-header"]' 'Functions' pub async fn test() {} diff --git a/tests/rustdoc/compiler-derive-proc-macro.rs b/tests/rustdoc/compiler-derive-proc-macro.rs index 489ec924c1fcf..1c3867ced9b9a 100644 --- a/tests/rustdoc/compiler-derive-proc-macro.rs +++ b/tests/rustdoc/compiler-derive-proc-macro.rs @@ -5,9 +5,9 @@ // @has 'foo/index.html' // Each compiler builtin proc-macro has a trait equivalent so we should have // a trait section as well. -// @count - '//*[@id="main-content"]//*[@class="small-section-header"]' 2 -// @has - '//*[@id="main-content"]//*[@class="small-section-header"]' 'Traits' -// @has - '//*[@id="main-content"]//*[@class="small-section-header"]' 'Derive Macros' +// @count - '//*[@id="main-content"]//*[@class="section-header"]' 2 +// @has - '//*[@id="main-content"]//*[@class="section-header"]' 'Traits' +// @has - '//*[@id="main-content"]//*[@class="section-header"]' 'Derive Macros' // Now checking the correct file is generated as well. // @has 'foo/derive.Clone.html' diff --git a/tests/rustdoc/const-effect-param.rs b/tests/rustdoc/const-effect-param.rs index f50a9b96d812b..b6379c05a8592 100644 --- a/tests/rustdoc/const-effect-param.rs +++ b/tests/rustdoc/const-effect-param.rs @@ -1,3 +1,5 @@ +// Check that we don't render host effect parameters & arguments. + #![crate_name = "foo"] #![feature(effects, const_trait_impl)] diff --git a/tests/rustdoc/deprecated-future-staged-api.rs b/tests/rustdoc/deprecated-future-staged-api.rs index 09120b8d411aa..64dfd89305040 100644 --- a/tests/rustdoc/deprecated-future-staged-api.rs +++ b/tests/rustdoc/deprecated-future-staged-api.rs @@ -12,7 +12,7 @@ pub struct S1; // @has deprecated_future_staged_api/index.html '//*[@class="stab deprecated"]' \ // 'Deprecation planned' // @has deprecated_future_staged_api/struct.S2.html '//*[@class="stab deprecated"]' \ -// 'Deprecating in a future Rust version: literally never' +// 'Deprecating in a future version: literally never' #[deprecated(since = "TBD", note = "literally never")] #[stable(feature = "deprecated_future_staged_api", since = "1.0.0")] pub struct S2; diff --git a/tests/rustdoc/doctest/auxiliary/empty.rs b/tests/rustdoc/doctest/auxiliary/empty.rs new file mode 100644 index 0000000000000..d11c69f812a8d --- /dev/null +++ b/tests/rustdoc/doctest/auxiliary/empty.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/rustdoc/doctest-cfg-feature-30252.rs b/tests/rustdoc/doctest/doctest-cfg-feature-30252.rs similarity index 100% rename from tests/rustdoc/doctest-cfg-feature-30252.rs rename to tests/rustdoc/doctest/doctest-cfg-feature-30252.rs diff --git a/tests/rustdoc/issue-38129.rs b/tests/rustdoc/doctest/doctest-crate-attributes-38129.rs similarity index 100% rename from tests/rustdoc/issue-38129.rs rename to tests/rustdoc/doctest/doctest-crate-attributes-38129.rs diff --git a/tests/rustdoc/doctest-hide-empty-line-23106.rs b/tests/rustdoc/doctest/doctest-hide-empty-line-23106.rs similarity index 100% rename from tests/rustdoc/doctest-hide-empty-line-23106.rs rename to tests/rustdoc/doctest/doctest-hide-empty-line-23106.rs diff --git a/tests/rustdoc/doctest-ignore-32556.rs b/tests/rustdoc/doctest/doctest-ignore-32556.rs similarity index 100% rename from tests/rustdoc/doctest-ignore-32556.rs rename to tests/rustdoc/doctest/doctest-ignore-32556.rs diff --git a/tests/rustdoc/issue-43153.rs b/tests/rustdoc/doctest/doctest-include-43153.rs similarity index 81% rename from tests/rustdoc/issue-43153.rs rename to tests/rustdoc/doctest/doctest-include-43153.rs index 0fe680f10af34..ec21a68c4ee51 100644 --- a/tests/rustdoc/issue-43153.rs +++ b/tests/rustdoc/doctest/doctest-include-43153.rs @@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/43153 + // Test that `include!` in a doc test searches relative to the directory in // which the test is declared. diff --git a/tests/rustdoc/issue-38219.rs b/tests/rustdoc/doctest/doctest-macro-38219.rs similarity index 68% rename from tests/rustdoc/issue-38219.rs rename to tests/rustdoc/doctest/doctest-macro-38219.rs index fa57c58c76184..6c81df110856e 100644 --- a/tests/rustdoc/issue-38219.rs +++ b/tests/rustdoc/doctest/doctest-macro-38219.rs @@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/38219 + // compile-flags:--test // should-fail diff --git a/tests/rustdoc/doctest-manual-crate-name.rs b/tests/rustdoc/doctest/doctest-manual-crate-name.rs similarity index 100% rename from tests/rustdoc/doctest-manual-crate-name.rs rename to tests/rustdoc/doctest/doctest-manual-crate-name.rs diff --git a/tests/rustdoc/doctest-markdown-inline-parse-23744.rs b/tests/rustdoc/doctest/doctest-markdown-inline-parse-23744.rs similarity index 100% rename from tests/rustdoc/doctest-markdown-inline-parse-23744.rs rename to tests/rustdoc/doctest/doctest-markdown-inline-parse-23744.rs diff --git a/tests/rustdoc/issue-48377.rs b/tests/rustdoc/doctest/doctest-markdown-trailing-docblock-48377.rs similarity index 77% rename from tests/rustdoc/issue-48377.rs rename to tests/rustdoc/doctest/doctest-markdown-trailing-docblock-48377.rs index c32bcf380ea3b..d481dc0dd7018 100644 --- a/tests/rustdoc/issue-48377.rs +++ b/tests/rustdoc/doctest/doctest-markdown-trailing-docblock-48377.rs @@ -1,5 +1,7 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/48377 + //! This is a doc comment //! //! ```rust diff --git a/tests/rustdoc/doctest-multi-line-string-literal-25944.rs b/tests/rustdoc/doctest/doctest-multi-line-string-literal-25944.rs similarity index 100% rename from tests/rustdoc/doctest-multi-line-string-literal-25944.rs rename to tests/rustdoc/doctest/doctest-multi-line-string-literal-25944.rs diff --git a/tests/rustdoc/enum-variant-fields-heading.rs b/tests/rustdoc/enum-variant-fields-heading.rs new file mode 100644 index 0000000000000..8a7c99a87359e --- /dev/null +++ b/tests/rustdoc/enum-variant-fields-heading.rs @@ -0,0 +1,18 @@ +// This is a regression test for . +// It ensures that the "Fields" heading is not generated if no field is displayed. + +#![crate_name = "foo"] + +// @has 'foo/enum.Foo.html' +// @has - '//*[@id="variant.A"]' 'A' +// @count - '//*[@id="variant.A.fields"]' 0 +// @has - '//*[@id="variant.B"]' 'B' +// @count - '//*[@id="variant.B.fields"]' 0 +// @snapshot variants - '//*[@id="main-content"]/*[@class="variants"]' + +pub enum Foo { + /// A variant with no fields + A {}, + /// A variant with hidden fields + B { #[doc(hidden)] a: u8 }, +} diff --git a/tests/rustdoc/enum-variant-fields-heading.variants.html b/tests/rustdoc/enum-variant-fields-heading.variants.html new file mode 100644 index 0000000000000..bcb36f7cf86f6 --- /dev/null +++ b/tests/rustdoc/enum-variant-fields-heading.variants.html @@ -0,0 +1,3 @@ +

    §

    A

    A variant with no fields

    +
    §

    B

    A variant with hidden fields

    +
    \ No newline at end of file diff --git a/tests/rustdoc/issue-46767.rs b/tests/rustdoc/enum-variant-private-46767.rs similarity index 78% rename from tests/rustdoc/issue-46767.rs rename to tests/rustdoc/enum-variant-private-46767.rs index ef6ed104b743b..6386aa75a95e6 100644 --- a/tests/rustdoc/issue-46767.rs +++ b/tests/rustdoc/enum-variant-private-46767.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/46767 #![crate_name = "foo"] mod private { diff --git a/tests/rustdoc/issue-43701.rs b/tests/rustdoc/foreign-implementors-js-43701.rs similarity index 65% rename from tests/rustdoc/issue-43701.rs rename to tests/rustdoc/foreign-implementors-js-43701.rs index de772881e7323..3b16ad2045a3d 100644 --- a/tests/rustdoc/issue-43701.rs +++ b/tests/rustdoc/foreign-implementors-js-43701.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/43701 #![crate_name = "foo"] pub use std::vec::Vec; diff --git a/tests/rustdoc/inline-private-with-intermediate-doc-hidden.rs b/tests/rustdoc/inline-private-with-intermediate-doc-hidden.rs index e382940a47eb8..ae830c03ea3c5 100644 --- a/tests/rustdoc/inline-private-with-intermediate-doc-hidden.rs +++ b/tests/rustdoc/inline-private-with-intermediate-doc-hidden.rs @@ -6,8 +6,8 @@ // @has 'foo/index.html' // There should only be one struct displayed. -// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 1 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs' +// @count - '//*[@id="main-content"]/*[@class="section-header"]' 1 +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Structs' // @has - '//*[@id="main-content"]//a[@href="struct.Reexport.html"]' 'Reexport' // @has - '//*[@id="main-content"]//*[@class="desc docblock-short"]' 'Visible. Original.' diff --git a/tests/rustdoc/issue-34473.rs b/tests/rustdoc/inline-rename-34473.rs similarity index 83% rename from tests/rustdoc/issue-34473.rs rename to tests/rustdoc/inline-rename-34473.rs index 37da3dd199975..7bc92cca1afd1 100644 --- a/tests/rustdoc/issue-34473.rs +++ b/tests/rustdoc/inline-rename-34473.rs @@ -1,5 +1,7 @@ #![crate_name = "foo"] +// https://github.com/rust-lang/rust/issues/34473 + mod second { pub struct SomeTypeWithLongName; } diff --git a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs new file mode 100644 index 0000000000000..b0c21ffaeb997 --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs @@ -0,0 +1,16 @@ +#![feature(effects, const_trait_impl)] + +#[const_trait] +pub trait Resource {} + +pub const fn load() -> i32 { + 0 +} + +pub const fn lock() {} + +#[allow(non_upper_case_globals)] +pub trait Clash {} + +#[allow(non_upper_case_globals)] +pub const fn clash, const host: u64>() {} diff --git a/tests/rustdoc/inline_cross/auxiliary/const-fn.rs b/tests/rustdoc/inline_cross/auxiliary/const-fn.rs deleted file mode 100644 index 26332b419b6d3..0000000000000 --- a/tests/rustdoc/inline_cross/auxiliary/const-fn.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(effects)] - -pub const fn load() -> i32 { - 0 -} diff --git a/tests/rustdoc/inline_cross/const-effect-param.rs b/tests/rustdoc/inline_cross/const-effect-param.rs new file mode 100644 index 0000000000000..1d003e28f36db --- /dev/null +++ b/tests/rustdoc/inline_cross/const-effect-param.rs @@ -0,0 +1,29 @@ +// Regression test for issue #116629. +// Check that we don't render host effect parameters & arguments. + +// aux-crate:const_effect_param=const-effect-param.rs +// edition: 2021 +#![crate_name = "user"] + +// Don't render the host param on `load` and the host arg `host` passed to `Resource`. +// @has user/fn.load.html +// @has - '//pre[@class="rust item-decl"]' "pub const fn load() -> i32\ +// where \ +// R: Resource" +pub use const_effect_param::load; + +// Don't render the host arg `true` passed to `Resource`. +// @has user/fn.lock.html +// @has - '//pre[@class="rust item-decl"]' "pub const fn lock()\ +// where \ +// R: Resource" +pub use const_effect_param::lock; + +// Regression test for an issue introduced in PR #116670. +// Don't hide the const param `host` since it actually isn't the host effect param. +// @has user/fn.clash.html +// @has - '//pre[@class="rust item-decl"]' \ +// "pub const fn clash()\ +// where \ +// T: Clash" +pub use const_effect_param::clash; diff --git a/tests/rustdoc/inline_cross/const-fn.rs b/tests/rustdoc/inline_cross/const-fn.rs deleted file mode 100644 index 24934b873c25b..0000000000000 --- a/tests/rustdoc/inline_cross/const-fn.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Regression test for issue #116629. -// Check that we render the correct generic params of const fn - -// aux-crate:const_fn=const-fn.rs -// edition: 2021 -#![crate_name = "user"] - -// @has user/fn.load.html -// @has - '//pre[@class="rust item-decl"]' "pub const fn load() -> i32" -pub use const_fn::load; diff --git a/tests/rustdoc/issue-46766.rs b/tests/rustdoc/inline_local/enum-variant-reexport-46766.rs similarity index 72% rename from tests/rustdoc/issue-46766.rs rename to tests/rustdoc/inline_local/enum-variant-reexport-46766.rs index 36ab739565b8e..ea6b7bac4c7a3 100644 --- a/tests/rustdoc/issue-46766.rs +++ b/tests/rustdoc/inline_local/enum-variant-reexport-46766.rs @@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/46766 #![crate_name = "foo"] pub enum Enum{Variant} diff --git a/tests/rustdoc/issue-105735-overlapping-reexport-2.rs b/tests/rustdoc/issue-105735-overlapping-reexport-2.rs index 5d2c553d8a51e..2905e7d44bcd3 100644 --- a/tests/rustdoc/issue-105735-overlapping-reexport-2.rs +++ b/tests/rustdoc/issue-105735-overlapping-reexport-2.rs @@ -7,9 +7,9 @@ // @has - '//*[@class="item-name"]/a[@class="type"]' 'AtomicU8' // @has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8' // We also ensure we don't have another item displayed. -// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 2 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Aliases' -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants' +// @count - '//*[@id="main-content"]/*[@class="section-header"]' 2 +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Type Aliases' +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Constants' mod other { pub type AtomicU8 = (); diff --git a/tests/rustdoc/issue-105735-overlapping-reexport.rs b/tests/rustdoc/issue-105735-overlapping-reexport.rs index 50f2450b90a0b..7fa7df7701a24 100644 --- a/tests/rustdoc/issue-105735-overlapping-reexport.rs +++ b/tests/rustdoc/issue-105735-overlapping-reexport.rs @@ -7,9 +7,9 @@ // @has - '//*[@class="item-name"]/a[@class="struct"]' 'AtomicU8' // @has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8' // We also ensure we don't have another item displayed. -// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 2 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs' -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants' +// @count - '//*[@id="main-content"]/*[@class="section-header"]' 2 +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Structs' +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Constants' mod thing { pub use core::sync::atomic::AtomicU8; diff --git a/tests/rustdoc/issue-109258-missing-private-inlining.rs b/tests/rustdoc/issue-109258-missing-private-inlining.rs index 96f606368b27d..12c5556f13266 100644 --- a/tests/rustdoc/issue-109258-missing-private-inlining.rs +++ b/tests/rustdoc/issue-109258-missing-private-inlining.rs @@ -4,9 +4,9 @@ // @has 'foo/index.html' // We should only have a "Re-exports" and a "Modules" headers. -// @count - '//*[@id="main-content"]/h2[@class="small-section-header"]' 2 -// @has - '//*[@id="main-content"]/h2[@class="small-section-header"]' 'Re-exports' -// @has - '//*[@id="main-content"]/h2[@class="small-section-header"]' 'Modules' +// @count - '//*[@id="main-content"]/h2[@class="section-header"]' 2 +// @has - '//*[@id="main-content"]/h2[@class="section-header"]' 'Re-exports' +// @has - '//*[@id="main-content"]/h2[@class="section-header"]' 'Modules' // @has - '//*[@id="reexport.Foo"]' 'pub use crate::issue_109258::Foo;' // @has - '//*[@id="reexport.Foo"]//a[@href="issue_109258/struct.Foo.html"]' 'Foo' @@ -15,8 +15,8 @@ pub use crate::issue_109258::Foo; // @has 'foo/issue_109258/index.html' // We should only have a "Structs" header. -// @count - '//*[@id="main-content"]/h2[@class="small-section-header"]' 1 -// @has - '//*[@id="main-content"]/h2[@class="small-section-header"]' 'Structs' +// @count - '//*[@id="main-content"]/h2[@class="section-header"]' 1 +// @has - '//*[@id="main-content"]/h2[@class="section-header"]' 'Structs' // @has - '//*[@id="main-content"]//a[@href="struct.Foo.html"]' 'Foo' // @has 'foo/issue_109258/struct.Foo.html' pub mod issue_109258 { diff --git a/tests/rustdoc/issue-109449-doc-hidden-reexports.rs b/tests/rustdoc/issue-109449-doc-hidden-reexports.rs index 3b836a219312c..9fb2f7c7c05b0 100644 --- a/tests/rustdoc/issue-109449-doc-hidden-reexports.rs +++ b/tests/rustdoc/issue-109449-doc-hidden-reexports.rs @@ -66,8 +66,8 @@ pub mod single_reexport_inherit_hidden { pub mod single_reexport_no_inline { // First we ensure that we only have re-exports and no inlined items. // @has 'foo/single_reexport_no_inline/index.html' - // @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 1 - // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Re-exports' + // @count - '//*[@id="main-content"]/*[@class="section-header"]' 1 + // @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Re-exports' // Now we check that we don't have links to the items, just `pub use`. // @has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Public as XFoo;' @@ -101,10 +101,10 @@ pub mod glob_reexport { // With glob re-exports, we don't inline `#[doc(hidden)]` items so only `module` items // should be inlined. // @has 'foo/glob_reexport/index.html' - // @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3 - // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Re-exports' - // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs' - // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Aliases' + // @count - '//*[@id="main-content"]/*[@class="section-header"]' 3 + // @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Re-exports' + // @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Structs' + // @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Type Aliases' // Now we check we have 1 re-export and 2 inlined items. // If not item from a glob re-export is visible, we don't show the re-export. diff --git a/tests/rustdoc/issue-110422-inner-private.rs b/tests/rustdoc/issue-110422-inner-private.rs index ee8ed5cc6e17f..43dc929ab074c 100644 --- a/tests/rustdoc/issue-110422-inner-private.rs +++ b/tests/rustdoc/issue-110422-inner-private.rs @@ -8,11 +8,11 @@ // @has 'foo/index.html' // Checking there is no "trait" entry. -// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 4 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs' -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants' -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions' -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Macros' +// @count - '//*[@id="main-content"]/*[@class="section-header"]' 4 +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Structs' +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Constants' +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Functions' +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Macros' // @has - '//a[@href="fn.foo.html"]' 'foo' fn foo() { @@ -50,11 +50,11 @@ const BAR: i32 = { // @has 'foo/struct.Bar.html' // @has - '//*[@id="method.foo"]/*[@class="code-header"]' 'pub(crate) fn foo()' - // @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3 + // @count - '//*[@id="main-content"]/*[@class="section-header"]' 3 // We now check that the `Foo` trait is not documented nor visible on `Bar` page. - // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Implementations' - // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Auto Trait Implementations' - // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Blanket Implementations' + // @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Implementations' + // @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Auto Trait Implementations' + // @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Blanket Implementations' // @!has - '//*[@href="trait.Foo.html#method.babar"]/*[@class="code-header"]' 'fn babar()' impl Bar { fn foo() {} diff --git a/tests/rustdoc/issue-115295-macro-const-display.rs b/tests/rustdoc/issue-115295-macro-const-display.rs new file mode 100644 index 0000000000000..2916c7a84a1ff --- /dev/null +++ b/tests/rustdoc/issue-115295-macro-const-display.rs @@ -0,0 +1,40 @@ +#![crate_name = "foo"] + +// @has foo/trait.Trait.html +pub trait Trait {} + +// @has foo/struct.WithConst.html +pub struct WithConst; + +macro_rules! spans_from_macro { + () => { + impl WithConst<42> { + pub fn new() -> Self { + Self + } + } + impl Trait> for WithConst<42> {} + impl Trait> for WithConst<{ 43 }> {} + impl Trait> for WithConst<44> {} + pub struct Other { + pub field: WithConst<42>, + } + }; +} + +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<41>" +impl Trait> for WithConst<41> {} + +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl WithConst<42>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<42>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<{ 43 }>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<44>" + +// @has foo/struct.Other.html +// @has - //pre "pub field: WithConst<42>" +spans_from_macro!(); diff --git a/tests/rustdoc/issue-118180-empty-tuple-struct.rs b/tests/rustdoc/issue-118180-empty-tuple-struct.rs new file mode 100644 index 0000000000000..bc6ddbe5defad --- /dev/null +++ b/tests/rustdoc/issue-118180-empty-tuple-struct.rs @@ -0,0 +1,9 @@ +// @has issue_118180_empty_tuple_struct/enum.Enum.html +pub enum Enum { + // @has - '//*[@id="variant.Empty"]//h3' 'Empty()' + Empty(), +} + +// @has issue_118180_empty_tuple_struct/struct.Empty.html +// @has - '//pre/code' 'Empty()' +pub struct Empty(); diff --git a/tests/rustdoc/issue-43893.rs b/tests/rustdoc/issue-43893.rs deleted file mode 100644 index 95d5519345936..0000000000000 --- a/tests/rustdoc/issue-43893.rs +++ /dev/null @@ -1,19 +0,0 @@ -// ignore-cross-compile - -#![crate_name = "foo"] - -pub trait SomeTrait {} -pub struct SomeStruct; - -// @has foo/trait.SomeTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#9' -impl SomeTrait for usize {} - -// @has foo/trait.SomeTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#12-14' -impl SomeTrait for SomeStruct { - // deliberately multi-line impl -} - -pub trait AnotherTrait {} - -// @has foo/trait.AnotherTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#19' -impl AnotherTrait for T {} diff --git a/tests/rustdoc/issue-46976.rs b/tests/rustdoc/issue-46976.rs deleted file mode 100644 index c59f8c72e64c2..0000000000000 --- a/tests/rustdoc/issue-46976.rs +++ /dev/null @@ -1 +0,0 @@ -pub fn ice(f: impl Fn()) {} diff --git a/tests/rustdoc/issue-60522-duplicated-glob-reexport.rs b/tests/rustdoc/issue-60522-duplicated-glob-reexport.rs index 1429b5e474100..50def2c3cd983 100644 --- a/tests/rustdoc/issue-60522-duplicated-glob-reexport.rs +++ b/tests/rustdoc/issue-60522-duplicated-glob-reexport.rs @@ -5,8 +5,8 @@ #![crate_name = "foo"] // @has 'foo/index.html' -// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 1 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Modules' +// @count - '//*[@id="main-content"]/*[@class="section-header"]' 1 +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Modules' // @count - '//*[@id="main-content"]/*[@class="item-table"]//*[@class="mod"]' 2 // @has - '//*[@id="main-content"]//*[@class="mod"]' 'banana' // @has - '//*[@id="main-content"]//*[@href="banana/index.html"]' 'banana' diff --git a/tests/rustdoc/nested-items-issue-111415.rs b/tests/rustdoc/nested-items-issue-111415.rs index 9b7688c332c44..c117569d9b468 100644 --- a/tests/rustdoc/nested-items-issue-111415.rs +++ b/tests/rustdoc/nested-items-issue-111415.rs @@ -5,10 +5,10 @@ // @has 'foo/index.html' // Checking there are only three sections. -// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs' -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions' -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Traits' +// @count - '//*[@id="main-content"]/*[@class="section-header"]' 3 +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Structs' +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Functions' +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Traits' // Checking that there are only three items. // @count - '//*[@id="main-content"]//*[@class="item-name"]' 3 // @has - '//*[@id="main-content"]//a[@href="struct.Bar.html"]' 'Bar' diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-slice.bare_fn_matches.html b/tests/rustdoc/notable-trait/doc-notable_trait-slice.bare_fn_matches.html index 46be00a080482..7d2a2589133be 100644 --- a/tests/rustdoc/notable-trait/doc-notable_trait-slice.bare_fn_matches.html +++ b/tests/rustdoc/notable-trait/doc-notable_trait-slice.bare_fn_matches.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/notable-trait/doc-notable_trait.bare-fn.html b/tests/rustdoc/notable-trait/doc-notable_trait.bare-fn.html index f592e3b375c02..9f71677cf4ffc 100644 --- a/tests/rustdoc/notable-trait/doc-notable_trait.bare-fn.html +++ b/tests/rustdoc/notable-trait/doc-notable_trait.bare-fn.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/notable-trait/doc-notable_trait.some-struct-new.html b/tests/rustdoc/notable-trait/doc-notable_trait.some-struct-new.html index e8f4f6000457d..38689c79f1ace 100644 --- a/tests/rustdoc/notable-trait/doc-notable_trait.some-struct-new.html +++ b/tests/rustdoc/notable-trait/doc-notable_trait.some-struct-new.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/notable-trait/doc-notable_trait.wrap-me.html b/tests/rustdoc/notable-trait/doc-notable_trait.wrap-me.html index e7909669b150a..c137be9e3a5d8 100644 --- a/tests/rustdoc/notable-trait/doc-notable_trait.wrap-me.html +++ b/tests/rustdoc/notable-trait/doc-notable_trait.wrap-me.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/notable-trait/spotlight-from-dependency.odd.html b/tests/rustdoc/notable-trait/spotlight-from-dependency.odd.html index 5f54b7522ae38..cce8739df1650 100644 --- a/tests/rustdoc/notable-trait/spotlight-from-dependency.odd.html +++ b/tests/rustdoc/notable-trait/spotlight-from-dependency.odd.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/issue-47038.rs b/tests/rustdoc/private-use-decl-macro-47038.rs similarity index 79% rename from tests/rustdoc/issue-47038.rs rename to tests/rustdoc/private-use-decl-macro-47038.rs index 810ddca3eab80..8944bdd42b4fb 100644 --- a/tests/rustdoc/issue-47038.rs +++ b/tests/rustdoc/private-use-decl-macro-47038.rs @@ -2,6 +2,8 @@ #![crate_name = "foo"] +// https://github.com/rust-lang/rust/issues/47038 + use std::vec; // @has 'foo/index.html' diff --git a/tests/rustdoc/issue-46506-pub-reexport-of-pub-reexport.rs b/tests/rustdoc/pub-reexport-of-pub-reexport-46506.rs similarity index 68% rename from tests/rustdoc/issue-46506-pub-reexport-of-pub-reexport.rs rename to tests/rustdoc/pub-reexport-of-pub-reexport-46506.rs index d8953eaf5970a..ae0aead244b31 100644 --- a/tests/rustdoc/issue-46506-pub-reexport-of-pub-reexport.rs +++ b/tests/rustdoc/pub-reexport-of-pub-reexport-46506.rs @@ -4,8 +4,8 @@ #![crate_name = "foo"] // @has 'foo/associations/index.html' -// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 1 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Traits' +// @count - '//*[@id="main-content"]/*[@class="section-header"]' 1 +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Traits' // @has - '//*[@id="main-content"]//a[@href="trait.GroupedBy.html"]' 'GroupedBy' // @has 'foo/associations/trait.GroupedBy.html' pub mod associations { @@ -16,8 +16,8 @@ pub mod associations { } // @has 'foo/prelude/index.html' -// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 1 -// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Re-exports' +// @count - '//*[@id="main-content"]/*[@class="section-header"]' 1 +// @has - '//*[@id="main-content"]/*[@class="section-header"]' 'Re-exports' // @has - '//*[@id="main-content"]//*[@id="reexport.GroupedBy"]' 'pub use associations::GroupedBy;' pub mod prelude { pub use associations::GroupedBy; diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs index 7f56b2ffeb8ad..6f264969e54ce 100644 --- a/tests/rustdoc/rfc-2632-const-trait-impl.rs +++ b/tests/rustdoc/rfc-2632-const-trait-impl.rs @@ -23,7 +23,7 @@ pub trait Tr { // @!has - '//section[@id="method.a"]/h4[@class="code-header"]' '~const' // @has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const' - // @has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' + // @has - '//section[@id="method.a"]/h4[@class="code-header"]/div[@class="where"]' ': Fn' fn a() where Option: /* ~const */ Fn() + ~const Destruct, @@ -35,7 +35,7 @@ pub trait Tr { // @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]' '~const' // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const' -// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' +// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/div[@class="where"]' ': Fn' impl const Tr for T where Option: /* ~const */ Fn() + ~const Destruct, @@ -49,8 +49,8 @@ where // @!has foo/fn.foo.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const' // @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn' -// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' '~const' -// @has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' ': Fn' +// @!has - '//pre[@class="rust item-decl"]/code/div[@class="where"]' '~const' +// @has - '//pre[@class="rust item-decl"]/code/div[@class="where"]' ': Fn' pub const fn foo() where Option: /* ~const */ Fn() + ~const Destruct, @@ -62,7 +62,7 @@ impl S { // @!has foo/struct.S.html '//section[@id="method.foo"]/h4[@class="code-header"]' '~const' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const' - // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' + // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/div[@class="where"]' ': Fn' pub const fn foo() where B: /* ~const */ Fn() + ~const Destruct, diff --git a/tests/rustdoc/src-links-implementor-43893.rs b/tests/rustdoc/src-links-implementor-43893.rs new file mode 100644 index 0000000000000..07e672847ca68 --- /dev/null +++ b/tests/rustdoc/src-links-implementor-43893.rs @@ -0,0 +1,21 @@ +// ignore-cross-compile + +// https://github.com/rust-lang/rust/issues/43893 + +#![crate_name = "foo"] + +pub trait SomeTrait {} +pub struct SomeStruct; + +// @has foo/trait.SomeTrait.html '//a/@href' '../src/foo/src-links-implementor-43893.rs.html#11' +impl SomeTrait for usize {} + +// @has foo/trait.SomeTrait.html '//a/@href' '../src/foo/src-links-implementor-43893.rs.html#14-16' +impl SomeTrait for SomeStruct { + // deliberately multi-line impl +} + +pub trait AnotherTrait {} + +// @has foo/trait.AnotherTrait.html '//a/@href' '../src/foo/src-links-implementor-43893.rs.html#21' +impl AnotherTrait for T {} diff --git a/tests/rustdoc/stability.rs b/tests/rustdoc/stability.rs index 90be2050d926b..c4d7118d07ff0 100644 --- a/tests/rustdoc/stability.rs +++ b/tests/rustdoc/stability.rs @@ -2,6 +2,14 @@ #![unstable(feature = "test", issue = "none")] +// @has stability/index.html +// @has - '//ul[@class="item-table"]/li[1]//a' AaStable +// @has - '//ul[@class="item-table"]/li[2]//a' ZzStable +// @has - '//ul[@class="item-table"]/li[3]//a' Unstable + +#[stable(feature = "rust2", since = "2.2.2")] +pub struct AaStable; + pub struct Unstable { // @has stability/struct.Unstable.html \ // '//span[@class="item-info"]//div[@class="stab unstable"]' \ @@ -10,3 +18,6 @@ pub struct Unstable { pub foo: u32, pub bar: u32, } + +#[stable(feature = "rust2", since = "2.2.2")] +pub struct ZzStable; diff --git a/tests/rustdoc/issue-45584.rs b/tests/rustdoc/trait-implementations-duplicate-self-45584.rs similarity index 90% rename from tests/rustdoc/issue-45584.rs rename to tests/rustdoc/trait-implementations-duplicate-self-45584.rs index 8a5f0413826a9..77b8c05f2fbe0 100644 --- a/tests/rustdoc/issue-45584.rs +++ b/tests/rustdoc/trait-implementations-duplicate-self-45584.rs @@ -1,5 +1,7 @@ #![crate_name = "foo"] +// https://github.com/rust-lang/rust/issues/45584 + pub trait Bar {} // @has 'foo/struct.Foo1.html' diff --git a/tests/rustdoc/issue-34928.rs b/tests/rustdoc/tuple-struct-where-clause-34928.rs similarity index 75% rename from tests/rustdoc/issue-34928.rs rename to tests/rustdoc/tuple-struct-where-clause-34928.rs index 4184086f622ab..909b91468931b 100644 --- a/tests/rustdoc/issue-34928.rs +++ b/tests/rustdoc/tuple-struct-where-clause-34928.rs @@ -1,5 +1,7 @@ #![crate_name = "foo"] +// https://github.com/rust-lang/rust/issues/34928 + pub trait Bar {} // @has foo/struct.Foo.html '//pre' 'pub struct Foo(pub T) where T: Bar;' diff --git a/tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs b/tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs index ff84352d7169f..bea25c75aa489 100644 --- a/tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs +++ b/tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs @@ -13,14 +13,14 @@ pub struct Pair { // @count - '//*[@id="aliased-type"]' 1 // @count - '//*[@id="variants"]' 0 // @count - '//*[@id="fields"]' 1 -// @count - '//span[@class="where fmt-newline"]' 0 +// @count - '//div[@class="where"]' 0 pub type ReversedTypesPair = Pair; // @has 'inner_types_lazy/type.ReadWrite.html' // @count - '//*[@id="aliased-type"]' 1 // @count - '//*[@id="variants"]' 0 // @count - '//*[@id="fields"]' 1 -// @count - '//span[@class="where fmt-newline"]' 2 +// @count - '//div[@class="where"]' 2 pub type ReadWrite = Pair where R: std::io::Read, @@ -30,5 +30,5 @@ where // @count - '//*[@id="aliased-type"]' 1 // @count - '//*[@id="variants"]' 0 // @count - '//*[@id="fields"]' 1 -// @count - '//span[@class="where fmt-newline"]' 0 +// @count - '//div[@class="where"]' 0 pub type VecPair = Pair, Vec>; diff --git a/tests/rustdoc/typedef-inner-variants.rs b/tests/rustdoc/typedef-inner-variants.rs index b734714fd6432..4d0ff85551ce9 100644 --- a/tests/rustdoc/typedef-inner-variants.rs +++ b/tests/rustdoc/typedef-inner-variants.rs @@ -65,7 +65,7 @@ pub union OneOr { // @count - '//*[@id="aliased-type"]' 1 // @count - '//*[@id="variants"]' 0 // @count - '//*[@id="fields"]' 1 -// @count - '//*[@class="structfield small-section-header"]' 2 +// @count - '//*[@class="structfield section-header"]' 2 // @matches - '//pre[@class="rust item-decl"]//code' "union OneOrF64" pub type OneOrF64 = OneOr; @@ -81,7 +81,7 @@ pub struct One { // @count - '//*[@id="aliased-type"]' 1 // @count - '//*[@id="variants"]' 0 // @count - '//*[@id="fields"]' 1 -// @count - '//*[@class="structfield small-section-header"]' 1 +// @count - '//*[@class="structfield section-header"]' 1 // @matches - '//pre[@class="rust item-decl"]//code' "struct OneU64" // @matches - '//pre[@class="rust item-decl"]//code' "pub val" pub type OneU64 = One; diff --git a/tests/rustdoc/where.SWhere_Echo_impl.html b/tests/rustdoc/where.SWhere_Echo_impl.html index 7517eb090f496..726196281a59f 100644 --- a/tests/rustdoc/where.SWhere_Echo_impl.html +++ b/tests/rustdoc/where.SWhere_Echo_impl.html @@ -1,2 +1,2 @@ -

    impl<D> Delta<D>where - D: MyTrait,

    \ No newline at end of file +

    impl<D> Delta<D>
    where + D: MyTrait,

    \ No newline at end of file diff --git a/tests/rustdoc/where.SWhere_Simd_item-decl.html b/tests/rustdoc/where.SWhere_Simd_item-decl.html index 46708b9e4e925..1987b1d59f516 100644 --- a/tests/rustdoc/where.SWhere_Simd_item-decl.html +++ b/tests/rustdoc/where.SWhere_Simd_item-decl.html @@ -1,3 +1,3 @@ -
    pub struct Simd<T>(/* private fields */)
    +
    pub struct Simd<T>(/* private fields */)
     where
    -    T: MyTrait;
    + T: MyTrait;
    \ No newline at end of file diff --git a/tests/rustdoc/where.alpha_trait_decl.html b/tests/rustdoc/where.alpha_trait_decl.html index 0c0b2d1ceca9d..2c010ca7c2d94 100644 --- a/tests/rustdoc/where.alpha_trait_decl.html +++ b/tests/rustdoc/where.alpha_trait_decl.html @@ -1,3 +1,3 @@ -pub struct Alpha<A>(/* private fields */) +pub struct Alpha<A>(/* private fields */) where A: MyTrait; \ No newline at end of file diff --git a/tests/rustdoc/where.bravo_trait_decl.html b/tests/rustdoc/where.bravo_trait_decl.html index 00524201a8aca..3f1c994b0b25d 100644 --- a/tests/rustdoc/where.bravo_trait_decl.html +++ b/tests/rustdoc/where.bravo_trait_decl.html @@ -1,5 +1,5 @@ -pub trait Bravo<B>where - B: MyTrait,{ +pub trait Bravo<B>
    where + B: MyTrait,
    { // Required method fn get(&self, B: B); }
    \ No newline at end of file diff --git a/tests/rustdoc/where.charlie_fn_decl.html b/tests/rustdoc/where.charlie_fn_decl.html index 8e3bc8b01ecbd..4dd410435c1ac 100644 --- a/tests/rustdoc/where.charlie_fn_decl.html +++ b/tests/rustdoc/where.charlie_fn_decl.html @@ -1,2 +1,2 @@ -pub fn charlie<C>()where - C: MyTrait, \ No newline at end of file +pub fn charlie<C>()
    where + C: MyTrait,
    \ No newline at end of file diff --git a/tests/rustdoc/where.golf_type_alias_decl.html b/tests/rustdoc/where.golf_type_alias_decl.html index 8da5402f90073..ab60bb262daf2 100644 --- a/tests/rustdoc/where.golf_type_alias_decl.html +++ b/tests/rustdoc/where.golf_type_alias_decl.html @@ -1,2 +1,2 @@ -pub type Golf<T>where - T: Clone, = (T, T); \ No newline at end of file +pub type Golf<T>
    where + T: Clone,
    = (T, T);
    \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.enum.html b/tests/rustdoc/whitespace-after-where-clause.enum.html index ff4971f33cd68..25e02145323d6 100644 --- a/tests/rustdoc/whitespace-after-where-clause.enum.html +++ b/tests/rustdoc/whitespace-after-where-clause.enum.html @@ -1,5 +1,5 @@ -
    pub enum Cow<'a, B>where
    -    B: ToOwned<()> + ?Sized + 'a,{
    +
    pub enum Cow<'a, B>
    where + B: ToOwned<()> + ?Sized + 'a,
    { Borrowed(&'a B), Whatever(u32), }
    \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.struct.html b/tests/rustdoc/whitespace-after-where-clause.struct.html index ca68535863398..bc62a3a0015e3 100644 --- a/tests/rustdoc/whitespace-after-where-clause.struct.html +++ b/tests/rustdoc/whitespace-after-where-clause.struct.html @@ -1,5 +1,5 @@ -
    pub struct Struct<'a, B>where
    -    B: ToOwned<()> + ?Sized + 'a,{
    +
    pub struct Struct<'a, B>
    where + B: ToOwned<()> + ?Sized + 'a,
    { pub a: &'a B, pub b: u32, }
    \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.trait.html b/tests/rustdoc/whitespace-after-where-clause.trait.html index 0928b48e6b64c..0e25ed86a7c86 100644 --- a/tests/rustdoc/whitespace-after-where-clause.trait.html +++ b/tests/rustdoc/whitespace-after-where-clause.trait.html @@ -1,5 +1,5 @@ -
    pub trait ToOwned<T>where
    -    T: Clone,{
    +
    pub trait ToOwned<T>
    where + T: Clone,
    { type Owned; // Required methods diff --git a/tests/rustdoc/whitespace-after-where-clause.union.html b/tests/rustdoc/whitespace-after-where-clause.union.html index 40b0c6712842b..e63374760d998 100644 --- a/tests/rustdoc/whitespace-after-where-clause.union.html +++ b/tests/rustdoc/whitespace-after-where-clause.union.html @@ -1,4 +1,4 @@ -
    pub union Union<'a, B>where
    -    B: ToOwned<()> + ?Sized + 'a,{
    -    /* private fields */
    +
    pub union Union<'a, B>
    where + B: ToOwned<()> + ?Sized + 'a,
    { + /* private fields */ }
    \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.union2.html b/tests/rustdoc/whitespace-after-where-clause.union2.html index 177a161b83a62..da984343daadc 100644 --- a/tests/rustdoc/whitespace-after-where-clause.union2.html +++ b/tests/rustdoc/whitespace-after-where-clause.union2.html @@ -1,3 +1,3 @@
    pub union Union2<'a, B: ?Sized + ToOwned<()> + 'a> {
    -    /* private fields */
    +    /* private fields */
     }
    \ No newline at end of file diff --git a/tests/ui-fulldeps/dropck-tarena-cycle-checked.rs b/tests/ui-fulldeps/dropck-tarena-cycle-checked.rs index cc97971a0ddb7..188da67295a17 100644 --- a/tests/ui-fulldeps/dropck-tarena-cycle-checked.rs +++ b/tests/ui-fulldeps/dropck-tarena-cycle-checked.rs @@ -1,3 +1,5 @@ +// ignore-stage1 + // Reject mixing cyclic structure and Drop when using TypedArena. // // (Compare against dropck-vec-cycle-checked.rs) diff --git a/tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr b/tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr index 47897dc003a43..2f5be3f7f5595 100644 --- a/tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr +++ b/tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr @@ -1,5 +1,5 @@ error[E0597]: `arena` does not live long enough - --> $DIR/dropck-tarena-cycle-checked.rs:116:7 + --> $DIR/dropck-tarena-cycle-checked.rs:118:7 | LL | let arena = TypedArena::default(); | ----- binding `arena` declared here @@ -11,6 +11,6 @@ LL | } | `arena` dropped here while still borrowed | borrow might be used here, when `arena` is dropped and runs the `Drop` code for type `TypedArena` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui-fulldeps/dropck-tarena-unsound-drop.rs b/tests/ui-fulldeps/dropck-tarena-unsound-drop.rs index 86485a9887fbe..5f9a5fb76eb45 100644 --- a/tests/ui-fulldeps/dropck-tarena-unsound-drop.rs +++ b/tests/ui-fulldeps/dropck-tarena-unsound-drop.rs @@ -1,3 +1,5 @@ +// ignore-stage1 + // Check that an arena (TypedArena) cannot carry elements whose drop // methods might access borrowed data of lifetime that does not // strictly outlive the arena itself. diff --git a/tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr b/tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr index 493d74b0bdec9..8bb3911241d10 100644 --- a/tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr +++ b/tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr @@ -1,5 +1,5 @@ error[E0597]: `arena` does not live long enough - --> $DIR/dropck-tarena-unsound-drop.rs:41:7 + --> $DIR/dropck-tarena-unsound-drop.rs:43:7 | LL | let arena: TypedArena = TypedArena::default(); | ----- binding `arena` declared here @@ -11,6 +11,6 @@ LL | } | `arena` dropped here while still borrowed | borrow might be used here, when `arena` is dropped and runs the `Drop` code for type `TypedArena` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs index 1dd6d211b3f0d..89ac48f36db52 100644 --- a/tests/ui-fulldeps/fluent-messages/test.rs +++ b/tests/ui-fulldeps/fluent-messages/test.rs @@ -2,9 +2,8 @@ #![feature(rustc_private)] #![crate_type = "lib"] - +extern crate rustc_errors; extern crate rustc_fluent_macro; -use rustc_fluent_macro::fluent_messages; /// Copy of the relevant `DiagnosticMessage` variant constructed by `fluent_messages` as it /// expects `crate::DiagnosticMessage` to exist. @@ -19,51 +18,37 @@ pub enum SubdiagnosticMessage { } mod missing_absolute { - use super::fluent_messages; - - fluent_messages! { "/definitely_does_not_exist.ftl" } + rustc_fluent_macro::fluent_messages! { "/definitely_does_not_exist.ftl" } //~^ ERROR could not open Fluent resource } mod missing_relative { - use super::fluent_messages; - - fluent_messages! { "../definitely_does_not_exist.ftl" } + rustc_fluent_macro::fluent_messages! { "../definitely_does_not_exist.ftl" } //~^ ERROR could not open Fluent resource } mod missing_message { - use super::fluent_messages; - - fluent_messages! { "./missing-message.ftl" } + rustc_fluent_macro::fluent_messages! { "./missing-message.ftl" } //~^ ERROR could not parse Fluent resource } mod duplicate { - use super::fluent_messages; - - fluent_messages! { "./duplicate.ftl" } + rustc_fluent_macro::fluent_messages! { "./duplicate.ftl" } //~^ ERROR overrides existing message: `no_crate_a_b_key` } mod slug_with_hyphens { - use super::fluent_messages; - - fluent_messages! { "./slug-with-hyphens.ftl" } + rustc_fluent_macro::fluent_messages! { "./slug-with-hyphens.ftl" } //~^ ERROR name `no_crate_this-slug-has-hyphens` contains a '-' character } mod label_with_hyphens { - use super::fluent_messages; - - fluent_messages! { "./label-with-hyphens.ftl" } + rustc_fluent_macro::fluent_messages! { "./label-with-hyphens.ftl" } //~^ ERROR attribute `label-has-hyphens` contains a '-' character } mod valid { - use super::fluent_messages; - - fluent_messages! { "./valid.ftl" } + rustc_fluent_macro::fluent_messages! { "./valid.ftl" } mod test_generated { use super::{fluent_generated::no_crate_key, DEFAULT_LOCALE_RESOURCE}; @@ -71,9 +56,7 @@ mod valid { } mod missing_crate_name { - use super::fluent_messages; - - fluent_messages! { "./missing-crate-name.ftl" } + rustc_fluent_macro::fluent_messages! { "./missing-crate-name.ftl" } //~^ ERROR name `no-crate_foo` contains a '-' character //~| ERROR name `with-hyphens` contains a '-' character //~| ERROR name `with-hyphens` does not start with the crate name @@ -87,16 +70,12 @@ mod missing_crate_name { } mod missing_message_ref { - use super::fluent_messages; - - fluent_messages! { "./missing-message-ref.ftl" } + rustc_fluent_macro::fluent_messages! { "./missing-message-ref.ftl" } //~^ ERROR referenced message `message` does not exist } mod bad_escape { - use super::fluent_messages; - - fluent_messages! { "./invalid-escape.ftl" } + rustc_fluent_macro::fluent_messages! { "./invalid-escape.ftl" } //~^ ERROR invalid escape `\n` //~| ERROR invalid escape `\"` //~| ERROR invalid escape `\'` diff --git a/tests/ui-fulldeps/fluent-messages/test.stderr b/tests/ui-fulldeps/fluent-messages/test.stderr index 2affe621c113a..09d4a38473204 100644 --- a/tests/ui-fulldeps/fluent-messages/test.stderr +++ b/tests/ui-fulldeps/fluent-messages/test.stderr @@ -1,20 +1,20 @@ error: could not open Fluent resource: os-specific message - --> $DIR/test.rs:24:24 + --> $DIR/test.rs:21:44 | -LL | fluent_messages! { "/definitely_does_not_exist.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "/definitely_does_not_exist.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not open Fluent resource: os-specific message - --> $DIR/test.rs:31:24 + --> $DIR/test.rs:26:44 | -LL | fluent_messages! { "../definitely_does_not_exist.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "../definitely_does_not_exist.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not parse Fluent resource - --> $DIR/test.rs:38:24 + --> $DIR/test.rs:31:44 | -LL | fluent_messages! { "./missing-message.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./missing-message.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: see additional errors emitted @@ -26,80 +26,80 @@ error: expected a message field for "no_crate_missing_message" | error: overrides existing message: `no_crate_a_b_key` - --> $DIR/test.rs:45:24 + --> $DIR/test.rs:36:44 | -LL | fluent_messages! { "./duplicate.ftl" } - | ^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./duplicate.ftl" } + | ^^^^^^^^^^^^^^^^^ error: name `no_crate_this-slug-has-hyphens` contains a '-' character - --> $DIR/test.rs:52:24 + --> $DIR/test.rs:41:44 | -LL | fluent_messages! { "./slug-with-hyphens.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./slug-with-hyphens.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: replace any '-'s with '_'s error: attribute `label-has-hyphens` contains a '-' character - --> $DIR/test.rs:59:24 + --> $DIR/test.rs:46:44 | -LL | fluent_messages! { "./label-with-hyphens.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./label-with-hyphens.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: replace any '-'s with '_'s error: name `with-hyphens` contains a '-' character - --> $DIR/test.rs:76:24 + --> $DIR/test.rs:59:44 | -LL | fluent_messages! { "./missing-crate-name.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./missing-crate-name.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: replace any '-'s with '_'s error: name `with-hyphens` does not start with the crate name - --> $DIR/test.rs:76:24 + --> $DIR/test.rs:59:44 | -LL | fluent_messages! { "./missing-crate-name.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./missing-crate-name.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: prepend `no_crate_` to the slug name: `no_crate_with_hyphens` error: name `no-crate_foo` contains a '-' character - --> $DIR/test.rs:76:24 + --> $DIR/test.rs:59:44 | -LL | fluent_messages! { "./missing-crate-name.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./missing-crate-name.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: replace any '-'s with '_'s error: referenced message `message` does not exist (in message `no_crate_missing_message_ref`) - --> $DIR/test.rs:92:24 + --> $DIR/test.rs:73:44 | -LL | fluent_messages! { "./missing-message-ref.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./missing-message-ref.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: you may have meant to use a variable reference (`{$message}`) error: invalid escape `\n` in Fluent resource - --> $DIR/test.rs:99:24 + --> $DIR/test.rs:78:44 | -LL | fluent_messages! { "./invalid-escape.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./invalid-escape.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: Fluent does not interpret these escape sequences () error: invalid escape `\"` in Fluent resource - --> $DIR/test.rs:99:24 + --> $DIR/test.rs:78:44 | -LL | fluent_messages! { "./invalid-escape.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./invalid-escape.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: Fluent does not interpret these escape sequences () error: invalid escape `\'` in Fluent resource - --> $DIR/test.rs:99:24 + --> $DIR/test.rs:78:44 | -LL | fluent_messages! { "./invalid-escape.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | rustc_fluent_macro::fluent_messages! { "./invalid-escape.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^ | = note: Fluent does not interpret these escape sequences () diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 994fc26ba021e..7f545ead152ca 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -16,11 +16,10 @@ use rustc_errors::{ AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, Handler, IntoDiagnostic, SubdiagnosticMessage, }; -use rustc_fluent_macro::fluent_messages; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; -fluent_messages! { "./diagnostics.ftl" } +rustc_fluent_macro::fluent_messages! { "./diagnostics.ftl" } #[derive(Diagnostic)] #[diag(no_crate_example)] diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index 6e670c018520b..8e0535e021beb 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,5 +1,5 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:43:17 + --> $DIR/diagnostics.rs:42:17 | LL | handler.struct_err("untranslatable diagnostic") | ^^^^^^^^^^ @@ -11,13 +11,13 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:63:14 + --> $DIR/diagnostics.rs:62:14 | LL | diag.note("untranslatable diagnostic"); | ^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:80:25 + --> $DIR/diagnostics.rs:79:25 | LL | let _diag = handler.struct_err(crate::fluent_generated::no_crate_example); | ^^^^^^^^^^ @@ -29,13 +29,13 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:83:25 + --> $DIR/diagnostics.rs:82:25 | LL | let _diag = handler.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:83:25 + --> $DIR/diagnostics.rs:82:25 | LL | let _diag = handler.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ diff --git a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs index aeb68bf05e1ed..392199866654d 100644 --- a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs +++ b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs @@ -1,7 +1,6 @@ // Test the `rustc::span_use_eq_ctxt` internal lint -// #[cfg(bootstrap)] -// ignore-stage1 // compile-flags: -Z unstable-options +// ignore-stage1 #![feature(rustc_private)] #![deny(rustc::span_use_eq_ctxt)] diff --git a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr index 3d8a7dd1ec050..fcf2565c8ab1e 100644 --- a/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr +++ b/tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr @@ -1,14 +1,14 @@ error: use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` - --> $DIR/span_use_eq_ctxt.rs:14:5 + --> $DIR/span_use_eq_ctxt.rs:13:5 | LL | s.ctxt() == t.ctxt() | ^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/span_use_eq_ctxt.rs:7:9 + --> $DIR/span_use_eq_ctxt.rs:6:9 | LL | #![deny(rustc::span_use_eq_ctxt)] | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui-fulldeps/pathless-extern-unstable.rs b/tests/ui-fulldeps/pathless-extern-unstable.rs index 7fba8343bc088..50d157c5795e8 100644 --- a/tests/ui-fulldeps/pathless-extern-unstable.rs +++ b/tests/ui-fulldeps/pathless-extern-unstable.rs @@ -1,5 +1,6 @@ // edition:2018 // compile-flags:--extern rustc_middle +// ignore-stage1 // Test that `--extern rustc_middle` fails with `rustc_private`. diff --git a/tests/ui-fulldeps/pathless-extern-unstable.stderr b/tests/ui-fulldeps/pathless-extern-unstable.stderr index 174cd3c280477..840b95d755c60 100644 --- a/tests/ui-fulldeps/pathless-extern-unstable.stderr +++ b/tests/ui-fulldeps/pathless-extern-unstable.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? - --> $DIR/pathless-extern-unstable.rs:6:9 + --> $DIR/pathless-extern-unstable.rs:7:9 | LL | pub use rustc_middle; | ^^^^^^^^^^^^ @@ -7,6 +7,6 @@ LL | pub use rustc_middle; = note: see issue #27812 for more information = help: add `#![feature(rustc_private)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 3d6cff00a6d2f..9e581620ec1b4 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -130,9 +130,9 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P)) { iter_exprs(depth - 1, &mut |e| { g(ExprKind::Closure(Box::new(Closure { binder: ClosureBinder::NotPresent, - capture_clause: CaptureBy::Value, + capture_clause: CaptureBy::Value { move_kw: DUMMY_SP }, constness: Const::No, - asyncness: Async::No, + coro_kind: None, movability: Movability::Movable, fn_decl: decl.clone(), body: e, diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs index 283d87d3eb604..221f26f8edc42 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs @@ -20,11 +20,10 @@ extern crate rustc_session; extern crate rustc_span; use rustc_errors::{Applicability, DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; -fluent_messages! { "./example.ftl" } +rustc_fluent_macro::fluent_messages! { "./example.ftl" } struct NotIntoDiagnosticArg; diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr index 70d7b3225b599..bdcf54bd19042 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive-doc-comment-field.rs:37:10 + --> $DIR/diagnostic-derive-doc-comment-field.rs:36:10 | LL | #[derive(Diagnostic)] | ---------- required by a bound introduced by this call @@ -13,7 +13,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive-doc-comment-field.rs:47:10 + --> $DIR/diagnostic-derive-doc-comment-field.rs:46:10 | LL | #[derive(Subdiagnostic)] | ------------- required by a bound introduced by this call diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index c30120e5cf3a3..63fb78ee91995 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -19,7 +19,6 @@ use rustc_span::Span; extern crate rustc_fluent_macro; extern crate rustc_macros; -use rustc_fluent_macro::fluent_messages; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; extern crate rustc_middle; @@ -30,7 +29,7 @@ use rustc_errors::{Applicability, DiagnosticMessage, MultiSpan, SubdiagnosticMes extern crate rustc_session; -fluent_messages! { "./example.ftl" } +rustc_fluent_macro::fluent_messages! { "./example.ftl" } #[derive(Diagnostic)] #[diag(no_crate_example, code = "E0123")] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 014cd5a73bd8b..d8ba65d297e42 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -1,11 +1,11 @@ error: unsupported type attribute for diagnostic derive enum - --> $DIR/diagnostic-derive.rs:44:1 + --> $DIR/diagnostic-derive.rs:43:1 | LL | #[diag(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:47:5 + --> $DIR/diagnostic-derive.rs:46:5 | LL | Foo, | ^^^ @@ -13,7 +13,7 @@ LL | Foo, = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:49:5 + --> $DIR/diagnostic-derive.rs:48:5 | LL | Bar, | ^^^ @@ -21,13 +21,13 @@ LL | Bar, = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[nonsense(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:60:1 + --> $DIR/diagnostic-derive.rs:59:1 | LL | #[nonsense(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:60:1 + --> $DIR/diagnostic-derive.rs:59:1 | LL | / #[nonsense(no_crate_example, code = "E0123")] LL | | @@ -39,7 +39,7 @@ LL | | struct InvalidStructAttr {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:67:1 + --> $DIR/diagnostic-derive.rs:66:1 | LL | / #[diag("E0123")] LL | | @@ -49,13 +49,13 @@ LL | | struct InvalidLitNestedAttr {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug must be the first argument - --> $DIR/diagnostic-derive.rs:77:16 + --> $DIR/diagnostic-derive.rs:76:16 | LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")] | ^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:77:1 + --> $DIR/diagnostic-derive.rs:76:1 | LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")] LL | | @@ -66,7 +66,7 @@ LL | | struct InvalidNestedStructAttr1 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: unknown argument - --> $DIR/diagnostic-derive.rs:83:8 + --> $DIR/diagnostic-derive.rs:82:8 | LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] | ^^^^^^^^ @@ -74,7 +74,7 @@ LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] = note: only the `code` parameter is valid after the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:83:1 + --> $DIR/diagnostic-derive.rs:82:1 | LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")] LL | | @@ -85,7 +85,7 @@ LL | | struct InvalidNestedStructAttr2 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: unknown argument - --> $DIR/diagnostic-derive.rs:89:8 + --> $DIR/diagnostic-derive.rs:88:8 | LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] | ^^^^^^^^ @@ -93,7 +93,7 @@ LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] = note: only the `code` parameter is valid after the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:89:1 + --> $DIR/diagnostic-derive.rs:88:1 | LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")] LL | | @@ -104,7 +104,7 @@ LL | | struct InvalidNestedStructAttr3 {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: unknown argument - --> $DIR/diagnostic-derive.rs:95:42 + --> $DIR/diagnostic-derive.rs:94:42 | LL | #[diag(no_crate_example, code = "E0123", slug = "foo")] | ^^^^ @@ -112,55 +112,55 @@ LL | #[diag(no_crate_example, code = "E0123", slug = "foo")] = note: only the `code` parameter is valid after the slug error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:102:5 + --> $DIR/diagnostic-derive.rs:101:5 | LL | #[suggestion = "bar"] | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:8 + --> $DIR/diagnostic-derive.rs:108:8 | LL | #[diag(no_crate_example, code = "E0456")] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:8 + --> $DIR/diagnostic-derive.rs:107:8 | LL | #[diag(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:26 + --> $DIR/diagnostic-derive.rs:108:26 | LL | #[diag(no_crate_example, code = "E0456")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:26 + --> $DIR/diagnostic-derive.rs:107:26 | LL | #[diag(no_crate_example, code = "E0123")] | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:115:42 + --> $DIR/diagnostic-derive.rs:114:42 | LL | #[diag(no_crate_example, code = "E0456", code = "E0457")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:115:26 + --> $DIR/diagnostic-derive.rs:114:26 | LL | #[diag(no_crate_example, code = "E0456", code = "E0457")] | ^^^^ error: diagnostic slug must be the first argument - --> $DIR/diagnostic-derive.rs:120:43 + --> $DIR/diagnostic-derive.rs:119:43 | LL | #[diag(no_crate_example, no_crate::example, code = "E0456")] | ^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:125:1 + --> $DIR/diagnostic-derive.rs:124:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -168,7 +168,7 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:128:1 + --> $DIR/diagnostic-derive.rs:127:1 | LL | / #[diag(code = "E0456")] LL | | @@ -178,31 +178,31 @@ LL | | struct SlugNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:139:5 + --> $DIR/diagnostic-derive.rs:138:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:147:5 + --> $DIR/diagnostic-derive.rs:146:5 | LL | #[nonsense] | ^^^^^^^^^^^ error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:164:5 + --> $DIR/diagnostic-derive.rs:163:5 | LL | #[label(no_crate_label)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:172:46 + --> $DIR/diagnostic-derive.rs:171:46 | LL | #[suggestion(no_crate_suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:177:10 + --> $DIR/diagnostic-derive.rs:176:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ expected `'}'` in format string @@ -211,7 +211,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:187:10 + --> $DIR/diagnostic-derive.rs:186:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ unmatched `}` in format string @@ -220,19 +220,19 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:207:5 + --> $DIR/diagnostic-derive.rs:206:5 | LL | #[label(no_crate_label)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:226:5 + --> $DIR/diagnostic-derive.rs:225:5 | LL | #[suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid nested attribute - --> $DIR/diagnostic-derive.rs:234:18 + --> $DIR/diagnostic-derive.rs:233:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^ @@ -240,13 +240,13 @@ LL | #[suggestion(nonsense = "bar")] = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:234:5 + --> $DIR/diagnostic-derive.rs:233:5 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid nested attribute - --> $DIR/diagnostic-derive.rs:243:18 + --> $DIR/diagnostic-derive.rs:242:18 | LL | #[suggestion(msg = "bar")] | ^^^ @@ -254,13 +254,13 @@ LL | #[suggestion(msg = "bar")] = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:243:5 + --> $DIR/diagnostic-derive.rs:242:5 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:266:5 + --> $DIR/diagnostic-derive.rs:265:5 | LL | / #[suggestion(no_crate_suggestion, code = "This is suggested code")] LL | | @@ -270,79 +270,79 @@ LL | | suggestion: Applicability, = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: specified multiple times - --> $DIR/diagnostic-derive.rs:282:24 + --> $DIR/diagnostic-derive.rs:281:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:282:18 + --> $DIR/diagnostic-derive.rs:281:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:290:33 + --> $DIR/diagnostic-derive.rs:289:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:290:18 + --> $DIR/diagnostic-derive.rs:289:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:297:5 + --> $DIR/diagnostic-derive.rs:296:5 | LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:448:5 + --> $DIR/diagnostic-derive.rs:447:5 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:450:24 + --> $DIR/diagnostic-derive.rs:449:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:456:69 + --> $DIR/diagnostic-derive.rs:455:69 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")] | ^^^^^^^^ error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()` - --> $DIR/diagnostic-derive.rs:523:5 + --> $DIR/diagnostic-derive.rs:522:5 | LL | #[help(no_crate_help)] | ^^^^^^^^^^^^^^^^^^^^^^ error: a diagnostic slug must be the first argument to the attribute - --> $DIR/diagnostic-derive.rs:532:32 + --> $DIR/diagnostic-derive.rs:531:32 | LL | #[label(no_crate_label, foo)] | ^ error: only `no_span` is a valid nested attribute - --> $DIR/diagnostic-derive.rs:540:29 + --> $DIR/diagnostic-derive.rs:539:29 | LL | #[label(no_crate_label, foo = "...")] | ^^^ error: only `no_span` is a valid nested attribute - --> $DIR/diagnostic-derive.rs:548:29 + --> $DIR/diagnostic-derive.rs:547:29 | LL | #[label(no_crate_label, foo("..."))] | ^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:560:5 + --> $DIR/diagnostic-derive.rs:559:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -350,13 +350,13 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:580:1 + --> $DIR/diagnostic-derive.rs:579:1 | LL | #[error(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:580:1 + --> $DIR/diagnostic-derive.rs:579:1 | LL | / #[error(no_crate_example, code = "E0123")] LL | | @@ -368,13 +368,13 @@ LL | | struct ErrorAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:587:1 + --> $DIR/diagnostic-derive.rs:586:1 | LL | #[warn_(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:587:1 + --> $DIR/diagnostic-derive.rs:586:1 | LL | / #[warn_(no_crate_example, code = "E0123")] LL | | @@ -386,13 +386,13 @@ LL | | struct WarnAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:594:1 + --> $DIR/diagnostic-derive.rs:593:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:594:1 + --> $DIR/diagnostic-derive.rs:593:1 | LL | / #[lint(no_crate_example, code = "E0123")] LL | | @@ -404,13 +404,13 @@ LL | | struct LintAttributeOnSessionDiag {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:600:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:600:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -418,7 +418,7 @@ LL | #[lint(no_crate_example, code = "E0123")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:600:1 | LL | / #[lint(no_crate_example, code = "E0123")] LL | | @@ -431,19 +431,19 @@ LL | | struct LintAttributeOnLintDiag {} = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]` error: specified multiple times - --> $DIR/diagnostic-derive.rs:611:53 + --> $DIR/diagnostic-derive.rs:610:53 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:611:39 + --> $DIR/diagnostic-derive.rs:610:39 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] | ^^^^ error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:620:24 + --> $DIR/diagnostic-derive.rs:619:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -451,7 +451,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:628:17 + --> $DIR/diagnostic-derive.rs:627:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -459,13 +459,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:635:5 + --> $DIR/diagnostic-derive.rs:634:5 | LL | #[suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:642:1 + --> $DIR/diagnostic-derive.rs:641:1 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -473,7 +473,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)] = help: consider creating a `Subdiagnostic` instead error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:645:1 + --> $DIR/diagnostic-derive.rs:644:1 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -481,7 +481,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:649:5 + --> $DIR/diagnostic-derive.rs:648:5 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -489,7 +489,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)] = help: consider creating a `Subdiagnostic` instead error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:657:1 + --> $DIR/diagnostic-derive.rs:656:1 | LL | #[suggestion(no_crate_suggestion, code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL | #[suggestion(no_crate_suggestion, code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:666:1 + --> $DIR/diagnostic-derive.rs:665:1 | LL | #[label] | ^^^^^^^^ @@ -505,31 +505,31 @@ LL | #[label] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:700:7 + --> $DIR/diagnostic-derive.rs:699:7 | LL | #[subdiagnostic(bad)] | ^^^^^^^^^^^^^^^^^^ error: `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:708:5 + --> $DIR/diagnostic-derive.rs:707:5 | LL | #[subdiagnostic = "bad"] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:716:7 + --> $DIR/diagnostic-derive.rs:715:7 | LL | #[subdiagnostic(bad, bad)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:724:7 + --> $DIR/diagnostic-derive.rs:723:7 | LL | #[subdiagnostic("bad")] | ^^^^^^^^^^^^^^^^^^^^ error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:732:5 + --> $DIR/diagnostic-derive.rs:731:5 | LL | #[subdiagnostic(eager)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -537,19 +537,19 @@ LL | #[subdiagnostic(eager)] = help: eager subdiagnostics are not supported on lints error: expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive.rs:790:23 + --> $DIR/diagnostic-derive.rs:789:23 | LL | #[suggestion(code())] | ^ error: `code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:798:23 + --> $DIR/diagnostic-derive.rs:797:23 | LL | #[suggestion(code(foo))] | ^^^ error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:822:5 + --> $DIR/diagnostic-derive.rs:821:5 | LL | #[suggestion(no_crate_suggestion, code = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -559,85 +559,85 @@ LL | #[suggestion(no_crate_suggestion, code = "")] = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:55:8 + --> $DIR/diagnostic-derive.rs:54:8 | LL | #[diag = "E0123"] | ^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:798:23 + --> $DIR/diagnostic-derive.rs:797:23 | LL | #[suggestion(code(foo))] | ^^^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:807:25 + --> $DIR/diagnostic-derive.rs:806:25 | LL | #[suggestion(code = 3)] | ^ maybe a missing crate `core`? error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:60:3 + --> $DIR/diagnostic-derive.rs:59:3 | LL | #[nonsense(no_crate_example, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:147:7 + --> $DIR/diagnostic-derive.rs:146:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:580:3 + --> $DIR/diagnostic-derive.rs:579:3 | LL | #[error(no_crate_example, code = "E0123")] | ^^^^^ error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:587:3 + --> $DIR/diagnostic-derive.rs:586:3 | LL | #[warn_(no_crate_example, code = "E0123")] | ^^^^^ help: a built-in attribute with a similar name exists: `warn` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:594:3 + --> $DIR/diagnostic-derive.rs:593:3 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:601:3 + --> $DIR/diagnostic-derive.rs:600:3 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:642:3 + --> $DIR/diagnostic-derive.rs:641:3 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:645:3 + --> $DIR/diagnostic-derive.rs:644:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:649:7 + --> $DIR/diagnostic-derive.rs:648:7 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated` - --> $DIR/diagnostic-derive.rs:72:8 + --> $DIR/diagnostic-derive.rs:71:8 | LL | #[diag(nonsense, code = "E0123")] | ^^^^^^^^ not found in `crate::fluent_generated` error[E0425]: cannot find value `__code_34` in this scope - --> $DIR/diagnostic-derive.rs:804:10 + --> $DIR/diagnostic-derive.rs:803:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ not found in this scope @@ -645,7 +645,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:346:12 + --> $DIR/diagnostic-derive.rs:345:12 | LL | #[derive(Diagnostic)] | ---------- required by a bound introduced by this call diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs index a0a8114e0c5c5..3314831126119 100644 --- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs +++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs @@ -1,4 +1,5 @@ // rustc-env:CARGO_CRATE_NAME=rustc_dummy +// ignore-stage1 #![feature(rustc_private)] #![crate_type = "lib"] diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr index dcf4af5df50a7..c752a5ee05757 100644 --- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr +++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr @@ -1,5 +1,5 @@ error: diagnostic slug and crate name do not match - --> $DIR/enforce_slug_naming.rs:22:8 + --> $DIR/enforce_slug_naming.rs:23:8 | LL | #[diag(compiletest_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,5 @@ LL | #[diag(compiletest_example, code = "E0123")] = note: slug is `compiletest_example` but the crate name is `rustc_dummy` = help: expected a slug starting with `dummy_...` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs b/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs index 57798dda3eb24..2ec07fa142030 100644 --- a/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs +++ b/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs @@ -9,12 +9,11 @@ extern crate rustc_driver; extern crate rustc_fluent_macro; extern crate rustc_macros; extern crate rustc_errors; -use rustc_fluent_macro::fluent_messages; use rustc_macros::Diagnostic; use rustc_errors::{SubdiagnosticMessage, DiagnosticMessage}; extern crate rustc_session; -fluent_messages! { "./example.ftl" } +rustc_fluent_macro::fluent_messages! { "./example.ftl" } #[derive(Diagnostic)] #[diag(no_crate_bad_reference)] diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index dd0f7a7efb71c..74cf91db7a7c5 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -18,11 +18,10 @@ extern crate rustc_session; extern crate rustc_span; use rustc_errors::{Applicability, DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_macros::Subdiagnostic; use rustc_span::Span; -fluent_messages! { "./example.ftl" } +rustc_fluent_macro::fluent_messages! { "./example.ftl" } #[derive(Subdiagnostic)] #[label(no_crate_example)] diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 1f267aceb9ef2..80bee3bd6e6c3 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -1,5 +1,5 @@ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:52:1 + --> $DIR/subdiagnostic-derive.rs:51:1 | LL | / #[label(no_crate_example)] LL | | @@ -9,127 +9,127 @@ LL | | } | |_^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:59:1 + --> $DIR/subdiagnostic-derive.rs:58:1 | LL | #[label] | ^^^^^^^^ error: `#[foo]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:68:1 + --> $DIR/subdiagnostic-derive.rs:67:1 | LL | #[foo] | ^^^^^^ error: `#[label = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:78:1 + --> $DIR/subdiagnostic-derive.rs:77:1 | LL | #[label = "..."] | ^^^^^^^^^^^^^^^^ error: only `no_span` is a valid nested attribute - --> $DIR/subdiagnostic-derive.rs:87:9 + --> $DIR/subdiagnostic-derive.rs:86:9 | LL | #[label(bug = "...")] | ^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:87:1 + --> $DIR/subdiagnostic-derive.rs:86:1 | LL | #[label(bug = "...")] | ^^^^^^^^^^^^^^^^^^^^^ error: only `no_span` is a valid nested attribute - --> $DIR/subdiagnostic-derive.rs:107:9 + --> $DIR/subdiagnostic-derive.rs:106:9 | LL | #[label(slug = 4)] | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:107:1 + --> $DIR/subdiagnostic-derive.rs:106:1 | LL | #[label(slug = 4)] | ^^^^^^^^^^^^^^^^^^ error: only `no_span` is a valid nested attribute - --> $DIR/subdiagnostic-derive.rs:117:9 + --> $DIR/subdiagnostic-derive.rs:116:9 | LL | #[label(slug("..."))] | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:117:1 + --> $DIR/subdiagnostic-derive.rs:116:1 | LL | #[label(slug("..."))] | ^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:137:1 + --> $DIR/subdiagnostic-derive.rs:136:1 | LL | #[label()] | ^^^^^^^^^^ error: only `no_span` is a valid nested attribute - --> $DIR/subdiagnostic-derive.rs:146:27 + --> $DIR/subdiagnostic-derive.rs:145:27 | LL | #[label(no_crate_example, code = "...")] | ^^^^ error: only `no_span` is a valid nested attribute - --> $DIR/subdiagnostic-derive.rs:155:27 + --> $DIR/subdiagnostic-derive.rs:154:27 | LL | #[label(no_crate_example, applicability = "machine-applicable")] | ^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:164:1 + --> $DIR/subdiagnostic-derive.rs:163:1 | LL | #[foo] | ^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:178:5 + --> $DIR/subdiagnostic-derive.rs:177:5 | LL | #[bar] | ^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:190:5 + --> $DIR/subdiagnostic-derive.rs:189:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:202:5 + --> $DIR/subdiagnostic-derive.rs:201:5 | LL | #[bar = 4] | ^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:214:5 + --> $DIR/subdiagnostic-derive.rs:213:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ error: only `no_span` is a valid nested attribute - --> $DIR/subdiagnostic-derive.rs:226:13 + --> $DIR/subdiagnostic-derive.rs:225:13 | LL | #[label(code = "...")] | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:226:5 + --> $DIR/subdiagnostic-derive.rs:225:5 | LL | #[label(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^ error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:255:5 + --> $DIR/subdiagnostic-derive.rs:254:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:252:1 + --> $DIR/subdiagnostic-derive.rs:251:1 | LL | / #[label(no_crate_example)] LL | | @@ -141,13 +141,13 @@ LL | | } | |_^ error: `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:265:5 + --> $DIR/subdiagnostic-derive.rs:264:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:275:5 + --> $DIR/subdiagnostic-derive.rs:274:5 | LL | #[bar] | ^^^^^^ @@ -155,13 +155,13 @@ LL | #[bar] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:286:5 + --> $DIR/subdiagnostic-derive.rs:285:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:297:5 + --> $DIR/subdiagnostic-derive.rs:296:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ @@ -169,73 +169,73 @@ LL | #[bar("...")] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:329:44 + --> $DIR/subdiagnostic-derive.rs:328:44 | LL | #[label(no_crate_example, no_crate::example)] | ^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:342:5 + --> $DIR/subdiagnostic-derive.rs:341:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:339:5 + --> $DIR/subdiagnostic-derive.rs:338:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:348:8 + --> $DIR/subdiagnostic-derive.rs:347:8 | LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:385:46 + --> $DIR/subdiagnostic-derive.rs:384:46 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:385:32 + --> $DIR/subdiagnostic-derive.rs:384:32 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] | ^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:403:5 + --> $DIR/subdiagnostic-derive.rs:402:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:400:5 + --> $DIR/subdiagnostic-derive.rs:399:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:413:5 + --> $DIR/subdiagnostic-derive.rs:412:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:426:1 + --> $DIR/subdiagnostic-derive.rs:425:1 | LL | #[suggestion(no_crate_example)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:436:62 + --> $DIR/subdiagnostic-derive.rs:435:62 | LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")] | ^^^^^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:454:1 + --> $DIR/subdiagnostic-derive.rs:453:1 | LL | / #[suggestion(no_crate_example, code = "...")] LL | | @@ -245,25 +245,25 @@ LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:468:1 + --> $DIR/subdiagnostic-derive.rs:467:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:488:39 + --> $DIR/subdiagnostic-derive.rs:487:39 | LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:507:43 + --> $DIR/subdiagnostic-derive.rs:506:43 | LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:530:5 + --> $DIR/subdiagnostic-derive.rs:529:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:533:5 + --> $DIR/subdiagnostic-derive.rs:532:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:527:1 + --> $DIR/subdiagnostic-derive.rs:526:1 | LL | / #[suggestion(no_crate_example, code = "...")] LL | | @@ -291,7 +291,7 @@ LL | | } | |_^ error: invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:542:42 + --> $DIR/subdiagnostic-derive.rs:541:42 | LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] | ^^^^ @@ -299,7 +299,7 @@ LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "mac = help: only `no_span`, `style` and `applicability` are valid nested attributes error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:542:1 + --> $DIR/subdiagnostic-derive.rs:541:1 | LL | / #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] LL | | @@ -310,19 +310,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:552:5 + --> $DIR/subdiagnostic-derive.rs:551:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:560:5 + --> $DIR/subdiagnostic-derive.rs:559:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:569:5 + --> $DIR/subdiagnostic-derive.rs:568:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -330,7 +330,7 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:566:1 + --> $DIR/subdiagnostic-derive.rs:565:1 | LL | / #[multipart_suggestion(no_crate_example)] LL | | @@ -342,91 +342,91 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:577:5 + --> $DIR/subdiagnostic-derive.rs:576:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:580:5 + --> $DIR/subdiagnostic-derive.rs:579:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `code` is the only valid nested attribute - --> $DIR/subdiagnostic-derive.rs:583:23 + --> $DIR/subdiagnostic-derive.rs:582:23 | LL | #[suggestion_part(foo = "bar")] | ^^^ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:588:5 + --> $DIR/subdiagnostic-derive.rs:587:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:591:5 + --> $DIR/subdiagnostic-derive.rs:590:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:599:37 + --> $DIR/subdiagnostic-derive.rs:598:37 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:599:23 + --> $DIR/subdiagnostic-derive.rs:598:23 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^ error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` - --> $DIR/subdiagnostic-derive.rs:628:5 + --> $DIR/subdiagnostic-derive.rs:627:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:676:34 + --> $DIR/subdiagnostic-derive.rs:675:34 | LL | #[suggestion_part(code("foo"))] | ^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:687:41 + --> $DIR/subdiagnostic-derive.rs:686:41 | LL | #[suggestion_part(code("foo", "bar"))] | ^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:698:30 + --> $DIR/subdiagnostic-derive.rs:697:30 | LL | #[suggestion_part(code(3))] | ^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:709:29 + --> $DIR/subdiagnostic-derive.rs:708:29 | LL | #[suggestion_part(code())] | ^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:764:1 + --> $DIR/subdiagnostic-derive.rs:763:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:764:1 + --> $DIR/subdiagnostic-derive.rs:763:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:773:1 + --> $DIR/subdiagnostic-derive.rs:772:1 | LL | #[suggestion_hidden(no_crate_example, code = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -434,7 +434,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:781:1 + --> $DIR/subdiagnostic-derive.rs:780:1 | LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -442,7 +442,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: invalid suggestion style - --> $DIR/subdiagnostic-derive.rs:789:51 + --> $DIR/subdiagnostic-derive.rs:788:51 | LL | #[suggestion(no_crate_example, code = "", style = "foo")] | ^^^^^ @@ -450,25 +450,25 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")] = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` error: expected `= "xxx"` - --> $DIR/subdiagnostic-derive.rs:797:49 + --> $DIR/subdiagnostic-derive.rs:796:49 | LL | #[suggestion(no_crate_example, code = "", style = 42)] | ^ error: a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:805:48 + --> $DIR/subdiagnostic-derive.rs:804:48 | LL | #[suggestion(no_crate_example, code = "", style)] | ^ error: expected `= "xxx"` - --> $DIR/subdiagnostic-derive.rs:813:48 + --> $DIR/subdiagnostic-derive.rs:812:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] | ^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:826:5 + --> $DIR/subdiagnostic-derive.rs:825:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -477,7 +477,7 @@ LL | #[primary_span] = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:823:1 + --> $DIR/subdiagnostic-derive.rs:822:1 | LL | / #[suggestion(no_crate_example, code = "")] LL | | @@ -489,115 +489,115 @@ LL | | } | |_^ error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/subdiagnostic-derive.rs:97:9 + --> $DIR/subdiagnostic-derive.rs:96:9 | LL | #[label("...")] | ^^^^^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/subdiagnostic-derive.rs:313:1 + --> $DIR/subdiagnostic-derive.rs:312:1 | LL | union AC { | ^^^^^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/subdiagnostic-derive.rs:583:27 + --> $DIR/subdiagnostic-derive.rs:582:27 | LL | #[suggestion_part(foo = "bar")] | ^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/subdiagnostic-derive.rs:676:28 + --> $DIR/subdiagnostic-derive.rs:675:28 | LL | #[suggestion_part(code("foo"))] | ^^^^^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/subdiagnostic-derive.rs:687:28 + --> $DIR/subdiagnostic-derive.rs:686:28 | LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/subdiagnostic-derive.rs:698:28 + --> $DIR/subdiagnostic-derive.rs:697:28 | LL | #[suggestion_part(code(3))] | ^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/subdiagnostic-derive.rs:721:30 + --> $DIR/subdiagnostic-derive.rs:720:30 | LL | #[suggestion_part(code = 3)] | ^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/subdiagnostic-derive.rs:813:48 + --> $DIR/subdiagnostic-derive.rs:812:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] | ^ maybe a missing crate `core`? error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:68:3 + --> $DIR/subdiagnostic-derive.rs:67:3 | LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:164:3 + --> $DIR/subdiagnostic-derive.rs:163:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:178:7 + --> $DIR/subdiagnostic-derive.rs:177:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:190:7 + --> $DIR/subdiagnostic-derive.rs:189:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:202:7 + --> $DIR/subdiagnostic-derive.rs:201:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:214:7 + --> $DIR/subdiagnostic-derive.rs:213:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:275:7 + --> $DIR/subdiagnostic-derive.rs:274:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:286:7 + --> $DIR/subdiagnostic-derive.rs:285:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:297:7 + --> $DIR/subdiagnostic-derive.rs:296:7 | LL | #[bar("...")] | ^^^ error[E0425]: cannot find value `slug` in module `crate::fluent_generated` - --> $DIR/subdiagnostic-derive.rs:127:9 + --> $DIR/subdiagnostic-derive.rs:126:9 | LL | #[label(slug)] | ^^^^ not found in `crate::fluent_generated` error[E0425]: cannot find value `__code_29` in this scope - --> $DIR/subdiagnostic-derive.rs:715:10 + --> $DIR/subdiagnostic-derive.rs:714:10 | LL | #[derive(Subdiagnostic)] | ^^^^^^^^^^^^^ not found in this scope diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs new file mode 100644 index 0000000000000..170b1fd73b16f --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -0,0 +1,120 @@ +// run-pass +//! Test that users are able to use stable mir APIs to retrieve information of global allocations +//! such as `vtable_allocation`. + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] +#![feature(ascii_char, ascii_char_variants)] + +extern crate rustc_hir; +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use rustc_middle::ty::TyCtxt; +use rustc_smir::rustc_internal; +use stable_mir::{CrateItem, CrateItems, ItemKind}; +use stable_mir::crate_def::CrateDef; +use stable_mir::mir::alloc::GlobalAlloc; +use stable_mir::mir::mono::StaticDef; +use std::ascii::Char; +use std::assert_matches::assert_matches; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + // Find items in the local crate. + let items = stable_mir::all_local_items(); + check_foo(*get_item(&items, (ItemKind::Static, "FOO")).unwrap()); + check_bar(*get_item(&items, (ItemKind::Static, "BAR")).unwrap()); + ControlFlow::Continue(()) +} + +/// Check the allocation data for static `FOO`. +/// +/// ```no_run +/// static FOO: [&str; 2] = ["hi", "there"]; +/// ``` +fn check_foo(item: CrateItem) { + let def = StaticDef::try_from(item).unwrap(); + let alloc = def.eval_initializer().unwrap(); + assert_eq!(alloc.provenance.ptrs.len(), 2); + + let alloc_id_0 = alloc.provenance.ptrs[0].1.0; + assert_matches!(GlobalAlloc::from(alloc_id_0), GlobalAlloc::Memory(..)); + + let alloc_id_1 = alloc.provenance.ptrs[1].1.0; + assert_matches!(GlobalAlloc::from(alloc_id_1), GlobalAlloc::Memory(..)); +} + +/// Check the allocation data for static `BAR`. +/// +/// ```no_run +/// static BAR: &str = "Bar"; +/// ``` +fn check_bar(item: CrateItem) { + let def = StaticDef::try_from(item).unwrap(); + let alloc = def.eval_initializer().unwrap(); + assert_eq!(alloc.provenance.ptrs.len(), 1); + + let alloc_id_0 = alloc.provenance.ptrs[0].1.0; + let GlobalAlloc::Memory(allocation) = GlobalAlloc::from(alloc_id_0) else { unreachable!() }; + assert_eq!(allocation.bytes.len(), 3); + assert_eq!(allocation.bytes[0].unwrap(), Char::CapitalB.to_u8()); + assert_eq!(allocation.bytes[1].unwrap(), Char::SmallA.to_u8()); + assert_eq!(allocation.bytes[2].unwrap(), Char::SmallR.to_u8()); +} + +// Use internal API to find a function in a crate. +fn get_item<'a>( + items: &'a CrateItems, + item: (ItemKind, &str), +) -> Option<&'a stable_mir::CrateItem> { + items.iter().find(|crate_item| { + (item.0 == crate_item.kind()) && crate_item.name() == item.1 + }) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "alloc_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, tcx, test_stable_mir(tcx)).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + static FOO: [&str; 2] = ["hi", "there"]; + static BAR: &str = "Bar"; + + pub fn main() {{ + println!("{{FOO:?}}! {{BAR}}"); + }}"# + )?; + Ok(()) +} diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs new file mode 100644 index 0000000000000..d311be5982d2d --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -0,0 +1,132 @@ +// run-pass +//! Test that users are able to use stable mir APIs to retrieve information about crate definitions. + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use std::assert_matches::assert_matches; +use mir::{mono::Instance, TerminatorKind::*}; +use rustc_middle::ty::TyCtxt; +use rustc_smir::rustc_internal; +use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy}; +use stable_mir::*; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let entry = stable_mir::entry_fn().unwrap(); + let main_fn = Instance::try_from(entry).unwrap(); + assert_eq!(main_fn.name(), "main"); + assert_eq!(main_fn.trimmed_name(), "main"); + + let instances = get_instances(main_fn.body().unwrap()); + assert_eq!(instances.len(), 2); + test_fn(instances[0], "from_u32", "std::char::from_u32", "core"); + test_fn(instances[1], "Vec::::new", "std::vec::Vec::::new", "alloc"); + test_vec_new(instances[1]); + ControlFlow::Continue(()) +} + +fn test_fn(instance: Instance, expected_trimmed: &str, expected_qualified: &str, krate: &str) { + let trimmed = instance.trimmed_name(); + let qualified = instance.name(); + assert_eq!(&trimmed, expected_trimmed); + assert_eq!(&qualified, expected_qualified); + + let item = CrateItem::try_from(instance).unwrap(); + let trimmed = item.trimmed_name(); + let qualified = item.name(); + assert_eq!(trimmed, expected_trimmed.replace("u8", "T")); + assert_eq!(qualified, expected_qualified.replace("u8", "T")); + assert_eq!(&item.krate().name, krate); +} + +fn extract_elem_ty(ty: Ty) -> Ty { + match ty.kind() { + TyKind::RigidTy(RigidTy::Adt(_, args)) => { + *args.0[0].expect_ty() + } + _ => unreachable!("Expected Vec ADT, but found: {ty:?}") + } +} + +/// Check signature and type of `Vec::::new` and its generic version. +fn test_vec_new(instance: mir::mono::Instance) { + let sig = instance.fn_sig(); + assert_matches!(sig.inputs(), &[]); + let elem_ty = extract_elem_ty(sig.output()); + assert_matches!(elem_ty.kind(), TyKind::RigidTy(RigidTy::Uint(UintTy::U8))); + + // Get the signature for Vec::::new. + let item = CrateItem::try_from(instance).unwrap(); + let ty = item.ty(); + let gen_sig = ty.kind().fn_sig().unwrap().skip_binder(); + let gen_ty = extract_elem_ty(gen_sig.output()); + assert_matches!(gen_ty.kind(), TyKind::Param(_)); +} + +/// Inspect the instance body +fn get_instances(body: mir::Body) -> Vec { + body.blocks.iter().filter_map(|bb| { + match &bb.terminator.kind { + Call { func, .. } => { + let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else { unreachable! + () }; + let RigidTy::FnDef(def, args) = ty else { unreachable!() }; + Instance::resolve(def, &args).ok() + } + _ => { + None + } + } + }).collect::>() +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "defs_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "-Cpanic=abort".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, tcx, test_stable_mir(tcx)).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + + fn main() {{ + let _c = core::char::from_u32(99); + let _v = Vec::::new(); + }} + "# + )?; + Ok(()) +} diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index a340877752d8f..5cb07eabf41d3 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -49,7 +49,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { assert!(generic.iter().all(|item| mir::mono::Instance::try_from(*item).is_err())); for instance in instances { - test_body(instance.body()) + test_body(instance.body().unwrap()) } ControlFlow::Continue(()) } @@ -59,10 +59,17 @@ fn test_body(body: mir::Body) { for term in body.blocks.iter().map(|bb| &bb.terminator) { match &term.kind { Call { func, .. } => { - let TyKind::RigidTy(ty) = func.ty(body.locals()).kind() else { unreachable!() }; + let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else { unreachable! + () }; let RigidTy::FnDef(def, args) = ty else { unreachable!() }; - let result = Instance::resolve(def, &args); - assert!(result.is_ok()); + let instance = Instance::resolve(def, &args).unwrap(); + let mangled_name = instance.mangled_name(); + assert!(instance.has_body() || (mangled_name == "setpwent"), "Failed: {func:?}"); + assert!(instance.has_body() ^ instance.is_foreign_item()); + if instance.has_body() { + let body = instance.body().unwrap(); + assert!(!body.locals().is_empty(), "Body must at least have a return local"); + } } Goto { .. } | Assert { .. } | SwitchInt { .. } | Return | Drop { .. } => { /* Do nothing */ @@ -105,10 +112,16 @@ fn generate_input(path: &str) -> std::io::Result<()> { LEN > 0 && a[0] }} + extern "C" {{ + // Body should not be available. + fn setpwent(); + }} + pub fn monomorphic() {{ let v = vec![10]; let dup = ty_param(&v); assert_eq!(v, dup); + unsafe {{ setpwent() }}; }} pub mod foo {{ diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs new file mode 100644 index 0000000000000..b90d47d4540ba --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -0,0 +1,115 @@ +// run-pass +//! Test that users are able to use stable mir APIs to retrieve monomorphized types, and that +//! we have an error handling for trying to instantiate types with incorrect arguments. + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use rustc_middle::ty::TyCtxt; +use rustc_smir::rustc_internal; +use stable_mir::ty::{RigidTy, TyKind, Ty, }; +use stable_mir::mir::{Body, MirVisitor, FieldIdx, Place, ProjectionElem, visit::{Location, + PlaceContext}}; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let main_fn = stable_mir::entry_fn(); + let body = main_fn.unwrap().body(); + let mut visitor = PlaceVisitor{ body: &body, tested: false}; + visitor.visit_body(&body); + assert!(visitor.tested); + ControlFlow::Continue(()) +} + +struct PlaceVisitor<'a> { + body: &'a Body, + /// Used to ensure that the test was reachable. Otherwise this test would vacuously succeed. + tested: bool, +} + +/// Check that `wrapper.inner` place projection can be correctly interpreted. +/// Ensure that instantiation is correct. +fn check_tys(local_ty: Ty, idx: FieldIdx, expected_ty: Ty) { + let TyKind::RigidTy(RigidTy::Adt(def, args)) = local_ty.kind() else { unreachable!() }; + assert_eq!(def.ty_with_args(&args), local_ty); + + let field_def = &def.variants_iter().next().unwrap().fields()[idx]; + let field_ty = field_def.ty_with_args(&args); + assert_eq!(field_ty, expected_ty); + + // Check that the generic version is different than the instantiated one. + let field_ty_gen = field_def.ty(); + assert_ne!(field_ty_gen, field_ty); +} + +impl<'a> MirVisitor for PlaceVisitor<'a> { + fn visit_place(&mut self, place: &Place, _ptx: PlaceContext, _loc: Location) { + let start_ty = self.body.locals()[place.local].ty; + match place.projection.as_slice() { + [ProjectionElem::Field(idx, ty)] => { + check_tys(start_ty, *idx, *ty); + self.tested = true; + } + _ => {} + } + } +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "ty_fold_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "-Cpanic=abort".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, tcx, test_stable_mir(tcx)).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + struct Wrapper {{ + pub inner: T + }} + + impl Wrapper {{ + pub fn new() -> Wrapper {{ + Wrapper {{ inner: T::default() }} + }} + }} + + fn main() {{ + let wrapper = Wrapper::::new(); + let _inner = wrapper.inner; + }} + "# + )?; + Ok(()) +} diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index ed6b786f5e1de..c2035430a33b8 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -22,6 +22,8 @@ extern crate stable_mir; use rustc_hir::def::DefKind; use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; +use stable_mir::ItemKind; +use stable_mir::crate_def::CrateDef; use stable_mir::mir::mono::Instance; use stable_mir::ty::{RigidTy, TyKind}; use std::assert_matches::assert_matches; @@ -120,13 +122,14 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let monomorphic = get_item(&items, (DefKind::Fn, "monomorphic")).unwrap(); let instance = Instance::try_from(monomorphic.clone()).unwrap(); - for block in instance.body().blocks { + for block in instance.body().unwrap().blocks { match &block.terminator.kind { stable_mir::mir::TerminatorKind::Call { func, .. } => { - let TyKind::RigidTy(ty) = func.ty(&body.locals()).kind() else { unreachable!() }; + let TyKind::RigidTy(ty) = func.ty(&body.locals()).unwrap().kind() else { + unreachable!() }; let RigidTy::FnDef(def, args) = ty else { unreachable!() }; let next_func = Instance::resolve(def, &args).unwrap(); - match next_func.body().locals()[1].ty.kind() { + match next_func.body().unwrap().locals()[1].ty.kind() { TyKind::RigidTy(RigidTy::Uint(_)) | TyKind::RigidTy(RigidTy::Tuple(_)) => {} other => panic!("{other:?}"), } @@ -172,7 +175,8 @@ fn get_item<'a>( item: (DefKind, &str), ) -> Option<&'a stable_mir::CrateItem> { items.iter().find(|crate_item| { - crate_item.kind().to_string() == format!("{:?}", item.0) && crate_item.name() == item.1 + matches!((item.0, crate_item.kind()), (DefKind::Fn, ItemKind::Fn) | (DefKind::Const, + ItemKind::Const)) && crate_item.name() == item.1 }) } diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs new file mode 100644 index 0000000000000..8c3fda7b6bb1f --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -0,0 +1,180 @@ +// run-pass +// Tests the Stable MIR projections API + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +extern crate rustc_hir; +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use rustc_middle::ty::TyCtxt; +use rustc_smir::rustc_internal; +use stable_mir::crate_def::CrateDef; +use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind}; +use stable_mir::ty::{RigidTy, TyKind, UintTy}; +use stable_mir::ItemKind; +use std::assert_matches::assert_matches; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +/// Tests projections within Place objects +fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let items = stable_mir::all_local_items(); + let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().body(); + assert_eq!(body.blocks.len(), 4); + // The first statement assigns `&s.c` to a local. The projections include a deref for `s`, since + // `s` is passed as a reference argument, and a field access for field `c`. + match &body.blocks[0].statements[0].kind { + StatementKind::Assign( + place @ stable_mir::mir::Place { local: _, projection: local_proj }, + Rvalue::Ref(_, _, stable_mir::mir::Place { local: _, projection: r_proj }), + ) => { + // We can't match on vecs, only on slices. Comparing statements for equality wouldn't be + // any easier since we'd then have to add in the expected local and region values + // instead of matching on wildcards. + assert!(local_proj.is_empty()); + match &r_proj[..] { + // Similarly we can't match against a type, only against its kind. + [ProjectionElem::Deref, ProjectionElem::Field(2, ty)] => { + assert_matches!( + ty.kind(), + TyKind::RigidTy(RigidTy::Uint(stable_mir::ty::UintTy::U8)) + ); + let ty = place.ty(body.locals()).unwrap(); + assert_matches!(ty.kind().rigid(), Some(RigidTy::Ref(..))); + }, + other => panic!( + "Unable to match against expected rvalue projection. Expected the projection \ + for `s.c`, which is a Deref and u8 Field. Got: {:?}", + other + ), + }; + } + other => panic!( + "Unable to match against expected Assign statement with a Ref rvalue. Expected the \ + statement to assign `&s.c` to a local. Got: {:?}", + other + ), + }; + // This statement assigns `slice[1]` to a local. The projections include a deref for `slice`, + // since `slice` is a reference, and an index. + match &body.blocks[2].statements[0].kind { + StatementKind::Assign( + place @ stable_mir::mir::Place { local: _, projection: local_proj }, + Rvalue::Use(stable_mir::mir::Operand::Copy(stable_mir::mir::Place { + local: _, + projection: r_proj, + })), + ) => { + // We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier + // since we'd then have to add in the expected local values instead of matching on + // wildcards. + assert!(local_proj.is_empty()); + assert_matches!(r_proj[..], [ProjectionElem::Deref, ProjectionElem::Index(_)]); + let ty = place.ty(body.locals()).unwrap(); + assert_matches!(ty.kind().rigid(), Some(RigidTy::Uint(UintTy::U8))); + } + other => panic!( + "Unable to match against expected Assign statement with a Use rvalue. Expected the \ + statement to assign `slice[1]` to a local. Got: {:?}", + other + ), + }; + // The first terminator gets a slice of an array via the Index operation. Specifically it + // performs `&vals[1..3]`. There are no projections in this case, the arguments are just locals. + match &body.blocks[0].terminator.kind { + stable_mir::mir::TerminatorKind::Call { args, .. } => + // We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier + // since we'd then have to add in the expected local values instead of matching on + // wildcards. + { + match &args[..] { + [ + stable_mir::mir::Operand::Move(stable_mir::mir::Place { + local: _, + projection: arg1_proj, + }), + stable_mir::mir::Operand::Move(stable_mir::mir::Place { + local: _, + projection: arg2_proj, + }), + ] => { + assert!(arg1_proj.is_empty()); + assert!(arg2_proj.is_empty()); + } + other => { + panic!( + "Unable to match against expected arguments to Index call. Expected two \ + move operands. Got: {:?}", + other + ) + } + } + } + other => panic!( + "Unable to match against expected Call terminator. Expected a terminator that calls \ + the Index operation. Got: {:?}", + other + ), + }; + + ControlFlow::Continue(()) +} + +// Use internal API to find a function in a crate. +fn get_item<'a>( + items: &'a stable_mir::CrateItems, + item: (ItemKind, &str), +) -> Option<&'a stable_mir::CrateItem> { + items.iter().find(|crate_item| { + crate_item.kind() == item.0 && crate_item.name() == item.1 + }) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, tcx, test_place_projections(tcx)).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + pub struct Struct1 {{ _a: u8, _b: u16, c: u8 }} + + pub fn projections(s: &Struct1) -> u8 {{ + let v = &s.c; + let vals = [1, 2, 3, 4]; + let slice = &vals[1..3]; + v + slice[1] + }}"# + )?; + Ok(()) +} diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index de5148bb5f420..027b0e7d9e85c 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -40,7 +40,7 @@ fn test_visitor(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let exit_fn = main_visitor.calls.last().unwrap(); assert!(exit_fn.mangled_name().contains("exit_fn"), "Unexpected last function: {exit_fn:?}"); - let exit_body = exit_fn.body(); + let exit_body = exit_fn.body().unwrap(); let exit_visitor = TestVisitor::collect(&exit_body); assert!(exit_visitor.ret_val.is_some()); assert_eq!(exit_visitor.args.len(), 1); @@ -92,7 +92,8 @@ impl<'a> mir::MirVisitor for TestVisitor<'a> { fn visit_terminator(&mut self, term: &mir::Terminator, location: mir::visit::Location) { if let mir::TerminatorKind::Call { func, .. } = &term.kind { - let ty::TyKind::RigidTy(ty) = func.ty(self.body.locals()).kind() else { unreachable! + let ty::TyKind::RigidTy(ty) = func.ty(self.body.locals()).unwrap().kind() else { + unreachable! () }; let ty::RigidTy::FnDef(def, args) = ty else { unreachable!() }; self.calls.push(mir::mono::Instance::resolve(def, &args).unwrap()); diff --git a/tests/ui/abi/abi-typo-unstable.stderr b/tests/ui/abi/abi-typo-unstable.stderr index 3b346e00227a3..d31cc2a896f72 100644 --- a/tests/ui/abi/abi-typo-unstable.stderr +++ b/tests/ui/abi/abi-typo-unstable.stderr @@ -6,6 +6,6 @@ LL | extern "rust-intrinsec" fn rust_intrinsic() {} | = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/abi/arm-unadjusted-intrinsic.rs b/tests/ui/abi/arm-unadjusted-intrinsic.rs new file mode 100644 index 0000000000000..33ea792752630 --- /dev/null +++ b/tests/ui/abi/arm-unadjusted-intrinsic.rs @@ -0,0 +1,54 @@ +// build-pass +// revisions: arm +//[arm] compile-flags: --target arm-unknown-linux-gnueabi +//[arm] needs-llvm-components: arm +// revisions: aarch64 +//[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//[aarch64] needs-llvm-components: aarch64 +#![feature( + no_core, lang_items, link_llvm_intrinsics, + abi_unadjusted, repr_simd, arm_target_feature, +)] +#![no_std] +#![no_core] +#![crate_type = "lib"] +#![allow(non_camel_case_types)] + +/// To work cross-target this test must be no_core. +/// This little prelude supplies what we need. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +pub trait Copy: Sized {} +impl Copy for i8 {} +impl Copy for *const T {} +impl Copy for *mut T {} + + +// Regression test for https://github.com/rust-lang/rust/issues/118124. + +#[repr(simd)] +pub struct int8x16_t( + pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, + pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, + pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, + pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, +); +impl Copy for int8x16_t {} + +#[repr(C)] +pub struct int8x16x4_t(pub int8x16_t, pub int8x16_t, pub int8x16_t, pub int8x16_t); +impl Copy for int8x16x4_t {} + +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v16i8.p0i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v16i8.p0i8")] + fn vld1q_s8_x4_(a: *const i8) -> int8x16x4_t; + } + vld1q_s8_x4_(a) +} diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 0cdf229711ad0..d5f0531307838 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -1,5 +1,14 @@ // check-pass // revisions: host +// revisions: i686 +//[i686] compile-flags: --target i686-unknown-linux-gnu +//[i686] needs-llvm-components: x86 +// revisions: x86-64 +//[x86-64] compile-flags: --target x86_64-unknown-linux-gnu +//[x86-64] needs-llvm-components: x86 +// revisions: x86-64-win +//[x86-64-win] compile-flags: --target x86_64-pc-windows-msvc +//[x86-64-win] needs-llvm-components: x86 // revisions: arm //[arm] compile-flags: --target arm-unknown-linux-gnueabi //[arm] needs-llvm-components: arm @@ -37,9 +46,23 @@ // revisions: wasi //[wasi] compile-flags: --target wasm32-wasi //[wasi] needs-llvm-components: webassembly -// revisions: nvptx64 -//[nvptx64] compile-flags: --target nvptx64-nvidia-cuda -//[nvptx64] needs-llvm-components: nvptx +// revisions: bpf +//[bpf] compile-flags: --target bpfeb-unknown-none +//[bpf] needs-llvm-components: bpf +// revisions: m68k +//[m68k] compile-flags: --target m68k-unknown-linux-gnu +//[m68k] needs-llvm-components: m68k +// FIXME: disabled on nvptx64 since the target ABI fails the sanity check +// see https://github.com/rust-lang/rust/issues/117480 +/* revisions: nvptx64 + [nvptx64] compile-flags: --target nvptx64-nvidia-cuda + [nvptx64] needs-llvm-components: nvptx +*/ +// FIXME: disabled since it fails on CI saying the csky component is missing +/* revisions: csky + [csky] compile-flags: --target csky-unknown-linux-gnuabiv2 + [csky] needs-llvm-components: csky +*/ #![feature(rustc_attrs, unsized_fn_params, transparent_unions)] #![cfg_attr(not(host), feature(no_core, lang_items), no_std, no_core)] #![allow(unused, improper_ctypes_definitions, internal_features)] @@ -231,8 +254,7 @@ macro_rules! test_abi_compatible { }; } -// Compatibility of pointers is probably de-facto guaranteed, -// but that does not seem to be documented. +// Compatibility of pointers. test_abi_compatible!(ptr_mut, *const i32, *mut i32); test_abi_compatible!(ptr_pointee, *const i32, *const Vec); test_abi_compatible!(ref_mut, &i32, &mut i32); @@ -241,14 +263,15 @@ test_abi_compatible!(box_ptr, Box, *const i32); test_abi_compatible!(nonnull_ptr, NonNull, *const i32); test_abi_compatible!(fn_fn, fn(), fn(i32) -> i32); -// Some further guarantees we will likely (have to) make. +// Compatibility of 1-ZST. test_abi_compatible!(zst_unit, Zst, ()); #[cfg(not(any(target_arch = "sparc64")))] test_abi_compatible!(zst_array, Zst, [u8; 0]); test_abi_compatible!(nonzero_int, NonZeroI32, i32); // `DispatchFromDyn` relies on ABI compatibility. -// This is interesting since these types are not `repr(transparent)`. +// This is interesting since these types are not `repr(transparent)`. So this is not part of our +// public ABI guarantees, but is relied on by the compiler. test_abi_compatible!(rc, Rc, *mut i32); test_abi_compatible!(arc, Arc, *mut i32); @@ -324,6 +347,7 @@ mod unsized_ { use super::*; test_transparent_unsized!(str_, str); test_transparent_unsized!(slice, [u8]); + test_transparent_unsized!(slice_with_prefix, (usize, [u8])); test_transparent_unsized!(dyn_trait, dyn Any); } diff --git a/tests/ui/abi/issue-94223.rs b/tests/ui/abi/issue-94223.rs deleted file mode 100644 index 79d6b94031bc2..0000000000000 --- a/tests/ui/abi/issue-94223.rs +++ /dev/null @@ -1,8 +0,0 @@ -// check-pass -#![allow(improper_ctypes_definitions)] -#![crate_type = "lib"] - -// Check that computing the fn abi for `bad`, with a external ABI fn ptr that is not FFI-safe, does -// not ICE. - -pub fn bad(f: extern "C" fn([u8])) {} diff --git a/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs b/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs new file mode 100644 index 0000000000000..a32cc6500f829 --- /dev/null +++ b/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs @@ -0,0 +1,30 @@ +// check-pass +#![allow(improper_ctypes_definitions)] +#![feature(unsized_tuple_coercion)] +#![feature(unsized_fn_params)] +#![crate_type = "lib"] + +// Check that computing the fn abi for `bad`, with a external ABI fn ptr that is not FFI-safe, does +// not ICE. + +pub fn bad(f: extern "C" fn([u8])) {} + +// While these get accepted, they should also not ICE. +// (If we ever reject them, remove them from this test to ensure the `bad` above +// is still tested. Do *not* make this a check/build-fail test.) + +pub extern "C" fn declare_bad(_x: str) {} + +#[no_mangle] +pub extern "system" fn declare_more_bad(f: dyn FnOnce()) { +} + +fn make_bad() -> extern "C" fn(([u8],)) { + todo!() +} + +pub fn call_bad() { + let f = make_bad(); + let slice: Box<([u8],)> = Box::new(([1; 8],)); + f(*slice); +} diff --git a/tests/ui/abi/variadic-ffi.rs b/tests/ui/abi/variadic-ffi.rs index a952ea0779329..1862177005f93 100644 --- a/tests/ui/abi/variadic-ffi.rs +++ b/tests/ui/abi/variadic-ffi.rs @@ -8,11 +8,6 @@ use std::ffi::VaList; extern "C" { fn rust_interesting_average(_: u64, ...) -> f64; - // FIXME: we need to disable this lint for `VaList`, - // since it contains a `MaybeUninit` on the asmjs target, - // and this type isn't FFI-safe. This is OK for now, - // since the type is layout-compatible with `i32`. - #[cfg_attr(target_arch = "asmjs", allow(improper_ctypes))] fn rust_valist_interesting_average(_: u64, _: VaList) -> f64; } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr index eb739b149a103..3be219bdb0646 100644 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr @@ -16,6 +16,6 @@ LL | fn oom() -> ! { | ^^^ = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/allocator/allocator-args.stderr b/tests/ui/allocator/allocator-args.stderr index dfff2a7e7094d..ad640767fee10 100644 --- a/tests/ui/allocator/allocator-args.stderr +++ b/tests/ui/allocator/allocator-args.stderr @@ -4,5 +4,5 @@ error: malformed `global_allocator` attribute input LL | #[global_allocator(malloc)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[global_allocator]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/allocator/function-allocator.stderr b/tests/ui/allocator/function-allocator.stderr index 5e47b0f0cc7ac..3c0ba9580f7af 100644 --- a/tests/ui/allocator/function-allocator.stderr +++ b/tests/ui/allocator/function-allocator.stderr @@ -4,5 +4,5 @@ error: allocators must be statics LL | fn foo() {} | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/allocator/two-allocators.stderr b/tests/ui/allocator/two-allocators.stderr index 7a914c2a3907c..1eecbc0a97b1f 100644 --- a/tests/ui/allocator/two-allocators.stderr +++ b/tests/ui/allocator/two-allocators.stderr @@ -10,5 +10,5 @@ LL | static B: System = System; | = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/allocator/two-allocators2.stderr b/tests/ui/allocator/two-allocators2.stderr index b1fb4421ea048..f1e4b093cc6db 100644 --- a/tests/ui/allocator/two-allocators2.stderr +++ b/tests/ui/allocator/two-allocators2.stderr @@ -1,4 +1,4 @@ error: the `#[global_allocator]` in this crate conflicts with global allocator in: system_allocator -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/allocator/two-allocators3.stderr b/tests/ui/allocator/two-allocators3.stderr index a3079113d01cf..bf0f3a7c637a8 100644 --- a/tests/ui/allocator/two-allocators3.stderr +++ b/tests/ui/allocator/two-allocators3.stderr @@ -1,4 +1,4 @@ error: the `#[global_allocator]` in system_allocator conflicts with global allocator in: system_allocator2 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/argument-suggestions/complex.stderr b/tests/ui/argument-suggestions/complex.stderr index 205a852983a3b..bb3817421df19 100644 --- a/tests/ui/argument-suggestions/complex.stderr +++ b/tests/ui/argument-suggestions/complex.stderr @@ -14,6 +14,6 @@ help: did you mean LL | complex(/* u32 */, &"", /* E */, F::X2, G{}, X {}, Y {}, Z {}); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/argument-suggestions/display-is-suggestable.stderr b/tests/ui/argument-suggestions/display-is-suggestable.stderr index edd72b53eb3b6..bde87475e0a65 100644 --- a/tests/ui/argument-suggestions/display-is-suggestable.stderr +++ b/tests/ui/argument-suggestions/display-is-suggestable.stderr @@ -14,6 +14,6 @@ help: provide the argument LL | foo(/* &dyn std::fmt::Display + Send */); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-112507.stderr b/tests/ui/argument-suggestions/issue-112507.stderr index dfb47e010e49f..17bde4d974338 100644 --- a/tests/ui/argument-suggestions/issue-112507.stderr +++ b/tests/ui/argument-suggestions/issue-112507.stderr @@ -22,6 +22,6 @@ LL ~ , LL ~ None); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-96638.stderr b/tests/ui/argument-suggestions/issue-96638.stderr index 4d18b97c98be1..887bf82a2f6f3 100644 --- a/tests/ui/argument-suggestions/issue-96638.stderr +++ b/tests/ui/argument-suggestions/issue-96638.stderr @@ -16,6 +16,6 @@ help: provide the argument LL | f(/* usize */, &x, /* usize */); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-97197.stderr b/tests/ui/argument-suggestions/issue-97197.stderr index de221ba1fe180..3768367a5e61a 100644 --- a/tests/ui/argument-suggestions/issue-97197.stderr +++ b/tests/ui/argument-suggestions/issue-97197.stderr @@ -14,6 +14,6 @@ help: provide the arguments LL | g((), /* bool */, /* bool */, /* bool */, /* bool */, ()); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-97484.stderr b/tests/ui/argument-suggestions/issue-97484.stderr index 082564fbc7f88..6bdb734fddfa3 100644 --- a/tests/ui/argument-suggestions/issue-97484.stderr +++ b/tests/ui/argument-suggestions/issue-97484.stderr @@ -23,6 +23,6 @@ LL - foo(&&A, B, C, D, E, F, G); LL + foo(&&A, D, /* &E */, G); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-98894.stderr b/tests/ui/argument-suggestions/issue-98894.stderr index f64a83ab71067..72e6fec27e62b 100644 --- a/tests/ui/argument-suggestions/issue-98894.stderr +++ b/tests/ui/argument-suggestions/issue-98894.stderr @@ -14,6 +14,6 @@ help: provide the argument LL | (|_, ()| ())(if true {} else {return;}, ()); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/argument-suggestions/issue-98897.stderr b/tests/ui/argument-suggestions/issue-98897.stderr index f2c47d353efad..eed3964559ab1 100644 --- a/tests/ui/argument-suggestions/issue-98897.stderr +++ b/tests/ui/argument-suggestions/issue-98897.stderr @@ -14,6 +14,6 @@ help: provide the argument LL | (|_, ()| ())([return, ()], ()); | ~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/argument-suggestions/issue-99482.stderr b/tests/ui/argument-suggestions/issue-99482.stderr index bcf36e37cdccf..9c83b47f8b64a 100644 --- a/tests/ui/argument-suggestions/issue-99482.stderr +++ b/tests/ui/argument-suggestions/issue-99482.stderr @@ -14,6 +14,6 @@ help: provide the argument LL | let _f = f((), main); | ~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/argument-suggestions/too-long.stderr b/tests/ui/argument-suggestions/too-long.stderr index bb6f06a35c6c5..04ee9275cb363 100644 --- a/tests/ui/argument-suggestions/too-long.stderr +++ b/tests/ui/argument-suggestions/too-long.stderr @@ -19,6 +19,6 @@ help: consider dereferencing the borrow LL | qux.foo(a, b, c, d, e, *f, g, h, i, j, k, l); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/argument-suggestions/two-mismatch-notes.stderr b/tests/ui/argument-suggestions/two-mismatch-notes.stderr index 70cc60255c717..65b3d285100d0 100644 --- a/tests/ui/argument-suggestions/two-mismatch-notes.stderr +++ b/tests/ui/argument-suggestions/two-mismatch-notes.stderr @@ -24,6 +24,6 @@ note: function defined here LL | fn foo(_: fn(i32), _: Wrapper) {} | ^^^ ---------- --------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/array_const_index-0.stderr b/tests/ui/array-slice-vec/array_const_index-0.stderr index 3b92cc76687b4..d16e8d50dfdd5 100644 --- a/tests/ui/array-slice-vec/array_const_index-0.stderr +++ b/tests/ui/array-slice-vec/array_const_index-0.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const B: i32 = (&A)[1]; | ^^^^^^^ index out of bounds: the length is 0 but the index is 1 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/array-slice-vec/array_const_index-1.stderr b/tests/ui/array-slice-vec/array_const_index-1.stderr index 591db268a9943..f9ba2f13911bd 100644 --- a/tests/ui/array-slice-vec/array_const_index-1.stderr +++ b/tests/ui/array-slice-vec/array_const_index-1.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const B: i32 = A[1]; | ^^^^ index out of bounds: the length is 0 but the index is 1 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/array-slice-vec/match_arr_unknown_len.stderr b/tests/ui/array-slice-vec/match_arr_unknown_len.stderr index 5e531a993c62c..3ed0d6bdf3ac9 100644 --- a/tests/ui/array-slice-vec/match_arr_unknown_len.stderr +++ b/tests/ui/array-slice-vec/match_arr_unknown_len.stderr @@ -7,6 +7,6 @@ LL | [1, 2] => true, = note: expected array `[u32; 2]` found array `[u32; N]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/slice-mut-2.stderr b/tests/ui/array-slice-vec/slice-mut-2.stderr index c33919c41cdc2..8cc2c6e03974c 100644 --- a/tests/ui/array-slice-vec/slice-mut-2.stderr +++ b/tests/ui/array-slice-vec/slice-mut-2.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | let x: &[isize] = &mut [1, 2, 3, 4, 5]; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/array-slice-vec/slice-mut.stderr b/tests/ui/array-slice-vec/slice-mut.stderr index 7d34defc1d577..288031e505cf1 100644 --- a/tests/ui/array-slice-vec/slice-mut.stderr +++ b/tests/ui/array-slice-vec/slice-mut.stderr @@ -9,6 +9,6 @@ LL | let y: &mut[_] = &x[2..4]; = note: expected mutable reference `&mut [_]` found reference `&[isize]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr b/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr index 47008e1d99946..7e5b8afea24b1 100644 --- a/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr +++ b/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr @@ -7,6 +7,6 @@ LL | a > b; = note: expected reference `&[_; 0]` found reference `&Vec` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr b/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr index ec4a001f4d01a..b3f953af6d278 100644 --- a/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr +++ b/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr @@ -6,5 +6,5 @@ LL | vec![,]; | = note: while trying to match end of macro -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/array-slice-vec/vec-mut-iter-borrow.stderr b/tests/ui/array-slice-vec/vec-mut-iter-borrow.stderr index 679fd8997733b..d9343140fb1dc 100644 --- a/tests/ui/array-slice-vec/vec-mut-iter-borrow.stderr +++ b/tests/ui/array-slice-vec/vec-mut-iter-borrow.stderr @@ -9,6 +9,6 @@ LL | for x in &mut xs { LL | xs.push(1) | ^^ second mutable borrow occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/array-slice-vec/vec-res-add.stderr b/tests/ui/array-slice-vec/vec-res-add.stderr index 7511271361de6..cf5796f7e4a4a 100644 --- a/tests/ui/array-slice-vec/vec-res-add.stderr +++ b/tests/ui/array-slice-vec/vec-res-add.stderr @@ -6,6 +6,6 @@ LL | let k = i + j; | | | Vec -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/array-slice-vec/vector-no-ann.stderr b/tests/ui/array-slice-vec/vector-no-ann.stderr index 619417a73c9ee..24b6abfb34260 100644 --- a/tests/ui/array-slice-vec/vector-no-ann.stderr +++ b/tests/ui/array-slice-vec/vector-no-ann.stderr @@ -9,6 +9,6 @@ help: consider giving `_foo` an explicit type, where the type for type parameter LL | let _foo: Vec = Vec::new(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/asm/aarch64/bad-reg.rs b/tests/ui/asm/aarch64/bad-reg.rs index 9ccb8ed676269..f71418161f297 100644 --- a/tests/ui/asm/aarch64/bad-reg.rs +++ b/tests/ui/asm/aarch64/bad-reg.rs @@ -48,14 +48,14 @@ fn main() { // (except in/lateout which don't conflict) asm!("", in("x0") foo, in("w0") bar); - //~^ ERROR register `x0` conflicts with register `x0` + //~^ ERROR register `w0` conflicts with register `x0` asm!("", in("x0") foo, out("x0") bar); //~^ ERROR register `x0` conflicts with register `x0` asm!("", in("w0") foo, lateout("w0") bar); asm!("", in("v0") foo, in("q0") bar); - //~^ ERROR register `v0` conflicts with register `v0` + //~^ ERROR register `q0` conflicts with register `v0` asm!("", in("v0") foo, out("q0") bar); - //~^ ERROR register `v0` conflicts with register `v0` + //~^ ERROR register `q0` conflicts with register `v0` asm!("", in("v0") foo, lateout("q0") bar); } } diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr index 0ba627dac309f..717a788caf67d 100644 --- a/tests/ui/asm/aarch64/bad-reg.stderr +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -98,11 +98,11 @@ error: register class `preg` can only be used as a clobber, not as an input or o LL | asm!("{}", out(preg) _); | ^^^^^^^^^^^ -error: register `x0` conflicts with register `x0` +error: register `w0` conflicts with register `x0` --> $DIR/bad-reg.rs:50:32 | LL | asm!("", in("x0") foo, in("w0") bar); - | ------------ ^^^^^^^^^^^^ register `x0` + | ------------ ^^^^^^^^^^^^ register `w0` | | | register `x0` @@ -120,19 +120,19 @@ help: use `lateout` instead of `out` to avoid conflict LL | asm!("", in("x0") foo, out("x0") bar); | ^^^^^^^^^^^^ -error: register `v0` conflicts with register `v0` +error: register `q0` conflicts with register `v0` --> $DIR/bad-reg.rs:55:32 | LL | asm!("", in("v0") foo, in("q0") bar); - | ------------ ^^^^^^^^^^^^ register `v0` + | ------------ ^^^^^^^^^^^^ register `q0` | | | register `v0` -error: register `v0` conflicts with register `v0` +error: register `q0` conflicts with register `v0` --> $DIR/bad-reg.rs:57:32 | LL | asm!("", in("v0") foo, out("q0") bar); - | ------------ ^^^^^^^^^^^^^ register `v0` + | ------------ ^^^^^^^^^^^^^ register `q0` | | | register `v0` | diff --git a/tests/ui/asm/const-error.rs b/tests/ui/asm/const-error.rs new file mode 100644 index 0000000000000..4e14becf74bef --- /dev/null +++ b/tests/ui/asm/const-error.rs @@ -0,0 +1,15 @@ +// only-x86_64 +// needs-asm-support + +#![feature(asm_const)] + +// Test to make sure that we emit const errors eagerly for inline asm + +use std::arch::asm; + +fn test() { + unsafe { asm!("/* {} */", const 1 / 0); } + //~^ ERROR evaluation of +} + +fn main() {} diff --git a/tests/ui/asm/const-error.stderr b/tests/ui/asm/const-error.stderr new file mode 100644 index 0000000000000..fe31183217726 --- /dev/null +++ b/tests/ui/asm/const-error.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of `test::::{constant#0}` failed + --> $DIR/const-error.rs:11:37 + | +LL | unsafe { asm!("/* {} */", const 1 / 0); } + | ^^^^^ attempt to divide `1_i32` by zero + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/asm/issue-113788.stderr b/tests/ui/asm/issue-113788.stderr index f8e65b6f53817..c44ba3c91d91a 100644 --- a/tests/ui/asm/issue-113788.stderr +++ b/tests/ui/asm/issue-113788.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `PEB` in this scope LL | let peb: *const PEB; | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/asm/issue-72570.stderr b/tests/ui/asm/issue-72570.stderr index 49013a23ced2d..13f39e7def968 100644 --- a/tests/ui/asm/issue-72570.stderr +++ b/tests/ui/asm/issue-72570.stderr @@ -4,5 +4,5 @@ error: invalid register `invalid`: unknown register LL | asm!("", in("invalid") "".len()); | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/asm/issue-85247.rwpi.stderr b/tests/ui/asm/issue-85247.rwpi.stderr index 996b0933a3412..8466a53be299e 100644 --- a/tests/ui/asm/issue-85247.rwpi.stderr +++ b/tests/ui/asm/issue-85247.rwpi.stderr @@ -4,5 +4,5 @@ error: cannot use register `r9`: the RWPI static base register (r9) cannot be us LL | asm!("", out("r9") _); | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/asm/issue-87802.stderr b/tests/ui/asm/issue-87802.stderr index de3e28fdd1228..762f3d02a41af 100644 --- a/tests/ui/asm/issue-87802.stderr +++ b/tests/ui/asm/issue-87802.stderr @@ -6,5 +6,5 @@ LL | asm!("/* {0} */", out(reg) x); | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/asm/issue-99071.stderr b/tests/ui/asm/issue-99071.stderr index 47386ffa4a8c9..1703d2977a723 100644 --- a/tests/ui/asm/issue-99071.stderr +++ b/tests/ui/asm/issue-99071.stderr @@ -4,5 +4,5 @@ error: cannot use register `r8`: high registers (r8+) can only be used as clobbe LL | asm!("", in("r8") 0); | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/asm/issue-99122.stderr b/tests/ui/asm/issue-99122.stderr index 2758a4ac4377e..2767a6d54ed7e 100644 --- a/tests/ui/asm/issue-99122.stderr +++ b/tests/ui/asm/issue-99122.stderr @@ -6,6 +6,6 @@ LL | let pointer = 1u32 as *const _; | = note: the type information given here is insufficient to check whether the pointer cast is valid -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0641`. diff --git a/tests/ui/asm/reg-conflict.stderr b/tests/ui/asm/reg-conflict.stderr index 2395566de3945..a4dd8e0a95984 100644 --- a/tests/ui/asm/reg-conflict.stderr +++ b/tests/ui/asm/reg-conflict.stderr @@ -6,5 +6,5 @@ LL | asm!("", out("d0") _, out("s1") _); | | | register `d0` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/asm/x86_64/bad-reg.rs b/tests/ui/asm/x86_64/bad-reg.rs index f5728079a6a56..e19221bc04e5f 100644 --- a/tests/ui/asm/x86_64/bad-reg.rs +++ b/tests/ui/asm/x86_64/bad-reg.rs @@ -56,10 +56,10 @@ fn main() { // (except in/lateout which don't conflict) asm!("", in("eax") foo, in("al") bar); - //~^ ERROR register `al` conflicts with register `ax` + //~^ ERROR register `al` conflicts with register `eax` //~| ERROR `i32` cannot be used with this register class asm!("", in("rax") foo, out("rax") bar); - //~^ ERROR register `ax` conflicts with register `ax` + //~^ ERROR register `rax` conflicts with register `rax` asm!("", in("al") foo, lateout("al") bar); //~^ ERROR `i32` cannot be used with this register class //~| ERROR `i32` cannot be used with this register class diff --git a/tests/ui/asm/x86_64/bad-reg.stderr b/tests/ui/asm/x86_64/bad-reg.stderr index 82b7ebd0fb07a..8017008e97d75 100644 --- a/tests/ui/asm/x86_64/bad-reg.stderr +++ b/tests/ui/asm/x86_64/bad-reg.stderr @@ -106,21 +106,21 @@ error: register class `mmx_reg` can only be used as a clobber, not as an input o LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ -error: register `al` conflicts with register `ax` +error: register `al` conflicts with register `eax` --> $DIR/bad-reg.rs:58:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` | | - | register `ax` + | register `eax` -error: register `ax` conflicts with register `ax` +error: register `rax` conflicts with register `rax` --> $DIR/bad-reg.rs:61:33 | LL | asm!("", in("rax") foo, out("rax") bar); - | ------------- ^^^^^^^^^^^^^^ register `ax` + | ------------- ^^^^^^^^^^^^^^ register `rax` | | - | register `ax` + | register `rax` | help: use `lateout` instead of `out` to avoid conflict --> $DIR/bad-reg.rs:61:18 diff --git a/tests/ui/assign-imm-local-twice.stderr b/tests/ui/assign-imm-local-twice.stderr index bba5d8dffe4bd..d92485de68fe7 100644 --- a/tests/ui/assign-imm-local-twice.stderr +++ b/tests/ui/assign-imm-local-twice.stderr @@ -10,6 +10,6 @@ LL | println!("v={}", v); LL | v = 2; | ^^^^^ cannot assign twice to immutable variable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs new file mode 100644 index 0000000000000..ac085864ff09f --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs @@ -0,0 +1,19 @@ +// We used to say "ambiguous associated type" on ambiguous associated consts. +// Ensure that we now use the correct label. + +#![feature(associated_const_equality)] + +trait Trait0: Parent0 + Parent0 {} +trait Parent0 { const K: (); } + +fn take0(_: impl Trait0) {} +//~^ ERROR ambiguous associated constant `K` in bounds of `Trait0` + +trait Trait1: Parent1 + Parent2 {} +trait Parent1 { const C: i32; } +trait Parent2 { const C: &'static str; } + +fn take1(_: impl Trait1) {} +//~^ ERROR ambiguous associated constant `C` in bounds of `Trait1` + +fn main() {} diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr new file mode 100644 index 0000000000000..ba3a870131606 --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr @@ -0,0 +1,38 @@ +error[E0222]: ambiguous associated constant `K` in bounds of `Trait0` + --> $DIR/assoc-const-eq-ambiguity.rs:9:25 + | +LL | trait Parent0 { const K: (); } + | ----------- + | | + | ambiguous `K` from `Parent0` + | ambiguous `K` from `Parent0` +LL | +LL | fn take0(_: impl Trait0) {} + | ^^^^^^^^^^ ambiguous associated constant `K` + | + = help: consider introducing a new type parameter `T` and adding `where` constraints: + where + T: Trait0, + T: Parent0::K = { () }, + T: Parent0::K = { () } + +error[E0222]: ambiguous associated constant `C` in bounds of `Trait1` + --> $DIR/assoc-const-eq-ambiguity.rs:16:25 + | +LL | trait Parent1 { const C: i32; } + | ------------ ambiguous `C` from `Parent1` +LL | trait Parent2 { const C: &'static str; } + | --------------------- ambiguous `C` from `Parent2` +LL | +LL | fn take1(_: impl Trait1) {} + | ^^^^^^^ ambiguous associated constant `C` + | + = help: consider introducing a new type parameter `T` and adding `where` constraints: + where + T: Trait1, + T: Parent2::C = "?", + T: Parent1::C = "?" + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0222`. diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.rs b/tests/ui/associated-consts/assoc-const-eq-missing.rs index 5e029a12df26f..f384927e4a34f 100644 --- a/tests/ui/associated-consts/assoc-const-eq-missing.rs +++ b/tests/ui/associated-consts/assoc-const-eq-missing.rs @@ -11,13 +11,12 @@ impl Foo for Bar { const N: usize = 3; } - -fn foo1>() {} -//~^ ERROR associated type -fn foo2>() {} -//~^ ERROR associated type -fn foo3>() {} -//~^ ERROR associated type +fn foo1>() {} +//~^ ERROR associated constant `Z` not found for `Foo` +fn foo2>() {} +//~^ ERROR associated type `Z` not found for `Foo` +fn foo3>() {} +//~^ ERROR associated constant `Z` not found for `Foo` fn main() { foo1::(); diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.stderr b/tests/ui/associated-consts/assoc-const-eq-missing.stderr index b4bd6456c8517..318c85dcfd6fd 100644 --- a/tests/ui/associated-consts/assoc-const-eq-missing.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-missing.stderr @@ -1,20 +1,20 @@ -error[E0220]: associated type `Z` not found for `Foo` - --> $DIR/assoc-const-eq-missing.rs:15:16 +error[E0220]: associated constant `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:14:16 | -LL | fn foo1>() {} - | ^ associated type `Z` not found +LL | fn foo1>() {} + | ^ help: there is an associated constant with a similar name: `N` error[E0220]: associated type `Z` not found for `Foo` - --> $DIR/assoc-const-eq-missing.rs:17:16 + --> $DIR/assoc-const-eq-missing.rs:16:16 | -LL | fn foo2>() {} +LL | fn foo2>() {} | ^ associated type `Z` not found -error[E0220]: associated type `Z` not found for `Foo` - --> $DIR/assoc-const-eq-missing.rs:19:16 +error[E0220]: associated constant `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:18:16 | -LL | fn foo3>() {} - | ^ associated type `Z` not found +LL | fn foo3>() {} + | ^ help: there is an associated constant with a similar name: `N` error: aborting due to 3 previous errors diff --git a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs new file mode 100644 index 0000000000000..de9008bfcf9ec --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs @@ -0,0 +1,21 @@ +// Regression test for issue #112560. +// Respect the fact that (associated) types and constants live in different namespaces and +// therefore equality bounds involving identically named associated items don't conflict if +// their kind (type vs. const) differs. + +// FIXME(fmease): Extend this test to cover supertraits again +// once #118040 is fixed. See initial version of PR #118360. + +// check-pass + +#![feature(associated_const_equality)] + +trait Trait { + type N; + + const N: usize; +} + +fn take(_: impl Trait) {} + +fn main() {} diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.rs b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs index c5d78469e955e..7211637659bd3 100644 --- a/tests/ui/associated-consts/assoc-const-ty-mismatch.rs +++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs @@ -2,30 +2,30 @@ #![allow(unused)] pub trait Foo { - const N: usize; + const N: usize; } pub trait FooTy { - type T; + type T; } pub struct Bar; impl Foo for Bar { - const N: usize = 3; + const N: usize = 3; } impl FooTy for Bar { - type T = usize; + type T = usize; } -fn foo>() {} -//~^ ERROR expected associated constant bound, found type -fn foo2>() {} -//~^ ERROR expected associated type bound, found constant +fn foo>() {} +//~^ ERROR expected constant, found type +fn foo2>() {} +//~^ ERROR expected type, found constant fn main() { - foo::(); - foo2::(); + foo::(); + foo2::(); } diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr index 11198729e38cb..b844cfc4ae486 100644 --- a/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr +++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr @@ -1,26 +1,30 @@ -error: expected associated constant bound, found type - --> $DIR/assoc-const-ty-mismatch.rs:23:15 +error: expected constant, found type + --> $DIR/assoc-const-ty-mismatch.rs:23:19 | -LL | fn foo>() {} - | ^^^^^^^ +LL | fn foo>() {} + | - ^^^^^ unexpected type + | | + | expected a constant because of this associated constant | -note: associated constant defined here - --> $DIR/assoc-const-ty-mismatch.rs:5:3 +note: the associated constant is defined here + --> $DIR/assoc-const-ty-mismatch.rs:5:5 | -LL | const N: usize; - | ^^^^^^^^^^^^^^ +LL | const N: usize; + | ^^^^^^^^^^^^^^ -error: expected associated type bound, found constant - --> $DIR/assoc-const-ty-mismatch.rs:25:18 +error: expected type, found constant + --> $DIR/assoc-const-ty-mismatch.rs:25:22 | -LL | fn foo2>() {} - | ^^^^^^^^ +LL | fn foo2>() {} + | - ^^^^^^ unexpected constant + | | + | expected a type because of this associated type | -note: associated type defined here - --> $DIR/assoc-const-ty-mismatch.rs:9:3 +note: the associated type is defined here + --> $DIR/assoc-const-ty-mismatch.rs:9:5 | -LL | type T; - | ^^^^^^ +LL | type T; + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr index e39224f2c1646..42d722291c38b 100644 --- a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr +++ b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr @@ -21,6 +21,6 @@ LL | const X: i32 = ::ID; LL | const X: i32 = ::ID; | ~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/associated-consts/associated-const-array-len.stderr b/tests/ui/associated-consts/associated-const-array-len.stderr index e3db45810fdd1..f804cf20591f2 100644 --- a/tests/ui/associated-consts/associated-const-array-len.stderr +++ b/tests/ui/associated-consts/associated-const-array-len.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-consts/associated-const-dead-code.stderr b/tests/ui/associated-consts/associated-const-dead-code.stderr index 7e485a314c540..33f5a5ceedf1e 100644 --- a/tests/ui/associated-consts/associated-const-dead-code.stderr +++ b/tests/ui/associated-consts/associated-const-dead-code.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-consts/associated-const-generic-obligations.stderr b/tests/ui/associated-consts/associated-const-generic-obligations.stderr index d45868151b166..5ea85ff3b9899 100644 --- a/tests/ui/associated-consts/associated-const-generic-obligations.stderr +++ b/tests/ui/associated-consts/associated-const-generic-obligations.stderr @@ -12,6 +12,6 @@ LL | const FROM: Self::Out; = note: expected associated type `::Out` found reference `&'static str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr index 742b81535dfdf..6037122a365d9 100644 --- a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr +++ b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr @@ -13,6 +13,6 @@ LL | impl<'a> Foo for &'a () { | ^^ = note: ...does not necessarily outlive the static lifetime -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr b/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr index f3616035fc7d4..b91b777d5850f 100644 --- a/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr +++ b/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr @@ -10,6 +10,6 @@ note: type in trait LL | const BAR: u32; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/associated-consts/associated-const-in-trait.stderr b/tests/ui/associated-consts/associated-const-in-trait.stderr index 60bbe385c019b..59acd4820aea9 100644 --- a/tests/ui/associated-consts/associated-const-in-trait.stderr +++ b/tests/ui/associated-consts/associated-const-in-trait.stderr @@ -13,6 +13,6 @@ LL | const N: usize; | ^ ...because it contains this associated `const` = help: consider moving `N` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/associated-consts/associated-const-no-item.stderr b/tests/ui/associated-consts/associated-const-no-item.stderr index fe27da5ac645f..7ded05b7b48e1 100644 --- a/tests/ui/associated-consts/associated-const-no-item.stderr +++ b/tests/ui/associated-consts/associated-const-no-item.stderr @@ -11,6 +11,6 @@ note: `Foo` defines an item `ID`, perhaps you need to implement it LL | trait Foo { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/associated-consts/associated-const-private-impl.stderr b/tests/ui/associated-consts/associated-const-private-impl.stderr index a3fa3002e1efb..13bde56a680fd 100644 --- a/tests/ui/associated-consts/associated-const-private-impl.stderr +++ b/tests/ui/associated-consts/associated-const-private-impl.stderr @@ -7,6 +7,6 @@ LL | const ID: i32 = 1; LL | assert_eq!(1, bar1::Foo::ID); | ^^ private associated constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr index 0bc019b2dc875..cd83039428567 100644 --- a/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr @@ -6,5 +6,5 @@ LL | let _array = [4; ::Y]; | = note: this may fail depending on what value the parameter takes -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr index 46a54a12d6245..7f9324035e408 100644 --- a/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr @@ -5,7 +5,7 @@ LL | let _array: [u32; ::Y]; | ^ cannot perform const operation using `A` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.stderr b/tests/ui/associated-consts/defaults-cyclic-fail.stderr index e29c32f5dfdaf..9cee03041fe6d 100644 --- a/tests/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/tests/ui/associated-consts/defaults-cyclic-fail.stderr @@ -27,6 +27,6 @@ LL | assert_eq!(<() as Tr>::A, 0); | ^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr index ac5ec8e05ea96..091a50f9463b9 100644 --- a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr +++ b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -27,6 +27,6 @@ LL | assert_eq!(<() as Tr>::B, 0); // causes the error above = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/associated-consts/double-elided.stderr b/tests/ui/associated-consts/double-elided.stderr index ba4e6a23e27e6..67834788ccd4a 100644 --- a/tests/ui/associated-consts/double-elided.stderr +++ b/tests/ui/associated-consts/double-elided.stderr @@ -42,6 +42,6 @@ note: but the referenced data is only valid for the anonymous lifetime as define LL | const C: &&str = &""; | ^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to 1 previous error; 2 warnings emitted For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr index f8c02420f96af..e946491a08482 100644 --- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr +++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr @@ -18,6 +18,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | const ASSOC: &dyn Fn(_) = 1i32; | ^ not allowed in type signatures -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/associated-consts/issue-102335-const.stderr b/tests/ui/associated-consts/issue-102335-const.stderr index 531d15c5900c5..b69dfd51ea8c1 100644 --- a/tests/ui/associated-consts/issue-102335-const.stderr +++ b/tests/ui/associated-consts/issue-102335-const.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | type A: S = 34>; | ^^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index 4418fb7556bd9..21062fdaf5859 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -38,6 +38,6 @@ LL | const BAR: u32 = IMPL_REF_BAR; = note: cycle used when running analysis passes on this crate = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index 392cd5e3443ae..e4abf6203e8f2 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -38,6 +38,6 @@ LL | const BAR: u32 = DEFAULT_REF_BAR; = note: cycle used when running analysis passes on this crate = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 6cbddca9c62a0..05ebd76f50012 100644 --- a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -38,6 +38,6 @@ LL | const BAR: u32 = TRAIT_REF_BAR; = note: cycle used when running analysis passes on this crate = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-47814.stderr b/tests/ui/associated-consts/issue-47814.stderr index 2e4ddb81166b4..7382426b0ffaa 100644 --- a/tests/ui/associated-consts/issue-47814.stderr +++ b/tests/ui/associated-consts/issue-47814.stderr @@ -10,5 +10,5 @@ note: not a concrete type LL | impl<'a> ArpIPv4<'a> { | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr b/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr index 8175e510a093f..91bfcf29cb37f 100644 --- a/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr +++ b/tests/ui/associated-consts/projection-unspecified-but-bounded.stderr @@ -12,6 +12,6 @@ note: required by a bound in `foo` LL | fn foo>() {} | ^^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-consts/shadowed-const.rs b/tests/ui/associated-consts/shadowed-const.rs index cfdb391d39d51..d9b565742d42a 100644 --- a/tests/ui/associated-consts/shadowed-const.rs +++ b/tests/ui/associated-consts/shadowed-const.rs @@ -17,7 +17,7 @@ trait Baz2: Foo { trait Baz3 { const BAR: usize; const QUX: Self::BAR; - //~^ ERROR found associated const + //~^ ERROR expected type, found constant } fn main() {} diff --git a/tests/ui/associated-consts/shadowed-const.stderr b/tests/ui/associated-consts/shadowed-const.stderr index fe21d2aec00bc..2db645b3c9662 100644 --- a/tests/ui/associated-consts/shadowed-const.stderr +++ b/tests/ui/associated-consts/shadowed-const.stderr @@ -1,8 +1,14 @@ -error: found associated const `BAR` when type was expected - --> $DIR/shadowed-const.rs:19:14 +error: expected type, found constant + --> $DIR/shadowed-const.rs:19:20 | LL | const QUX: Self::BAR; - | ^^^^^^^^^ + | ^^^ unexpected constant + | +note: the associated constant is defined here + --> $DIR/shadowed-const.rs:18:3 + | +LL | const BAR: usize; + | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/ambiguity.stderr b/tests/ui/associated-inherent-types/ambiguity.stderr index 155c296cbb3c4..09e6c13970378 100644 --- a/tests/ui/associated-inherent-types/ambiguity.stderr +++ b/tests/ui/associated-inherent-types/ambiguity.stderr @@ -15,6 +15,6 @@ note: candidate #2 is defined in an impl for the type `Wrapper<()>` LL | type Foo = (); | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs b/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs new file mode 100644 index 0000000000000..b6993f66fe795 --- /dev/null +++ b/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo(T); + +impl<'a> Foo { + type Assoc = &'a (); +} + +fn bar(_: for<'a> fn(Foo::Assoc)>::Assoc)) {} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/assoc-inherent-no-body.stderr b/tests/ui/associated-inherent-types/assoc-inherent-no-body.stderr index 387a5658da373..c332416c6f31c 100644 --- a/tests/ui/associated-inherent-types/assoc-inherent-no-body.stderr +++ b/tests/ui/associated-inherent-types/assoc-inherent-no-body.stderr @@ -6,5 +6,5 @@ LL | type Baz; | | | help: provide a definition for the type: `= ;` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr b/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr index 415ee0193c94c..cf2aee6ab53e0 100644 --- a/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr +++ b/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr @@ -6,6 +6,6 @@ LL | type Data = aux::Owner::Data; | = help: add `#![feature(data)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr index 3c373f139cbe8..a2ad4cbde01ca 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr @@ -39,6 +39,6 @@ LL | | fn main() {} | |____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr index ab6a97b3d858f..b3d55fea14b5a 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr @@ -33,6 +33,6 @@ LL | | fn main() {} | |____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr b/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr index fcf828c21c7c2..5859834053887 100644 --- a/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr @@ -10,6 +10,6 @@ note: required by a bound in `Ty::Pr` LL | type Pr = T; | ^^^^ required by this bound in `Ty::Pr` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.region.stderr b/tests/ui/associated-inherent-types/generic-associated-types-bad.region.stderr index 94c20521857f0..1be65687a3e82 100644 --- a/tests/ui/associated-inherent-types/generic-associated-types-bad.region.stderr +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.region.stderr @@ -7,5 +7,5 @@ LL | #[cfg(region)] LL | let _: Ty::Static<&'a str> = ""; | ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/inference-fail.stderr b/tests/ui/associated-inherent-types/inference-fail.stderr index f29144e4aa755..bf329c69e99c1 100644 --- a/tests/ui/associated-inherent-types/inference-fail.stderr +++ b/tests/ui/associated-inherent-types/inference-fail.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | let _: S<_>::P = (); | ^^^^^^^ cannot infer type for type parameter `T` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/associated-inherent-types/issue-109299-1.stderr b/tests/ui/associated-inherent-types/issue-109299-1.stderr index dc59b56ee207d..c25ffb9d9c2ac 100644 --- a/tests/ui/associated-inherent-types/issue-109299-1.stderr +++ b/tests/ui/associated-inherent-types/issue-109299-1.stderr @@ -10,6 +10,6 @@ LL | type X = impl for Fn() -> Lexer::Cursor; = note: the associated type was found for - `Lexer` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-inherent-types/issue-109299.stderr b/tests/ui/associated-inherent-types/issue-109299.stderr index 63f50732d3c50..1e11c0e8c2af1 100644 --- a/tests/ui/associated-inherent-types/issue-109299.stderr +++ b/tests/ui/associated-inherent-types/issue-109299.stderr @@ -6,6 +6,6 @@ LL | impl Lexer<'d> { | | | help: consider introducing lifetime `'d` here: `<'d>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs index f4ad5d7ff6c03..dd62e59f07d22 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.rs +++ b/tests/ui/associated-inherent-types/issue-111404-1.rs @@ -9,5 +9,6 @@ impl<'a> Foo { fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} //~^ ERROR higher-ranked subtype error +//~| ERROR higher-ranked subtype error fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr index c55f1432389c7..cf4d4a5f19b12 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr @@ -4,5 +4,13 @@ error: higher-ranked subtype error LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: higher-ranked subtype error + --> $DIR/issue-111404-1.rs:10:1 + | +LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors diff --git a/tests/ui/associated-inherent-types/issue-111879-0.stderr b/tests/ui/associated-inherent-types/issue-111879-0.stderr index f6367c88aea6d..f60fd58c23b6b 100644 --- a/tests/ui/associated-inherent-types/issue-111879-0.stderr +++ b/tests/ui/associated-inherent-types/issue-111879-0.stderr @@ -4,5 +4,5 @@ error: overflow evaluating associated type `Carrier<'b>::Focus` LL | pub type Focus = &'a mut for<'b> fn(Carrier<'b>::Focus); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/issue-111879-1.stderr b/tests/ui/associated-inherent-types/issue-111879-1.stderr index bf35f2bb5b532..eb3329dc5e981 100644 --- a/tests/ui/associated-inherent-types/issue-111879-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111879-1.stderr @@ -7,6 +7,6 @@ LL | fn main(_: for<'a> fn(Foo::Assoc)) {} = note: expected signature `fn()` found signature `fn(for<'a> fn(&'a ()))` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/associated-inherent-types/late-bound-regions.stderr b/tests/ui/associated-inherent-types/late-bound-regions.stderr index 0dd17b05cd0db..fba3a5b853370 100644 --- a/tests/ui/associated-inherent-types/late-bound-regions.stderr +++ b/tests/ui/associated-inherent-types/late-bound-regions.stderr @@ -7,6 +7,6 @@ LL | f(&local) | | `local` is borrowed here | returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/associated-inherent-types/normalization-overflow.stderr b/tests/ui/associated-inherent-types/normalization-overflow.stderr index 16bb64281e3af..7f991a53c9bb7 100644 --- a/tests/ui/associated-inherent-types/normalization-overflow.stderr +++ b/tests/ui/associated-inherent-types/normalization-overflow.stderr @@ -4,5 +4,5 @@ error: overflow evaluating associated type `T::This` LL | type This = Self::This; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr index 3561db354c03f..9bd5a842fdc7c 100644 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr +++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr @@ -10,6 +10,6 @@ LL | let _: S::::Pr = (); = note: the associated type was found for - `S<()>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr index 9206b4f6db7e5..978305c2ce355 100644 --- a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr +++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr @@ -4,6 +4,6 @@ error[E0223]: ambiguous associated type LL | let _: S::::Pr = (); | ^^^^^^^^^^^^^ help: use fully-qualified syntax: ` as Tr>::Pr` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr index 230bfa538b4f3..0d5f781dc6334 100644 --- a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr +++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr @@ -10,5 +10,5 @@ LL | struct Container(T); = note: the following trait bounds were not satisfied: `T: Clone` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr index 3ddab25deb54c..650b5946064c2 100644 --- a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr +++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr @@ -16,5 +16,5 @@ LL | let _: S::::X; `Featureless: One` `Featureless: Two` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/regionck-0.stderr b/tests/ui/associated-inherent-types/regionck-0.stderr index 3a438ee630e1e..32e6d8e465a0f 100644 --- a/tests/ui/associated-inherent-types/regionck-0.stderr +++ b/tests/ui/associated-inherent-types/regionck-0.stderr @@ -6,5 +6,5 @@ LL | fn user<'a>() { LL | let _: S::<&'a ()>::T; | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/regionck-2.stderr b/tests/ui/associated-inherent-types/regionck-2.stderr index b0a4ed35d5609..4c68a591240f2 100644 --- a/tests/ui/associated-inherent-types/regionck-2.stderr +++ b/tests/ui/associated-inherent-types/regionck-2.stderr @@ -13,6 +13,6 @@ LL | fn test(_: Lexer::Cursor) {} | ^^^^^ = note: ...does not necessarily outlive the static lifetime -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-inherent-types/style.stderr b/tests/ui/associated-inherent-types/style.stderr index f83061f8c4216..12e4d545ab1d1 100644 --- a/tests/ui/associated-inherent-types/style.stderr +++ b/tests/ui/associated-inherent-types/style.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(non_camel_case_types)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.stderr b/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.stderr index ecf30f4cdec58..7ce69a94bf8c1 100644 --- a/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.stderr +++ b/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.stderr @@ -12,6 +12,6 @@ LL | impl S { LL | type T = T; | - required by a bound in this associated type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr b/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr index d4968cd05dcee..cb35cdde0b4be 100644 --- a/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr +++ b/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr @@ -13,6 +13,6 @@ LL | where LL | T: Copy; | ^^^^ required by this bound in `S::X` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr index f7a47be8dc39a..9e1dd73980792 100644 --- a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr @@ -4,6 +4,6 @@ error[E0223]: ambiguous associated type LL | let _x: >::Ty; | ^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: ` as Assoc>::Ty` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-item/associated-item-duplicate-bounds.stderr b/tests/ui/associated-item/associated-item-duplicate-bounds.stderr index f2e4ca524a439..8898880586c92 100644 --- a/tests/ui/associated-item/associated-item-duplicate-bounds.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-bounds.stderr @@ -5,7 +5,7 @@ LL | links: [u32; A::LINKS], // Shouldn't suggest bounds already there. | ^^^^^^^^ cannot perform const operation using `A` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-item/associated-item-duplicate-names-2.stderr b/tests/ui/associated-item/associated-item-duplicate-names-2.stderr index 0b96a6bd7c009..ee0686b0f912c 100644 --- a/tests/ui/associated-item/associated-item-duplicate-names-2.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-names-2.stderr @@ -6,6 +6,6 @@ LL | const bar: bool = true; LL | fn bar() {} | ^^^^^^^^ duplicate definitions for `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/associated-item/impl-duplicate-methods.stderr b/tests/ui/associated-item/impl-duplicate-methods.stderr index 6f753845ac85a..fbd2434003a49 100644 --- a/tests/ui/associated-item/impl-duplicate-methods.stderr +++ b/tests/ui/associated-item/impl-duplicate-methods.stderr @@ -6,6 +6,6 @@ LL | fn orange(&self) {} LL | fn orange(&self) {} | ^^^^^^^^^^^^^^^^ duplicate definitions for `orange` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr b/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr index f2604f0ba881d..9b077a4d3effb 100644 --- a/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr +++ b/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr @@ -12,6 +12,6 @@ LL | trait Baz: Foo + Bar {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index a32ab453152a0..7942992874da5 100644 --- a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -4,6 +4,6 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | fn func() -> Self::Out { | ^^^^^^^^^ the trait `Copy` is not implemented for `String` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr index 6fa266d23d49b..fe300a7de427b 100644 --- a/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr +++ b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr @@ -4,5 +4,5 @@ error: associated type bounds are only allowed in where clauses and function sig LL | dyn for<'j> B:, | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr index 8b66627d57fe2..7bdb2c5a7c292 100644 --- a/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr +++ b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr @@ -4,5 +4,5 @@ error: associated type bounds are only allowed in where clauses and function sig LL | impl dyn Trait {} | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/binder-on-bound.stderr b/tests/ui/associated-type-bounds/binder-on-bound.stderr index f71f72bfb94f3..d09ad73a61f10 100644 --- a/tests/ui/associated-type-bounds/binder-on-bound.stderr +++ b/tests/ui/associated-type-bounds/binder-on-bound.stderr @@ -4,5 +4,5 @@ error: `for<...>` is not allowed on associated type bounds LL | fn foo() where Trait Bound<'a> = &'a ()> { | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/const-projection-err.gce.stderr b/tests/ui/associated-type-bounds/const-projection-err.gce.stderr index 0f1ec9ad0522f..0b6207074979a 100644 --- a/tests/ui/associated-type-bounds/const-projection-err.gce.stderr +++ b/tests/ui/associated-type-bounds/const-projection-err.gce.stderr @@ -19,6 +19,6 @@ note: required by a bound in `foo` LL | fn foo>() {} | ^^^^^ required by this bound in `foo` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-type-bounds/const-projection-err.stock.stderr b/tests/ui/associated-type-bounds/const-projection-err.stock.stderr index bf0824259a5a7..e782571c7dea5 100644 --- a/tests/ui/associated-type-bounds/const-projection-err.stock.stderr +++ b/tests/ui/associated-type-bounds/const-projection-err.stock.stderr @@ -12,6 +12,6 @@ note: required by a bound in `foo` LL | fn foo>() {} | ^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-type-bounds/consts.rs b/tests/ui/associated-type-bounds/consts.rs index 9b95b1b52c05a..8f90c36ed45e1 100644 --- a/tests/ui/associated-type-bounds/consts.rs +++ b/tests/ui/associated-type-bounds/consts.rs @@ -1,7 +1,7 @@ #![feature(associated_type_bounds)] pub fn accept(_: impl Trait) {} -//~^ ERROR expected associated type, found associated constant +//~^ ERROR expected type, found constant pub trait Trait { const K: i32; diff --git a/tests/ui/associated-type-bounds/consts.stderr b/tests/ui/associated-type-bounds/consts.stderr index ddfb6612b081f..7f9fe5e500a3c 100644 --- a/tests/ui/associated-type-bounds/consts.stderr +++ b/tests/ui/associated-type-bounds/consts.stderr @@ -1,10 +1,16 @@ -error: expected associated type, found associated constant +error: expected type, found constant --> $DIR/consts.rs:3:29 | LL | pub fn accept(_: impl Trait) {} - | ^ + | ^------ bounds are not allowed on associated constants + | | + | unexpected constant | - = note: trait bounds not allowed on associated constant +note: the associated constant is defined here + --> $DIR/consts.rs:7:5 + | +LL | const K: i32; + | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr index 78bf93c32d57c..1f99d7db0b024 100644 --- a/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr +++ b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr @@ -13,6 +13,6 @@ LL | let _low = self.lows.remove(low.identify()).unwrap(); note: method defined here --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.stderr b/tests/ui/associated-type-bounds/issue-102335-ty.stderr index 8777b2965153a..561ca15ab0d05 100644 --- a/tests/ui/associated-type-bounds/issue-102335-ty.stderr +++ b/tests/ui/associated-type-bounds/issue-102335-ty.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | type A: S = ()>; | ^^^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-type-bounds/issue-104916.stderr b/tests/ui/associated-type-bounds/issue-104916.stderr index 35435962ffe9d..65c89735c5dcc 100644 --- a/tests/ui/associated-type-bounds/issue-104916.stderr +++ b/tests/ui/associated-type-bounds/issue-104916.stderr @@ -4,5 +4,5 @@ error: associated type bounds are only allowed in where clauses and function sig LL | dyn for<'j> B:, | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/issue-71443-1.stderr b/tests/ui/associated-type-bounds/issue-71443-1.stderr index 09c8ec2e289f5..6abaaf8e182be 100644 --- a/tests/ui/associated-type-bounds/issue-71443-1.stderr +++ b/tests/ui/associated-type-bounds/issue-71443-1.stderr @@ -6,6 +6,6 @@ LL | fn hello Iterator>() { LL | Incorrect | ^^^^^^^^^ expected `()`, found `Incorrect` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-type-bounds/issue-99828.rs b/tests/ui/associated-type-bounds/issue-99828.rs index 7b711283f5b83..67ba50f3cbce6 100644 --- a/tests/ui/associated-type-bounds/issue-99828.rs +++ b/tests/ui/associated-type-bounds/issue-99828.rs @@ -1,5 +1,5 @@ fn get_iter(vec: &[i32]) -> impl Iterator + '_ { - //~^ ERROR expected associated type bound, found constant + //~^ ERROR expected type, found constant //~| ERROR associated const equality is incomplete vec.iter() } diff --git a/tests/ui/associated-type-bounds/issue-99828.stderr b/tests/ui/associated-type-bounds/issue-99828.stderr index dc93c47dace23..8813baf84de45 100644 --- a/tests/ui/associated-type-bounds/issue-99828.stderr +++ b/tests/ui/associated-type-bounds/issue-99828.stderr @@ -7,13 +7,15 @@ LL | fn get_iter(vec: &[i32]) -> impl Iterator + '_ { = note: see issue #92827 for more information = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable -error: expected associated type bound, found constant - --> $DIR/issue-99828.rs:1:43 +error: expected type, found constant + --> $DIR/issue-99828.rs:1:50 | LL | fn get_iter(vec: &[i32]) -> impl Iterator + '_ { - | ^^^^^^^^^ + | ---- ^^ unexpected constant + | | + | expected a type because of this associated type | -note: associated type defined here +note: the associated type is defined here --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error: aborting due to 2 previous errors diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr index 6c2645ae5bd1e..3666007e3d388 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.current_without.stderr @@ -25,5 +25,5 @@ note: required by a bound in `is_send` LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr index 6c2645ae5bd1e..3666007e3d388 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.next_without.stderr @@ -25,5 +25,5 @@ note: required by a bound in `is_send` LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr index 5b96676d037c6..f576cc9c95f09 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr @@ -25,5 +25,5 @@ note: required by a bound in `is_send` LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr index d2a445f338796..26b4d935ac7c6 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr @@ -13,5 +13,5 @@ error: return type notation is not allowed to use type equality LL | fn test>>>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr index d2a445f338796..26b4d935ac7c6 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr @@ -13,5 +13,5 @@ error: return type notation is not allowed to use type equality LL | fn test>>>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr index 1a2f84715243c..d432e95773541 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr @@ -13,5 +13,5 @@ error: return type notation is not allowed to use type equality LL | fn test>>>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.rs b/tests/ui/associated-type-bounds/return-type-notation/missing.rs index 0679b96f6c58a..e6270ec3166c5 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/missing.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/missing.rs @@ -8,6 +8,6 @@ trait Trait { } fn bar>() {} -//~^ ERROR cannot find associated function `methid` for `Trait` +//~^ ERROR associated function `methid` not found for `Trait` fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr index fb6538fa05c40..db9cb9f49a305 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr @@ -7,11 +7,12 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -error: cannot find associated function `methid` for `Trait` +error[E0220]: associated function `methid` not found for `Trait` --> $DIR/missing.rs:10:17 | LL | fn bar>() {} - | ^^^^^^^^^^^^^^ + | ^^^^^^ help: there is an associated function with a similar name: `method` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr index 31b793995f8ab..3e307c5f42ca4 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr @@ -18,5 +18,5 @@ LL | fn test>() {} | = note: function returns `()`, which is not compatible with associated type return bounds -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stderr b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stderr index 77e015b4160bb..f27603e3719df 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.stderr @@ -7,6 +7,6 @@ LL | fn foo>() {} = note: see issue #52662 for more information = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr index b104f38ce9080..7ca9aff432279 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr @@ -11,6 +11,6 @@ help: consider constraining the associated type `::M` to `u8` LL | impl> U for u16 { | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/associated-type-macro.stderr b/tests/ui/associated-types/associated-type-macro.stderr index 6a4cf99c474e2..dc540a475c358 100644 --- a/tests/ui/associated-types/associated-type-macro.stderr +++ b/tests/ui/associated-types/associated-type-macro.stderr @@ -4,5 +4,5 @@ error: macros cannot use qualified paths LL | <() as module>::mac!(); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/associated-type-shadowed-from-non-local-supertrait.rs b/tests/ui/associated-types/associated-type-shadowed-from-non-local-supertrait.rs new file mode 100644 index 0000000000000..045a43548dcaa --- /dev/null +++ b/tests/ui/associated-types/associated-type-shadowed-from-non-local-supertrait.rs @@ -0,0 +1,15 @@ +// Test that no help message is emitted that suggests renaming the +// associated type from a non-local trait + +pub trait NewIter: Iterator { + type Item; +} + +impl Clone for Box> { + //~^ ERROR the value of the associated type `Item` in `Iterator` must be specified + fn clone(&self) -> Self { + unimplemented!(); + } +} + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-type-shadowed-from-non-local-supertrait.stderr b/tests/ui/associated-types/associated-type-shadowed-from-non-local-supertrait.stderr new file mode 100644 index 0000000000000..fdb4e4fc1a85e --- /dev/null +++ b/tests/ui/associated-types/associated-type-shadowed-from-non-local-supertrait.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `Item` in `Iterator` must be specified + --> $DIR/associated-type-shadowed-from-non-local-supertrait.rs:8:27 + | +LL | type Item; + | --------- `Iterator::Item` shadowed here, consider renaming it +... +LL | impl Clone for Box> { + | ^^^^^^^^^^^^^^^^^ associated type `Item` must be specified + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/associated-types/associated-type-shadowed-from-supertrait.rs b/tests/ui/associated-types/associated-type-shadowed-from-supertrait.rs new file mode 100644 index 0000000000000..95d03892838b8 --- /dev/null +++ b/tests/ui/associated-types/associated-type-shadowed-from-supertrait.rs @@ -0,0 +1,19 @@ +// Test Setting the value of an associated type +// that is shadowed from a supertrait + +pub trait Super { + type X; +} + +pub trait Sub: Super { + type X; +} + +impl Clone for Box> { + //~^ ERROR value of the associated type `X` in `Super` must be specified + fn clone(&self) -> Self { + unimplemented!(); + } +} + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-type-shadowed-from-supertrait.stderr b/tests/ui/associated-types/associated-type-shadowed-from-supertrait.stderr new file mode 100644 index 0000000000000..e6cec255eeef8 --- /dev/null +++ b/tests/ui/associated-types/associated-type-shadowed-from-supertrait.stderr @@ -0,0 +1,15 @@ +error[E0191]: the value of the associated type `X` in `Super` must be specified + --> $DIR/associated-type-shadowed-from-supertrait.rs:12:27 + | +LL | type X; + | ------ `Super::X` defined here, consider renaming it +... +LL | type X; + | ------ `Super::X` shadowed here, consider renaming it +... +LL | impl Clone for Box> { + | ^^^^^^^^^^ associated type `X` must be specified + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr b/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr index fbc4ccd4cf440..ebe56c8cd6894 100644 --- a/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr +++ b/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait Add { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-bound-failure.stderr b/tests/ui/associated-types/associated-types-bound-failure.stderr index 3eda22796e099..0b404819c2c0d 100644 --- a/tests/ui/associated-types/associated-types-bound-failure.stderr +++ b/tests/ui/associated-types/associated-types-bound-failure.stderr @@ -11,6 +11,6 @@ help: consider further restricting the associated type LL | where G : GetToInt, ::R: ToInt | +++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-eq-1.stderr b/tests/ui/associated-types/associated-types-eq-1.stderr index e9ace7d2574b9..14ef36876740b 100644 --- a/tests/ui/associated-types/associated-types-eq-1.stderr +++ b/tests/ui/associated-types/associated-types-eq-1.stderr @@ -15,6 +15,6 @@ help: you might be missing a type parameter LL | fn foo2(x: I) { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr index 23ee8cd23b5c3..447b8413ee294 100644 --- a/tests/ui/associated-types/associated-types-eq-2.stderr +++ b/tests/ui/associated-types/associated-types-eq-2.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | fn baz(x: &>::A) {} | ^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-types/associated-types-eq-expr-path.stderr b/tests/ui/associated-types/associated-types-eq-expr-path.stderr index bd354cf3e16f2..7559f3b7c2e55 100644 --- a/tests/ui/associated-types/associated-types-eq-expr-path.stderr +++ b/tests/ui/associated-types/associated-types-eq-expr-path.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | let x: isize = Foo::::bar(); | ^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr index 6552c8be78089..17941b6bf1eef 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -9,6 +9,6 @@ help: consider further restricting `Self` LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} | +++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr b/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr index 676d6353d985a..adde31b4a321c 100644 --- a/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr +++ b/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr @@ -9,6 +9,6 @@ help: consider further restricting this bound LL | fn f + Foo>(t: &T) { | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-issue-17359.stderr b/tests/ui/associated-types/associated-types-issue-17359.stderr index 9e40d8095862b..f5397b8ecdc93 100644 --- a/tests/ui/associated-types/associated-types-issue-17359.stderr +++ b/tests/ui/associated-types/associated-types-issue-17359.stderr @@ -7,6 +7,6 @@ LL | type Type; LL | impl Trait for isize {} | ^^^^^^^^^^^^^^^^^^^^ missing `Type` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/associated-types/associated-types-issue-20346.stderr b/tests/ui/associated-types/associated-types-issue-20346.stderr index f384079862fba..8e6b847b3aac9 100644 --- a/tests/ui/associated-types/associated-types-issue-20346.stderr +++ b/tests/ui/associated-types/associated-types-issue-20346.stderr @@ -22,6 +22,6 @@ note: required by a bound in `is_iterator_of` LL | fn is_iterator_of>(_: &I) {} | ^^^^^^ required by this bound in `is_iterator_of` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr index b2ee1b5e6d045..fe1be6be01554 100644 --- a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `T` LL | fn uhoh(foo: ::Value) {} | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index 2e40dbd065d3e..b586053a5bc9c 100644 --- a/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -9,6 +9,6 @@ help: consider further restricting `Self` LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} | +++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-outlives.stderr b/tests/ui/associated-types/associated-types-outlives.stderr index 2fe3f2d4a0250..deeedd2226698 100644 --- a/tests/ui/associated-types/associated-types-outlives.stderr +++ b/tests/ui/associated-types/associated-types-outlives.stderr @@ -11,6 +11,6 @@ LL | drop(x); LL | return f(y); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr index fdec01b95e3b1..4dfd275a19058 100644 --- a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -6,6 +6,6 @@ LL | let _: &dyn I32Iterator = &vec![42].into_iter(); | = note: required for the cast from `&std::vec::IntoIter` to `&dyn Iterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr index c508006c3a499..83bad291e5666 100644 --- a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr @@ -9,6 +9,6 @@ help: use a fully qualified path with inferred lifetimes LL | x: >::A) | ~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0212`. diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 2e67c21940fc7..64a88525af8d4 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -9,6 +9,6 @@ help: consider further restricting `Self` LL | fn okay(&self, foo: U, bar: ::Value) where Self: Get; | +++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-unconstrained.stderr b/tests/ui/associated-types/associated-types-unconstrained.stderr index ef9b7cae01bbd..4221a064ff9ce 100644 --- a/tests/ui/associated-types/associated-types-unconstrained.stderr +++ b/tests/ui/associated-types/associated-types-unconstrained.stderr @@ -12,6 +12,6 @@ help: use the fully-qualified path to the only available implementation LL | let x: isize = ::bar(); | +++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/associated-types/associated-types-unsized.stderr b/tests/ui/associated-types/associated-types-unsized.stderr index bec9b1500c9d7..e46b2a394640b 100644 --- a/tests/ui/associated-types/associated-types-unsized.stderr +++ b/tests/ui/associated-types/associated-types-unsized.stderr @@ -12,6 +12,6 @@ help: consider further restricting the associated type LL | fn foo(t: T) where ::Value: Sized { | ++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr index 4de4afb6e9246..8ccfb2122167b 100644 --- a/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -10,6 +10,6 @@ help: consider using the `'static` lifetime LL | fn elision &'static i32>() { | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr index b709fae5a8e56..435e224bd8922 100644 --- a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() { } | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr index 7753d186504f8..0593a62a75074 100644 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -10,6 +10,6 @@ help: consider using the `'static` lifetime LL | fn elision(_: fn() -> &'static i32) { | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.local.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.local.stderr index 788cf667c8d28..138b777e664e4 100644 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.local.stderr +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.local.stderr @@ -4,6 +4,6 @@ error[E0581]: return type references lifetime `'a`, which is not constrained by LL | let _: for<'a> fn() -> &'a i32 = loop { }; | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0581`. diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr index 1c0d3ac105852..1815a7be7ee81 100644 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() { } | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.structure.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.structure.stderr index f7833500d00c4..c7d097d37462d 100644 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.structure.stderr +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.structure.stderr @@ -4,6 +4,6 @@ error[E0581]: return type references lifetime `'a`, which is not constrained by LL | x: for<'a> fn() -> &'a i32 | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0581`. diff --git a/tests/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/tests/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr index 6d8ab2c3fdc74..6ae13e9222a3b 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr +++ b/tests/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr @@ -6,5 +6,5 @@ LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { LL | bar(foo, x) | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index b64cb2c3d0b6a..b8100f6dfaec0 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -11,5 +11,5 @@ LL | bar(foo, x) = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/defaults-wf.stderr b/tests/ui/associated-types/defaults-wf.stderr index fc830b8d67686..aeb4e47abcbf7 100644 --- a/tests/ui/associated-types/defaults-wf.stderr +++ b/tests/ui/associated-types/defaults-wf.stderr @@ -8,6 +8,6 @@ LL | type Ty = Vec<[u8]>; note: required by a bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr index 3ecac9c83e571..606084aea34a6 100644 --- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr +++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr @@ -7,6 +7,6 @@ LL | debug_assert_eq!(iter.next(), Some(value)); = note: expected enum `Option<::Item>` found enum `Option<&::Item>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/higher-ranked-projection.bad.stderr b/tests/ui/associated-types/higher-ranked-projection.bad.stderr index 239f455393861..09606a1944d57 100644 --- a/tests/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/tests/ui/associated-types/higher-ranked-projection.bad.stderr @@ -12,6 +12,6 @@ note: the lifetime requirement is introduced here LL | where for<'a> &'a T: Mirror | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-1.stderr index b380a1b6f0658..ab5dc803cdf47 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-1.stderr @@ -14,6 +14,6 @@ LL | where LL | for<'b> >::U: Clone, | ^^^^^ required by this bound in `X` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-2.stderr index 8ccbc9fb5144a..2a7d75ef29bef 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-2.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-2.stderr @@ -18,6 +18,6 @@ LL | for<'b> >::U: Clone, = note: 128 redundant requirements hidden = note: required for `u32` to implement `for<'b> X<'b>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-object.stderr b/tests/ui/associated-types/hr-associated-type-bound-object.stderr index a0a6f76a58371..8c91211b964b4 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-object.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-object.stderr @@ -13,6 +13,6 @@ LL | where LL | for<'b> >::U: Clone, | ^^^^^ required by this bound in `X` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr index e249f2e0c2799..9e03936422491 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -14,6 +14,6 @@ LL | trait Y<'a, T: ?Sized> LL | for<'b> >::V: Clone, | ^^^^^ required by this bound in `Y` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr index f49439d3573d3..f8be4ec241052 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -14,6 +14,6 @@ LL | trait X<'a, T> LL | for<'b> >::U: Clone, | ^^^^^ required by this bound in `X` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr index f8733b423d778..22c4bd68690e3 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -14,6 +14,6 @@ LL | trait X<'a, T> LL | for<'b> <(T,) as X<'b, T>>::U: Clone, | ^^^^^ required by this bound in `X` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr index bd6e627a3d0d5..da988f4cfc1b6 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `T` LL | impl X<'b, T>> X<'_, T> for (S,) { | ++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index 425cfdca01d1f..59b52521ef80b 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -21,6 +21,6 @@ help: consider further restricting this bound LL | impl> UnsafeCopy<'_, T> for T { | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr b/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr index fbd76a64c1e92..24409b32ad3eb 100644 --- a/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -19,6 +19,6 @@ help: consider constraining the associated type `::Item` to `i3 LL | fn bar() -> impl Bar { | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/impl-wf-cycle-1.stderr b/tests/ui/associated-types/impl-wf-cycle-1.stderr index 53022dcb4c787..5fa36733f6677 100644 --- a/tests/ui/associated-types/impl-wf-cycle-1.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-1.stderr @@ -19,6 +19,6 @@ LL | Self::A: Baz, = note: 1 redundant requirement hidden = note: required for `(T,)` to implement `Grault` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-types/impl-wf-cycle-2.stderr b/tests/ui/associated-types/impl-wf-cycle-2.stderr index 81c58be927e6d..17a96bbd93430 100644 --- a/tests/ui/associated-types/impl-wf-cycle-2.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-2.stderr @@ -16,6 +16,6 @@ LL | impl Grault for (T,) LL | Self::A: Copy, | ---- unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-types/issue-19883.stderr b/tests/ui/associated-types/issue-19883.stderr index bd6a86b742089..35184e852cfe1 100644 --- a/tests/ui/associated-types/issue-19883.stderr +++ b/tests/ui/associated-types/issue-19883.stderr @@ -10,6 +10,6 @@ LL | >::Dst | not found in `From` | help: maybe you meant this associated type: `Output` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0576`. diff --git a/tests/ui/associated-types/issue-20005.stderr b/tests/ui/associated-types/issue-20005.stderr index c8e57df0d9fee..02470a4424919 100644 --- a/tests/ui/associated-types/issue-20005.stderr +++ b/tests/ui/associated-types/issue-20005.stderr @@ -18,6 +18,6 @@ help: consider relaxing the implicit `Sized` restriction LL | trait From { | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-20825.stderr b/tests/ui/associated-types/issue-20825.stderr index 02b3536e2d15c..e4f1fc62387c0 100644 --- a/tests/ui/associated-types/issue-20825.stderr +++ b/tests/ui/associated-types/issue-20825.stderr @@ -12,6 +12,6 @@ LL | pub trait Processor: Subscriber { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-types/issue-22037.stderr b/tests/ui/associated-types/issue-22037.stderr index 0e019f10f37f2..b02dad97d354e 100644 --- a/tests/ui/associated-types/issue-22037.stderr +++ b/tests/ui/associated-types/issue-22037.stderr @@ -9,6 +9,6 @@ LL | fn a(&self) -> ::X; | not found in `A` | help: maybe you meant this associated type: `Output` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0576`. diff --git a/tests/ui/associated-types/issue-23595-1.stderr b/tests/ui/associated-types/issue-23595-1.stderr index 3443c4925f4e8..f9d58c23cbba8 100644 --- a/tests/ui/associated-types/issue-23595-1.stderr +++ b/tests/ui/associated-types/issue-23595-1.stderr @@ -8,6 +8,6 @@ LL | type ChildKey; LL | type Children = dyn Index; | ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/associated-types/issue-23595-2.stderr b/tests/ui/associated-types/issue-23595-2.stderr index 73effa9f95535..2671bf57d0c43 100644 --- a/tests/ui/associated-types/issue-23595-2.stderr +++ b/tests/ui/associated-types/issue-23595-2.stderr @@ -4,6 +4,6 @@ error[E0220]: associated type `anything_here_kills_it` not found for `Self` LL | type B = C; | ^^^^^^^^^^^^^^^^^^^^^^ help: `Self` has the following associated type: `B` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr index fa309a55c3c22..4e432c0e702a9 100644 --- a/tests/ui/associated-types/issue-25700.stderr +++ b/tests/ui/associated-types/issue-25700.stderr @@ -8,6 +8,6 @@ LL | drop(t); LL | drop(t); | ^ value used here after move -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/associated-types/issue-26681.stderr b/tests/ui/associated-types/issue-26681.stderr index 977620d9052f2..b64bcee07f043 100644 --- a/tests/ui/associated-types/issue-26681.stderr +++ b/tests/ui/associated-types/issue-26681.stderr @@ -9,6 +9,6 @@ LL | const C: ::Bar = 6665; = note: expected associated type `<::Fv as Foo>::Bar` found type `{integer}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr index a14a273b3ece9..70bf90150b8fa 100644 --- a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr +++ b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-32323.stderr b/tests/ui/associated-types/issue-32323.stderr index 8212c607e1126..6b0ef1efdd0eb 100644 --- a/tests/ui/associated-types/issue-32323.stderr +++ b/tests/ui/associated-types/issue-32323.stderr @@ -13,6 +13,6 @@ help: consider constraining the associated type `>::Out` to `()` LL | pub fn f<'a, T: Tr<'a, Out = ()>>() -> >::Out {} | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/issue-36499.rs b/tests/ui/associated-types/issue-36499.rs index 7f8f13ef8d4ac..3d6f11faff78c 100644 --- a/tests/ui/associated-types/issue-36499.rs +++ b/tests/ui/associated-types/issue-36499.rs @@ -1,4 +1,4 @@ -// error-pattern: aborting due to previous error +// error-pattern: aborting due to 1 previous error fn main() { 2 + +2; diff --git a/tests/ui/associated-types/issue-36499.stderr b/tests/ui/associated-types/issue-36499.stderr index 80e42b61d2057..dd91bac815861 100644 --- a/tests/ui/associated-types/issue-36499.stderr +++ b/tests/ui/associated-types/issue-36499.stderr @@ -10,5 +10,5 @@ LL - 2 + +2; LL + 2 + 2; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index a52a9c138f147..8b628f5ae6d19 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -17,6 +17,6 @@ help: consider further restricting the associated type LL | Expr: Expression::Nullable>, ::SqlType: NotNull, | +++++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr index 50fa7d1ac4d43..529fc1f119a9c 100644 --- a/tests/ui/associated-types/issue-43784-associated-type.stderr +++ b/tests/ui/associated-types/issue-43784-associated-type.stderr @@ -19,6 +19,6 @@ help: consider restricting type parameter `T` LL | impl Complete for T { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-44153.stderr b/tests/ui/associated-types/issue-44153.stderr index 73365d64d5602..384b8685a1e78 100644 --- a/tests/ui/associated-types/issue-44153.stderr +++ b/tests/ui/associated-types/issue-44153.stderr @@ -17,6 +17,6 @@ LL | impl<'a> Visit for () where LL | (): Array, | -------------- unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/issue-47814.stderr b/tests/ui/associated-types/issue-47814.stderr index 2e4ddb81166b4..7382426b0ffaa 100644 --- a/tests/ui/associated-types/issue-47814.stderr +++ b/tests/ui/associated-types/issue-47814.stderr @@ -10,5 +10,5 @@ note: not a concrete type LL | impl<'a> ArpIPv4<'a> { | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/issue-54108.stderr b/tests/ui/associated-types/issue-54108.stderr index 6ff5e45423431..f300208fcc871 100644 --- a/tests/ui/associated-types/issue-54108.stderr +++ b/tests/ui/associated-types/issue-54108.stderr @@ -15,6 +15,6 @@ help: consider further restricting the associated type LL | T: SubEncoder, ::ActualSize: Add | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-62200.stderr b/tests/ui/associated-types/issue-62200.stderr index 04f0728f58ea8..7b040f8aa147c 100644 --- a/tests/ui/associated-types/issue-62200.stderr +++ b/tests/ui/associated-types/issue-62200.stderr @@ -7,6 +7,6 @@ LL | fn foo(x: impl Fn(>::A) -> >::A) {} = note: lifetimes appearing in an associated or opaque type are not considered constrained = note: consider introducing a named lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/associated-types/issue-63593.stderr b/tests/ui/associated-types/issue-63593.stderr index f643ec3ff1fdc..67151431a67a7 100644 --- a/tests/ui/associated-types/issue-63593.stderr +++ b/tests/ui/associated-types/issue-63593.stderr @@ -14,6 +14,6 @@ help: consider further restricting `Self` LL | trait MyTrait: Sized { | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-64855.stderr b/tests/ui/associated-types/issue-64855.stderr index f1016f0e3a191..7c09abdb3b6f3 100644 --- a/tests/ui/associated-types/issue-64855.stderr +++ b/tests/ui/associated-types/issue-64855.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | pub trait Foo { | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-72806.stderr b/tests/ui/associated-types/issue-72806.stderr index e95943f34d549..9cb615bbb2882 100644 --- a/tests/ui/associated-types/issue-72806.stderr +++ b/tests/ui/associated-types/issue-72806.stderr @@ -15,6 +15,6 @@ note: required by a bound in `Bar::Sibling` LL | type Sibling: Bar2; | ^^^^^^^ required by this bound in `Bar::Sibling` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/issue-85103-layout-debug.stderr b/tests/ui/associated-types/issue-85103-layout-debug.stderr index 0bdea10ba474a..c79543e73cd0b 100644 --- a/tests/ui/associated-types/issue-85103-layout-debug.stderr +++ b/tests/ui/associated-types/issue-85103-layout-debug.stderr @@ -11,6 +11,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | type Edges<'a, E> where [E]: ToOwned = Cow<'a, [E]>; | ++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/missing-associated-types.stderr b/tests/ui/associated-types/missing-associated-types.stderr index e9669afe8c704..0636667ea1fd5 100644 --- a/tests/ui/associated-types/missing-associated-types.stderr +++ b/tests/ui/associated-types/missing-associated-types.stderr @@ -49,7 +49,7 @@ LL | type B; LL | type Bar = dyn Add + Sub + X + Z; | ^^^^^^^^ ^^^^^^^^ ^^^^^^ ^^^^^^ associated types `A`, `B`, `Output` must be specified | | | | - | | | associated types `Output` (from trait `Mul`), `Output` (from trait `Div`) must be specified + | | | associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified | | associated type `Output` must be specified | associated type `Output` must be specified | @@ -119,7 +119,7 @@ error[E0191]: the value of the associated types `Output` in `Div`, `Output` in ` --> $DIR/missing-associated-types.rs:24:21 | LL | type Bal = dyn X; - | ^^^^^^ associated types `Output` (from trait `Mul`), `Output` (from trait `Div`) must be specified + | ^^^^^^ associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified | = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types diff --git a/tests/ui/associated-types/point-at-type-on-obligation-failure.stderr b/tests/ui/associated-types/point-at-type-on-obligation-failure.stderr index 9afbe82c32195..1c9de509e683e 100644 --- a/tests/ui/associated-types/point-at-type-on-obligation-failure.stderr +++ b/tests/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -15,6 +15,6 @@ note: required by a bound in `Bar::Sibling` LL | type Sibling: Bar2; | ^^^^^^^^^^^ required by this bound in `Bar::Sibling` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr index 8e7cf86c4066f..99a46dedcdce6 100644 --- a/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr +++ b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr @@ -11,6 +11,6 @@ help: consider further restricting `Self` LL | trait ArithmeticOps: Add + Sub + Mul + Div + Sized {} | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr index 10691aad04e81..1d8d1c67bae16 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr @@ -16,6 +16,6 @@ help: to force the closure to take ownership of `x` (and any other referenced va LL | Box::new((async move || x)()) | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/async-fn-path-elision.stderr b/tests/ui/async-await/async-fn-path-elision.stderr index 224198653dc57..4b0139a396c43 100644 --- a/tests/ui/async-await/async-fn-path-elision.stderr +++ b/tests/ui/async-await/async-fn-path-elision.stderr @@ -9,6 +9,6 @@ help: indicate the anonymous lifetime LL | async fn error(lt: HasLifetime<'_>) { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr index eaa455380505e..99bce89e8d3bf 100644 --- a/tests/ui/async-await/async-is-unwindsafe.stderr +++ b/tests/ui/async-await/async-is-unwindsafe.stderr @@ -29,6 +29,6 @@ note: required by a bound in `is_unwindsafe` LL | fn is_unwindsafe(_: impl std::panic::UnwindSafe) {} | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_unwindsafe` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/await-keyword/post_expansion_error.stderr b/tests/ui/async-await/await-keyword/post_expansion_error.stderr index 0996c38b3b6c6..7948fb9564e07 100644 --- a/tests/ui/async-await/await-keyword/post_expansion_error.stderr +++ b/tests/ui/async-await/await-keyword/post_expansion_error.stderr @@ -4,5 +4,5 @@ error: expected expression, found `)` LL | await!() | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/awaiting-unsized-param.stderr b/tests/ui/async-await/awaiting-unsized-param.stderr index 47a5dcebf25d6..0104736976d5d 100644 --- a/tests/ui/async-await/awaiting-unsized-param.stderr +++ b/tests/ui/async-await/awaiting-unsized-param.stderr @@ -16,6 +16,6 @@ LL | async fn bug(mut f: dyn Future + Unpin) -> T { = help: the trait `Sized` is not implemented for `(dyn Future + Unpin + 'static)` = note: all values captured by value by a closure must have a statically known size -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/clone-suggestion.stderr b/tests/ui/async-await/clone-suggestion.stderr index b5c8ef6993d6e..3374068ed3f60 100644 --- a/tests/ui/async-await/clone-suggestion.stderr +++ b/tests/ui/async-await/clone-suggestion.stderr @@ -15,6 +15,6 @@ help: you can `clone` the value and consume it, but this might not be your desir LL | f.clone().await; | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/const-async-fn-in-main.stderr b/tests/ui/async-await/const-async-fn-in-main.stderr index 10b15170922f7..06f3e34629a55 100644 --- a/tests/ui/async-await/const-async-fn-in-main.stderr +++ b/tests/ui/async-await/const-async-fn-in-main.stderr @@ -7,5 +7,5 @@ LL | const async fn a() {} | | `async` because of this | `const` because of this -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/dont-print-desugared-async.stderr b/tests/ui/async-await/dont-print-desugared-async.stderr index d80467c7fa887..1dade23f62313 100644 --- a/tests/ui/async-await/dont-print-desugared-async.stderr +++ b/tests/ui/async-await/dont-print-desugared-async.stderr @@ -4,6 +4,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | async fn async_fn(&ref mut s: &[i32]) {} | ^^^^^^^^^ cannot borrow as mutable through `&` reference -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr index e65d9d0e5d35f..1faaf4ddce2f6 100644 --- a/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr +++ b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `test` found for opaque type `impl Future` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/async-await/dont-suggest-missing-await.stderr b/tests/ui/async-await/dont-suggest-missing-await.stderr index 1fa4e5db0cbbc..45a226c31f840 100644 --- a/tests/ui/async-await/dont-suggest-missing-await.stderr +++ b/tests/ui/async-await/dont-suggest-missing-await.stderr @@ -21,6 +21,6 @@ help: consider `await`ing on the `Future` LL | take_u32(x.await) | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr index 6c235916d647e..9fce4d61b3b6f 100644 --- a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr +++ b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr @@ -19,5 +19,5 @@ note: required by a bound in `assert_send` LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/feature-async-closure.stderr b/tests/ui/async-await/feature-async-closure.stderr index 485a838b67ff2..c69a0dd9ed98d 100644 --- a/tests/ui/async-await/feature-async-closure.stderr +++ b/tests/ui/async-await/feature-async-closure.stderr @@ -8,6 +8,6 @@ LL | let _ = async || {}; = help: add `#![feature(async_closure)]` to the crate attributes to enable = help: to use an async block, remove the `||`: `async {` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/async-await/feature-self-return-type.stderr b/tests/ui/async-await/feature-self-return-type.stderr index dc160bfbf6179..120f1c9b00d00 100644 --- a/tests/ui/async-await/feature-self-return-type.stderr +++ b/tests/ui/async-await/feature-self-return-type.stderr @@ -11,6 +11,6 @@ LL | LL | }; | - `bar` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/async-await/field-assign-nonsend.stderr b/tests/ui/async-await/field-assign-nonsend.stderr index 3037d7024472d..418a0829c657e 100644 --- a/tests/ui/async-await/field-assign-nonsend.stderr +++ b/tests/ui/async-await/field-assign-nonsend.stderr @@ -19,5 +19,5 @@ note: required by a bound in `assert_send` LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/future-contains-err-issue-115188.stderr b/tests/ui/async-await/future-contains-err-issue-115188.stderr index 8fd2550c1c77a..0e2da190af71b 100644 --- a/tests/ui/async-await/future-contains-err-issue-115188.stderr +++ b/tests/ui/async-await/future-contains-err-issue-115188.stderr @@ -4,6 +4,6 @@ error[E0063]: missing field `t` in initializer of `Wrapper<_>` LL | let y = Wrapper { }; | ^^^^^^^ missing `t` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr index b70b36adb4a5b..34aded73da55b 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr @@ -12,6 +12,6 @@ LL | fn foo(&self) -> Pin + '_>>; = note: expected signature `fn(&i32) -> Pin>>` found signature `fn(&i32) -> impl Future` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index 6392ce86e4a0f..1462c694e161e 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -7,5 +7,5 @@ LL | async fn foo(&self) -> i32; LL | fn foo(&self) -> Pin + '_>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index 1eda6fe6532a3..a2f1060e36fc4 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -7,5 +7,5 @@ LL | async fn foo(&self) -> i32; LL | fn foo(&self) -> MyFuture { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr index cf0bcd741fc31..11489c18ad401 100644 --- a/tests/ui/async-await/in-trait/async-recursive-generic.stderr +++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr @@ -7,6 +7,6 @@ LL | async fn foo_recursive(&self, n: usize) -> T { = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr index b959652ea167f..5879628572697 100644 --- a/tests/ui/async-await/in-trait/async-recursive.stderr +++ b/tests/ui/async-await/in-trait/async-recursive.stderr @@ -7,6 +7,6 @@ LL | async fn foo_recursive(&self, n: usize) -> i32 { = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr index cd085074ae344..f75ccb65d1509 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr @@ -7,5 +7,5 @@ LL | async fn foo(&self) -> i32; LL | fn foo(&self) -> i32 { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/in-trait/generics-mismatch.stderr b/tests/ui/async-await/in-trait/generics-mismatch.stderr index 647cc698f9f5e..5f7aeb17117b7 100644 --- a/tests/ui/async-await/in-trait/generics-mismatch.stderr +++ b/tests/ui/async-await/in-trait/generics-mismatch.stderr @@ -11,6 +11,6 @@ LL | impl Foo for () { LL | async fn foo() {} | ^^^^^^^^^^^^^^ found const parameter of type `usize` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr index ce02c1e99675c..95731b67ccf77 100644 --- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr +++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr @@ -5,6 +5,6 @@ error[E0391]: cycle detected when computing layout of `{async fn body@$DIR/indir = note: cycle used when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:6:13: 8:6}` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.stderr b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr index 3841ab9345faf..6b8716d2a8d2c 100644 --- a/tests/ui/async-await/in-trait/lifetime-mismatch.stderr +++ b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr @@ -7,6 +7,6 @@ LL | async fn foo<'a>(&self); LL | async fn foo(&self) {} | ^ lifetimes do not match method in trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr index 139bd06c7df05..aeabb5931dfc7 100644 --- a/tests/ui/async-await/in-trait/missing-send-bound.stderr +++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr @@ -21,5 +21,5 @@ LL - async fn bar(); LL + fn bar() -> impl std::future::Future + Send; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/object-safety.stderr index 5b9fd98ac60e2..f45e6a2c8bb51 100644 --- a/tests/ui/async-await/in-trait/object-safety.stderr +++ b/tests/ui/async-await/in-trait/object-safety.stderr @@ -13,6 +13,6 @@ LL | async fn foo(&self); | ^^^ ...because method `foo` is `async` = help: consider moving `foo` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr index a66dd13bb7a12..84e0a643485f7 100644 --- a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr +++ b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Missing` in this scope LL | fn bar() -> Wrapper>; | ^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.stderr index 363870619f05d..4947b7fec9d14 100644 --- a/tests/ui/async-await/in-trait/return-type-suggestion.stderr +++ b/tests/ui/async-await/in-trait/return-type-suggestion.stderr @@ -7,6 +7,6 @@ LL | Ok(()) = note: expected unit type `()` found enum `Result<(), _>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.stderr b/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.stderr index 482707351d745..dd38e205b03f9 100644 --- a/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.stderr +++ b/tests/ui/async-await/in-trait/send-on-foreign-async-fn-in-trait.stderr @@ -18,6 +18,6 @@ note: required by a bound in `needs_send` LL | fn needs_send(_: impl Send) {} | ^^^^ required by this bound in `needs_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr index 2cb0da2e8bc01..ef7e4ef0eb85f 100644 --- a/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr +++ b/tests/ui/async-await/in-trait/unconstrained-impl-region.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a> Actor for () { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/async-await/in-trait/warn.stderr b/tests/ui/async-await/in-trait/warn.stderr index d0278628c97bc..c741a23c6d56e 100644 --- a/tests/ui/async-await/in-trait/warn.stderr +++ b/tests/ui/async-await/in-trait/warn.stderr @@ -16,5 +16,5 @@ LL - async fn not_send(); LL + fn not_send() -> impl std::future::Future + Send; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr b/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr index 5367b986d2b8d..782fa4295fd7f 100644 --- a/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr +++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr @@ -9,5 +9,5 @@ help: try switching the order LL | let _ = async move { }; | ~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-101715.stderr b/tests/ui/async-await/issue-101715.stderr index d161fb0c05e75..f6af15c00d621 100644 --- a/tests/ui/async-await/issue-101715.stderr +++ b/tests/ui/async-await/issue-101715.stderr @@ -11,6 +11,6 @@ LL | .await = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-108572.stderr b/tests/ui/async-await/issue-108572.stderr index 588669092b01c..6a80bc1491062 100644 --- a/tests/ui/async-await/issue-108572.stderr +++ b/tests/ui/async-await/issue-108572.stderr @@ -12,6 +12,6 @@ LL ~ let mut pinned = std::pin::pin!(fut); LL ~ pinned.as_mut().poll(cx); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/async-await/issue-60709.rs b/tests/ui/async-await/issue-60709.rs index 2cda40e9e11ba..c206f01b98f78 100644 --- a/tests/ui/async-await/issue-60709.rs +++ b/tests/ui/async-await/issue-60709.rs @@ -3,7 +3,6 @@ // compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018 // run-pass -// ignore-asmjs wasm2js does not support source maps yet use std::future::Future; use std::task::Poll; diff --git a/tests/ui/async-await/issue-64130-1-sync.stderr b/tests/ui/async-await/issue-64130-1-sync.stderr index 207e085d273f0..5428d7ef71b30 100644 --- a/tests/ui/async-await/issue-64130-1-sync.stderr +++ b/tests/ui/async-await/issue-64130-1-sync.stderr @@ -18,5 +18,5 @@ note: required by a bound in `is_sync` LL | fn is_sync(t: T) { } | ^^^^ required by this bound in `is_sync` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-64130-2-send.stderr b/tests/ui/async-await/issue-64130-2-send.stderr index a433c76ae7088..f05e954d2d714 100644 --- a/tests/ui/async-await/issue-64130-2-send.stderr +++ b/tests/ui/async-await/issue-64130-2-send.stderr @@ -18,5 +18,5 @@ note: required by a bound in `is_send` LL | fn is_send(t: T) { } | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-64130-3-other.stderr b/tests/ui/async-await/issue-64130-3-other.stderr index 4bbb7731b1104..3ac30bdc23e63 100644 --- a/tests/ui/async-await/issue-64130-3-other.stderr +++ b/tests/ui/async-await/issue-64130-3-other.stderr @@ -20,6 +20,6 @@ note: required by a bound in `is_qux` LL | fn is_qux(t: T) {} | ^^^ required by this bound in `is_qux` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr index cb02fcf5ce782..d28807e223bef 100644 --- a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -18,5 +18,5 @@ note: required by a bound in `is_send` LL | fn is_send(t: T) { } | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-66387-if-without-else.stderr b/tests/ui/async-await/issue-66387-if-without-else.stderr index 8155fcb56b697..17f9b88c60024 100644 --- a/tests/ui/async-await/issue-66387-if-without-else.stderr +++ b/tests/ui/async-await/issue-66387-if-without-else.stderr @@ -9,6 +9,6 @@ LL | | } = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/async-await/issue-67252-unnamed-future.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr index 069befa912162..e1c5a22967e08 100644 --- a/tests/ui/async-await/issue-67252-unnamed-future.stderr +++ b/tests/ui/async-await/issue-67252-unnamed-future.stderr @@ -18,5 +18,5 @@ note: required by a bound in `spawn` LL | fn spawn(_: T) {} | ^^^^ required by this bound in `spawn` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-67651.stderr b/tests/ui/async-await/issue-67651.stderr index 89017f6cc3ec6..9047fa4f3feee 100644 --- a/tests/ui/async-await/issue-67651.stderr +++ b/tests/ui/async-await/issue-67651.stderr @@ -7,6 +7,6 @@ LL | impl From for () { LL | impl From for () { | ^^^^^^^^^^^^^^^^ conflicting implementation for `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/async-await/issue-67765-async-diagnostic.stderr b/tests/ui/async-await/issue-67765-async-diagnostic.stderr index 492e06fbbc06c..833df51a7aac8 100644 --- a/tests/ui/async-await/issue-67765-async-diagnostic.stderr +++ b/tests/ui/async-await/issue-67765-async-diagnostic.stderr @@ -7,6 +7,6 @@ LL | LL | Err(b)?; | ^^^^^^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/async-await/issue-68523-start.stderr b/tests/ui/async-await/issue-68523-start.stderr index 7c06fe3400ee0..5b76ab56e2459 100644 --- a/tests/ui/async-await/issue-68523-start.stderr +++ b/tests/ui/async-await/issue-68523-start.stderr @@ -4,6 +4,6 @@ error[E0752]: `#[start]` function is not allowed to be `async` LL | pub async fn start(_: isize, _: *const *const u8) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `#[start]` is not allowed to be `async` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0752`. diff --git a/tests/ui/async-await/issue-68523.stderr b/tests/ui/async-await/issue-68523.stderr index dfdf078e30351..ec3e2e96231f4 100644 --- a/tests/ui/async-await/issue-68523.stderr +++ b/tests/ui/async-await/issue-68523.stderr @@ -4,6 +4,6 @@ error[E0752]: `main` function is not allowed to be `async` LL | async fn main() -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0752`. diff --git a/tests/ui/async-await/issue-69446-fnmut-capture.stderr b/tests/ui/async-await/issue-69446-fnmut-capture.stderr index 3d2b0402bc52c..0366c2f44c0e7 100644 --- a/tests/ui/async-await/issue-69446-fnmut-capture.stderr +++ b/tests/ui/async-await/issue-69446-fnmut-capture.stderr @@ -15,5 +15,5 @@ LL | | }); = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-70594.rs b/tests/ui/async-await/issue-70594.rs index 9e7c5847b3b2e..4c8209348b37a 100644 --- a/tests/ui/async-await/issue-70594.rs +++ b/tests/ui/async-await/issue-70594.rs @@ -3,9 +3,6 @@ async fn fun() { [1; ().await]; //~^ error: `await` is only allowed inside `async` functions and blocks - //~| error: `.await` is not allowed in a `const` - //~| error: `.await` is not allowed in a `const` - //~| error: `()` is not a future } fn main() {} diff --git a/tests/ui/async-await/issue-70594.stderr b/tests/ui/async-await/issue-70594.stderr index 9866e00bb83a9..aed99ec3f1f08 100644 --- a/tests/ui/async-await/issue-70594.stderr +++ b/tests/ui/async-await/issue-70594.stderr @@ -1,37 +1,12 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-70594.rs:4:12 | -LL | async fn fun() { - | --- this is not `async` LL | [1; ().await]; - | ^^^^^ only allowed inside `async` functions and blocks + | ---^^^^^ + | | | + | | only allowed inside `async` functions and blocks + | this is not `async` -error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:9 - | -LL | [1; ().await]; - | ^^^^^^^^ - -error[E0744]: `.await` is not allowed in a `const` - --> $DIR/issue-70594.rs:4:12 - | -LL | [1; ().await]; - | ^^^^^ - -error[E0277]: `()` is not a future - --> $DIR/issue-70594.rs:4:12 - | -LL | [1; ().await]; - | -^^^^^ - | || - | |`()` is not a future - | help: remove the `.await` - | - = help: the trait `Future` is not implemented for `()` - = note: () must be a future or must implement `IntoFuture` to be awaited - = note: required for `()` to implement `IntoFuture` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0728, E0744. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr index 20109d4d1166a..317c04d2c7478 100644 --- a/tests/ui/async-await/issue-70818.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -14,5 +14,5 @@ help: consider restricting type parameter `U` LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index d0605d7e1a6f2..14ef1cbb67c50 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -36,6 +36,6 @@ LL | | }).await; LL | | } | |_____^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-71137.stderr b/tests/ui/async-await/issue-71137.stderr index 443af010c4a1a..8739c22a31048 100644 --- a/tests/ui/async-await/issue-71137.stderr +++ b/tests/ui/async-await/issue-71137.stderr @@ -18,5 +18,5 @@ note: required by a bound in `fake_spawn` LL | fn fake_spawn(f: F) { } | ^^^^ required by this bound in `fake_spawn` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-72442.stderr b/tests/ui/async-await/issue-72442.stderr index 4a1705715cacc..313f6079c7c16 100644 --- a/tests/ui/async-await/issue-72442.stderr +++ b/tests/ui/async-await/issue-72442.stderr @@ -9,6 +9,6 @@ LL | let mut f = File::open(path.to_str())?; note: required by a bound in `File::open` --> $SRC_DIR/std/src/fs.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-73541-1.stderr b/tests/ui/async-await/issue-73541-1.stderr index 80c1fdf002a83..3fd60223542bb 100644 --- a/tests/ui/async-await/issue-73541-1.stderr +++ b/tests/ui/async-await/issue-73541-1.stderr @@ -9,6 +9,6 @@ LL | continue 'a | = note: labels are unreachable through functions, closures, async blocks and modules -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0767`. diff --git a/tests/ui/async-await/issue-73541-2.stderr b/tests/ui/async-await/issue-73541-2.stderr index 4c9741f6f37a0..584b71ce643f5 100644 --- a/tests/ui/async-await/issue-73541-2.stderr +++ b/tests/ui/async-await/issue-73541-2.stderr @@ -13,6 +13,6 @@ LL | b!(); = note: labels are unreachable through functions, closures, async blocks and modules = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0767`. diff --git a/tests/ui/async-await/issue-73541-3.stderr b/tests/ui/async-await/issue-73541-3.stderr index 53487aaca998c..baa41c2e82225 100644 --- a/tests/ui/async-await/issue-73541-3.stderr +++ b/tests/ui/async-await/issue-73541-3.stderr @@ -7,6 +7,6 @@ LL | || { LL | loop { continue 'aaaaaa } | ^^^^^^^ undeclared label `'aaaaaa` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/async-await/issue-73541.stderr b/tests/ui/async-await/issue-73541.stderr index 4bb466ff16c58..6c3aac5ed3ba5 100644 --- a/tests/ui/async-await/issue-73541.stderr +++ b/tests/ui/async-await/issue-73541.stderr @@ -9,6 +9,6 @@ LL | loop { continue 'a } | = note: labels are unreachable through functions, closures, async blocks and modules -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0767`. diff --git a/tests/ui/async-await/issue-73741-type-err.stderr b/tests/ui/async-await/issue-73741-type-err.stderr index 0b5343a98cfb4..9fafdb1ed3917 100644 --- a/tests/ui/async-await/issue-73741-type-err.stderr +++ b/tests/ui/async-await/issue-73741-type-err.stderr @@ -6,6 +6,6 @@ LL | 1 = 2; | | | cannot assign to this expression -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/async-await/issue-74047.stderr b/tests/ui/async-await/issue-74047.stderr index 6bdb9ded48276..c2dfa050fc2ed 100644 --- a/tests/ui/async-await/issue-74047.stderr +++ b/tests/ui/async-await/issue-74047.stderr @@ -7,6 +7,6 @@ LL | impl TryFrom for MyStream {} = help: implement the missing item: `type Error = /* Type */;` = help: implement the missing item: `fn try_from(_: OtherStream) -> Result>::Error> { todo!() }` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr b/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr index 4427014ae3bf9..1bdd6423e78ff 100644 --- a/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr +++ b/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr @@ -7,5 +7,5 @@ LL | let _ = foo(|x| bar(x)); | |return type of closure `impl Future` contains a lifetime `'2` | has type `&'1 u8` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-75785-confusing-named-region.stderr b/tests/ui/async-await/issue-75785-confusing-named-region.stderr index b69033a0eda0b..c7316b971f5a3 100644 --- a/tests/ui/async-await/issue-75785-confusing-named-region.stderr +++ b/tests/ui/async-await/issue-75785-confusing-named-region.stderr @@ -10,6 +10,6 @@ LL | *x += 1; LL | (&32, y) | -------- returning this value requires that `*x` is borrowed for `'1` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/async-await/issue-77993-2.stderr b/tests/ui/async-await/issue-77993-2.stderr index 64b378f83fc03..6c3ca750e0ee7 100644 --- a/tests/ui/async-await/issue-77993-2.stderr +++ b/tests/ui/async-await/issue-77993-2.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `!` LL | macro!(); | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr index d5a3f72cf251f..0398e57ef780f 100644 --- a/tests/ui/async-await/issue-86507.stderr +++ b/tests/ui/async-await/issue-86507.stderr @@ -19,5 +19,5 @@ help: consider further restricting this bound LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issues/issue-102206.stderr b/tests/ui/async-await/issues/issue-102206.stderr index cd84505680514..19c70e8743a17 100644 --- a/tests/ui/async-await/issues/issue-102206.stderr +++ b/tests/ui/async-await/issues/issue-102206.stderr @@ -13,6 +13,6 @@ help: consider borrowing here LL | std::mem::size_of_val(&foo()); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/issues/issue-107280.stderr b/tests/ui/async-await/issues/issue-107280.stderr index c5fd5c5bf0a03..d1d80ce038ceb 100644 --- a/tests/ui/async-await/issues/issue-107280.stderr +++ b/tests/ui/async-await/issues/issue-107280.stderr @@ -16,6 +16,6 @@ help: add missing generic argument LL | inner::().await | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/async-await/issues/issue-112225-2.stderr b/tests/ui/async-await/issues/issue-112225-2.stderr index 5926a4f3995ad..c44ad583d9237 100644 --- a/tests/ui/async-await/issues/issue-112225-2.stderr +++ b/tests/ui/async-await/issues/issue-112225-2.stderr @@ -12,6 +12,6 @@ help: consider giving `x` an explicit type LL | let x: /* Type */ = Default::default(); | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/async-await/issues/issue-51719.stderr b/tests/ui/async-await/issues/issue-51719.stderr index 19cc339ec0a07..3fa5c738c0116 100644 --- a/tests/ui/async-await/issues/issue-51719.stderr +++ b/tests/ui/async-await/issues/issue-51719.stderr @@ -6,6 +6,6 @@ LL | let _gen = || foo().await; | | | this is not `async` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-51751.stderr b/tests/ui/async-await/issues/issue-51751.stderr index 6dd3726608ba8..ba256b19948c0 100644 --- a/tests/ui/async-await/issues/issue-51751.stderr +++ b/tests/ui/async-await/issues/issue-51751.stderr @@ -7,6 +7,6 @@ LL | let result = inc(10000); LL | let finished = result.await; | ^^^^^ only allowed inside `async` functions and blocks -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-61187.stderr b/tests/ui/async-await/issues/issue-61187.stderr index 203b17550a0b6..59c6a4e493af0 100644 --- a/tests/ui/async-await/issues/issue-61187.stderr +++ b/tests/ui/async-await/issues/issue-61187.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | async fn response(mut data: Vec) { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/async-await/issues/issue-62009-1.rs b/tests/ui/async-await/issues/issue-62009-1.rs index 40ccf25712e2b..51d216408d7ee 100644 --- a/tests/ui/async-await/issues/issue-62009-1.rs +++ b/tests/ui/async-await/issues/issue-62009-1.rs @@ -11,5 +11,4 @@ fn main() { //~^ ERROR `await` is only allowed inside `async` functions and blocks (|_| 2333).await; //~^ ERROR `await` is only allowed inside `async` functions and blocks - //~| ERROR is not a future } diff --git a/tests/ui/async-await/issues/issue-62009-1.stderr b/tests/ui/async-await/issues/issue-62009-1.stderr index bb617d09076f0..02933f4f2f233 100644 --- a/tests/ui/async-await/issues/issue-62009-1.stderr +++ b/tests/ui/async-await/issues/issue-62009-1.stderr @@ -24,20 +24,6 @@ LL | fn main() { LL | (|_| 2333).await; | ^^^^^ only allowed inside `async` functions and blocks -error[E0277]: `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future - --> $DIR/issue-62009-1.rs:12:16 - | -LL | (|_| 2333).await; - | -^^^^^ - | || - | |`{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` is not a future - | help: remove the `.await` - | - = help: the trait `Future` is not implemented for closure `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` - = note: {closure@$DIR/issue-62009-1.rs:12:6: 12:9} must be a future or must implement `IntoFuture` to be awaited - = note: required for `{closure@$DIR/issue-62009-1.rs:12:6: 12:9}` to implement `IntoFuture` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0728. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-62009-2.stderr b/tests/ui/async-await/issues/issue-62009-2.stderr index 9c2f20df6576f..80a831cc5475f 100644 --- a/tests/ui/async-await/issues/issue-62009-2.stderr +++ b/tests/ui/async-await/issues/issue-62009-2.stderr @@ -6,6 +6,6 @@ LL | fn main() { LL | (async || 2333)().await; | ^^^^^ only allowed inside `async` functions and blocks -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index 88542315ec00c..f7f285ad0ccda 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -10,6 +10,6 @@ LL | | foo LL | | } | |_____^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/async-await/issues/issue-65159.stderr b/tests/ui/async-await/issues/issue-65159.stderr index b8741333c3283..19512116a66cd 100644 --- a/tests/ui/async-await/issues/issue-65159.stderr +++ b/tests/ui/async-await/issues/issue-65159.stderr @@ -11,6 +11,6 @@ help: add missing generic argument LL | async fn copy() -> Result<(), E> | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr index e2a73539874e0..3fb504a0e3ada 100644 --- a/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr +++ b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr @@ -8,6 +8,6 @@ LL | Self::full(self); | = note: partial move occurs because `self.0` has type `S`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr index 2a712aee9c481..90c1e976dcee6 100644 --- a/tests/ui/async-await/issues/issue-67893.stderr +++ b/tests/ui/async-await/issues/issue-67893.stderr @@ -28,6 +28,6 @@ note: required by a bound in `g` LL | fn g(_: impl Send) {} | ^^^^ required by this bound in `g` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr index 679272858bdee..cd93f8a3c5597 100644 --- a/tests/ui/async-await/issues/issue-72312.stderr +++ b/tests/ui/async-await/issues/issue-72312.stderr @@ -18,6 +18,6 @@ LL | | }); | |__________`self` escapes the method body here | argument requires that `'1` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/async-await/issues/issue-78938-async-block.stderr b/tests/ui/async-await/issues/issue-78938-async-block.stderr index c1a4b467f104e..dc373a24f6f52 100644 --- a/tests/ui/async-await/issues/issue-78938-async-block.stderr +++ b/tests/ui/async-await/issues/issue-78938-async-block.stderr @@ -14,6 +14,6 @@ help: to force the async block to take ownership of `room_ref` (and any other re LL | let gameloop_handle = spawn(async move { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/issues/non-async-enclosing-span.stderr b/tests/ui/async-await/issues/non-async-enclosing-span.stderr index b6583022c161a..91a9e5aa6cabf 100644 --- a/tests/ui/async-await/issues/non-async-enclosing-span.stderr +++ b/tests/ui/async-await/issues/non-async-enclosing-span.stderr @@ -7,6 +7,6 @@ LL | let x = move || {}; LL | let y = do_the_thing().await; | ^^^^^ only allowed inside `async` functions and blocks -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/no-async-const.rs b/tests/ui/async-await/no-async-const.rs index 963460c118249..c9941d1c5a00a 100644 --- a/tests/ui/async-await/no-async-const.rs +++ b/tests/ui/async-await/no-async-const.rs @@ -3,3 +3,4 @@ pub async const fn x() {} //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` +//~| ERROR functions cannot be both `const` and `async` diff --git a/tests/ui/async-await/no-async-const.stderr b/tests/ui/async-await/no-async-const.stderr index a51dc88a4eded..524d778c09b85 100644 --- a/tests/ui/async-await/no-async-const.stderr +++ b/tests/ui/async-await/no-async-const.stderr @@ -9,5 +9,14 @@ LL | pub async const fn x() {} | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` -error: aborting due to previous error +error: functions cannot be both `const` and `async` + --> $DIR/no-async-const.rs:4:5 + | +LL | pub async const fn x() {} + | ----^^^^^-^^^^^---------- + | | | + | | `const` because of this + | `async` because of this + +error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/no-const-async.stderr b/tests/ui/async-await/no-const-async.stderr index 90ec646c8c09c..29095f3c4d2aa 100644 --- a/tests/ui/async-await/no-const-async.stderr +++ b/tests/ui/async-await/no-const-async.stderr @@ -7,5 +7,5 @@ LL | pub const async fn x() {} | | `async` because of this | `const` because of this -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/no-move-across-await-struct.stderr b/tests/ui/async-await/no-move-across-await-struct.stderr index 4eaed1cf155e9..ddc9bde59adff 100644 --- a/tests/ui/async-await/no-move-across-await-struct.stderr +++ b/tests/ui/async-await/no-move-across-await-struct.stderr @@ -8,6 +8,6 @@ LL | s.x | = note: move occurs because `s.x` has type `Vec`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/no-move-across-await-tuple.stderr b/tests/ui/async-await/no-move-across-await-tuple.stderr index d750df9918ee0..61b492fe98950 100644 --- a/tests/ui/async-await/no-move-across-await-tuple.stderr +++ b/tests/ui/async-await/no-move-across-await-tuple.stderr @@ -9,6 +9,6 @@ LL | x.1 | = note: move occurs because `x.1` has type `Vec`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/no-non-guaranteed-initialization.stderr b/tests/ui/async-await/no-non-guaranteed-initialization.stderr index 12c15bf56ce22..7adccdba2f87c 100644 --- a/tests/ui/async-await/no-non-guaranteed-initialization.stderr +++ b/tests/ui/async-await/no-non-guaranteed-initialization.stderr @@ -11,6 +11,6 @@ LL | } LL | y | ^ `y` used here but it is possibly-uninitialized -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/async-await/no-params-non-move-async-closure.stderr b/tests/ui/async-await/no-params-non-move-async-closure.stderr index 1f589c516a90b..d265955369900 100644 --- a/tests/ui/async-await/no-params-non-move-async-closure.stderr +++ b/tests/ui/async-await/no-params-non-move-async-closure.stderr @@ -6,6 +6,6 @@ LL | let _ = async |x: u8| {}; | = help: consider using `let` statements to manually capture variables by reference before entering an `async move` closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0708`. diff --git a/tests/ui/async-await/no-unsafe-async.rs b/tests/ui/async-await/no-unsafe-async.rs index f40154e16f34e..7c6811d81eeae 100644 --- a/tests/ui/async-await/no-unsafe-async.rs +++ b/tests/ui/async-await/no-unsafe-async.rs @@ -9,3 +9,5 @@ impl S { #[cfg(FALSE)] unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` + +fn main() {} diff --git a/tests/ui/async-await/no-unsafe-async.stderr b/tests/ui/async-await/no-unsafe-async.stderr index f23d17d6bfa57..49b112f9313d4 100644 --- a/tests/ui/async-await/no-unsafe-async.stderr +++ b/tests/ui/async-await/no-unsafe-async.stderr @@ -1,16 +1,11 @@ error: expected one of `extern` or `fn`, found keyword `async` --> $DIR/no-unsafe-async.rs:7:12 | -LL | impl S { - | - while parsing this item list starting here -LL | #[cfg(FALSE)] LL | unsafe async fn g() {} | -------^^^^^ | | | | | expected one of `extern` or `fn` | help: `async` must come before `unsafe`: `async unsafe` -LL | } - | - the item list ends here | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` diff --git a/tests/ui/async-await/partial-drop-partial-reinit.stderr b/tests/ui/async-await/partial-drop-partial-reinit.stderr index 310a292395571..f088b118730aa 100644 --- a/tests/ui/async-await/partial-drop-partial-reinit.stderr +++ b/tests/ui/async-await/partial-drop-partial-reinit.stderr @@ -30,6 +30,6 @@ note: required by a bound in `gimme_send` LL | fn gimme_send(t: T) { | ^^^^ required by this bound in `gimme_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr index 61126faf89926..9c1ad32cc2ce9 100644 --- a/tests/ui/async-await/pin-needed-to-poll-2.stderr +++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr @@ -16,6 +16,6 @@ LL | struct Sleep(std::marker::PhantomPinned); note: required by a bound in `Pin::

    ::new` --> $SRC_DIR/core/src/pin.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/pin-needed-to-poll.stderr b/tests/ui/async-await/pin-needed-to-poll.stderr index 964709daeda2d..e576cd6c7a429 100644 --- a/tests/ui/async-await/pin-needed-to-poll.stderr +++ b/tests/ui/async-await/pin-needed-to-poll.stderr @@ -13,6 +13,6 @@ LL ~ let mut pinned = std::pin::pin!(self.sleep); LL ~ pinned.as_mut().poll(cx) | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/async-await/proper-span-for-type-error.stderr b/tests/ui/async-await/proper-span-for-type-error.stderr index 592ef7faf8137..2c72a8eb5f643 100644 --- a/tests/ui/async-await/proper-span-for-type-error.stderr +++ b/tests/ui/async-await/proper-span-for-type-error.stderr @@ -12,6 +12,6 @@ LL ~ a().await; LL ~ Ok(()) | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.stderr index 64917329c499f..969258f84ed67 100644 --- a/tests/ui/async-await/recursive-async-impl-trait-type.stderr +++ b/tests/ui/async-await/recursive-async-impl-trait-type.stderr @@ -7,6 +7,6 @@ LL | async fn recursive_async_function() -> () { = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr index 6a47f1ab98327..d2db6abe3132c 100644 --- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr @@ -30,6 +30,6 @@ note: required by a bound in `build` LL | fn build(_: T) where T: Foo {} | ^^^^ required by this bound in `build` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr index 52d8168c9d836..4321d876e163c 100644 --- a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr +++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr @@ -13,6 +13,6 @@ error[E0229]: associated type bindings are not allowed here LL | impl Super1<'_, bar(): Send> for () {} | ^^^^^^^^^^^ associated type not allowed here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs index 891b30638ee52..73c085315990c 100644 --- a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs +++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs @@ -23,7 +23,7 @@ impl Foo for () {} fn test() where T: Foo, - //~^ ERROR ambiguous associated function `test` for `Foo` + //~^ ERROR ambiguous associated function `test` in bounds of `Foo` { } diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr index d9caab5875a78..4003aad6d03c3 100644 --- a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr +++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr @@ -7,13 +7,18 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -error: ambiguous associated function `test` for `Foo` +error[E0221]: ambiguous associated function `test` in bounds of `Foo` --> $DIR/super-method-bound-ambig.rs:25:12 | +LL | async fn test(); + | ---------------- ambiguous `test` from `for<'a> Super1<'a>` +... +LL | async fn test(); + | ---------------- ambiguous `test` from `Super2` +... LL | T: Foo, - | ^^^^^^^^^^^^ - | - = note: `test` is declared in two supertraits: `Super2` and `Super1<'a>` + | ^^^^^^^^^^^^ ambiguous associated function `test` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0221`. diff --git a/tests/ui/async-await/suggest-missing-await-closure.stderr b/tests/ui/async-await/suggest-missing-await-closure.stderr index d44af5b8dd832..47af270a03a82 100644 --- a/tests/ui/async-await/suggest-missing-await-closure.stderr +++ b/tests/ui/async-await/suggest-missing-await-closure.stderr @@ -21,6 +21,6 @@ help: consider `await`ing on the `Future` LL | take_u32(x.await) | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs index 4919e0a051dcb..4a3195174df49 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs +++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs @@ -23,6 +23,7 @@ fn await_on_struct_similar() { let x = S { awai: 42 }; x.await; //~^ ERROR no field `await` on type + //~| NOTE unknown field //~| HELP a field with a similar name exists //~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| HELP set `edition = "2021"` in `Cargo.toml` @@ -41,6 +42,7 @@ fn await_on_63533(x: Pin<&mut dyn Future>) { fn await_on_apit(x: impl Future) { x.await; //~^ ERROR no field `await` on type + //~| NOTE unknown field //~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| HELP set `edition = "2021"` in `Cargo.toml` //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr index 409eb179e83a0..dd863ca541c9e 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr @@ -12,14 +12,18 @@ error[E0609]: no field `await` on type `await_on_struct_similar::S` --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7 | LL | x.await; - | ^^^^^ help: a field with a similar name exists: `awai` + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: set `edition = "2021"` in `Cargo.toml` = note: for more on editions, read https://doc.rust-lang.org/edition-guide +help: a field with a similar name exists + | +LL | x.awai; + | ~~~~ error[E0609]: no field `await` on type `Pin<&mut dyn Future>` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:33:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:34:7 | LL | x.await; | ^^^^^ unknown field @@ -29,10 +33,10 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0609]: no field `await` on type `impl Future` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:42:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:43:7 | LL | x.await; - | ^^^^^ + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: set `edition = "2021"` in `Cargo.toml` diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.rs b/tests/ui/async-await/suggest-switching-edition-on-await.rs index 9852e8fc918fe..10e245796ee3c 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.rs +++ b/tests/ui/async-await/suggest-switching-edition-on-await.rs @@ -21,6 +21,7 @@ fn await_on_struct_similar() { let x = S { awai: 42 }; x.await; //~^ ERROR no field `await` on type + //~| NOTE unknown field //~| HELP a field with a similar name exists //~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| HELP pass `--edition 2021` to `rustc` @@ -39,6 +40,7 @@ fn await_on_63533(x: Pin<&mut dyn Future>) { fn await_on_apit(x: impl Future) { x.await; //~^ ERROR no field `await` on type + //~| NOTE unknown field //~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| HELP pass `--edition 2021` to `rustc` //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.stderr b/tests/ui/async-await/suggest-switching-edition-on-await.stderr index ef3334381b715..0ed256b059ffe 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr @@ -12,14 +12,18 @@ error[E0609]: no field `await` on type `await_on_struct_similar::S` --> $DIR/suggest-switching-edition-on-await.rs:22:7 | LL | x.await; - | ^^^^^ help: a field with a similar name exists: `awai` + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide +help: a field with a similar name exists + | +LL | x.awai; + | ~~~~ error[E0609]: no field `await` on type `Pin<&mut dyn Future>` - --> $DIR/suggest-switching-edition-on-await.rs:31:7 + --> $DIR/suggest-switching-edition-on-await.rs:32:7 | LL | x.await; | ^^^^^ unknown field @@ -29,10 +33,10 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0609]: no field `await` on type `impl Future` - --> $DIR/suggest-switching-edition-on-await.rs:40:7 + --> $DIR/suggest-switching-edition-on-await.rs:41:7 | LL | x.await; - | ^^^^^ + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: pass `--edition 2021` to `rustc` diff --git a/tests/ui/async-await/unreachable-lint-1.stderr b/tests/ui/async-await/unreachable-lint-1.stderr index e9325788961b2..061cc7246a71c 100644 --- a/tests/ui/async-await/unreachable-lint-1.stderr +++ b/tests/ui/async-await/unreachable-lint-1.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/unresolved_type_param.stderr b/tests/ui/async-await/unresolved_type_param.stderr index 45aa766065e46..b9fb9832086cd 100644 --- a/tests/ui/async-await/unresolved_type_param.stderr +++ b/tests/ui/async-await/unresolved_type_param.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | bar::().await; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/async-await/unsized-across-await.stderr b/tests/ui/async-await/unsized-across-await.stderr index 649b12ce5a5bb..5bb2b7f479177 100644 --- a/tests/ui/async-await/unsized-across-await.stderr +++ b/tests/ui/async-await/unsized-across-await.stderr @@ -16,6 +16,6 @@ LL | let _x = *x; = help: the trait `Sized` is not implemented for `dyn std::fmt::Display` = note: all values live across `await` must have a statically known size -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/atomic-from-mut-not-available.stderr b/tests/ui/atomic-from-mut-not-available.stderr index d1ebca8a29e93..a3edf18935603 100644 --- a/tests/ui/atomic-from-mut-not-available.stderr +++ b/tests/ui/atomic-from-mut-not-available.stderr @@ -3,7 +3,11 @@ error[E0599]: no function or associated item named `from_mut` found for struct ` | LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64); | ^^^^^^^^ function or associated item not found in `AtomicU64` + | +note: if you're trying to build a new `AtomicU64`, consider using `AtomicU64::new` which returns `AtomicU64` + --> $SRC_DIR/core/src/sync/atomic.rs:LL:COL + = note: this error originates in the macro `atomic_int` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/attr-bad-crate-attr.stderr b/tests/ui/attr-bad-crate-attr.stderr index ff420eeea4a06..9df991f71b3fb 100644 --- a/tests/ui/attr-bad-crate-attr.stderr +++ b/tests/ui/attr-bad-crate-attr.stderr @@ -4,5 +4,5 @@ error: expected item after attributes LL | #[attr = "val"] // Unterminated | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/attr-eq-token-tree.stderr b/tests/ui/attributes/attr-eq-token-tree.stderr index 1846444b668f4..d642e168e18fc 100644 --- a/tests/ui/attributes/attr-eq-token-tree.stderr +++ b/tests/ui/attributes/attr-eq-token-tree.stderr @@ -4,5 +4,5 @@ error: expected expression, found `]` LL | #[my_attr = !] | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-1.stderr b/tests/ui/attributes/attrs-with-no-formal-in-generics-1.stderr index 5b4f5222a2b14..6377d27f49360 100644 --- a/tests/ui/attributes/attrs-with-no-formal-in-generics-1.stderr +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-1.stderr @@ -4,5 +4,5 @@ error: trailing attribute after generic parameter LL | impl<#[rustc_dummy] 'a, 'b, #[oops]> RefIntPair<'a, 'b> { | ^^^^^^^ attributes must go before parameters -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-2.stderr b/tests/ui/attributes/attrs-with-no-formal-in-generics-2.stderr index fce3ff7de78e8..3224da58a85f2 100644 --- a/tests/ui/attributes/attrs-with-no-formal-in-generics-2.stderr +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-2.stderr @@ -4,5 +4,5 @@ error: trailing attribute after generic parameter LL | impl<#[rustc_dummy] 'a, #[rustc_dummy] T, #[oops]> RefAny<'a, T> {} | ^^^^^^^ attributes must go before parameters -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-3.stderr b/tests/ui/attributes/attrs-with-no-formal-in-generics-3.stderr index b9ca00974677b..996df10a721e6 100644 --- a/tests/ui/attributes/attrs-with-no-formal-in-generics-3.stderr +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-3.stderr @@ -4,5 +4,5 @@ error: trailing attribute after generic parameter LL | where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 | ^^^^^^^ attributes must go before parameters -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/doc-test-literal.stderr b/tests/ui/attributes/doc-test-literal.stderr index ebee09994ba9f..ed2964825c7a8 100644 --- a/tests/ui/attributes/doc-test-literal.stderr +++ b/tests/ui/attributes/doc-test-literal.stderr @@ -13,5 +13,5 @@ LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/extented-attribute-macro-error.stderr b/tests/ui/attributes/extented-attribute-macro-error.stderr index 0fcde9b7cc69f..884f3c7b16657 100644 --- a/tests/ui/attributes/extented-attribute-macro-error.stderr +++ b/tests/ui/attributes/extented-attribute-macro-error.stderr @@ -6,5 +6,5 @@ LL | #![doc = include_str!("../not_existing_file.md")] | = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/invalid-repr.stderr b/tests/ui/attributes/invalid-repr.stderr index 98a6a24b3c42c..681460ad0812f 100644 --- a/tests/ui/attributes/invalid-repr.stderr +++ b/tests/ui/attributes/invalid-repr.stderr @@ -7,6 +7,6 @@ LL | LL | pub type Foo = i32; | ------------------- not a struct, enum, function, associated function, or union -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/attributes/issue-100631.stderr b/tests/ui/attributes/issue-100631.stderr index caa5351ddc7aa..6e8e4f3b418fb 100644 --- a/tests/ui/attributes/issue-100631.stderr +++ b/tests/ui/attributes/issue-100631.stderr @@ -7,6 +7,6 @@ LL | #[repr(C)] LL | enum Foo {} | -------- zero-variant enum -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0084`. diff --git a/tests/ui/attributes/key-value-expansion-on-mac.stderr b/tests/ui/attributes/key-value-expansion-on-mac.stderr index 64ab892d99727..7d817da13626d 100644 --- a/tests/ui/attributes/key-value-expansion-on-mac.stderr +++ b/tests/ui/attributes/key-value-expansion-on-mac.stderr @@ -4,5 +4,5 @@ error: unexpected expression: `stringify!(b)` LL | #[rustc_dummy = stringify!(b)] | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/key-value-non-ascii.stderr b/tests/ui/attributes/key-value-non-ascii.stderr index 23d482de6a868..cc01bc46ebd29 100644 --- a/tests/ui/attributes/key-value-non-ascii.stderr +++ b/tests/ui/attributes/key-value-non-ascii.stderr @@ -9,5 +9,5 @@ help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes LL | #[rustc_dummy = b"/xEF/xAC/x83.rs"] | ~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/macro_export_on_decl_macro.stderr b/tests/ui/attributes/macro_export_on_decl_macro.stderr index 565e07919bc2c..10b86da4fd9eb 100644 --- a/tests/ui/attributes/macro_export_on_decl_macro.stderr +++ b/tests/ui/attributes/macro_export_on_decl_macro.stderr @@ -12,5 +12,5 @@ LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/main-removed-1.stderr b/tests/ui/attributes/main-removed-1.stderr index 2422c5c3b6239..fda28772e429b 100644 --- a/tests/ui/attributes/main-removed-1.stderr +++ b/tests/ui/attributes/main-removed-1.stderr @@ -6,5 +6,5 @@ LL | #[main] | = note: `main` is in scope, but it is a function, not an attribute -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/no-mangle-closure.stderr b/tests/ui/attributes/no-mangle-closure.stderr index 949eb70510e4d..c183783493bdb 100644 --- a/tests/ui/attributes/no-mangle-closure.stderr +++ b/tests/ui/attributes/no-mangle-closure.stderr @@ -4,5 +4,5 @@ error: `#[no_mangle]` cannot be used on a closure as it has no name LL | (#[no_mangle] || y.0[0])() | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr index 225b8e8f32fb0..1666f4a3ee81c 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr @@ -13,5 +13,5 @@ LL - #![unix_sigpipe = "inherit"] LL + #[unix_sigpipe = "inherit"] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr index 2362c17a09041..931aae96b0ff7 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr @@ -10,5 +10,5 @@ note: attribute also specified here LL | #[unix_sigpipe = "sig_ign"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr index 59a87e139181b..b1d79d7c2a2eb 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr @@ -11,5 +11,5 @@ LL | #[unix_sigpipe = "inherit|sig_ign|sig_dfl"] LL | #[unix_sigpipe] | ~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr index c4b81118c9f01..124141b655218 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr @@ -4,5 +4,5 @@ error: `unix_sigpipe` attribute can only be used on `fn main()` LL | #[unix_sigpipe = "inherit"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr index a04f605edc2e4..346d83fa66458 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr @@ -4,5 +4,5 @@ error: `unix_sigpipe` attribute can only be used on root `fn main()` LL | #[unix_sigpipe = "inherit"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr index 2c9ce479b6caf..9f691e396bdaf 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr @@ -4,5 +4,5 @@ error: `unix_sigpipe` attribute can only be used on `fn main()` LL | #[unix_sigpipe = "inherit"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr index c56ee60bb2e69..d5eec9424c82c 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr @@ -4,5 +4,5 @@ error: `unix_sigpipe` attribute can only be used on `fn main()` LL | #[unix_sigpipe = "inherit"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr index a66e45aa2104b..d750443e4a984 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr @@ -4,5 +4,5 @@ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or ` LL | #[unix_sigpipe = "wrong"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe.stderr index 1b1eda825aaea..b18ec9abc3745 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe.stderr @@ -4,5 +4,5 @@ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or ` LL | #[unix_sigpipe] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/attributes/used_with_multi_args.stderr b/tests/ui/attributes/used_with_multi_args.stderr index c93aafcfc7cce..d4417a202d5fe 100644 --- a/tests/ui/attributes/used_with_multi_args.stderr +++ b/tests/ui/attributes/used_with_multi_args.stderr @@ -4,5 +4,5 @@ error: expected `used`, `used(compiler)` or `used(linker)` LL | #[used(compiler, linker)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/auto-traits/bad-generics-on-dyn.stderr b/tests/ui/auto-traits/bad-generics-on-dyn.stderr index ade69ced6060d..06c7cbcd76da6 100644 --- a/tests/ui/auto-traits/bad-generics-on-dyn.stderr +++ b/tests/ui/auto-traits/bad-generics-on-dyn.stderr @@ -6,6 +6,6 @@ LL | auto trait Trait1<'a> {} | | | auto trait cannot have generic parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0567`. diff --git a/tests/ui/auto-traits/has-arguments.rs b/tests/ui/auto-traits/has-arguments.rs new file mode 100644 index 0000000000000..f579eb6772d44 --- /dev/null +++ b/tests/ui/auto-traits/has-arguments.rs @@ -0,0 +1,10 @@ +#![feature(auto_traits)] + +auto trait Trait1<'outer> {} +//~^ ERROR auto traits cannot have generic parameters + +fn f<'a>(x: impl Trait1<'a>) {} + +fn main() { + f(""); +} diff --git a/tests/ui/auto-traits/has-arguments.stderr b/tests/ui/auto-traits/has-arguments.stderr new file mode 100644 index 0000000000000..b8a680e6a5cad --- /dev/null +++ b/tests/ui/auto-traits/has-arguments.stderr @@ -0,0 +1,11 @@ +error[E0567]: auto traits cannot have generic parameters + --> $DIR/has-arguments.rs:3:18 + | +LL | auto trait Trait1<'outer> {} + | ------^^^^^^^^ help: remove the parameters + | | + | auto trait cannot have generic parameters + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0567`. diff --git a/tests/ui/auto-traits/issue-117789.rs b/tests/ui/auto-traits/issue-117789.rs new file mode 100644 index 0000000000000..0c30931a1b508 --- /dev/null +++ b/tests/ui/auto-traits/issue-117789.rs @@ -0,0 +1,7 @@ +#![deny(suspicious_auto_trait_impls)] + +auto trait Trait

    {} //~ ERROR auto traits cannot have generic parameters +//~^ ERROR auto traits are experimental and possibly buggy +impl

    Trait

    for () {} + +fn main() {} diff --git a/tests/ui/auto-traits/issue-117789.stderr b/tests/ui/auto-traits/issue-117789.stderr new file mode 100644 index 0000000000000..9a3a7efed3e1e --- /dev/null +++ b/tests/ui/auto-traits/issue-117789.stderr @@ -0,0 +1,21 @@ +error[E0567]: auto traits cannot have generic parameters + --> $DIR/issue-117789.rs:3:17 + | +LL | auto trait Trait

    {} + | -----^^^ help: remove the parameters + | | + | auto trait cannot have generic parameters + +error[E0658]: auto traits are experimental and possibly buggy + --> $DIR/issue-117789.rs:3:1 + | +LL | auto trait Trait

    ` (where P is one of the previous types except `Self`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/feature-gates/feature-gate-doc_cfg.stderr b/tests/ui/feature-gates/feature-gate-doc_cfg.stderr index fe88e08c12346..1a313a86f7cc2 100644 --- a/tests/ui/feature-gates/feature-gate-doc_cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-doc_cfg.stderr @@ -7,6 +7,6 @@ LL | #[doc(cfg(unix))] = note: see issue #43781 for more information = help: add `#![feature(doc_cfg)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-doc_masked.stderr b/tests/ui/feature-gates/feature-gate-doc_masked.stderr index 80522b6eee526..96377d8d03647 100644 --- a/tests/ui/feature-gates/feature-gate-doc_masked.stderr +++ b/tests/ui/feature-gates/feature-gate-doc_masked.stderr @@ -7,6 +7,6 @@ LL | #[doc(masked)] = note: see issue #44027 for more information = help: add `#![feature(doc_masked)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr b/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr index 1f9bef40c4e73..d19d3fa0ff7f0 100644 --- a/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr +++ b/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr @@ -7,6 +7,6 @@ LL | #[doc(notable_trait)] = note: see issue #45040 for more information = help: add `#![feature(doc_notable_trait)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr index 6d7f4844a993b..4a0c8d7fdc3f9 100644 --- a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr +++ b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr @@ -7,6 +7,6 @@ LL | 0 .. 3 => {} = note: see issue #37854 for more information = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index 49e7ab6082c82..d34f257c8d910 100644 --- a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -12,6 +12,6 @@ help: you might want to use `let else` to handle the variant that isn't matched LL | let Ok(_x) = foo() else { todo!() }; | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr index 7de67da9b5d14..2fcad98be9f73 100644 --- a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr +++ b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr @@ -2,9 +2,10 @@ error[E0432]: unresolved import `core` --> $DIR/feature-gate-extern_absolute_paths.rs:1:5 | LL | use core::default; - | ^^^^ maybe a missing crate `core`? - | - = help: consider adding `extern crate core` to use the `core` crate + | ^^^^ + | | + | maybe a missing crate `core`? + | help: try using `std` instead of `core`: `std` error[E0433]: failed to resolve: maybe a missing crate `core`? --> $DIR/feature-gate-extern_absolute_paths.rs:4:19 @@ -12,7 +13,10 @@ error[E0433]: failed to resolve: maybe a missing crate `core`? LL | let _: u8 = ::core::default::Default(); | ^^^^ maybe a missing crate `core`? | - = help: consider adding `extern crate core` to use the `core` crate +help: try using `std` instead of `core` + | +LL | let _: u8 = ::std::default::Default(); + | ~~~ help: consider importing this module | LL + use std::default; diff --git a/tests/ui/feature-gates/feature-gate-extern_prelude.stderr b/tests/ui/feature-gates/feature-gate-extern_prelude.stderr index d72e47e9ed8ff..3b0ffae869653 100644 --- a/tests/ui/feature-gates/feature-gate-extern_prelude.stderr +++ b/tests/ui/feature-gates/feature-gate-extern_prelude.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `-` LL | can-only-test-this-in-run-make-fulldeps | ^ expected one of `!` or `::` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-extern_types.stderr b/tests/ui/feature-gates/feature-gate-extern_types.stderr index 923fae400a91c..17ce01fd59bbf 100644 --- a/tests/ui/feature-gates/feature-gate-extern_types.stderr +++ b/tests/ui/feature-gates/feature-gate-extern_types.stderr @@ -7,6 +7,6 @@ LL | type T; = note: see issue #43467 for more information = help: add `#![feature(extern_types)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-feature-gate.stderr b/tests/ui/feature-gates/feature-gate-feature-gate.stderr index ad97741dae4d0..8ff99ddbe2188 100644 --- a/tests/ui/feature-gates/feature-gate-feature-gate.stderr +++ b/tests/ui/feature-gates/feature-gate-feature-gate.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![forbid(unstable_features)] | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-ffi_const.stderr b/tests/ui/feature-gates/feature-gate-ffi_const.stderr index bed6a2ce48825..c86606f335275 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_const.stderr +++ b/tests/ui/feature-gates/feature-gate-ffi_const.stderr @@ -7,6 +7,6 @@ LL | #[ffi_const] = note: see issue #58328 for more information = help: add `#![feature(ffi_const)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr index 2b0308fd661c2..4392fb16deb4f 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr +++ b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr @@ -7,6 +7,6 @@ LL | #[ffi_pure] = note: see issue #58329 for more information = help: add `#![feature(ffi_pure)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr index 3585355ab77fc..7a030d4546042 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr +++ b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr @@ -7,6 +7,6 @@ LL | #[ffi_returns_twice] = note: see issue #58314 for more information = help: add `#![feature(ffi_returns_twice)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-fn_align.stderr b/tests/ui/feature-gates/feature-gate-fn_align.stderr index 5ff124e48dca9..3351ceaf2f019 100644 --- a/tests/ui/feature-gates/feature-gate-fn_align.stderr +++ b/tests/ui/feature-gates/feature-gate-fn_align.stderr @@ -7,6 +7,6 @@ LL | #[repr(align(16))] = note: see issue #82232 for more information = help: add `#![feature(fn_align)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-fn_delegation.rs b/tests/ui/feature-gates/feature-gate-fn_delegation.rs new file mode 100644 index 0000000000000..6ac3671209033 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-fn_delegation.rs @@ -0,0 +1,3 @@ +todo!(); //~ ERROR + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-fn_delegation.stderr b/tests/ui/feature-gates/feature-gate-fn_delegation.stderr new file mode 100644 index 0000000000000..14d85c5263e0d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-fn_delegation.stderr @@ -0,0 +1,13 @@ +error: expected one of `!` or `::`, found `(` + --> $DIR/feature-gate-fn_delegation.rs:1:1 + | +LL | todo!(); + | ^^^^^^^ + | | + | expected one of `!` or `::` + | in this macro invocation + | + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + diff --git a/tests/ui/feature-gates/feature-gate-format_args_nl.stderr b/tests/ui/feature-gates/feature-gate-format_args_nl.stderr index b211e2f8ed8a2..35a712aad8a15 100644 --- a/tests/ui/feature-gates/feature-gate-format_args_nl.stderr +++ b/tests/ui/feature-gates/feature-gate-format_args_nl.stderr @@ -6,6 +6,6 @@ LL | format_args_nl!(""); | = help: add `#![feature(format_args_nl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-fundamental.stderr b/tests/ui/feature-gates/feature-gate-fundamental.stderr index 1ae8d9128b1ff..14ee169bdaa2c 100644 --- a/tests/ui/feature-gates/feature-gate-fundamental.stderr +++ b/tests/ui/feature-gates/feature-gate-fundamental.stderr @@ -7,6 +7,6 @@ LL | #[fundamental] = note: see issue #29635 for more information = help: add `#![feature(fundamental)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr b/tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr index b448c35e84626..56f8309a69f9b 100644 --- a/tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr +++ b/tests/ui/feature-gates/feature-gate-gen_blocks.none.stderr @@ -4,6 +4,6 @@ error[E0422]: cannot find struct, variant or union type `gen` in this scope LL | gen {}; | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr index bb1622628dc1f..e5265b67eaba1 100644 --- a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr +++ b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr @@ -6,6 +6,6 @@ LL | #[rustc_error] | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-imported_main.stderr b/tests/ui/feature-gates/feature-gate-imported_main.stderr index 3b879fdfc6bbf..94cb74047c859 100644 --- a/tests/ui/feature-gates/feature-gate-imported_main.stderr +++ b/tests/ui/feature-gates/feature-gate-imported_main.stderr @@ -7,6 +7,6 @@ LL | use foo::bar as main; = note: see issue #28937 for more information = help: add `#![feature(imported_main)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-inherent_associated_types.stderr b/tests/ui/feature-gates/feature-gate-inherent_associated_types.stderr index 76e65d239f878..8e117422a7964 100644 --- a/tests/ui/feature-gates/feature-gate-inherent_associated_types.stderr +++ b/tests/ui/feature-gates/feature-gate-inherent_associated_types.stderr @@ -7,6 +7,6 @@ LL | type Bar = isize; = note: see issue #8995 for more information = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-inline_const.stderr b/tests/ui/feature-gates/feature-gate-inline_const.stderr index be2f567155c3d..3cb4aad003f48 100644 --- a/tests/ui/feature-gates/feature-gate-inline_const.stderr +++ b/tests/ui/feature-gates/feature-gate-inline_const.stderr @@ -7,6 +7,6 @@ LL | let _ = const { = note: see issue #76001 for more information = help: add `#![feature(inline_const)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr b/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr index ca533d8505cf7..eab024dde662a 100644 --- a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr +++ b/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr @@ -7,6 +7,6 @@ LL | let const { () } = (); = note: see issue #76001 for more information = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-large-assignments.stderr b/tests/ui/feature-gates/feature-gate-large-assignments.stderr index 8ddc3043e966c..c025be4f63652 100644 --- a/tests/ui/feature-gates/feature-gate-large-assignments.stderr +++ b/tests/ui/feature-gates/feature-gate-large-assignments.stderr @@ -7,6 +7,6 @@ LL | #![move_size_limit = "42"] = note: see issue #83518 for more information = help: add `#![feature(large_assignments)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs new file mode 100644 index 0000000000000..9036095fbc495 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs @@ -0,0 +1,5 @@ +#[link(kind = "link-arg", name = "foo")] +//~^ ERROR link kind `link-arg` is unstable +extern "C" {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr b/tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr new file mode 100644 index 0000000000000..673835b8b9ebf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr @@ -0,0 +1,12 @@ +error[E0658]: link kind `link-arg` is unstable + --> $DIR/feature-gate-link-arg-attribute.rs:1:15 + | +LL | #[link(kind = "link-arg", name = "foo")] + | ^^^^^^^^^^ + | + = note: see issue #99427 for more information + = help: add `#![feature(link_arg_attribute)]` to the crate attributes to enable + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-link_cfg.stderr b/tests/ui/feature-gates/feature-gate-link_cfg.stderr index 97b6cbca41240..6e42be3954d1e 100644 --- a/tests/ui/feature-gates/feature-gate-link_cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-link_cfg.stderr @@ -6,6 +6,6 @@ LL | #[link(name = "foo", cfg(foo))] | = help: add `#![feature(link_cfg)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr b/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr index 6bce5b823f385..0cad260a14a45 100644 --- a/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr +++ b/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr @@ -7,6 +7,6 @@ LL | fn sqrt(x: f32) -> f32; = note: see issue #29602 for more information = help: add `#![feature(link_llvm_intrinsics)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-linkage.stderr b/tests/ui/feature-gates/feature-gate-linkage.stderr index a1c73e555ef7a..ca1f54145689c 100644 --- a/tests/ui/feature-gates/feature-gate-linkage.stderr +++ b/tests/ui/feature-gates/feature-gate-linkage.stderr @@ -7,6 +7,6 @@ LL | #[linkage = "extern_weak"] static foo: *mut isize; = note: see issue #29603 for more information = help: add `#![feature(linkage)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-log_syntax.stderr b/tests/ui/feature-gates/feature-gate-log_syntax.stderr index fdc1c8553476c..500c752e20d07 100644 --- a/tests/ui/feature-gates/feature-gate-log_syntax.stderr +++ b/tests/ui/feature-gates/feature-gate-log_syntax.stderr @@ -7,6 +7,6 @@ LL | log_syntax!() = note: see issue #29598 for more information = help: add `#![feature(log_syntax)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-log_syntax2.stderr b/tests/ui/feature-gates/feature-gate-log_syntax2.stderr index 6deb4a46cd53a..a808a9463a046 100644 --- a/tests/ui/feature-gates/feature-gate-log_syntax2.stderr +++ b/tests/ui/feature-gates/feature-gate-log_syntax2.stderr @@ -7,6 +7,6 @@ LL | println!("{:?}", log_syntax!()); = note: see issue #29598 for more information = help: add `#![feature(log_syntax)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr b/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr index e3c3756fd21c9..4555ef1874f32 100644 --- a/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr +++ b/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr @@ -7,6 +7,6 @@ LL | #[marker] trait ExplicitMarker {} = note: see issue #29864 for more information = help: add `#![feature(marker_trait_attr)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-may-dangle.stderr b/tests/ui/feature-gates/feature-gate-may-dangle.stderr index d47a76a50efb8..c12b3ba517d10 100644 --- a/tests/ui/feature-gates/feature-gate-may-dangle.stderr +++ b/tests/ui/feature-gates/feature-gate-may-dangle.stderr @@ -7,6 +7,6 @@ LL | unsafe impl<#[may_dangle] A> Drop for Pt { = note: see issue #34761 for more information = help: add `#![feature(dropck_eyepatch)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr index 2ef6a1c040424..4c7ae9e2ef5e5 100644 --- a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr +++ b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr @@ -7,6 +7,6 @@ LL | #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")] = note: see issue #81490 for more information = help: add `#![feature(native_link_modifiers_as_needed)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-needs-allocator.stderr b/tests/ui/feature-gates/feature-gate-needs-allocator.stderr index 2b213acebb503..ca21f222588d0 100644 --- a/tests/ui/feature-gates/feature-gate-needs-allocator.stderr +++ b/tests/ui/feature-gates/feature-gate-needs-allocator.stderr @@ -6,6 +6,6 @@ LL | #![needs_allocator] | = help: add `#![feature(allocator_internals)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-negative_bounds.stderr b/tests/ui/feature-gates/feature-gate-negative_bounds.stderr index ae010fdf3f848..74b9e4bc4c867 100644 --- a/tests/ui/feature-gates/feature-gate-negative_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-negative_bounds.stderr @@ -4,5 +4,5 @@ error: negative bounds are not supported LL | fn test() {} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs new file mode 100644 index 0000000000000..ca5ce3b948943 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs @@ -0,0 +1,27 @@ +// Check that never patterns require the feature gate. +use std::ptr::NonNull; + +enum Void {} + +fn main() { + let res: Result = Ok(0); + let (Ok(_x) | Err(&!)) = res.as_ref(); + //~^ ERROR `!` patterns are experimental + //~| ERROR: is not bound in all patterns + + unsafe { + let ptr: *const Void = NonNull::dangling().as_ptr(); + match *ptr { + ! //~ ERROR `!` patterns are experimental + } + } + + // Check that the gate operates even behind `cfg`. + #[cfg(FALSE)] + unsafe { + let ptr: *const Void = NonNull::dangling().as_ptr(); + match *ptr { + ! => {} //~ ERROR `!` patterns are experimental + } + } +} diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.stderr b/tests/ui/feature-gates/feature-gate-never_patterns.stderr new file mode 100644 index 0000000000000..2354a3b0476d8 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-never_patterns.stderr @@ -0,0 +1,39 @@ +error[E0408]: variable `_x` is not bound in all patterns + --> $DIR/feature-gate-never_patterns.rs:8:19 + | +LL | let (Ok(_x) | Err(&!)) = res.as_ref(); + | -- ^^^^^^^ pattern doesn't bind `_x` + | | + | variable not in all patterns + +error[E0658]: `!` patterns are experimental + --> $DIR/feature-gate-never_patterns.rs:8:24 + | +LL | let (Ok(_x) | Err(&!)) = res.as_ref(); + | ^ + | + = note: see issue #118155 for more information + = help: add `#![feature(never_patterns)]` to the crate attributes to enable + +error[E0658]: `!` patterns are experimental + --> $DIR/feature-gate-never_patterns.rs:15:13 + | +LL | ! + | ^ + | + = note: see issue #118155 for more information + = help: add `#![feature(never_patterns)]` to the crate attributes to enable + +error[E0658]: `!` patterns are experimental + --> $DIR/feature-gate-never_patterns.rs:24:13 + | +LL | ! => {} + | ^ + | + = note: see issue #118155 for more information + = help: add `#![feature(never_patterns)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0408, E0658. +For more information about an error, try `rustc --explain E0408`. diff --git a/tests/ui/feature-gates/feature-gate-no_core.stderr b/tests/ui/feature-gates/feature-gate-no_core.stderr index 8430a9ec6a757..e525c95ac36ba 100644 --- a/tests/ui/feature-gates/feature-gate-no_core.stderr +++ b/tests/ui/feature-gates/feature-gate-no_core.stderr @@ -7,6 +7,6 @@ LL | #![no_core] = note: see issue #29639 for more information = help: add `#![feature(no_core)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-no_sanitize.stderr b/tests/ui/feature-gates/feature-gate-no_sanitize.stderr index 3993357006f4b..bb808961eb217 100644 --- a/tests/ui/feature-gates/feature-gate-no_sanitize.stderr +++ b/tests/ui/feature-gates/feature-gate-no_sanitize.stderr @@ -7,6 +7,6 @@ LL | #[no_sanitize(address)] = note: see issue #39699 for more information = help: add `#![feature(no_sanitize)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index 8af0eedc82b1a..a533371397762 100644 --- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -192,6 +192,6 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to previous error; 16 warnings emitted +error: aborting due to 1 previous error; 16 warnings emitted For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr index 01c8ee30c5f56..f727fdae90ecd 100644 --- a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr +++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr @@ -7,6 +7,6 @@ LL | fn foo() where for T:, {} = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs new file mode 100644 index 0000000000000..e19dcf9f6a54c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs @@ -0,0 +1,15 @@ +#![feature(offset_of)] + +use std::mem::offset_of; + +enum Alpha { + One(u8), + Two(u8), +} + +fn main() { + offset_of!(Alpha::One, 0); //~ ERROR expected type, found variant `Alpha::One` + offset_of!(Alpha, One); //~ ERROR `One` is an enum variant; expected field at end of `offset_of` + //~| ERROR using enums in offset_of is experimental + offset_of!(Alpha, Two.0); //~ ERROR using enums in offset_of is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr new file mode 100644 index 0000000000000..893f78702375c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr @@ -0,0 +1,37 @@ +error[E0573]: expected type, found variant `Alpha::One` + --> $DIR/feature-gate-offset-of-enum.rs:11:16 + | +LL | offset_of!(Alpha::One, 0); + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Alpha` + +error[E0658]: using enums in offset_of is experimental + --> $DIR/feature-gate-offset-of-enum.rs:12:23 + | +LL | offset_of!(Alpha, One); + | ^^^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable + +error[E0795]: `One` is an enum variant; expected field at end of `offset_of` + --> $DIR/feature-gate-offset-of-enum.rs:12:23 + | +LL | offset_of!(Alpha, One); + | ^^^ enum variant + +error[E0658]: using enums in offset_of is experimental + --> $DIR/feature-gate-offset-of-enum.rs:14:23 + | +LL | offset_of!(Alpha, Two.0); + | ^^^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0573, E0658, E0795. +For more information about an error, try `rustc --explain E0573`. diff --git a/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr b/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr index a5ec3599f6a17..86f6040b14ff3 100644 --- a/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr +++ b/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr @@ -6,6 +6,6 @@ LL | #[omit_gdb_pretty_printer_section] | = help: add `#![feature(omit_gdb_pretty_printer_section)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr b/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr index 0526c6dc83980..fe9a88b5ebbcc 100644 --- a/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr +++ b/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr @@ -6,6 +6,6 @@ LL | impl MyMarker for T {} LL | impl MyMarker for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr index 8694924e52fe0..c89dcaf727ac3 100644 --- a/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr +++ b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr @@ -6,7 +6,6 @@ LL | match 0usize { | = note: the matched value is of type `usize` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ 0..=usize::MAX => {}, @@ -21,7 +20,6 @@ LL | match 0isize { | = note: the matched value is of type `isize` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching 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 ~ isize::MIN..=isize::MAX => {}, diff --git a/tests/ui/feature-gates/feature-gate-prelude_import.stderr b/tests/ui/feature-gates/feature-gate-prelude_import.stderr index 8686aed8f8293..b2e2a7c8cc114 100644 --- a/tests/ui/feature-gates/feature-gate-prelude_import.stderr +++ b/tests/ui/feature-gates/feature-gate-prelude_import.stderr @@ -6,6 +6,6 @@ LL | #[prelude_import] | = help: add `#![feature(prelude_import)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.stderr b/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.stderr index 0069153893886..f8fa8c54198b0 100644 --- a/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.stderr +++ b/tests/ui/feature-gates/feature-gate-proc_macro_byte_character.stderr @@ -7,6 +7,6 @@ LL | Literal::byte_character(b'a'); = note: see issue #115268 for more information = help: add `#![feature(proc_macro_byte_character)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr b/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr index 18e6503c5524e..cc6506c5680e6 100644 --- a/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr +++ b/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr @@ -6,6 +6,6 @@ LL | #![profiler_runtime] | = help: add `#![feature(profiler_runtime)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-register_tool.stderr b/tests/ui/feature-gates/feature-gate-register_tool.stderr index 9ffaaa8de7a06..d72249e02129b 100644 --- a/tests/ui/feature-gates/feature-gate-register_tool.stderr +++ b/tests/ui/feature-gates/feature-gate-register_tool.stderr @@ -7,6 +7,6 @@ LL | #![register_tool(tool)] = note: see issue #66079 for more information = help: add `#![feature(register_tool)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-repr128.stderr b/tests/ui/feature-gates/feature-gate-repr128.stderr index 3999a6d2d2f89..657802632b058 100644 --- a/tests/ui/feature-gates/feature-gate-repr128.stderr +++ b/tests/ui/feature-gates/feature-gate-repr128.stderr @@ -7,6 +7,6 @@ LL | enum A { = note: see issue #56071 for more information = help: add `#![feature(repr128)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr index 1bdb2574eadc3..a15b01618f5b0 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr @@ -15,13 +15,18 @@ LL | fn foo>() {} | | | help: remove these parentheses -error[E0220]: associated type `m` not found for `Trait` +error: expected type, found function --> $DIR/feature-gate-return_type_notation.rs:14:17 | LL | fn foo>() {} - | ^ associated type `m` not found + | ^ unexpected function + | +note: the associated function is defined here + --> $DIR/feature-gate-return_type_notation.rs:10:5 + | +LL | async fn m(); + | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors -Some errors have detailed explanations: E0220, E0658. -For more information about an error, try `rustc --explain E0220`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs index 86e2c48e188bc..60ac9f8d4f1a5 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs @@ -14,7 +14,7 @@ trait Trait { fn foo>() {} //[cfg]~^ ERROR return type notation is experimental //[cfg]~| ERROR parenthesized generic arguments cannot be used in associated type constraints -//[cfg]~| ERROR associated type `m` not found for `Trait` +//[cfg]~| ERROR expected type, found function //[no]~^^^^ WARN return type notation is experimental //[no]~| WARN unstable syntax can change at any point in the future, causing a hard error! diff --git a/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr b/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr index a549cb64e0cb6..b33721ca43d9d 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr @@ -7,6 +7,6 @@ LL | #[rustc_allow_const_fn_unstable()] = note: see issue #69399 for more information = help: add `#![feature(rustc_allow_const_fn_unstable)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr b/tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr index 48493b786d649..869764fa4569a 100644 --- a/tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr @@ -4,6 +4,6 @@ error[E0734]: stability attributes may not be used outside of the standard libra LL | #[rustc_const_unstable(feature="fzzzzzt")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/feature-gates/feature-gate-simd.stderr b/tests/ui/feature-gates/feature-gate-simd.stderr index 6e0e0b2703a34..fa30d461f9c13 100644 --- a/tests/ui/feature-gates/feature-gate-simd.stderr +++ b/tests/ui/feature-gates/feature-gate-simd.stderr @@ -7,6 +7,6 @@ LL | #[repr(simd)] = note: see issue #27731 for more information = help: add `#![feature(repr_simd)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-start.stderr b/tests/ui/feature-gates/feature-gate-start.stderr index eec9d1a29248b..157bf18c9e87a 100644 --- a/tests/ui/feature-gates/feature-gate-start.stderr +++ b/tests/ui/feature-gates/feature-gate-start.stderr @@ -7,6 +7,6 @@ LL | fn foo(_: isize, _: *const *const u8) -> isize { 0 } = note: see issue #29633 for more information = help: add `#![feature(start)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr index 57ffaed78f5e5..4ff85dc0797ec 100644 --- a/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr +++ b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr @@ -7,6 +7,6 @@ LL | const X: i32 = #[allow(dead_code)] 8; = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-thread_local.stderr b/tests/ui/feature-gates/feature-gate-thread_local.stderr index 6352e908708af..8fbbfb59a4829 100644 --- a/tests/ui/feature-gates/feature-gate-thread_local.stderr +++ b/tests/ui/feature-gates/feature-gate-thread_local.stderr @@ -7,6 +7,6 @@ LL | #[thread_local] = note: see issue #29594 for more information = help: add `#![feature(thread_local)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-trace_macros.stderr b/tests/ui/feature-gates/feature-gate-trace_macros.stderr index 3978d4111bb05..305186e51173c 100644 --- a/tests/ui/feature-gates/feature-gate-trace_macros.stderr +++ b/tests/ui/feature-gates/feature-gate-trace_macros.stderr @@ -7,6 +7,6 @@ LL | trace_macros!(true); = note: see issue #29598 for more information = help: add `#![feature(trace_macros)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-trait-alias.stderr b/tests/ui/feature-gates/feature-gate-trait-alias.stderr index 41cd6dbd8bc0e..919a97673fb0c 100644 --- a/tests/ui/feature-gates/feature-gate-trait-alias.stderr +++ b/tests/ui/feature-gates/feature-gate-trait-alias.stderr @@ -7,6 +7,6 @@ LL | trait Foo = Default; = note: see issue #41517 for more information = help: add `#![feature(trait_alias)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-trait_upcasting.rs b/tests/ui/feature-gates/feature-gate-trait_upcasting.rs deleted file mode 100644 index e4102f1cfa75d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-trait_upcasting.rs +++ /dev/null @@ -1,13 +0,0 @@ -trait Foo {} - -trait Bar: Foo {} - -impl Foo for () {} - -impl Bar for () {} - -fn main() { - let bar: &dyn Bar = &(); - let foo: &dyn Foo = bar; - //~^ ERROR trait upcasting coercion is experimental [E0658] -} diff --git a/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr b/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr deleted file mode 100644 index 93afa78459d3d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental - --> $DIR/feature-gate-trait_upcasting.rs:11:25 - | -LL | let foo: &dyn Foo = bar; - | ^^^ - | - = note: see issue #65991 for more information - = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable - = note: required when coercing `&dyn Bar` into `&dyn Foo` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-transparent_unions.stderr b/tests/ui/feature-gates/feature-gate-transparent_unions.stderr index 65c8fe0522905..13ea3603a8dab 100644 --- a/tests/ui/feature-gates/feature-gate-transparent_unions.stderr +++ b/tests/ui/feature-gates/feature-gate-transparent_unions.stderr @@ -7,6 +7,6 @@ LL | union OkButUnstableUnion { = note: see issue #60405 for more information = help: add `#![feature(transparent_unions)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-try_blocks.stderr b/tests/ui/feature-gates/feature-gate-try_blocks.stderr index 022409f95566b..028dff34c9d38 100644 --- a/tests/ui/feature-gates/feature-gate-try_blocks.stderr +++ b/tests/ui/feature-gates/feature-gate-try_blocks.stderr @@ -11,6 +11,6 @@ LL | | }; = note: see issue #31436 for more information = help: add `#![feature(try_blocks)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-type_ascription.stderr b/tests/ui/feature-gates/feature-gate-type_ascription.stderr index d747aea6d177f..2c78e4e38320c 100644 --- a/tests/ui/feature-gates/feature-gate-type_ascription.stderr +++ b/tests/ui/feature-gates/feature-gate-type_ascription.stderr @@ -7,6 +7,6 @@ LL | let a = type_ascribe!(10, u8); = note: see issue #23416 for more information = help: add `#![feature(type_ascription)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr b/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr index cf3284467f77d..6fbade424b8e2 100644 --- a/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr +++ b/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr @@ -7,6 +7,6 @@ LL | #[unix_sigpipe = "inherit"] = note: see issue #97889 for more information = help: add `#![feature(unix_sigpipe)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr index 39afbf2db7e56..fc9bcd90e52ee 100644 --- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr +++ b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![forbid(internal_features, unsafe_code)] | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-unsized_locals.stderr b/tests/ui/feature-gates/feature-gate-unsized_locals.stderr index 9aeeb88cf04f2..f1595e034be55 100644 --- a/tests/ui/feature-gates/feature-gate-unsized_locals.stderr +++ b/tests/ui/feature-gates/feature-gate-unsized_locals.stderr @@ -15,6 +15,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn f(f: &dyn FnOnce()) {} | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr index bea6cee0a89e8..dd5a1cd89e7f2 100644 --- a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr +++ b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr @@ -7,6 +7,6 @@ LL | let _ : &(dyn Send,) = &((),); = note: see issue #42877 for more information = help: add `#![feature(unsized_tuple_coercion)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr index d4c201b5d3ec5..ba076568088b2 100644 --- a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr +++ b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr @@ -7,6 +7,6 @@ LL | LL | impl Foo for &T { } | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr index 218e0292776d0..0053d9d5cff8d 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr @@ -6,6 +6,6 @@ LL | extern "rust-intrinsic" { | = help: add `#![feature(intrinsics)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/issue-49983-see-issue-0.stderr b/tests/ui/feature-gates/issue-49983-see-issue-0.stderr index 314238a34df86..5f9e5d440fb24 100644 --- a/tests/ui/feature-gates/issue-49983-see-issue-0.stderr +++ b/tests/ui/feature-gates/issue-49983-see-issue-0.stderr @@ -6,6 +6,6 @@ LL | #[allow(unused_imports)] use core::ptr::Unique; | = help: add `#![feature(ptr_internals)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/rustc-private.stderr b/tests/ui/feature-gates/rustc-private.stderr index 1a8536d37d6f7..7419af80a3232 100644 --- a/tests/ui/feature-gates/rustc-private.stderr +++ b/tests/ui/feature-gates/rustc-private.stderr @@ -7,6 +7,6 @@ LL | extern crate libc; = note: see issue #27812 for more information = help: add `#![feature(rustc_private)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/unknown-feature.stderr b/tests/ui/feature-gates/unknown-feature.stderr index e5c05872dbf85..0a731ddcc0b62 100644 --- a/tests/ui/feature-gates/unknown-feature.stderr +++ b/tests/ui/feature-gates/unknown-feature.stderr @@ -4,6 +4,6 @@ error[E0635]: unknown feature `unknown_rust_feature` LL | #![feature(unknown_rust_feature)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0635`. diff --git a/tests/ui/ffi_const2.stderr b/tests/ui/ffi_const2.stderr index 0c30c9dc50c0d..b8cbc296370de 100644 --- a/tests/ui/ffi_const2.stderr +++ b/tests/ui/ffi_const2.stderr @@ -4,6 +4,6 @@ error[E0757]: `#[ffi_const]` function cannot be `#[ffi_pure]` LL | #[ffi_pure] | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0757`. diff --git a/tests/ui/fmt/closing-brace-as-fill.stderr b/tests/ui/fmt/closing-brace-as-fill.stderr index aa1e5aff6525f..70068fa3aadc4 100644 --- a/tests/ui/fmt/closing-brace-as-fill.stderr +++ b/tests/ui/fmt/closing-brace-as-fill.stderr @@ -8,5 +8,5 @@ LL | println!("Hello, world! {0:}<3", 2); | = note: the character `'}'` is interpreted as a fill character because of the `:` that precedes it -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.stderr b/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.stderr index bb6a14d88b3d6..950dea721e29d 100644 --- a/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.stderr +++ b/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.stderr @@ -8,5 +8,5 @@ LL | format_string_proc_macro::bad_format_args_captures!(); = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fmt/format-raw-string-error.stderr b/tests/ui/fmt/format-raw-string-error.stderr index 8d61950d8c2ad..090ca9353a7f3 100644 --- a/tests/ui/fmt/format-raw-string-error.stderr +++ b/tests/ui/fmt/format-raw-string-error.stderr @@ -6,5 +6,5 @@ LL | println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#); | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr index 4c0ac52865d77..c0650ff17c5ed 100644 --- a/tests/ui/fmt/ifmt-unimpl.stderr +++ b/tests/ui/fmt/ifmt-unimpl.stderr @@ -21,6 +21,6 @@ note: required by a bound in `core::fmt::rt::Argument::<'a>::new_upper_hex` --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/fmt/ifmt-unknown-trait.stderr b/tests/ui/fmt/ifmt-unknown-trait.stderr index 459432bf4e426..66147ae45faf2 100644 --- a/tests/ui/fmt/ifmt-unknown-trait.stderr +++ b/tests/ui/fmt/ifmt-unknown-trait.stderr @@ -15,5 +15,5 @@ LL | format!("{:notimplemented}", "3"); - `x`, which uses the `LowerHex` trait - `X`, which uses the `UpperHex` trait -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fmt/issue-104142.stderr b/tests/ui/fmt/issue-104142.stderr index d41644faa2827..690ccb8d08b03 100644 --- a/tests/ui/fmt/issue-104142.stderr +++ b/tests/ui/fmt/issue-104142.stderr @@ -6,5 +6,5 @@ LL | \"\'}、"# | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fmt/issue-75307.stderr b/tests/ui/fmt/issue-75307.stderr index c5b0b11e7d099..986e805d4f99e 100644 --- a/tests/ui/fmt/issue-75307.stderr +++ b/tests/ui/fmt/issue-75307.stderr @@ -4,5 +4,5 @@ error: 3 positional arguments in format string, but there is 1 argument LL | format!(r"{}{}{}", named_arg=1); | ^^^^^^ - -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fmt/issue-86085.stderr b/tests/ui/fmt/issue-86085.stderr index ee7d8a5cc237a..f325a3ce2931c 100644 --- a/tests/ui/fmt/issue-86085.stderr +++ b/tests/ui/fmt/issue-86085.stderr @@ -7,5 +7,5 @@ LL | format ! ( concat ! ( r#"lJ𐏿Æ�.𐏿�"# , "r} {}" ) ) ; = note: if you intended to print `}`, you can escape it using `}}` = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fmt/issue-89173.stderr b/tests/ui/fmt/issue-89173.stderr index ddeb769eadc52..62ca8862d21b6 100644 --- a/tests/ui/fmt/issue-89173.stderr +++ b/tests/ui/fmt/issue-89173.stderr @@ -14,5 +14,5 @@ LL | print!("%0*x", width, num); | ^^^^ = note: printf formatting is not supported; see the documentation for `std::fmt` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fmt/issue-91556.stderr b/tests/ui/fmt/issue-91556.stderr index dbd5aef458b8e..beab3db0d94c1 100644 --- a/tests/ui/fmt/issue-91556.stderr +++ b/tests/ui/fmt/issue-91556.stderr @@ -7,5 +7,5 @@ LL | let _ = format!(concat!("{0}𝖳𝖾𝗌𝗍{"), i); = note: if you intended to print `{`, you can escape it using `{{` = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fn-in-pat.stderr b/tests/ui/fn-in-pat.stderr index 2482d632695cc..41ea4df72a2ff 100644 --- a/tests/ui/fn-in-pat.stderr +++ b/tests/ui/fn-in-pat.stderr @@ -6,6 +6,6 @@ LL | A::new() => (), | = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/fn/bad-main.stderr b/tests/ui/fn/bad-main.stderr index 65140a0794f84..47aa02c09af2c 100644 --- a/tests/ui/fn/bad-main.stderr +++ b/tests/ui/fn/bad-main.stderr @@ -7,6 +7,6 @@ LL | fn main(x: isize) { } = note: expected signature `fn()` found signature `fn(isize)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/fn/fn-bad-block-type.stderr b/tests/ui/fn/fn-bad-block-type.stderr index 13ebfd1e2033a..6917bea659153 100644 --- a/tests/ui/fn/fn-bad-block-type.stderr +++ b/tests/ui/fn/fn-bad-block-type.stderr @@ -6,6 +6,6 @@ LL | fn f() -> isize { true } | | | expected `isize` because of return type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fn/fn-closure-mutable-capture.stderr b/tests/ui/fn/fn-closure-mutable-capture.stderr index 03e3d545a9919..5a2f92250e020 100644 --- a/tests/ui/fn/fn-closure-mutable-capture.stderr +++ b/tests/ui/fn/fn-closure-mutable-capture.stderr @@ -10,6 +10,6 @@ LL | bar(move || x = 1); | | in this closure | expects `Fn` instead of `FnMut` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr index 0c3df04eabcd2..e57b5af82cded 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr @@ -13,5 +13,5 @@ LL | f::<'a, 'b>(()); = note: the function `f` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr index 4df639232a332..3be630e2b2352 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr @@ -11,6 +11,6 @@ LL | LL | println!("{}", y); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr index 3f6401b9f7a4d..4662eb32abb7a 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr @@ -16,6 +16,6 @@ help: consider adding an explicit lifetime bound LL | impl<'a, T: 'a> Trait<'a> for T { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr index d417f28839368..c2a8fa741ca5a 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr @@ -11,6 +11,6 @@ LL | LL | println!("{}", y); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/fn/issue-3044.stderr b/tests/ui/fn/issue-3044.stderr index 219029e2afd6c..06254775b74d5 100644 --- a/tests/ui/fn/issue-3044.stderr +++ b/tests/ui/fn/issue-3044.stderr @@ -16,6 +16,6 @@ LL + LL ~ }, /* f */); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/fn/issue-3099.stderr b/tests/ui/fn/issue-3099.stderr index 32ee2e1d20736..4417f2326654c 100644 --- a/tests/ui/fn/issue-3099.stderr +++ b/tests/ui/fn/issue-3099.stderr @@ -9,6 +9,6 @@ LL | fn a(x: String, y: String) -> String { | = note: `a` must be defined only once in the value namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/fn/issue-39259.stderr b/tests/ui/fn/issue-39259.stderr index b656b76bfe4eb..bd102e5813562 100644 --- a/tests/ui/fn/issue-39259.stderr +++ b/tests/ui/fn/issue-39259.stderr @@ -10,6 +10,6 @@ help: parenthesized trait syntax expands to `Fn<(u32,), Output=u32>` LL | impl Fn(u32) -> u32 for S { | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.stderr b/tests/ui/fn/signature-error-reporting-under-verbose.stderr index 067ee824d5d84..6c6a313c4df71 100644 --- a/tests/ui/fn/signature-error-reporting-under-verbose.stderr +++ b/tests/ui/fn/signature-error-reporting-under-verbose.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn needs_ptr(_: fn(i32, u32)) {} | ^^^^^^^^^ --------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/for-loop-while/break-while-condition.stderr b/tests/ui/for-loop-while/break-while-condition.stderr index e79f6a75fdec5..48b29f44fa106 100644 --- a/tests/ui/for-loop-while/break-while-condition.stderr +++ b/tests/ui/for-loop-while/break-while-condition.stderr @@ -38,7 +38,7 @@ LL | while false { | ^^^^^^^^^^^ this might have zero elements to iterate on LL | return | ------ if the loop doesn't execute, this value would never get returned - = help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility + = help: return a value for the case when the loop has zero elements to iterate on, otherwise consider changing the return type to account for that possibility error: aborting due to 3 previous errors diff --git a/tests/ui/for/for-c-in-str.stderr b/tests/ui/for/for-c-in-str.stderr index 959a7c43fff7d..475cf8c887491 100644 --- a/tests/ui/for/for-c-in-str.stderr +++ b/tests/ui/for/for-c-in-str.stderr @@ -7,6 +7,6 @@ LL | for c in "asdf" { = help: the trait `Iterator` is not implemented for `&str` = note: required for `&str` to implement `IntoIterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/for/for-else-err.stderr b/tests/ui/for/for-else-err.stderr index b330d10764769..bd49dc4724450 100644 --- a/tests/ui/for/for-else-err.stderr +++ b/tests/ui/for/for-else-err.stderr @@ -13,5 +13,5 @@ LL | | } | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/for/for-else-let-else-err.stderr b/tests/ui/for/for-else-let-else-err.stderr index a2396a8fbb161..bb6558739ba75 100644 --- a/tests/ui/for/for-else-let-else-err.stderr +++ b/tests/ui/for/for-else-let-else-err.stderr @@ -13,5 +13,5 @@ LL | | }; | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/for/for-expn.stderr b/tests/ui/for/for-expn.stderr index cdb2115552744..00822324039f0 100644 --- a/tests/ui/for/for-expn.stderr +++ b/tests/ui/for/for-expn.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `foo` in this scope LL | foo | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/for/for-loop-bogosity.stderr b/tests/ui/for/for-loop-bogosity.stderr index 9bf8056e82ecd..194a2fa08ceab 100644 --- a/tests/ui/for/for-loop-bogosity.stderr +++ b/tests/ui/for/for-loop-bogosity.stderr @@ -7,6 +7,6 @@ LL | for x in bogus { = help: the trait `Iterator` is not implemented for `MyStruct` = note: required for `MyStruct` to implement `IntoIterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/for/for-loop-refutable-pattern-error-message.stderr b/tests/ui/for/for-loop-refutable-pattern-error-message.stderr index 49a82a6769dce..2082603d2fb72 100644 --- a/tests/ui/for/for-loop-refutable-pattern-error-message.stderr +++ b/tests/ui/for/for-loop-refutable-pattern-error-message.stderr @@ -6,6 +6,6 @@ LL | for &1 in [1].iter() {} | = note: the matched value is of type `&i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/for/for-loop-type-error.stderr b/tests/ui/for/for-loop-type-error.stderr index c93a3b9b25c15..393becd1b3452 100644 --- a/tests/ui/for/for-loop-type-error.stderr +++ b/tests/ui/for/for-loop-type-error.stderr @@ -6,6 +6,6 @@ LL | let x = () + (); | | | () -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/for/for-loop-unconstrained-element-type.stderr b/tests/ui/for/for-loop-unconstrained-element-type.stderr index b1b38f6b9194b..3add3ae2eeb21 100644 --- a/tests/ui/for/for-loop-unconstrained-element-type.stderr +++ b/tests/ui/for/for-loop-unconstrained-element-type.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | for i in Vec::::new() { } | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/for/issue-20605.current.stderr b/tests/ui/for/issue-20605.current.stderr index b9a53cbd4fcb2..c8d39afdeb957 100644 --- a/tests/ui/for/issue-20605.current.stderr +++ b/tests/ui/for/issue-20605.current.stderr @@ -11,6 +11,6 @@ help: consider mutably borrowing here LL | for item in &mut *things { *item = 0 } | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/foreign-fn-return-lifetime.stderr b/tests/ui/foreign-fn-return-lifetime.stderr index df1a23a19edd5..43edcbde35c6b 100644 --- a/tests/ui/foreign-fn-return-lifetime.stderr +++ b/tests/ui/foreign-fn-return-lifetime.stderr @@ -10,6 +10,6 @@ help: consider using the `'static` lifetime LL | pub fn f() -> &'static u8; | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr b/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr index d4a9ca3e7c66e..564ee14668763 100644 --- a/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr +++ b/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr @@ -15,5 +15,5 @@ LL | | } = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/foreign/issue-91370-foreign-fn-block-impl.stderr b/tests/ui/foreign/issue-91370-foreign-fn-block-impl.stderr index 4fb2f8c659c53..fea2ab61e929f 100644 --- a/tests/ui/foreign/issue-91370-foreign-fn-block-impl.stderr +++ b/tests/ui/foreign/issue-91370-foreign-fn-block-impl.stderr @@ -17,5 +17,5 @@ LL | | } = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr index 258a8d163936a..7497e48c5d245 100644 --- a/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -15,6 +15,6 @@ help: try wrapping the expression in `Some` LL | x = Some(5); | +++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr index c7c0846595d5a..af716916548a9 100644 --- a/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr @@ -18,6 +18,6 @@ note: `y::Foo` is defined in module `crate::y` of the current crate LL | pub enum Foo { } | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr index 6b312202bfed4..45634131ad316 100644 --- a/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr @@ -13,6 +13,6 @@ help: try wrapping the expression in `Some` LL | return Some(x); | +++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr b/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr index 45cdd3d2ddca5..16808f29daca1 100644 --- a/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr +++ b/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr @@ -7,6 +7,6 @@ LL | let _b = A { y: Arc::new(3), ..a }; | cannot move out of here | move occurs because `a.x` has type `Arc`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr index 0b8af90b41867..692d98bc53c82 100644 --- a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr +++ b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr @@ -4,6 +4,6 @@ error[E0451]: field `secret_uid` of struct `S` is private LL | let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ... | ^^^ field `secret_uid` is private -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/future-incompatible-lint-group.stderr b/tests/ui/future-incompatible-lint-group.stderr index a8fb100a74960..161fe82e3739c 100644 --- a/tests/ui/future-incompatible-lint-group.stderr +++ b/tests/ui/future-incompatible-lint-group.stderr @@ -24,5 +24,5 @@ LL | #![deny(future_incompatible)] | ^^^^^^^^^^^^^^^^^^^ = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(future_incompatible)]` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs index 7b16870723976..e2d51c6649ab9 100644 --- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs @@ -1,4 +1,4 @@ -// check-pass +// known-bug: #117606 #![feature(associated_type_defaults)] diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr new file mode 100644 index 0000000000000..685c2794967b2 --- /dev/null +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `::Bar<()>: Eq` is not satisfied + --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30 + | +LL | type Bar: Baz = i32; + | ^^^ the trait `Eq` is not implemented for `::Bar<()>` + | +note: required for `i32` to implement `Baz` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23 + | +LL | impl Baz for i32 where T::Bar<()>: Eq {} + | ^^^^^^ ^^^ ------- unsatisfied trait bound introduced here +note: required by a bound in `Foo::Bar` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:18 + | +LL | type Bar: Baz = i32; + | ^^^^^^^^^ required by this bound in `Foo::Bar` +help: consider further restricting the associated type + | +LL | trait Foo where ::Bar<()>: Eq { + | +++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr index 362aeae23614f..5dfc42bc8735a 100644 --- a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr @@ -15,6 +15,6 @@ note: due to current limitations in the borrow checker, this implies a `'static` LL | for<'a> I::Item<'a>: Debug, | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr index 1ee270398de4d..9a1a09b29df9a 100644 --- a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr @@ -17,6 +17,6 @@ LL | let _next = iter2.next(); = help: see for more information about variance = note: due to current limitations in the borrow checker, this implies a `'static` lifetime -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr index c67e02437cd8d..77f363ee87db8 100644 --- a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr @@ -17,6 +17,6 @@ note: due to current limitations in the borrow checker, this implies a `'static` LL | for<'a> I::Item<'a>: Sized, | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.stderr b/tests/ui/generic-associated-types/bugs/issue-87735.stderr index ebe2054ce5efc..b80e3e798bd41 100644 --- a/tests/ui/generic-associated-types/bugs/issue-87735.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-87735.stderr @@ -4,6 +4,6 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self LL | impl<'b, T, U> AsRef2 for Foo | ^ unconstrained type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/bugs/issue-87755.stderr b/tests/ui/generic-associated-types/bugs/issue-87755.stderr index 5e94db9b0c00f..e16312dbb2754 100644 --- a/tests/ui/generic-associated-types/bugs/issue-87755.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-87755.stderr @@ -4,6 +4,6 @@ error[E0275]: overflow evaluating the requirement `::Ass == _` LL | type Ass = Bar; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/bugs/issue-87803.stderr b/tests/ui/generic-associated-types/bugs/issue-87803.stderr index fe2abdedbf37c..31ed47749a87c 100644 --- a/tests/ui/generic-associated-types/bugs/issue-87803.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-87803.stderr @@ -7,6 +7,6 @@ LL | fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>; LL | fn scan<'a>(&mut self, s : &'a str) -> &'a str { | ^^^^ lifetimes do not match method in trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88382.stderr b/tests/ui/generic-associated-types/bugs/issue-88382.stderr index a9a70bb7130cb..9b061528e3beb 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-88382.stderr @@ -16,7 +16,11 @@ note: required by a bound in `do_something` | LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` +help: consider wrapping the function in a closure + | +LL | do_something(SomeImplementation(), |arg0: &mut std::iter::Empty| test(/* &mut <_ as Iterable>::Iterator<'_> */)); + | ++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.stderr b/tests/ui/generic-associated-types/bugs/issue-88460.stderr index b9e2c4186c14a..74418a0c0bd52 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88460.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-88460.stderr @@ -24,6 +24,6 @@ LL | fn test(value: T) LL | for<'a> T::Assoc<'a>: Marker, | ^^^^^^ required by this bound in `test` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.stderr b/tests/ui/generic-associated-types/bugs/issue-88526.stderr index 56857c6550bdc..ba87ac9185d30 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88526.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-88526.stderr @@ -4,6 +4,6 @@ error[E0207]: the type parameter `I` is not constrained by the impl trait, self LL | impl<'q, Q, I, F> A for TestB | ^ unconstrained type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.stderr b/tests/ui/generic-associated-types/bugs/issue-91762.stderr index 1045e80f046f2..b4ca65889ada0 100644 --- a/tests/ui/generic-associated-types/bugs/issue-91762.stderr +++ b/tests/ui/generic-associated-types/bugs/issue-91762.stderr @@ -10,6 +10,6 @@ help: consider specifying the generic arguments LL | ret = ::fmap::(arg); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/generic-associated-types/collections-project-default.stderr b/tests/ui/generic-associated-types/collections-project-default.stderr index 3c3ae24dd4730..db1deab92b834 100644 --- a/tests/ui/generic-associated-types/collections-project-default.stderr +++ b/tests/ui/generic-associated-types/collections-project-default.stderr @@ -11,6 +11,6 @@ LL | res found associated type `<>::Family as CollectionFamily>::Member` = note: an associated type was expected, but a different one was found -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/collectivity-regression.stderr b/tests/ui/generic-associated-types/collectivity-regression.stderr index a085096e1f8c5..0c395a1664f0d 100644 --- a/tests/ui/generic-associated-types/collectivity-regression.stderr +++ b/tests/ui/generic-associated-types/collectivity-regression.stderr @@ -20,5 +20,5 @@ help: consider restricting the type parameter to the `'static` lifetime LL | for<'a> T: Get = ()> + 'static, | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/const_params_have_right_type.stderr b/tests/ui/generic-associated-types/const_params_have_right_type.stderr index fdedd3bf5fbff..78992112a7c53 100644 --- a/tests/ui/generic-associated-types/const_params_have_right_type.stderr +++ b/tests/ui/generic-associated-types/const_params_have_right_type.stderr @@ -11,6 +11,6 @@ LL | impl Trait for () { LL | type Foo = u32; | ^^^^^^^^^^^^ found const parameter of type `u64` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr index 3b65b32f45d90..54dbe28bd0336 100644 --- a/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr +++ b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr @@ -13,6 +13,6 @@ help: consider constraining the associated type `::Y` to `Vec` LL | fn f = Vec>>(a: T::Y) { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/cross-crate-bounds.stderr b/tests/ui/generic-associated-types/cross-crate-bounds.stderr index 83ee04d5a6c60..ebd733c2ef1f8 100644 --- a/tests/ui/generic-associated-types/cross-crate-bounds.stderr +++ b/tests/ui/generic-associated-types/cross-crate-bounds.stderr @@ -10,6 +10,6 @@ note: required by a bound in `foo_defn::Foo::Bar` LL | type Bar: AsRef<()>; | ^^^^^^^^^ required by this bound in `Foo::Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/empty_generics.stderr b/tests/ui/generic-associated-types/empty_generics.stderr index b753181cf4808..1ac35b318fd88 100644 --- a/tests/ui/generic-associated-types/empty_generics.stderr +++ b/tests/ui/generic-associated-types/empty_generics.stderr @@ -9,5 +9,5 @@ LL | LL | } | - the item list ends here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr index 614c4a34c187d..84210eeb1a62b 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr @@ -7,6 +7,6 @@ LL | fn from_iter LendingIterator = A>>(iter: T) -> Self LL | fn from_iter LendingIterator = A>>(mut iter: I) -> Self { | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr index f6b0b644e4064..717d867057e77 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr @@ -7,6 +7,6 @@ LL | fn from_iter LendingIterator = A>>(iter: T) -> Self LL | fn from_iter LendingIterator = A>>(mut iter: I) -> Self { | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index 7ea7a7b2de7bc..8ae308303b8a3 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -7,5 +7,5 @@ LL | type Gat<'a> = &'a str; = note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr index 9013d42953001..bd3728cec8c82 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr +++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr @@ -16,6 +16,6 @@ LL | type A<'a> where Self: 'a; Fooy Fooer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs b/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs new file mode 100644 index 0000000000000..5ef9437c96875 --- /dev/null +++ b/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs @@ -0,0 +1,20 @@ +// check-pass + +trait Database: for<'r> HasValueRef<'r, Database = Self> {} + +trait HasValueRef<'r> { + type Database: Database; +} + +struct Any; + +impl Database for Any {} + +impl<'r> HasValueRef<'r> for Any { + // Make sure we don't have issues when the GAT assumption + // `>::Database = Any` isn't universally + // parameterized over `'r`. + type Database = Any; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-101020.stderr b/tests/ui/generic-associated-types/issue-101020.stderr index 91967fb850976..9c3753c2d1809 100644 --- a/tests/ui/generic-associated-types/issue-101020.stderr +++ b/tests/ui/generic-associated-types/issue-101020.stderr @@ -23,6 +23,6 @@ LL | fn consume(self, _f: F) LL | for<'a> Self::Item<'a>: FuncInput<'a, Self::Item<'a>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `LendingIterator::consume` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-102114.current.stderr b/tests/ui/generic-associated-types/issue-102114.current.stderr index 6e7a0b1f67f71..69ae5676ee02a 100644 --- a/tests/ui/generic-associated-types/issue-102114.current.stderr +++ b/tests/ui/generic-associated-types/issue-102114.current.stderr @@ -7,6 +7,6 @@ LL | type B<'b>; LL | type B = Wrapper; | ^ found 1 type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/generic-associated-types/issue-102114.next.stderr b/tests/ui/generic-associated-types/issue-102114.next.stderr index 6e7a0b1f67f71..69ae5676ee02a 100644 --- a/tests/ui/generic-associated-types/issue-102114.next.stderr +++ b/tests/ui/generic-associated-types/issue-102114.next.stderr @@ -7,6 +7,6 @@ LL | type B<'b>; LL | type B = Wrapper; | ^ found 1 type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/generic-associated-types/issue-102335-gat.stderr b/tests/ui/generic-associated-types/issue-102335-gat.stderr index 7a7900a1e656a..39ca7954edef1 100644 --- a/tests/ui/generic-associated-types/issue-102335-gat.stderr +++ b/tests/ui/generic-associated-types/issue-102335-gat.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | type A: S = ()>; | ^^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/generic-associated-types/issue-47206-where-clause.stderr b/tests/ui/generic-associated-types/issue-47206-where-clause.stderr index 7006744df4987..da0924312f167 100644 --- a/tests/ui/generic-associated-types/issue-47206-where-clause.stderr +++ b/tests/ui/generic-associated-types/issue-47206-where-clause.stderr @@ -7,6 +7,6 @@ LL | type Assoc3; LL | type Assoc3 = Vec where T: Iterator; | ^^^^^^^^ impl has extra requirement `T: Iterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/issue-67510-pass.base.stderr b/tests/ui/generic-associated-types/issue-67510-pass.base.stderr index 4cc68530ee1a6..f39d00554282a 100644 --- a/tests/ui/generic-associated-types/issue-67510-pass.base.stderr +++ b/tests/ui/generic-associated-types/issue-67510-pass.base.stderr @@ -13,6 +13,6 @@ LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr index 6bb7492af8114..55901cf450b67 100644 --- a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr +++ b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | impl UnsafeCopy for T { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index 2376bda8190d0..6bf832bb9e2a5 100644 --- a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -15,6 +15,6 @@ help: consider restricting type parameter `T` LL | impl> Fun for T { | ++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr index 2429531e4e5ab..d9f26ee6c291b 100644 --- a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -15,6 +15,6 @@ help: consider restricting type parameter `T` LL | impl> Fun for T { | ++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr index 11221353a92d4..3dc9ff10243fd 100644 --- a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -15,6 +15,6 @@ help: consider restricting type parameter `T` LL | impl> Fun for T { | ++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index 52300efc2d8ca..45fb65f6cf1e4 100644 --- a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -15,6 +15,6 @@ help: consider restricting type parameter `T` LL | impl> Fun for T { | ++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68648-2.stderr b/tests/ui/generic-associated-types/issue-68648-2.stderr index 0514e7bd6f69c..d71ad870d3c46 100644 --- a/tests/ui/generic-associated-types/issue-68648-2.stderr +++ b/tests/ui/generic-associated-types/issue-68648-2.stderr @@ -16,6 +16,6 @@ note: associated function defined here LL | fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } | ^^^^^^^^ -------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr index 20c07db4c04f3..ecb337bbceb91 100644 --- a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr +++ b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -18,6 +18,6 @@ help: consider further restricting this bound LL | impl> UnsafeCopy for T { | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr index 4b4fe43e8c4fd..ed837f3475338 100644 --- a/tests/ui/generic-associated-types/issue-71176.stderr +++ b/tests/ui/generic-associated-types/issue-71176.stderr @@ -14,6 +14,6 @@ help: add missing lifetime argument LL | inner: Box = B>>, | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-74684-1.stderr b/tests/ui/generic-associated-types/issue-74684-1.stderr index b93ee37987f27..4bc13d7b2894d 100644 --- a/tests/ui/generic-associated-types/issue-74684-1.stderr +++ b/tests/ui/generic-associated-types/issue-74684-1.stderr @@ -14,6 +14,6 @@ LL | let _x = T::identity(&a); LL | } | - `a` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr index 59b85abf5c8ce..e50e3df85b363 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.stderr +++ b/tests/ui/generic-associated-types/issue-74684-2.stderr @@ -17,6 +17,6 @@ note: required by a bound in `bug` LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { | ^^^^^^^^^^^^ required by this bound in `bug` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-76535.extended.stderr b/tests/ui/generic-associated-types/issue-76535.extended.stderr index 369b86d29284d..f6fe8b16902b1 100644 --- a/tests/ui/generic-associated-types/issue-76535.extended.stderr +++ b/tests/ui/generic-associated-types/issue-76535.extended.stderr @@ -14,6 +14,6 @@ help: add missing lifetime argument LL | let sub: Box = SubStruct>> = Box::new(SuperStruct::new(0)); | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-78671.extended.stderr b/tests/ui/generic-associated-types/issue-78671.extended.stderr index 1d8a3d410f8dc..a5d56256d283b 100644 --- a/tests/ui/generic-associated-types/issue-78671.extended.stderr +++ b/tests/ui/generic-associated-types/issue-78671.extended.stderr @@ -14,6 +14,6 @@ help: add missing generic argument LL | Box::new(Family) as &dyn CollectionFamily=usize> | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-79636-1.stderr b/tests/ui/generic-associated-types/issue-79636-1.stderr index 6e0d2ff4ded41..4076e951875e3 100644 --- a/tests/ui/generic-associated-types/issue-79636-1.stderr +++ b/tests/ui/generic-associated-types/issue-79636-1.stderr @@ -14,6 +14,6 @@ help: add missing generic argument LL | MInner: Monad = MOuter::Wrapped>, | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-79636-2.stderr b/tests/ui/generic-associated-types/issue-79636-2.stderr index 16287323995de..a8b63f150797f 100644 --- a/tests/ui/generic-associated-types/issue-79636-2.stderr +++ b/tests/ui/generic-associated-types/issue-79636-2.stderr @@ -14,6 +14,6 @@ help: add missing generic argument LL | W: SomeTrait = W>, | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr index 4f4f96a4b9218..488fbeceddd1e 100644 --- a/tests/ui/generic-associated-types/issue-80433.stderr +++ b/tests/ui/generic-associated-types/issue-80433.stderr @@ -14,6 +14,6 @@ help: add missing lifetime argument LL | fn test_simpler<'a>(dst: &'a mut impl TestMut = &'a mut f32>) | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr index e0fc225f463ae..5eb988ea042aa 100644 --- a/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr +++ b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr @@ -14,6 +14,6 @@ help: add missing generic argument LL | type CType: C = Self>; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-81862.stderr b/tests/ui/generic-associated-types/issue-81862.stderr index df30be65ec54b..730dc8fffe856 100644 --- a/tests/ui/generic-associated-types/issue-81862.stderr +++ b/tests/ui/generic-associated-types/issue-81862.stderr @@ -14,6 +14,6 @@ help: add missing lifetime argument LL | fn next(&mut self) -> Option>; | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-87258_a.stderr b/tests/ui/generic-associated-types/issue-87258_a.stderr index eae9bd9b16f2d..01f2a92f94a6b 100644 --- a/tests/ui/generic-associated-types/issue-87258_a.stderr +++ b/tests/ui/generic-associated-types/issue-87258_a.stderr @@ -6,5 +6,5 @@ LL | type FooFuture<'a> = impl Trait1; | = note: `FooFuture` must be used in combination with a concrete type within the same impl -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-87258_b.stderr b/tests/ui/generic-associated-types/issue-87258_b.stderr index 0ee665f38ad08..73f984dcfb868 100644 --- a/tests/ui/generic-associated-types/issue-87258_b.stderr +++ b/tests/ui/generic-associated-types/issue-87258_b.stderr @@ -6,5 +6,5 @@ LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; | = note: `Helper` must be used in combination with a concrete type within the same module -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr index a44bb6993d49d..c85b72fbfe11b 100644 --- a/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr +++ b/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr @@ -16,6 +16,6 @@ LL + #[derive(PartialEq)] LL | struct Foo; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-87429-specialization.stderr b/tests/ui/generic-associated-types/issue-87429-specialization.stderr index c259c89a712ec..44f871e71c57d 100644 --- a/tests/ui/generic-associated-types/issue-87429-specialization.stderr +++ b/tests/ui/generic-associated-types/issue-87429-specialization.stderr @@ -26,6 +26,6 @@ LL + #[derive(PartialEq)] LL | struct Foo; | -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-88287.stderr b/tests/ui/generic-associated-types/issue-88287.stderr index d77076a28fab6..79ac6d0f10bd2 100644 --- a/tests/ui/generic-associated-types/issue-88287.stderr +++ b/tests/ui/generic-associated-types/issue-88287.stderr @@ -22,6 +22,6 @@ help: consider relaxing the implicit `Sized` restriction LL | T: SearchableResource + ?Sized, | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr index ad40ee180019d..64cd55e684c65 100644 --- a/tests/ui/generic-associated-types/issue-88360.stderr +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -17,6 +17,6 @@ LL - *self.test() LL + self.test() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr index 2b1a25acfa430..ab75a92400601 100644 --- a/tests/ui/generic-associated-types/issue-88595.stderr +++ b/tests/ui/generic-associated-types/issue-88595.stderr @@ -10,5 +10,5 @@ note: for this opaque type LL | type B<'b> = impl Clone; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-90014-tait.stderr b/tests/ui/generic-associated-types/issue-90014-tait.stderr index b86e2a204b047..e4bcc92bf6e02 100644 --- a/tests/ui/generic-associated-types/issue-90014-tait.stderr +++ b/tests/ui/generic-associated-types/issue-90014-tait.stderr @@ -17,6 +17,6 @@ note: this item must have the opaque type in its signature in order to be able t LL | fn make_fut<'a>(&'a self) -> Self::Fut<'a> { | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr index d04788a919aaa..ed0b2085c8858 100644 --- a/tests/ui/generic-associated-types/issue-90014-tait2.stderr +++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/generic-associated-types/issue-90014.stderr b/tests/ui/generic-associated-types/issue-90014.stderr index 0d49398cac94a..2bb9d0c7ba609 100644 --- a/tests/ui/generic-associated-types/issue-90014.stderr +++ b/tests/ui/generic-associated-types/issue-90014.stderr @@ -17,6 +17,6 @@ help: copy the `where` clause predicates from the trait LL | type Fut<'a> = impl Future where Self: 'a; | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/generic-associated-types/issue-91139.migrate.stderr b/tests/ui/generic-associated-types/issue-91139.migrate.stderr index 690160577cd9c..23b7bf45afbb6 100644 --- a/tests/ui/generic-associated-types/issue-91139.migrate.stderr +++ b/tests/ui/generic-associated-types/issue-91139.migrate.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `<<` LL | <<<<<<< HEAD | ^^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-91883.stderr b/tests/ui/generic-associated-types/issue-91883.stderr index d5db962094ce9..ac636ebb648cb 100644 --- a/tests/ui/generic-associated-types/issue-91883.stderr +++ b/tests/ui/generic-associated-types/issue-91883.stderr @@ -22,6 +22,6 @@ help: copy the `where` clause predicates from the trait LL | type Cursor<'tx> = CursorImpl<'tx> where 'db: 'tx, Self: 'tx; | +++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/generic-associated-types/issue-92033.stderr b/tests/ui/generic-associated-types/issue-92033.stderr index ddc420a7b4e61..5dfd66d544a35 100644 --- a/tests/ui/generic-associated-types/issue-92033.stderr +++ b/tests/ui/generic-associated-types/issue-92033.stderr @@ -17,6 +17,6 @@ help: copy the `where` clause predicates from the trait LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture> where Self: 'a; | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/generic-associated-types/issue-92096.stderr b/tests/ui/generic-associated-types/issue-92096.stderr index 91a06d5acde1a..b9a16cf184e4c 100644 --- a/tests/ui/generic-associated-types/issue-92096.stderr +++ b/tests/ui/generic-associated-types/issue-92096.stderr @@ -4,5 +4,5 @@ error: `C` does not live long enough LL | async move { c.connect().await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-95305.stderr b/tests/ui/generic-associated-types/issue-95305.stderr index eb15cbc620acb..752bb32926cd5 100644 --- a/tests/ui/generic-associated-types/issue-95305.stderr +++ b/tests/ui/generic-associated-types/issue-95305.stderr @@ -4,6 +4,6 @@ error[E0637]: `'_` cannot be used here LL | fn foo(x: &impl Foo = u32>) { } | ^^ `'_` is a reserved lifetime name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr index 4246f8c069d4b..7ca0b2912a68a 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr @@ -19,6 +19,6 @@ LL | impl = i32>> M for T {} | | | unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr b/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr index 91a0300764084..ee90f61aabc74 100644 --- a/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr +++ b/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr @@ -12,6 +12,6 @@ help: copy the `where` clause predicates from the trait LL | type T<'a2, 'b2> = () where 'a2: 'b2; | ~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/missing-item-sugg.stderr b/tests/ui/generic-associated-types/missing-item-sugg.stderr index 378115f6d3893..1f142f7f6c12e 100644 --- a/tests/ui/generic-associated-types/missing-item-sugg.stderr +++ b/tests/ui/generic-associated-types/missing-item-sugg.stderr @@ -6,6 +6,6 @@ LL | impl missing_item_sugg::Foo for Local { | = help: implement the missing item: `type Gat = /* Type */ where T: std::fmt::Display;` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr index 8a71fc73a9d2d..d0eb27343a967 100644 --- a/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr +++ b/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -13,6 +13,6 @@ LL - type Assoc<'a, 'b> = () where 'a: 'b; LL + type Assoc<'a, 'b> = () ; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/missing_lifetime_const.stderr b/tests/ui/generic-associated-types/missing_lifetime_const.stderr index 41945aabfb58c..ac09608640763 100644 --- a/tests/ui/generic-associated-types/missing_lifetime_const.stderr +++ b/tests/ui/generic-associated-types/missing_lifetime_const.stderr @@ -14,6 +14,6 @@ help: add missing lifetime argument LL | let _: ::Assoc<'a, 3>; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/multiple-type-params-with-unmet-bounds.stderr b/tests/ui/generic-associated-types/multiple-type-params-with-unmet-bounds.stderr index 72a987b4a1d58..57bff7c9e054f 100644 --- a/tests/ui/generic-associated-types/multiple-type-params-with-unmet-bounds.stderr +++ b/tests/ui/generic-associated-types/multiple-type-params-with-unmet-bounds.stderr @@ -10,6 +10,6 @@ note: required by a bound in `Trait::P` LL | type P; | ^^^^ required by this bound in `Trait::P` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/own-bound-span.stderr b/tests/ui/generic-associated-types/own-bound-span.stderr index 4a0566ca7b519..7c34a0acdbe08 100644 --- a/tests/ui/generic-associated-types/own-bound-span.stderr +++ b/tests/ui/generic-associated-types/own-bound-span.stderr @@ -10,6 +10,6 @@ note: required by a bound in `D::P` LL | type P; | ^^^^ required by this bound in `D::P` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr index 53d5f9de65754..838d37cc64f30 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr @@ -2,9 +2,7 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` --> $DIR/trait-path-expected-token.rs:5:33 | LL | fn f1<'a>(arg : Box>) {} - | - ^ expected one of 7 possible tokens - | | - | maybe try to close unmatched angle bracket + | ^ expected one of 7 possible tokens -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr b/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr index cf2b1763fc9da..06dbf00af633e 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr @@ -10,9 +10,7 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-expressions.rs:16:36 | LL | fn f2<'a>(arg : Box>) {} - | - ^ expected one of `,`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `:`, or `>` | help: you might have meant to end the type parameters here | diff --git a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr index bfddb6dc693ca..4bc57f550963f 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr @@ -8,9 +8,7 @@ error: expected one of `>`, a const expression, lifetime, or type, found `=` --> $DIR/trait-path-missing-gen_arg.rs:11:30 | LL | fn f1<'a>(arg : Box>) {} - | - ^ expected one of `>`, a const expression, lifetime, or type - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `>`, a const expression, lifetime, or type error: aborting due to 2 previous errors diff --git a/tests/ui/generic-associated-types/parse/trait-path-segments.stderr b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr index 8bc737d675204..0ab155590e22d 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-segments.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -2,9 +2,7 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=` --> $DIR/trait-path-segments.rs:6:36 | LL | fn f1<'a>(arg : Box>) {} - | - ^ expected one of 8 possible tokens - | | - | maybe try to close unmatched angle bracket + | ^ expected one of 8 possible tokens | help: you might have meant to end the type parameters here | @@ -15,9 +13,7 @@ error: expected one of `,`, `::`, `:`, or `>`, found `=` --> $DIR/trait-path-segments.rs:17:35 | LL | impl::Y<'a> = &'a u32>> Z for T {} - | - ^ expected one of `,`, `::`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `::`, `:`, or `>` | help: you might have meant to end the type parameters here | @@ -28,9 +24,7 @@ error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=` --> $DIR/trait-path-segments.rs:28:25 | LL | impl = &'a u32>> Z for T {} - | - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` | help: you might have meant to end the type parameters here | diff --git a/tests/ui/generic-associated-types/parse/trait-path-types.stderr b/tests/ui/generic-associated-types/parse/trait-path-types.stderr index 8f7a73c95b65f..ec1aa71846d6a 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-types.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-types.stderr @@ -2,9 +2,7 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:6:37 | LL | fn f<'a>(arg : Box>) {} - | - ^ expected one of `,`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `:`, or `>` | help: you might have meant to end the type parameters here | @@ -15,9 +13,7 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:11:37 | LL | fn f1<'a>(arg : Box) = &'a ()>>) {} - | - ^ expected one of `,`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `:`, or `>` | help: you might have meant to end the type parameters here | @@ -28,9 +24,7 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/trait-path-types.rs:16:33 | LL | fn f1<'a>(arg : Box>) {} - | -- ^ expected one of `,`, `:`, or `>` - | | - | maybe try to close unmatched angle bracket + | ^ expected one of `,`, `:`, or `>` | help: you might have meant to end the type parameters here | diff --git a/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr index aae9a56bb6128..1b3b264e75088 100644 --- a/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr +++ b/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -4,6 +4,6 @@ error[E0275]: overflow evaluating the requirement ` as Foo>::Item == _ LL | type Item = [T] where [T]: Sized; | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/projection-bound-cycle.stderr b/tests/ui/generic-associated-types/projection-bound-cycle.stderr index b1b8afeecd02f..6f5eee9928ce6 100644 --- a/tests/ui/generic-associated-types/projection-bound-cycle.stderr +++ b/tests/ui/generic-associated-types/projection-bound-cycle.stderr @@ -4,6 +4,6 @@ error[E0275]: overflow evaluating the requirement `::Item == _` LL | type Item = str where str: Sized; | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/trait-objects.base.stderr b/tests/ui/generic-associated-types/trait-objects.base.stderr index 556422c272cf6..e3cfd46524ea9 100644 --- a/tests/ui/generic-associated-types/trait-objects.base.stderr +++ b/tests/ui/generic-associated-types/trait-objects.base.stderr @@ -13,6 +13,6 @@ LL | type Item<'a> where Self: 'a; | ^^^^ ...because it contains the generic associated type `Item` = help: consider moving `Item` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/trait-objects.extended.stderr b/tests/ui/generic-associated-types/trait-objects.extended.stderr index 45b64d2b02483..9f9418e20b9dc 100644 --- a/tests/ui/generic-associated-types/trait-objects.extended.stderr +++ b/tests/ui/generic-associated-types/trait-objects.extended.stderr @@ -14,6 +14,6 @@ LL | x.size_hint().0 | = note: due to current limitations in the borrow checker, this implies a `'static` lifetime -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index d30f7af170dcc..43cdf818c4694 100644 --- a/tests/ui/generic-const-items/const-trait-impl.rs +++ b/tests/ui/generic-const-items/const-trait-impl.rs @@ -7,8 +7,8 @@ #![allow(incomplete_features)] #![crate_type = "lib"] -// FIXME(generic_const_items): Interpret `~const` as always-const. -const CREATE: T = T::create(); +// FIXME(generic_const_items, effects): Introduce `const` bounds to make this work. +const CREATE: T = T::create(); pub const K0: i32 = CREATE::; pub const K1: i32 = CREATE; // arg inferred diff --git a/tests/ui/generic-const-items/const-trait-impl.stderr b/tests/ui/generic-const-items/const-trait-impl.stderr index 34360c581d536..e7e905427960b 100644 --- a/tests/ui/generic-const-items/const-trait-impl.stderr +++ b/tests/ui/generic-const-items/const-trait-impl.stderr @@ -1,11 +1,11 @@ error[E0015]: cannot call non-const fn `::create` in constants - --> $DIR/const-trait-impl.rs:11:37 + --> $DIR/const-trait-impl.rs:11:30 | -LL | const CREATE: T = T::create(); - | ^^^^^^^^^^^ +LL | const CREATE: T = T::create(); + | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr b/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr index 930080f7c378d..1475d988ea482 100644 --- a/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr +++ b/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr @@ -6,5 +6,5 @@ LL | const ARRAY: [i32; Self::LEN]; | = help: try adding a `where` bound using this expression: `where [(); Self::LEN]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-const-items/parameter-defaults.stderr b/tests/ui/generic-const-items/parameter-defaults.stderr index 62da45e55d6b6..598622869454f 100644 --- a/tests/ui/generic-const-items/parameter-defaults.stderr +++ b/tests/ui/generic-const-items/parameter-defaults.stderr @@ -4,5 +4,5 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type` LL | const NONE: Option = None::; | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generic-const-items/reference-outlives-referent.stderr b/tests/ui/generic-const-items/reference-outlives-referent.stderr index 2b57713b5c109..34553c51654bb 100644 --- a/tests/ui/generic-const-items/reference-outlives-referent.stderr +++ b/tests/ui/generic-const-items/reference-outlives-referent.stderr @@ -15,6 +15,6 @@ note: but the referenced data is only valid for the lifetime `'b` as defined her LL | const Q<'a, 'b>: &'a &'b () = &&(); | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr index c3ef94529a49b..942e5dbd88ef4 100644 --- a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr +++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.stderr @@ -13,6 +13,6 @@ LL | where LL | String: Copy; | ^^^^ required by this bound in `UNUSABLE` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr index a68400798d81c..b8438a0589c5c 100644 --- a/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr +++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr @@ -6,6 +6,6 @@ LL | | where LL | | String: Copy; | |_________________^ entering unreachable code -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.stderr index bed213b0caa7a..f522190e8aa32 100644 --- a/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.stderr +++ b/tests/ui/generic-const-items/unsatisfied-evaluatable-bounds.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of `POSITIVE::<0>::{constant#0}` failed LL | [(); N - 1]:; | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/generics/generic-extern.stderr b/tests/ui/generics/generic-extern.stderr index c90215b612d4c..4d9f6fedef14e 100644 --- a/tests/ui/generics/generic-extern.stderr +++ b/tests/ui/generics/generic-extern.stderr @@ -6,6 +6,6 @@ LL | fn foo(); | = help: replace the type parameters with concrete types like `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0044`. diff --git a/tests/ui/generics/generic-function-item-where-type.stderr b/tests/ui/generics/generic-function-item-where-type.stderr index 88594129caaba..00e62843cb4b6 100644 --- a/tests/ui/generics/generic-function-item-where-type.stderr +++ b/tests/ui/generics/generic-function-item-where-type.stderr @@ -7,6 +7,6 @@ LL | foo::

    () = help: `main` is a function item, not a type = help: function item types cannot be named directly -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/generics/generic-impl-less-params-with-defaults.stderr b/tests/ui/generics/generic-impl-less-params-with-defaults.stderr index 262561fa81e6c..11227328e1b95 100644 --- a/tests/ui/generics/generic-impl-less-params-with-defaults.stderr +++ b/tests/ui/generics/generic-impl-less-params-with-defaults.stderr @@ -16,6 +16,6 @@ help: add missing generic argument LL | Foo::::new(); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-impl-more-params-with-defaults.stderr b/tests/ui/generics/generic-impl-more-params-with-defaults.stderr index 2f4682c4e5a97..c5812abfd3dfa 100644 --- a/tests/ui/generics/generic-impl-more-params-with-defaults.stderr +++ b/tests/ui/generics/generic-impl-more-params-with-defaults.stderr @@ -12,6 +12,6 @@ note: struct defined here, with at most 2 generic parameters: `T`, `A` LL | struct Vec( | ^^^ - -------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-lifetime-trait-impl.stderr b/tests/ui/generics/generic-lifetime-trait-impl.stderr index 4ae5098a121f5..6974c8ad04573 100644 --- a/tests/ui/generics/generic-lifetime-trait-impl.stderr +++ b/tests/ui/generics/generic-lifetime-trait-impl.stderr @@ -7,6 +7,6 @@ LL | fn bar<'b, T: Bar<'b>>(self) -> &'b str; LL | fn bar>(self) -> &'a str { panic!() } | ^^^^^^^^^^^^ lifetimes do not match method in trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/generics/generic-type-less-params-with-defaults.stderr b/tests/ui/generics/generic-type-less-params-with-defaults.stderr index 6450bbd8b4326..6f79b09f6cd33 100644 --- a/tests/ui/generics/generic-type-less-params-with-defaults.stderr +++ b/tests/ui/generics/generic-type-less-params-with-defaults.stderr @@ -14,6 +14,6 @@ help: add missing generic argument LL | let _: Vec; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-type-more-params-with-defaults.stderr b/tests/ui/generics/generic-type-more-params-with-defaults.stderr index 4d01ba1f453d8..c44f6b7ddc02d 100644 --- a/tests/ui/generics/generic-type-more-params-with-defaults.stderr +++ b/tests/ui/generics/generic-type-more-params-with-defaults.stderr @@ -12,6 +12,6 @@ note: struct defined here, with at most 2 generic parameters: `T`, `A` LL | struct Vec( | ^^^ - -------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-type-params-forward-mention.stderr b/tests/ui/generics/generic-type-params-forward-mention.stderr index fa661c274ebca..d7a6faa19410d 100644 --- a/tests/ui/generics/generic-type-params-forward-mention.stderr +++ b/tests/ui/generics/generic-type-params-forward-mention.stderr @@ -4,6 +4,6 @@ error[E0128]: generic parameters with a default cannot use forward declared iden LL | struct Foo, U = bool>(T, U); | ^ defaulted generic parameters cannot be forward declared -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/generics/issue-59508-1.stderr b/tests/ui/generics/issue-59508-1.stderr index 1c510044f806f..7d4fdb2d87911 100644 --- a/tests/ui/generics/issue-59508-1.stderr +++ b/tests/ui/generics/issue-59508-1.stderr @@ -4,5 +4,5 @@ error: lifetime parameters must be declared prior to type and const parameters LL | pub fn do_things() { | ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generics/issue-59508.stderr b/tests/ui/generics/issue-59508.stderr index fd23b6276f92b..aeaf0187eb51b 100644 --- a/tests/ui/generics/issue-59508.stderr +++ b/tests/ui/generics/issue-59508.stderr @@ -4,5 +4,5 @@ error: lifetime parameters must be declared prior to type and const parameters LL | pub fn do_things() { | ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr index 6791182238c72..3f4f50562e252 100644 --- a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr +++ b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr @@ -11,6 +11,6 @@ note: required by a bound in `Tsized` LL | trait Tsized {} | ^^^^^^^^^^^^^^^^^ required by this bound in `Tsized` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generics/issue-79605.stderr b/tests/ui/generics/issue-79605.stderr index c5584962dc9e2..67fed200f9693 100644 --- a/tests/ui/generics/issue-79605.stderr +++ b/tests/ui/generics/issue-79605.stderr @@ -9,6 +9,6 @@ help: use type parameters instead LL | impl X<'_, T> {} | +++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/generics/issue-80512-param-reordering-with-defaults.stderr b/tests/ui/generics/issue-80512-param-reordering-with-defaults.stderr index 70793a9c92084..d7e12f07e060b 100644 --- a/tests/ui/generics/issue-80512-param-reordering-with-defaults.stderr +++ b/tests/ui/generics/issue-80512-param-reordering-with-defaults.stderr @@ -4,5 +4,5 @@ error: lifetime parameters must be declared prior to type and const parameters LL | struct S(&'a T); | ---------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T = ()>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generics/issue-83556.stderr b/tests/ui/generics/issue-83556.stderr index 93affaffe60c3..0c5a65f0c3d86 100644 --- a/tests/ui/generics/issue-83556.stderr +++ b/tests/ui/generics/issue-83556.stderr @@ -4,5 +4,5 @@ error: lifetime parameters must be declared prior to type and const parameters LL | struct Foo(&'a ()); | ----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generics/issue-95208-ignore-qself.stderr b/tests/ui/generics/issue-95208-ignore-qself.stderr index acbc1300d00fd..cf40e857d42ba 100644 --- a/tests/ui/generics/issue-95208-ignore-qself.stderr +++ b/tests/ui/generics/issue-95208-ignore-qself.stderr @@ -6,5 +6,5 @@ LL | impl Struct where ::Item:: std:: | | | help: use single colon: `:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generics/issue-95208.stderr b/tests/ui/generics/issue-95208.stderr index 559527663e8a8..0d856d096affc 100644 --- a/tests/ui/generics/issue-95208.stderr +++ b/tests/ui/generics/issue-95208.stderr @@ -6,5 +6,5 @@ LL | impl Struct where T:: std::fmt::Display { | | | help: use single colon: `:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generics/issue-98432.stderr b/tests/ui/generics/issue-98432.stderr index 0736d94106e7d..2b09d43960f62 100644 --- a/tests/ui/generics/issue-98432.stderr +++ b/tests/ui/generics/issue-98432.stderr @@ -9,6 +9,6 @@ LL | struct _Obligation where T:; | | | help: try introducing a local generic parameter here: `` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/generics/param-in-ct-in-ty-param-default.stderr b/tests/ui/generics/param-in-ct-in-ty-param-default.stderr index ab09ebcae7197..03dbb3eb9fc5b 100644 --- a/tests/ui/generics/param-in-ct-in-ty-param-default.stderr +++ b/tests/ui/generics/param-in-ct-in-ty-param-default.stderr @@ -5,7 +5,7 @@ LL | struct Foo()]>(T, U); | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generics/single-colon-path-not-const-generics.stderr b/tests/ui/generics/single-colon-path-not-const-generics.stderr index 96f07e190c1e2..d61562bb199ff 100644 --- a/tests/ui/generics/single-colon-path-not-const-generics.stderr +++ b/tests/ui/generics/single-colon-path-not-const-generics.stderr @@ -8,5 +8,5 @@ LL | a: Vec, | = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/generics/slightly-nice-generic-literal-messages.stderr b/tests/ui/generics/slightly-nice-generic-literal-messages.stderr index 83ef522ab46e8..9811d30cf6a89 100644 --- a/tests/ui/generics/slightly-nice-generic-literal-messages.stderr +++ b/tests/ui/generics/slightly-nice-generic-literal-messages.stderr @@ -9,6 +9,6 @@ LL | 1 => {} = note: expected struct `Foo<{float}, _>` found type `{integer}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generics/unclosed-generics-in-impl-def.rs b/tests/ui/generics/unclosed-generics-in-impl-def.rs new file mode 100644 index 0000000000000..2ec99b16e552b --- /dev/null +++ b/tests/ui/generics/unclosed-generics-in-impl-def.rs @@ -0,0 +1,2 @@ +impl> From for Canonical {} //~ ERROR expected +fn main() {} diff --git a/tests/ui/generics/unclosed-generics-in-impl-def.stderr b/tests/ui/generics/unclosed-generics-in-impl-def.stderr new file mode 100644 index 0000000000000..aa1977ad82a68 --- /dev/null +++ b/tests/ui/generics/unclosed-generics-in-impl-def.stderr @@ -0,0 +1,13 @@ +error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From` + --> $DIR/unclosed-generics-in-impl-def.rs:1:46 + | +LL | impl> From for Canonical {} + | ^^^^ expected one of `+`, `,`, `::`, `=`, or `>` + | +help: you might have meant to end the type parameters here + | +LL | impl>> From for Canonical {} + | + + +error: aborting due to 1 previous error + diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr index 6ce56ba4b7ce5..357d3a4a124d9 100644 --- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr +++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr @@ -9,6 +9,6 @@ LL | [_, 99.., _] => {}, = note: expected struct `std::ops::Range<{integer}>` found type `{integer}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr index ee5b0e11c66fa..b44a69525a65c 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr @@ -7,6 +7,6 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; = note: see issue #67264 for more information = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr index cb7f998df7a5b..8dfc46069f13f 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr @@ -11,5 +11,5 @@ help: add a space between the pattern and `=>` LL | 74.. => {}, | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/half-open-range-patterns/pat-tuple-5.stderr b/tests/ui/half-open-range-patterns/pat-tuple-5.stderr index 43e7f03b8b4ef..a7dd413979237 100644 --- a/tests/ui/half-open-range-patterns/pat-tuple-5.stderr +++ b/tests/ui/half-open-range-patterns/pat-tuple-5.stderr @@ -9,6 +9,6 @@ LL | (PAT ..) => {} = note: expected tuple `({integer}, {integer})` found type `u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs index 55353999b6788..9ffc2190d20d1 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs @@ -17,7 +17,7 @@ fn main() { } match x as i32 { 0..5+1 => errors_only.push(x), - //~^ error: expected one of `=>`, `if`, or `|`, found `+` + //~^ error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `+` 1 | -3..0 => first_or.push(x), y @ (0..5 | 6) => or_two.push(y), y @ 0..const { 5 + 1 } => assert_eq!(y, 5), diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr index 19ebcaf0f3699..05235c9b92295 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -1,8 +1,8 @@ -error: expected one of `=>`, `if`, or `|`, found `+` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `+` --> $DIR/range_pat_interactions1.rs:19:17 | LL | 0..5+1 => errors_only.push(x), - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error[E0408]: variable `n` is not bound in all patterns --> $DIR/range_pat_interactions1.rs:10:25 diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs index 4615ebd688a9c..b212bfbe093eb 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs @@ -9,7 +9,7 @@ fn main() { match x as i32 { 0..=(5+1) => errors_only.push(x), //~^ error: inclusive range with no end - //~| error: expected one of `=>`, `if`, or `|`, found `(` + //~| error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `(` 1 | -3..0 => first_or.push(x), y @ (0..5 | 6) => or_two.push(y), y @ 0..const { 5 + 1 } => assert_eq!(y, 5), diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr index 13a5542a4741f..0129f927e3464 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -6,11 +6,11 @@ LL | 0..=(5+1) => errors_only.push(x), | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `=>`, `if`, or `|`, found `(` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `(` --> $DIR/range_pat_interactions2.rs:10:17 | LL | 0..=(5+1) => errors_only.push(x), - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error: aborting due to 2 previous errors diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr index ec3472a503684..eca5c3301801f 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr @@ -4,6 +4,6 @@ error[E0527]: pattern requires 2 elements but array has 8 LL | let [first_three @ ..3, rest @ 2..] = xs; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 8 elements -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/hashmap/hashmap-index-mut.stderr b/tests/ui/hashmap/hashmap-index-mut.stderr index c1948ab627149..2381b8ecb9692 100644 --- a/tests/ui/hashmap/hashmap-index-mut.stderr +++ b/tests/ui/hashmap/hashmap-index-mut.stderr @@ -14,6 +14,6 @@ LL | map.get_mut(&0).map(|val| { *val = 1; }); LL | let val = map.entry(&0).or_insert(1); | +++++++++ ~~~~~~~ ~~~~~~~~~~~~ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/hashmap/hashmap-iter-value-lifetime.stderr b/tests/ui/hashmap/hashmap-iter-value-lifetime.stderr index de2591329c887..5cf188702daba 100644 --- a/tests/ui/hashmap/hashmap-iter-value-lifetime.stderr +++ b/tests/ui/hashmap/hashmap-iter-value-lifetime.stderr @@ -10,6 +10,6 @@ LL | LL | println!("{}", *thing); | ------ immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/hashmap/hashmap-lifetimes.stderr b/tests/ui/hashmap/hashmap-lifetimes.stderr index 497c7d1216cd9..a52f956d063ab 100644 --- a/tests/ui/hashmap/hashmap-lifetimes.stderr +++ b/tests/ui/hashmap/hashmap-lifetimes.stderr @@ -8,6 +8,6 @@ LL | my_stuff.insert(1, 43); LL | it; | -- immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-error.rs b/tests/ui/higher-ranked/higher-ranked-lifetime-error.rs new file mode 100644 index 0000000000000..aee5db8366948 --- /dev/null +++ b/tests/ui/higher-ranked/higher-ranked-lifetime-error.rs @@ -0,0 +1,14 @@ +fn assert_all(_f: F) +where + F: FnMut(&String) -> T, +{ +} + +fn id(x: &String) -> &String { + x +} + +fn main() { + assert_all::<_, &String>(id); + //~^ mismatched types +} diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr new file mode 100644 index 0000000000000..d0892fd8b0953 --- /dev/null +++ b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/higher-ranked-lifetime-error.rs:12:5 + | +LL | assert_all::<_, &String>(id); + | ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&String` + found reference `&String` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index b7264c7e933f3..7cb7edfafeb66 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -12,6 +12,6 @@ LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } found enum `Option fn(&'a u32, &'a u32) -> &'a u32>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr index 2355979b0f95d..c6adbd91e7860 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -12,6 +12,6 @@ LL | | fn(&'x u32)) } found enum `Option` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr index 269cde54c7e3d..a8e00125fc63a 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr @@ -15,5 +15,5 @@ LL | | fn(&'y u32)) } = help: consider adding the following bound: `'x: 'y` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr index 5241b475d5ca1..c6d6f50832829 100644 --- a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr +++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr @@ -9,6 +9,6 @@ LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub; = note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)` found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr index 520938a633514..916854e07afbe 100644 --- a/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr +++ b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr @@ -7,5 +7,5 @@ LL | test::(&mut 42); = note: `FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`... = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr index 8ab88c580755b..77aa37cefe363 100644 --- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr +++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr @@ -14,6 +14,6 @@ LL | where LL | for<'w> fn(&'w ()): Fn(&'w ()), | ^^^^^^^^^^ required by this bound in `ice` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr index 139c844d8a225..67417a5e525cf 100644 --- a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr @@ -16,6 +16,6 @@ LL | f = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` found reference `&dyn Fn(u32)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr index f014eab8601fa..7f81ee331bf65 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-cache-issue-54302.stderr @@ -7,5 +7,5 @@ LL | assert_deserialize_owned::<&'static str>(); = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`... = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.stderr index 70d5b3c2ec58c..10904515fd8f5 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-debruijn-in-receiver.stderr @@ -9,6 +9,6 @@ LL | foo.insert(); | second mutable borrow occurs here | first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr index db5fc4bf1baea..f269babcf71aa 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr @@ -9,6 +9,6 @@ LL | let _: for<'b> fn(&'b u32) = foo(); = note: expected fn pointer `for<'b> fn(&'b u32)` found fn pointer `fn(&u32)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr index 364b613fc7717..9697a270b8aa0 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -7,5 +7,5 @@ LL | foo::<()>(); = note: `()` must implement `Trait fn(&'b u32)>` = note: ...but it actually implements `Trait`, for some specific lifetime `'0` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr index cb2ce8a4116aa..cf64c2acdbe9c 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -7,5 +7,5 @@ LL | foo::<()>(); = note: `()` must implement `Trait fn(Cell<&'b u32>)>` = note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr index b1b8ffa8c5483..e10da26665ebb 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr @@ -18,6 +18,6 @@ help: consider further restricting this bound LL | where B : Qux + for<'ccx> Bar<'ccx> | +++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.stderr index 25af011e3fc41..b1081c073ef01 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-identity-fn-borrows.stderr @@ -9,6 +9,6 @@ LL | x = 5; LL | drop(y); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr index a94c80eb30b16..795484f110884 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr @@ -67,5 +67,5 @@ LL | | } | = help: a `loop` may express intention better if this is on purpose -error: aborting due to previous error; 4 warnings emitted +error: aborting due to 1 previous error; 4 warnings emitted diff --git a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr index 3f874220a2708..c50e79dd4cc48 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr @@ -7,5 +7,5 @@ LL | assert_foo::(); = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr b/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr index 0f051be2128b0..99d088799fbde 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-58451.stderr @@ -14,6 +14,6 @@ help: provide the argument LL | f(&[f(/* i */)]); | ~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/higher-ranked/trait-bounds/issue-95230.next.stderr b/tests/ui/higher-ranked/trait-bounds/issue-95230.next.stderr index d4bc5b67220a0..6155579c9fa8f 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-95230.next.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-95230.next.stderr @@ -14,6 +14,6 @@ LL | where LL | for<'a> &'a mut Self:; | ^^^^^^^^^^^^ required by this bound in `Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr index 7b0743cc7c5ce..64707642eeb01 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -22,6 +22,6 @@ note: required by a bound in `call` LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr index 4ef96cd954106..1cf364aa9f6a1 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | foo(bar, "string", |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` - found trait `for<'a> FnOnce<(&'a &str,)>` + = note: expected trait `for<'a, 'b> FnOnce(&'a &'b str)` + found trait `for<'a> FnOnce(&'a &str)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:45:24 | @@ -23,8 +23,8 @@ error[E0308]: mismatched types LL | foo(bar, "string", |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` - found trait `for<'a> FnOnce<(&'a &str,)>` + = note: expected trait `for<'a, 'b> FnOnce(&'a &'b str)` + found trait `for<'a> FnOnce(&'a &str)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:45:24 | @@ -42,8 +42,8 @@ error[E0308]: mismatched types LL | foo(baz, "string", |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` - found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` + = note: expected trait `for<'a, 'b> FnOnce(&'a Wrapper<'b>)` + found trait `for<'a> FnOnce(&'a Wrapper<'_>)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:48:24 | @@ -61,8 +61,8 @@ error[E0308]: mismatched types LL | foo(baz, "string", |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` - found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` + = note: expected trait `for<'a, 'b> FnOnce(&'a Wrapper<'b>)` + found trait `for<'a> FnOnce(&'a Wrapper<'_>)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-71955.rs:48:24 | diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr index 55eaef78634c0..075e422e29c0b 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr @@ -24,6 +24,6 @@ LL | Y: for<'a> Yokeable<'a>, LL | for<'a> >::Output: IsCovariant<'a> | ^^^^^^^^^^^^^^^ required by this bound in `upcast` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr index 081dbb67df85a..a2ec96f1a2d0f 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr @@ -18,6 +18,6 @@ LL | fn weird_bound() -> X LL | for<'a> >::Out: Copy | ^^^^ required by this bound in `weird_bound` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/hygiene/arguments.stderr b/tests/ui/hygiene/arguments.stderr index 714178375f2d1..0d8d652b6f33d 100644 --- a/tests/ui/hygiene/arguments.stderr +++ b/tests/ui/hygiene/arguments.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `S` in this scope LL | m!(S, S); | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/hygiene/cross-crate-glob-hygiene.stderr b/tests/ui/hygiene/cross-crate-glob-hygiene.stderr index 7369e77d0709e..1abc739fc362d 100644 --- a/tests/ui/hygiene/cross-crate-glob-hygiene.stderr +++ b/tests/ui/hygiene/cross-crate-glob-hygiene.stderr @@ -6,6 +6,6 @@ LL | let x = my_struct!(create); | = note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr index 46314cdd5ab4e..a5d509fab996f 100644 --- a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr +++ b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr @@ -4,6 +4,6 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope LL | let x = MyStruct {}; | ^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/hygiene/cross-crate-name-hiding.stderr b/tests/ui/hygiene/cross-crate-name-hiding.stderr index f8840c8f85a33..4abd14f935581 100644 --- a/tests/ui/hygiene/cross-crate-name-hiding.stderr +++ b/tests/ui/hygiene/cross-crate-name-hiding.stderr @@ -4,6 +4,6 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope LL | let x = MyStruct {}; | ^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/hygiene/cross-crate-redefine.stderr b/tests/ui/hygiene/cross-crate-redefine.stderr index 4f1419de42677..c0fd3f4b7ebf2 100644 --- a/tests/ui/hygiene/cross-crate-redefine.stderr +++ b/tests/ui/hygiene/cross-crate-redefine.stderr @@ -10,6 +10,6 @@ LL | my_struct!(define); = note: `MyStruct` must be defined only once in the type namespace of this module = note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/hygiene/expansion-info-reset.stderr b/tests/ui/hygiene/expansion-info-reset.stderr index 64d27e0648700..a3ae5042f0bc7 100644 --- a/tests/ui/hygiene/expansion-info-reset.stderr +++ b/tests/ui/hygiene/expansion-info-reset.stderr @@ -9,5 +9,5 @@ help: you might be missing a string literal to format with LL | format_args!("{}", { #[derive(Clone)] struct S; }); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr index 7ed15e89caafa..78e6376bca2e8 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr @@ -25,8 +25,8 @@ LL | a!(); | ---- in this macro invocation | = help: consider importing one of these items: - std::mem core::mem + std::mem = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared crate or module `my_core` diff --git a/tests/ui/hygiene/fields-definition.stderr b/tests/ui/hygiene/fields-definition.stderr index 9d091cedd237d..701986ea76e7f 100644 --- a/tests/ui/hygiene/fields-definition.stderr +++ b/tests/ui/hygiene/fields-definition.stderr @@ -11,6 +11,6 @@ LL | legacy!(a); | = note: this error originates in the macro `legacy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/hygiene/fields-numeric-borrowck.stderr b/tests/ui/hygiene/fields-numeric-borrowck.stderr index fb90825c0d93d..a2dd83d560fe4 100644 --- a/tests/ui/hygiene/fields-numeric-borrowck.stderr +++ b/tests/ui/hygiene/fields-numeric-borrowck.stderr @@ -9,6 +9,6 @@ LL | let S { 0: ref mut borrow2 } = s; LL | borrow1.use_mut(); | ------- first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/hygiene/for-loop.stderr b/tests/ui/hygiene/for-loop.stderr index 932c951e7a541..5f334fd89603c 100644 --- a/tests/ui/hygiene/for-loop.stderr +++ b/tests/ui/hygiene/for-loop.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `iter` in this scope LL | iter.next(); | ^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/hygiene/hygienic-label-1.stderr b/tests/ui/hygiene/hygienic-label-1.stderr index deb6a205994aa..5529d8dc83656 100644 --- a/tests/ui/hygiene/hygienic-label-1.stderr +++ b/tests/ui/hygiene/hygienic-label-1.stderr @@ -9,6 +9,6 @@ LL | 'x: loop { foo!(); } | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/hygiene/hygienic-label-2.stderr b/tests/ui/hygiene/hygienic-label-2.stderr index f23e741debe9d..77a77c8472f65 100644 --- a/tests/ui/hygiene/hygienic-label-2.stderr +++ b/tests/ui/hygiene/hygienic-label-2.stderr @@ -4,6 +4,6 @@ error[E0426]: use of undeclared label `'x` LL | foo!(break 'x); | ^^ undeclared label `'x` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/hygiene/hygienic-label-3.stderr b/tests/ui/hygiene/hygienic-label-3.stderr index cf7f78a99e818..495afc69a9543 100644 --- a/tests/ui/hygiene/hygienic-label-3.stderr +++ b/tests/ui/hygiene/hygienic-label-3.stderr @@ -9,6 +9,6 @@ LL | foo!(); | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/hygiene/hygienic-label-4.stderr b/tests/ui/hygiene/hygienic-label-4.stderr index 1c93da02f6142..b9f447e15122e 100644 --- a/tests/ui/hygiene/hygienic-label-4.stderr +++ b/tests/ui/hygiene/hygienic-label-4.stderr @@ -4,6 +4,6 @@ error[E0426]: use of undeclared label `'x` LL | foo!(break 'x); | ^^ undeclared label `'x` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/hygiene/impl_items-2.stderr b/tests/ui/hygiene/impl_items-2.stderr index 3c0ffeb105752..e7128f83e110b 100644 --- a/tests/ui/hygiene/impl_items-2.stderr +++ b/tests/ui/hygiene/impl_items-2.stderr @@ -10,6 +10,6 @@ LL | fn foo() {} LL | fn foo() {} | ^^^^^^^^^^^ duplicate definition -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0201`. diff --git a/tests/ui/hygiene/impl_items.stderr b/tests/ui/hygiene/impl_items.stderr index 32ba3741a59e6..35f2750403de4 100644 --- a/tests/ui/hygiene/impl_items.stderr +++ b/tests/ui/hygiene/impl_items.stderr @@ -9,5 +9,5 @@ LL | foo::m!(); | = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/intercrate.stderr b/tests/ui/hygiene/intercrate.stderr index f108617fba615..230ad052db3ee 100644 --- a/tests/ui/hygiene/intercrate.stderr +++ b/tests/ui/hygiene/intercrate.stderr @@ -6,5 +6,5 @@ LL | assert_eq!(intercrate::foo::m!(), 1); | = note: this error originates in the macro `intercrate::foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/missing-self-diag.stderr b/tests/ui/hygiene/missing-self-diag.stderr index 690bcd03226fb..6921ed29e207f 100644 --- a/tests/ui/hygiene/missing-self-diag.stderr +++ b/tests/ui/hygiene/missing-self-diag.stderr @@ -12,6 +12,6 @@ LL | | } | = note: this error originates in the macro `call_bar` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0424`. diff --git a/tests/ui/hygiene/nested_macro_privacy.stderr b/tests/ui/hygiene/nested_macro_privacy.stderr index 1d11cd0f57139..44d11cfbafa9c 100644 --- a/tests/ui/hygiene/nested_macro_privacy.stderr +++ b/tests/ui/hygiene/nested_macro_privacy.stderr @@ -4,6 +4,6 @@ error[E0616]: field `i` of struct `S` is private LL | S::default().i; | ^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/hygiene/no_implicit_prelude-2018.stderr b/tests/ui/hygiene/no_implicit_prelude-2018.stderr index b22f3e75b6f4f..7b124edf6f6db 100644 --- a/tests/ui/hygiene/no_implicit_prelude-2018.stderr +++ b/tests/ui/hygiene/no_implicit_prelude-2018.stderr @@ -9,5 +9,5 @@ help: consider importing this macro LL + use std::print; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 1fd61084130a9..e0dc13c0c95c8 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:535:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:545:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/hygiene/pattern-macro.stderr b/tests/ui/hygiene/pattern-macro.stderr index edd05916ede2c..a9764cea49e59 100644 --- a/tests/ui/hygiene/pattern-macro.stderr +++ b/tests/ui/hygiene/pattern-macro.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `x` in this scope LL | x + 1; | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/hygiene/privacy-early.stderr b/tests/ui/hygiene/privacy-early.stderr index 0375ed56d9669..1c2f9ff5405f4 100644 --- a/tests/ui/hygiene/privacy-early.stderr +++ b/tests/ui/hygiene/privacy-early.stderr @@ -17,6 +17,6 @@ LL | foo::m!(); | --------- in this macro invocation = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/hygiene/privacy.stderr b/tests/ui/hygiene/privacy.stderr index 70a24304dda33..c677c88128865 100644 --- a/tests/ui/hygiene/privacy.stderr +++ b/tests/ui/hygiene/privacy.stderr @@ -10,6 +10,6 @@ note: the function `f` is defined here LL | fn f() {} | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/hygiene/trait_items.stderr b/tests/ui/hygiene/trait_items.stderr index f303534c709fc..016ee8f71f981 100644 --- a/tests/ui/hygiene/trait_items.stderr +++ b/tests/ui/hygiene/trait_items.stderr @@ -17,6 +17,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use foo::T; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/illegal-sized-bound/mutability-mismatch-arg.stderr b/tests/ui/illegal-sized-bound/mutability-mismatch-arg.stderr index 89613bd5c2028..b5ca62f4e23de 100644 --- a/tests/ui/illegal-sized-bound/mutability-mismatch-arg.stderr +++ b/tests/ui/illegal-sized-bound/mutability-mismatch-arg.stderr @@ -9,5 +9,5 @@ help: you need `&mut dyn Iterator` instead of `&dyn Iterator) -> u64 { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/illegal-ufcs-drop.stderr b/tests/ui/illegal-ufcs-drop.stderr index 7a5c0612c07eb..4f214a12747e4 100644 --- a/tests/ui/illegal-ufcs-drop.stderr +++ b/tests/ui/illegal-ufcs-drop.stderr @@ -7,6 +7,6 @@ LL | Drop::drop(&mut Foo) | explicit destructor calls not allowed | help: consider using `drop` function: `drop` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0040`. diff --git a/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr b/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr index 762698c4fc141..2ef35a377e2fc 100644 --- a/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr +++ b/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -11,6 +11,6 @@ LL | static_val(x); | `x` escapes the function body here | argument requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/impl-header-lifetime-elision/path-elided.stderr b/tests/ui/impl-header-lifetime-elision/path-elided.stderr index 18e4c618dba99..4df7ffb29ba6f 100644 --- a/tests/ui/impl-header-lifetime-elision/path-elided.stderr +++ b/tests/ui/impl-header-lifetime-elision/path-elided.stderr @@ -9,6 +9,6 @@ help: indicate the anonymous lifetime LL | impl MyTrait for Foo<'_> { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/impl-header-lifetime-elision/trait-elided.stderr b/tests/ui/impl-header-lifetime-elision/trait-elided.stderr index 74631a0378601..cbc6eee5a3fc5 100644 --- a/tests/ui/impl-header-lifetime-elision/trait-elided.stderr +++ b/tests/ui/impl-header-lifetime-elision/trait-elided.stderr @@ -9,6 +9,6 @@ help: indicate the anonymous lifetime LL | impl MyTrait<'_> for u32 {} | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr index 168a5aa18ec45..825682c52f9f3 100644 --- a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr +++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr @@ -13,6 +13,6 @@ help: to declare that `impl Sized + 'a` captures `'b`, you can add an explicit ` LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a + 'b { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr index cabba4bafafdd..b87e31acc1253 100644 --- a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr +++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr @@ -13,6 +13,6 @@ help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `' LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + 'b { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr index baeec6d5892d1..6c9b8cf24273b 100644 --- a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr +++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr @@ -8,6 +8,6 @@ LL | pub(super) fn step2<'a, 'b: 'a>() -> Tait<'a> { LL | super::step1::<'a, 'b>() | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr index d5086c7bc5152..158cfc8347c5a 100644 --- a/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr +++ b/tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr @@ -17,6 +17,6 @@ LL | let () = y; = note: expected type parameter `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry]) -> R` found unit type `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/auto-trait-coherence.next.stderr b/tests/ui/impl-trait/auto-trait-coherence.next.stderr index 7833ac688babf..3f979d1a50b33 100644 --- a/tests/ui/impl-trait/auto-trait-coherence.next.stderr +++ b/tests/ui/impl-trait/auto-trait-coherence.next.stderr @@ -7,6 +7,6 @@ LL | impl AnotherTrait for T {} LL | impl AnotherTrait for D { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/auto-trait-coherence.old.stderr b/tests/ui/impl-trait/auto-trait-coherence.old.stderr index 7833ac688babf..3f979d1a50b33 100644 --- a/tests/ui/impl-trait/auto-trait-coherence.old.stderr +++ b/tests/ui/impl-trait/auto-trait-coherence.old.stderr @@ -7,6 +7,6 @@ LL | impl AnotherTrait for T {} LL | impl AnotherTrait for D { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr index 28643ec03e170..3fab766fa235c 100644 --- a/tests/ui/impl-trait/auto-trait-leak.stderr +++ b/tests/ui/impl-trait/auto-trait-leak.stderr @@ -22,5 +22,5 @@ note: required by a bound in `send` LL | fn send(_: T) {} | ^^^^ required by this bound in `send` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr index 61fed16294b4e..444f3d6689f20 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr @@ -8,6 +8,6 @@ LL | impl Into for Foo { - impl Into for T where U: From; -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr index 7c69c4bfe97ba..faaad27692716 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr @@ -8,6 +8,6 @@ LL | impl Into for Foo { - impl Into for T where U: From; -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr b/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr index a1a629bddbdea..06b5ae6e3b01b 100644 --- a/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr +++ b/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | ().foo(|| ()) | ^^^ cannot infer type for type parameter `T` declared on the trait `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/does-not-live-long-enough.stderr b/tests/ui/impl-trait/does-not-live-long-enough.stderr index 750687e232228..cfc13298071a5 100644 --- a/tests/ui/impl-trait/does-not-live-long-enough.stderr +++ b/tests/ui/impl-trait/does-not-live-long-enough.stderr @@ -16,6 +16,6 @@ help: to force the closure to take ownership of `prefix` (and any other referenc LL | self.data.iter().filter(move |s| s.starts_with(prefix)).map(|s| s.as_ref()) | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/impl-trait/dont-suggest-box-on-empty-else-arm.stderr b/tests/ui/impl-trait/dont-suggest-box-on-empty-else-arm.stderr index 9b63911da7aa3..ea3d7f324a58e 100644 --- a/tests/ui/impl-trait/dont-suggest-box-on-empty-else-arm.stderr +++ b/tests/ui/impl-trait/dont-suggest-box-on-empty-else-arm.stderr @@ -11,6 +11,6 @@ LL | | LL | | } | |_____^ expected `&str`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr index 83791f0d3afd7..046d35e4e4acf 100644 --- a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr +++ b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: no errors encountered even though `delay_span_bug` issued +error: internal compiler error: no errors encountered even though `span_delayed_bug` issued error: internal compiler error: {OpaqueTypeKey { def_id: DefId(rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }) } }} | diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr index 84b61dc504480..4cd4febc4f0a1 100644 --- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr @@ -1,4 +1,4 @@ -error: {foo::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} +error: {foo::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} --> $DIR/erased-regions-in-hidden-ty.rs:11:36 | LL | fn foo<'a: 'a>(x: &'a Vec) -> impl Fn() + 'static { diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr index 84b61dc504480..4cd4febc4f0a1 100644 --- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr @@ -1,4 +1,4 @@ -error: {foo::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} +error: {foo::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} --> $DIR/erased-regions-in-hidden-ty.rs:11:36 | LL | fn foo<'a: 'a>(x: &'a Vec) -> impl Fn() + 'static { diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr index 9c10110187042..e8cd16bc30168 100644 --- a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr @@ -13,6 +13,6 @@ LL | fn foo(_f: impl AsRef) {} | ^^^ - = note: `impl Trait` cannot be explicitly specified as a generic argument -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr index a26460c8ecc3a..b2478c4cd295f 100644 --- a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr @@ -16,6 +16,6 @@ help: add missing generic argument LL | f::<[u8], U>("a", b"a"); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/impl-trait/extra-item.stderr b/tests/ui/impl-trait/extra-item.stderr index 728bcc0aa865e..6229970728735 100644 --- a/tests/ui/impl-trait/extra-item.stderr +++ b/tests/ui/impl-trait/extra-item.stderr @@ -4,6 +4,6 @@ error[E0407]: method `extra` is not a member of trait `extra_item::MyTrait` LL | fn extra() {} | ^^^^^^^^^^^^^ not a member of trait `extra_item::MyTrait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0407`. diff --git a/tests/ui/impl-trait/fallback_inference.stderr b/tests/ui/impl-trait/fallback_inference.stderr index 4ac3c238fe958..4f8121ae879e6 100644 --- a/tests/ui/impl-trait/fallback_inference.stderr +++ b/tests/ui/impl-trait/fallback_inference.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | PhantomData:: | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr index edf3911e2a097..6e36922b46964 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr @@ -4,6 +4,6 @@ error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is LL | fn ice() -> impl AsRef { | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr index 30fbba168689b..2e13ca753fc29 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -9,6 +9,6 @@ help: add `dyn` keyword before this trait LL | fn ice() -> impl AsRef { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr index 835f7f765600f..4e453c108d4bb 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -8,6 +8,6 @@ LL | |x| x | | | hidden type `&u8` captures the anonymous lifetime as defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/impl-generic-mismatch-ab.stderr b/tests/ui/impl-trait/impl-generic-mismatch-ab.stderr index db97fc2bdc46a..7046e729e1834 100644 --- a/tests/ui/impl-trait/impl-generic-mismatch-ab.stderr +++ b/tests/ui/impl-trait/impl-generic-mismatch-ab.stderr @@ -18,6 +18,6 @@ LL | fn foo(&self, a: &A, b: &impl Debug); = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/impl-trait-in-macro.stderr b/tests/ui/impl-trait/impl-trait-in-macro.stderr index 7cfbe3447b813..4380f47c5de46 100644 --- a/tests/ui/impl-trait/impl-trait-in-macro.stderr +++ b/tests/ui/impl-trait/impl-trait-in-macro.stderr @@ -17,6 +17,6 @@ LL | a = y; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr index af60da07cac31..d5b543ea953df 100644 --- a/tests/ui/impl-trait/in-assoc-type.stderr +++ b/tests/ui/impl-trait/in-assoc-type.stderr @@ -17,6 +17,6 @@ note: this item must have the opaque type in its signature in order to be able t LL | fn foo(&self) -> >::Bar {} | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs b/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs new file mode 100644 index 0000000000000..af6ffe8339452 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs @@ -0,0 +1,11 @@ +// edition:2021 +// https://github.com/rust-lang/rust/issues/117547 + +trait T {} + +trait MyTrait { + async fn foo() -> &'static impl T; + //~^ ERROR the associated type `::{opaque#0}` may not live long enough +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr new file mode 100644 index 0000000000000..79a86b0a3aedf --- /dev/null +++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr @@ -0,0 +1,14 @@ +error[E0310]: the associated type `::{opaque#0}` may not live long enough + --> $DIR/async-and-ret-ref.rs:7:5 + | +LL | async fn foo() -> &'static impl T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::{opaque#0}` must be valid for the static lifetime... + | ...so that the reference type `&'static impl T` does not outlive the data it points at + | + = help: consider adding an explicit lifetime bound `::{opaque#0}: 'static`... + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr index 324eaa37a3d2a..c898d17f4b709 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr @@ -28,6 +28,6 @@ help: replace the return type so that it matches the trait LL | fn iter(&self) -> impl Iterator::Item<'_>> + '_ { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/impl-trait/in-trait/check-wf-on-non-defaulted-rpitit.stderr b/tests/ui/impl-trait/in-trait/check-wf-on-non-defaulted-rpitit.stderr index 1570b2ecd535d..86f9cc4d99265 100644 --- a/tests/ui/impl-trait/in-trait/check-wf-on-non-defaulted-rpitit.stderr +++ b/tests/ui/impl-trait/in-trait/check-wf-on-non-defaulted-rpitit.stderr @@ -11,6 +11,6 @@ note: required by a bound in `Wrapper` LL | struct Wrapper(G); | ^^^^ required by this bound in `Wrapper` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/deep-match.stderr b/tests/ui/impl-trait/in-trait/deep-match.stderr index a658d8fa0781a..8ec30239ea8d7 100644 --- a/tests/ui/impl-trait/in-trait/deep-match.stderr +++ b/tests/ui/impl-trait/in-trait/deep-match.stderr @@ -10,6 +10,6 @@ LL | fn bar() -> i32 { = note: expected struct `Wrapper<_>` found type `i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr index fcace10cd0149..77f6945f064cc 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr @@ -6,6 +6,6 @@ LL | 42 | | | expected `String`, found integer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr index 596ff1011555c..6f1ac4bce43b7 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr @@ -7,6 +7,6 @@ LL | LL | &1i32 | ----- return type was inferred to be `&i32` here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr index cd45c6a9c6d45..baee1b5db6e9c 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -12,6 +12,6 @@ note: required by a bound in `Foo::{opaque#0}` LL | fn bar() -> impl std::fmt::Display; | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr index 830e663da3760..39f70e4135713 100644 --- a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr +++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr @@ -7,6 +7,6 @@ LL | fn foo(&self) -> impl Sized; LL | impl MyTrait for i32 { | ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr index f29ec95d59402..9cc4c4b2f9e53 100644 --- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr @@ -11,6 +11,6 @@ LL | fn bar(self) -> impl Deref; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type = help: only type `rpitit::Foreign` implements the trait, consider using it directly instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr index 043dbc8db5d07..d847065ebc2a5 100644 --- a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr @@ -7,6 +7,6 @@ LL | fn bar(&self) -> impl Sized; LL | fn bar(&self) {} | ^ found 1 type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/in-trait/issue-102571.stderr b/tests/ui/impl-trait/in-trait/issue-102571.stderr index 872988faf7ab6..1f25069a01699 100644 --- a/tests/ui/impl-trait/in-trait/issue-102571.stderr +++ b/tests/ui/impl-trait/in-trait/issue-102571.stderr @@ -9,6 +9,6 @@ LL | let () = t.bar(); = note: expected associated type `impl Deref` found unit type `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr index 874a1b95a4313..59ffea6fb9f02 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr @@ -16,6 +16,6 @@ LL | fn early<'early, T>(x: &'early T) -> impl Sized; = note: expected signature `fn(&T)` found signature `fn(&'late ())` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr index e0bd1cc4f1946..f8980828b89e2 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr @@ -15,6 +15,6 @@ LL | fn owo(x: ()) -> impl Sized; = note: expected signature `fn(())` found signature `fn(u8)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr index 096e96c85c4be..a6fb1a200e697 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr @@ -15,6 +15,6 @@ LL | async fn owo(x: ()) {} = note: expected signature `fn(()) -> _` found signature `fn(u8) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr index 96eff1a5815e6..0b26e039e6b2e 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr @@ -7,6 +7,6 @@ LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; LL | fn come_on_a_little_more_effort() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0050`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr index 0fc847051c970..9226e1f8b9830 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr @@ -7,6 +7,6 @@ LL | fn calm_down_please() -> impl Sized; LL | fn calm_down_please(_: (), _: (), _: ()) {} | ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0050`. diff --git a/tests/ui/impl-trait/in-trait/missing-lt-outlives-in-rpitit-114274.stderr b/tests/ui/impl-trait/in-trait/missing-lt-outlives-in-rpitit-114274.stderr index 1fd678a1f3ac3..3e763c9f1df2a 100644 --- a/tests/ui/impl-trait/in-trait/missing-lt-outlives-in-rpitit-114274.stderr +++ b/tests/ui/impl-trait/in-trait/missing-lt-outlives-in-rpitit-114274.stderr @@ -18,6 +18,6 @@ help: consider introducing lifetime `'missing` here LL | trait Iterable<'missing> { | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr index e260762d89f59..4996e6839e967 100644 --- a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr @@ -12,6 +12,6 @@ LL | let x: &str = ().bar(); = note: expected reference `&str` found opaque type `impl std::fmt::Display` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs b/tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs new file mode 100644 index 0000000000000..33d3487030e4d --- /dev/null +++ b/tests/ui/impl-trait/in-trait/placeholder-implied-bounds.rs @@ -0,0 +1,14 @@ +// check-pass + +pub fn main() {} + +pub trait Iced { + fn get(&self) -> &impl Sized; +} + +/// Impl causes ICE +impl Iced for () { + fn get(&self) -> &impl Sized { + &() + } +} diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index 181d6a284daae..db587d069f8b8 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -11,6 +11,6 @@ note: required by a bound in `Foo::{opaque#0}` LL | fn foo(self) -> impl Foo; | ^^^^^^ required by this bound in `Foo::{opaque#0}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr index afc59cc5b5805..5ace64b690351 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.stderr @@ -11,6 +11,6 @@ note: but the referenced data is only valid for the lifetime `'a` as defined her LL | fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr index 7e1a8f083acc6..3430055dab171 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr @@ -11,6 +11,6 @@ note: but the referenced data is only valid for the anonymous lifetime defined h LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr index 6e4a5bb5df36a..73ada8d709610 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Missing` in this scope LL | fn w() -> impl Deref>; | ^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/impl-trait/in-trait/sibling-function-constraint.stderr b/tests/ui/impl-trait/in-trait/sibling-function-constraint.stderr index 729963a8141ec..b8ac826adaa9b 100644 --- a/tests/ui/impl-trait/in-trait/sibling-function-constraint.stderr +++ b/tests/ui/impl-trait/in-trait/sibling-function-constraint.stderr @@ -12,6 +12,6 @@ LL | fn bar() -> impl Sized { = note: expected struct `String` found opaque type `impl Sized` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr index 468cf12f1bc03..0cd76815afa7c 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr @@ -9,6 +9,6 @@ LL | ) -> impl Future> { | | | ...but data from `buff` is returned here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0623`. diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr index cec94e39a35f9..cf68ed87030a9 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr @@ -16,6 +16,6 @@ LL | async fn baz(&self) -> &i32; LL | impl Trait for S {} | ^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `test`, `baz` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr index 2836e9c7821ee..eed4c07710e06 100644 --- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr @@ -7,6 +7,6 @@ LL | fn bar() -> impl Sized; LL | fn bar() -> impl Sized {} | ^ found 0 type parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr b/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr index 61a0f8454d133..4c5a42c0b4b47 100644 --- a/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr +++ b/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, T> Foo for T { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/impl-trait/issue-100075-2.stderr b/tests/ui/impl-trait/issue-100075-2.stderr index d2dbd8c620546..b3b6967750705 100644 --- a/tests/ui/impl-trait/issue-100075-2.stderr +++ b/tests/ui/impl-trait/issue-100075-2.stderr @@ -19,6 +19,6 @@ LL | fn opaque(t: T) -> impl Sized { LL | opaque(Some(t)) | --------------- returning here with type `impl Sized` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issue-100075.stderr b/tests/ui/impl-trait/issue-100075.stderr index 267ecfdaed124..7596348923693 100644 --- a/tests/ui/impl-trait/issue-100075.stderr +++ b/tests/ui/impl-trait/issue-100075.stderr @@ -7,6 +7,6 @@ LL | fn _g(t: &'static T) -> &'static impl Marker { LL | return _g(t); | ----- returning here with type `&impl Marker` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issue-103181-1.current.stderr b/tests/ui/impl-trait/issue-103181-1.current.stderr index e87a9d28ae1f7..83410dfc6ea90 100644 --- a/tests/ui/impl-trait/issue-103181-1.current.stderr +++ b/tests/ui/impl-trait/issue-103181-1.current.stderr @@ -7,6 +7,6 @@ LL | } LL | impl HttpBody for () { | ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/issue-103181-1.next.stderr b/tests/ui/impl-trait/issue-103181-1.next.stderr index e87a9d28ae1f7..83410dfc6ea90 100644 --- a/tests/ui/impl-trait/issue-103181-1.next.stderr +++ b/tests/ui/impl-trait/issue-103181-1.next.stderr @@ -7,6 +7,6 @@ LL | } LL | impl HttpBody for () { | ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/issue-103181-2.stderr b/tests/ui/impl-trait/issue-103181-2.stderr index 5eb2dd9184bec..cef4449dbb986 100644 --- a/tests/ui/impl-trait/issue-103181-2.stderr +++ b/tests/ui/impl-trait/issue-103181-2.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `ident_error` in this scope LL | ident_error; | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/impl-trait/issue-35668.stderr b/tests/ui/impl-trait/issue-35668.stderr index 84add5799abae..ba02d2898e9b1 100644 --- a/tests/ui/impl-trait/issue-35668.stderr +++ b/tests/ui/impl-trait/issue-35668.stderr @@ -11,6 +11,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn func<'a, T>(a: &'a [T]) -> impl Iterator where &T: Mul<&T> { | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/impl-trait/issue-54966.stderr b/tests/ui/impl-trait/issue-54966.stderr index aa9a61cb592d1..4024c5afa80b6 100644 --- a/tests/ui/impl-trait/issue-54966.stderr +++ b/tests/ui/impl-trait/issue-54966.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Oper` in this scope LL | fn generate_duration() -> Oper {} | ^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/impl-trait/issue-55872-3.stderr b/tests/ui/impl-trait/issue-55872-3.stderr index b542b61419960..9af0fad9cdb94 100644 --- a/tests/ui/impl-trait/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issue-55872-3.stderr @@ -4,6 +4,6 @@ error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:17}: LL | fn foo() -> Self::E { | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:17}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issue-55872.stderr b/tests/ui/impl-trait/issue-55872.stderr index cb370fbe1c41d..4ff8527bbe9d1 100644 --- a/tests/ui/impl-trait/issue-55872.stderr +++ b/tests/ui/impl-trait/issue-55872.stderr @@ -4,5 +4,5 @@ error: type parameter `T` is part of concrete type but not used in parameter lis LL | || () | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issue-86465.stderr b/tests/ui/impl-trait/issue-86465.stderr index 90d6904ed6164..e330d178d4eac 100644 --- a/tests/ui/impl-trait/issue-86465.stderr +++ b/tests/ui/impl-trait/issue-86465.stderr @@ -7,5 +7,5 @@ LL | (a, a) | expected `&'a u32`, got `&'b u32` | this expression supplies two conflicting concrete types for the same opaque type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issue-87450.stderr b/tests/ui/impl-trait/issue-87450.stderr index 173fca63fa01f..9567e09651d6c 100644 --- a/tests/ui/impl-trait/issue-87450.stderr +++ b/tests/ui/impl-trait/issue-87450.stderr @@ -22,6 +22,6 @@ LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) LL | fn wrap(f: impl Fn()) -> impl Fn() { | --------- returning this opaque type `impl Fn()` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issue-99914.stderr b/tests/ui/impl-trait/issue-99914.stderr index c86e9eadc87cb..06e85e521d226 100644 --- a/tests/ui/impl-trait/issue-99914.stderr +++ b/tests/ui/impl-trait/issue-99914.stderr @@ -9,6 +9,6 @@ help: try wrapping the expression in `Ok` LL | t.and_then(|t| -> _ { Ok(bar(t)) }); | +++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 9150d957db76d..e5d7183937387 100644 --- a/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -14,6 +14,6 @@ note: `Foo` defines an item `foo`, perhaps you need to implement it LL | trait Foo { | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr index 9a8e3675b9569..946ad74b87228 100644 --- a/tests/ui/impl-trait/issues/issue-54600.stderr +++ b/tests/ui/impl-trait/issues/issue-54600.stderr @@ -4,6 +4,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument LL | let x: Option = Some(44_u32); | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr index 67cabf4495067..c4ab79f110dde 100644 --- a/tests/ui/impl-trait/issues/issue-54840.stderr +++ b/tests/ui/impl-trait/issues/issue-54840.stderr @@ -4,6 +4,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument LL | let j: &impl Add = &i; | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-54895.stderr b/tests/ui/impl-trait/issues/issue-54895.stderr index 7d22f027a6daf..999ffd5214154 100644 --- a/tests/ui/impl-trait/issues/issue-54895.stderr +++ b/tests/ui/impl-trait/issues/issue-54895.stderr @@ -10,5 +10,5 @@ note: lifetime declared here LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr b/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr index 6bebbc01f3d6f..83d0d77657247 100644 --- a/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr +++ b/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr @@ -7,6 +7,6 @@ LL | pub fn demo(_: impl Quux>>) { } | | nested `impl Trait` here | outer `impl Trait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0666`. diff --git a/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr index e31393181d734..55f47785f0eeb 100644 --- a/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr +++ b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr @@ -4,6 +4,6 @@ error[E0667]: `impl Trait` is not allowed in path parameters LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux>::Assoc>) { } | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0667`. diff --git a/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr b/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr index 8d3d4b5e20618..0e105817b18af 100644 --- a/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr +++ b/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr @@ -7,6 +7,6 @@ LL | pub fn demo(_: impl Quux>) { } | | nested `impl Trait` here | outer `impl Trait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0666`. diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr index 49376f559cfcf..e67e48728ed09 100644 --- a/tests/ui/impl-trait/issues/issue-58504.stderr +++ b/tests/ui/impl-trait/issues/issue-58504.stderr @@ -4,6 +4,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument LL | let gens: [impl Coroutine;2] = [ mk_gen(), mk_gen() ]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-67830.stderr b/tests/ui/impl-trait/issues/issue-67830.stderr index d3ea8cb0377c7..17cfa151a6863 100644 --- a/tests/ui/impl-trait/issues/issue-67830.stderr +++ b/tests/ui/impl-trait/issues/issue-67830.stderr @@ -10,5 +10,5 @@ note: lifetime declared here LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-70877.stderr b/tests/ui/impl-trait/issues/issue-70877.stderr index ee140e6f6c43d..274139f01d087 100644 --- a/tests/ui/impl-trait/issues/issue-70877.stderr +++ b/tests/ui/impl-trait/issues/issue-70877.stderr @@ -15,5 +15,5 @@ note: opaque type being used as hidden type LL | type FooRet = impl std::fmt::Debug; | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr index 5609f8b9b012c..fcc67291e4d2b 100644 --- a/tests/ui/impl-trait/issues/issue-70971.stderr +++ b/tests/ui/impl-trait/issues/issue-70971.stderr @@ -4,6 +4,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument LL | let x : (impl Copy,) = (true,); | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-82139.stderr b/tests/ui/impl-trait/issues/issue-82139.stderr index 0adcd4a7a2f5c..b87084433120b 100644 --- a/tests/ui/impl-trait/issues/issue-82139.stderr +++ b/tests/ui/impl-trait/issues/issue-82139.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `j` in this scope LL | Some(42).map(|_| j) | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/impl-trait/issues/issue-83919.stderr b/tests/ui/impl-trait/issues/issue-83919.stderr index d39dcf7fbf5d9..200257235feae 100644 --- a/tests/ui/impl-trait/issues/issue-83919.stderr +++ b/tests/ui/impl-trait/issues/issue-83919.stderr @@ -7,6 +7,6 @@ LL | fn get_fut(&self) -> Self::Fut { = help: the trait `Future` is not implemented for `{integer}` = note: {integer} must be a future or must implement `IntoFuture` to be awaited -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr index b4be16ff0420e..d03e458aeb821 100644 --- a/tests/ui/impl-trait/issues/issue-84073.stderr +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -9,6 +9,6 @@ help: consider giving this closure parameter an explicit type, where the type fo LL | Race::new(|race: RaceBuilder>| race.when()); | ++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr index 20b131b8bd200..963865efa69f7 100644 --- a/tests/ui/impl-trait/issues/issue-84919.stderr +++ b/tests/ui/impl-trait/issues/issue-84919.stderr @@ -4,6 +4,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument LL | let _x: impl Trait = (); | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-86642.stderr b/tests/ui/impl-trait/issues/issue-86642.stderr index 6d3be3fff0e10..3ad18a13290a2 100644 --- a/tests/ui/impl-trait/issues/issue-86642.stderr +++ b/tests/ui/impl-trait/issues/issue-86642.stderr @@ -4,6 +4,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr index 3fe4ee73c80c3..e9a635f244bcb 100644 --- a/tests/ui/impl-trait/issues/issue-87295.stderr +++ b/tests/ui/impl-trait/issues/issue-87295.stderr @@ -4,6 +4,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument LL | let _do_not_waste: Struct> = Struct::new(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-87340.stderr b/tests/ui/impl-trait/issues/issue-87340.stderr index 2ab1e6a031248..8513cb2881e1f 100644 --- a/tests/ui/impl-trait/issues/issue-87340.stderr +++ b/tests/ui/impl-trait/issues/issue-87340.stderr @@ -4,6 +4,6 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl X for () { | ^ unconstrained type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/impl-trait/issues/issue-88236.stderr b/tests/ui/impl-trait/issues/issue-88236.stderr index 7a4cc57b0881a..6cf1a42d6a997 100644 --- a/tests/ui/impl-trait/issues/issue-88236.stderr +++ b/tests/ui/impl-trait/issues/issue-88236.stderr @@ -10,5 +10,5 @@ note: lifetime declared here LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-92305.stderr b/tests/ui/impl-trait/issues/issue-92305.stderr index 86d7184da7a45..88fb1fb27070e 100644 --- a/tests/ui/impl-trait/issues/issue-92305.stderr +++ b/tests/ui/impl-trait/issues/issue-92305.stderr @@ -9,6 +9,6 @@ help: add missing generic argument LL | fn f(data: &[T]) -> impl Iterator> { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr index f0dceb1b11a5d..a83e0df911b09 100644 --- a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr +++ b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr @@ -20,6 +20,6 @@ note: required by a bound in `Foo::Item` LL | type Item: Bar; | ^^^^^^^^^^^^ required by this bound in `Foo::Item` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/method-suggestion-no-duplication.stderr b/tests/ui/impl-trait/method-suggestion-no-duplication.stderr index b727b2ca0cce3..c401269da83cc 100644 --- a/tests/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/tests/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -11,6 +11,6 @@ LL | foo(|s| s.is_empty()); = note: the following trait defines an item `is_empty`, perhaps you need to implement it: candidate #1: `ExactSizeIterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr index f3c090408b42e..faa5d3ba4489d 100644 --- a/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr +++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr @@ -22,5 +22,5 @@ note: previous use here LL | let a: T = foo::(); | ^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr index 5b0b1cc5e426f..b968592beffd9 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr @@ -10,6 +10,6 @@ LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { LL | u.0 | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr index ccd0040030da2..c511081a86fff 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr @@ -11,5 +11,5 @@ LL | let _: &'b i32 = *u.0; | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr index 01d9f506a0c58..00709ee7438a7 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr @@ -11,5 +11,5 @@ LL | let _: &'b i32 = *u.0; | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index 68ac22a05f4dd..4d4ba58c97440 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -14,6 +14,6 @@ help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explici LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 493a9e66eaf86..060eaa7e64a13 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -14,6 +14,6 @@ help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explici LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/negative-reasoning.stderr b/tests/ui/impl-trait/negative-reasoning.stderr index ddce5e7ece2be..3cb4be16fc3f1 100644 --- a/tests/ui/impl-trait/negative-reasoning.stderr +++ b/tests/ui/impl-trait/negative-reasoning.stderr @@ -9,6 +9,6 @@ LL | impl AnotherTrait for D { | = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `OpaqueType` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/nested-return-type4.stderr b/tests/ui/impl-trait/nested-return-type4.stderr index a1e2d227ff385..14d51a1b06424 100644 --- a/tests/ui/impl-trait/nested-return-type4.stderr +++ b/tests/ui/impl-trait/nested-return-type4.stderr @@ -17,6 +17,6 @@ help: to declare that `impl Sized` captures `'s`, you can add an explicit `'s` l LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/nested-rpit-hrtb-2.stderr b/tests/ui/impl-trait/nested-rpit-hrtb-2.stderr index 71d1d45f48bdb..0fcacc19ca3a6 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb-2.stderr +++ b/tests/ui/impl-trait/nested-rpit-hrtb-2.stderr @@ -7,6 +7,6 @@ LL | fn test() -> impl for<'a> Trait<'a, Assoc = impl Sized> {} | | opaque type defined here | hidden type `&'a str` captures the lifetime `'a` as defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/no-trait.stderr b/tests/ui/impl-trait/no-trait.stderr index 3a636f2524fff..a58fa5cd7115a 100644 --- a/tests/ui/impl-trait/no-trait.stderr +++ b/tests/ui/impl-trait/no-trait.stderr @@ -4,5 +4,5 @@ error: at least one trait must be specified LL | fn f() -> impl 'static {} | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index ada8fd7fa50ee..e0513433b8ec1 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -4,5 +4,5 @@ error: ~const can only be applied to `#[const_trait]` traits LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr index 2347805343c93..5ade6a69d4b0d 100644 --- a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr +++ b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr @@ -6,6 +6,6 @@ LL | fn run() -> Foo> { | = note: cannot satisfy `_: Future` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr index a4ff510477a4c..c4ea44740662d 100644 --- a/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr +++ b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -15,6 +15,6 @@ note: required for `()` to implement `Test` LL | impl Test for T where T: Super {} | ^^^^ ^ ---------- unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/recursive-coroutine.stderr b/tests/ui/impl-trait/recursive-coroutine.current.stderr similarity index 81% rename from tests/ui/impl-trait/recursive-coroutine.stderr rename to tests/ui/impl-trait/recursive-coroutine.current.stderr index d36a58a864343..e838634ed087c 100644 --- a/tests/ui/impl-trait/recursive-coroutine.stderr +++ b/tests/ui/impl-trait/recursive-coroutine.current.stderr @@ -1,5 +1,5 @@ error[E0720]: cannot resolve opaque type - --> $DIR/recursive-coroutine.rs:5:13 + --> $DIR/recursive-coroutine.rs:7:13 | LL | fn foo() -> impl Coroutine { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type @@ -7,6 +7,6 @@ LL | fn foo() -> impl Coroutine { LL | let mut gen = Box::pin(foo()); | ------- coroutine captures itself here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-coroutine.next.stderr b/tests/ui/impl-trait/recursive-coroutine.next.stderr new file mode 100644 index 0000000000000..e838634ed087c --- /dev/null +++ b/tests/ui/impl-trait/recursive-coroutine.next.stderr @@ -0,0 +1,12 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-coroutine.rs:7:13 + | +LL | fn foo() -> impl Coroutine { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type +... +LL | let mut gen = Box::pin(foo()); + | ------- coroutine captures itself here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-coroutine.rs b/tests/ui/impl-trait/recursive-coroutine.rs index 6351cef95a618..f0bee4f120ffe 100644 --- a/tests/ui/impl-trait/recursive-coroutine.rs +++ b/tests/ui/impl-trait/recursive-coroutine.rs @@ -1,3 +1,5 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next #![feature(coroutines, coroutine_trait)] use std::ops::{Coroutine, CoroutineState}; diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr index b98b859a99bf8..bc810c0f88f3d 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr @@ -10,6 +10,6 @@ LL | Bar = help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar` = help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/region-escape-via-bound.stderr b/tests/ui/impl-trait/region-escape-via-bound.stderr index e4556bc21a7f9..43f0eeeb55838 100644 --- a/tests/ui/impl-trait/region-escape-via-bound.stderr +++ b/tests/ui/impl-trait/region-escape-via-bound.stderr @@ -14,6 +14,6 @@ help: to declare that `impl Trait<'y>` captures `'x`, you can add an explicit `' LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/rpit-not-sized.stderr b/tests/ui/impl-trait/rpit-not-sized.stderr index 608c94fc07237..7fe275f06fbe7 100644 --- a/tests/ui/impl-trait/rpit-not-sized.stderr +++ b/tests/ui/impl-trait/rpit-not-sized.stderr @@ -7,6 +7,6 @@ LL | fn foo() -> impl ?Sized { = help: the trait `Sized` is not implemented for `impl ?Sized` = note: the return type of a function must have a statically known size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/suggest-calling-rpit-closure.stderr b/tests/ui/impl-trait/suggest-calling-rpit-closure.stderr index c10a856d83ba8..b0ae10b8d8629 100644 --- a/tests/ui/impl-trait/suggest-calling-rpit-closure.stderr +++ b/tests/ui/impl-trait/suggest-calling-rpit-closure.stderr @@ -16,6 +16,6 @@ help: use parentheses to call this opaque type LL | opaque()() | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/two_tait_defining_each_other.stderr b/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr similarity index 72% rename from tests/ui/impl-trait/two_tait_defining_each_other.stderr rename to tests/ui/impl-trait/two_tait_defining_each_other.current.stderr index 1a42ac525a6a8..b60529ed00293 100644 --- a/tests/ui/impl-trait/two_tait_defining_each_other.stderr +++ b/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr @@ -1,19 +1,19 @@ error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/two_tait_defining_each_other.rs:12:5 + --> $DIR/two_tait_defining_each_other.rs:16:5 | LL | x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other | ^ one of the two opaque types used here has to be outside its defining scope | note: opaque type whose hidden type is being assigned - --> $DIR/two_tait_defining_each_other.rs:4:10 + --> $DIR/two_tait_defining_each_other.rs:8:10 | LL | type B = impl Foo; | ^^^^^^^^ note: opaque type being used as hidden type - --> $DIR/two_tait_defining_each_other.rs:3:10 + --> $DIR/two_tait_defining_each_other.rs:7:10 | LL | type A = impl Foo; | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/two_tait_defining_each_other.rs b/tests/ui/impl-trait/two_tait_defining_each_other.rs index 6eb2a11b22c5f..b43a7cabd0589 100644 --- a/tests/ui/impl-trait/two_tait_defining_each_other.rs +++ b/tests/ui/impl-trait/two_tait_defining_each_other.rs @@ -1,3 +1,7 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +//[next] check-pass + #![feature(type_alias_impl_trait)] type A = impl Foo; @@ -10,7 +14,7 @@ fn muh(x: A) -> B { return Bar; // B's hidden type is Bar } x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other - //~^ ERROR opaque type's hidden type cannot be another opaque type + //[current]~^ ERROR opaque type's hidden type cannot be another opaque type } struct Bar; diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr similarity index 76% rename from tests/ui/impl-trait/two_tait_defining_each_other2.stderr rename to tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr index 4d8f96de1626c..33866451c6b4e 100644 --- a/tests/ui/impl-trait/two_tait_defining_each_other2.stderr +++ b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr @@ -1,5 +1,5 @@ error: unconstrained opaque type - --> $DIR/two_tait_defining_each_other2.rs:3:10 + --> $DIR/two_tait_defining_each_other2.rs:5:10 | LL | type A = impl Foo; | ^^^^^^^^ @@ -7,18 +7,18 @@ LL | type A = impl Foo; = note: `A` must be used in combination with a concrete type within the same module error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/two_tait_defining_each_other2.rs:9:5 + --> $DIR/two_tait_defining_each_other2.rs:11:5 | LL | x // B's hidden type is A (opaquely) | ^ one of the two opaque types used here has to be outside its defining scope | note: opaque type whose hidden type is being assigned - --> $DIR/two_tait_defining_each_other2.rs:4:10 + --> $DIR/two_tait_defining_each_other2.rs:6:10 | LL | type B = impl Foo; | ^^^^^^^^ note: opaque type being used as hidden type - --> $DIR/two_tait_defining_each_other2.rs:3:10 + --> $DIR/two_tait_defining_each_other2.rs:5:10 | LL | type A = impl Foo; | ^^^^^^^^ diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr new file mode 100644 index 0000000000000..e49d1d18b0cf7 --- /dev/null +++ b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr @@ -0,0 +1,9 @@ +error[E0284]: type annotations needed: cannot satisfy `A <: B` + --> $DIR/two_tait_defining_each_other2.rs:11:5 + | +LL | x // B's hidden type is A (opaquely) + | ^ cannot satisfy `A <: B` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs index 05b09668016c4..817de109fbe95 100644 --- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs +++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs @@ -1,13 +1,16 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next #![feature(type_alias_impl_trait)] -type A = impl Foo; //~ ERROR unconstrained opaque type +type A = impl Foo; //[current]~ ERROR unconstrained opaque type type B = impl Foo; trait Foo {} fn muh(x: A) -> B { x // B's hidden type is A (opaquely) - //~^ ERROR opaque type's hidden type cannot be another opaque type + //[current]~^ ERROR opaque type's hidden type cannot be another opaque type + //[next]~^^ ERROR type annotations needed: cannot satisfy `A <: B` } struct Bar; diff --git a/tests/ui/impl-trait/two_tait_defining_each_other3.stderr b/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr similarity index 70% rename from tests/ui/impl-trait/two_tait_defining_each_other3.stderr rename to tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr index b06dc16d5e700..1dccfd17a7095 100644 --- a/tests/ui/impl-trait/two_tait_defining_each_other3.stderr +++ b/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr @@ -1,19 +1,19 @@ error: opaque type's hidden type cannot be another opaque type from the same scope - --> $DIR/two_tait_defining_each_other3.rs:10:16 + --> $DIR/two_tait_defining_each_other3.rs:13:16 | LL | return x; // B's hidden type is A (opaquely) | ^ one of the two opaque types used here has to be outside its defining scope | note: opaque type whose hidden type is being assigned - --> $DIR/two_tait_defining_each_other3.rs:4:10 + --> $DIR/two_tait_defining_each_other3.rs:7:10 | LL | type B = impl Foo; | ^^^^^^^^ note: opaque type being used as hidden type - --> $DIR/two_tait_defining_each_other3.rs:3:10 + --> $DIR/two_tait_defining_each_other3.rs:6:10 | LL | type A = impl Foo; | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/two_tait_defining_each_other3.rs b/tests/ui/impl-trait/two_tait_defining_each_other3.rs index 37f8ae1b84b55..6fb9e6e718898 100644 --- a/tests/ui/impl-trait/two_tait_defining_each_other3.rs +++ b/tests/ui/impl-trait/two_tait_defining_each_other3.rs @@ -1,3 +1,6 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +//[next] check-pass #![feature(type_alias_impl_trait)] type A = impl Foo; @@ -8,7 +11,7 @@ trait Foo {} fn muh(x: A) -> B { if false { return x; // B's hidden type is A (opaquely) - //~^ ERROR opaque type's hidden type cannot be another opaque type + //[current]~^ ERROR opaque type's hidden type cannot be another opaque type } Bar // A's hidden type is `Bar`, because all the return types are compared with each other } diff --git a/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr b/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr index 30322f88cca42..d3d651a28e131 100644 --- a/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr +++ b/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr @@ -10,6 +10,6 @@ LL | fn foo(&self, t: impl Clone) {} | found 1 type parameter | `impl Trait` introduces an implicit type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/type_parameters_captured.stderr b/tests/ui/impl-trait/type_parameters_captured.stderr index 46859296fb8b4..28dfcd8b871d8 100644 --- a/tests/ui/impl-trait/type_parameters_captured.stderr +++ b/tests/ui/impl-trait/type_parameters_captured.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | fn foo(x: T) -> impl Any + 'static { | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/impl-trait/unactionable_diagnostic.stderr b/tests/ui/impl-trait/unactionable_diagnostic.stderr index 4df7f45c3b37e..be37da08e76ff 100644 --- a/tests/ui/impl-trait/unactionable_diagnostic.stderr +++ b/tests/ui/impl-trait/unactionable_diagnostic.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | pub fn bar<'t, T: 't>( | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/impl-trait/universal-mismatched-type.stderr b/tests/ui/impl-trait/universal-mismatched-type.stderr index 82e0f23964f78..21da1d087acfb 100644 --- a/tests/ui/impl-trait/universal-mismatched-type.stderr +++ b/tests/ui/impl-trait/universal-mismatched-type.stderr @@ -11,6 +11,6 @@ LL | x = note: expected struct `String` found type parameter `impl Debug` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/universal-two-impl-traits.stderr b/tests/ui/impl-trait/universal-two-impl-traits.stderr index ab8a53d0db399..3b4844ab1333d 100644 --- a/tests/ui/impl-trait/universal-two-impl-traits.stderr +++ b/tests/ui/impl-trait/universal-two-impl-traits.stderr @@ -15,6 +15,6 @@ LL | a = y; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.stderr b/tests/ui/impl-trait/universal_wrong_hrtb.stderr index b5a091b61faf0..e0718927976ac 100644 --- a/tests/ui/impl-trait/universal_wrong_hrtb.stderr +++ b/tests/ui/impl-trait/universal_wrong_hrtb.stderr @@ -4,5 +4,5 @@ error: `impl Trait` can only mention lifetimes from an fn or impl LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {} | -- lifetime declared here ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/where-allowed-2.stderr b/tests/ui/impl-trait/where-allowed-2.stderr index b3765ac1a541f..c421e587a9ef6 100644 --- a/tests/ui/impl-trait/where-allowed-2.stderr +++ b/tests/ui/impl-trait/where-allowed-2.stderr @@ -6,6 +6,6 @@ LL | fn in_adt_in_return() -> Vec { panic!() } | = note: cannot satisfy `_: Debug` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/impl-unused-rps-in-assoc-type.stderr b/tests/ui/impl-unused-rps-in-assoc-type.stderr index c7ad1b4e608fc..ef61fa4be4830 100644 --- a/tests/ui/impl-unused-rps-in-assoc-type.stderr +++ b/tests/ui/impl-unused-rps-in-assoc-type.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a> Fun for Holder { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/implicit-method-bind.stderr b/tests/ui/implicit-method-bind.stderr index e0a968527205f..e9357113f364e 100644 --- a/tests/ui/implicit-method-bind.stderr +++ b/tests/ui/implicit-method-bind.stderr @@ -9,6 +9,6 @@ help: use parentheses to call the method LL | let _f = 10i32.abs(); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr b/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr index 307899297bc01..92284df41c741 100644 --- a/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr +++ b/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr @@ -12,6 +12,6 @@ LL | let _: &'static u8 = test(&x, &&3); LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/implied-bounds/impl-header-unnormalized-types.stderr b/tests/ui/implied-bounds/impl-header-unnormalized-types.stderr index 88abd5f54c2a6..07cb0aecda8eb 100644 --- a/tests/ui/implied-bounds/impl-header-unnormalized-types.stderr +++ b/tests/ui/implied-bounds/impl-header-unnormalized-types.stderr @@ -15,6 +15,6 @@ note: but the referenced data is only valid for the lifetime `'b` as defined her LL | impl<'a, 'b> NeedsWf<'a, 'b> for Foo<<&'a &'b () as GoodBye>::Forget> { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr index ebe07027d2fa1..86b12cf8fa291 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![deny(implied_bounds_entailment)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: error: impl method assumes more implied bounds than the corresponding trait method diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr index 43d3e058ffeb3..a89645c128bfe 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![deny(implied_bounds_entailment)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: error: impl method assumes more implied bounds than the corresponding trait method diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr index ac9f7ab252968..49f2fcd0a677b 100644 --- a/tests/ui/implied-bounds/issue-100690.stderr +++ b/tests/ui/implied-bounds/issue-100690.stderr @@ -17,6 +17,6 @@ LL | fn real_dispatch(f: F) -> Result<(), io::Error> LL | F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/implied-bounds/issue-110161.stderr b/tests/ui/implied-bounds/issue-110161.stderr index 9e0188694ed9c..0b736317980c9 100644 --- a/tests/ui/implied-bounds/issue-110161.stderr +++ b/tests/ui/implied-bounds/issue-110161.stderr @@ -7,6 +7,6 @@ LL | type Ty; LL | impl LtTrait for () { | ^^^^^^^^^^^^^^^^^^^ missing `Ty` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr index 898e5e9511e71..abffee57a0f09 100644 --- a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr +++ b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr @@ -13,6 +13,6 @@ note: `'static` lifetime requirement introduced by this bound LL | I::Item: 'static; | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0759`. diff --git a/tests/ui/implied-bounds/normalization-placeholder-leak.fail.stderr b/tests/ui/implied-bounds/normalization-placeholder-leak.fail.stderr new file mode 100644 index 0000000000000..a591d0f5d4d0a --- /dev/null +++ b/tests/ui/implied-bounds/normalization-placeholder-leak.fail.stderr @@ -0,0 +1,15 @@ +error[E0477]: the type `&'lt u8` does not fulfill the required lifetime + --> $DIR/normalization-placeholder-leak.rs:31:40 + | +LL | fn test_lifetime<'lt, T: Trait>(_: Foo<&'lt u8>) {} + | ^^^^^^^^^^^^ + +error[E0477]: the type `::Ty2<'lt>` does not fulfill the required lifetime + --> $DIR/normalization-placeholder-leak.rs:36:44 + | +LL | fn test_alias<'lt, T: AnotherTrait>(_: Foo>) {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/implied-bounds/normalization-placeholder-leak.rs b/tests/ui/implied-bounds/normalization-placeholder-leak.rs new file mode 100644 index 0000000000000..5350dcbb23314 --- /dev/null +++ b/tests/ui/implied-bounds/normalization-placeholder-leak.rs @@ -0,0 +1,56 @@ +// Because of #109628, when we compute the implied bounds from `Foo`, +// we incorrectly get `X: placeholder('x)`. +// Make sure we ignore these bogus bounds and not use them for anything useful. +// +// revisions: fail pass +// [fail] check-fail +// [pass] check-pass + +trait Trait { + type Ty<'a> where Self: 'a; +} + +impl Trait for T { + type Ty<'a> = () where Self: 'a; +} + +struct Foo(T) +where + for<'x> T::Ty<'x>: Sized; + +trait AnotherTrait { + type Ty2<'a>: 'a; +} + +#[cfg(fail)] +mod fail { + use super::*; + + // implied_bound: `'lt: placeholder('x)`. + // don't use the bound to prove `'lt: 'static`. + fn test_lifetime<'lt, T: Trait>(_: Foo<&'lt u8>) {} + //[fail]~^ ERROR `&'lt u8` does not fulfill the required lifetime + + // implied bound: `T::Ty2<'lt>: placeholder('x)`. + // don't use the bound to prove `T::Ty2<'lt>: 'static`. + fn test_alias<'lt, T: AnotherTrait>(_: Foo>) {} + //[fail]~^ ERROR `::Ty2<'lt>` does not fulfill the required lifetime +} + + +mod pass { + use super::*; + + // implied_bound: 'static: placeholder('x). + // don't ice. + fn test_lifetime(_: Foo<&'static u8>) {} + + // implied bound: T::Ty2<'static>: placeholder('x). + // don't add the bound to the environment, + // otherwise we would fail to infer a value for `'_`. + fn test_alias(_: Foo>) { + None::<&'static T::Ty2<'_>>; + } +} + +fn main() {} diff --git a/tests/ui/implied-bounds/references-err.stderr b/tests/ui/implied-bounds/references-err.stderr index 6076eea3c75fa..df83fce3bdef7 100644 --- a/tests/ui/implied-bounds/references-err.stderr +++ b/tests/ui/implied-bounds/references-err.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `DoesNotExist` in this scope LL | type Assoc = DoesNotExist; | ^^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/imports/ambiguous-11.stderr b/tests/ui/imports/ambiguous-11.stderr index 765d6afa8d7e9..5b7f3059ef42e 100644 --- a/tests/ui/imports/ambiguous-11.stderr +++ b/tests/ui/imports/ambiguous-11.stderr @@ -18,6 +18,6 @@ LL | use ambiguous_11_extern::*; | ^^^^^^^^^^^^^^^^^^^^^^ = help: consider adding an explicit import of `Error` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/ambiguous-7.stderr b/tests/ui/imports/ambiguous-7.stderr index 2c6b56c61fd4c..addc28ff52a35 100644 --- a/tests/ui/imports/ambiguous-7.stderr +++ b/tests/ui/imports/ambiguous-7.stderr @@ -18,6 +18,6 @@ LL | pub use t2::*; | ^^^^^ = help: consider adding an explicit import of `Error` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/ambiguous-8.stderr b/tests/ui/imports/ambiguous-8.stderr index 32056fba69f96..11914efe9d87c 100644 --- a/tests/ui/imports/ambiguous-8.stderr +++ b/tests/ui/imports/ambiguous-8.stderr @@ -18,6 +18,6 @@ LL | use ambiguous_8_extern::*; | ^^^^^^^^^^^^^^^^^^^^^ = help: consider adding an explicit import of `Error` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/double-import.stderr b/tests/ui/imports/double-import.stderr index 82f5eb83e6f2d..73bb73e349066 100644 --- a/tests/ui/imports/double-import.stderr +++ b/tests/ui/imports/double-import.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use sub2::foo as other_foo; | ~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/extern-crate-used.stderr b/tests/ui/imports/extern-crate-used.stderr index 1b9a2e4720d5f..982da0c913ed8 100644 --- a/tests/ui/imports/extern-crate-used.stderr +++ b/tests/ui/imports/extern-crate-used.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_extern_crates)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/imports/extern-with-ambiguous-1.stderr b/tests/ui/imports/extern-with-ambiguous-1.stderr index dca2b4ebee7b1..ab4aeacbd998c 100644 --- a/tests/ui/imports/extern-with-ambiguous-1.stderr +++ b/tests/ui/imports/extern-with-ambiguous-1.stderr @@ -18,6 +18,6 @@ LL | use extern_with_ambiguous_1_extern::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: consider adding an explicit import of `error` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/import-crate-var.stderr b/tests/ui/imports/import-crate-var.stderr index f1f1dfbdbdbfc..41a8772d28fa5 100644 --- a/tests/ui/imports/import-crate-var.stderr +++ b/tests/ui/imports/import-crate-var.stderr @@ -6,5 +6,5 @@ LL | m!(); | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/imports/import-from-missing.stderr b/tests/ui/imports/import-from-missing.stderr index 4254bfb5efb59..4020ec1b579d8 100644 --- a/tests/ui/imports/import-from-missing.stderr +++ b/tests/ui/imports/import-from-missing.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `spam::eggs` LL | use spam::{ham, eggs}; | ^^^^ no `eggs` in `spam` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-glob-0.stderr b/tests/ui/imports/import-glob-0.stderr index 820ff1bb536de..6a2837e770dc5 100644 --- a/tests/ui/imports/import-glob-0.stderr +++ b/tests/ui/imports/import-glob-0.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `f999` in this scope LL | f999(); | ^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/import-glob-circular.stderr b/tests/ui/imports/import-glob-circular.stderr index 86bbea579ae23..2eb268813d0f2 100644 --- a/tests/ui/imports/import-glob-circular.stderr +++ b/tests/ui/imports/import-glob-circular.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `f1066` in this scope LL | fn test() { f1066(); } | ^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/import-loop-2.stderr b/tests/ui/imports/import-loop-2.stderr index 1abfcde03dfb5..1a95200a66221 100644 --- a/tests/ui/imports/import-loop-2.stderr +++ b/tests/ui/imports/import-loop-2.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `a::x` LL | pub use a::x; | ^^^^ no `x` in `a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-loop.stderr b/tests/ui/imports/import-loop.stderr index b87bfb1be52cd..8ad2d6be4d27e 100644 --- a/tests/ui/imports/import-loop.stderr +++ b/tests/ui/imports/import-loop.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `y::x` LL | pub use y::x; | ^^^^ no `x` in `y` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-prefix-macro-1.stderr b/tests/ui/imports/import-prefix-macro-1.stderr index a6a5b1393daec..bdc0e85b43ed0 100644 --- a/tests/ui/imports/import-prefix-macro-1.stderr +++ b/tests/ui/imports/import-prefix-macro-1.stderr @@ -9,5 +9,5 @@ LL | import! { a::b::c } | = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/imports/import-prefix-macro-2.stderr b/tests/ui/imports/import-prefix-macro-2.stderr index 23f8d57645d18..070186f2bf2fb 100644 --- a/tests/ui/imports/import-prefix-macro-2.stderr +++ b/tests/ui/imports/import-prefix-macro-2.stderr @@ -9,5 +9,5 @@ LL | import! { a::b::c } | = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/imports/import-trait-method.stderr b/tests/ui/imports/import-trait-method.stderr index 3c26907d3d06e..9786eb52d3544 100644 --- a/tests/ui/imports/import-trait-method.stderr +++ b/tests/ui/imports/import-trait-method.stderr @@ -4,6 +4,6 @@ error[E0253]: `foo` is not directly importable LL | use Foo::foo; | ^^^^^^^^ cannot be imported directly -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0253`. diff --git a/tests/ui/imports/import2.stderr b/tests/ui/imports/import2.stderr index da888979c30f0..55eea66fd3b0e 100644 --- a/tests/ui/imports/import2.stderr +++ b/tests/ui/imports/import2.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `baz::zed` LL | use baz::zed::bar; | ^^^ could not find `zed` in `baz` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import3.stderr b/tests/ui/imports/import3.stderr index ca75c9c18bd28..80b0a7f061994 100644 --- a/tests/ui/imports/import3.stderr +++ b/tests/ui/imports/import3.stderr @@ -6,6 +6,6 @@ LL | use main::bar; | = help: consider adding `extern crate main` to use the `main` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import4.stderr b/tests/ui/imports/import4.stderr index e0b478f1aec4b..c99e838511877 100644 --- a/tests/ui/imports/import4.stderr +++ b/tests/ui/imports/import4.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `a::foo` LL | mod b { pub use a::foo; } | ^^^^^^ no `foo` in `a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-109148.stderr b/tests/ui/imports/issue-109148.stderr index 6cc1221cfe993..b7f1f69dc8f0c 100644 --- a/tests/ui/imports/issue-109148.stderr +++ b/tests/ui/imports/issue-109148.stderr @@ -9,5 +9,5 @@ LL | m!(); | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr index 8d9a3aee98024..1b95fcf55679f 100644 --- a/tests/ui/imports/issue-109343.stderr +++ b/tests/ui/imports/issue-109343.stderr @@ -6,6 +6,6 @@ LL | pub use unresolved::f; | = help: consider adding `extern crate unresolved` to use the `unresolved` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-113953.stderr b/tests/ui/imports/issue-113953.stderr index 70f91bd3c5bf0..9daa73a9fe6bb 100644 --- a/tests/ui/imports/issue-113953.stderr +++ b/tests/ui/imports/issue-113953.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `unresolved` LL | use unresolved as u8; | ^^^^^^^^^^^^^^^^ no external crate `unresolved` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-13404.stderr b/tests/ui/imports/issue-13404.stderr index 1f50debb07b11..a77f399e7918e 100644 --- a/tests/ui/imports/issue-13404.stderr +++ b/tests/ui/imports/issue-13404.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `b::f` LL | use b::f; | ^^^^ no `f` in `b` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-1697.stderr b/tests/ui/imports/issue-1697.stderr index 019ef9ad56a1f..840608ca2a14d 100644 --- a/tests/ui/imports/issue-1697.stderr +++ b/tests/ui/imports/issue-1697.stderr @@ -6,6 +6,6 @@ LL | use unresolved::*; | = help: consider adding `extern crate unresolved` to use the `unresolved` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-28388-1.stderr b/tests/ui/imports/issue-28388-1.stderr index 7f5e47aa84fbe..8256f96c62dd9 100644 --- a/tests/ui/imports/issue-28388-1.stderr +++ b/tests/ui/imports/issue-28388-1.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `foo` LL | use foo::{}; | ^^^^^^^ no `foo` in the root -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-28388-2.stderr b/tests/ui/imports/issue-28388-2.stderr index 1afaf622be7da..4eda57dd9e5ee 100644 --- a/tests/ui/imports/issue-28388-2.stderr +++ b/tests/ui/imports/issue-28388-2.stderr @@ -10,6 +10,6 @@ note: the module `n` is defined here LL | mod n {} | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/issue-2937.stderr b/tests/ui/imports/issue-2937.stderr index 428634828f9be..15622f233fa5d 100644 --- a/tests/ui/imports/issue-2937.stderr +++ b/tests/ui/imports/issue-2937.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `m::f` LL | use m::f as x; | ^^^^^^^^^ no `f` in `m` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-32354-suggest-import-rename.stderr b/tests/ui/imports/issue-32354-suggest-import-rename.stderr index 4c5875ba77664..de9bdc4f2cc85 100644 --- a/tests/ui/imports/issue-32354-suggest-import-rename.stderr +++ b/tests/ui/imports/issue-32354-suggest-import-rename.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use extension2::ConstructorExtension as OtherConstructorExtension; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-32833.stderr b/tests/ui/imports/issue-32833.stderr index 430cc0fda26da..332561eca7a33 100644 --- a/tests/ui/imports/issue-32833.stderr +++ b/tests/ui/imports/issue-32833.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `bar::Foo` LL | use bar::Foo; | ^^^^^^^^ no `Foo` in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-36881.stderr b/tests/ui/imports/issue-36881.stderr index 2e1b468603d47..e9b632d2718ce 100644 --- a/tests/ui/imports/issue-36881.stderr +++ b/tests/ui/imports/issue-36881.stderr @@ -6,6 +6,6 @@ LL | use issue_36881_aux::Foo; | = help: consider adding `extern crate issue_36881_aux` to use the `issue_36881_aux` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-4366.stderr b/tests/ui/imports/issue-4366.stderr index 4d5b392a7e104..e63399d554ee3 100644 --- a/tests/ui/imports/issue-4366.stderr +++ b/tests/ui/imports/issue-4366.stderr @@ -9,6 +9,6 @@ help: consider importing this function LL + use foo::foo; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr index 25aca4cb7ec22..80cea1a83d931 100644 --- a/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr +++ b/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr @@ -10,6 +10,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate std as other_std; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/issue-45829/import-twice.stderr b/tests/ui/imports/issue-45829/import-twice.stderr index 656b011bc3be8..b19d5d8f75891 100644 --- a/tests/ui/imports/issue-45829/import-twice.stderr +++ b/tests/ui/imports/issue-45829/import-twice.stderr @@ -8,6 +8,6 @@ LL | use foo::{A, A}; | = note: `A` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/issue-45829.stderr b/tests/ui/imports/issue-45829/issue-45829.stderr index e9a9d47ce7cd6..627a09a07b860 100644 --- a/tests/ui/imports/issue-45829/issue-45829.stderr +++ b/tests/ui/imports/issue-45829/issue-45829.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use foo::{A, B as OtherA}; | ~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/rename-extern-vs-use.stderr b/tests/ui/imports/issue-45829/rename-extern-vs-use.stderr index 98fd8a623fea1..8f2f7bbac0c9a 100644 --- a/tests/ui/imports/issue-45829/rename-extern-vs-use.stderr +++ b/tests/ui/imports/issue-45829/rename-extern-vs-use.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate issue_45829_b as other_bar; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/imports/issue-45829/rename-extern-with-tab.stderr b/tests/ui/imports/issue-45829/rename-extern-with-tab.stderr index 2c4e8ce996b15..ae26d1fd0bbc5 100644 --- a/tests/ui/imports/issue-45829/rename-extern-with-tab.stderr +++ b/tests/ui/imports/issue-45829/rename-extern-with-tab.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate issue_45829_b as other_issue_45829_a; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/issue-45829/rename-extern.stderr b/tests/ui/imports/issue-45829/rename-extern.stderr index 209ae2201f995..46560ef9244ea 100644 --- a/tests/ui/imports/issue-45829/rename-extern.stderr +++ b/tests/ui/imports/issue-45829/rename-extern.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate issue_45829_b as other_issue_45829_a; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr b/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr index dfb5810c494c6..9b0a2534a1d1f 100644 --- a/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr +++ b/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use std as other_issue_45829_b; | ~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr b/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr index 5a63af5885541..5751f41ae9d12 100644 --- a/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr +++ b/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use foo::{A, bar::B as OtherA}; | ~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/rename-with-path.stderr b/tests/ui/imports/issue-45829/rename-with-path.stderr index 2d26b08384e10..69e084db6ffc1 100644 --- a/tests/ui/imports/issue-45829/rename-with-path.stderr +++ b/tests/ui/imports/issue-45829/rename-with-path.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use std::{collections::HashMap as A, sync::Arc as OtherA}; | ~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/rename.stderr b/tests/ui/imports/issue-45829/rename.stderr index ed185ae2a4463..f1ee5112dc164 100644 --- a/tests/ui/imports/issue-45829/rename.stderr +++ b/tests/ui/imports/issue-45829/rename.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use std as other_core; | ~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-47623.stderr b/tests/ui/imports/issue-47623.stderr index 53968a2960ccd..be42a4a5b1d8d 100644 --- a/tests/ui/imports/issue-47623.stderr +++ b/tests/ui/imports/issue-47623.stderr @@ -4,6 +4,6 @@ error[E0429]: `self` imports are only allowed within a { } list LL | use self; | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0429`. diff --git a/tests/ui/imports/issue-53512.stderr b/tests/ui/imports/issue-53512.stderr index 05fe111b38bc6..6bcba1ad429c2 100644 --- a/tests/ui/imports/issue-53512.stderr +++ b/tests/ui/imports/issue-53512.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `m::assert` LL | use m::assert; | ^^^^^^^^^ no `assert` in `m` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-55884-1.stderr b/tests/ui/imports/issue-55884-1.stderr index c38166ddea6aa..ae8edb0495647 100644 --- a/tests/ui/imports/issue-55884-1.stderr +++ b/tests/ui/imports/issue-55884-1.stderr @@ -18,6 +18,6 @@ LL | pub use self::m2::*; | ^^^^^^^^^^^ = help: consider adding an explicit import of `S` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/issue-55884-2.stderr b/tests/ui/imports/issue-55884-2.stderr index 67d4114149a4b..8a9d5f2a6d8a6 100644 --- a/tests/ui/imports/issue-55884-2.stderr +++ b/tests/ui/imports/issue-55884-2.stderr @@ -13,18 +13,22 @@ note: ...and refers to the struct import `ParseOptions` which is defined here... --> $DIR/issue-55884-2.rs:13:9 | LL | pub use parser::ParseOptions; - | ^^^^^^^^^^^^^^^^^^^^ consider importing it directly + | ^^^^^^^^^^^^^^^^^^^^ you could import this re-export note: ...and refers to the struct import `ParseOptions` which is defined here... --> $DIR/issue-55884-2.rs:6:13 | LL | pub use options::*; - | ^^^^^^^^^^ consider importing it directly + | ^^^^^^^^^^ you could import this re-export note: ...and refers to the struct `ParseOptions` which is defined here --> $DIR/issue-55884-2.rs:2:5 | LL | pub struct ParseOptions {} - | ^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly + | ^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly +help: import `ParseOptions` through the re-export + | +LL | pub use parser::ParseOptions; + | ~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/issue-57015.stderr b/tests/ui/imports/issue-57015.stderr index 5374ba3dc9e6d..f1ae784524170 100644 --- a/tests/ui/imports/issue-57015.stderr +++ b/tests/ui/imports/issue-57015.stderr @@ -9,6 +9,6 @@ help: consider importing this module instead LL | use glob_ok::something; | ~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-57539.stderr b/tests/ui/imports/issue-57539.stderr index 88cc42ccf6682..c8473cc85bdae 100644 --- a/tests/ui/imports/issue-57539.stderr +++ b/tests/ui/imports/issue-57539.stderr @@ -15,6 +15,6 @@ LL | use crate::*; = help: consider adding an explicit import of `core` to disambiguate = help: or use `self::core` to refer to this module unambiguously -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/issue-81413.stderr b/tests/ui/imports/issue-81413.stderr index e2dfe02bc8530..c2a3212501181 100644 --- a/tests/ui/imports/issue-81413.stderr +++ b/tests/ui/imports/issue-81413.stderr @@ -6,6 +6,6 @@ LL | pub use doesnt_exist::*; | = help: consider adding `extern crate doesnt_exist` to use the `doesnt_exist` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-85992.stderr b/tests/ui/imports/issue-85992.stderr index 810d41009c520..6c75b45d926c0 100644 --- a/tests/ui/imports/issue-85992.stderr +++ b/tests/ui/imports/issue-85992.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `crate::issue_85992_extern_2` LL | use crate::issue_85992_extern_2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `issue_85992_extern_2` in the root -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-8640.stderr b/tests/ui/imports/issue-8640.stderr index ab44f067fe744..ea350e97e6420 100644 --- a/tests/ui/imports/issue-8640.stderr +++ b/tests/ui/imports/issue-8640.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use baz::bar as other_bar; | ~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/imports/issue-99695-b.stderr b/tests/ui/imports/issue-99695-b.stderr index b6f5c726a5ca9..d58d2798746c1 100644 --- a/tests/ui/imports/issue-99695-b.stderr +++ b/tests/ui/imports/issue-99695-b.stderr @@ -11,6 +11,6 @@ LL ~ use ::nu; LL ~ pub use self::p::{other_item as _}; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-99695.stderr b/tests/ui/imports/issue-99695.stderr index 0ef762e1c8230..536f51dcb3b20 100644 --- a/tests/ui/imports/issue-99695.stderr +++ b/tests/ui/imports/issue-99695.stderr @@ -11,6 +11,6 @@ LL ~ use ::nu; LL ~ pub use self::{other_item as _}; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/no-pub-reexports-but-used.rs b/tests/ui/imports/no-pub-reexports-but-used.rs new file mode 100644 index 0000000000000..28991bde829f8 --- /dev/null +++ b/tests/ui/imports/no-pub-reexports-but-used.rs @@ -0,0 +1,15 @@ +// check-pass +// https://github.com/rust-lang/rust/issues/115966 + +mod m { + pub(crate) type A = u8; +} + +#[warn(unused_imports)] //~ NOTE: the lint level is defined here +pub use m::*; +//~^ WARNING: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough +//~| NOTE: the most public imported item is `pub(crate)` + +fn main() { + let _: A; +} diff --git a/tests/ui/imports/no-pub-reexports-but-used.stderr b/tests/ui/imports/no-pub-reexports-but-used.stderr new file mode 100644 index 0000000000000..b693dea193579 --- /dev/null +++ b/tests/ui/imports/no-pub-reexports-but-used.stderr @@ -0,0 +1,20 @@ +warning: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough + --> $DIR/no-pub-reexports-but-used.rs:9:9 + | +LL | pub use m::*; + | ^^^^ + | +note: the most public imported item is `pub(crate)` + --> $DIR/no-pub-reexports-but-used.rs:9:9 + | +LL | pub use m::*; + | ^^^^ + = help: reduce the glob import's visibility or increase visibility of imported items +note: the lint level is defined here + --> $DIR/no-pub-reexports-but-used.rs:8:8 + | +LL | #[warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/imports/no-std-inject.stderr b/tests/ui/imports/no-std-inject.stderr index 8e226804890d9..597ecdce9eb99 100644 --- a/tests/ui/imports/no-std-inject.stderr +++ b/tests/ui/imports/no-std-inject.stderr @@ -10,6 +10,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate core as other_core; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/overlapping_pub_trait.stderr b/tests/ui/imports/overlapping_pub_trait.stderr index 490dccd3e808e..a82a4101ce0ba 100644 --- a/tests/ui/imports/overlapping_pub_trait.stderr +++ b/tests/ui/imports/overlapping_pub_trait.stderr @@ -15,6 +15,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use overlapping_pub_trait_source::m::Tr; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/imports/private-std-reexport-suggest-public.fixed b/tests/ui/imports/private-std-reexport-suggest-public.fixed new file mode 100644 index 0000000000000..b6fd22f5d3ffc --- /dev/null +++ b/tests/ui/imports/private-std-reexport-suggest-public.fixed @@ -0,0 +1,9 @@ +// run-rustfix +#![allow(unused_imports)] +fn main() { + use std::mem; //~ ERROR module import `mem` is private +} + +pub mod foo { + use std::mem; +} diff --git a/tests/ui/imports/private-std-reexport-suggest-public.rs b/tests/ui/imports/private-std-reexport-suggest-public.rs new file mode 100644 index 0000000000000..1247055af6063 --- /dev/null +++ b/tests/ui/imports/private-std-reexport-suggest-public.rs @@ -0,0 +1,9 @@ +// run-rustfix +#![allow(unused_imports)] +fn main() { + use foo::mem; //~ ERROR module import `mem` is private +} + +pub mod foo { + use std::mem; +} diff --git a/tests/ui/imports/private-std-reexport-suggest-public.stderr b/tests/ui/imports/private-std-reexport-suggest-public.stderr new file mode 100644 index 0000000000000..222553235aaac --- /dev/null +++ b/tests/ui/imports/private-std-reexport-suggest-public.stderr @@ -0,0 +1,23 @@ +error[E0603]: module import `mem` is private + --> $DIR/private-std-reexport-suggest-public.rs:4:14 + | +LL | use foo::mem; + | ^^^ private module import + | +note: the module import `mem` is defined here... + --> $DIR/private-std-reexport-suggest-public.rs:8:9 + | +LL | use std::mem; + | ^^^^^^^^ +note: ...and refers to the module `mem` which is defined here + --> $SRC_DIR/std/src/lib.rs:LL:COL + | + = note: you could import this directly +help: import `mem` through the re-export + | +LL | use std::mem; + | ~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/reexports.rs b/tests/ui/imports/reexports.rs index cb1a3ebe18028..2a1a62834ce8b 100644 --- a/tests/ui/imports/reexports.rs +++ b/tests/ui/imports/reexports.rs @@ -9,7 +9,7 @@ mod a { //~^ ERROR cannot be re-exported //~| WARNING unused import: `super::foo` pub use super::*; - //~^ WARNING glob import doesn't reexport anything because no candidate is public enough + //~^ WARNING glob import doesn't reexport anything with visibility `pub` because no imported item is public enough //~| WARNING unused import: `super::*` } } diff --git a/tests/ui/imports/reexports.stderr b/tests/ui/imports/reexports.stderr index 401e422af0f8e..bf4ba474875bf 100644 --- a/tests/ui/imports/reexports.stderr +++ b/tests/ui/imports/reexports.stderr @@ -56,11 +56,18 @@ note: the lint level is defined here LL | #![warn(unused_imports)] | ^^^^^^^^^^^^^^ -warning: glob import doesn't reexport anything because no candidate is public enough +warning: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough --> $DIR/reexports.rs:11:17 | LL | pub use super::*; | ^^^^^^^^ + | +note: the most public imported item is `pub(a)` + --> $DIR/reexports.rs:11:17 + | +LL | pub use super::*; + | ^^^^^^^^ + = help: reduce the glob import's visibility or increase visibility of imported items warning: unused import: `super::*` --> $DIR/reexports.rs:11:17 diff --git a/tests/ui/imports/resolve-other-libc.stderr b/tests/ui/imports/resolve-other-libc.stderr index e57b88e50c639..81fe1294671d7 100644 --- a/tests/ui/imports/resolve-other-libc.stderr +++ b/tests/ui/imports/resolve-other-libc.stderr @@ -4,5 +4,5 @@ error: extern location for libc does not exist: test.rlib LL | extern crate libc; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/imports/rfc-1560-warning-cycle.stderr b/tests/ui/imports/rfc-1560-warning-cycle.stderr index fd7e99165b551..8a83e58138365 100644 --- a/tests/ui/imports/rfc-1560-warning-cycle.stderr +++ b/tests/ui/imports/rfc-1560-warning-cycle.stderr @@ -18,6 +18,6 @@ LL | use bar::*; | ^^^^^^ = help: consider adding an explicit import of `Foo` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/unnamed_pub_trait.stderr b/tests/ui/imports/unnamed_pub_trait.stderr index 5133273c22f6c..41772b8e694d3 100644 --- a/tests/ui/imports/unnamed_pub_trait.stderr +++ b/tests/ui/imports/unnamed_pub_trait.stderr @@ -15,6 +15,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use unnamed_pub_trait_source::prelude::*; // trait Tr | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/imports/unused-import-issue-87973.stderr b/tests/ui/imports/unused-import-issue-87973.stderr index 81b7ea791912d..a43e92b145802 100644 --- a/tests/ui/imports/unused-import-issue-87973.stderr +++ b/tests/ui/imports/unused-import-issue-87973.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_imports)] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/imports/unused.stderr b/tests/ui/imports/unused.stderr index 08128d794251b..a76c3c87a4703 100644 --- a/tests/ui/imports/unused.stderr +++ b/tests/ui/imports/unused.stderr @@ -11,5 +11,5 @@ LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(unused_imports)]` implied by `#[deny(unused)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/indexing/index-bot.stderr b/tests/ui/indexing/index-bot.stderr index bf231c92cad07..dca57f3d5b634 100644 --- a/tests/ui/indexing/index-bot.stderr +++ b/tests/ui/indexing/index-bot.stderr @@ -4,6 +4,6 @@ error[E0608]: cannot index into a value of type `!` LL | (return)[0]; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr index 2cb212a013960..4ec28ddf87171 100644 --- a/tests/ui/indexing/index-help.stderr +++ b/tests/ui/indexing/index-help.stderr @@ -9,6 +9,6 @@ LL | x[0i32]; = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec<{integer}>` to implement `Index` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/indexing/index_message.stderr b/tests/ui/indexing/index_message.stderr index 80f2bd52314d9..6affb1ed96252 100644 --- a/tests/ui/indexing/index_message.stderr +++ b/tests/ui/indexing/index_message.stderr @@ -4,6 +4,6 @@ error[E0608]: cannot index into a value of type `({integer},)` LL | let _ = z[0]; | ^^^ help: to access tuple elements, use: `.0` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 6ea6bb600e944..3041c2c99a108 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -8,6 +8,8 @@ LL | [0][0u8]; = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[{integer}]` to implement `Index` + = note: 1 redundant requirement hidden + = note: required for `[{integer}; 1]` to implement `Index` error[E0308]: mismatched types --> $DIR/indexing-requires-a-uint.rs:12:18 diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.rs b/tests/ui/indexing/point-at-index-for-obligation-failure.rs new file mode 100644 index 0000000000000..e9c429b53ced1 --- /dev/null +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.rs @@ -0,0 +1,7 @@ +fn main() { + let a = std::collections::HashMap::::new(); + let s = "hello"; + let _b = a[ + &s //~ ERROR E0277 + ]; +} diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr new file mode 100644 index 0000000000000..4cced22789f74 --- /dev/null +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `String: Borrow<&str>` is not satisfied + --> $DIR/point-at-index-for-obligation-failure.rs:5:9 + | +LL | &s + | ^^ the trait `Borrow<&str>` is not implemented for `String` + | + = help: the trait `Borrow` is implemented for `String` + = help: for that trait implementation, expected `str`, found `&str` + = note: required for `HashMap` to implement `Index<&&str>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/inference/ambiguous_type_parameter.stderr b/tests/ui/inference/ambiguous_type_parameter.stderr index 9cbe221de1393..0674deb63ba0c 100644 --- a/tests/ui/inference/ambiguous_type_parameter.stderr +++ b/tests/ui/inference/ambiguous_type_parameter.stderr @@ -9,6 +9,6 @@ help: try using a fully qualified path to specify the expected types LL | >>::get_raw(&InMemoryStore, &String::default()); | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/cannot-infer-async.stderr b/tests/ui/inference/cannot-infer-async.stderr index 0579cf238a9da..346109fd5c018 100644 --- a/tests/ui/inference/cannot-infer-async.stderr +++ b/tests/ui/inference/cannot-infer-async.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic arguments LL | Ok::<(), E>(()) | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr index 98639f307fbfd..e3cf0cca83711 100644 --- a/tests/ui/inference/cannot-infer-closure-circular.stderr +++ b/tests/ui/inference/cannot-infer-closure-circular.stderr @@ -12,6 +12,6 @@ help: consider giving this closure parameter an explicit type, where the type fo LL | let x = |r: Result<(), E>| { | +++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/cannot-infer-closure.stderr b/tests/ui/inference/cannot-infer-closure.stderr index a4b818e6e2bb8..507a70c1bac46 100644 --- a/tests/ui/inference/cannot-infer-closure.stderr +++ b/tests/ui/inference/cannot-infer-closure.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic arguments LL | Ok::<(), E>(b) | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/cannot-infer-partial-try-return.stderr b/tests/ui/inference/cannot-infer-partial-try-return.stderr index 888c321bc479b..ff4d7418a63af 100644 --- a/tests/ui/inference/cannot-infer-partial-try-return.stderr +++ b/tests/ui/inference/cannot-infer-partial-try-return.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic arguments LL | Ok::<(), QualifiedError<_>>(()) | +++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/inference_unstable_featured.stderr b/tests/ui/inference/inference_unstable_featured.stderr index dc43abf52c650..b908c7142d4b1 100644 --- a/tests/ui/inference/inference_unstable_featured.stderr +++ b/tests/ui/inference/inference_unstable_featured.stderr @@ -15,6 +15,6 @@ help: disambiguate the method for candidate #2 LL | assert_eq!(IpuItertools::ipu_flatten(&'x'), 0); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/inference/inference_unstable_forced.stderr b/tests/ui/inference/inference_unstable_forced.stderr index a1c4cd851cb94..2301eacc596dd 100644 --- a/tests/ui/inference/inference_unstable_forced.stderr +++ b/tests/ui/inference/inference_unstable_forced.stderr @@ -7,6 +7,6 @@ LL | assert_eq!('x'.ipu_flatten(), 0); = note: see issue #99999 for more information = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr index 2819329275d17..afece960914da 100644 --- a/tests/ui/inference/issue-104649.stderr +++ b/tests/ui/inference/issue-104649.stderr @@ -9,6 +9,6 @@ help: consider giving `a` an explicit type, where the type for type parameter `E LL | let a: A, Error>> = A(Result::Ok(Result::Ok(()))); | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/issue-113354.stderr b/tests/ui/inference/issue-113354.stderr index 045a5aa7bf0ea..27cc7a33238e9 100644 --- a/tests/ui/inference/issue-113354.stderr +++ b/tests/ui/inference/issue-113354.stderr @@ -9,6 +9,6 @@ help: consider adding `let` LL | let _ = || { while let Some(_) = Some(1) { } }; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/issue-70082.stderr b/tests/ui/inference/issue-70082.stderr index 47229a5fee14d..442e7479a9eb4 100644 --- a/tests/ui/inference/issue-70082.stderr +++ b/tests/ui/inference/issue-70082.stderr @@ -12,6 +12,6 @@ help: try using a fully qualified path to specify the expected types LL | let y: f64 = 0.01f64 * >::into(1i16); | +++++++++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/inference/issue-71309.stderr b/tests/ui/inference/issue-71309.stderr index af8714f1c8083..673649c767e3d 100644 --- a/tests/ui/inference/issue-71309.stderr +++ b/tests/ui/inference/issue-71309.stderr @@ -10,6 +10,6 @@ help: you can convert an `i32` to a `u32` and panic if the converted value doesn LL | let y: u32 = x?.try_into().unwrap(); | ++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/issue-71584.stderr b/tests/ui/inference/issue-71584.stderr index 22c0f113d6ab8..391d3e7613e03 100644 --- a/tests/ui/inference/issue-71584.stderr +++ b/tests/ui/inference/issue-71584.stderr @@ -12,6 +12,6 @@ help: try using a fully qualified path to specify the expected types LL | d = d % >::into(n); | +++++++++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/inference/issue-71732.stderr b/tests/ui/inference/issue-71732.stderr index e89e4dca61917..af8b310fd1d9c 100644 --- a/tests/ui/inference/issue-71732.stderr +++ b/tests/ui/inference/issue-71732.stderr @@ -17,6 +17,6 @@ help: consider specifying the generic argument LL | .get::(&"key".into()) | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/issue-80816.stderr b/tests/ui/inference/issue-80816.stderr index 80c0c8abec6a3..ab62db8e6af21 100644 --- a/tests/ui/inference/issue-80816.stderr +++ b/tests/ui/inference/issue-80816.stderr @@ -24,6 +24,6 @@ help: try using a fully qualified path to specify the expected types LL | let guard: Guard> = >> as Access>::load(&s); | ++++++++++++++++++++++++++++++++++++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr index 97ed53fb3ce56..00de4029e4281 100644 --- a/tests/ui/inference/issue-83606.stderr +++ b/tests/ui/inference/issue-83606.stderr @@ -9,6 +9,6 @@ help: consider giving this pattern a type, where the value of const parameter `N LL | let _: [usize; N] = foo("foo"); | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/issue-86162-1.stderr b/tests/ui/inference/issue-86162-1.stderr index 4f621b82dc579..fe3cee771609c 100644 --- a/tests/ui/inference/issue-86162-1.stderr +++ b/tests/ui/inference/issue-86162-1.stderr @@ -17,6 +17,6 @@ help: consider specifying the generic argument LL | foo(gen::()); //<- Do not suggest `foo::()`! | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/issue-86162-2.stderr b/tests/ui/inference/issue-86162-2.stderr index 9aff2cec160f2..7b45b196629ec 100644 --- a/tests/ui/inference/issue-86162-2.stderr +++ b/tests/ui/inference/issue-86162-2.stderr @@ -17,6 +17,6 @@ help: consider specifying the generic argument LL | Foo::bar(gen::()); //<- Do not suggest `Foo::bar::()`! | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/multiple-impl-apply.stderr b/tests/ui/inference/multiple-impl-apply.stderr index ec49e15201af9..1a81955e1e88c 100644 --- a/tests/ui/inference/multiple-impl-apply.stderr +++ b/tests/ui/inference/multiple-impl-apply.stderr @@ -18,6 +18,6 @@ help: consider giving `y` an explicit type LL | let y: /* Type */ = x.into(); | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr index 6b86753caf992..7b400fd17db48 100644 --- a/tests/ui/inference/need_type_info/concrete-impl.stderr +++ b/tests/ui/inference/need_type_info/concrete-impl.stderr @@ -13,6 +13,6 @@ LL | LL | impl Ambiguous for Struct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr index 2ad35ab039f4c..fcac537a9b842 100644 --- a/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr +++ b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | OhNo::C::; | ^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the enum `OhNo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr index 68ecb38134837..dfbdc3266c56c 100644 --- a/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | needs_infer::(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr index cbc2477deb39a..c72529f71c2a3 100644 --- a/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | Self::Output::Simple {}; | ^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated type `Output` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr index 397d8e7be04ff..333c93859b57f 100644 --- a/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | needs_infer::(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr b/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr index 36d75469392b6..aeebf68e67576 100644 --- a/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr +++ b/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr @@ -9,6 +9,6 @@ help: use a fully-qualified path to a specific available implementation LL | let _ = (::default(),); | +++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/inference/need_type_info/issue-103053.stderr b/tests/ui/inference/need_type_info/issue-103053.stderr index 84f0475d8cdac..ed389393abc91 100644 --- a/tests/ui/inference/need_type_info/issue-103053.stderr +++ b/tests/ui/inference/need_type_info/issue-103053.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | None::; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr b/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr index 464655bbcf451..3de317d2af6d1 100644 --- a/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr +++ b/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr @@ -6,6 +6,6 @@ LL | println!("{:?}", []); | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr index 9ca94cd58df32..455304524edc4 100644 --- a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr +++ b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr @@ -17,6 +17,6 @@ help: consider specifying the generic argument LL | (S {}).owo(None::<&_>) | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/need_type_info/self-ty-in-path.stderr b/tests/ui/inference/need_type_info/self-ty-in-path.stderr index 04b521dbdb360..d651927788ea3 100644 --- a/tests/ui/inference/need_type_info/self-ty-in-path.stderr +++ b/tests/ui/inference/need_type_info/self-ty-in-path.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | Self::func_a::(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/type-alias-indirect.stderr b/tests/ui/inference/need_type_info/type-alias-indirect.stderr index 6161690df5050..535c0044aec03 100644 --- a/tests/ui/inference/need_type_info/type-alias-indirect.stderr +++ b/tests/ui/inference/need_type_info/type-alias-indirect.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | IndirectAlias::new(); | ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/question-mark-type-infer.stderr b/tests/ui/inference/question-mark-type-infer.stderr index 52baa213302c0..45303a2c87ff0 100644 --- a/tests/ui/inference/question-mark-type-infer.stderr +++ b/tests/ui/inference/question-mark-type-infer.stderr @@ -12,6 +12,6 @@ help: consider specifying the generic argument LL | l.iter().map(f).collect::>()? | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/infinite/infinite-alias.stderr b/tests/ui/infinite/infinite-alias.stderr index 9d9265f8c367c..3862c1139c5c7 100644 --- a/tests/ui/infinite/infinite-alias.stderr +++ b/tests/ui/infinite/infinite-alias.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | struct Rec(Box>); | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/infinite/infinite-instantiation.polonius.stderr b/tests/ui/infinite/infinite-instantiation.polonius.stderr index 29eb8c481cdee..f048c942f1a7b 100644 --- a/tests/ui/infinite/infinite-instantiation.polonius.stderr +++ b/tests/ui/infinite/infinite-instantiation.polonius.stderr @@ -11,5 +11,5 @@ LL | fn function(counter: usize, t: T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation.polonius/infinite-instantiation.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/infinite/infinite-instantiation.stderr b/tests/ui/infinite/infinite-instantiation.stderr index 951e0f5870d7d..43d267fa46bfc 100644 --- a/tests/ui/infinite/infinite-instantiation.stderr +++ b/tests/ui/infinite/infinite-instantiation.stderr @@ -11,5 +11,5 @@ LL | fn function(counter: usize, t: T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation/infinite-instantiation.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/infinite/infinite-macro-expansion.stderr b/tests/ui/infinite/infinite-macro-expansion.stderr index 15654dfaf88f1..08fb4fa77236b 100644 --- a/tests/ui/infinite/infinite-macro-expansion.stderr +++ b/tests/ui/infinite/infinite-macro-expansion.stderr @@ -10,5 +10,5 @@ LL | recursive!() = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_macro_expansion`) = note: this error originates in the macro `recursive` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/infinite/infinite-recursion-const-fn.stderr b/tests/ui/infinite/infinite-recursion-const-fn.stderr index 53b603a47b551..fd5a3c3c5464d 100644 --- a/tests/ui/infinite/infinite-recursion-const-fn.stderr +++ b/tests/ui/infinite/infinite-recursion-const-fn.stderr @@ -645,6 +645,6 @@ note: inside `ARR::{constant#0}` LL | const ARR: [i32; a()] = [5; 6]; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/infinite/infinite-tag-type-recursion.stderr b/tests/ui/infinite/infinite-tag-type-recursion.stderr index 513bbfc1b8cf1..4ca408260b84a 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.stderr +++ b/tests/ui/infinite/infinite-tag-type-recursion.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum MList { Cons(isize, Box), Nil } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/infinite/infinite-trait-alias-recursion.stderr b/tests/ui/infinite/infinite-trait-alias-recursion.stderr index 39d7aa4c16aa3..220d81031ac22 100644 --- a/tests/ui/infinite/infinite-trait-alias-recursion.stderr +++ b/tests/ui/infinite/infinite-trait-alias-recursion.stderr @@ -23,6 +23,6 @@ LL | trait T1 = T2; | ^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr b/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr index ec63688fa8b93..57ca1b24d2a38 100644 --- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr @@ -31,6 +31,6 @@ LL | | fn main() {} | |____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/infinite/infinite-vec-type-recursion.feature.stderr b/tests/ui/infinite/infinite-vec-type-recursion.feature.stderr index 3a146215905a6..3aac0d7d1db74 100644 --- a/tests/ui/infinite/infinite-vec-type-recursion.feature.stderr +++ b/tests/ui/infinite/infinite-vec-type-recursion.feature.stderr @@ -6,6 +6,6 @@ LL | type X = Vec; | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr b/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr index e47d9b652fb4a..efafc9b75cdbf 100644 --- a/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr +++ b/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr @@ -21,6 +21,6 @@ LL | | fn main() { let b: X = Vec::new(); } | |____________________________________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/inline-const/const-expr-generic-err2.stderr b/tests/ui/inline-const/const-expr-generic-err2.stderr index 00b716cd25965..5876a6c9e198d 100644 --- a/tests/ui/inline-const/const-expr-generic-err2.stderr +++ b/tests/ui/inline-const/const-expr-generic-err2.stderr @@ -6,5 +6,5 @@ LL | let _ = [0u8; const { std::mem::size_of::() }]; | = note: this may fail depending on what value the parameter takes -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/inline-const/const-expr-lifetime-err.stderr b/tests/ui/inline-const/const-expr-lifetime-err.stderr index 443fcf89c4e11..75877bc093a79 100644 --- a/tests/ui/inline-const/const-expr-lifetime-err.stderr +++ b/tests/ui/inline-const/const-expr-lifetime-err.stderr @@ -14,6 +14,6 @@ LL | LL | } | - `y` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/inline-const/expr-unsafe-err.mir.stderr b/tests/ui/inline-const/expr-unsafe-err.mir.stderr index 1bec41e2efa01..ebd18f89d9c94 100644 --- a/tests/ui/inline-const/expr-unsafe-err.mir.stderr +++ b/tests/ui/inline-const/expr-unsafe-err.mir.stderr @@ -6,6 +6,6 @@ LL | require_unsafe(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/inline-const/expr-unsafe-err.thir.stderr b/tests/ui/inline-const/expr-unsafe-err.thir.stderr index c971e8afb3577..45f850d1f99bf 100644 --- a/tests/ui/inline-const/expr-unsafe-err.thir.stderr +++ b/tests/ui/inline-const/expr-unsafe-err.thir.stderr @@ -6,6 +6,6 @@ LL | require_unsafe(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/inline-const/expr-with-block-err.stderr b/tests/ui/inline-const/expr-with-block-err.stderr index 6f7408f4e2a6a..a46d739504582 100644 --- a/tests/ui/inline-const/expr-with-block-err.stderr +++ b/tests/ui/inline-const/expr-with-block-err.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | const { 2 } - const { 1 }; | ^ expected `()`, found integer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inline-const/pat-match-fndef.stderr b/tests/ui/inline-const/pat-match-fndef.stderr index c94782b17ce95..02c4a60b68f20 100644 --- a/tests/ui/inline-const/pat-match-fndef.stderr +++ b/tests/ui/inline-const/pat-match-fndef.stderr @@ -13,5 +13,5 @@ error: `fn() {uwu}` cannot be used in patterns LL | const { uwu } => {} | ^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/inline-const/promotion.stderr b/tests/ui/inline-const/promotion.stderr index 795fc8f5921a9..7f06b97818bf5 100644 --- a/tests/ui/inline-const/promotion.stderr +++ b/tests/ui/inline-const/promotion.stderr @@ -9,6 +9,6 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr index d6948e7acc03a..cd86020184dda 100644 --- a/tests/ui/inline-const/required-const.stderr +++ b/tests/ui/inline-const/required-const.stderr @@ -6,6 +6,6 @@ LL | const { panic!() } | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/inline-disallow-on-variant.stderr b/tests/ui/inline-disallow-on-variant.stderr index 1b176579bbbcf..255f6bc6a1957 100644 --- a/tests/ui/inline-disallow-on-variant.stderr +++ b/tests/ui/inline-disallow-on-variant.stderr @@ -7,6 +7,6 @@ LL | LL | Variant, | ------- not a function or closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/instrument-xray/target-not-supported.stderr b/tests/ui/instrument-xray/target-not-supported.stderr index 6e3b0c8a380b8..119094bfc4c7c 100644 --- a/tests/ui/instrument-xray/target-not-supported.stderr +++ b/tests/ui/instrument-xray/target-not-supported.stderr @@ -1,4 +1,4 @@ error: XRay instrumentation is not supported for this target -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/integral-variable-unification-error.stderr b/tests/ui/integral-variable-unification-error.stderr index f77c265a2ada7..1caa6042fd206 100644 --- a/tests/ui/integral-variable-unification-error.stderr +++ b/tests/ui/integral-variable-unification-error.stderr @@ -9,6 +9,6 @@ LL | 2; LL | x = 5.0; | ^^^ expected integer, found floating-point number -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/interior-mutability/interior-mutability.stderr b/tests/ui/interior-mutability/interior-mutability.stderr index 0c3be7ca60774..36686565e2e3a 100644 --- a/tests/ui/interior-mutability/interior-mutability.stderr +++ b/tests/ui/interior-mutability/interior-mutability.stderr @@ -18,6 +18,6 @@ LL | catch_unwind(|| { x.set(23); }); note: required by a bound in `catch_unwind` --> $SRC_DIR/std/src/panic.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/internal-lints/existing_doc_keyword.stderr b/tests/ui/internal-lints/existing_doc_keyword.stderr index 5110b9be08a53..8f519fe6b5f28 100644 --- a/tests/ui/internal-lints/existing_doc_keyword.stderr +++ b/tests/ui/internal-lints/existing_doc_keyword.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(rustc::existing_doc_keyword)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/internal/internal-unstable-const.stderr b/tests/ui/internal/internal-unstable-const.stderr index 5c63992d81985..ed9196d2b63bd 100644 --- a/tests/ui/internal/internal-unstable-const.stderr +++ b/tests/ui/internal/internal-unstable-const.stderr @@ -15,5 +15,5 @@ LL + #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] LL | pub const fn foo() -> f32 { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/internal/internal-unstable-thread-local.stderr b/tests/ui/internal/internal-unstable-thread-local.stderr index 558e3dbb78df6..7c07c762827d4 100644 --- a/tests/ui/internal/internal-unstable-thread-local.stderr +++ b/tests/ui/internal/internal-unstable-thread-local.stderr @@ -6,6 +6,6 @@ LL | thread_local!(static BAR: () = internal_unstable::unstable()); | = help: add `#![feature(function)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr index e6ff9d5a0df7d..bf91dc72cc14d 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.stderr +++ b/tests/ui/intrinsics/const-eval-select-bad.stderr @@ -86,6 +86,10 @@ LL | const_eval_select((true,), foo, baz); found function signature `fn(i32) -> _` note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | const_eval_select((true,), |arg0: bool| foo(/* i32 */), baz); + | ++++++++++++ +++++++++++ error: this argument must be a `const fn` --> $DIR/const-eval-select-bad.rs:42:29 diff --git a/tests/ui/intrinsics/const-eval-select-stability.stderr b/tests/ui/intrinsics/const-eval-select-stability.stderr index 65b507b887b46..335b9877aa008 100644 --- a/tests/ui/intrinsics/const-eval-select-stability.stderr +++ b/tests/ui/intrinsics/const-eval-select-stability.stderr @@ -6,5 +6,5 @@ LL | const_eval_select((), nothing, log); | = help: const-stable functions can only call other const-stable functions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/intrinsics/issue-28575.mir.stderr b/tests/ui/intrinsics/issue-28575.mir.stderr index c42498390c78d..4b29b4c1b6a9a 100644 --- a/tests/ui/intrinsics/issue-28575.mir.stderr +++ b/tests/ui/intrinsics/issue-28575.mir.stderr @@ -6,6 +6,6 @@ LL | FOO() | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/issue-28575.thir.stderr b/tests/ui/intrinsics/issue-28575.thir.stderr index c42498390c78d..4b29b4c1b6a9a 100644 --- a/tests/ui/intrinsics/issue-28575.thir.stderr +++ b/tests/ui/intrinsics/issue-28575.thir.stderr @@ -6,6 +6,6 @@ LL | FOO() | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr index 52a5919026463..7bc17c5c68c2b 100644 --- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr @@ -1,4 +1,4 @@ error: `-Zbranch-protection` is only supported on aarch64 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid-compile-flags/fuel.rs b/tests/ui/invalid-compile-flags/fuel.rs new file mode 100644 index 0000000000000..456bc47d359ee --- /dev/null +++ b/tests/ui/invalid-compile-flags/fuel.rs @@ -0,0 +1,11 @@ +// revisions: incremental threads +// dont-check-compiler-stderr +// +// [threads] compile-flags: -Zfuel=a=1 -Zthreads=2 +// [threads] error-pattern:optimization fuel is incompatible with multiple threads +// +// [incremental] incremental +// [incremental] compile-flags: -Zprint-fuel=a +// [incremental] error-pattern:optimization fuel is incompatible with incremental compilation + +fn main() {} diff --git a/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.aarch64.stderr b/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.aarch64.stderr new file mode 100644 index 0000000000000..a4fe77f5cbbd9 --- /dev/null +++ b/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.aarch64.stderr @@ -0,0 +1,4 @@ +error: `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 + +error: aborting due to 1 previous error + diff --git a/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs b/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs new file mode 100644 index 0000000000000..15a88ebdb118a --- /dev/null +++ b/tests/ui/invalid-compile-flags/function-return/requires-x86-or-x86_64.rs @@ -0,0 +1,20 @@ +// revisions: x86 x86_64 aarch64 + +// compile-flags: -Zfunction-return=thunk-extern + +//[x86] check-pass +//[x86] needs-llvm-components: x86 +//[x86] compile-flags: --target i686-unknown-linux-gnu + +//[x86_64] check-pass +//[x86_64] needs-llvm-components: x86 +//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu + +//[aarch64] check-fail +//[aarch64] needs-llvm-components: aarch64 +//[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//[aarch64] error-pattern: `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 + +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.large.stderr b/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.large.stderr new file mode 100644 index 0000000000000..683b3213d07eb --- /dev/null +++ b/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.large.stderr @@ -0,0 +1,4 @@ +error: `-Zfunction-return=thunk-extern` is only supported on non-large code models + +error: aborting due to 1 previous error + diff --git a/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs b/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs new file mode 100644 index 0000000000000..f925905de3613 --- /dev/null +++ b/tests/ui/invalid-compile-flags/function-return/thunk-extern-requires-non-large-code-model.rs @@ -0,0 +1,21 @@ +// revisions: small kernel medium large + +// needs-llvm-components: x86 +// compile-flags: --target x86_64-unknown-linux-gnu -Zfunction-return=thunk-extern + +//[small] check-pass +//[small] compile-flags: -Ccode-model=small + +//[kernel] check-pass +//[kernel] compile-flags: -Ccode-model=kernel + +//[medium] check-pass +//[medium] compile-flags: -Ccode-model=medium + +//[large] check-fail +//[large] compile-flags: -Ccode-model=large +//[large] error-pattern: `-Zfunction-return=thunk-extern` is only supported on non-large code models + +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/tests/ui/invalid-compile-flags/invalid-llvm-passes.stderr b/tests/ui/invalid-compile-flags/invalid-llvm-passes.stderr index ae1f85e41e410..bbacf3f46cfbe 100644 --- a/tests/ui/invalid-compile-flags/invalid-llvm-passes.stderr +++ b/tests/ui/invalid-compile-flags/invalid-llvm-passes.stderr @@ -1,4 +1,4 @@ error: failed to run LLVM passes: unknown pass name 'unknown-pass' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid-module-declaration/invalid-module-declaration.stderr b/tests/ui/invalid-module-declaration/invalid-module-declaration.stderr index 08aec25928c0d..a8f65883d6364 100644 --- a/tests/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/tests/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -7,6 +7,6 @@ LL | pub mod baz; = help: to create the module `baz`, create file "$DIR/auxiliary/foo/bar/baz.rs" or "$DIR/auxiliary/foo/bar/baz/mod.rs" = note: if there is a `mod baz` elsewhere in the crate already, import it with `use crate::...` instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/invalid-self-argument/bare-fn-start.stderr b/tests/ui/invalid-self-argument/bare-fn-start.stderr index 37753e61f582a..bf7160bcd2d35 100644 --- a/tests/ui/invalid-self-argument/bare-fn-start.stderr +++ b/tests/ui/invalid-self-argument/bare-fn-start.stderr @@ -6,5 +6,5 @@ LL | fn a(&self) { } | = note: associated functions are those in `impl` or `trait` definitions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid-self-argument/bare-fn.stderr b/tests/ui/invalid-self-argument/bare-fn.stderr index ff2217b5e80bc..7abb56602d4bc 100644 --- a/tests/ui/invalid-self-argument/bare-fn.stderr +++ b/tests/ui/invalid-self-argument/bare-fn.stderr @@ -4,5 +4,5 @@ error: unexpected `self` parameter in function LL | fn b(foo: u32, &mut self) { } | ^^^^^^^^^ must be the first parameter of an associated function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid-self-argument/trait-fn.stderr b/tests/ui/invalid-self-argument/trait-fn.stderr index b9887af962cbc..c9d0a338ef428 100644 --- a/tests/ui/invalid-self-argument/trait-fn.stderr +++ b/tests/ui/invalid-self-argument/trait-fn.stderr @@ -4,5 +4,5 @@ error: unexpected `self` parameter in function LL | fn c(foo: u32, self) {} | ^^^^ must be the first parameter of an associated function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid/invalid-crate-type-macro.stderr b/tests/ui/invalid/invalid-crate-type-macro.stderr index c196d4278a277..1cf77d4086bb0 100644 --- a/tests/ui/invalid/invalid-crate-type-macro.stderr +++ b/tests/ui/invalid/invalid-crate-type-macro.stderr @@ -4,5 +4,5 @@ error: malformed `crate_type` attribute input LL | #![crate_type = foo!()] | ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr index c8a4d68137923..1df3453253372 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr +++ b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr @@ -4,5 +4,5 @@ error: attribute should be applied to a module LL | #[debugger_visualizer(natvis_file = "./foo.natvis.xml")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid/invalid-macro-matcher.stderr b/tests/ui/invalid/invalid-macro-matcher.stderr index dbe025b7330b0..f85adc10cac0c 100644 --- a/tests/ui/invalid/invalid-macro-matcher.stderr +++ b/tests/ui/invalid/invalid-macro-matcher.stderr @@ -4,5 +4,5 @@ error: invalid macro matcher; matchers must be contained in balanced delimiters LL | _ => (); | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid/invalid-no-sanitize.stderr b/tests/ui/invalid/invalid-no-sanitize.stderr index 4600034952b39..b1c80438b318d 100644 --- a/tests/ui/invalid/invalid-no-sanitize.stderr +++ b/tests/ui/invalid/invalid-no-sanitize.stderr @@ -6,5 +6,5 @@ LL | #[no_sanitize(brontosaurus)] | = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/invalid/invalid-path-in-const.stderr b/tests/ui/invalid/invalid-path-in-const.stderr index a14ab7d85e851..31528ab856e61 100644 --- a/tests/ui/invalid/invalid-path-in-const.stderr +++ b/tests/ui/invalid/invalid-path-in-const.stderr @@ -4,6 +4,6 @@ error[E0599]: no associated item named `DOESNOTEXIST` found for type `u32` in th LL | fn f(a: [u8; u32::DOESNOTEXIST]) {} | ^^^^^^^^^^^^ associated item not found in `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/invalid_crate_type_syntax.stderr b/tests/ui/invalid_crate_type_syntax.stderr index 4072a2fa1624a..a5563720f6223 100644 --- a/tests/ui/invalid_crate_type_syntax.stderr +++ b/tests/ui/invalid_crate_type_syntax.stderr @@ -4,5 +4,5 @@ error: malformed `crate_type` attribute input LL | #![crate_type(lib)] | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr index f1d9ed8ac8b76..5775a4032c39d 100644 --- a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr +++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr @@ -2,5 +2,5 @@ warning: ignoring --out-dir flag due to -o flag error: io error modifying ./does-not-exist/ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/issues/issue-10291.stderr b/tests/ui/issues/issue-10291.stderr index a7b827d27a87b..68ed9a0de5d59 100644 --- a/tests/ui/issues/issue-10291.stderr +++ b/tests/ui/issues/issue-10291.stderr @@ -7,5 +7,5 @@ LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { LL | x | ^ returning this value requires that `'x` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-102964.stderr b/tests/ui/issues/issue-102964.stderr index c0766480a41f4..0e2761f3f57b1 100644 --- a/tests/ui/issues/issue-102964.stderr +++ b/tests/ui/issues/issue-102964.stderr @@ -14,6 +14,6 @@ LL ~ let rc = Rc::new(function); LL + rc | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-10465.stderr b/tests/ui/issues/issue-10465.stderr index 1b7b9d5909ebb..c6bc0786af1eb 100644 --- a/tests/ui/issues/issue-10465.stderr +++ b/tests/ui/issues/issue-10465.stderr @@ -10,6 +10,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use a::A; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-10545.stderr b/tests/ui/issues/issue-10545.stderr index f1da33eaba1c3..9aa0421717480 100644 --- a/tests/ui/issues/issue-10545.stderr +++ b/tests/ui/issues/issue-10545.stderr @@ -10,6 +10,6 @@ note: the struct `S` is defined here LL | struct S; | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-10656.stderr b/tests/ui/issues/issue-10656.stderr index 2e4365f1ed76b..61828f9c02a6c 100644 --- a/tests/ui/issues/issue-10656.stderr +++ b/tests/ui/issues/issue-10656.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(missing_docs)] | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-10764.stderr b/tests/ui/issues/issue-10764.stderr index 4d8a85a139715..f3bd0100a72a3 100644 --- a/tests/ui/issues/issue-10764.stderr +++ b/tests/ui/issues/issue-10764.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn f(_: extern "Rust" fn()) {} | ^ --------------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-11004.stderr b/tests/ui/issues/issue-11004.stderr index b5831e42e399f..ea141e61df8d3 100644 --- a/tests/ui/issues/issue-11004.stderr +++ b/tests/ui/issues/issue-11004.stderr @@ -3,7 +3,8 @@ error[E0609]: no field `x` on type `*mut A` | LL | let x : i32 = n.x; | --^ - | | + | | | + | | unknown field | help: `n` is a raw pointer; try dereferencing it: `(*n).x` error[E0609]: no field `y` on type `*mut A` @@ -11,7 +12,8 @@ error[E0609]: no field `y` on type `*mut A` | LL | let y : f64 = n.y; | --^ - | | + | | | + | | unknown field | help: `n` is a raw pointer; try dereferencing it: `(*n).y` error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-11192.stderr b/tests/ui/issues/issue-11192.stderr index fc15480134056..a8a18c49549d5 100644 --- a/tests/ui/issues/issue-11192.stderr +++ b/tests/ui/issues/issue-11192.stderr @@ -12,6 +12,6 @@ LL | test(&*ptr); | | | mutable borrow later used by call -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr index 879dc5b76c599..275a0e6b5d775 100644 --- a/tests/ui/issues/issue-11374.stderr +++ b/tests/ui/issues/issue-11374.stderr @@ -18,6 +18,6 @@ help: consider mutably borrowing here LL | c.read_to(&mut v); | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-11593.stderr b/tests/ui/issues/issue-11593.stderr index aa9768b1885a2..8262bc9321ac4 100644 --- a/tests/ui/issues/issue-11593.stderr +++ b/tests/ui/issues/issue-11593.stderr @@ -10,6 +10,6 @@ note: the trait `Foo` is defined here LL | trait Foo {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-11681.stderr b/tests/ui/issues/issue-11681.stderr index f2f9307667194..4f23ba86eecc4 100644 --- a/tests/ui/issues/issue-11681.stderr +++ b/tests/ui/issues/issue-11681.stderr @@ -6,6 +6,6 @@ LL | let testValue = &Test; LL | return testValue; | ^^^^^^^^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-11692-1.stderr b/tests/ui/issues/issue-11692-1.stderr index 386463436b8e6..46382f6521841 100644 --- a/tests/ui/issues/issue-11692-1.stderr +++ b/tests/ui/issues/issue-11692-1.stderr @@ -4,5 +4,5 @@ error: cannot find macro `testo` in this scope LL | print!(testo!()); | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-11692-2.stderr b/tests/ui/issues/issue-11692-2.stderr index 84746ca2c889c..53add509ca56d 100644 --- a/tests/ui/issues/issue-11692-2.stderr +++ b/tests/ui/issues/issue-11692-2.stderr @@ -6,5 +6,5 @@ LL | concat!(test!()); | = note: `test` is in scope, but it is an attribute: `#[test]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-11844.stderr b/tests/ui/issues/issue-11844.stderr index 9afd209773b73..9ff66eaef498e 100644 --- a/tests/ui/issues/issue-11844.stderr +++ b/tests/ui/issues/issue-11844.stderr @@ -9,6 +9,6 @@ LL | Ok(a) => = note: expected enum `Option>` found enum `Result<_, _>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-12028.stderr b/tests/ui/issues/issue-12028.stderr index 8d6b81c24b682..3d7fb13d44757 100644 --- a/tests/ui/issues/issue-12028.stderr +++ b/tests/ui/issues/issue-12028.stderr @@ -10,6 +10,6 @@ help: try using a fully qualified path to specify the expected types LL | >::input_stream(self, &mut stream); | ++++++++++++++++++++++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/issues/issue-12041.stderr b/tests/ui/issues/issue-12041.stderr index b9ffa499afe03..51061c0262eb1 100644 --- a/tests/ui/issues/issue-12041.stderr +++ b/tests/ui/issues/issue-12041.stderr @@ -6,6 +6,6 @@ LL | let tx = tx; | = note: move occurs because `tx` has type `Sender`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-12127.stderr b/tests/ui/issues/issue-12127.stderr index 2e585867941d8..2a6233547ee8c 100644 --- a/tests/ui/issues/issue-12127.stderr +++ b/tests/ui/issues/issue-12127.stderr @@ -13,6 +13,6 @@ LL | f(); | ^ = note: move occurs because `f` has type `{closure@$DIR/issue-12127.rs:8:24: 8:30}`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-12187-1.stderr b/tests/ui/issues/issue-12187-1.stderr index d2a6a96082e53..93dc1df8f6342 100644 --- a/tests/ui/issues/issue-12187-1.stderr +++ b/tests/ui/issues/issue-12187-1.stderr @@ -9,6 +9,6 @@ help: consider giving this pattern a type, where the type for type parameter `T` LL | let &v: &T = new(); | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-12187-2.stderr b/tests/ui/issues/issue-12187-2.stderr index ac75ebb4256d5..e9ba52ff4fde2 100644 --- a/tests/ui/issues/issue-12187-2.stderr +++ b/tests/ui/issues/issue-12187-2.stderr @@ -9,6 +9,6 @@ help: consider giving this pattern a type, where the type for type parameter `T` LL | let &v: &T = new(); | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-12863.stderr b/tests/ui/issues/issue-12863.stderr index 9c29a37cb930b..95d4a704e72db 100644 --- a/tests/ui/issues/issue-12863.stderr +++ b/tests/ui/issues/issue-12863.stderr @@ -4,6 +4,6 @@ error[E0532]: expected unit struct, unit variant or constant, found function `fo LL | foo::bar => {} | ^^^^^^^^ not a unit struct, unit variant or constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-13058.stderr b/tests/ui/issues/issue-13058.stderr index 8368978deab1a..7cc2860eb5086 100644 --- a/tests/ui/issues/issue-13058.stderr +++ b/tests/ui/issues/issue-13058.stderr @@ -7,6 +7,6 @@ LL | { LL | let cont_iter = cont.iter(); | ^^^^^^^^^^^ lifetime `'r` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-13446.stderr b/tests/ui/issues/issue-13446.stderr index 139c34c8880a6..28c459e6e62ce 100644 --- a/tests/ui/issues/issue-13446.stderr +++ b/tests/ui/issues/issue-13446.stderr @@ -8,6 +8,6 @@ LL | static VEC: [u32; 256] = vec![]; found struct `Vec<_>` = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13482-2.stderr b/tests/ui/issues/issue-13482-2.stderr index ccab95878b524..87a6782a5e6c9 100644 --- a/tests/ui/issues/issue-13482-2.stderr +++ b/tests/ui/issues/issue-13482-2.stderr @@ -4,6 +4,6 @@ error[E0527]: pattern requires 0 elements but array has 2 LL | [] => None, | ^^ expected 2 elements -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/issues/issue-13482.stderr b/tests/ui/issues/issue-13482.stderr index 3eb05f504c23e..6226c580811c3 100644 --- a/tests/ui/issues/issue-13482.stderr +++ b/tests/ui/issues/issue-13482.stderr @@ -4,6 +4,6 @@ error[E0527]: pattern requires 0 elements but array has 2 LL | [] => None, | ^^ expected 2 elements -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/issues/issue-13497-2.stderr b/tests/ui/issues/issue-13497-2.stderr index 8ad921027e2e3..e2ba1150d07bd 100644 --- a/tests/ui/issues/issue-13497-2.stderr +++ b/tests/ui/issues/issue-13497-2.stderr @@ -9,6 +9,6 @@ LL | rawLines LL | | .iter().map(|l| l.trim()).collect() | |___________________________________________^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-13497.stderr b/tests/ui/issues/issue-13497.stderr index 4b1d979da36e3..236e6b48607f9 100644 --- a/tests/ui/issues/issue-13497.stderr +++ b/tests/ui/issues/issue-13497.stderr @@ -10,6 +10,6 @@ help: consider using the `'static` lifetime LL | &'static str | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/issues/issue-1362.stderr b/tests/ui/issues/issue-1362.stderr index babbb6e519bc0..6f6fdff66788c 100644 --- a/tests/ui/issues/issue-1362.stderr +++ b/tests/ui/issues/issue-1362.stderr @@ -11,6 +11,6 @@ help: change the type of the numeric literal from `i32` to `u32` LL | let x: u32 = 20u32; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13847.stderr b/tests/ui/issues/issue-13847.stderr index 52b8dc049702a..1c1855ce94ded 100644 --- a/tests/ui/issues/issue-13847.stderr +++ b/tests/ui/issues/issue-13847.stderr @@ -2,8 +2,8 @@ error[E0609]: no field `is_failure` on type `!` --> $DIR/issue-13847.rs:2:12 | LL | return.is_failure - | ^^^^^^^^^^ + | ^^^^^^^^^^ unknown field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-14091-2.stderr b/tests/ui/issues/issue-14091-2.stderr index f8375d4ef9014..ac8947670592a 100644 --- a/tests/ui/issues/issue-14091-2.stderr +++ b/tests/ui/issues/issue-14091-2.stderr @@ -13,6 +13,6 @@ note: the trait `Not` must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/issues/issue-14091.stderr b/tests/ui/issues/issue-14091.stderr index 0a9640a9e3178..83879583b1f29 100644 --- a/tests/ui/issues/issue-14091.stderr +++ b/tests/ui/issues/issue-14091.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | assert!(1,1); | ^^^^^^^^^^^^ expected `bool`, found integer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-14092.stderr b/tests/ui/issues/issue-14092.stderr index 3a43627e69105..0de7b902fe05c 100644 --- a/tests/ui/issues/issue-14092.stderr +++ b/tests/ui/issues/issue-14092.stderr @@ -9,6 +9,6 @@ help: add missing generic argument LL | fn fn1(0: Box) {} | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-14285.stderr b/tests/ui/issues/issue-14285.stderr index 5c07066018e83..4f89ae51157b8 100644 --- a/tests/ui/issues/issue-14285.stderr +++ b/tests/ui/issues/issue-14285.stderr @@ -6,6 +6,6 @@ LL | fn foo<'a>(a: &dyn Foo) -> B<'a> { LL | B(a) | ^^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-14366.stderr b/tests/ui/issues/issue-14366.stderr index df61aabf00a74..e7bf555c1b708 100644 --- a/tests/ui/issues/issue-14366.stderr +++ b/tests/ui/issues/issue-14366.stderr @@ -11,6 +11,6 @@ help: consider borrowing the value, since `&&'static str` can be coerced into `& LL | let _x = &"test" as &dyn (::std::any::Any); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-1448-2.stderr b/tests/ui/issues/issue-1448-2.stderr index 203dd92c9fb02..a6f1daefe636b 100644 --- a/tests/ui/issues/issue-1448-2.stderr +++ b/tests/ui/issues/issue-1448-2.stderr @@ -16,6 +16,6 @@ help: change the type of the numeric literal from `i32` to `u32` LL | println!("{}", foo(10u32)); | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-14541.stderr b/tests/ui/issues/issue-14541.stderr index b80c68ce47311..370e64779012f 100644 --- a/tests/ui/issues/issue-14541.stderr +++ b/tests/ui/issues/issue-14541.stderr @@ -6,6 +6,6 @@ LL | let Vec3 { y: _, z: _ } = v; | | | expected `Vec2`, found `Vec3` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-14721.stderr b/tests/ui/issues/issue-14721.stderr index 49ebb2976e8ad..c71b0363eef64 100644 --- a/tests/ui/issues/issue-14721.stderr +++ b/tests/ui/issues/issue-14721.stderr @@ -2,8 +2,8 @@ error[E0609]: no field `desc` on type `&str` --> $DIR/issue-14721.rs:3:24 | LL | println!("{}", foo.desc); - | ^^^^ + | ^^^^ unknown field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-1476.stderr b/tests/ui/issues/issue-1476.stderr index 670bd546335f4..e30dbfd205b87 100644 --- a/tests/ui/issues/issue-1476.stderr +++ b/tests/ui/issues/issue-1476.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `x` in this scope LL | println!("{}", x); | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-14853.stderr b/tests/ui/issues/issue-14853.stderr index 2adcf55eca97f..25dd1e3374dba 100644 --- a/tests/ui/issues/issue-14853.stderr +++ b/tests/ui/issues/issue-14853.stderr @@ -7,6 +7,6 @@ LL | fn yay(_: Option, thing: &[T]); LL | fn yay(_:Option, thing: &[T]) { | ^^^ impl has extra requirement `T: Str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/issues/issue-14915.stderr b/tests/ui/issues/issue-14915.stderr index 6e63269293b75..279f5772d21d3 100644 --- a/tests/ui/issues/issue-14915.stderr +++ b/tests/ui/issues/issue-14915.stderr @@ -6,6 +6,6 @@ LL | println!("{}", x + 1); | | | Box -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-15034.stderr b/tests/ui/issues/issue-15034.stderr index f142e260a2313..587a5c85e924a 100644 --- a/tests/ui/issues/issue-15034.stderr +++ b/tests/ui/issues/issue-15034.stderr @@ -6,6 +6,6 @@ LL | pub fn new(lexer: &'a mut Lexer) -> Parser<'a> { LL | Parser { lexer: lexer } | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-15094.stderr b/tests/ui/issues/issue-15094.stderr index b7c950892dc29..8e0fc8f177099 100644 --- a/tests/ui/issues/issue-15094.stderr +++ b/tests/ui/issues/issue-15094.stderr @@ -7,6 +7,6 @@ LL | fn call_once(self, _args: ()) { = note: expected signature `extern "rust-call" fn(Debuger<_>, ())` found signature `fn(Debuger<_>, ())` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-15207.stderr b/tests/ui/issues/issue-15207.stderr index 25ce7cb5cc069..a1047e27ba22a 100644 --- a/tests/ui/issues/issue-15207.stderr +++ b/tests/ui/issues/issue-15207.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `push` found for type `!` in the current scope LL | break.push(1) | ^^^^ method not found in `!` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-15381.stderr b/tests/ui/issues/issue-15381.stderr index 085958411ccb9..03a0100f1bdc9 100644 --- a/tests/ui/issues/issue-15381.stderr +++ b/tests/ui/issues/issue-15381.stderr @@ -6,6 +6,6 @@ LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { | = note: the matched value is of type `&[u8]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/issues/issue-15756.stderr b/tests/ui/issues/issue-15756.stderr index d9bdc69ad7179..af50fe467d17c 100644 --- a/tests/ui/issues/issue-15756.stderr +++ b/tests/ui/issues/issue-15756.stderr @@ -8,6 +8,6 @@ LL | &mut something = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-15783.stderr b/tests/ui/issues/issue-15783.stderr index 598ec7e6053be..7ed2e19913031 100644 --- a/tests/ui/issues/issue-15783.stderr +++ b/tests/ui/issues/issue-15783.stderr @@ -14,6 +14,6 @@ note: function defined here LL | pub fn foo(params: Option<&[&str]>) -> usize { | ^^^ ----------------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-15896.stderr b/tests/ui/issues/issue-15896.stderr index ec0d74596aa8d..381f6dc22760e 100644 --- a/tests/ui/issues/issue-15896.stderr +++ b/tests/ui/issues/issue-15896.stderr @@ -7,6 +7,6 @@ LL | E::B( LL | Tau{t: x}, | ^^^^^^^^^ expected `R`, found `Tau` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-15965.stderr b/tests/ui/issues/issue-15965.stderr index fe06810b8dff4..14727e74334c7 100644 --- a/tests/ui/issues/issue-15965.stderr +++ b/tests/ui/issues/issue-15965.stderr @@ -6,6 +6,6 @@ LL | | LL | | () | |______^ cannot infer type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-16149.stderr b/tests/ui/issues/issue-16149.stderr index bb809840b2aac..9ffd0e7e64536 100644 --- a/tests/ui/issues/issue-16149.stderr +++ b/tests/ui/issues/issue-16149.stderr @@ -7,6 +7,6 @@ LL | static externalValue: isize; LL | externalValue => true, | ^^^^^^^^^^^^^ cannot be named the same as a static -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/issues/issue-16250.stderr b/tests/ui/issues/issue-16250.stderr index 5eb5e0864ad19..9d3e88114616b 100644 --- a/tests/ui/issues/issue-16250.stderr +++ b/tests/ui/issues/issue-16250.stderr @@ -18,5 +18,5 @@ LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(improper_ctypes)]` implied by `#[deny(warnings)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-16338.stderr b/tests/ui/issues/issue-16338.stderr index 0f08485e515dd..e24b9bfa3c041 100644 --- a/tests/ui/issues/issue-16338.stderr +++ b/tests/ui/issues/issue-16338.stderr @@ -9,6 +9,6 @@ LL | let Slice { data: data, len: len } = "foo"; = note: expected type `str` found struct `Slice<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-16401.stderr b/tests/ui/issues/issue-16401.stderr index 02f9f3ea8fdf7..6af920ca43970 100644 --- a/tests/ui/issues/issue-16401.stderr +++ b/tests/ui/issues/issue-16401.stderr @@ -9,6 +9,6 @@ LL | Slice { data: data, len: len } => (), = note: expected unit type `()` found struct `Slice<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-16562.stderr b/tests/ui/issues/issue-16562.stderr index 3fe7507e8a412..efbd7f712a45a 100644 --- a/tests/ui/issues/issue-16562.stderr +++ b/tests/ui/issues/issue-16562.stderr @@ -4,6 +4,6 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl Collection for Col { | ^ unconstrained type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-16683.stderr b/tests/ui/issues/issue-16683.stderr index fff681b2e0b76..39b22ed1f1568 100644 --- a/tests/ui/issues/issue-16683.stderr +++ b/tests/ui/issues/issue-16683.stderr @@ -9,5 +9,5 @@ LL | fn b(&self) { LL | self.a(); | ^^^^^^^^ argument requires that `'1` must outlive `'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-16725.stderr b/tests/ui/issues/issue-16725.stderr index 5f6eae73e5850..a4a406b3d4ba9 100644 --- a/tests/ui/issues/issue-16725.stderr +++ b/tests/ui/issues/issue-16725.stderr @@ -10,6 +10,6 @@ note: the function `bar` is defined here LL | fn bar(); | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-16939.stderr b/tests/ui/issues/issue-16939.stderr index 6db29bc61b12a..229ff9f181773 100644 --- a/tests/ui/issues/issue-16939.stderr +++ b/tests/ui/issues/issue-16939.stderr @@ -13,6 +13,6 @@ note: callable defined here LL | fn _foo (f: F) { | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/issues/issue-16966.stderr b/tests/ui/issues/issue-16966.stderr index c53707c5d696a..0ed12d3a2e974 100644 --- a/tests/ui/issues/issue-16966.stderr +++ b/tests/ui/issues/issue-16966.stderr @@ -11,6 +11,6 @@ LL | panic!(std::default::Default::default()); note: required by a bound in `begin_panic` --> $SRC_DIR/std/src/panicking.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-17001.stderr b/tests/ui/issues/issue-17001.stderr index d7e6069977b4e..6ea32e0a45c39 100644 --- a/tests/ui/issues/issue-17001.stderr +++ b/tests/ui/issues/issue-17001.stderr @@ -4,6 +4,6 @@ error[E0574]: expected struct, variant or union type, found module `foo` LL | let p = foo { x: () }; | ^^^ not a struct, variant or union type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-17033.stderr b/tests/ui/issues/issue-17033.stderr index 3419c0798595e..0b42274223a0d 100644 --- a/tests/ui/issues/issue-17033.stderr +++ b/tests/ui/issues/issue-17033.stderr @@ -11,6 +11,6 @@ help: consider mutably borrowing here LL | (*p)(&mut ()) | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-17252.stderr b/tests/ui/issues/issue-17252.stderr index 32e20d77465a1..d898486045759 100644 --- a/tests/ui/issues/issue-17252.stderr +++ b/tests/ui/issues/issue-17252.stderr @@ -17,6 +17,6 @@ LL | let _x: [u8; FOO]; // caused stack overflow prior to fix | ^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-17337.stderr b/tests/ui/issues/issue-17337.stderr index 55e51e566d981..8fbf6882699de 100644 --- a/tests/ui/issues/issue-17337.stderr +++ b/tests/ui/issues/issue-17337.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(deprecated)] | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-17373.stderr b/tests/ui/issues/issue-17373.stderr index 5c429d1113df4..9438f5c6345df 100644 --- a/tests/ui/issues/issue-17373.stderr +++ b/tests/ui/issues/issue-17373.stderr @@ -4,6 +4,6 @@ error[E0614]: type `!` cannot be dereferenced LL | *return | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/issues/issue-17405.stderr b/tests/ui/issues/issue-17405.stderr index 37274e239ba0b..47f5bf4dc330a 100644 --- a/tests/ui/issues/issue-17405.stderr +++ b/tests/ui/issues/issue-17405.stderr @@ -4,6 +4,6 @@ error[E0574]: expected struct, variant or union type, found enum `Foo` LL | Foo { i } => () | ^^^ not a struct, variant or union type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-17551.stderr b/tests/ui/issues/issue-17551.stderr index 3a8f569a3a5c2..68f54a310844b 100644 --- a/tests/ui/issues/issue-17551.stderr +++ b/tests/ui/issues/issue-17551.stderr @@ -9,6 +9,6 @@ help: consider giving `foo` an explicit type, where the type for type parameter LL | let foo: B = B(marker::PhantomData); | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-17651.stderr b/tests/ui/issues/issue-17651.stderr index b37811e19559c..0c95a3c0c40d8 100644 --- a/tests/ui/issues/issue-17651.stderr +++ b/tests/ui/issues/issue-17651.stderr @@ -10,6 +10,6 @@ LL | (|| Box::new(*(&[0][..])))(); note: required by a bound in `Box::::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-17758.stderr b/tests/ui/issues/issue-17758.stderr index 613ef6b907c54..7a7d2374ef879 100644 --- a/tests/ui/issues/issue-17758.stderr +++ b/tests/ui/issues/issue-17758.stderr @@ -9,5 +9,5 @@ LL | fn bar(&self) { LL | self.foo(); | ^^^^^^^^^^ argument requires that `'1` must outlive `'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-17800.stderr b/tests/ui/issues/issue-17800.stderr index baab675834fca..2a15af50d02a0 100644 --- a/tests/ui/issues/issue-17800.stderr +++ b/tests/ui/issues/issue-17800.stderr @@ -9,6 +9,6 @@ help: use the tuple variant pattern syntax instead LL | MyOption::MySome(42) => (), | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0769`. diff --git a/tests/ui/issues/issue-17904-2.stderr b/tests/ui/issues/issue-17904-2.stderr index 62b7b79538c61..102c8537f8e04 100644 --- a/tests/ui/issues/issue-17904-2.stderr +++ b/tests/ui/issues/issue-17904-2.stderr @@ -6,6 +6,6 @@ LL | struct Foo where T: Copy; | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/issues/issue-17933.stderr b/tests/ui/issues/issue-17933.stderr index 33534d3f8f6a9..42a7e04420735 100644 --- a/tests/ui/issues/issue-17933.stderr +++ b/tests/ui/issues/issue-17933.stderr @@ -4,6 +4,6 @@ error[E0532]: expected unit struct, unit variant or constant, found static `self LL | self::X => { }, | ^^^^^^^ not a unit struct, unit variant or constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-17954.stderr b/tests/ui/issues/issue-17954.stderr index 3e3706bcb7de9..bba7e725b1243 100644 --- a/tests/ui/issues/issue-17954.stderr +++ b/tests/ui/issues/issue-17954.stderr @@ -7,6 +7,6 @@ LL | let a = &FOO; LL | } | - end of enclosing function is here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0712`. diff --git a/tests/ui/issues/issue-17959.stderr b/tests/ui/issues/issue-17959.stderr index fb795febf7954..604413c4b6d19 100644 --- a/tests/ui/issues/issue-17959.stderr +++ b/tests/ui/issues/issue-17959.stderr @@ -10,6 +10,6 @@ note: the implementor must specify the same requirement LL | struct G { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/issues/issue-17994.stderr b/tests/ui/issues/issue-17994.stderr index 61e1e496f7958..ba3def64dfb5d 100644 --- a/tests/ui/issues/issue-17994.stderr +++ b/tests/ui/issues/issue-17994.stderr @@ -4,6 +4,6 @@ error[E0091]: type parameter `T` is unused LL | type Huh where T: Tr = isize; | ^ unused type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0091`. diff --git a/tests/ui/issues/issue-18058.stderr b/tests/ui/issues/issue-18058.stderr index 18159ffc23840..c880bb0029192 100644 --- a/tests/ui/issues/issue-18058.stderr +++ b/tests/ui/issues/issue-18058.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Undefined` in this scope LL | impl Undefined {} | ^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-18107.stderr b/tests/ui/issues/issue-18107.stderr index cf4e06316a710..702207c30f7cd 100644 --- a/tests/ui/issues/issue-18107.stderr +++ b/tests/ui/issues/issue-18107.stderr @@ -17,6 +17,6 @@ LL | match 0 { LL ~ _ => Box::new(unimplemented!()) | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/issues/issue-18159.stderr b/tests/ui/issues/issue-18159.stderr index 5e0589eed435d..5de13a5c314c5 100644 --- a/tests/ui/issues/issue-18159.stderr +++ b/tests/ui/issues/issue-18159.stderr @@ -9,6 +9,6 @@ help: consider giving `x` an explicit type LL | let x: /* Type */; | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-18183.stderr b/tests/ui/issues/issue-18183.stderr index a7dc64708d856..11015d75d9735 100644 --- a/tests/ui/issues/issue-18183.stderr +++ b/tests/ui/issues/issue-18183.stderr @@ -4,6 +4,6 @@ error[E0128]: generic parameters with a default cannot use forward declared iden LL | pub struct Foo(Bar); | ^^^ defaulted generic parameters cannot be forward declared -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/issues/issue-18423.stderr b/tests/ui/issues/issue-18423.stderr index 5d154dbbbdd6e..2c6015eaa9d4b 100644 --- a/tests/ui/issues/issue-18423.stderr +++ b/tests/ui/issues/issue-18423.stderr @@ -6,6 +6,6 @@ LL | x: Box<'a, isize> | | | expected 0 lifetime arguments -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-18446.stderr b/tests/ui/issues/issue-18446.stderr index 602b80c6824f7..d84c490df4dcc 100644 --- a/tests/ui/issues/issue-18446.stderr +++ b/tests/ui/issues/issue-18446.stderr @@ -19,6 +19,6 @@ help: disambiguate the method for candidate #2 LL | T::foo(&x); | ~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/issues/issue-18532.stderr b/tests/ui/issues/issue-18532.stderr index 4c224eb2d2430..059c7f137819e 100644 --- a/tests/ui/issues/issue-18532.stderr +++ b/tests/ui/issues/issue-18532.stderr @@ -6,6 +6,6 @@ LL | (return)((),()); | | | call expression requires function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-18566.stderr b/tests/ui/issues/issue-18566.stderr index 8db78935f839c..e8ec48b0d2696 100644 --- a/tests/ui/issues/issue-18566.stderr +++ b/tests/ui/issues/issue-18566.stderr @@ -7,6 +7,6 @@ LL | MyPtr(s).poke(s); | | first borrow later used by call | first mutable borrow occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/issues/issue-18611.stderr b/tests/ui/issues/issue-18611.stderr index 784b9b984e900..ab2374586e4e5 100644 --- a/tests/ui/issues/issue-18611.stderr +++ b/tests/ui/issues/issue-18611.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait HasState { | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-18804/main.rs b/tests/ui/issues/issue-18804/main.rs index c36048ea54503..47c3f13d23cad 100644 --- a/tests/ui/issues/issue-18804/main.rs +++ b/tests/ui/issues/issue-18804/main.rs @@ -2,7 +2,6 @@ // Test for issue #18804, #[linkage] does not propagate through generic // functions. Failure results in a linker error. -// ignore-asmjs no weak symbol support // ignore-emscripten no weak symbol support // ignore-windows no extern_weak linkage // ignore-macos no extern_weak linkage diff --git a/tests/ui/issues/issue-18819.stderr b/tests/ui/issues/issue-18819.stderr index 40098f9622fa9..b2cf0bad1df62 100644 --- a/tests/ui/issues/issue-18819.stderr +++ b/tests/ui/issues/issue-18819.stderr @@ -25,6 +25,6 @@ help: provide the argument LL | print_x(/* &dyn Foo */, /* &str */); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/issues/issue-18919.stderr b/tests/ui/issues/issue-18919.stderr index b0b03a0eea69e..6dcd891cedac9 100644 --- a/tests/ui/issues/issue-18919.stderr +++ b/tests/ui/issues/issue-18919.stderr @@ -18,6 +18,6 @@ LL | enum Option { LL | Some(T), | - ...if indirection were used here: `Box` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr index b9e27873636c3..76082dadd374e 100644 --- a/tests/ui/issues/issue-18959.stderr +++ b/tests/ui/issues/issue-18959.stderr @@ -13,6 +13,6 @@ LL | pub trait Bar: Foo { } | --- this trait cannot be made into an object... = help: consider moving `foo` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-1900.stderr b/tests/ui/issues/issue-1900.stderr index ce413662f0dac..31fd46c8e2a53 100644 --- a/tests/ui/issues/issue-1900.stderr +++ b/tests/ui/issues/issue-1900.stderr @@ -4,6 +4,6 @@ error[E0131]: `main` function is not allowed to have generic parameters LL | fn main() { } | ^^^ `main` cannot have generic parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0131`. diff --git a/tests/ui/issues/issue-19086.stderr b/tests/ui/issues/issue-19086.stderr index 90d0bb4065543..03b9249bb1e3d 100644 --- a/tests/ui/issues/issue-19086.stderr +++ b/tests/ui/issues/issue-19086.stderr @@ -7,6 +7,6 @@ LL | FooB { x: i32, y: i32 } LL | FooB(a, b) => println!("{} {}", a, b), | ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x: a, y: b }` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-1920-1.stderr b/tests/ui/issues/issue-1920-1.stderr index a546924253c2a..b7c7da0067239 100644 --- a/tests/ui/issues/issue-1920-1.stderr +++ b/tests/ui/issues/issue-1920-1.stderr @@ -10,6 +10,6 @@ note: required by a bound in `assert_clone` LL | fn assert_clone() where T : Clone { } | ^^^^^ required by this bound in `assert_clone` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-1920-2.stderr b/tests/ui/issues/issue-1920-2.stderr index 1083b011252e9..844cb0ff1999c 100644 --- a/tests/ui/issues/issue-1920-2.stderr +++ b/tests/ui/issues/issue-1920-2.stderr @@ -10,6 +10,6 @@ note: required by a bound in `assert_clone` LL | fn assert_clone() where T : Clone { } | ^^^^^ required by this bound in `assert_clone` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-1920-3.stderr b/tests/ui/issues/issue-1920-3.stderr index 3f0787c887570..525ca4685bb77 100644 --- a/tests/ui/issues/issue-1920-3.stderr +++ b/tests/ui/issues/issue-1920-3.stderr @@ -10,6 +10,6 @@ note: required by a bound in `assert_clone` LL | fn assert_clone() where T : Clone { } | ^^^^^ required by this bound in `assert_clone` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-19244-1.stderr b/tests/ui/issues/issue-19244-1.stderr index 1eb530542c02b..9c1336402e649 100644 --- a/tests/ui/issues/issue-19244-1.stderr +++ b/tests/ui/issues/issue-19244-1.stderr @@ -2,8 +2,8 @@ error[E0609]: no field `1` on type `(usize,)` --> $DIR/issue-19244-1.rs:4:24 | LL | let a: [isize; TUP.1]; - | ^ + | ^ unknown field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-19244-2.stderr b/tests/ui/issues/issue-19244-2.stderr index 54529fdf5ba72..533861b1114e5 100644 --- a/tests/ui/issues/issue-19244-2.stderr +++ b/tests/ui/issues/issue-19244-2.stderr @@ -4,8 +4,8 @@ error[E0609]: no field `nonexistent_field` on type `MyStruct` LL | let a: [isize; STRUCT.nonexistent_field]; | ^^^^^^^^^^^^^^^^^ unknown field | - = note: available fields are: `field` + = note: available field is: `field` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-19482.stderr b/tests/ui/issues/issue-19482.stderr index 90e6f79956054..903a9f98c7588 100644 --- a/tests/ui/issues/issue-19482.stderr +++ b/tests/ui/issues/issue-19482.stderr @@ -7,6 +7,6 @@ LL | type A; LL | fn bar(x: &dyn Foo) {} | ^^^ help: specify the associated type: `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-19521.stderr b/tests/ui/issues/issue-19521.stderr index 13a12acb3605b..f451dc36d45fe 100644 --- a/tests/ui/issues/issue-19521.stderr +++ b/tests/ui/issues/issue-19521.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `homura` found for reference `&'static str` in the LL | "".homura()(); | ^^^^^^ method not found in `&str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-1962.stderr b/tests/ui/issues/issue-1962.stderr index 4c32a4cf3dd59..db235d473038a 100644 --- a/tests/ui/issues/issue-1962.stderr +++ b/tests/ui/issues/issue-1962.stderr @@ -6,5 +6,5 @@ LL | 'a: while true { | = note: requested on the command line with `-D while-true` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-19692.stderr b/tests/ui/issues/issue-19692.stderr index 9e888ed758a11..1e3d7a2e2f517 100644 --- a/tests/ui/issues/issue-19692.stderr +++ b/tests/ui/issues/issue-19692.stderr @@ -7,6 +7,6 @@ LL | struct Homura; LL | let Some(ref madoka) = Some(homura.kaname()); | ^^^^^^ method not found in `Homura` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-19734.stderr b/tests/ui/issues/issue-19734.stderr index 81757974de9dd..ed48714fe5078 100644 --- a/tests/ui/issues/issue-19734.stderr +++ b/tests/ui/issues/issue-19734.stderr @@ -4,5 +4,5 @@ error: cannot find macro `undef` in this scope LL | undef!(); | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-19922.stderr b/tests/ui/issues/issue-19922.stderr index 826b2ac049b0e..0355d3a89710b 100644 --- a/tests/ui/issues/issue-19922.stderr +++ b/tests/ui/issues/issue-19922.stderr @@ -6,6 +6,6 @@ LL | let homura = Homura::Akemi { kaname: () }; | = note: available fields are: `madoka` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0559`. diff --git a/tests/ui/issues/issue-19991.stderr b/tests/ui/issues/issue-19991.stderr index 57b0882b636e3..ff039f3adba90 100644 --- a/tests/ui/issues/issue-19991.stderr +++ b/tests/ui/issues/issue-19991.stderr @@ -11,6 +11,6 @@ LL | | }; = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/issues/issue-20162.stderr b/tests/ui/issues/issue-20162.stderr index ebdf2528fe1f2..8f45f0d36c71e 100644 --- a/tests/ui/issues/issue-20162.stderr +++ b/tests/ui/issues/issue-20162.stderr @@ -12,6 +12,6 @@ LL + #[derive(Ord)] LL | struct X { x: i32 } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-20261.stderr b/tests/ui/issues/issue-20261.stderr index 9ac751e4dc437..6738708ca225d 100644 --- a/tests/ui/issues/issue-20261.stderr +++ b/tests/ui/issues/issue-20261.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | i.clone(); | ^^^^^ cannot infer type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-20313.stderr b/tests/ui/issues/issue-20313.stderr index 7a0b344a5aa22..f740b0cca06c0 100644 --- a/tests/ui/issues/issue-20313.stderr +++ b/tests/ui/issues/issue-20313.stderr @@ -7,6 +7,6 @@ LL | fn sqrt(x: f32) -> f32; = note: see issue #29602 for more information = help: add `#![feature(link_llvm_intrinsics)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-20433.stderr b/tests/ui/issues/issue-20433.stderr index 3ae952546a62d..2dd0b3c2f8439 100644 --- a/tests/ui/issues/issue-20433.stderr +++ b/tests/ui/issues/issue-20433.stderr @@ -8,6 +8,6 @@ LL | fn iceman(c: Vec<[i32]>) {} note: required by a bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-20714.stderr b/tests/ui/issues/issue-20714.stderr index a3447aa6845b9..f537a01582b6b 100644 --- a/tests/ui/issues/issue-20714.stderr +++ b/tests/ui/issues/issue-20714.stderr @@ -15,6 +15,6 @@ LL - let g = G(); LL + let g = G; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-20772.stderr b/tests/ui/issues/issue-20772.stderr index 0c7e728c67e8d..81f80aef59446 100644 --- a/tests/ui/issues/issue-20772.stderr +++ b/tests/ui/issues/issue-20772.stderr @@ -12,6 +12,6 @@ LL | trait T : Iterator | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr index c3af1f6786b34..bd3ff5d59c622 100644 --- a/tests/ui/issues/issue-20831-debruijn.stderr +++ b/tests/ui/issues/issue-20831-debruijn.stderr @@ -22,6 +22,6 @@ LL | fn subscribe(&mut self, t : Box as Publisher<'_>>` found ` as Publisher<'_>>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/issues/issue-20939.stderr b/tests/ui/issues/issue-20939.stderr index 3819a21a2cfff..00357155c8a90 100644 --- a/tests/ui/issues/issue-20939.stderr +++ b/tests/ui/issues/issue-20939.stderr @@ -4,6 +4,6 @@ error[E0371]: the object type `(dyn Foo + 'a)` automatically implements the trai LL | impl<'a> Foo for dyn Foo + 'a {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Foo + 'a)` automatically implements trait `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0371`. diff --git a/tests/ui/issues/issue-21160.stderr b/tests/ui/issues/issue-21160.stderr index b39a3aad37198..892a4530ebcbb 100644 --- a/tests/ui/issues/issue-21160.stderr +++ b/tests/ui/issues/issue-21160.stderr @@ -13,6 +13,6 @@ LL + #[derive(Hash)] LL | struct Bar; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-21174.stderr b/tests/ui/issues/issue-21174.stderr index 5981d9dc73303..a6b75c913524d 100644 --- a/tests/ui/issues/issue-21174.stderr +++ b/tests/ui/issues/issue-21174.stderr @@ -7,6 +7,6 @@ LL | let new: T::B = unsafe { std::mem::transmute(value) }; = note: source type: `>::A` (this type does not have a fixed size) = note: target type: `>::B` (this type does not have a fixed size) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/issues/issue-21177.stderr b/tests/ui/issues/issue-21177.stderr index 8b749edcc77f0..9f66f43a195a1 100644 --- a/tests/ui/issues/issue-21177.stderr +++ b/tests/ui/issues/issue-21177.stderr @@ -12,6 +12,6 @@ LL | fn foo>() { } | ^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-21202.stderr b/tests/ui/issues/issue-21202.stderr index e7c3f2f9a071c..3485994e8f42d 100644 --- a/tests/ui/issues/issue-21202.stderr +++ b/tests/ui/issues/issue-21202.stderr @@ -9,6 +9,6 @@ LL | Foo::foo(&f); LL | fn foo(&self) { } | ------------- private method defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/issues/issue-21332.stderr b/tests/ui/issues/issue-21332.stderr index 82549288064a1..96e0f5fdb31db 100644 --- a/tests/ui/issues/issue-21332.stderr +++ b/tests/ui/issues/issue-21332.stderr @@ -10,6 +10,6 @@ LL | fn next(&mut self) -> Result { Ok(7) } = note: expected signature `fn(&mut S) -> Option` found signature `fn(&mut S) -> Result` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-21449.stderr b/tests/ui/issues/issue-21449.stderr index ecaf6faba429e..cd1059d48993a 100644 --- a/tests/ui/issues/issue-21449.stderr +++ b/tests/ui/issues/issue-21449.stderr @@ -4,6 +4,6 @@ error[E0574]: expected struct, variant or union type, found module `MyMod` LL | let myVar = MyMod { T: 0 }; | ^^^^^ not a struct, variant or union type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-2150.stderr b/tests/ui/issues/issue-2150.stderr index 26874faa2b938..a9268646edfcb 100644 --- a/tests/ui/issues/issue-2150.stderr +++ b/tests/ui/issues/issue-2150.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-2151.stderr b/tests/ui/issues/issue-2151.stderr index c75038b6169c0..b130f162414d0 100644 --- a/tests/ui/issues/issue-2151.stderr +++ b/tests/ui/issues/issue-2151.stderr @@ -11,6 +11,6 @@ help: consider giving `x` an explicit type LL | let x: /* Type */ = panic!(); | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-21554.stderr b/tests/ui/issues/issue-21554.stderr index 6ea552a26a5cb..b1b59af6ec2b2 100644 --- a/tests/ui/issues/issue-21554.stderr +++ b/tests/ui/issues/issue-21554.stderr @@ -4,6 +4,6 @@ error[E0606]: casting `fn(i32) -> Inches {Inches}` as `f32` is invalid LL | Inches as f32; | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/issues/issue-21596.stderr b/tests/ui/issues/issue-21596.stderr index a336d1b0ed55d..8a7fca5f43647 100644 --- a/tests/ui/issues/issue-21596.stderr +++ b/tests/ui/issues/issue-21596.stderr @@ -10,6 +10,6 @@ LL | println!("{}", z.to_string()); `*const u8: std::fmt::Display` which is required by `*const u8: ToString` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-21763.stderr b/tests/ui/issues/issue-21763.stderr index a887635d35466..3d623985cbb3c 100644 --- a/tests/ui/issues/issue-21763.stderr +++ b/tests/ui/issues/issue-21763.stderr @@ -17,6 +17,6 @@ note: required by a bound in `foo` LL | fn foo() {} | ^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-21837.stderr b/tests/ui/issues/issue-21837.stderr index 3d38526649992..f198939268802 100644 --- a/tests/ui/issues/issue-21837.stderr +++ b/tests/ui/issues/issue-21837.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | impl Trait2 for Foo {} | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-21946.stderr b/tests/ui/issues/issue-21946.stderr index 67f6b3081bb30..d1b4a808d2ec6 100644 --- a/tests/ui/issues/issue-21946.stderr +++ b/tests/ui/issues/issue-21946.stderr @@ -4,6 +4,6 @@ error[E0275]: overflow evaluating the requirement `::A == _` LL | type A = ::A; | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/issues/issue-21974.stderr b/tests/ui/issues/issue-21974.stderr index 2d60b18b1f208..3934846ea0280 100644 --- a/tests/ui/issues/issue-21974.stderr +++ b/tests/ui/issues/issue-21974.stderr @@ -12,6 +12,6 @@ LL | where &'a T : Foo, LL | &'b T : Foo | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-22034.stderr b/tests/ui/issues/issue-22034.stderr index d64b024098c9b..6d899618d7a94 100644 --- a/tests/ui/issues/issue-22034.stderr +++ b/tests/ui/issues/issue-22034.stderr @@ -8,6 +8,6 @@ LL | &mut *(ptr as *mut dyn Fn()) = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` = note: required for the cast from `*mut ()` to `*mut dyn Fn()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-22289.stderr b/tests/ui/issues/issue-22289.stderr index b594e8b7a1eed..560fbc73bbdc8 100644 --- a/tests/ui/issues/issue-22289.stderr +++ b/tests/ui/issues/issue-22289.stderr @@ -9,6 +9,6 @@ help: consider borrowing the value LL | &0 as &dyn std::any::Any; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/issues/issue-22312.stderr b/tests/ui/issues/issue-22312.stderr index da15c092fc311..be3f5ace5480e 100644 --- a/tests/ui/issues/issue-22312.stderr +++ b/tests/ui/issues/issue-22312.stderr @@ -9,6 +9,6 @@ help: consider borrowing the value LL | let indexer = &(&*self as &dyn Index>::Output>); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/issues/issue-22370.stderr b/tests/ui/issues/issue-22370.stderr index cd27c4e4e4edf..977cfe06bb8b9 100644 --- a/tests/ui/issues/issue-22370.stderr +++ b/tests/ui/issues/issue-22370.stderr @@ -9,6 +9,6 @@ LL | fn f(a: &dyn A) {} | = note: because of the default `Self` reference, type parameters must be specified on object types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/issues/issue-22434.stderr b/tests/ui/issues/issue-22434.stderr index dab62bcbb4d2e..172ae386c3e4a 100644 --- a/tests/ui/issues/issue-22434.stderr +++ b/tests/ui/issues/issue-22434.stderr @@ -7,6 +7,6 @@ LL | type A; LL | type I<'a> = &'a (dyn Foo + 'a); | ^^^ help: specify the associated type: `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-22468.stderr b/tests/ui/issues/issue-22468.stderr index 3fff91acbc25f..052888d2029b9 100644 --- a/tests/ui/issues/issue-22468.stderr +++ b/tests/ui/issues/issue-22468.stderr @@ -7,7 +7,10 @@ LL | let x = foo("baz"); | ^^^------- | | | call expression requires function +... +LL | fn foo(file: &str) -> bool { + | -------------------------- this function of the same name is available here, but it's shadowed by the local binding -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-22599.stderr b/tests/ui/issues/issue-22599.stderr index 2b34830d08427..b599f6febe31b 100644 --- a/tests/ui/issues/issue-22599.stderr +++ b/tests/ui/issues/issue-22599.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_variables)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-22638.polonius.stderr b/tests/ui/issues/issue-22638.polonius.stderr index 87a7c00e4107b..3a94ed7bd3da2 100644 --- a/tests/ui/issues/issue-22638.polonius.stderr +++ b/tests/ui/issues/issue-22638.polonius.stderr @@ -11,5 +11,5 @@ LL | pub fn matches(&self, f: &F) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-22638.polonius/issue-22638.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-22638.stderr b/tests/ui/issues/issue-22638.stderr index 1caa4221f2501..a372078abd84e 100644 --- a/tests/ui/issues/issue-22638.stderr +++ b/tests/ui/issues/issue-22638.stderr @@ -10,5 +10,5 @@ note: `A::matches` defined here LL | pub fn matches(&self, f: &F) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-22684.stderr b/tests/ui/issues/issue-22684.stderr index 2407ece5e4f7d..e2ca54caeac05 100644 --- a/tests/ui/issues/issue-22684.stderr +++ b/tests/ui/issues/issue-22684.stderr @@ -6,6 +6,6 @@ LL | let _: () = foo::Foo.bar(); | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-22706.stderr b/tests/ui/issues/issue-22706.stderr index 5366a36b1a689..309e11a25f1ac 100644 --- a/tests/ui/issues/issue-22706.stderr +++ b/tests/ui/issues/issue-22706.stderr @@ -6,6 +6,6 @@ LL | fn is_copy::Copy>() {} | | | not allowed on module `marker` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/issues/issue-2281-part1.stderr b/tests/ui/issues/issue-2281-part1.stderr index c2391a7c0911f..47a1ef8cc0277 100644 --- a/tests/ui/issues/issue-2281-part1.stderr +++ b/tests/ui/issues/issue-2281-part1.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `foobar` in this scope LL | fn main() { println!("{}", foobar); } | ^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-22872.stderr b/tests/ui/issues/issue-22872.stderr index 63222d25c0171..6ff710b113325 100644 --- a/tests/ui/issues/issue-22872.stderr +++ b/tests/ui/issues/issue-22872.stderr @@ -19,6 +19,6 @@ help: consider further restricting the associated type LL | fn push_process

    (process: P) where P: Process<'static>,

    >::Item: Iterator { | ++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-22874.stderr b/tests/ui/issues/issue-22874.stderr index d648990804442..717ce72b9c140 100644 --- a/tests/ui/issues/issue-22874.stderr +++ b/tests/ui/issues/issue-22874.stderr @@ -7,6 +7,6 @@ LL | rows: [[String]], = help: the trait `Sized` is not implemented for `[String]` = note: slice and array elements must have `Sized` type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-22886.stderr b/tests/ui/issues/issue-22886.stderr index c4b3965592411..a04fa677f9ec5 100644 --- a/tests/ui/issues/issue-22886.stderr +++ b/tests/ui/issues/issue-22886.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a> Iterator for Newtype { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-22933-2.stderr b/tests/ui/issues/issue-22933-2.stderr index 1a0e87e15d6bc..8cda8598f3c4f 100644 --- a/tests/ui/issues/issue-22933-2.stderr +++ b/tests/ui/issues/issue-22933-2.stderr @@ -10,6 +10,6 @@ LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, | variant or associated item not found in `Delicious` | help: there is a variant with a similar name: `Pie` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-23041.stderr b/tests/ui/issues/issue-23041.stderr index 4271c67c3bcf3..0142926dd1562 100644 --- a/tests/ui/issues/issue-23041.stderr +++ b/tests/ui/issues/issue-23041.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | b.downcast_ref:: _>(); | ~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-23046.stderr b/tests/ui/issues/issue-23046.stderr index 1403ecbd92d49..b6e23814543f3 100644 --- a/tests/ui/issues/issue-23046.stderr +++ b/tests/ui/issues/issue-23046.stderr @@ -9,6 +9,6 @@ help: consider giving this closure parameter an explicit type, where the type fo LL | let ex = |x: Expr<'_, VAR>| { | +++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-23073.stderr b/tests/ui/issues/issue-23073.stderr index 3a9f49ef167d6..6a61df8d46b2c 100644 --- a/tests/ui/issues/issue-23073.stderr +++ b/tests/ui/issues/issue-23073.stderr @@ -9,6 +9,6 @@ help: if there were a trait named `Example` with associated type `T` implemented LL | type FooT = <::Foo as Example>::T; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/issues/issue-23122-1.stderr b/tests/ui/issues/issue-23122-1.stderr index 0b568b30e08d8..c432a502c1340 100644 --- a/tests/ui/issues/issue-23122-1.stderr +++ b/tests/ui/issues/issue-23122-1.stderr @@ -4,6 +4,6 @@ error[E0275]: overflow evaluating the requirement ` as Next>::Next == LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/issues/issue-23122-2.stderr b/tests/ui/issues/issue-23122-2.stderr index af77e4b1a4123..b8aa587a7398c 100644 --- a/tests/ui/issues/issue-23122-2.stderr +++ b/tests/ui/issues/issue-23122-2.stderr @@ -13,6 +13,6 @@ LL | impl Next for GetNext { | | | unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/issues/issue-23189.stderr b/tests/ui/issues/issue-23189.stderr index ed065212c560b..37d778dc992eb 100644 --- a/tests/ui/issues/issue-23189.stderr +++ b/tests/ui/issues/issue-23189.stderr @@ -4,6 +4,6 @@ error[E0574]: expected struct, variant or union type, found module `module` LL | let _ = module { x: 0 }; | ^^^^^^ not a struct, variant or union type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-23217.stderr b/tests/ui/issues/issue-23217.stderr index 5d3d8a4f808a8..05ee0474c7838 100644 --- a/tests/ui/issues/issue-23217.stderr +++ b/tests/ui/issues/issue-23217.stderr @@ -9,6 +9,6 @@ LL | B = SomeEnum::A, | variant or associated item not found in `SomeEnum` | help: there is a variant with a similar name: `B` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-23253.stderr b/tests/ui/issues/issue-23253.stderr index be5714cd91a2b..ec7696909e725 100644 --- a/tests/ui/issues/issue-23253.stderr +++ b/tests/ui/issues/issue-23253.stderr @@ -2,8 +2,8 @@ error[E0609]: no field `a` on type `Foo` --> $DIR/issue-23253.rs:4:14 | LL | Foo::Bar.a; - | ^ + | ^ unknown field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-23281.stderr b/tests/ui/issues/issue-23281.stderr index 804334c9b0d24..e1f4e8a96c825 100644 --- a/tests/ui/issues/issue-23281.stderr +++ b/tests/ui/issues/issue-23281.stderr @@ -18,6 +18,6 @@ LL | struct Vec { LL | t: T, | - ...if indirection were used here: `Box` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-23302-1.stderr b/tests/ui/issues/issue-23302-1.stderr index d753bdeb9f701..5c2758dc60900 100644 --- a/tests/ui/issues/issue-23302-1.stderr +++ b/tests/ui/issues/issue-23302-1.stderr @@ -17,6 +17,6 @@ LL | A = X::A as isize, | ^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-23302-2.stderr b/tests/ui/issues/issue-23302-2.stderr index b756ee1d5e25c..93665af69dd8d 100644 --- a/tests/ui/issues/issue-23302-2.stderr +++ b/tests/ui/issues/issue-23302-2.stderr @@ -17,6 +17,6 @@ LL | A = Y::B as isize, | ^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-23302-3.stderr b/tests/ui/issues/issue-23302-3.stderr index 6cdc94551fe4d..b3e933a21718e 100644 --- a/tests/ui/issues/issue-23302-3.stderr +++ b/tests/ui/issues/issue-23302-3.stderr @@ -27,6 +27,6 @@ LL | const A: i32 = B; | ^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-23477.rs b/tests/ui/issues/issue-23477.rs index 988ebe03ccf66..1ce05ba390d76 100644 --- a/tests/ui/issues/issue-23477.rs +++ b/tests/ui/issues/issue-23477.rs @@ -1,5 +1,4 @@ // build-pass -// ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g pub struct Dst { diff --git a/tests/ui/issues/issue-23543.stderr b/tests/ui/issues/issue-23543.stderr index ebb70afe31681..d917a4c51d595 100644 --- a/tests/ui/issues/issue-23543.stderr +++ b/tests/ui/issues/issue-23543.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | where T: A; | ^^^^^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-23544.stderr b/tests/ui/issues/issue-23544.stderr index c912baccb4924..2a7e93f0eb71d 100644 --- a/tests/ui/issues/issue-23544.stderr +++ b/tests/ui/issues/issue-23544.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | where T: A; | ^^^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-23966.stderr b/tests/ui/issues/issue-23966.stderr index 542aed0eb2618..c29e88614442f 100644 --- a/tests/ui/issues/issue-23966.stderr +++ b/tests/ui/issues/issue-23966.stderr @@ -10,6 +10,6 @@ LL | "".chars().fold(|_, _| (), ()); note: required by a bound in `fold` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-24013.stderr b/tests/ui/issues/issue-24013.stderr index 72102f460e0bd..37a86ecc54374 100644 --- a/tests/ui/issues/issue-24013.stderr +++ b/tests/ui/issues/issue-24013.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-24322.stderr b/tests/ui/issues/issue-24322.stderr index 954fd4928126f..b260d02738854 100644 --- a/tests/ui/issues/issue-24322.stderr +++ b/tests/ui/issues/issue-24322.stderr @@ -9,6 +9,6 @@ LL | let x: &fn(&B) -> u32 = &B::func; = note: expected reference `&for<'a> fn(&'a B) -> u32` found reference `&for<'a> fn(&'a B) -> u32 {B::func}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-24352.stderr b/tests/ui/issues/issue-24352.stderr index f1c3891b87000..015569cce06b5 100644 --- a/tests/ui/issues/issue-24352.stderr +++ b/tests/ui/issues/issue-24352.stderr @@ -15,6 +15,6 @@ help: consider using a floating-point literal by writing it with `.0` LL | 1.0f64 - 1.0 | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-24357.stderr b/tests/ui/issues/issue-24357.stderr index b9e15f5e21bab..08a5a8ac56e1b 100644 --- a/tests/ui/issues/issue-24357.stderr +++ b/tests/ui/issues/issue-24357.stderr @@ -12,6 +12,6 @@ LL | let f = move || { let y = x; }; LL | let z = x; | ^ value used here after move -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-24365.stderr b/tests/ui/issues/issue-24365.stderr index f9eead8a4f213..3f6ed0231d8b5 100644 --- a/tests/ui/issues/issue-24365.stderr +++ b/tests/ui/issues/issue-24365.stderr @@ -2,19 +2,19 @@ error[E0609]: no field `b` on type `Foo` --> $DIR/issue-24365.rs:10:22 | LL | println!("{}", a.b); - | ^ + | ^ unknown field error[E0609]: no field `attr_name_idx` on type `&Attribute` --> $DIR/issue-24365.rs:17:18 | LL | let z = (&x).attr_name_idx; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ unknown field error[E0609]: no field `attr_name_idx` on type `Attribute` --> $DIR/issue-24365.rs:18:15 | LL | let y = x.attr_name_idx; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ unknown field error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-24424.stderr b/tests/ui/issues/issue-24424.stderr index 50d7f988e194c..d42750e7a2b55 100644 --- a/tests/ui/issues/issue-24424.stderr +++ b/tests/ui/issues/issue-24424.stderr @@ -10,6 +10,6 @@ note: multiple `impl`s or `where` clauses satisfying `T0: Trait0<'l0>` found LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} | ^^^^^^^^^^^ ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-24687-embed-debuginfo/main.rs b/tests/ui/issues/issue-24687-embed-debuginfo/main.rs index f08bcdfe6d16c..773792c7a3f1f 100644 --- a/tests/ui/issues/issue-24687-embed-debuginfo/main.rs +++ b/tests/ui/issues/issue-24687-embed-debuginfo/main.rs @@ -1,7 +1,6 @@ // run-pass // aux-build:issue-24687-lib.rs // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet extern crate issue_24687_lib as d; diff --git a/tests/ui/issues/issue-24819.stderr b/tests/ui/issues/issue-24819.stderr index 8b4f1dbce431d..8ec34aa13fa6a 100644 --- a/tests/ui/issues/issue-24819.stderr +++ b/tests/ui/issues/issue-24819.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn foo(h: &mut HashSet) { | ^^^ -------------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-24945-repeat-dash-opts.rs b/tests/ui/issues/issue-24945-repeat-dash-opts.rs index 0f92fc2f7f31a..cf3834952c6a6 100644 --- a/tests/ui/issues/issue-24945-repeat-dash-opts.rs +++ b/tests/ui/issues/issue-24945-repeat-dash-opts.rs @@ -3,7 +3,6 @@ // as options to the compiler. // compile-flags:-g -g -O -O -// ignore-asmjs wasm2js does not support source maps yet fn main() { assert_eq!(1, 1); diff --git a/tests/ui/issues/issue-25076.stderr b/tests/ui/issues/issue-25076.stderr index 065bf7def42f8..2acfe70b48542 100644 --- a/tests/ui/issues/issue-25076.stderr +++ b/tests/ui/issues/issue-25076.stderr @@ -17,6 +17,6 @@ note: required by a bound in `do_fold` LL | fn do_fold>(init: B, f: F) {} | ^^^^^^^^^^^^^^^ required by this bound in `do_fold` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-25368.stderr b/tests/ui/issues/issue-25368.stderr index e6ed3aac71032..23f1441e69dcf 100644 --- a/tests/ui/issues/issue-25368.stderr +++ b/tests/ui/issues/issue-25368.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | tx.send(Foo{ foo: PhantomData:: }); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-25386.stderr b/tests/ui/issues/issue-25386.stderr index 727b96908291e..720b77866a583 100644 --- a/tests/ui/issues/issue-25386.stderr +++ b/tests/ui/issues/issue-25386.stderr @@ -9,6 +9,6 @@ LL | println!("{}", check_ptr_exist!(item, name)); | = note: this error originates in the macro `check_ptr_exist` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/issues/issue-2590.stderr b/tests/ui/issues/issue-2590.stderr index 6aacd563af162..517b4814eaea5 100644 --- a/tests/ui/issues/issue-2590.stderr +++ b/tests/ui/issues/issue-2590.stderr @@ -4,6 +4,6 @@ error[E0507]: cannot move out of `self.tokens` which is behind a shared referenc LL | self.tokens | ^^^^^^^^^^^ move occurs because `self.tokens` has type `Vec`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-25901.stderr b/tests/ui/issues/issue-25901.stderr index 1427e43854f57..673f29fff18c2 100644 --- a/tests/ui/issues/issue-25901.stderr +++ b/tests/ui/issues/issue-25901.stderr @@ -19,6 +19,6 @@ LL | impl Deref for A { = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/issues/issue-26056.stderr b/tests/ui/issues/issue-26056.stderr index 2c873243fe9e4..f1f553adf0f65 100644 --- a/tests/ui/issues/issue-26056.stderr +++ b/tests/ui/issues/issue-26056.stderr @@ -12,6 +12,6 @@ LL | trait Map: MapLookup<::Key> { | | | this trait cannot be made into an object... -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-26217.stderr b/tests/ui/issues/issue-26217.stderr index 73c772205c3da..0b153ad7490e0 100644 --- a/tests/ui/issues/issue-26217.stderr +++ b/tests/ui/issues/issue-26217.stderr @@ -12,5 +12,5 @@ note: due to current limitations in the borrow checker, this implies a `'static` LL | fn foo() where for<'a> T: 'a {} | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-26237.stderr b/tests/ui/issues/issue-26237.stderr index 91d28a5e1e1ef..d15e5753a25e7 100644 --- a/tests/ui/issues/issue-26237.stderr +++ b/tests/ui/issues/issue-26237.stderr @@ -10,6 +10,6 @@ LL | let mut value_b = 0; LL | macro_panic!(value_a, value_b); | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-26484.rs b/tests/ui/issues/issue-26484.rs index 2a8750d3e431f..3b40b3dd8f075 100644 --- a/tests/ui/issues/issue-26484.rs +++ b/tests/ui/issues/issue-26484.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet fn helper bool>(_f: F) { print!(""); diff --git a/tests/ui/issues/issue-26619.stderr b/tests/ui/issues/issue-26619.stderr index 1282fd7d3c238..9175bd2a3032c 100644 --- a/tests/ui/issues/issue-26619.stderr +++ b/tests/ui/issues/issue-26619.stderr @@ -6,6 +6,6 @@ LL | for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| | | | function parameter borrowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-26812.stderr b/tests/ui/issues/issue-26812.stderr index fd1bbb9c5673d..c2a3d4b83d536 100644 --- a/tests/ui/issues/issue-26812.stderr +++ b/tests/ui/issues/issue-26812.stderr @@ -4,6 +4,6 @@ error[E0128]: generic parameters with a default cannot use forward declared iden LL | fn avg(_: T) {} | ^^^^^^^ defaulted generic parameters cannot be forward declared -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/issues/issue-26905.stderr b/tests/ui/issues/issue-26905.stderr index 10dbb73258599..86f6a14cd1053 100644 --- a/tests/ui/issues/issue-26905.stderr +++ b/tests/ui/issues/issue-26905.stderr @@ -7,6 +7,6 @@ LL | impl, U: ?Sized> CoerceUnsized> for MyRc{ = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced = note: currently, 2 fields need coercions: `_ptr` (`*const T` to `*const U`), `_boo` (`NotPhantomData` to `NotPhantomData`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0375`. diff --git a/tests/ui/issues/issue-26948.stderr b/tests/ui/issues/issue-26948.stderr index faede1687673c..982c9758a3bc1 100644 --- a/tests/ui/issues/issue-26948.stderr +++ b/tests/ui/issues/issue-26948.stderr @@ -4,6 +4,6 @@ error[E0436]: functional record update syntax requires a struct LL | Foo::A { x: 6, ..orig }; | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0436`. diff --git a/tests/ui/issues/issue-27008.stderr b/tests/ui/issues/issue-27008.stderr index 9d18045aa794c..b4bfaa2786332 100644 --- a/tests/ui/issues/issue-27008.stderr +++ b/tests/ui/issues/issue-27008.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | let b = [0; S]; | ^ expected `usize`, found `S` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-27078.stderr b/tests/ui/issues/issue-27078.stderr index ced92bbd4848f..d0ba9f6ae2b18 100644 --- a/tests/ui/issues/issue-27078.stderr +++ b/tests/ui/issues/issue-27078.stderr @@ -14,6 +14,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn foo(&self) -> &'static i32 { | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/issues/issue-27340.stderr index 9caaffd9c9a21..3353b83f4e560 100644 --- a/tests/ui/issues/issue-27340.stderr +++ b/tests/ui/issues/issue-27340.stderr @@ -9,6 +9,6 @@ LL | struct Bar(Foo); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/issues/issue-27433.stderr b/tests/ui/issues/issue-27433.stderr index da751a6495736..aba8e612858a2 100644 --- a/tests/ui/issues/issue-27433.stderr +++ b/tests/ui/issues/issue-27433.stderr @@ -6,6 +6,6 @@ LL | const FOO : u32 = foo; | | | help: consider using `let` instead of `const`: `let FOO` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-2823.stderr b/tests/ui/issues/issue-2823.stderr index b5a2b2f55a6d4..5cd3f080450d6 100644 --- a/tests/ui/issues/issue-2823.stderr +++ b/tests/ui/issues/issue-2823.stderr @@ -11,6 +11,6 @@ LL | let _d = c.clone(); = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `Clone` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-2848.stderr b/tests/ui/issues/issue-2848.stderr index 71ed7d70b5b81..873f7efcd73f3 100644 --- a/tests/ui/issues/issue-2848.stderr +++ b/tests/ui/issues/issue-2848.stderr @@ -6,6 +6,6 @@ LL | alpha | beta => {} | | | pattern doesn't bind `beta` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/issues/issue-2849.stderr b/tests/ui/issues/issue-2849.stderr index 9027098d2d1a8..ef5cdb42e6106 100644 --- a/tests/ui/issues/issue-2849.stderr +++ b/tests/ui/issues/issue-2849.stderr @@ -6,6 +6,6 @@ LL | Foo::Alpha | Foo::Beta(i) => {} | | | pattern doesn't bind `i` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/issues/issue-28568.stderr b/tests/ui/issues/issue-28568.stderr index 960259080f739..c8db0403e59a2 100644 --- a/tests/ui/issues/issue-28568.stderr +++ b/tests/ui/issues/issue-28568.stderr @@ -7,6 +7,6 @@ LL | impl Drop for MyStruct { LL | impl Drop for MyStruct { | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-28586.stderr b/tests/ui/issues/issue-28586.stderr index d19c4af2df7c9..33f40a341c8f0 100644 --- a/tests/ui/issues/issue-28586.stderr +++ b/tests/ui/issues/issue-28586.stderr @@ -4,6 +4,6 @@ error[E0599]: no associated item named `BYTES` found for type `usize` in the cur LL | impl Foo for [u8; usize::BYTES] {} | ^^^^^ associated item not found in `usize` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-28625.stderr b/tests/ui/issues/issue-28625.stderr index 7ee0cd4867073..3600622a45424 100644 --- a/tests/ui/issues/issue-28625.stderr +++ b/tests/ui/issues/issue-28625.stderr @@ -7,6 +7,6 @@ LL | unsafe { std::mem::transmute(a) } = note: source type: `&ArrayPeano` (N bits) = note: target type: `&[T]` (N bits) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/issues/issue-28776.mir.stderr b/tests/ui/issues/issue-28776.mir.stderr index 1d470fb5e0f00..e7b7ba082688c 100644 --- a/tests/ui/issues/issue-28776.mir.stderr +++ b/tests/ui/issues/issue-28776.mir.stderr @@ -6,6 +6,6 @@ LL | (&ptr::write)(1 as *mut _, 42); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/issues/issue-28776.thir.stderr b/tests/ui/issues/issue-28776.thir.stderr index e3562810b3aa8..63172b85424df 100644 --- a/tests/ui/issues/issue-28776.thir.stderr +++ b/tests/ui/issues/issue-28776.thir.stderr @@ -6,6 +6,6 @@ LL | (&ptr::write)(1 as *mut _, 42); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/issues/issue-28971.stderr b/tests/ui/issues/issue-28971.stderr index 2eb8a1c2653c8..8fd3c7ffc3035 100644 --- a/tests/ui/issues/issue-28971.stderr +++ b/tests/ui/issues/issue-28971.stderr @@ -10,6 +10,6 @@ LL | Foo::Baz(..) => (), | variant or associated item not found in `Foo` | help: there is a variant with a similar name: `Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-29147.stderr b/tests/ui/issues/issue-29147.stderr index d0d9485310b46..a9cda55fd9acf 100644 --- a/tests/ui/issues/issue-29147.stderr +++ b/tests/ui/issues/issue-29147.stderr @@ -12,6 +12,6 @@ LL | impl Foo for S5 { fn xxx(&self) {} } LL | impl Foo for S5 { fn xxx(&self) {} } | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-2951.stderr b/tests/ui/issues/issue-2951.stderr index 538bbe2f50296..134808b4d236b 100644 --- a/tests/ui/issues/issue-2951.stderr +++ b/tests/ui/issues/issue-2951.stderr @@ -15,6 +15,6 @@ LL | xx = y; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-29861.stderr b/tests/ui/issues/issue-29861.stderr index d9d3cf360df2d..e7860c19eaa45 100644 --- a/tests/ui/issues/issue-29861.stderr +++ b/tests/ui/issues/issue-29861.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, T: 'a> MakeRef2 for T { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-2995.stderr b/tests/ui/issues/issue-2995.stderr index 0d09612c6c2c6..f4a08e1751fc8 100644 --- a/tests/ui/issues/issue-2995.stderr +++ b/tests/ui/issues/issue-2995.stderr @@ -10,6 +10,6 @@ LL - let _q: &isize = p as &isize; LL + let _q: &isize = &*p; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/issues/issue-30007.stderr b/tests/ui/issues/issue-30007.stderr index 87e770e1543d5..f303221cf8aa8 100644 --- a/tests/ui/issues/issue-30007.stderr +++ b/tests/ui/issues/issue-30007.stderr @@ -9,5 +9,5 @@ LL | let i: Vec; | = note: the usage of `t!` is likely invalid in type context -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-30123.stderr b/tests/ui/issues/issue-30123.stderr index a00a1dbb8843d..cf71a01b58a5c 100644 --- a/tests/ui/issues/issue-30123.stderr +++ b/tests/ui/issues/issue-30123.stderr @@ -7,6 +7,6 @@ LL | let ug = Graph::::new_undirected(); = note: the function or associated item was found for - `issue_30123_aux::Graph` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-3021-b.stderr b/tests/ui/issues/issue-3021-b.stderr index 72289c5f9c344..48777fec0a3ff 100644 --- a/tests/ui/issues/issue-3021-b.stderr +++ b/tests/ui/issues/issue-3021-b.stderr @@ -6,6 +6,6 @@ LL | self.v0 = k0 ^ 0x736f6d6570736575; | = help: use the `|| { ... }` closure form instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/issues/issue-30236.stderr b/tests/ui/issues/issue-30236.stderr index 64cbd58d69547..0f69f49f505a0 100644 --- a/tests/ui/issues/issue-30236.stderr +++ b/tests/ui/issues/issue-30236.stderr @@ -4,6 +4,6 @@ error[E0091]: type parameter `Unused` is unused LL | Unused | ^^^^^^ unused type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0091`. diff --git a/tests/ui/issues/issue-30589.stderr b/tests/ui/issues/issue-30589.stderr index 4b88547a1aff4..6f97a189cead9 100644 --- a/tests/ui/issues/issue-30589.stderr +++ b/tests/ui/issues/issue-30589.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `DecoderError` in this scope LL | impl fmt::Display for DecoderError { | ^^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-31011.stderr b/tests/ui/issues/issue-31011.stderr index 58c170409fd44..9785d56f4fcbc 100644 --- a/tests/ui/issues/issue-31011.stderr +++ b/tests/ui/issues/issue-31011.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `trace` on type `&T` --> $DIR/issue-31011.rs:3:17 | LL | if $ctx.trace { - | ^^^^^ + | ^^^^^ unknown field ... LL | fn wrap(context: &T) -> () | - type parameter 'T' declared here @@ -12,6 +12,6 @@ LL | log!(context, "entered wrapper"); | = note: this error originates in the macro `log` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-31511.stderr b/tests/ui/issues/issue-31511.stderr index cb2991809dd13..177b78754cc3c 100644 --- a/tests/ui/issues/issue-31511.stderr +++ b/tests/ui/issues/issue-31511.stderr @@ -4,6 +4,6 @@ error[E0607]: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]` LL | x as *const [u8]; | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0607`. diff --git a/tests/ui/issues/issue-3154.stderr b/tests/ui/issues/issue-3154.stderr index da2af83ff03c3..3106aaddc4a1c 100644 --- a/tests/ui/issues/issue-3154.stderr +++ b/tests/ui/issues/issue-3154.stderr @@ -6,6 +6,6 @@ LL | fn thing<'a,Q>(x: &Q) -> Thing<'a,Q> { LL | Thing { x: x } | ^^^^^^^^^^^^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-31910.stderr b/tests/ui/issues/issue-31910.stderr index 2603c944207d0..6ef84d7daef55 100644 --- a/tests/ui/issues/issue-31910.stderr +++ b/tests/ui/issues/issue-31910.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | X = Trait::Number, | ^^^^^^^^^^^^^ expected `isize`, found `i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-32122-1.stderr b/tests/ui/issues/issue-32122-1.stderr index b4f5b1296670f..ae5dffe1fadf0 100644 --- a/tests/ui/issues/issue-32122-1.stderr +++ b/tests/ui/issues/issue-32122-1.stderr @@ -13,6 +13,6 @@ help: consider dereferencing LL | let _: *const u8 = &*a; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-32122-2.stderr b/tests/ui/issues/issue-32122-2.stderr index 02c335c1547fb..eb4327bef6251 100644 --- a/tests/ui/issues/issue-32122-2.stderr +++ b/tests/ui/issues/issue-32122-2.stderr @@ -13,6 +13,6 @@ help: consider dereferencing LL | let _: *const u8 = &***a; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-32326.stderr b/tests/ui/issues/issue-32326.stderr index dc51198d98ce8..1989a915cc14c 100644 --- a/tests/ui/issues/issue-32326.stderr +++ b/tests/ui/issues/issue-32326.stderr @@ -11,6 +11,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | Plus(Box, Expr), | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-32377.stderr b/tests/ui/issues/issue-32377.stderr index 5e870eb3e8d17..01a81cea1eca9 100644 --- a/tests/ui/issues/issue-32377.stderr +++ b/tests/ui/issues/issue-32377.stderr @@ -7,6 +7,6 @@ LL | unsafe { mem::transmute(x) } = note: source type: `[usize; 2]` (N bits) = note: target type: `Bar` (N bits) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/issues/issue-32782.stderr b/tests/ui/issues/issue-32782.stderr index a6c55ba03fca3..477c01f686403 100644 --- a/tests/ui/issues/issue-32782.stderr +++ b/tests/ui/issues/issue-32782.stderr @@ -10,6 +10,6 @@ LL | foo!(); = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-33096.rs b/tests/ui/issues/issue-33096.rs index 2501e1430b3d1..f0b472e2fe821 100644 --- a/tests/ui/issues/issue-33096.rs +++ b/tests/ui/issues/issue-33096.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet use std::ops::Deref; diff --git a/tests/ui/issues/issue-33293.stderr b/tests/ui/issues/issue-33293.stderr index c8450f400429c..5badaa153f2b1 100644 --- a/tests/ui/issues/issue-33293.stderr +++ b/tests/ui/issues/issue-33293.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `aaa` LL | aaa::bbb(_) => () | ^^^ use of undeclared crate or module `aaa` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/issues/issue-3344.stderr b/tests/ui/issues/issue-3344.stderr index e849f5d0490d7..eac8f10fcc164 100644 --- a/tests/ui/issues/issue-3344.stderr +++ b/tests/ui/issues/issue-3344.stderr @@ -6,6 +6,6 @@ LL | impl PartialOrd for Thing { | = help: implement the missing item: `fn partial_cmp(&self, _: &Thing) -> Option { todo!() }` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/issues/issue-33504.stderr b/tests/ui/issues/issue-33504.stderr index a831cf585f4e0..f3e1ca08b6fc3 100644 --- a/tests/ui/issues/issue-33504.stderr +++ b/tests/ui/issues/issue-33504.stderr @@ -11,6 +11,6 @@ LL | let Test = 1; | `Test` is interpreted as a unit struct, not a new binding | help: introduce a new binding instead: `other_test` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-33525.stderr b/tests/ui/issues/issue-33525.stderr index f8d703dc3b169..ee9f4d4c3016d 100644 --- a/tests/ui/issues/issue-33525.stderr +++ b/tests/ui/issues/issue-33525.stderr @@ -8,13 +8,13 @@ error[E0609]: no field `lorem` on type `&'static str` --> $DIR/issue-33525.rs:3:8 | LL | "".lorem; - | ^^^^^ + | ^^^^^ unknown field error[E0609]: no field `ipsum` on type `&'static str` --> $DIR/issue-33525.rs:4:8 | LL | "".ipsum; - | ^^^^^ + | ^^^^^ unknown field error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-34047.stderr b/tests/ui/issues/issue-34047.stderr index f770ded50d0fd..97b1230ce3509 100644 --- a/tests/ui/issues/issue-34047.stderr +++ b/tests/ui/issues/issue-34047.stderr @@ -7,6 +7,6 @@ LL | const C: u8 = 0; LL | mut C => {} | ^ cannot be named the same as a constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/issues/issue-34209.stderr b/tests/ui/issues/issue-34209.stderr index f9a25b69ff621..41bc60d03dd81 100644 --- a/tests/ui/issues/issue-34209.stderr +++ b/tests/ui/issues/issue-34209.stderr @@ -7,6 +7,6 @@ LL | enum S { LL | S::B {} => {}, | ^ help: there is a variant with a similar name: `A` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-34229.stderr b/tests/ui/issues/issue-34229.stderr index 69ef876d25502..e6aa0d25934cb 100644 --- a/tests/ui/issues/issue-34229.stderr +++ b/tests/ui/issues/issue-34229.stderr @@ -13,6 +13,6 @@ help: consider annotating `Comparable` with `#[derive(PartialOrd)]` LL | #[derive(PartialEq)] #[derive(PartialOrd)] | +++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr index 753942dd1d189..ac2e63eca3ede 100644 --- a/tests/ui/issues/issue-34334.stderr +++ b/tests/ui/issues/issue-34334.stderr @@ -2,9 +2,8 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/issue-34334.rs:2:29 | LL | let sr: Vec<(u32, _, _) = vec![]; - | -- - ^ expected one of `,`, `:`, or `>` - | | | - | | maybe try to close unmatched angle bracket + | -- ^ expected one of `,`, `:`, or `>` + | | | while parsing the type for `sr` | help: you might have meant to end the type parameters here diff --git a/tests/ui/issues/issue-34349.stderr b/tests/ui/issues/issue-34349.stderr index 8e9a16619f3b1..6a6188f10c8f8 100644 --- a/tests/ui/issues/issue-34349.stderr +++ b/tests/ui/issues/issue-34349.stderr @@ -17,6 +17,6 @@ note: required by a bound in `apply` LL | fn apply(f: F) where F: Fn() { | ^^^^ required by this bound in `apply` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/issues/issue-34373.stderr index 0f0821518a424..c6906734b2de9 100644 --- a/tests/ui/issues/issue-34373.stderr +++ b/tests/ui/issues/issue-34373.stderr @@ -23,6 +23,6 @@ LL | | } | |_^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-34569.rs b/tests/ui/issues/issue-34569.rs index 88dcdd4113807..1f68560509e8c 100644 --- a/tests/ui/issues/issue-34569.rs +++ b/tests/ui/issues/issue-34569.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet // In this test we just want to make sure that the code below does not lead to // a debuginfo verification assertion during compilation. This was caused by the diff --git a/tests/ui/issues/issue-3477.stderr b/tests/ui/issues/issue-3477.stderr index fd5f7dcf6e66a..2a4d6d2449ed4 100644 --- a/tests/ui/issues/issue-3477.stderr +++ b/tests/ui/issues/issue-3477.stderr @@ -6,6 +6,6 @@ LL | let _p: char = 100; | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-35139.stderr b/tests/ui/issues/issue-35139.stderr index 79e889b7e599e..875af70483224 100644 --- a/tests/ui/issues/issue-35139.stderr +++ b/tests/ui/issues/issue-35139.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a> MethodType for MTFn { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-3521-2.stderr b/tests/ui/issues/issue-3521-2.stderr index 84c7a9efa35bb..0be0e93c19e64 100644 --- a/tests/ui/issues/issue-3521-2.stderr +++ b/tests/ui/issues/issue-3521-2.stderr @@ -6,6 +6,6 @@ LL | static y: isize = foo + 1; | | | help: consider using `let` instead of `static`: `let y` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-35241.stderr b/tests/ui/issues/issue-35241.stderr index 4a2c15511fe26..6f6602793fdb7 100644 --- a/tests/ui/issues/issue-35241.stderr +++ b/tests/ui/issues/issue-35241.stderr @@ -16,6 +16,6 @@ help: use parentheses to construct this tuple struct LL | fn test() -> Foo { Foo(/* u32 */) } | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-35570.stderr b/tests/ui/issues/issue-35570.stderr index 197e80ac097c2..f23b55689e3e4 100644 --- a/tests/ui/issues/issue-35570.stderr +++ b/tests/ui/issues/issue-35570.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait Trait2<'a> { | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-35976.unimported.stderr b/tests/ui/issues/issue-35976.unimported.stderr index b31d2a31551ef..169e3d05d23b1 100644 --- a/tests/ui/issues/issue-35976.unimported.stderr +++ b/tests/ui/issues/issue-35976.unimported.stderr @@ -12,5 +12,5 @@ help: another candidate was found in the following trait, perhaps add a `use` fo LL + use private::Future; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-35988.stderr b/tests/ui/issues/issue-35988.stderr index 55988844c178c..4a674b010ea62 100644 --- a/tests/ui/issues/issue-35988.stderr +++ b/tests/ui/issues/issue-35988.stderr @@ -16,6 +16,6 @@ help: the `Box` type always has a statically known size and allocates its conten LL | V(Box<[Box]>), | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-36400.stderr b/tests/ui/issues/issue-36400.stderr index 5b753c69d5d10..522fb36e14343 100644 --- a/tests/ui/issues/issue-36400.stderr +++ b/tests/ui/issues/issue-36400.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut x = Box::new(3); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-3668-2.stderr b/tests/ui/issues/issue-3668-2.stderr index ba96510415435..3676f388891eb 100644 --- a/tests/ui/issues/issue-3668-2.stderr +++ b/tests/ui/issues/issue-3668-2.stderr @@ -6,6 +6,6 @@ LL | static child: isize = x + 1; | | | help: consider using `let` instead of `static`: `let child` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-3668.stderr b/tests/ui/issues/issue-3668.stderr index edc49979c10a0..d761b2d87db4e 100644 --- a/tests/ui/issues/issue-3668.stderr +++ b/tests/ui/issues/issue-3668.stderr @@ -6,6 +6,6 @@ LL | static childVal: Box

    = self.child.get(); | | | help: consider using `let` instead of `static`: `let childVal` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-3680.stderr b/tests/ui/issues/issue-3680.stderr index 0b0ae419e2bf9..2a757b44dc834 100644 --- a/tests/ui/issues/issue-3680.stderr +++ b/tests/ui/issues/issue-3680.stderr @@ -13,6 +13,6 @@ help: try wrapping the pattern in `Some` LL | Some(Err(_)) => () | +++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-36836.stderr b/tests/ui/issues/issue-36836.stderr index 418194fac9923..e5c943c7c3d82 100644 --- a/tests/ui/issues/issue-36836.stderr +++ b/tests/ui/issues/issue-36836.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Bar` in this scope LL | impl Foo for Bar {} | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-36856.rs b/tests/ui/issues/issue-36856.rs index 5657ba69f9449..f2dfaf3dd367e 100644 --- a/tests/ui/issues/issue-36856.rs +++ b/tests/ui/issues/issue-36856.rs @@ -2,7 +2,6 @@ // Regression test for #36856. // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet fn g() -> bool { false diff --git a/tests/ui/issues/issue-3702-2.stderr b/tests/ui/issues/issue-3702-2.stderr index 0b94c3135a106..4edca796f43ea 100644 --- a/tests/ui/issues/issue-3702-2.stderr +++ b/tests/ui/issues/issue-3702-2.stderr @@ -23,6 +23,6 @@ help: disambiguate the method for candidate #2 LL | Add::to_int(&self) + other.to_int() | ~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr index 3a1c0b82c227a..08b4573dd0b81 100644 --- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr +++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr @@ -11,5 +11,5 @@ LL | fn recurse(&self) { | ^^^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-37311-type-length-limit/issue-37311.polonius/issue-37311.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr index 87832dd29b284..ccee9ed4daadb 100644 --- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr +++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr @@ -11,5 +11,5 @@ LL | fn recurse(&self) { | ^^^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-37311-type-length-limit/issue-37311/issue-37311.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-37665.stderr b/tests/ui/issues/issue-37665.stderr index 1e1f451b450af..2c404b4e74473 100644 --- a/tests/ui/issues/issue-37665.stderr +++ b/tests/ui/issues/issue-37665.stderr @@ -6,6 +6,6 @@ LL | let x: () = 0; | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-3779.stderr b/tests/ui/issues/issue-3779.stderr index a0dbcc920fa3d..d4f4b79102d5e 100644 --- a/tests/ui/issues/issue-3779.stderr +++ b/tests/ui/issues/issue-3779.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | element: Option> | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-37884.stderr b/tests/ui/issues/issue-37884.stderr index 7ddb36c8e6f7f..633abeb6f2266 100644 --- a/tests/ui/issues/issue-37884.stderr +++ b/tests/ui/issues/issue-37884.stderr @@ -17,6 +17,6 @@ note: ...does not necessarily outlive the lifetime `'a` as defined here LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-38412.stderr b/tests/ui/issues/issue-38412.stderr index 610696f84d5f0..ed8b6b60afc06 100644 --- a/tests/ui/issues/issue-38412.stderr +++ b/tests/ui/issues/issue-38412.stderr @@ -4,6 +4,6 @@ error[E0532]: cannot match against a tuple struct which contains private fields LL | let Box(a) = loop { }; | ^^^ constructor is not visible here due to private fields -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-38458.stderr b/tests/ui/issues/issue-38458.stderr index c04a01118a441..fbf88d5033973 100644 --- a/tests/ui/issues/issue-38458.stderr +++ b/tests/ui/issues/issue-38458.stderr @@ -4,6 +4,6 @@ error[E0572]: return statement outside of function body LL | return; | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/issues/issue-38919.stderr b/tests/ui/issues/issue-38919.stderr index f9ab8a5150716..4a4bd2ee43d8d 100644 --- a/tests/ui/issues/issue-38919.stderr +++ b/tests/ui/issues/issue-38919.stderr @@ -6,6 +6,6 @@ LL | fn foo() { LL | T::Item; | ^^^^ associated item not found in `T` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-38954.stderr b/tests/ui/issues/issue-38954.stderr index ab15bb1afa827..4dd83ddf32d3a 100644 --- a/tests/ui/issues/issue-38954.stderr +++ b/tests/ui/issues/issue-38954.stderr @@ -11,6 +11,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn _test(ref _p: &str) {} | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-39175.stderr b/tests/ui/issues/issue-39175.stderr index 3a1476ac0e3af..1bc11dab327ab 100644 --- a/tests/ui/issues/issue-39175.stderr +++ b/tests/ui/issues/issue-39175.stderr @@ -10,6 +10,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use std::os::unix::process::CommandExt; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-39211.stderr b/tests/ui/issues/issue-39211.stderr index cd2a014bb683d..15c9a80bb3526 100644 --- a/tests/ui/issues/issue-39211.stderr +++ b/tests/ui/issues/issue-39211.stderr @@ -6,5 +6,5 @@ LL | let a = [3; M::Row::DIM]; | = note: this may fail depending on what value the parameter takes -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-39687.stderr b/tests/ui/issues/issue-39687.stderr index b1b3041ea0275..f4742115a1999 100644 --- a/tests/ui/issues/issue-39687.stderr +++ b/tests/ui/issues/issue-39687.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | ::call; | ^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-39848.rs b/tests/ui/issues/issue-39848.rs index 1964d739989eb..2a059120e8175 100644 --- a/tests/ui/issues/issue-39848.rs +++ b/tests/ui/issues/issue-39848.rs @@ -1,6 +1,6 @@ macro_rules! get_opt { ($tgt:expr, $field:ident) => { - if $tgt.has_$field() {} //~ ERROR expected `{`, found `foo` + if $tgt.has_$field() {} //~ ERROR expected `{`, found identifier `foo` } } diff --git a/tests/ui/issues/issue-39848.stderr b/tests/ui/issues/issue-39848.stderr index 387ef0776ff4a..a6c6c61f17095 100644 --- a/tests/ui/issues/issue-39848.stderr +++ b/tests/ui/issues/issue-39848.stderr @@ -1,4 +1,4 @@ -error: expected `{`, found `foo` +error: expected `{`, found identifier `foo` --> $DIR/issue-39848.rs:3:21 | LL | if $tgt.has_$field() {} @@ -21,5 +21,5 @@ help: try placing this code inside a block LL | if $tgt.has_{ $field() } {} | + + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-3993.stderr b/tests/ui/issues/issue-3993.stderr index deecf7a9d752c..cf839a1314065 100644 --- a/tests/ui/issues/issue-3993.stderr +++ b/tests/ui/issues/issue-3993.stderr @@ -10,6 +10,6 @@ note: the function `fly` is defined here LL | fn fly() {} | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-39970.stderr b/tests/ui/issues/issue-39970.stderr index 713bc404f6700..0fe73574bad6f 100644 --- a/tests/ui/issues/issue-39970.stderr +++ b/tests/ui/issues/issue-39970.stderr @@ -18,6 +18,6 @@ LL | //(): for<'a> Array<'a, Element=&'a ()>, // No ICE LL | (): for<'a> Array<'a, Element=()>, // ICE | ---------- unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-40288.stderr b/tests/ui/issues/issue-40288.stderr index db5d064379a76..180adcd6e99bc 100644 --- a/tests/ui/issues/issue-40288.stderr +++ b/tests/ui/issues/issue-40288.stderr @@ -10,6 +10,6 @@ LL | *refr = 3; LL | println!("{:?}", out[0]); | ------ borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr b/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr index e15eed6561234..7976d09054201 100644 --- a/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr +++ b/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr @@ -9,6 +9,6 @@ help: consider borrowing here LL | let e = &f.v[0]; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr b/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr index 1bc554efb5c3d..987558903ee42 100644 --- a/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr +++ b/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr @@ -13,6 +13,6 @@ help: consider borrowing here LL | let (a, b) = &x[0]; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-40510-1.migrate.stderr b/tests/ui/issues/issue-40510-1.migrate.stderr index 776a724d3106a..2090530571b3b 100644 --- a/tests/ui/issues/issue-40510-1.migrate.stderr +++ b/tests/ui/issues/issue-40510-1.migrate.stderr @@ -9,5 +9,5 @@ LL | &mut x = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-40510-1.stderr b/tests/ui/issues/issue-40510-1.stderr index e88f31ea1ee17..81fed1305cbe7 100644 --- a/tests/ui/issues/issue-40510-1.stderr +++ b/tests/ui/issues/issue-40510-1.stderr @@ -15,5 +15,5 @@ LL | &mut x = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-40510-3.migrate.stderr b/tests/ui/issues/issue-40510-3.migrate.stderr index a49475a8570a1..59aba4a8ef8ba 100644 --- a/tests/ui/issues/issue-40510-3.migrate.stderr +++ b/tests/ui/issues/issue-40510-3.migrate.stderr @@ -11,5 +11,5 @@ LL | | } = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-40510-3.stderr b/tests/ui/issues/issue-40510-3.stderr index eb077415e6ce0..43e8a73b8194b 100644 --- a/tests/ui/issues/issue-40510-3.stderr +++ b/tests/ui/issues/issue-40510-3.stderr @@ -19,5 +19,5 @@ help: consider adding 'move' keyword before the nested closure LL | move || { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-40610.stderr b/tests/ui/issues/issue-40610.stderr index b4e302dfffc7a..1bd1c4dd57d7e 100644 --- a/tests/ui/issues/issue-40610.stderr +++ b/tests/ui/issues/issue-40610.stderr @@ -6,6 +6,6 @@ LL | () + f(&[1.0]); | | | () -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-40749.stderr b/tests/ui/issues/issue-40749.stderr index afc39adec467a..f7770e00013c3 100644 --- a/tests/ui/issues/issue-40749.stderr +++ b/tests/ui/issues/issue-40749.stderr @@ -7,6 +7,6 @@ LL | [0; ..10]; = note: expected type `usize` found struct `RangeTo<{integer}>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-40861.stderr b/tests/ui/issues/issue-40861.stderr index 9b6469d05e92a..dec9af4b6d1cb 100644 --- a/tests/ui/issues/issue-40861.stderr +++ b/tests/ui/issues/issue-40861.stderr @@ -6,6 +6,6 @@ LL | ()[f(&[1.0])]; | = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/issues/issue-41139.stderr b/tests/ui/issues/issue-41139.stderr index 97492e6e0fa2e..d7b35245d8f5a 100644 --- a/tests/ui/issues/issue-41139.stderr +++ b/tests/ui/issues/issue-41139.stderr @@ -7,6 +7,6 @@ LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { LL | let t: &dyn Trait = &get_function()(); | ^^^^^^^^^^^^^^ this trait object returns an unsized value `(dyn Trait + 'static)`, so it cannot be called -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-41229-ref-str.stderr b/tests/ui/issues/issue-41229-ref-str.stderr index 31fdf3b72e7a4..afc2cac7343f3 100644 --- a/tests/ui/issues/issue-41229-ref-str.stderr +++ b/tests/ui/issues/issue-41229-ref-str.stderr @@ -11,6 +11,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | pub fn example(ref s: &str) {} | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-41549.stderr b/tests/ui/issues/issue-41549.stderr index 62307d387c822..55be59684b55d 100644 --- a/tests/ui/issues/issue-41549.stderr +++ b/tests/ui/issues/issue-41549.stderr @@ -4,6 +4,6 @@ error[E0326]: implemented const `CONST` has an incompatible type for trait LL | const CONST: () = (); | ^^ expected `u32`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/issues/issue-41652/issue-41652.stderr b/tests/ui/issues/issue-41652/issue-41652.stderr index 1618f0f5a11aa..a5a2fab2ede03 100644 --- a/tests/ui/issues/issue-41652/issue-41652.stderr +++ b/tests/ui/issues/issue-41652/issue-41652.stderr @@ -9,6 +9,6 @@ help: you must specify a concrete type for this numeric value, like `i32` LL | 3_i32.f() | ~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0689`. diff --git a/tests/ui/issues/issue-41726.stderr b/tests/ui/issues/issue-41726.stderr index 7c87fde540d1c..fe7d4df70676f 100644 --- a/tests/ui/issues/issue-41726.stderr +++ b/tests/ui/issues/issue-41726.stderr @@ -7,6 +7,6 @@ LL | things[src.as_str()].sort(); = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap>` = help: to modify a `HashMap>`, use `.get_mut()`, `.insert()` or the entry API -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-41742.stderr b/tests/ui/issues/issue-41742.stderr index 61a0ae5fa91a7..47c7e5dc11ff7 100644 --- a/tests/ui/issues/issue-41742.stderr +++ b/tests/ui/issues/issue-41742.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | H["?"].f(); | ^^^ expected `u32`, found `&str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-41880.stderr b/tests/ui/issues/issue-41880.stderr index 6414e26929a41..9d09be66305b4 100644 --- a/tests/ui/issues/issue-41880.stderr +++ b/tests/ui/issues/issue-41880.stderr @@ -7,6 +7,6 @@ LL | pub struct Iterate { LL | println!("{:?}", a.iter().take(10).collect::>()); | ^^^^ method not found in `Iterate<{integer}, {closure@issue-41880.rs:26:24}>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-42106.stderr b/tests/ui/issues/issue-42106.stderr index d5a9d233bc969..d5919870d9be2 100644 --- a/tests/ui/issues/issue-42106.stderr +++ b/tests/ui/issues/issue-42106.stderr @@ -8,6 +8,6 @@ LL | collection.swap(1, 2); LL | _a.use_ref(); | -- immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/issues/issue-42210.rs b/tests/ui/issues/issue-42210.rs index 01a5d563639b5..318e3099f98ba 100644 --- a/tests/ui/issues/issue-42210.rs +++ b/tests/ui/issues/issue-42210.rs @@ -2,7 +2,6 @@ // Regression test for #42210. // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet trait Foo { fn foo() { } diff --git a/tests/ui/issues/issue-4265.stderr b/tests/ui/issues/issue-4265.stderr index 8c7303f3c3c51..48b1c762e19a2 100644 --- a/tests/ui/issues/issue-4265.stderr +++ b/tests/ui/issues/issue-4265.stderr @@ -7,6 +7,6 @@ LL | fn bar() { LL | fn bar() { | ^^^^^^^^ duplicate definitions for `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/issues/issue-42755.stderr b/tests/ui/issues/issue-42755.stderr index 12047e22f1b02..41f6cc97e49bf 100644 --- a/tests/ui/issues/issue-42755.stderr +++ b/tests/ui/issues/issue-42755.stderr @@ -4,5 +4,5 @@ error: repetition matches empty token tree LL | ($($p:vis)*) => {} | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-42796.stderr b/tests/ui/issues/issue-42796.stderr index f2971df5db275..670b98c770898 100644 --- a/tests/ui/issues/issue-42796.stderr +++ b/tests/ui/issues/issue-42796.stderr @@ -15,6 +15,6 @@ help: consider cloning the value if the performance cost is acceptable LL | let mut s_copy = s.clone(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-42880.stderr b/tests/ui/issues/issue-42880.stderr index bec14429d38f1..f174f42b2398f 100644 --- a/tests/ui/issues/issue-42880.stderr +++ b/tests/ui/issues/issue-42880.stderr @@ -4,6 +4,6 @@ error[E0599]: no associated item named `String` found for struct `String` in the LL | let f = |&Value::String(_)| (); | ^^^^^^ associated item not found in `String` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-4335.stderr b/tests/ui/issues/issue-4335.stderr index ecc1fa5239892..8b4aff54dc3c0 100644 --- a/tests/ui/issues/issue-4335.stderr +++ b/tests/ui/issues/issue-4335.stderr @@ -8,6 +8,6 @@ LL | id(Box::new(|| *v)) | | | captured by this `FnMut` closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-43355.stderr b/tests/ui/issues/issue-43355.stderr index 9aeca8efe4a66..25179ef6a96c7 100644 --- a/tests/ui/issues/issue-43355.stderr +++ b/tests/ui/issues/issue-43355.stderr @@ -9,6 +9,6 @@ LL | impl Trait1> for A { | = note: downstream crates may implement trait `Trait2>` for type `A` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-43420-no-over-suggest.stderr b/tests/ui/issues/issue-43420-no-over-suggest.stderr index 9b141e2bf99af..3da8cc7288d31 100644 --- a/tests/ui/issues/issue-43420-no-over-suggest.stderr +++ b/tests/ui/issues/issue-43420-no-over-suggest.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn foo(b: &[u16]) {} | ^^^ --------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-43424.stderr b/tests/ui/issues/issue-43424.stderr index 8f59d7cc3aa77..64a3c2a3d8d06 100644 --- a/tests/ui/issues/issue-43424.stderr +++ b/tests/ui/issues/issue-43424.stderr @@ -4,5 +4,5 @@ error: unexpected generic arguments in path LL | m!(inline); | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-43431.stderr b/tests/ui/issues/issue-43431.stderr index 4edb528699d47..6d47ba2716240 100644 --- a/tests/ui/issues/issue-43431.stderr +++ b/tests/ui/issues/issue-43431.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | B>::call(self, (a,)) | ^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-43925.stderr b/tests/ui/issues/issue-43925.stderr index b0ad25063de83..7cc347c6163b5 100644 --- a/tests/ui/issues/issue-43925.stderr +++ b/tests/ui/issues/issue-43925.stderr @@ -4,5 +4,5 @@ error: link cfg must have a single predicate argument LL | #[link(name = "foo", cfg("rlib"))] | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-43926.stderr b/tests/ui/issues/issue-43926.stderr index f67f91a6bd3d8..7c5c50a38a93e 100644 --- a/tests/ui/issues/issue-43926.stderr +++ b/tests/ui/issues/issue-43926.stderr @@ -4,5 +4,5 @@ error: link cfg must have a single predicate argument LL | #[link(name = "foo", cfg())] | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-44023.stderr b/tests/ui/issues/issue-44023.stderr index 9e97012416a94..8554154fba515 100644 --- a/tests/ui/issues/issue-44023.stderr +++ b/tests/ui/issues/issue-44023.stderr @@ -6,6 +6,6 @@ LL | fn საჭმელად_გემრიელი_სადილი ( ) | | | implicitly returns `()` as its body has no tail or `return` expression -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-44078.stderr b/tests/ui/issues/issue-44078.stderr index daf67219f4d0a..3e12de34e11ee 100644 --- a/tests/ui/issues/issue-44078.stderr +++ b/tests/ui/issues/issue-44078.stderr @@ -6,6 +6,6 @@ LL | "😊""; LL | | } | |__^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0765`. diff --git a/tests/ui/issues/issue-44239.stderr b/tests/ui/issues/issue-44239.stderr index 2a245c92c4868..633fb177b75df 100644 --- a/tests/ui/issues/issue-44239.stderr +++ b/tests/ui/issues/issue-44239.stderr @@ -7,6 +7,6 @@ LL | let n: usize = 0; LL | const N: usize = n; | ^ non-constant value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-44405.stderr b/tests/ui/issues/issue-44405.stderr index 1fd69f6e77799..26d2b385efa28 100644 --- a/tests/ui/issues/issue-44405.stderr +++ b/tests/ui/issues/issue-44405.stderr @@ -6,6 +6,6 @@ LL | container[&mut val].test(); | = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Container` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-4517.stderr b/tests/ui/issues/issue-4517.stderr index 78ee336f19a43..5d544ee10a909 100644 --- a/tests/ui/issues/issue-4517.stderr +++ b/tests/ui/issues/issue-4517.stderr @@ -12,6 +12,6 @@ note: function defined here LL | fn bar(int_param: usize) {} | ^^^ ---------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-45562.stderr b/tests/ui/issues/issue-45562.stderr index be259d3f8a49e..6fae86f9f31ca 100644 --- a/tests/ui/issues/issue-45562.stderr +++ b/tests/ui/issues/issue-45562.stderr @@ -8,5 +8,5 @@ LL | #[no_mangle] pub const RAH: usize = 5; | = note: `#[deny(no_mangle_const_items)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-45731.rs b/tests/ui/issues/issue-45731.rs index 5c5ac59873a3a..d20c07276a8c5 100644 --- a/tests/ui/issues/issue-45731.rs +++ b/tests/ui/issues/issue-45731.rs @@ -1,7 +1,6 @@ // run-pass #![allow(unused_variables)] // compile-flags:--test -g -// ignore-asmjs wasm2js does not support source maps yet #[cfg(target_os = "macos")] #[test] diff --git a/tests/ui/issues/issue-45801.stderr b/tests/ui/issues/issue-45801.stderr index e651e2a68d160..5a10c429564c4 100644 --- a/tests/ui/issues/issue-45801.stderr +++ b/tests/ui/issues/issue-45801.stderr @@ -7,6 +7,6 @@ LL | req.get_ref::(); = help: the trait `Plugin` is implemented for `Params` = help: for that trait implementation, expected `Foo`, found `i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-45965.stderr b/tests/ui/issues/issue-45965.stderr index f3eaa91769f61..95a39b1d1980e 100644 --- a/tests/ui/issues/issue-45965.stderr +++ b/tests/ui/issues/issue-45965.stderr @@ -6,6 +6,6 @@ LL | let a = |r: f64| if r != 0.0(r != 0.0) { 1.0 } else { 0.0 }; | | | call expression requires function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-46302.stderr b/tests/ui/issues/issue-46302.stderr index 6e126038cc95c..e87c17b2ad365 100644 --- a/tests/ui/issues/issue-46302.stderr +++ b/tests/ui/issues/issue-46302.stderr @@ -9,6 +9,6 @@ help: consider borrowing here LL | let u: &str = if true { &s[..2] } else { s }; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-46311.stderr b/tests/ui/issues/issue-46311.stderr index d72d6477db649..86a3602899ab2 100644 --- a/tests/ui/issues/issue-46311.stderr +++ b/tests/ui/issues/issue-46311.stderr @@ -4,5 +4,5 @@ error: invalid label name `'break` LL | 'break: loop { | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-46332.stderr b/tests/ui/issues/issue-46332.stderr index 890ef8014b489..8c0c1dfa6ee86 100644 --- a/tests/ui/issues/issue-46332.stderr +++ b/tests/ui/issues/issue-46332.stderr @@ -7,6 +7,6 @@ LL | struct TyUint {} LL | TyUInt {}; | ^^^^^^ help: a struct with a similar name exists (notice the capitalization): `TyUint` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/issues/issue-46438.stderr b/tests/ui/issues/issue-46438.stderr index c1fad44b885f1..aff2d77a0c852 100644 --- a/tests/ui/issues/issue-46438.stderr +++ b/tests/ui/issues/issue-46438.stderr @@ -4,5 +4,5 @@ error: expected a trait, found type LL | m!(&'static u8); | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-46471-1.stderr b/tests/ui/issues/issue-46471-1.stderr index 2ae6e709d5ad5..d45172239820d 100644 --- a/tests/ui/issues/issue-46471-1.stderr +++ b/tests/ui/issues/issue-46471-1.stderr @@ -8,6 +8,6 @@ LL | &mut z LL | }; | - `z` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/issues/issue-46472.stderr b/tests/ui/issues/issue-46472.stderr index 6e561e03a8b7a..6115da28cc91c 100644 --- a/tests/ui/issues/issue-46472.stderr +++ b/tests/ui/issues/issue-46472.stderr @@ -7,6 +7,6 @@ LL | &mut 4 | | temporary value created here | returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-46771.stderr b/tests/ui/issues/issue-46771.stderr index 512827b2dbdcd..fab55fbfd704a 100644 --- a/tests/ui/issues/issue-46771.stderr +++ b/tests/ui/issues/issue-46771.stderr @@ -8,6 +8,6 @@ LL | (1 .. 2).find(|_| Foo(0) == 0); | | | call expression requires function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-46983.stderr b/tests/ui/issues/issue-46983.stderr index 38a219bbd7b52..f47df306ab845 100644 --- a/tests/ui/issues/issue-46983.stderr +++ b/tests/ui/issues/issue-46983.stderr @@ -6,5 +6,5 @@ LL | fn foo(x: &u32) -> &'static u32 { LL | &*x | ^^^ returning this value requires that `'1` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr index 5e1b816defda3..0aa1ae7222f57 100644 --- a/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr +++ b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `00` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:8:30 | LL | let _condemned = justice.00; - | ^^ help: a field with a similar name exists: `0` + | ^^ unknown field + | +help: a field with a similar name exists + | +LL | let _condemned = justice.0; + | ~ error[E0609]: no field `001` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31 diff --git a/tests/ui/issues/issue-47184.stderr b/tests/ui/issues/issue-47184.stderr index c2c7df7a333a4..d25c6eda9c349 100644 --- a/tests/ui/issues/issue-47184.stderr +++ b/tests/ui/issues/issue-47184.stderr @@ -7,6 +7,6 @@ LL | let _vec: Vec<&'static String> = vec![&String::new()]; | | creates a temporary value which is freed while still in use | type annotation requires that borrow lasts for `'static` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/issues/issue-4736.stderr b/tests/ui/issues/issue-4736.stderr index 2a1f1819c33cd..146dd1d57ce33 100644 --- a/tests/ui/issues/issue-4736.stderr +++ b/tests/ui/issues/issue-4736.stderr @@ -12,6 +12,6 @@ help: `NonCopyable` is a tuple struct, use the appropriate syntax LL | let z = NonCopyable(/* fields */); | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/issues/issue-47377.stderr b/tests/ui/issues/issue-47377.stderr index 4f0fd948e7604..12e5c15d77fc8 100644 --- a/tests/ui/issues/issue-47377.stderr +++ b/tests/ui/issues/issue-47377.stderr @@ -13,6 +13,6 @@ help: create an owned `String` from a string reference LL | let _a = b.to_owned() + ", World!"; | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-47380.stderr b/tests/ui/issues/issue-47380.stderr index b04ac5536c41f..4fca0296e437a 100644 --- a/tests/ui/issues/issue-47380.stderr +++ b/tests/ui/issues/issue-47380.stderr @@ -13,6 +13,6 @@ help: create an owned `String` from a string reference LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-47725.stderr b/tests/ui/issues/issue-47725.stderr index 7143fb4d6e140..0d3b77b46084c 100644 --- a/tests/ui/issues/issue-47725.stderr +++ b/tests/ui/issues/issue-47725.stderr @@ -56,5 +56,5 @@ help: try `#[link(name = "...")]` instead LL | #[link_name] | ^^^^^^^^^^^^ -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted diff --git a/tests/ui/issues/issue-48364.stderr b/tests/ui/issues/issue-48364.stderr index 3f2e1b83ad574..74bfa1e06933f 100644 --- a/tests/ui/issues/issue-48364.stderr +++ b/tests/ui/issues/issue-48364.stderr @@ -11,6 +11,6 @@ LL | b"".starts_with(stringify!(foo)) note: method defined here --> $SRC_DIR/core/src/slice/mod.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-48728.stderr b/tests/ui/issues/issue-48728.stderr index 0bb46724f6166..6b4247f1d7965 100644 --- a/tests/ui/issues/issue-48728.stderr +++ b/tests/ui/issues/issue-48728.stderr @@ -10,6 +10,6 @@ LL | impl Clone for Node<[T]> { = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `[_]` in future versions = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-48838.stderr b/tests/ui/issues/issue-48838.stderr index 159199a7fcecc..504ea3e80103a 100644 --- a/tests/ui/issues/issue-48838.stderr +++ b/tests/ui/issues/issue-48838.stderr @@ -7,6 +7,6 @@ LL | Square = |x| x, = note: expected type `isize` found closure `{closure@$DIR/issue-48838.rs:2:14: 2:17}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-4935.stderr b/tests/ui/issues/issue-4935.stderr index e544e4244034d..25f299ae5f3bb 100644 --- a/tests/ui/issues/issue-4935.stderr +++ b/tests/ui/issues/issue-4935.stderr @@ -13,6 +13,6 @@ note: function defined here LL | fn foo(a: usize) {} | ^^^ -------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/issues/issue-4968.stderr b/tests/ui/issues/issue-4968.stderr index 1ce0333846f44..549e5509474de 100644 --- a/tests/ui/issues/issue-4968.stderr +++ b/tests/ui/issues/issue-4968.stderr @@ -15,6 +15,6 @@ LL | match 42 { A => () } = note: expected type `{integer}` found tuple `(isize, isize)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-4972.stderr b/tests/ui/issues/issue-4972.stderr index 83daded7e093e..8de3909ca305e 100644 --- a/tests/ui/issues/issue-4972.stderr +++ b/tests/ui/issues/issue-4972.stderr @@ -4,6 +4,6 @@ error[E0033]: type `Box<(dyn MyTrait + 'static)>` cannot be dereferenced LL | TraitWrapper::A(box ref map) => map, | ^^^^^^^^^^^ type `Box<(dyn MyTrait + 'static)>` cannot be dereferenced -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0033`. diff --git a/tests/ui/issues/issue-49824.stderr b/tests/ui/issues/issue-49824.stderr index 14beadececb99..1c77090de27b8 100644 --- a/tests/ui/issues/issue-49824.stderr +++ b/tests/ui/issues/issue-49824.stderr @@ -19,5 +19,5 @@ help: consider adding 'move' keyword before the nested closure LL | move || { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-49919.stderr b/tests/ui/issues/issue-49919.stderr index 8098be5cc4584..597d76fc27b38 100644 --- a/tests/ui/issues/issue-49919.stderr +++ b/tests/ui/issues/issue-49919.stderr @@ -4,6 +4,6 @@ error[E0582]: binding for associated type `Output` references lifetime `'c`, whi LL | let foo: Box Fn() -> &'c T> = Box::new(move || &t); | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index ce8173169b1b3..84247a4270484 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -7,6 +7,6 @@ LL | let _result = &Some(42).as_deref(); = note: the following trait bounds were not satisfied: `{integer}: Deref` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index 943f7748696bc..bf05ab5665cba 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -7,6 +7,6 @@ LL | let _result = &mut Some(42).as_deref_mut(); = note: the following trait bounds were not satisfied: `{integer}: Deref` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index a3b9ac6775805..ac744a6d3b672 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -7,6 +7,6 @@ LL | let _result = &Ok(42).as_deref(); = note: the following trait bounds were not satisfied: `{integer}: Deref` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index aa771e4c04e85..688d2cf3486e8 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -7,6 +7,6 @@ LL | let _result = &mut Ok(42).as_deref_mut(); = note: the following trait bounds were not satisfied: `{integer}: Deref` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50403.stderr b/tests/ui/issues/issue-50403.stderr index d50befa5e326b..193d815d5195f 100644 --- a/tests/ui/issues/issue-50403.stderr +++ b/tests/ui/issues/issue-50403.stderr @@ -4,5 +4,5 @@ error: `concat_idents!()` takes 1 or more arguments LL | let x = concat_idents!(); | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-50571.stderr b/tests/ui/issues/issue-50571.stderr index f69963bb7af6c..fe47790f1ddfb 100644 --- a/tests/ui/issues/issue-50571.stderr +++ b/tests/ui/issues/issue-50571.stderr @@ -9,6 +9,6 @@ help: give this argument a name or use an underscore to ignore it LL | fn foo(_: [i32; 2]) {} | ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0642`. diff --git a/tests/ui/issues/issue-50581.stderr b/tests/ui/issues/issue-50581.stderr index 07b6df072cb44..bac1ade3b0c8f 100644 --- a/tests/ui/issues/issue-50581.stderr +++ b/tests/ui/issues/issue-50581.stderr @@ -4,6 +4,6 @@ error[E0268]: `break` outside of a loop or labeled block LL | |_: [u8; break]| (); | ^^^^^ cannot `break` outside of a loop or labeled block -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/issues/issue-50600.stderr b/tests/ui/issues/issue-50600.stderr index d285c3467ab4c..e3ae7f144c35b 100644 --- a/tests/ui/issues/issue-50600.stderr +++ b/tests/ui/issues/issue-50600.stderr @@ -7,6 +7,6 @@ LL | fn([u8; |x: u8| {}]), = note: expected type `usize` found closure `{closure@$DIR/issue-50600.rs:2:13: 2:20}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-50618.stderr b/tests/ui/issues/issue-50618.stderr index 1ac5dde66e9e5..1a3514fb715d1 100644 --- a/tests/ui/issues/issue-50618.stderr +++ b/tests/ui/issues/issue-50618.stderr @@ -6,6 +6,6 @@ LL | nonexistent: 0, | = note: available fields are: `x`, `y` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/issues/issue-5062.stderr b/tests/ui/issues/issue-5062.stderr index 3191bd3de32fe..0839ece79aaff 100644 --- a/tests/ui/issues/issue-5062.stderr +++ b/tests/ui/issues/issue-5062.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | fn main() { format!("{:?}", None::); } | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-50688.stderr b/tests/ui/issues/issue-50688.stderr index df7603d797478..873f179f56d94 100644 --- a/tests/ui/issues/issue-50688.stderr +++ b/tests/ui/issues/issue-50688.stderr @@ -7,6 +7,6 @@ LL | [1; || {}]; = note: expected type `usize` found closure `{closure@$DIR/issue-50688.rs:2:9: 2:11}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-50714-1.stderr b/tests/ui/issues/issue-50714-1.stderr index bacd09b2ae11c..7593ac3834697 100644 --- a/tests/ui/issues/issue-50714-1.stderr +++ b/tests/ui/issues/issue-50714-1.stderr @@ -4,6 +4,6 @@ error[E0647]: `#[start]` function is not allowed to have a `where` clause LL | fn start(_: isize, _: *const *const u8) -> isize where fn(&()): Eq { | ^^^^^^^^^^^^^^^^^ `#[start]` function cannot have a `where` clause -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0647`. diff --git a/tests/ui/issues/issue-50714.stderr b/tests/ui/issues/issue-50714.stderr index a11aceb6211c5..57f9769d1dd56 100644 --- a/tests/ui/issues/issue-50714.stderr +++ b/tests/ui/issues/issue-50714.stderr @@ -4,6 +4,6 @@ error[E0646]: `main` function is not allowed to have a `where` clause LL | fn main() where fn(&()): Eq {} | ^^^^^^^^^^^^^^^^^ `main` cannot have a `where` clause -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0646`. diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr index e185ecdda238f..beaea1e634ce3 100644 --- a/tests/ui/issues/issue-50781.stderr +++ b/tests/ui/issues/issue-50781.stderr @@ -20,5 +20,5 @@ note: the lint level is defined here LL | #![deny(where_clauses_object_safety)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-50802.stderr b/tests/ui/issues/issue-50802.stderr index e064fabccd045..e1b5ae3251206 100644 --- a/tests/ui/issues/issue-50802.stderr +++ b/tests/ui/issues/issue-50802.stderr @@ -4,6 +4,6 @@ error[E0590]: `break` or `continue` with no label in the condition of a `while` LL | break while continue { | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0590`. diff --git a/tests/ui/issues/issue-51022.stderr b/tests/ui/issues/issue-51022.stderr index 5e196bd4e25a5..c02c0ac93fa07 100644 --- a/tests/ui/issues/issue-51022.stderr +++ b/tests/ui/issues/issue-51022.stderr @@ -4,6 +4,6 @@ error[E0131]: `main` function is not allowed to have generic parameters LL | fn main<'a>() { } | ^^^^ `main` cannot have generic parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0131`. diff --git a/tests/ui/issues/issue-51116.stderr b/tests/ui/issues/issue-51116.stderr index c07f8735eb2c7..4839a0d46095f 100644 --- a/tests/ui/issues/issue-51116.stderr +++ b/tests/ui/issues/issue-51116.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | *tile = 0; | ^^^^^ cannot infer type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-51154.stderr b/tests/ui/issues/issue-51154.stderr index 5ae8e067807f8..b7451ea28ee97 100644 --- a/tests/ui/issues/issue-51154.stderr +++ b/tests/ui/issues/issue-51154.stderr @@ -14,6 +14,6 @@ LL | let _: Box = Box::new(|| ()); note: associated function defined here --> $SRC_DIR/alloc/src/boxed.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-5153.stderr b/tests/ui/issues/issue-5153.stderr index 93aaf4b9d8237..53c140b5b6d1b 100644 --- a/tests/ui/issues/issue-5153.stderr +++ b/tests/ui/issues/issue-5153.stderr @@ -7,6 +7,6 @@ LL | fn foo(self: Box); LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr index c92da53dbc48b..99fce1eeea6f6 100644 --- a/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr +++ b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr @@ -19,6 +19,6 @@ help: try wrapping the expression in `Ok` LL | Ok(missing_discourses()?) | +++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-51874.stderr b/tests/ui/issues/issue-51874.stderr index b39159a65390d..5be3695dd4548 100644 --- a/tests/ui/issues/issue-51874.stderr +++ b/tests/ui/issues/issue-51874.stderr @@ -9,6 +9,6 @@ help: you must specify a concrete type for this numeric value, like `f32` LL | let a = (1.0_f32).pow(1.0); | ~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0689`. diff --git a/tests/ui/issues/issue-52049.stderr b/tests/ui/issues/issue-52049.stderr index 0812976cf4092..1d8e136f217b0 100644 --- a/tests/ui/issues/issue-52049.stderr +++ b/tests/ui/issues/issue-52049.stderr @@ -7,6 +7,6 @@ LL | foo(&unpromotable(5u32)); | | creates a temporary value which is freed while still in use | argument requires that borrow lasts for `'static` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/issues/issue-52126-assign-op-invariance.stderr b/tests/ui/issues/issue-52126-assign-op-invariance.stderr index 316e755f42aac..af9553e5cf382 100644 --- a/tests/ui/issues/issue-52126-assign-op-invariance.stderr +++ b/tests/ui/issues/issue-52126-assign-op-invariance.stderr @@ -12,6 +12,6 @@ LL | acc += cnt2; LL | } | - `line` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/issues/issue-52262.stderr b/tests/ui/issues/issue-52262.stderr index ef41f078b8037..ce8e6fe2bf8dd 100644 --- a/tests/ui/issues/issue-52262.stderr +++ b/tests/ui/issues/issue-52262.stderr @@ -4,6 +4,6 @@ error[E0507]: cannot move out of `*key` which is behind a shared reference LL | String::from_utf8(*key).unwrap() | ^^^^ move occurs because `*key` has type `Vec`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-5239-1.stderr b/tests/ui/issues/issue-5239-1.stderr index f53ddb95416d1..63c2dbfc55cdd 100644 --- a/tests/ui/issues/issue-5239-1.stderr +++ b/tests/ui/issues/issue-5239-1.stderr @@ -6,6 +6,6 @@ LL | let x = |ref x: isize| { x += 1; }; | | | cannot use `+=` on type `&isize` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0368`. diff --git a/tests/ui/issues/issue-52489.stderr b/tests/ui/issues/issue-52489.stderr index 842ebd196983b..442902bd1c3fd 100644 --- a/tests/ui/issues/issue-52489.stderr +++ b/tests/ui/issues/issue-52489.stderr @@ -6,6 +6,6 @@ LL | use issue_52489; | = help: add `#![feature(issue_52489_unstable)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-52533.stderr b/tests/ui/issues/issue-52533.stderr index c764736d79878..8b56b36d39b78 100644 --- a/tests/ui/issues/issue-52533.stderr +++ b/tests/ui/issues/issue-52533.stderr @@ -7,5 +7,5 @@ LL | foo(|a, b| b) | | has type `&'1 u32` | has type `&'2 u32` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-52717.stderr b/tests/ui/issues/issue-52717.stderr index 468cdf2dcf921..ab8c37225cae6 100644 --- a/tests/ui/issues/issue-52717.stderr +++ b/tests/ui/issues/issue-52717.stderr @@ -7,6 +7,6 @@ LL | A::A { fob } => { println!("{}", fob); } | variant `A::A` does not have this field | help: a field with a similar name exists: `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0026`. diff --git a/tests/ui/issues/issue-53300.stderr b/tests/ui/issues/issue-53300.stderr index 2fedef7d23ddf..293465ecb8140 100644 --- a/tests/ui/issues/issue-53300.stderr +++ b/tests/ui/issues/issue-53300.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Wrapper` in this scope LL | fn addition() -> Wrapper {} | ^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-53348.stderr b/tests/ui/issues/issue-53348.stderr index e4cdb7e889bca..38fa98e65e138 100644 --- a/tests/ui/issues/issue-53348.stderr +++ b/tests/ui/issues/issue-53348.stderr @@ -7,6 +7,6 @@ LL | for i in v { LL | a = *i.to_string(); | ^^^^^^^^^^^^^^ expected `String`, found `str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-53498.stderr b/tests/ui/issues/issue-53498.stderr index b28fbff62b907..61a1aedf50821 100644 --- a/tests/ui/issues/issue-53498.stderr +++ b/tests/ui/issues/issue-53498.stderr @@ -7,6 +7,6 @@ LL | fn foo() {} LL | test::Foo::::foo(); | ^^^ private associated function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/issues/issue-5358-1.stderr b/tests/ui/issues/issue-5358-1.stderr index 059462a363e8e..1bb946ce4cb54 100644 --- a/tests/ui/issues/issue-5358-1.stderr +++ b/tests/ui/issues/issue-5358-1.stderr @@ -17,6 +17,6 @@ help: you might have meant to use field `0` whose type is `Either` LL | match S(Either::Left(5)).0 { | ~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-54062.stderr b/tests/ui/issues/issue-54062.stderr index 5361ee1d3455f..75eef543f272e 100644 --- a/tests/ui/issues/issue-54062.stderr +++ b/tests/ui/issues/issue-54062.stderr @@ -4,6 +4,6 @@ error[E0616]: field `inner` of struct `Mutex` is private LL | let _ = test.comps.inner.try_lock(); | ^^^^^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/issues/issue-5439.stderr b/tests/ui/issues/issue-5439.stderr index a91e4b31f4bdf..6d1d74e304558 100644 --- a/tests/ui/issues/issue-5439.stderr +++ b/tests/ui/issues/issue-5439.stderr @@ -6,6 +6,6 @@ LL | return Box::new(Foo { nonexistent: self, foo: i }); | = note: all struct fields are already assigned -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr index 516c59afb33e7..97e5990750e3c 100644 --- a/tests/ui/issues/issue-54410.stderr +++ b/tests/ui/issues/issue-54410.stderr @@ -6,6 +6,6 @@ LL | pub static mut symbol: [i8]; | = help: the trait `Sized` is not implemented for `[i8]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-55587.stderr b/tests/ui/issues/issue-55587.stderr index faf78cfe8d9f8..eec6426a29950 100644 --- a/tests/ui/issues/issue-55587.stderr +++ b/tests/ui/issues/issue-55587.stderr @@ -6,6 +6,6 @@ LL | let Path::new(); | = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/issues/issue-55731.stderr b/tests/ui/issues/issue-55731.stderr index 97fd6678c997e..2c38041642d33 100644 --- a/tests/ui/issues/issue-55731.stderr +++ b/tests/ui/issues/issue-55731.stderr @@ -10,5 +10,5 @@ LL | | }); = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr index f164fd0c5d245..f3d4c2fef94e2 100644 --- a/tests/ui/issues/issue-56806.stderr +++ b/tests/ui/issues/issue-56806.stderr @@ -7,6 +7,6 @@ LL | fn dyn_instead_of_self(self: Box); = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

    ` (where P is one of the previous types except `Self`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/issues/issue-56943.stderr b/tests/ui/issues/issue-56943.stderr index c394e620b82fe..60a2e92dc71b5 100644 --- a/tests/ui/issues/issue-56943.stderr +++ b/tests/ui/issues/issue-56943.stderr @@ -6,6 +6,6 @@ LL | let _: issue_56943::S = issue_56943::S2; | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-57271.stderr b/tests/ui/issues/issue-57271.stderr index 391e69c91fb0f..10cbb34ef5de4 100644 --- a/tests/ui/issues/issue-57271.stderr +++ b/tests/ui/issues/issue-57271.stderr @@ -22,6 +22,6 @@ LL | Base(BaseType), LL ~ Object(Box), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-57362-1.stderr b/tests/ui/issues/issue-57362-1.stderr index b10273f14bd03..79b1b131afa2c 100644 --- a/tests/ui/issues/issue-57362-1.stderr +++ b/tests/ui/issues/issue-57362-1.stderr @@ -11,6 +11,6 @@ note: `Trait` defines an item `f`, perhaps you need to implement it LL | trait Trait { | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-57362-2.stderr b/tests/ui/issues/issue-57362-2.stderr index 37beb587d2767..57477f5341ede 100644 --- a/tests/ui/issues/issue-57362-2.stderr +++ b/tests/ui/issues/issue-57362-2.stderr @@ -13,6 +13,6 @@ note: `X` defines an item `make_g`, perhaps you need to implement it LL | trait X { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-57924.stderr b/tests/ui/issues/issue-57924.stderr index 0323a4dfb8ad3..40435fd0f0a93 100644 --- a/tests/ui/issues/issue-57924.stderr +++ b/tests/ui/issues/issue-57924.stderr @@ -6,6 +6,6 @@ LL | Self::(e) | | | not allowed on self constructor -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/issues/issue-5844.mir.stderr b/tests/ui/issues/issue-5844.mir.stderr index 6134d6889ff6c..4434f5a0ff254 100644 --- a/tests/ui/issues/issue-5844.mir.stderr +++ b/tests/ui/issues/issue-5844.mir.stderr @@ -6,6 +6,6 @@ LL | issue_5844_aux::rand(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/issues/issue-5844.thir.stderr b/tests/ui/issues/issue-5844.thir.stderr index 310a2b593fe85..6074f7d0ed4ef 100644 --- a/tests/ui/issues/issue-5844.thir.stderr +++ b/tests/ui/issues/issue-5844.thir.stderr @@ -6,6 +6,6 @@ LL | issue_5844_aux::rand(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/issues/issue-58463.rs b/tests/ui/issues/issue-58463.rs index af93f76221d4e..9573c9b703aa3 100644 --- a/tests/ui/issues/issue-58463.rs +++ b/tests/ui/issues/issue-58463.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags:-C debuginfo=2 -// ignore-asmjs wasm2js does not support source maps yet fn foo() -> impl Copy { foo diff --git a/tests/ui/issues/issue-58734.stderr b/tests/ui/issues/issue-58734.stderr index d2314626d3e88..5ae1ec7cac8f8 100644 --- a/tests/ui/issues/issue-58734.stderr +++ b/tests/ui/issues/issue-58734.stderr @@ -18,6 +18,6 @@ error[E0599]: no function or associated item named `nonexistent` found for trait LL | Trait::nonexistent(()); | ^^^^^^^^^^^ function or associated item not found in `dyn Trait` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/issues/issue-5883.stderr index a3e2531b5caa4..51d9708e0fa40 100644 --- a/tests/ui/issues/issue-5883.stderr +++ b/tests/ui/issues/issue-5883.stderr @@ -15,6 +15,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | r: &dyn A + 'static | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-58857.stderr b/tests/ui/issues/issue-58857.stderr index 6aef35f0bb96a..ac70bc725e277 100644 --- a/tests/ui/issues/issue-58857.stderr +++ b/tests/ui/issues/issue-58857.stderr @@ -4,5 +4,5 @@ error: negative bounds are not supported LL | impl Conj{} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-59494.stderr b/tests/ui/issues/issue-59494.stderr index e9a4bf96741e6..960de1be299e1 100644 --- a/tests/ui/issues/issue-59494.stderr +++ b/tests/ui/issues/issue-59494.stderr @@ -13,6 +13,6 @@ note: required by a bound in `t8n` LL | fn t8n(f: impl Fn(A) -> B, g: impl Fn(A) -> C) -> impl Fn(A) -> (B, C) | ^^^^^^^^^^ required by this bound in `t8n` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-59756.stderr b/tests/ui/issues/issue-59756.stderr index 9066e57aabfe5..27c07fecd5b50 100644 --- a/tests/ui/issues/issue-59756.stderr +++ b/tests/ui/issues/issue-59756.stderr @@ -15,6 +15,6 @@ help: try using a variant of the expected enum LL | Ok(foo()?) | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-5997-enum.stderr b/tests/ui/issues/issue-5997-enum.stderr index d07258ea7a2f9..c0b3cd6de66d7 100644 --- a/tests/ui/issues/issue-5997-enum.stderr +++ b/tests/ui/issues/issue-5997-enum.stderr @@ -8,6 +8,6 @@ LL | enum E { V(Z) } | | | help: try introducing a local generic parameter here: `` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/issues/issue-5997-struct.stderr b/tests/ui/issues/issue-5997-struct.stderr index 83229e02c6ca0..670a54894b5c6 100644 --- a/tests/ui/issues/issue-5997-struct.stderr +++ b/tests/ui/issues/issue-5997-struct.stderr @@ -8,6 +8,6 @@ LL | struct S(T); | | | help: try introducing a local generic parameter here: `` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/issues/issue-60218.stderr b/tests/ui/issues/issue-60218.stderr index ae3c4d12025e3..b9317621b77ac 100644 --- a/tests/ui/issues/issue-60218.stderr +++ b/tests/ui/issues/issue-60218.stderr @@ -20,6 +20,6 @@ LL | pub fn trigger_error(iterable: I, functor: F) LL | for<'t> ::IntoIter, F> as Iterator>::Item: Foo, | ^^^ required by this bound in `trigger_error` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-61106.stderr b/tests/ui/issues/issue-61106.stderr index aa922e2682d83..f825141fa062a 100644 --- a/tests/ui/issues/issue-61106.stderr +++ b/tests/ui/issues/issue-61106.stderr @@ -16,6 +16,6 @@ help: consider borrowing here LL | foo(&x.clone()); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-61108.stderr b/tests/ui/issues/issue-61108.stderr index dd87b62664b55..d018986efecec 100644 --- a/tests/ui/issues/issue-61108.stderr +++ b/tests/ui/issues/issue-61108.stderr @@ -16,6 +16,6 @@ help: consider iterating over a slice of the `Vec`'s content to avoid movi LL | for l in &bad_letters { | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-61623.stderr b/tests/ui/issues/issue-61623.stderr index bedea3890a32e..be6e28edfc24f 100644 --- a/tests/ui/issues/issue-61623.stderr +++ b/tests/ui/issues/issue-61623.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | fn f3<'a>(x: &'a mut ((), &'a mut ())) { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-62375.stderr b/tests/ui/issues/issue-62375.stderr index f6d7968c0c405..8750fbcf4cf75 100644 --- a/tests/ui/issues/issue-62375.stderr +++ b/tests/ui/issues/issue-62375.stderr @@ -21,6 +21,6 @@ help: use parentheses to construct this tuple variant LL | a == A::Value(/* () */); | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-64430.stderr b/tests/ui/issues/issue-64430.stderr index b6b1f3a66c785..1c8e020e9cbb4 100644 --- a/tests/ui/issues/issue-64430.stderr +++ b/tests/ui/issues/issue-64430.stderr @@ -7,6 +7,6 @@ LL | pub struct Foo; LL | Foo.bar() | ^^^ method not found in `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-64559.stderr b/tests/ui/issues/issue-64559.stderr index 386ac794d7db3..0cab37553406c 100644 --- a/tests/ui/issues/issue-64559.stderr +++ b/tests/ui/issues/issue-64559.stderr @@ -17,6 +17,6 @@ help: consider iterating over a slice of the `Vec`'s content to avoid movi LL | for _val in &orig {} | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-64792-bad-unicode-ctor.stderr b/tests/ui/issues/issue-64792-bad-unicode-ctor.stderr index 2ec151d24d1c6..7fc414602d281 100644 --- a/tests/ui/issues/issue-64792-bad-unicode-ctor.stderr +++ b/tests/ui/issues/issue-64792-bad-unicode-ctor.stderr @@ -7,6 +7,6 @@ LL | LL | const Y: X = X("ö"); | ^^^^^^ help: use struct literal syntax instead: `X {}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/issues/issue-65131.stderr b/tests/ui/issues/issue-65131.stderr index e234e6da552a8..70e85b584bd22 100644 --- a/tests/ui/issues/issue-65131.stderr +++ b/tests/ui/issues/issue-65131.stderr @@ -7,6 +7,6 @@ LL | get_pair(&mut x, &mut x); | | first mutable borrow occurs here | first borrow later used by call -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/issues/issue-65230.stderr b/tests/ui/issues/issue-65230.stderr index 7ccab88948371..c959658c0ce27 100644 --- a/tests/ui/issues/issue-65230.stderr +++ b/tests/ui/issues/issue-65230.stderr @@ -13,6 +13,6 @@ LL | impl T1 for &dyn T2 {} | ^ = note: ...does not necessarily outlive the static lifetime -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr index 4af3672ef72b9..d4266814a7c47 100644 --- a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr +++ b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr @@ -23,6 +23,6 @@ help: disambiguate the method for candidate #2 LL | await::r#struct(&r#fn {}); | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr index 2b96a0fb5e554..fe104bfe44544 100644 --- a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr +++ b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr @@ -23,6 +23,6 @@ help: disambiguate the method for candidate #2 LL | r#await::r#struct(&r#fn {}); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/issues/issue-6596-2.stderr b/tests/ui/issues/issue-6596-2.stderr index 4fa73a464fbbe..e6281eb54270a 100644 --- a/tests/ui/issues/issue-6596-2.stderr +++ b/tests/ui/issues/issue-6596-2.stderr @@ -9,5 +9,5 @@ LL | g!(foo); | = note: this error originates in the macro `g` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-66706.stderr b/tests/ui/issues/issue-66706.stderr index 8a30c0cad39c5..ffdd61e7723be 100644 --- a/tests/ui/issues/issue-66706.stderr +++ b/tests/ui/issues/issue-66706.stderr @@ -24,7 +24,9 @@ error: expected identifier, found reserved identifier `_` --> $DIR/issue-66706.rs:18:26 | LL | [0; match [|f @ &ref _| () ] {} ] - | ^ expected identifier, found reserved identifier + | ----- ^ expected identifier, found reserved identifier + | | + | while parsing this `match` expression error[E0282]: type annotations needed --> $DIR/issue-66706.rs:2:11 diff --git a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr index 6fde44eaf0ced..1ea2d48b474d7 100644 --- a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr +++ b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr @@ -8,6 +8,6 @@ LL | let _ = Pin::new(Apple) == Rc::pin(Apple); found struct `Rc` = note: required for `Pin` to implement `PartialEq>>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-6738.stderr b/tests/ui/issues/issue-6738.stderr index f97d899c2d3f3..9c25c0fd9a142 100644 --- a/tests/ui/issues/issue-6738.stderr +++ b/tests/ui/issues/issue-6738.stderr @@ -11,6 +11,6 @@ help: consider restricting type parameter `T` LL | impl Foo { | +++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0368`. diff --git a/tests/ui/issues/issue-67552.polonius.stderr b/tests/ui/issues/issue-67552.polonius.stderr index 9ab77d3444d00..ca42f87e81942 100644 --- a/tests/ui/issues/issue-67552.polonius.stderr +++ b/tests/ui/issues/issue-67552.polonius.stderr @@ -13,5 +13,5 @@ LL | | T: Iterator, | |________________^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-67552.polonius/issue-67552.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-67552.stderr b/tests/ui/issues/issue-67552.stderr index f93ed67dab244..539bd45dbf1ad 100644 --- a/tests/ui/issues/issue-67552.stderr +++ b/tests/ui/issues/issue-67552.stderr @@ -13,5 +13,5 @@ LL | | T: Iterator, | |________________^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-67552/issue-67552.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-70381.stderr b/tests/ui/issues/issue-70381.stderr index 96b8e656991c2..298a1cf9e0d5f 100644 --- a/tests/ui/issues/issue-70381.stderr +++ b/tests/ui/issues/issue-70381.stderr @@ -4,5 +4,5 @@ error: 1 positional argument in format string, but no arguments were given LL | println!("\r¡{}") | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-7044.stderr b/tests/ui/issues/issue-7044.stderr index 2ad67ec23be87..9d1fb3a10ddd3 100644 --- a/tests/ui/issues/issue-7044.stderr +++ b/tests/ui/issues/issue-7044.stderr @@ -8,6 +8,6 @@ LL | struct X; | = note: `X` must be defined only once in the value namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/issues/issue-7061.stderr b/tests/ui/issues/issue-7061.stderr index a209f8a4249f1..4fca2ff39fed2 100644 --- a/tests/ui/issues/issue-7061.stderr +++ b/tests/ui/issues/issue-7061.stderr @@ -9,6 +9,6 @@ LL | fn foo(&'a mut self) -> Box { self } = note: expected struct `Box` found mutable reference `&'a mut BarStruct` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-7092.stderr b/tests/ui/issues/issue-7092.stderr index e35379fd1cfef..e2e5748674615 100644 --- a/tests/ui/issues/issue-7092.stderr +++ b/tests/ui/issues/issue-7092.stderr @@ -9,6 +9,6 @@ LL | Some(field) => = note: expected enum `Whatever` found enum `Option<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-71406.stderr b/tests/ui/issues/issue-71406.stderr index 918163b609473..cd7921f550e5d 100644 --- a/tests/ui/issues/issue-71406.stderr +++ b/tests/ui/issues/issue-71406.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: expected type, found function `channel` in `mps LL | let (tx, rx) = mpsc::channel::new(1); | ^^^^^^^ expected type, found function `channel` in `mpsc` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/issues/issue-71676-2.stderr b/tests/ui/issues/issue-71676-2.stderr index 80fb4aed1cd68..6ed318c8768b0 100644 --- a/tests/ui/issues/issue-71676-2.stderr +++ b/tests/ui/issues/issue-71676-2.stderr @@ -13,6 +13,6 @@ help: consider dereferencing LL | let _: *mut u8 = &mut ***a; | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-72076.stderr b/tests/ui/issues/issue-72076.stderr index b942cf75b06a7..a08704c907327 100644 --- a/tests/ui/issues/issue-72076.stderr +++ b/tests/ui/issues/issue-72076.stderr @@ -9,6 +9,6 @@ LL | fn f() -> Self::S {} = help: consider constraining the associated type `::S` to `()` or calling a method that returns `::S` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-7246.stderr b/tests/ui/issues/issue-7246.stderr index a9bf2bf763d57..1fb6ab14e644b 100644 --- a/tests/ui/issues/issue-7246.stderr +++ b/tests/ui/issues/issue-7246.stderr @@ -20,5 +20,5 @@ LL | if *ptr::null() {}; | = note: `#[warn(deref_nullptr)]` on by default -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/issues/issue-72839-error-overflow.stderr b/tests/ui/issues/issue-72839-error-overflow.stderr index c4b6f90ca69a3..35be632f57975 100644 --- a/tests/ui/issues/issue-72839-error-overflow.stderr +++ b/tests/ui/issues/issue-72839-error-overflow.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `missing_var` in this scope LL | if missing_var % 8 == 0 {} | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-73112.stderr b/tests/ui/issues/issue-73112.stderr index 4b8b979665cc3..c2c15ca10ce2e 100644 --- a/tests/ui/issues/issue-73112.stderr +++ b/tests/ui/issues/issue-73112.stderr @@ -10,6 +10,6 @@ note: `PageTable` has a `#[repr(align)]` attribute LL | pub struct PageTable { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0588`. diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/issues/issue-7364.stderr index 7449fe697ae9f..7371e2105de8d 100644 --- a/tests/ui/issues/issue-7364.stderr +++ b/tests/ui/issues/issue-7364.stderr @@ -11,6 +11,6 @@ note: required because it appears within the type `Box>` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL = note: shared static variables must have a type that implements `Sync` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-74236/main.stderr b/tests/ui/issues/issue-74236/main.stderr index 5cd64e48ab88b..a31d29de1d5d9 100644 --- a/tests/ui/issues/issue-74236/main.stderr +++ b/tests/ui/issues/issue-74236/main.stderr @@ -6,6 +6,6 @@ LL | let () = dep::Renamed; | | | expected `Renamed`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-75283.stderr b/tests/ui/issues/issue-75283.stderr index da3800affc05a..240d9716a5561 100644 --- a/tests/ui/issues/issue-75283.stderr +++ b/tests/ui/issues/issue-75283.stderr @@ -14,5 +14,5 @@ LL | | } = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-7607-1.stderr b/tests/ui/issues/issue-7607-1.stderr index c983026995b20..db4c8f25dbc43 100644 --- a/tests/ui/issues/issue-7607-1.stderr +++ b/tests/ui/issues/issue-7607-1.stderr @@ -7,6 +7,6 @@ LL | impl Fo { | = note: similarly named trait `Fn` defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-76077.stderr b/tests/ui/issues/issue-76077.stderr index 197ca8d5a7b25..3fef5ffce30dc 100644 --- a/tests/ui/issues/issue-76077.stderr +++ b/tests/ui/issues/issue-76077.stderr @@ -4,7 +4,7 @@ error: cannot construct `Foo` with struct literal syntax due to private fields LL | foo::Foo {}; | ^^^^^^^^ | - = note: ... and other private field `you_cant_use_this_field` that was not provided + = note: private field `you_cant_use_this_field` that was not provided -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-77218/issue-77218-2.stderr b/tests/ui/issues/issue-77218/issue-77218-2.stderr index 58c1c18f9a9b0..dfed0b6e67e33 100644 --- a/tests/ui/issues/issue-77218/issue-77218-2.stderr +++ b/tests/ui/issues/issue-77218/issue-77218-2.stderr @@ -11,6 +11,6 @@ help: you might have meant to use pattern destructuring LL | while let Some(0) = value.get(0) { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/issues/issue-77218/issue-77218.stderr b/tests/ui/issues/issue-77218/issue-77218.stderr index eda635646dfa4..e98e69314d91d 100644 --- a/tests/ui/issues/issue-77218/issue-77218.stderr +++ b/tests/ui/issues/issue-77218/issue-77218.stderr @@ -11,6 +11,6 @@ help: you might have meant to use pattern destructuring LL | while let Some(0) = value.get(0) {} | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/issues/issue-78622.stderr b/tests/ui/issues/issue-78622.stderr index 70daf8a2f1a64..985d6dde9f2aa 100644 --- a/tests/ui/issues/issue-78622.stderr +++ b/tests/ui/issues/issue-78622.stderr @@ -9,6 +9,6 @@ help: if there were a trait named `Example` with associated type `A` implemented LL | ::A:: {} | ~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/issues/issue-7867.stderr b/tests/ui/issues/issue-7867.stderr index 4fb1af344cda6..1a0cf5da8be50 100644 --- a/tests/ui/issues/issue-7867.stderr +++ b/tests/ui/issues/issue-7867.stderr @@ -12,6 +12,6 @@ LL | A::B => (), = note: expected tuple `(bool, bool)` found enum `A` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-7950.stderr b/tests/ui/issues/issue-7950.stderr index b8b0eb310cf3e..80504c070a3c4 100644 --- a/tests/ui/issues/issue-7950.stderr +++ b/tests/ui/issues/issue-7950.stderr @@ -7,6 +7,6 @@ LL | struct Foo; LL | Foo::bar(); | ^^^ function or associated item not found in `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-7970a.stderr b/tests/ui/issues/issue-7970a.stderr index b04a0eef37139..1e6bb92ea579e 100644 --- a/tests/ui/issues/issue-7970a.stderr +++ b/tests/ui/issues/issue-7970a.stderr @@ -13,5 +13,5 @@ note: while trying to match meta-variable `$fmt:expr` LL | ($fmt:expr) => (print!(concat!($fmt, "\n"))); | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-80607.stderr b/tests/ui/issues/issue-80607.stderr index 38e46683b0823..20494f319ddd0 100644 --- a/tests/ui/issues/issue-80607.stderr +++ b/tests/ui/issues/issue-80607.stderr @@ -12,6 +12,6 @@ help: `Enum::V1` is a tuple variant, use the appropriate syntax LL | Enum::V1(/* fields */) | ~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0559`. diff --git a/tests/ui/issues/issue-81584.stderr b/tests/ui/issues/issue-81584.stderr index d57f1b778df17..eb97916ad75ef 100644 --- a/tests/ui/issues/issue-81584.stderr +++ b/tests/ui/issues/issue-81584.stderr @@ -9,6 +9,6 @@ LL | .map(|y| y.iter().map(|x| x + 1)) | = help: use `.collect()` to allocate the iterator -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-83048.stderr b/tests/ui/issues/issue-83048.stderr index dade9e4695035..672bf69a7325b 100644 --- a/tests/ui/issues/issue-83048.stderr +++ b/tests/ui/issues/issue-83048.stderr @@ -4,6 +4,6 @@ error[E0268]: `break` outside of a loop or labeled block LL | break; | ^^^^^ cannot `break` outside of a loop or labeled block -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr index e02cd7fcfa9e4..d81bc3615575e 100644 --- a/tests/ui/issues/issue-87199.stderr +++ b/tests/ui/issues/issue-87199.stderr @@ -33,6 +33,6 @@ help: consider relaxing the implicit `Sized` restriction LL | fn ref_arg(_: &T) {} | ++++++++ -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-8727.polonius.stderr b/tests/ui/issues/issue-8727.polonius.stderr index 283c01b6b62a2..4fb8c2b3aff1c 100644 --- a/tests/ui/issues/issue-8727.polonius.stderr +++ b/tests/ui/issues/issue-8727.polonius.stderr @@ -22,5 +22,5 @@ LL | fn generic() { | ^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-8727.polonius/issue-8727.long-type.txt' -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/issues/issue-8727.stderr b/tests/ui/issues/issue-8727.stderr index 22332b357231b..9af598fe43f52 100644 --- a/tests/ui/issues/issue-8727.stderr +++ b/tests/ui/issues/issue-8727.stderr @@ -22,5 +22,5 @@ LL | fn generic() { | ^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-8727/issue-8727.long-type.txt' -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/issues/issue-87490.stderr b/tests/ui/issues/issue-87490.stderr index f359dd638ad93..5a4ec55833bea 100644 --- a/tests/ui/issues/issue-87490.stderr +++ b/tests/ui/issues/issue-87490.stderr @@ -9,6 +9,6 @@ LL | String::new = note: expected type `usize` found fn item `fn() -> String {String::new}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-8767.stderr b/tests/ui/issues/issue-8767.stderr index 91d99f393b61a..66141628e28d2 100644 --- a/tests/ui/issues/issue-8767.stderr +++ b/tests/ui/issues/issue-8767.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `B` in this scope LL | impl B { | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-9575.stderr b/tests/ui/issues/issue-9575.stderr index e49eac3babf8c..2f6e2687d24c9 100644 --- a/tests/ui/issues/issue-9575.stderr +++ b/tests/ui/issues/issue-9575.stderr @@ -7,6 +7,6 @@ LL | fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isiz = note: expected signature `fn(isize, *const *const u8) -> _` found signature `fn(isize, *const *const u8, *const u8) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-9814.stderr b/tests/ui/issues/issue-9814.stderr index bd9e7df4991ba..d647edaf37e2e 100644 --- a/tests/ui/issues/issue-9814.stderr +++ b/tests/ui/issues/issue-9814.stderr @@ -4,6 +4,6 @@ error[E0614]: type `Foo` cannot be dereferenced LL | let _ = *Foo::Bar(2); | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/issues/issue-98299.stderr b/tests/ui/issues/issue-98299.stderr index 4fd9f3030fc55..e99d8e5cc80a0 100644 --- a/tests/ui/issues/issue-98299.stderr +++ b/tests/ui/issues/issue-98299.stderr @@ -9,6 +9,6 @@ help: consider giving this closure parameter an explicit type, where the value o LL | SmallCString::try_from(p).map(|cstr: SmallCString| cstr); | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/iterators/bound.stderr b/tests/ui/iterators/bound.stderr index cc7ded498fc20..e5ed19f3731ca 100644 --- a/tests/ui/iterators/bound.stderr +++ b/tests/ui/iterators/bound.stderr @@ -12,6 +12,6 @@ note: required by a bound in `S` LL | struct S(I); | ^^^^^^^^ required by this bound in `S` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/collect-into-array.stderr b/tests/ui/iterators/collect-into-array.stderr index e38745cc10e1f..38e5de803ccf0 100644 --- a/tests/ui/iterators/collect-into-array.stderr +++ b/tests/ui/iterators/collect-into-array.stderr @@ -8,6 +8,6 @@ LL | let whatever: [u32; 10] = (0..10).collect(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/float_iterator_hint.stderr b/tests/ui/iterators/float_iterator_hint.stderr index bae23a1f8ff8a..c3cb00c3c684c 100644 --- a/tests/ui/iterators/float_iterator_hint.stderr +++ b/tests/ui/iterators/float_iterator_hint.stderr @@ -8,6 +8,6 @@ LL | for i in 0.2 { = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{float}` to implement `IntoIterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr index e728fec29102c..f68c596367e5e 100644 --- a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr +++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr @@ -21,6 +21,6 @@ LL | let x = Some(()).iter().map(|()| 1).sum::(); note: required by a bound in `std::iter::Iterator::sum` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr index a7d9c481a1a66..e2a80dbffdeaa 100644 --- a/tests/ui/iterators/vec-on-unimplemented.stderr +++ b/tests/ui/iterators/vec-on-unimplemented.stderr @@ -13,6 +13,6 @@ LL | vec![true, false].map(|v| !v).collect::>(); `[bool]: Iterator` which is required by `&mut [bool]: Iterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/json/json-bom-plus-crlf-multifile.stderr b/tests/ui/json/json-bom-plus-crlf-multifile.stderr index 84040e8050e96..0c6c654d60a15 100644 --- a/tests/ui/json/json-bom-plus-crlf-multifile.stderr +++ b/tests/ui/json/json-bom-plus-crlf-multifile.stderr @@ -1,4 +1,4 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -26,7 +26,7 @@ most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":622,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -54,7 +54,7 @@ most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":682,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -82,7 +82,7 @@ most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":746,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -110,5 +110,5 @@ most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types "} -{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors +{"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors "} diff --git a/tests/ui/json/json-bom-plus-crlf.stderr b/tests/ui/json/json-bom-plus-crlf.stderr index b0f450e9ecc14..31dbacb59e1ee 100644 --- a/tests/ui/json/json-bom-plus-crlf.stderr +++ b/tests/ui/json/json-bom-plus-crlf.stderr @@ -1,4 +1,4 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -26,7 +26,7 @@ most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":607,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -54,7 +54,7 @@ most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":667,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -82,7 +82,7 @@ most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":731,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types "} -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -110,5 +110,5 @@ most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types "} -{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors +{"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors "} diff --git a/tests/ui/json/json-multiple.stderr b/tests/ui/json/json-multiple.stderr index 55ccfd5fa70de..7689fb94a6c8d 100644 --- a/tests/ui/json/json-multiple.stderr +++ b/tests/ui/json/json-multiple.stderr @@ -1 +1 @@ -{"artifact":"$TEST_BUILD_DIR/json/json-multiple/libjson_multiple.rlib","emit":"link"} +{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/json/json-multiple/libjson_multiple.rlib","emit":"link"} diff --git a/tests/ui/json/json-options.stderr b/tests/ui/json/json-options.stderr index 645a26f5ad407..668fc18097f0d 100644 --- a/tests/ui/json/json-options.stderr +++ b/tests/ui/json/json-options.stderr @@ -1 +1 @@ -{"artifact":"$TEST_BUILD_DIR/json/json-options/libjson_options.rlib","emit":"link"} +{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/json/json-options/libjson_options.rlib","emit":"link"} diff --git a/tests/ui/json/json-short.stderr b/tests/ui/json/json-short.stderr index 3bd85b083d002..a18bceaa6cf10 100644 --- a/tests/ui/json/json-short.stderr +++ b/tests/ui/json/json-short.stderr @@ -1,4 +1,4 @@ -{"message":"`main` function not found in crate `json_short`","code":{"code":"E0601","explanation":"No `main` function was found in a binary crate. +{"$message_type":"diagnostic","message":"`main` function not found in crate `json_short`","code":{"code":"E0601","explanation":"No `main` function was found in a binary crate. To fix this error, add a `main` function: @@ -15,5 +15,5 @@ If you don't know the basics of Rust, you can look at the [rust-book]: https://doc.rust-lang.org/book/ "},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":62,"byte_end":62,"line_start":1,"line_end":1,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:63: error[E0601]: `main` function not found in crate `json_short` "} -{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error +{"$message_type":"diagnostic","message":"aborting due to 1 previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 1 previous error "} diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr index 8bb89d2ee215e..7cc4a95ac149d 100644 --- a/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr @@ -4,5 +4,5 @@ error: expected expression, found keyword `extern` LL | let s = extern::foo::Bar; | ^^^^^^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr index 9bf416341e8c3..f9def6fd831fd 100644 --- a/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr @@ -9,5 +9,5 @@ help: escape `extern` to use it as an identifier LL | let r#extern = 0; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-type.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-type.stderr index 20ecf6bac764c..50cac77c1b07d 100644 --- a/tests/ui/keyword/extern/keyword-extern-as-identifier-type.stderr +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-type.stderr @@ -4,5 +4,5 @@ error: expected type, found keyword `extern` LL | type A = extern::foo::bar; | ^^^^^^ expected type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/keyword/keyword-false-as-identifier.stderr b/tests/ui/keyword/keyword-false-as-identifier.stderr index 6dcfa3a481161..b8f0901bc3073 100644 --- a/tests/ui/keyword/keyword-false-as-identifier.stderr +++ b/tests/ui/keyword/keyword-false-as-identifier.stderr @@ -6,6 +6,6 @@ LL | let false = 22; | | | expected integer, found `bool` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/keyword/keyword-self-as-identifier.stderr b/tests/ui/keyword/keyword-self-as-identifier.stderr index 060e7c3eafc26..098ef8d82a04f 100644 --- a/tests/ui/keyword/keyword-self-as-identifier.stderr +++ b/tests/ui/keyword/keyword-self-as-identifier.stderr @@ -4,6 +4,6 @@ error[E0531]: cannot find unit struct, unit variant or constant `Self` in this s LL | let Self = 22; | ^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0531`. diff --git a/tests/ui/keyword/keyword-super-as-identifier.stderr b/tests/ui/keyword/keyword-super-as-identifier.stderr index 1f64f3b73d6cd..bfb27c143ff79 100644 --- a/tests/ui/keyword/keyword-super-as-identifier.stderr +++ b/tests/ui/keyword/keyword-super-as-identifier.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: there are too many leading `super` keywords LL | let super = 22; | ^^^^^ there are too many leading `super` keywords -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/keyword/keyword-super.stderr b/tests/ui/keyword/keyword-super.stderr index 0e0d67cb97b1f..bf595442c3b8b 100644 --- a/tests/ui/keyword/keyword-super.stderr +++ b/tests/ui/keyword/keyword-super.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: there are too many leading `super` keywords LL | let super: isize; | ^^^^^ there are too many leading `super` keywords -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/keyword/keyword-true-as-identifier.stderr b/tests/ui/keyword/keyword-true-as-identifier.stderr index 86f6e00064f7d..0f7a8a7e7ea8e 100644 --- a/tests/ui/keyword/keyword-true-as-identifier.stderr +++ b/tests/ui/keyword/keyword-true-as-identifier.stderr @@ -6,6 +6,6 @@ LL | let true = 22; | | | expected integer, found `bool` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/kindck/kindck-impl-type-params-2.stderr b/tests/ui/kindck/kindck-impl-type-params-2.stderr index 1d26ae51f44ab..a51232090adbb 100644 --- a/tests/ui/kindck/kindck-impl-type-params-2.stderr +++ b/tests/ui/kindck/kindck-impl-type-params-2.stderr @@ -19,6 +19,6 @@ note: required by a bound in `take_param` LL | fn take_param(foo: &T) { } | ^^^ required by this bound in `take_param` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-nonsendable-1.stderr b/tests/ui/kindck/kindck-nonsendable-1.stderr index 077004ae76163..8bb784d1d4966 100644 --- a/tests/ui/kindck/kindck-nonsendable-1.stderr +++ b/tests/ui/kindck/kindck-nonsendable-1.stderr @@ -20,6 +20,6 @@ note: required by a bound in `bar` LL | fn bar(_: F) { } | ^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-owned.stderr b/tests/ui/kindck/kindck-send-owned.stderr index dc1bb6206afcf..860a9391bbb08 100644 --- a/tests/ui/kindck/kindck-send-owned.stderr +++ b/tests/ui/kindck/kindck-send-owned.stderr @@ -14,6 +14,6 @@ note: required by a bound in `assert_send` LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lang-items/bad-add-impl.stderr b/tests/ui/lang-items/bad-add-impl.stderr index 3143729f99bb0..c5ad9ff2a0856 100644 --- a/tests/ui/lang-items/bad-add-impl.stderr +++ b/tests/ui/lang-items/bad-add-impl.stderr @@ -6,6 +6,6 @@ LL | 1u32 + 1u32; | | | u32 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/lang-items/issue-19660.stderr b/tests/ui/lang-items/issue-19660.stderr index f5d903f38eb99..e5a8a143d0301 100644 --- a/tests/ui/lang-items/issue-19660.stderr +++ b/tests/ui/lang-items/issue-19660.stderr @@ -1,4 +1,4 @@ error: requires `copy` lang_item -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lang-items/issue-86238.stderr b/tests/ui/lang-items/issue-86238.stderr index c6e811a94fe20..b492904bcc73a 100644 --- a/tests/ui/lang-items/issue-86238.stderr +++ b/tests/ui/lang-items/issue-86238.stderr @@ -6,5 +6,5 @@ LL | one() | = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lang-items/lang-item-missing.stderr b/tests/ui/lang-items/lang-item-missing.stderr index f7516c7d377da..08e679a7c559a 100644 --- a/tests/ui/lang-items/lang-item-missing.stderr +++ b/tests/ui/lang-items/lang-item-missing.stderr @@ -1,4 +1,4 @@ error: requires `sized` lang_item -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lang-items/missing-clone-for-suggestion.stderr b/tests/ui/lang-items/missing-clone-for-suggestion.stderr index 35783a1be78ad..0187f965b5c00 100644 --- a/tests/ui/lang-items/missing-clone-for-suggestion.stderr +++ b/tests/ui/lang-items/missing-clone-for-suggestion.stderr @@ -16,6 +16,6 @@ LL | fn g(x: T) {} | | | in this function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/lang-items/required-lang-item.stderr b/tests/ui/lang-items/required-lang-item.stderr index 83764a91ac780..bb53d336bb29d 100644 --- a/tests/ui/lang-items/required-lang-item.stderr +++ b/tests/ui/lang-items/required-lang-item.stderr @@ -1,4 +1,4 @@ error: requires `start` lang_item -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lang-items/start_lang_item_args.argc.stderr b/tests/ui/lang-items/start_lang_item_args.argc.stderr index 66d4397a2935a..cd7361255eb91 100644 --- a/tests/ui/lang-items/start_lang_item_args.argc.stderr +++ b/tests/ui/lang-items/start_lang_item_args.argc.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: = note: expected signature `fn(fn() -> _, isize, _, _) -> _` found signature `fn(fn() -> _, i8, _, _) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.argv.stderr b/tests/ui/lang-items/start_lang_item_args.argv.stderr index 53d776cd846a4..1a5905ab8e602 100644 --- a/tests/ui/lang-items/start_lang_item_args.argv.stderr +++ b/tests/ui/lang-items/start_lang_item_args.argv.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isi = note: expected signature `fn(fn() -> _, _, *const *const u8, _) -> _` found signature `fn(fn() -> _, _, u8, _) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr index 7d002e090b5a8..c61ace3cd628e 100644 --- a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr +++ b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _si = note: expected signature `fn(fn() -> _, _, *const *const u8, _) -> _` found signature `fn(fn() -> _, _, *const *const usize, _) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.main_args.stderr b/tests/ui/lang-items/start_lang_item_args.main_args.stderr index 91994b9d74296..ef943d6b3dba1 100644 --- a/tests/ui/lang-items/start_lang_item_args.main_args.stderr +++ b/tests/ui/lang-items/start_lang_item_args.main_args.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _si = note: expected signature `fn(fn() -> _, _, _, _) -> _` found signature `fn(fn(i32) -> _, _, _, _) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr index 25570f9605370..00395a05d33f7 100644 --- a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr @@ -9,6 +9,6 @@ LL | fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sig = note: expected signature `fn(fn() -> T, _, _, _) -> _` found signature `fn(fn() -> u16, _, _, _) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr index 87940d05e785f..193f25bab05b1 100644 --- a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr +++ b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8 = note: expected signature `fn(fn() -> T, _, _, _) -> _` found signature `fn(u64, _, _, _) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr index 5363871e20223..56b787d2ae38f 100644 --- a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr +++ b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr @@ -7,6 +7,6 @@ LL | fn start() -> isize { = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _` found signature `fn() -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr index 14bfcc3d04d9c..aa1b1b73baefb 100644 --- a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpi = note: expected signature `fn(fn() -> _, _, _, _) -> isize` found signature `fn(fn() -> _, _, _, _)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr index f873f7614bdce..98814dcd24a7c 100644 --- a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr +++ b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isi = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _` found signature `fn(fn() -> T, isize, *const *const u8) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr index 280d423bd7e1b..e0a8496dba99b 100644 --- a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr +++ b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpi = note: expected signature `fn(fn() -> _, _, _, u8) -> _` found signature `fn(fn() -> _, _, _, i64) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr index 4e4f8a5cdb39e..4437b0fdcfb18 100644 --- a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr +++ b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpi = note: expected signature `fn(fn() -> _, _, _, _) -> isize` found signature `fn(fn() -> _, _, _, _) -> u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr index 085d4b1f238e3..8570d96fc6219 100644 --- a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr +++ b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr @@ -13,6 +13,6 @@ LL | | ) -> isize { = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _` found signature `fn(fn() -> T, isize, *const *const u8, u8, ()) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.stderr b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr index ff55a1365e458..bb0583dfde056 100644 --- a/tests/ui/lang-items/start_lang_item_with_target_feature.stderr +++ b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr @@ -7,5 +7,5 @@ LL | LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { | ------------------------------------------------------------------------------------------- `start` language item function is not allowed to have `#[target_feature]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/late-bound-lifetimes/issue-80618.stderr b/tests/ui/late-bound-lifetimes/issue-80618.stderr index cf7423fc16feb..28ea61f38a3ec 100644 --- a/tests/ui/late-bound-lifetimes/issue-80618.stderr +++ b/tests/ui/late-bound-lifetimes/issue-80618.stderr @@ -10,6 +10,6 @@ note: the late bound lifetime parameter is introduced here LL | fn foo<'a>(x: &'a str) -> &'a str { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0794`. diff --git a/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr b/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr index de58a014ee8fa..1b8f1c3fd6fae 100644 --- a/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr +++ b/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr @@ -12,6 +12,6 @@ note: type alias defined here, with 1 lifetime parameter: `'a` LL | type Alias<'a, T> = >::Assoc; | ^^^^^ -- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/late-bound-lifetimes/predicate-is-global.rs b/tests/ui/late-bound-lifetimes/predicate-is-global.rs new file mode 100644 index 0000000000000..be017a3f94fb4 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/predicate-is-global.rs @@ -0,0 +1,40 @@ +// check-pass + +trait Foo { + type Assoc; + + fn do_it(_: &Self::Assoc) + where + for<'a> Self: Baz<'a>; +} + +trait Baz<'a>: Foo {} + +impl Foo for () { + type Assoc = Inherent; + + // Ensure that the `for<'a> Self: Baz<'a>` predicate, which has + // a supertrait `for<'a> Self: Foo`, does not cause us to fail + // to normalize `Self::Assoc`. + fn do_it(x: &Self::Assoc) + where + for<'a> Self: Baz<'a>, + { + x.inherent(); + } +} + +struct Inherent; +impl Inherent { + fn inherent(&self) {} +} + +// This trivial bound doesn't hold, but the unused lifetime tripped up that check after #117589, and +// showed up in its crater results (in `soa-derive 0.13.0`). +fn do_it() +where + for<'a> Inherent: Clone, +{ +} + +fn main() {} diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr index ee2c5ab7e39cc..d17564a1ecaef 100644 --- a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr +++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Missing` in this scope LL | Missing: Trait, | ^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/layout/malformed-unsized-type-in-union.stderr b/tests/ui/layout/malformed-unsized-type-in-union.stderr index cbb8d6af38ad1..ad4f0cda19e5c 100644 --- a/tests/ui/layout/malformed-unsized-type-in-union.stderr +++ b/tests/ui/layout/malformed-unsized-type-in-union.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Missing` in this scope LL | union W { s: dyn Iterator } | ^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/layout/too-big-with-padding.stderr b/tests/ui/layout/too-big-with-padding.stderr index 5cc854adce0d3..71309788dac86 100644 --- a/tests/ui/layout/too-big-with-padding.stderr +++ b/tests/ui/layout/too-big-with-padding.stderr @@ -4,5 +4,5 @@ error: values of the type `Example` are too big for the current architecture LL | pub fn lib(_x: Example) {} | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/layout/transmute-to-tail-with-err.stderr b/tests/ui/layout/transmute-to-tail-with-err.stderr index 97ab59c398a3b..433c6b38d0b42 100644 --- a/tests/ui/layout/transmute-to-tail-with-err.stderr +++ b/tests/ui/layout/transmute-to-tail-with-err.stderr @@ -9,6 +9,6 @@ help: you might be missing a type parameter LL | struct Bar(Box>); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/lazy-type-alias-impl-trait/branches.stderr b/tests/ui/lazy-type-alias-impl-trait/branches.stderr index 0b206f31e7b6e..9e93762277518 100644 --- a/tests/ui/lazy-type-alias-impl-trait/branches.stderr +++ b/tests/ui/lazy-type-alias-impl-trait/branches.stderr @@ -8,6 +8,6 @@ LL | std::iter::empty().collect() note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr index 3b216ac1581f4..fdc5bae153790 100644 --- a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr +++ b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr @@ -10,6 +10,6 @@ note: required by a bound in `lazy::Alias` LL | pub type Alias = Option; | ^^^^ required by this bound in `Alias` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr index 3b216ac1581f4..fdc5bae153790 100644 --- a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr +++ b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr @@ -10,6 +10,6 @@ note: required by a bound in `lazy::Alias` LL | pub type Alias = Option; | ^^^^ required by this bound in `Alias` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias/leading-where-clause.stderr b/tests/ui/lazy-type-alias/leading-where-clause.stderr index 8ddf0ce6c6558..6b0613787e8bf 100644 --- a/tests/ui/lazy-type-alias/leading-where-clause.stderr +++ b/tests/ui/lazy-type-alias/leading-where-clause.stderr @@ -12,5 +12,5 @@ LL + LL ~ = T where String: From; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lazy-type-alias/trailing-where-clause.stderr b/tests/ui/lazy-type-alias/trailing-where-clause.stderr index 193f80b23d3cb..baf4215bbf788 100644 --- a/tests/ui/lazy-type-alias/trailing-where-clause.stderr +++ b/tests/ui/lazy-type-alias/trailing-where-clause.stderr @@ -20,6 +20,6 @@ LL | where LL | String: From; | ^^^^^^^ required by this bound in `Alias` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr index d022f82514075..bd8095224a720 100644 --- a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr +++ b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `T` LL | type Alias = ::Output; | +++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/let-else/accidental-if.stderr b/tests/ui/let-else/accidental-if.stderr index 57e5259173078..12948e956cace 100644 --- a/tests/ui/let-else/accidental-if.stderr +++ b/tests/ui/let-else/accidental-if.stderr @@ -15,5 +15,5 @@ LL - if let Some(y) = x else { LL + let Some(y) = x else { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/let-else/issue-94176.stderr b/tests/ui/let-else/issue-94176.stderr index 6a015aced6f4e..1ff5000e7a3d0 100644 --- a/tests/ui/let-else/issue-94176.stderr +++ b/tests/ui/let-else/issue-94176.stderr @@ -14,6 +14,6 @@ LL ~ println!("Foo"); LL + a | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/let-else/let-else-allow-unused.stderr b/tests/ui/let-else/let-else-allow-unused.stderr index 05b8a9169fb70..2cad1be8c463b 100644 --- a/tests/ui/let-else/let-else-allow-unused.stderr +++ b/tests/ui/let-else/let-else-allow-unused.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #[deny(unused_variables)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/let-else/let-else-binding-explicit-mut-borrow.stderr b/tests/ui/let-else/let-else-binding-explicit-mut-borrow.stderr index 023fab8fe4a3d..e4d6534c51534 100644 --- a/tests/ui/let-else/let-else-binding-explicit-mut-borrow.stderr +++ b/tests/ui/let-else/let-else-binding-explicit-mut-borrow.stderr @@ -4,6 +4,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | let Some(n): &mut Option = &mut &Some(5i32) else { | ^^^^^^^^^^^^^^^^ cannot borrow as mutable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/let-else/let-else-binding-immutable.stderr b/tests/ui/let-else/let-else-binding-immutable.stderr index dd1365a9ef078..0f854493b7e47 100644 --- a/tests/ui/let-else/let-else-binding-immutable.stderr +++ b/tests/ui/let-else/let-else-binding-immutable.stderr @@ -4,6 +4,6 @@ error[E0594]: cannot assign to `*x`, which is behind a `&` reference LL | *x += 1; | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/let-else/let-else-if.stderr b/tests/ui/let-else/let-else-if.stderr index c63fd61c5dec9..c8058ec669243 100644 --- a/tests/ui/let-else/let-else-if.stderr +++ b/tests/ui/let-else/let-else-if.stderr @@ -13,5 +13,5 @@ LL | return; LL ~ } }; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/let-else/let-else-no-double-error.stderr b/tests/ui/let-else/let-else-no-double-error.stderr index 941e588b1768d..05668a23138ea 100644 --- a/tests/ui/let-else/let-else-no-double-error.stderr +++ b/tests/ui/let-else/let-else-no-double-error.stderr @@ -4,6 +4,6 @@ error[E0599]: no associated item named `XXX` found for type `u32` in the current LL | let u32::XXX = foo else { return }; | ^^^ associated item not found in `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/let-else/let-else-scope.stderr b/tests/ui/let-else/let-else-scope.stderr index 3b4f0982940e8..335ee3dfb1ea7 100644 --- a/tests/ui/let-else/let-else-scope.stderr +++ b/tests/ui/let-else/let-else-scope.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `x` in this scope LL | panic!("{}", x); | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/let-else/let-else-slicing-error.stderr b/tests/ui/let-else/let-else-slicing-error.stderr index 064025e0345b7..73c357dd5d462 100644 --- a/tests/ui/let-else/let-else-slicing-error.stderr +++ b/tests/ui/let-else/let-else-slicing-error.stderr @@ -6,6 +6,6 @@ LL | let [x, y] = nums else { | | | pattern cannot match with input type `Vec<{integer}>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/let-else/let-else-then-diverge.stderr b/tests/ui/let-else/let-else-then-diverge.stderr index 470a11d4769bc..eda0025afa5ed 100644 --- a/tests/ui/let-else/let-else-then-diverge.stderr +++ b/tests/ui/let-else/let-else-then-diverge.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_variables)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lexer/lex-bad-char-literals-2.stderr b/tests/ui/lexer/lex-bad-char-literals-2.stderr index c2b19a7ad5f2d..1518a37ab53f3 100644 --- a/tests/ui/lexer/lex-bad-char-literals-2.stderr +++ b/tests/ui/lexer/lex-bad-char-literals-2.stderr @@ -9,5 +9,5 @@ help: if you meant to write a `str` literal, use double quotes LL | "nope" | ~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lexer/lex-bad-char-literals-4.stderr b/tests/ui/lexer/lex-bad-char-literals-4.stderr index fec4421c48a7c..1a1dd85e606e4 100644 --- a/tests/ui/lexer/lex-bad-char-literals-4.stderr +++ b/tests/ui/lexer/lex-bad-char-literals-4.stderr @@ -4,6 +4,6 @@ error[E0762]: unterminated character literal LL | '● | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0762`. diff --git a/tests/ui/lexer/lex-bad-token.stderr b/tests/ui/lexer/lex-bad-token.stderr index 43c43721b19f2..6ce309ca20559 100644 --- a/tests/ui/lexer/lex-bad-token.stderr +++ b/tests/ui/lexer/lex-bad-token.stderr @@ -4,5 +4,5 @@ error: unknown start of token: \u{25cf} LL | ● | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lexer/lex-stray-backslash.stderr b/tests/ui/lexer/lex-stray-backslash.stderr index 06dc0f2b537ba..6173a4b1d51fa 100644 --- a/tests/ui/lexer/lex-stray-backslash.stderr +++ b/tests/ui/lexer/lex-stray-backslash.stderr @@ -4,5 +4,5 @@ error: unknown start of token: \ LL | \ | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lexer/unterminated-comment.stderr b/tests/ui/lexer/unterminated-comment.stderr index c513fafeeb35c..ea65bffd10368 100644 --- a/tests/ui/lexer/unterminated-comment.stderr +++ b/tests/ui/lexer/unterminated-comment.stderr @@ -4,6 +4,6 @@ error[E0758]: unterminated block comment LL | /* | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0758`. diff --git a/tests/ui/lexer/unterminated-nested-comment.stderr b/tests/ui/lexer/unterminated-nested-comment.stderr index 3653e76c9cbda..9117b689c94e3 100644 --- a/tests/ui/lexer/unterminated-nested-comment.stderr +++ b/tests/ui/lexer/unterminated-nested-comment.stderr @@ -16,6 +16,6 @@ LL | | */ | | | ...and last nested comment terminates here. -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0758`. diff --git a/tests/ui/lifetimes/borrowck-let-suggestion.stderr b/tests/ui/lifetimes/borrowck-let-suggestion.stderr index 621196647644a..cca7f52957e4c 100644 --- a/tests/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/tests/ui/lifetimes/borrowck-let-suggestion.stderr @@ -20,6 +20,6 @@ LL ~ let binding = vec![1]; LL ~ let mut x = binding.iter(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/lifetimes/conflicting-bounds.stderr b/tests/ui/lifetimes/conflicting-bounds.stderr index 42aa393667dc2..cd66eb5e3fea6 100644 --- a/tests/ui/lifetimes/conflicting-bounds.stderr +++ b/tests/ui/lifetimes/conflicting-bounds.stderr @@ -9,6 +9,6 @@ LL | pub trait Gen<'source> { LL | Self: for<'s> Gen<'s, Output = T>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/lifetimes/copy_modulo_regions.stderr b/tests/ui/lifetimes/copy_modulo_regions.stderr index 87dbb64abd1a6..310ddb21647f6 100644 --- a/tests/ui/lifetimes/copy_modulo_regions.stderr +++ b/tests/ui/lifetimes/copy_modulo_regions.stderr @@ -10,5 +10,5 @@ LL | [mk_foo::<'a>(); 100] = note: the struct `Foo<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.stderr b/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.stderr index 808d8bb905885..24bb9e2ef7d63 100644 --- a/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.stderr +++ b/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.stderr @@ -11,5 +11,5 @@ help: to declare that the trait object captures data from argument `self`, you c LL | type BoxedGreeter<'a> = (Box, Box); | ++++ ++++ ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index 54ecd35ed6acd..f1fa5a5986060 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | thing(f); | ^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>` - found trait `for<'a> FnOnce<(&u32, &'a u32, u32)>` + = note: expected trait `for<'a, 'b> FnOnce(&'a u32, &'b u32, u32)` + found trait `for<'a> FnOnce(&u32, &'a u32, u32)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-105675.rs:4:13 | @@ -27,8 +27,8 @@ error[E0308]: mismatched types LL | thing(f); | ^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>` - found trait `for<'a> FnOnce<(&u32, &'a u32, u32)>` + = note: expected trait `for<'a, 'b> FnOnce(&'a u32, &'b u32, u32)` + found trait `for<'a> FnOnce(&u32, &'a u32, u32)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-105675.rs:4:13 | @@ -46,8 +46,8 @@ error[E0308]: mismatched types LL | thing(f); | ^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>` - found trait `FnOnce<(&u32, &u32, u32)>` + = note: expected trait `for<'a, 'b> FnOnce(&'a u32, &'b u32, u32)` + found trait `FnOnce(&u32, &u32, u32)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-105675.rs:8:13 | @@ -69,8 +69,8 @@ error[E0308]: mismatched types LL | thing(f); | ^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> FnOnce<(&'a u32, &'b u32, u32)>` - found trait `FnOnce<(&u32, &u32, u32)>` + = note: expected trait `for<'a, 'b> FnOnce(&'a u32, &'b u32, u32)` + found trait `FnOnce(&u32, &u32, u32)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-105675.rs:8:13 | diff --git a/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr index c235c31809fb7..9bc2263ab3dd4 100644 --- a/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr +++ b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr @@ -4,5 +4,5 @@ error: unexpected default lifetime parameter LL | pub struct DefaultLifetime<'a, 'b = 'static> { | ^^^^^^^^^ lifetime parameters cannot have default values -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr index 535073d6ebb0f..fb1c7cf7ad35b 100644 --- a/tests/ui/lifetimes/issue-17728.stderr +++ b/tests/ui/lifetimes/issue-17728.stderr @@ -16,6 +16,6 @@ LL | | } = note: expected enum `RoomDirection` found enum `Option<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/issue-34979.stderr b/tests/ui/lifetimes/issue-34979.stderr index 3d4208031cd06..0877f1548a842 100644 --- a/tests/ui/lifetimes/issue-34979.stderr +++ b/tests/ui/lifetimes/issue-34979.stderr @@ -15,6 +15,6 @@ LL | &'a (): Foo, LL | &'static (): Foo; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr index 02ca10b2eb67c..ec4aea623911a 100644 --- a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr +++ b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr @@ -5,7 +5,7 @@ LL | beta: [(); foo::<&'a ()>()], | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic `Self` types are currently not permitted in anonymous constants --> $DIR/issue-64173-unused-lifetimes.rs:4:28 diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 75fd87b3fe9b3..86a4ac4132e44 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -31,8 +31,8 @@ error[E0308]: mismatched types LL | take_foo(|a| a); | ^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a> Fn<(&'a i32,)>` - found trait `Fn<(&i32,)>` + = note: expected trait `for<'a> Fn(&'a i32)` + found trait `Fn(&i32)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-79187-2.rs:8:14 | diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index 209f2b7b7398a..14bdfe75c08be 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | thing(f); | ^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a> FnOnce<(&'a u32,)>` - found trait `FnOnce<(&u32,)>` + = note: expected trait `for<'a> FnOnce(&'a u32)` + found trait `FnOnce(&u32)` note: this closure does not fulfill the lifetime requirements --> $DIR/issue-79187.rs:4:13 | diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr index f7bdee6336e2d..d99ea6a0c309f 100644 --- a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr +++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | fn bar(foo: Foo) {} | ^^^^^^^^^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/lifetimes/issue-91763.stderr b/tests/ui/lifetimes/issue-91763.stderr index 6ccf008c003e4..f7293ed809c3a 100644 --- a/tests/ui/lifetimes/issue-91763.stderr +++ b/tests/ui/lifetimes/issue-91763.stderr @@ -14,5 +14,5 @@ help: indicate the anonymous lifetime LL | fn f() -> Ptr<'_>; | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr index 421ab3fcf4ebb..1664466df3cb3 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait Future { | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr b/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr index 63d00875dd330..af22078aff590 100644 --- a/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr +++ b/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr @@ -7,6 +7,6 @@ LL | fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 { LL | &*x | ^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr index 64aa8361cd5ea..e202c31214d37 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr @@ -7,6 +7,6 @@ LL | fn bar(&self, other: Foo) -> Foo<'a> { LL | other | ^^^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr index b40481ecdc401..5518ded0106d9 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -6,6 +6,6 @@ LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { LL | if x > y { x } else { y } | ^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr index 194fd95891eb0..c689fa9884a76 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -6,6 +6,6 @@ LL | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { LL | if x > y { x } else { y } | ^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr index 64f4bd0fc7061..3da50cfbb1d08 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -6,6 +6,6 @@ LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { LL | if x > y { x } else { y } | ^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 961f9de6614af..6dda9e61a79ca 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -7,6 +7,6 @@ LL | LL | if true { &self.field } else { x } | ^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr index 5bb763813322d..5827b2fe695a6 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr @@ -9,5 +9,5 @@ LL | LL | if x > y { x } else { y } | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index 29a70695710f7..1df0776a51b58 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -6,6 +6,6 @@ LL | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { LL | if x > y { x } else { y } | ^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr index 6fd7f67d15ea6..da454b8fd8637 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -9,5 +9,5 @@ LL | LL | x | ^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr index 2687266e09862..a1dfff883a004 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr @@ -9,5 +9,5 @@ LL | LL | if true { x } else { self } | ^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index bcc3e9510ac97..62b0a8a04bf79 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -10,6 +10,6 @@ help: consider introducing a named lifetime parameter LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { | ++++ ++ ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr index 90d4754ebab82..25a2f4b96f40d 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -6,6 +6,6 @@ LL | fn foo<'a>(x: Ref, y: &mut Vec>) { LL | y.push(x); | ^^^^^^^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr index a03e16b3b7919..e2725977d8370 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr @@ -7,6 +7,6 @@ LL | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T) LL | x.push(y); | ^^^^^^^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr index 487b34e3d18f4..1025581d5acf5 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -6,6 +6,6 @@ LL | fn foo<'a>(x: &mut Vec>, y: Ref) { LL | x.push(y); | ^^^^^^^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr index 1622ce4229052..df1d03d517032 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -8,5 +8,5 @@ LL | fn foo(x: &mut Vec>, y: Ref) { LL | x.push(y); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr index 99fab4631a216..cace80272f5b5 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr @@ -11,5 +11,5 @@ LL | x.push(z); | = help: consider adding the following bound: `'c: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr index 52c5752f6ea1e..4a981e4de604d 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -11,5 +11,5 @@ LL | a.push(b); | = help: consider adding the following bound: `'c: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr index e90c81ee3e1af..2bd047113bca0 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -11,5 +11,5 @@ LL | Vec::push(a, b); | = help: consider adding the following bound: `'c: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr index 5a23f1e0e9d99..30083b5ef5462 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -13,5 +13,5 @@ help: consider introducing a named lifetime parameter LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) { | ++++ ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr index 4c0ffe5c0901a..4f1cb1e797221 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr @@ -8,5 +8,5 @@ LL | fn foo(mut x: Ref, y: Ref) { LL | x.b = y.b; | ^^^^^^^^^ assignment requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr index 97c665347f6ec..3a1947973b551 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr @@ -9,5 +9,5 @@ LL | fn foo(mut x: Ref) { LL | x.a = x.b; | ^^^^^^^^^ assignment requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr index b3d0bc2b882f9..352619c0ffc3f 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr @@ -11,5 +11,5 @@ LL | x.push(y); | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr index fbe98a4263ec1..16cf009ee48bc 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr @@ -10,5 +10,5 @@ LL | x.push(y); | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr index 9630729d0ee6a..c778f77366abc 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr @@ -8,5 +8,5 @@ LL | fn foo(mut x: Vec, y: Ref) { LL | x.push(y); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr index 1e24032fc1ce2..080eb43cecbc4 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr @@ -10,5 +10,5 @@ LL | x.push(y); | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr index 79e7e8e157d95..60ca416845515 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr @@ -8,5 +8,5 @@ LL | fn foo(mut y: Ref, x: &u32) { LL | y.b = x; | ^^^^^^^ assignment requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr index 53615fd1aba69..98e490c3827b5 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr @@ -8,5 +8,5 @@ LL | fn foo(mut y: Ref, x: &u32) { LL | y.b = x; | ^^^^^^^ assignment requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr index 6ff4411673756..ea1cc1f18a4dc 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr @@ -8,5 +8,5 @@ LL | fn foo(mut x: Ref, y: &u32) { LL | x.b = y; | ^^^^^^^ assignment requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr index 9ff5e42d732cc..e934ce7c040ef 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr @@ -13,5 +13,5 @@ help: consider introducing a named lifetime parameter and update trait if needed LL | fn foo<'a>(&'a self, x: &'a i32) -> &i32 { | ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr index e4c855e11fe28..dde271d100c58 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr @@ -13,5 +13,5 @@ help: consider introducing a named lifetime parameter and update trait if needed LL | fn foo<'a>(&'a self, x: &'a Foo) -> &Foo { | ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr index 9661f1e5144b4..420cfa6b569b6 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr @@ -13,5 +13,5 @@ help: consider introducing a named lifetime parameter and update trait if needed LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { | ++++ ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr index ec9fac0c288e0..875d22576e58c 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr @@ -13,5 +13,5 @@ help: consider introducing a named lifetime parameter LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { | ++++ ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index dbc587dd004a4..677f918fe932e 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -18,8 +18,8 @@ error[E0308]: mismatched types LL | f(data, identity) | ^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a> Fn<(&'a T,)>` - found trait `Fn<(&T,)>` + = note: expected trait `for<'a> Fn(&'a T)` + found trait `Fn(&T)` note: the lifetime requirement is introduced here --> $DIR/issue_74400.rs:8:34 | diff --git a/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr index 9c61d5a0c25e1..917d204367ffe 100644 --- a/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -12,5 +12,5 @@ LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/nested-binder-print.stderr b/tests/ui/lifetimes/nested-binder-print.stderr index 32dd896932d2e..fb93b7855a4c8 100644 --- a/tests/ui/lifetimes/nested-binder-print.stderr +++ b/tests/ui/lifetimes/nested-binder-print.stderr @@ -9,6 +9,6 @@ LL | let x: u32 = y; = note: expected type `u32` found fn pointer `for<'a> fn(for<'b> fn(TwoLt<'b, 'a>))` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/re-empty-in-error.stderr b/tests/ui/lifetimes/re-empty-in-error.stderr index c35d8ecec5e2d..554bcb5451fc0 100644 --- a/tests/ui/lifetimes/re-empty-in-error.stderr +++ b/tests/ui/lifetimes/re-empty-in-error.stderr @@ -6,5 +6,5 @@ LL | foo(&10); | = note: could not prove `for<'b> &'b (): 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr index 79df2c8dfbcc8..a491de8ac1e33 100644 --- a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr +++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr @@ -11,6 +11,6 @@ help: consider adding an explicit lifetime bound LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { | +++ ++++ ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr b/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr index 4399045098d0f..3f457da1b4746 100644 --- a/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr +++ b/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr @@ -16,6 +16,6 @@ help: to force the closure to take ownership of `a` (and any other referenced va LL | [0].iter().flat_map(|a| [0].iter().map(move |_| &a)); | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/limits/huge-array-simple-32.stderr b/tests/ui/limits/huge-array-simple-32.stderr index d1e4e6295a911..1b86b02297f34 100644 --- a/tests/ui/limits/huge-array-simple-32.stderr +++ b/tests/ui/limits/huge-array-simple-32.stderr @@ -4,5 +4,5 @@ error: values of the type `[u8; 2147516416]` are too big for the current archite LL | let _fat: [u8; (1<<31)+(1<<15)] = | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/huge-array-simple-64.stderr b/tests/ui/limits/huge-array-simple-64.stderr index 5791b6439c935..8d395c3c6a959 100644 --- a/tests/ui/limits/huge-array-simple-64.stderr +++ b/tests/ui/limits/huge-array-simple-64.stderr @@ -4,5 +4,5 @@ error: values of the type `[u8; 2305843011361177600]` are too big for the curren LL | let _fat: [u8; (1<<61)+(1<<31)] = | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/huge-array.stderr b/tests/ui/limits/huge-array.stderr index 24adb33b08891..2ebaf17a138cd 100644 --- a/tests/ui/limits/huge-array.stderr +++ b/tests/ui/limits/huge-array.stderr @@ -4,5 +4,5 @@ error: values of the type `[[u8; 1518599999]; 1518600000]` are too big for the c LL | let s: [T; 1518600000] = [t; 1518600000]; | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.stderr index 5e2bda9be5043..fcd40607af461 100644 --- a/tests/ui/limits/huge-enum.stderr +++ b/tests/ui/limits/huge-enum.stderr @@ -4,5 +4,5 @@ error: values of the type `Option` are too big for the current architectur LL | let big: BIG = None; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/huge-struct.stderr b/tests/ui/limits/huge-struct.stderr index ce14bc5b88869..782db20c7f345 100644 --- a/tests/ui/limits/huge-struct.stderr +++ b/tests/ui/limits/huge-struct.stderr @@ -4,5 +4,5 @@ error: values of the type `SXX>>` are too big for the current archi LL | let fat: Option>>> = None; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/issue-15919-32.stderr b/tests/ui/limits/issue-15919-32.stderr index f9e48a52cb9da..abd65ff3c9eb7 100644 --- a/tests/ui/limits/issue-15919-32.stderr +++ b/tests/ui/limits/issue-15919-32.stderr @@ -4,5 +4,5 @@ error: values of the type `[usize; usize::MAX]` are too big for the current arch LL | let x = [0usize; 0xffff_ffff]; | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/issue-15919-64.stderr b/tests/ui/limits/issue-15919-64.stderr index 167272890aaad..d1f0cc39c1884 100644 --- a/tests/ui/limits/issue-15919-64.stderr +++ b/tests/ui/limits/issue-15919-64.stderr @@ -4,5 +4,5 @@ error: values of the type `[usize; usize::MAX]` are too big for the current arch LL | let x = [0usize; 0xffff_ffff_ffff_ffff]; | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/issue-17913.stderr b/tests/ui/limits/issue-17913.stderr index 0d21a42883ebb..893730cbbd261 100644 --- a/tests/ui/limits/issue-17913.stderr +++ b/tests/ui/limits/issue-17913.stderr @@ -1,5 +1,5 @@ error: values of the type `[&usize; usize::MAX]` are too big for the current architecture --> $SRC_DIR/alloc/src/boxed.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr index 6b463930b007e..97ca0f4fb592c 100644 --- a/tests/ui/limits/issue-55878.stderr +++ b/tests/ui/limits/issue-55878.stderr @@ -28,6 +28,6 @@ LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr b/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr index 44b2be269494a..7b9b8f76d0c88 100644 --- a/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr +++ b/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr @@ -4,5 +4,5 @@ error: values of the type `[u8; usize::MAX]` are too big for the current archite LL | Bug::V([0; !0]); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/limits/issue-75158-64.stderr b/tests/ui/limits/issue-75158-64.stderr index d5991bcf5693d..06aad9616cb7a 100644 --- a/tests/ui/limits/issue-75158-64.stderr +++ b/tests/ui/limits/issue-75158-64.stderr @@ -1,4 +1,4 @@ error: values of the type `[u8; usize::MAX]` are too big for the current architecture -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/incompatible-flavor.stderr b/tests/ui/linkage-attr/incompatible-flavor.stderr index aabdd14b69b7e..a0f6bff66760c 100644 --- a/tests/ui/linkage-attr/incompatible-flavor.stderr +++ b/tests/ui/linkage-attr/incompatible-flavor.stderr @@ -2,5 +2,5 @@ error: linker flavor `msvc` is incompatible with the current target | = note: compatible flavors are: gnu, gnu-lld, gnu-cc, gnu-lld-cc, gcc, ld, ld.lld -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/issue-109144.stderr b/tests/ui/linkage-attr/issue-109144.stderr index 33187cfdbb636..0748d94189c63 100644 --- a/tests/ui/linkage-attr/issue-109144.stderr +++ b/tests/ui/linkage-attr/issue-109144.stderr @@ -4,6 +4,6 @@ error[E0459]: `#[link]` attribute requires a `name = "string"` argument LL | #[link(kind = "static", modifiers = "+whole-archive,+bundle")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0459`. diff --git a/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr index 06a070822630e..2448c160c5c0c 100644 --- a/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr +++ b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr @@ -4,5 +4,5 @@ error: symbol `collision` is already defined LL | pub static collision: *const i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr b/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr index e0be1ac2117bd..fcaaa39b6744e 100644 --- a/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr +++ b/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr @@ -4,5 +4,5 @@ error: symbol `collision` is already defined LL | pub static collision: *const i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/linkage2.stderr b/tests/ui/linkage-attr/linkage2.stderr index 7265f711fd016..49290d5a13fbb 100644 --- a/tests/ui/linkage-attr/linkage2.stderr +++ b/tests/ui/linkage-attr/linkage2.stderr @@ -4,6 +4,6 @@ error[E0791]: invalid type for variable with `#[linkage]` attribute LL | static foo: i32; | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0791`. diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr index dbb5880ab92fd..5f7b7ef227c84 100644 --- a/tests/ui/linkage-attr/linkage3.stderr +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -4,5 +4,5 @@ error: invalid linkage specified LL | static foo: *const i32; | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/linkage4.stderr b/tests/ui/linkage-attr/linkage4.stderr index 30d4d2b7bbabf..f76655b3c7254 100644 --- a/tests/ui/linkage-attr/linkage4.stderr +++ b/tests/ui/linkage-attr/linkage4.stderr @@ -7,6 +7,6 @@ LL | #[linkage = "external"] = note: see issue #29603 for more information = help: add `#![feature(linkage)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint-group-forbid-always-trumps-cli.stderr b/tests/ui/lint-group-forbid-always-trumps-cli.stderr index cd042179cce79..04a0f56c1633a 100644 --- a/tests/ui/lint-group-forbid-always-trumps-cli.stderr +++ b/tests/ui/lint-group-forbid-always-trumps-cli.stderr @@ -7,5 +7,5 @@ LL | let x = 1; = note: `-F unused-variables` implied by `-F unused` = help: to override `-F unused` add `#[allow(unused_variables)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/bad-lint-cap2.stderr b/tests/ui/lint/bad-lint-cap2.stderr index 3f3affe5a9811..05b16b44c5347 100644 --- a/tests/ui/lint/bad-lint-cap2.stderr +++ b/tests/ui/lint/bad-lint-cap2.stderr @@ -11,5 +11,5 @@ LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr index 01ca08a6f19be..c5d72707f80e8 100644 --- a/tests/ui/lint/bare-trait-objects-path.stderr +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -57,6 +57,6 @@ help: use `dyn` LL | ::CONST; | ++++ + -error: aborting due to previous error; 4 warnings emitted +error: aborting due to 1 previous error; 4 warnings emitted For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/lint/cli-lint-override.forbid_warn.stderr b/tests/ui/lint/cli-lint-override.forbid_warn.stderr index d1c66a81cd8a3..d8c75c33b0c56 100644 --- a/tests/ui/lint/cli-lint-override.forbid_warn.stderr +++ b/tests/ui/lint/cli-lint-override.forbid_warn.stderr @@ -7,5 +7,5 @@ LL | extern fn foo() {} = help: the default ABI is C = note: requested on the command line with `-F missing-abi` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/cli-lint-override.warn_deny.stderr b/tests/ui/lint/cli-lint-override.warn_deny.stderr index f034cfa9338a1..1ba42e9ce3234 100644 --- a/tests/ui/lint/cli-lint-override.warn_deny.stderr +++ b/tests/ui/lint/cli-lint-override.warn_deny.stderr @@ -7,5 +7,5 @@ LL | extern fn foo() {} = help: the default ABI is C = note: requested on the command line with `-D missing-abi` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/command-line-lint-group-deny.stderr b/tests/ui/lint/command-line-lint-group-deny.stderr index 59d8429ea6967..d78f198e73210 100644 --- a/tests/ui/lint/command-line-lint-group-deny.stderr +++ b/tests/ui/lint/command-line-lint-group-deny.stderr @@ -7,5 +7,5 @@ LL | let _InappropriateCamelCasing = true; = note: `-D non-snake-case` implied by `-D bad-style` = help: to override `-D bad-style` add `#[allow(non_snake_case)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/command-line-lint-group-forbid.stderr b/tests/ui/lint/command-line-lint-group-forbid.stderr index 486d32a9f08c6..7b527e7b8b461 100644 --- a/tests/ui/lint/command-line-lint-group-forbid.stderr +++ b/tests/ui/lint/command-line-lint-group-forbid.stderr @@ -7,5 +7,5 @@ LL | let _InappropriateCamelCasing = true; = note: `-F non-snake-case` implied by `-F bad-style` = help: to override `-F bad-style` add `#[allow(non_snake_case)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/basic.stderr b/tests/ui/lint/dead-code/basic.stderr index 7d068cead44b1..9f7d25502e734 100644 --- a/tests/ui/lint/dead-code/basic.stderr +++ b/tests/ui/lint/dead-code/basic.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/closure-bang.stderr b/tests/ui/lint/dead-code/closure-bang.stderr index 119ce11e34a1b..a0f5962dfe024 100644 --- a/tests/ui/lint/dead-code/closure-bang.stderr +++ b/tests/ui/lint/dead-code/closure-bang.stderr @@ -13,5 +13,5 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/empty-unused-enum.stderr b/tests/ui/lint/dead-code/empty-unused-enum.stderr index 6391f0941c86f..a6bf2e1f436c9 100644 --- a/tests/ui/lint/dead-code/empty-unused-enum.stderr +++ b/tests/ui/lint/dead-code/empty-unused-enum.stderr @@ -11,5 +11,5 @@ LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/impl-trait.stderr b/tests/ui/lint/dead-code/impl-trait.stderr index e35e13a9ec6d6..1c7d6d9459763 100644 --- a/tests/ui/lint/dead-code/impl-trait.stderr +++ b/tests/ui/lint/dead-code/impl-trait.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/type-alias.stderr b/tests/ui/lint/dead-code/type-alias.stderr index 446447d974a86..87c858fdb2a29 100644 --- a/tests/ui/lint/dead-code/type-alias.stderr +++ b/tests/ui/lint/dead-code/type-alias.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/unused-assoc-fns.stderr b/tests/ui/lint/dead-code/unused-assoc-fns.stderr index 6344a70ea3aee..2e43a67d5c83d 100644 --- a/tests/ui/lint/dead-code/unused-assoc-fns.stderr +++ b/tests/ui/lint/dead-code/unused-assoc-fns.stderr @@ -25,5 +25,5 @@ LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/unused-struct-variant.stderr b/tests/ui/lint/dead-code/unused-struct-variant.stderr index d26dd3aff9547..bd7b412566032 100644 --- a/tests/ui/lint/dead-code/unused-struct-variant.stderr +++ b/tests/ui/lint/dead-code/unused-struct-variant.stderr @@ -14,5 +14,5 @@ LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/unused-variant.stderr b/tests/ui/lint/dead-code/unused-variant.stderr index 6029bf2685607..0ae15fde47b05 100644 --- a/tests/ui/lint/dead-code/unused-variant.stderr +++ b/tests/ui/lint/dead-code/unused-variant.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/dead-code/with-core-crate.stderr b/tests/ui/lint/dead-code/with-core-crate.stderr index 7adcf884886e7..f466a616580c5 100644 --- a/tests/ui/lint/dead-code/with-core-crate.stderr +++ b/tests/ui/lint/dead-code/with-core-crate.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/enable-unstable-lib-feature.stderr b/tests/ui/lint/enable-unstable-lib-feature.stderr index bb4e928ad1583..327e6e3e956fb 100644 --- a/tests/ui/lint/enable-unstable-lib-feature.stderr +++ b/tests/ui/lint/enable-unstable-lib-feature.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(non_snake_case)] // To trigger a hard error | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/expr_attr_paren_order.stderr b/tests/ui/lint/expr_attr_paren_order.stderr index 42beed10c19fd..b3a3741d245f1 100644 --- a/tests/ui/lint/expr_attr_paren_order.stderr +++ b/tests/ui/lint/expr_attr_paren_order.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #[allow(non_snake_case)] #[deny(non_snake_case)] ( | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/forbid-group-group-1.stderr b/tests/ui/lint/forbid-group-group-1.stderr index fd425e5f74e6f..bbea56ac64ae7 100644 --- a/tests/ui/lint/forbid-group-group-1.stderr +++ b/tests/ui/lint/forbid-group-group-1.stderr @@ -11,5 +11,5 @@ LL | #![forbid(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: `#[forbid(non_snake_case)]` implied by `#[forbid(nonstandard_style)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/future-incompat-json-test.rs b/tests/ui/lint/future-incompat-json-test.rs new file mode 100644 index 0000000000000..6ccd670294c60 --- /dev/null +++ b/tests/ui/lint/future-incompat-json-test.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zfuture-incompat-test --json=future-incompat --error-format=json +// check-pass + +// The `-Zfuture-incompat-test flag causes any normal warning to be included +// in the future-incompatible report. The stderr output here should mention +// the future incompatible report (as extracted by compiletest). + +fn main() { + let x = 1; +} diff --git a/tests/ui/lint/future-incompat-json-test.stderr b/tests/ui/lint/future-incompat-json-test.stderr new file mode 100644 index 0000000000000..c4ab5a00d16cc --- /dev/null +++ b/tests/ui/lint/future-incompat-json-test.stderr @@ -0,0 +1,10 @@ +{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`-A unused-variables` implied by `-A unused`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"to override `-A unused` add `#[allow(unused_variables)]`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` + --> $DIR/future-incompat-json-test.rs:9:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-A unused-variables` implied by `-A unused` + = help: to override `-A unused` add `#[allow(unused_variables)]` + +"}}]} diff --git a/tests/ui/lint/internal_features.rs b/tests/ui/lint/internal_features.rs new file mode 100644 index 0000000000000..32ce9540cb364 --- /dev/null +++ b/tests/ui/lint/internal_features.rs @@ -0,0 +1,11 @@ +#![forbid(internal_features)] +// A lang feature and a lib feature. +#![feature(intrinsics, panic_internals)] +//~^ ERROR: internal +//~| ERROR: internal + +extern "rust-intrinsic" { + fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); +} + +fn main() {} diff --git a/tests/ui/lint/internal_features.stderr b/tests/ui/lint/internal_features.stderr new file mode 100644 index 0000000000000..8b52bef8f033b --- /dev/null +++ b/tests/ui/lint/internal_features.stderr @@ -0,0 +1,23 @@ +error: the feature `intrinsics` is internal to the compiler or standard library + --> $DIR/internal_features.rs:3:12 + | +LL | #![feature(intrinsics, panic_internals)] + | ^^^^^^^^^^ + | + = note: using it is strongly discouraged +note: the lint level is defined here + --> $DIR/internal_features.rs:1:11 + | +LL | #![forbid(internal_features)] + | ^^^^^^^^^^^^^^^^^ + +error: the feature `panic_internals` is internal to the compiler or standard library + --> $DIR/internal_features.rs:3:24 + | +LL | #![feature(intrinsics, panic_internals)] + | ^^^^^^^^^^^^^^^ + | + = note: using it is strongly discouraged + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/issue-103435-extra-parentheses.fixed b/tests/ui/lint/issue-103435-extra-parentheses.fixed index 2b01b414baa6e..74b5aa06e355a 100644 --- a/tests/ui/lint/issue-103435-extra-parentheses.fixed +++ b/tests/ui/lint/issue-103435-extra-parentheses.fixed @@ -13,6 +13,5 @@ fn main() { // reported by parser for _x in 1..10 {} - //~^ ERROR expected one of - //~| ERROR unexpected parentheses surrounding + //~^ ERROR unexpected parentheses surrounding } diff --git a/tests/ui/lint/issue-103435-extra-parentheses.rs b/tests/ui/lint/issue-103435-extra-parentheses.rs index 8261610cf5646..cc81a64f21779 100644 --- a/tests/ui/lint/issue-103435-extra-parentheses.rs +++ b/tests/ui/lint/issue-103435-extra-parentheses.rs @@ -8,11 +8,10 @@ fn main() { for(_x)in 1..10 {} //~^ ERROR unnecessary parentheses around pattern - if(2 == 1){} + if(2 == 1) {} //~^ ERROR unnecessary parentheses around `if` condition // reported by parser - for(_x in 1..10){} - //~^ ERROR expected one of - //~| ERROR unexpected parentheses surrounding + for(_x in 1..10) {} + //~^ ERROR unexpected parentheses surrounding } diff --git a/tests/ui/lint/issue-103435-extra-parentheses.stderr b/tests/ui/lint/issue-103435-extra-parentheses.stderr index 29c41c91050b9..5a166eb5008eb 100644 --- a/tests/ui/lint/issue-103435-extra-parentheses.stderr +++ b/tests/ui/lint/issue-103435-extra-parentheses.stderr @@ -1,18 +1,12 @@ -error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` - --> $DIR/issue-103435-extra-parentheses.rs:15:12 - | -LL | for(_x in 1..10){} - | ^^ expected one of `)`, `,`, `@`, or `|` - error: unexpected parentheses surrounding `for` loop head --> $DIR/issue-103435-extra-parentheses.rs:15:8 | -LL | for(_x in 1..10){} +LL | for(_x in 1..10) {} | ^ ^ | help: remove parentheses in `for` loop | -LL - for(_x in 1..10){} +LL - for(_x in 1..10) {} LL + for _x in 1..10 {} | @@ -48,14 +42,14 @@ LL + for _x in 1..10 {} error: unnecessary parentheses around `if` condition --> $DIR/issue-103435-extra-parentheses.rs:11:7 | -LL | if(2 == 1){} +LL | if(2 == 1) {} | ^ ^ | help: remove these parentheses | -LL - if(2 == 1){} +LL - if(2 == 1) {} LL + if 2 == 1 {} | -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr index 728d51f34a49a..1f3d40605f673 100644 --- a/tests/ui/lint/issue-104897.stderr +++ b/tests/ui/lint/issue-104897.stderr @@ -8,5 +8,5 @@ LL | fn f(){(print!(á | |unclosed delimiter | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/issue-106991.stderr b/tests/ui/lint/issue-106991.stderr index 7b43f0b2ca8f3..4704e9ef8355f 100644 --- a/tests/ui/lint/issue-106991.stderr +++ b/tests/ui/lint/issue-106991.stderr @@ -6,6 +6,6 @@ LL | fn bar() -> impl Iterator { | = note: required for `Map>, for<'a> fn(&'a mut Vec) {foo}>` to implement `Iterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/lint/issue-109152.stderr b/tests/ui/lint/issue-109152.stderr index 7db9e71a584b0..a175964ccf63f 100644 --- a/tests/ui/lint/issue-109152.stderr +++ b/tests/ui/lint/issue-109152.stderr @@ -19,5 +19,5 @@ help: you might have meant to use `Iterator::for_each` LL | vec![42].iter().for_each(drop); | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/issue-63364.stderr b/tests/ui/lint/issue-63364.stderr index 9b5453fa82d4c..f4305f37fe017 100644 --- a/tests/ui/lint/issue-63364.stderr +++ b/tests/ui/lint/issue-63364.stderr @@ -7,5 +7,5 @@ LL | for n in 100_000.. { = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535` = note: `#[deny(overflowing_literals)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr index cc44f8aa58bd0..f78bf899b848c 100644 --- a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr +++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -14,5 +14,5 @@ note: the lint level is defined here LL | #![forbid(forbidden_lint_groups)] | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/issue-79744.stderr b/tests/ui/lint/issue-79744.stderr index c1b56250d3ed9..4cb79f7fd2921 100644 --- a/tests/ui/lint/issue-79744.stderr +++ b/tests/ui/lint/issue-79744.stderr @@ -8,5 +8,5 @@ LL | let e2 = 230; = help: consider using the type `u8` instead = note: `#[deny(overflowing_literals)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/issue-99387.stderr b/tests/ui/lint/issue-99387.stderr index 3a46ce7e1952d..0005e55324f7d 100644 --- a/tests/ui/lint/issue-99387.stderr +++ b/tests/ui/lint/issue-99387.stderr @@ -11,5 +11,5 @@ note: this item must mention the opaque type in its signature in order to be abl LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item { | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/let_underscore/let_underscore_lock.stderr b/tests/ui/lint/let_underscore/let_underscore_lock.stderr index fb58af0a42f81..f88a1df55e066 100644 --- a/tests/ui/lint/let_underscore/let_underscore_lock.stderr +++ b/tests/ui/lint/let_underscore/let_underscore_lock.stderr @@ -16,5 +16,5 @@ help: consider immediately dropping the value LL | drop(data.lock().unwrap()); | ~~~~~ + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-attr-non-item-node.stderr b/tests/ui/lint/lint-attr-non-item-node.stderr index 5835791409660..7922d1c084dad 100644 --- a/tests/ui/lint/lint-attr-non-item-node.stderr +++ b/tests/ui/lint/lint-attr-non-item-node.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #[deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr index 49fa54114b213..ef30a406969d3 100644 --- a/tests/ui/lint/lint-ctypes-73249-2.stderr +++ b/tests/ui/lint/lint-ctypes-73249-2.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-ctypes-73249-3.stderr b/tests/ui/lint/lint-ctypes-73249-3.stderr index c41ce666db872..e5607ba72e978 100644 --- a/tests/ui/lint/lint-ctypes-73249-3.stderr +++ b/tests/ui/lint/lint-ctypes-73249-3.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-ctypes-73249-5.stderr b/tests/ui/lint/lint-ctypes-73249-5.stderr index 98245c4f144ae..fcb106c485d85 100644 --- a/tests/ui/lint/lint-ctypes-73249-5.stderr +++ b/tests/ui/lint/lint-ctypes-73249-5.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-ctypes-73251-1.stderr b/tests/ui/lint/lint-ctypes-73251-1.stderr index b4eb921b97e26..a3b3ebaac3031 100644 --- a/tests/ui/lint/lint-ctypes-73251-1.stderr +++ b/tests/ui/lint/lint-ctypes-73251-1.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-ctypes-73251-2.stderr b/tests/ui/lint/lint-ctypes-73251-2.stderr index e44cd45bd30fa..40a9cd00c50ff 100644 --- a/tests/ui/lint/lint-ctypes-73251-2.stderr +++ b/tests/ui/lint/lint-ctypes-73251-2.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-ctypes-option-nonnull-unsized.stderr b/tests/ui/lint/lint-ctypes-option-nonnull-unsized.stderr index f59fb3cc750dd..746304694167f 100644 --- a/tests/ui/lint/lint-ctypes-option-nonnull-unsized.stderr +++ b/tests/ui/lint/lint-ctypes-option-nonnull-unsized.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes_definitions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-forbid-internal-unsafe.stderr b/tests/ui/lint/lint-forbid-internal-unsafe.stderr index ba425ceb442b2..52d9c8471e56e 100644 --- a/tests/ui/lint/lint-forbid-internal-unsafe.stderr +++ b/tests/ui/lint/lint-forbid-internal-unsafe.stderr @@ -18,5 +18,5 @@ LL | println!("{}", evil!(*(0 as *const u8))); | = note: `#[warn(deref_nullptr)]` on by default -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/lint-match-arms.stderr b/tests/ui/lint/lint-match-arms.stderr index 1bc0e41fd550c..eccfa19fda781 100644 --- a/tests/ui/lint/lint-match-arms.stderr +++ b/tests/ui/lint/lint-match-arms.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #[deny(unused_variables)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-missing-copy-implementations.stderr b/tests/ui/lint/lint-missing-copy-implementations.stderr index e5f5ce20d1c90..37c9192d2a49c 100644 --- a/tests/ui/lint/lint-missing-copy-implementations.stderr +++ b/tests/ui/lint/lint-missing-copy-implementations.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(missing_copy_implementations)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-non-snake-case-crate-2.stderr b/tests/ui/lint/lint-non-snake-case-crate-2.stderr index 4b42145bbed8b..f3207226cd93e 100644 --- a/tests/ui/lint/lint-non-snake-case-crate-2.stderr +++ b/tests/ui/lint/lint-non-snake-case-crate-2.stderr @@ -7,5 +7,5 @@ note: the lint level is defined here LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-non-snake-case-crate.stderr b/tests/ui/lint/lint-non-snake-case-crate.stderr index da6b89c1e0499..1136b707d595b 100644 --- a/tests/ui/lint/lint-non-snake-case-crate.stderr +++ b/tests/ui/lint/lint-non-snake-case-crate.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-non-snake-case-lifetimes.stderr b/tests/ui/lint/lint-non-snake-case-lifetimes.stderr index d4fe26a43c2e9..8be7365cfc341 100644 --- a/tests/ui/lint/lint-non-snake-case-lifetimes.stderr +++ b/tests/ui/lint/lint-non-snake-case-lifetimes.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-non-snake-case-modules.stderr b/tests/ui/lint/lint-non-snake-case-modules.stderr index c8b997c870704..f21f9a934f3f9 100644 --- a/tests/ui/lint/lint-non-snake-case-modules.stderr +++ b/tests/ui/lint/lint-non-snake-case-modules.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-non-uppercase-associated-const.stderr b/tests/ui/lint/lint-non-uppercase-associated-const.stderr index 411ff51aad748..54c951b1f63ed 100644 --- a/tests/ui/lint/lint-non-uppercase-associated-const.stderr +++ b/tests/ui/lint/lint-non-uppercase-associated-const.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(non_upper_case_globals)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-non-uppercase-trait-assoc-const.stderr b/tests/ui/lint/lint-non-uppercase-trait-assoc-const.stderr index 98d8d1dd27f35..a5ac540d12542 100644 --- a/tests/ui/lint/lint-non-uppercase-trait-assoc-const.stderr +++ b/tests/ui/lint/lint-non-uppercase-trait-assoc-const.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(non_upper_case_globals)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr b/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr index 970e6b838ada0..3d4337bbc6f92 100644 --- a/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr +++ b/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![forbid(non_upper_case_globals)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr index 90a06bc6cbe5d..2448a64f11d90 100644 --- a/tests/ui/lint/lint-qualification.stderr +++ b/tests/ui/lint/lint-qualification.stderr @@ -15,5 +15,5 @@ LL - foo::bar(); LL + bar(); | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-removed-allow.stderr b/tests/ui/lint/lint-removed-allow.stderr index 029334c2eb67c..849c9ec5ca0ff 100644 --- a/tests/ui/lint/lint-removed-allow.stderr +++ b/tests/ui/lint/lint-removed-allow.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #[deny(unused_variables)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr index 6b76ad3b578c7..fd63433c30867 100644 --- a/tests/ui/lint/lint-removed-cmdline.stderr +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -26,5 +26,5 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted diff --git a/tests/ui/lint/lint-removed.stderr b/tests/ui/lint/lint-removed.stderr index dc0515b84820b..6d3629ba388f6 100644 --- a/tests/ui/lint/lint-removed.stderr +++ b/tests/ui/lint/lint-removed.stderr @@ -18,5 +18,5 @@ note: the lint level is defined here LL | #[deny(unused_variables)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/lint-renamed-allow.stderr b/tests/ui/lint/lint-renamed-allow.stderr index 46f6a10de2743..8bc8530b42246 100644 --- a/tests/ui/lint/lint-renamed-allow.stderr +++ b/tests/ui/lint/lint-renamed-allow.stderr @@ -11,5 +11,5 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr index 675443ddedf5d..d6bb72f34dce2 100644 --- a/tests/ui/lint/lint-renamed-cmdline.stderr +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -29,5 +29,5 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted diff --git a/tests/ui/lint/lint-renamed.stderr b/tests/ui/lint/lint-renamed.stderr index 9842545714529..a1aa85e6744e0 100644 --- a/tests/ui/lint/lint-renamed.stderr +++ b/tests/ui/lint/lint-renamed.stderr @@ -19,5 +19,5 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/lint-stability2.stderr b/tests/ui/lint/lint-stability2.stderr index 51bdf84a321bd..3df0c42816793 100644 --- a/tests/ui/lint/lint-stability2.stderr +++ b/tests/ui/lint/lint-stability2.stderr @@ -11,5 +11,5 @@ LL | #![deny(deprecated)] | ^^^^^^^^^^ = note: this error originates in the macro `macro_test` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-stability3.stderr b/tests/ui/lint/lint-stability3.stderr index 3bbb60dd35927..3a2af452ce200 100644 --- a/tests/ui/lint/lint-stability3.stderr +++ b/tests/ui/lint/lint-stability3.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(deprecated)] | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr index 383623b48317f..0b12897427586 100644 --- a/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr +++ b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr @@ -15,5 +15,5 @@ help: use `.with_addr()` to adjust a valid pointer in the same allocation, to th LL | let dangling = (...).with_addr(16_usize); | ++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-struct-necessary.stderr b/tests/ui/lint/lint-struct-necessary.stderr index eb65a9e98c6e7..90b2af7dea9b0 100644 --- a/tests/ui/lint/lint-struct-necessary.stderr +++ b/tests/ui/lint/lint-struct-necessary.stderr @@ -15,5 +15,5 @@ LL - match (e) { LL + match e { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-temporary-cstring-as-param.stderr b/tests/ui/lint/lint-temporary-cstring-as-param.stderr index 838b3bc13feea..7aa21f2560c2d 100644 --- a/tests/ui/lint/lint-temporary-cstring-as-param.stderr +++ b/tests/ui/lint/lint-temporary-cstring-as-param.stderr @@ -14,5 +14,5 @@ note: the lint level is defined here LL | #![deny(temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-type-limits2.stderr b/tests/ui/lint/lint-type-limits2.stderr index b3420ad8afde6..91363350884e0 100644 --- a/tests/ui/lint/lint-type-limits2.stderr +++ b/tests/ui/lint/lint-type-limits2.stderr @@ -20,5 +20,5 @@ note: the lint level is defined here LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/lint-type-limits3.stderr b/tests/ui/lint/lint-type-limits3.stderr index db46e7ae7148e..77487164a1361 100644 --- a/tests/ui/lint/lint-type-limits3.stderr +++ b/tests/ui/lint/lint-type-limits3.stderr @@ -20,5 +20,5 @@ note: the lint level is defined here LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/lint-unconditional-drop-recursion.stderr b/tests/ui/lint/lint-unconditional-drop-recursion.stderr index 76f95481605f1..5ac56499c1f28 100644 --- a/tests/ui/lint/lint-unconditional-drop-recursion.stderr +++ b/tests/ui/lint/lint-unconditional-drop-recursion.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unconditional_recursion)] | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/lint-unnecessary-import-braces.stderr b/tests/ui/lint/lint-unnecessary-import-braces.stderr index 2d289404ded74..5f441ef4a6640 100644 --- a/tests/ui/lint/lint-unnecessary-import-braces.stderr +++ b/tests/ui/lint/lint-unnecessary-import-braces.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_import_braces)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/boxed.stderr b/tests/ui/lint/must_not_suspend/boxed.stderr index a2abfffc170b7..6170a36a8139b 100644 --- a/tests/ui/lint/must_not_suspend/boxed.stderr +++ b/tests/ui/lint/must_not_suspend/boxed.stderr @@ -22,5 +22,5 @@ note: the lint level is defined here LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/dedup.stderr b/tests/ui/lint/must_not_suspend/dedup.stderr index 5d5b04a5d9593..2876e1cf6750e 100644 --- a/tests/ui/lint/must_not_suspend/dedup.stderr +++ b/tests/ui/lint/must_not_suspend/dedup.stderr @@ -18,5 +18,5 @@ note: the lint level is defined here LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr index ab20a8be8747d..9ec33b1c49031 100644 --- a/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr +++ b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr @@ -7,6 +7,6 @@ LL | #[must_not_suspend = "You gotta use Umm's, ya know?"] = note: see issue #83310 for more information = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/must_not_suspend/mutex.stderr b/tests/ui/lint/must_not_suspend/mutex.stderr index 9b5fc37a3329b..ca53a753150ec 100644 --- a/tests/ui/lint/must_not_suspend/mutex.stderr +++ b/tests/ui/lint/must_not_suspend/mutex.stderr @@ -22,5 +22,5 @@ note: the lint level is defined here LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/other_items.stderr b/tests/ui/lint/must_not_suspend/other_items.stderr index 41c8896921b0f..e6c36b7895109 100644 --- a/tests/ui/lint/must_not_suspend/other_items.stderr +++ b/tests/ui/lint/must_not_suspend/other_items.stderr @@ -6,5 +6,5 @@ LL | #[must_not_suspend] LL | mod inner {} | ------------ is not a struct, enum, or trait -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/ref.stderr b/tests/ui/lint/must_not_suspend/ref.stderr index ed91a4a0bc624..aa772afc7a96b 100644 --- a/tests/ui/lint/must_not_suspend/ref.stderr +++ b/tests/ui/lint/must_not_suspend/ref.stderr @@ -23,5 +23,5 @@ note: the lint level is defined here LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/return.stderr b/tests/ui/lint/must_not_suspend/return.stderr index fdada85eb4d1c..5a73064c78776 100644 --- a/tests/ui/lint/must_not_suspend/return.stderr +++ b/tests/ui/lint/must_not_suspend/return.stderr @@ -8,5 +8,5 @@ LL | | 0 LL | | } | |_- is not a struct, enum, or trait -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr index 294476107ef78..3adf26cfee229 100644 --- a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr +++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr @@ -7,6 +7,6 @@ LL | yield ((), ()); = note: expected tuple `((), ())` found unit type `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lint/must_not_suspend/unit.stderr b/tests/ui/lint/must_not_suspend/unit.stderr index 11c95c1464ae1..716369d8e6a5a 100644 --- a/tests/ui/lint/must_not_suspend/unit.stderr +++ b/tests/ui/lint/must_not_suspend/unit.stderr @@ -22,5 +22,5 @@ note: the lint level is defined here LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr index e8d696477ada1..9efc187833f00 100644 --- a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr +++ b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr index ba9e18bcce5c7..7f5d1792bf12a 100644 --- a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/renamed-lints-still-apply.stderr b/tests/ui/lint/renamed-lints-still-apply.stderr index e926719bb6be9..9eaf711293388 100644 --- a/tests/ui/lint/renamed-lints-still-apply.stderr +++ b/tests/ui/lint/renamed-lints-still-apply.stderr @@ -25,5 +25,5 @@ LL - fn _foo<'a>(_x: &'a u32) {} LL + fn _foo(_x: &u32) {} | -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr index b5601cf9e6594..b8e7d61a1ecc2 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr @@ -7,6 +7,6 @@ LL | #[expect(unused)] = note: see issue #54503 for more information = help: add `#![feature(lint_reasons)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr index 4852c3313969e..0e445d2439b40 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr @@ -48,5 +48,5 @@ warning: this lint expectation is unfulfilled LL | #[expect(unused_variables)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 4 warnings emitted +error: aborting due to 1 previous error; 4 warnings emitted diff --git a/tests/ui/lint/rustdoc-renamed.stderr b/tests/ui/lint/rustdoc-renamed.stderr index 096e867aa16db..8491a43275640 100644 --- a/tests/ui/lint/rustdoc-renamed.stderr +++ b/tests/ui/lint/rustdoc-renamed.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(renamed_and_removed_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unaligned_references_external_macro.stderr b/tests/ui/lint/unaligned_references_external_macro.stderr index 94a95c1d8fda7..9945c78e8ba66 100644 --- a/tests/ui/lint/unaligned_references_external_macro.stderr +++ b/tests/ui/lint/unaligned_references_external_macro.stderr @@ -14,6 +14,6 @@ LL | | } = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0793`. diff --git a/tests/ui/lint/unconditional_panic_98444.stderr b/tests/ui/lint/unconditional_panic_98444.stderr index a347458097fa9..29719b2dad523 100644 --- a/tests/ui/lint/unconditional_panic_98444.stderr +++ b/tests/ui/lint/unconditional_panic_98444.stderr @@ -6,5 +6,5 @@ LL | let _ = xs[7]; | = note: `#[deny(unconditional_panic)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/assoc-types.assoc_ty.stderr b/tests/ui/lint/unused/assoc-types.assoc_ty.stderr new file mode 100644 index 0000000000000..190c4ef0cea0d --- /dev/null +++ b/tests/ui/lint/unused/assoc-types.assoc_ty.stderr @@ -0,0 +1,15 @@ +error: unused implementer of `Future` that must be used + --> $DIR/assoc-types.rs:19:5 + | +LL | T::foo(); + | ^^^^^^^^ + | + = note: futures do nothing unless you `.await` or poll them +note: the lint level is defined here + --> $DIR/assoc-types.rs:4:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/unused/assoc-types.rpitit.stderr b/tests/ui/lint/unused/assoc-types.rpitit.stderr new file mode 100644 index 0000000000000..190c4ef0cea0d --- /dev/null +++ b/tests/ui/lint/unused/assoc-types.rpitit.stderr @@ -0,0 +1,15 @@ +error: unused implementer of `Future` that must be used + --> $DIR/assoc-types.rs:19:5 + | +LL | T::foo(); + | ^^^^^^^^ + | + = note: futures do nothing unless you `.await` or poll them +note: the lint level is defined here + --> $DIR/assoc-types.rs:4:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/unused/assoc-types.rs b/tests/ui/lint/unused/assoc-types.rs new file mode 100644 index 0000000000000..cebb9b4090ce9 --- /dev/null +++ b/tests/ui/lint/unused/assoc-types.rs @@ -0,0 +1,23 @@ +// edition: 2021 +// revisions: rpitit assoc_ty + +#![deny(unused_must_use)] + +use std::future::Future; + +pub trait Tr { + type Fut: Future; + + #[cfg(rpitit)] + fn foo() -> impl Future; + + #[cfg(assoc_ty)] + fn foo() -> Self::Fut; +} + +pub async fn bar() { + T::foo(); + //~^ ERROR unused implementer of `Future` that must be used +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-105061.stderr b/tests/ui/lint/unused/issue-105061.stderr index f07aa2012df5f..b41f14d82ebfd 100644 --- a/tests/ui/lint/unused/issue-105061.stderr +++ b/tests/ui/lint/unused/issue-105061.stderr @@ -16,5 +16,5 @@ LL - ((for<'a> fn(Inv<'a>)),): Trait, LL + (for<'a> fn(Inv<'a>),): Trait, | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/issue-30730.stderr b/tests/ui/lint/unused/issue-30730.stderr index b299e99a3a908..c815045df88fa 100644 --- a/tests/ui/lint/unused/issue-30730.stderr +++ b/tests/ui/lint/unused/issue-30730.stderr @@ -11,5 +11,5 @@ LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/issue-46576.stderr b/tests/ui/lint/unused/issue-46576.stderr index 6f4d97068b353..44e4fb582b5c3 100644 --- a/tests/ui/lint/unused/issue-46576.stderr +++ b/tests/ui/lint/unused/issue-46576.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_imports)] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/issue-59896.stderr b/tests/ui/lint/unused/issue-59896.stderr index 95b7938ae0383..3e8298c6b72e6 100644 --- a/tests/ui/lint/unused/issue-59896.stderr +++ b/tests/ui/lint/unused/issue-59896.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unused_imports)] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/issue-85913.stderr b/tests/ui/lint/unused/issue-85913.stderr index 8234ed3b1678c..b69ac3d97fd25 100644 --- a/tests/ui/lint/unused/issue-85913.stderr +++ b/tests/ui/lint/unused/issue-85913.stderr @@ -14,5 +14,5 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = function() && return 1; | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.stderr b/tests/ui/lint/unused/lint-unused-mut-variables.stderr index 5f66c03158178..dcda1e5306f9e 100644 --- a/tests/ui/lint/unused/lint-unused-mut-variables.stderr +++ b/tests/ui/lint/unused/lint-unused-mut-variables.stderr @@ -226,5 +226,5 @@ LL | fn write_through_reference(mut arg: &mut Arg) { | | | help: remove this `mut` -error: aborting due to previous error; 26 warnings emitted +error: aborting due to 1 previous error; 26 warnings emitted diff --git a/tests/ui/lint/unused/must_use-pin.rs b/tests/ui/lint/unused/must_use-pin.rs new file mode 100644 index 0000000000000..b08515428b1b5 --- /dev/null +++ b/tests/ui/lint/unused/must_use-pin.rs @@ -0,0 +1,45 @@ +#![deny(unused_must_use)] + +use std::{ops::Deref, pin::Pin}; + +#[must_use] +struct MustUse; + +#[must_use] +struct MustUsePtr<'a, T>(&'a T); + +impl<'a, T> Deref for MustUsePtr<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.0 + } +} + +fn pin_ref() -> Pin<&'static ()> { + Pin::new(&()) +} + +fn pin_ref_mut() -> Pin<&'static mut ()> { + Pin::new(unimplemented!()) +} + +fn pin_must_use_ptr() -> Pin> { + Pin::new(MustUsePtr(&())) +} + +fn pin_box() -> Pin> { + Box::pin(()) +} + +fn pin_box_must_use() -> Pin> { + Box::pin(MustUse) +} + +fn main() { + pin_ref(); + pin_ref_mut(); + pin_must_use_ptr(); //~ ERROR unused pinned `MustUsePtr` that must be used + pin_box(); + pin_box_must_use(); //~ ERROR unused pinned boxed `MustUse` that must be used +} diff --git a/tests/ui/lint/unused/must_use-pin.stderr b/tests/ui/lint/unused/must_use-pin.stderr new file mode 100644 index 0000000000000..c04f8fef4873f --- /dev/null +++ b/tests/ui/lint/unused/must_use-pin.stderr @@ -0,0 +1,20 @@ +error: unused pinned `MustUsePtr` that must be used + --> $DIR/must_use-pin.rs:42:5 + | +LL | pin_must_use_ptr(); + | ^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-pin.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused pinned boxed `MustUse` that must be used + --> $DIR/must_use-pin.rs:44:5 + | +LL | pin_box_must_use(); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr index 797c867103f03..76b2a0556393e 100644 --- a/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr +++ b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr @@ -4,5 +4,5 @@ error: macro rhs must be delimited LL | () => 0; | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr index 6edf0a2cf8d52..f027e169b42bb 100644 --- a/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr +++ b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr @@ -6,5 +6,5 @@ LL | ($wrong:t_ty) => () | = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr b/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr index 5eced4f06c0cd..a8a41e081294a 100644 --- a/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr +++ b/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr @@ -6,5 +6,5 @@ LL | ($e:expr +) => () | = note: allowed there are: `=>`, `,` or `;` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr b/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr index 20aeedcc24125..d4fa96c10a284 100644 --- a/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr +++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![forbid(unused_mut)] | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/unused-supertrait.stderr b/tests/ui/lint/unused/unused-supertrait.stderr index cb45add9c2b1b..c7ccf30ea24e7 100644 --- a/tests/ui/lint/unused/unused-supertrait.stderr +++ b/tests/ui/lint/unused/unused-supertrait.stderr @@ -11,5 +11,5 @@ note: the lint level is defined here LL | #![deny(unused_must_use)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused_parens_json_suggestion.stderr b/tests/ui/lint/unused_parens_json_suggestion.stderr index ea19e0cdc0cb3..4bdfee9159b2d 100644 --- a/tests/ui/lint/unused_parens_json_suggestion.stderr +++ b/tests/ui/lint/unused_parens_json_suggestion.stderr @@ -1,4 +1,4 @@ -{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); +{"$message_type":"diagnostic","message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); --> $DIR/unused_parens_json_suggestion.rs:16:14 | LL | let _a = (1 / (2 + 3)); @@ -16,6 +16,6 @@ LL + let _a = 1 / (2 + 3); | "} -{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error +{"$message_type":"diagnostic","message":"aborting due to 1 previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 1 previous error "} diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.stderr b/tests/ui/lint/unused_parens_multibyte_recovery.stderr index adbf27fcca2f4..ef4089f31f430 100644 --- a/tests/ui/lint/unused_parens_multibyte_recovery.stderr +++ b/tests/ui/lint/unused_parens_multibyte_recovery.stderr @@ -8,5 +8,5 @@ LL | fn f(){(print!(á | |unclosed delimiter | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.stderr b/tests/ui/lint/unused_parens_remove_json_suggestion.stderr index f4c6ceaf1dc1b..7521d41cc939d 100644 --- a/tests/ui/lint/unused_parens_remove_json_suggestion.stderr +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -1,4 +1,4 @@ -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) { +{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) { --> $DIR/unused_parens_remove_json_suggestion.rs:17:8 | LL | if (_b) { @@ -16,7 +16,7 @@ LL + if _b { | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) { +{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) { --> $DIR/unused_parens_remove_json_suggestion.rs:28:7 | LL | if(c) { @@ -29,7 +29,7 @@ LL + if c { | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){ +{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){ --> $DIR/unused_parens_remove_json_suggestion.rs:32:8 | LL | if (c){ @@ -42,7 +42,7 @@ LL + if c { | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition +{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition --> $DIR/unused_parens_remove_json_suggestion.rs:36:11 | LL | while (false && true){ @@ -55,7 +55,7 @@ LL + while false && true { | "} -{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) { +{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) { --> $DIR/unused_parens_remove_json_suggestion.rs:37:12 | LL | if (c) { @@ -68,7 +68,7 @@ LL + if c { | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) { +{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) { --> $DIR/unused_parens_remove_json_suggestion.rs:43:10 | LL | while(true && false) { @@ -81,7 +81,7 @@ LL + while true && false { | "} -{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ +{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 | LL | for _ in (0 .. 3){ @@ -94,7 +94,7 @@ LL + for _ in 0 .. 3 { | "} -{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { +{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 | LL | for _ in (0 .. 3) { @@ -107,7 +107,7 @@ LL + for _ in 0 .. 3 { | "} -{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) { +{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) { --> $DIR/unused_parens_remove_json_suggestion.rs:50:15 | LL | while (true && false) { @@ -120,6 +120,6 @@ LL + while true && false { | "} -{"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors +{"$message_type":"diagnostic","message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors "} diff --git a/tests/ui/lint/unused_variables-issue-82488.stderr b/tests/ui/lint/unused_variables-issue-82488.stderr index dce03a0f738b3..3babc94b4eb64 100644 --- a/tests/ui/lint/unused_variables-issue-82488.stderr +++ b/tests/ui/lint/unused_variables-issue-82488.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_variables)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lint/use_suggestion_json.stderr b/tests/ui/lint/use_suggestion_json.stderr index d17514303abf6..7dfd269a4e247 100644 --- a/tests/ui/lint/use_suggestion_json.stderr +++ b/tests/ui/lint/use_suggestion_json.stderr @@ -1,3 +1,3 @@ -{"message":"`--error-format=pretty-json` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: `--error-format=pretty-json` is unstable\u001b[0m +{"$message_type":"diagnostic","message":"`--error-format=pretty-json` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: `--error-format=pretty-json` is unstable\u001b[0m "} diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr index 66cdce7dacf83..f0174560fd58c 100644 --- a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr @@ -7,6 +7,6 @@ LL | let v: isize; LL | v = 1; | ^^^^^ cannot assign twice to immutable variable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr index 5db9539cbf1e5..578a40e4070d0 100644 --- a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr @@ -9,6 +9,6 @@ LL | v = 2; LL | v += 1; | ^^^^^^ cannot assign twice to immutable variable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr index bb7e7e27a4ca0..2f55b50f0baf4 100644 --- a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr @@ -10,6 +10,6 @@ LL | let b = Box::new(1); LL | b = Box::new(2); | ^ cannot assign twice to immutable variable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr index 80458a70a0107..8eb71cd99bfc1 100644 --- a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr @@ -10,6 +10,6 @@ LL | let v: isize = 1; LL | v = 2; | ^^^^^ cannot assign twice to immutable variable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/liveness/liveness-closure-require-ret.stderr b/tests/ui/liveness/liveness-closure-require-ret.stderr index 07b2ef6cd1bc2..b5d48f4985ea9 100644 --- a/tests/ui/liveness/liveness-closure-require-ret.stderr +++ b/tests/ui/liveness/liveness-closure-require-ret.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | fn main() { println!("{}", force(|| {})); } | ^^ expected `isize`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-forgot-ret.stderr b/tests/ui/liveness/liveness-forgot-ret.stderr index ddbdbdb0fd043..a5adadca26ee2 100644 --- a/tests/ui/liveness/liveness-forgot-ret.stderr +++ b/tests/ui/liveness/liveness-forgot-ret.stderr @@ -11,6 +11,6 @@ help: consider returning the local binding `a` LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a } | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-issue-2163.stderr b/tests/ui/liveness/liveness-issue-2163.stderr index 2adc2d43809ba..216469bf6abb1 100644 --- a/tests/ui/liveness/liveness-issue-2163.stderr +++ b/tests/ui/liveness/liveness-issue-2163.stderr @@ -7,6 +7,6 @@ LL | | LL | | }); | |_____^ expected `bool`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-missing-ret2.stderr b/tests/ui/liveness/liveness-missing-ret2.stderr index afdb733cd030f..8fe999e02e3ad 100644 --- a/tests/ui/liveness/liveness-missing-ret2.stderr +++ b/tests/ui/liveness/liveness-missing-ret2.stderr @@ -6,6 +6,6 @@ LL | fn f() -> isize { | | | implicitly returns `()` as its body has no tail or `return` expression -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-move-call-arg-2.stderr b/tests/ui/liveness/liveness-move-call-arg-2.stderr index 479a086a80c32..f4252e1ac33c9 100644 --- a/tests/ui/liveness/liveness-move-call-arg-2.stderr +++ b/tests/ui/liveness/liveness-move-call-arg-2.stderr @@ -21,6 +21,6 @@ help: consider cloning the value if the performance cost is acceptable LL | take(x.clone()); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-move-call-arg.stderr b/tests/ui/liveness/liveness-move-call-arg.stderr index d14cd6cb4e03a..9697ed5cb114b 100644 --- a/tests/ui/liveness/liveness-move-call-arg.stderr +++ b/tests/ui/liveness/liveness-move-call-arg.stderr @@ -21,6 +21,6 @@ help: consider cloning the value if the performance cost is acceptable LL | take(x.clone()); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-move-in-loop.stderr b/tests/ui/liveness/liveness-move-in-loop.stderr index a060914f17859..7180eb23bf5e8 100644 --- a/tests/ui/liveness/liveness-move-in-loop.stderr +++ b/tests/ui/liveness/liveness-move-in-loop.stderr @@ -21,6 +21,6 @@ help: consider cloning the value if the performance cost is acceptable LL | x = y.clone(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-move-in-while.stderr b/tests/ui/liveness/liveness-move-in-while.stderr index 4dff7447dd766..dc48c4cc9acfc 100644 --- a/tests/ui/liveness/liveness-move-in-while.stderr +++ b/tests/ui/liveness/liveness-move-in-while.stderr @@ -41,6 +41,6 @@ help: consider cloning the value if the performance cost is acceptable LL | while true { while true { while true { x = y.clone(); x.clone(); } } } | ++++++++ -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-use-after-move.stderr b/tests/ui/liveness/liveness-use-after-move.stderr index 3accba197a13d..eab51edca37f4 100644 --- a/tests/ui/liveness/liveness-use-after-move.stderr +++ b/tests/ui/liveness/liveness-use-after-move.stderr @@ -15,6 +15,6 @@ help: consider cloning the value if the performance cost is acceptable LL | let y = x.clone(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-use-after-send.stderr b/tests/ui/liveness/liveness-use-after-send.stderr index 65d55ca8f7073..2323451a7d2df 100644 --- a/tests/ui/liveness/liveness-use-after-send.stderr +++ b/tests/ui/liveness/liveness-use-after-send.stderr @@ -19,6 +19,6 @@ help: consider cloning the value if the performance cost is acceptable LL | send(ch, message.clone()); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/loops/issue-82916.stderr b/tests/ui/loops/issue-82916.stderr index e6a60d7bc4072..5a5e9c4f0bbeb 100644 --- a/tests/ui/loops/issue-82916.stderr +++ b/tests/ui/loops/issue-82916.stderr @@ -16,6 +16,6 @@ help: consider iterating over a slice of the `Vec`'s content to avoid moving LL | for y in &x { | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/loops/loop-break-value-no-repeat.stderr b/tests/ui/loops/loop-break-value-no-repeat.stderr index 605a1841cf376..946057d054398 100644 --- a/tests/ui/loops/loop-break-value-no-repeat.stderr +++ b/tests/ui/loops/loop-break-value-no-repeat.stderr @@ -11,6 +11,6 @@ help: use `break` on its own without a value inside this `for` loop LL | break | ~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0571`. diff --git a/tests/ui/loops/loop-else-break-with-value.stderr b/tests/ui/loops/loop-else-break-with-value.stderr index 972e2d341ec0d..c933e0d0cd8ea 100644 --- a/tests/ui/loops/loop-else-break-with-value.stderr +++ b/tests/ui/loops/loop-else-break-with-value.stderr @@ -14,5 +14,5 @@ LL | | }; | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/loops/loop-else-err.stderr b/tests/ui/loops/loop-else-err.stderr index c2c5c84cded5d..c1cbd544afde2 100644 --- a/tests/ui/loops/loop-else-err.stderr +++ b/tests/ui/loops/loop-else-err.stderr @@ -13,5 +13,5 @@ LL | | } | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/loops/loop-else-let-else-err.stderr b/tests/ui/loops/loop-else-let-else-err.stderr index a57c784ff6fca..6ee77fb47af33 100644 --- a/tests/ui/loops/loop-else-let-else-err.stderr +++ b/tests/ui/loops/loop-else-let-else-err.stderr @@ -13,5 +13,5 @@ LL | | }; | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/loops/loop-proper-liveness.stderr b/tests/ui/loops/loop-proper-liveness.stderr index f9d94b6810cb0..bcd6eb353e525 100644 --- a/tests/ui/loops/loop-proper-liveness.stderr +++ b/tests/ui/loops/loop-proper-liveness.stderr @@ -13,6 +13,6 @@ help: consider assigning a value LL | let x: i32 = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/loops/loop-properly-diverging-2.stderr b/tests/ui/loops/loop-properly-diverging-2.stderr index 1d1ae60cda174..c9f27a6a672c6 100644 --- a/tests/ui/loops/loop-properly-diverging-2.stderr +++ b/tests/ui/loops/loop-properly-diverging-2.stderr @@ -12,6 +12,6 @@ help: give it a value of the expected type LL | let x: i32 = loop { break 42 }; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lto/debuginfo-lto.rs b/tests/ui/lto/debuginfo-lto.rs index 43f75b0344be7..e4beee9e737ba 100644 --- a/tests/ui/lto/debuginfo-lto.rs +++ b/tests/ui/lto/debuginfo-lto.rs @@ -7,7 +7,6 @@ // aux-build:debuginfo-lto-aux.rs // compile-flags: -C lto -g // no-prefer-dynamic -// ignore-asmjs wasm2js does not support source maps yet extern crate debuginfo_lto_aux; diff --git a/tests/ui/lto/issue-11154.stderr b/tests/ui/lto/issue-11154.stderr index 8eec8b37c85ec..4d52f6c0f3d76 100644 --- a/tests/ui/lto/issue-11154.stderr +++ b/tests/ui/lto/issue-11154.stderr @@ -2,5 +2,5 @@ error: cannot prefer dynamic linking when performing LTO note: only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/lto/lto-duplicate-symbols.stderr b/tests/ui/lto/lto-duplicate-symbols.stderr index f66afa94f4da7..7e421845258a3 100644 --- a/tests/ui/lto/lto-duplicate-symbols.stderr +++ b/tests/ui/lto/lto-duplicate-symbols.stderr @@ -2,5 +2,5 @@ warning: Linking globals named 'foo': symbol multiply defined! error: failed to load bitcode of module "lto-duplicate-symbols2.lto_duplicate_symbols2.HASH-cgu.0.rcgu.o": -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr index 4448f9326cb94..0d1f9a7690f9d 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr @@ -16,6 +16,6 @@ LL | | }; = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr index 0d61311350e8c..8396265356987 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr @@ -7,6 +7,6 @@ LL | _ => y, = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr index dd0fdf3a12abf..c3d7960de5641 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr @@ -15,6 +15,6 @@ LL | | }; = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr index cb046d0b0acad..8e4a514c7c6b8 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr @@ -7,6 +7,6 @@ LL | _ => y, = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr index e54fcf068d8e8..a1958cc436adc 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr @@ -14,6 +14,6 @@ LL | | }; = note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/macros/bad-concat.stderr b/tests/ui/macros/bad-concat.stderr index d67f3c33d36e3..85f5994c7204c 100644 --- a/tests/ui/macros/bad-concat.stderr +++ b/tests/ui/macros/bad-concat.stderr @@ -6,5 +6,5 @@ LL | let _ = concat!(x, y, z, "bar"); | = note: only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/bang-after-name.stderr b/tests/ui/macros/bang-after-name.stderr index f609c4943ef21..27853161e4f31 100644 --- a/tests/ui/macros/bang-after-name.stderr +++ b/tests/ui/macros/bang-after-name.stderr @@ -4,5 +4,5 @@ error: macro names aren't followed by a `!` LL | macro_rules! foo! { | ^ help: remove the `!` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/best-failure.stderr b/tests/ui/macros/best-failure.stderr index a52fc5e3da6a5..c5f8b9abc19a1 100644 --- a/tests/ui/macros/best-failure.stderr +++ b/tests/ui/macros/best-failure.stderr @@ -17,5 +17,5 @@ LL | (neg false, $self:ident) => { $self }; | ^^^^^^^^^^^ = note: this error originates in the macro `number` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/derive-in-eager-expansion-hang.stderr b/tests/ui/macros/derive-in-eager-expansion-hang.stderr index e0a4f3878d8bb..e0f6d5b2de009 100644 --- a/tests/ui/macros/derive-in-eager-expansion-hang.stderr +++ b/tests/ui/macros/derive-in-eager-expansion-hang.stderr @@ -18,5 +18,5 @@ help: you might be missing a string literal to format with LL | format_args!("{}", hang!()); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/duplicate-builtin.stderr b/tests/ui/macros/duplicate-builtin.stderr index 58accea27bb96..887a4fbbdc8e0 100644 --- a/tests/ui/macros/duplicate-builtin.stderr +++ b/tests/ui/macros/duplicate-builtin.stderr @@ -16,6 +16,6 @@ LL | | /* compiler built-in */ LL | | } | |_^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0773`. diff --git a/tests/ui/macros/include-single-expr.stderr b/tests/ui/macros/include-single-expr.stderr index 80eecf8f1b979..e99109e11729c 100644 --- a/tests/ui/macros/include-single-expr.stderr +++ b/tests/ui/macros/include-single-expr.stderr @@ -6,5 +6,5 @@ LL | 10 | = note: `#[deny(incomplete_include)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-100199.stderr b/tests/ui/macros/issue-100199.stderr index 89a6f585ce415..89c634ce4f0b5 100644 --- a/tests/ui/macros/issue-100199.stderr +++ b/tests/ui/macros/issue-100199.stderr @@ -10,6 +10,6 @@ help: consider importing this trait LL + use traits::MyTrait; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/macros/issue-102878.stderr b/tests/ui/macros/issue-102878.stderr index 034e3731b87fa..1971a6bd12e42 100644 --- a/tests/ui/macros/issue-102878.stderr +++ b/tests/ui/macros/issue-102878.stderr @@ -7,5 +7,5 @@ LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} | |unclosed delimiter | closing delimiter possibly meant for this -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-105011.stderr b/tests/ui/macros/issue-105011.stderr index e898af7faa30a..ae59102684d54 100644 --- a/tests/ui/macros/issue-105011.stderr +++ b/tests/ui/macros/issue-105011.stderr @@ -4,5 +4,5 @@ error: suffixes on string literals are invalid LL | println!(""y); | ^^^ invalid suffix `y` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-109237.stderr b/tests/ui/macros/issue-109237.stderr index d125cff63eab2..a335786df8642 100644 --- a/tests/ui/macros/issue-109237.stderr +++ b/tests/ui/macros/issue-109237.stderr @@ -14,5 +14,5 @@ help: surround the macro invocation with `{}` to interpret the expansion as a st LL | let _ = { statement!(); }; | ~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-16098.stderr b/tests/ui/macros/issue-16098.stderr index 64280219d7592..a7249981648c0 100644 --- a/tests/ui/macros/issue-16098.stderr +++ b/tests/ui/macros/issue-16098.stderr @@ -10,5 +10,5 @@ LL | println!("Problem 1: {}", prob1!(1000)); = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`) = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-19163.stderr b/tests/ui/macros/issue-19163.stderr index af509aa59d481..95af07d82d8f9 100644 --- a/tests/ui/macros/issue-19163.stderr +++ b/tests/ui/macros/issue-19163.stderr @@ -4,6 +4,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | mywrite!(&v, "Hello world"); | ^^ cannot borrow as mutable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/macros/issue-21356.stderr b/tests/ui/macros/issue-21356.stderr index 17014c6ceeeb4..dd09da6df4f43 100644 --- a/tests/ui/macros/issue-21356.stderr +++ b/tests/ui/macros/issue-21356.stderr @@ -6,5 +6,5 @@ LL | macro_rules! test { ($wrong:t_ty ..) => () } | = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-26094.stderr b/tests/ui/macros/issue-26094.stderr index ecdf48470f730..0b614e3e5f8cb 100644 --- a/tests/ui/macros/issue-26094.stderr +++ b/tests/ui/macros/issue-26094.stderr @@ -13,6 +13,6 @@ note: function defined here LL | fn some_function() {} | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/macros/issue-29084.stderr b/tests/ui/macros/issue-29084.stderr index f83e192130bdb..9c33e4e8427ab 100644 --- a/tests/ui/macros/issue-29084.stderr +++ b/tests/ui/macros/issue-29084.stderr @@ -19,6 +19,6 @@ LL | foo!(0u8); | --------- in this macro invocation = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/macros/issue-35450.stderr b/tests/ui/macros/issue-35450.stderr index f2065689f444e..6f06df3861db4 100644 --- a/tests/ui/macros/issue-35450.stderr +++ b/tests/ui/macros/issue-35450.stderr @@ -4,5 +4,5 @@ error: expected expression, found `$` LL | m!($t); | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-39388.stderr b/tests/ui/macros/issue-39388.stderr index 62e7dff547692..c94662c2d7f8e 100644 --- a/tests/ui/macros/issue-39388.stderr +++ b/tests/ui/macros/issue-39388.stderr @@ -4,5 +4,5 @@ error: expected one of: `*`, `+`, or `?` LL | (($($a:tt)*) = ($($b:tt))*) => { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-39404.stderr b/tests/ui/macros/issue-39404.stderr index 3886a70bb15c4..33cafd93a4042 100644 --- a/tests/ui/macros/issue-39404.stderr +++ b/tests/ui/macros/issue-39404.stderr @@ -8,5 +8,5 @@ LL | macro_rules! m { ($i) => {} } = note: for more information, see issue #40107 = note: `#[deny(missing_fragment_specifier)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-41776.stderr b/tests/ui/macros/issue-41776.stderr index e06873b50265d..ea926e0103add 100644 --- a/tests/ui/macros/issue-41776.stderr +++ b/tests/ui/macros/issue-41776.stderr @@ -4,5 +4,5 @@ error: argument must be a string literal LL | include!(line!()); | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-42954.stderr b/tests/ui/macros/issue-42954.stderr index 396a91994eb59..d5a8a117f9a37 100644 --- a/tests/ui/macros/issue-42954.stderr +++ b/tests/ui/macros/issue-42954.stderr @@ -15,5 +15,5 @@ help: try comparing the cast value LL | ($i as u32) < 0 | + + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-54441.stderr b/tests/ui/macros/issue-54441.stderr index bbbca211b8d17..fb2c103139b97 100644 --- a/tests/ui/macros/issue-54441.stderr +++ b/tests/ui/macros/issue-54441.stderr @@ -9,5 +9,5 @@ LL | m!(); | = note: the usage of `m!` is likely invalid in foreign item context -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-58490.stderr b/tests/ui/macros/issue-58490.stderr index b1f0896f3b65c..4e796333748c1 100644 --- a/tests/ui/macros/issue-58490.stderr +++ b/tests/ui/macros/issue-58490.stderr @@ -9,6 +9,6 @@ LL | macro_rules! b { () => () } | = note: `b` must be defined only once in the macro namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/macros/issue-61053-duplicate-binder.stderr b/tests/ui/macros/issue-61053-duplicate-binder.stderr index 5a2af45d077c4..7c7cb26b4071e 100644 --- a/tests/ui/macros/issue-61053-duplicate-binder.stderr +++ b/tests/ui/macros/issue-61053-duplicate-binder.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(meta_variable_misuse)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-6596-1.stderr b/tests/ui/macros/issue-6596-1.stderr index 7ab3685c5cbf1..f20d67329dbe7 100644 --- a/tests/ui/macros/issue-6596-1.stderr +++ b/tests/ui/macros/issue-6596-1.stderr @@ -9,5 +9,5 @@ LL | e!(foo); | = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-78325-inconsistent-resolution.stderr b/tests/ui/macros/issue-78325-inconsistent-resolution.stderr index 53a0a0793b262..b75e4a9c9e064 100644 --- a/tests/ui/macros/issue-78325-inconsistent-resolution.stderr +++ b/tests/ui/macros/issue-78325-inconsistent-resolution.stderr @@ -9,5 +9,5 @@ LL | define_other_core!(); | = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-83340.stderr b/tests/ui/macros/issue-83340.stderr index 1935de02b57a9..0a083ec1d9ceb 100644 --- a/tests/ui/macros/issue-83340.stderr +++ b/tests/ui/macros/issue-83340.stderr @@ -4,5 +4,5 @@ error: 1 positional argument in format string, but no arguments were given LL | \n {} │", | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-83344.stderr b/tests/ui/macros/issue-83344.stderr index 1ef70f87a1fb4..9c404aeb429eb 100644 --- a/tests/ui/macros/issue-83344.stderr +++ b/tests/ui/macros/issue-83344.stderr @@ -4,5 +4,5 @@ error: 1 positional argument in format string, but no arguments were given LL | println!("{}\ | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-84195-lint-anon-const.stderr b/tests/ui/macros/issue-84195-lint-anon-const.stderr index 29ccd17e06999..d9042adfc375a 100644 --- a/tests/ui/macros/issue-84195-lint-anon-const.stderr +++ b/tests/ui/macros/issue-84195-lint-anon-const.stderr @@ -16,7 +16,7 @@ LL | #![deny(semicolon_in_expressions_from_macros)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: error: trailing semicolon in macro used in expression position diff --git a/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr b/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr index e266617bd2249..c395e0c9100d3 100644 --- a/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr +++ b/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr @@ -10,5 +10,5 @@ LL | a!(A, A, A, A, A, A, A, A, A, A, A); = help: consider increasing the recursion limit by adding a `#![recursion_limit = "30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`) = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-92267.stderr b/tests/ui/macros/issue-92267.stderr index 5359f68cd5517..4259815328b30 100644 --- a/tests/ui/macros/issue-92267.stderr +++ b/tests/ui/macros/issue-92267.stderr @@ -12,5 +12,5 @@ LL | pub fn main() { println!("🦀%%%", 0) } | ^^ = note: printf formatting is not supported; see the documentation for `std::fmt` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-attribute.stderr b/tests/ui/macros/macro-attribute.stderr index 3316d38726487..bbcaaba66e51b 100644 --- a/tests/ui/macros/macro-attribute.stderr +++ b/tests/ui/macros/macro-attribute.stderr @@ -4,5 +4,5 @@ error: expected expression, found `$` LL | #[doc = $not_there] | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-backtrace-println.stderr b/tests/ui/macros/macro-backtrace-println.stderr index b4e2883e83716..9e65cc3dcd62d 100644 --- a/tests/ui/macros/macro-backtrace-println.stderr +++ b/tests/ui/macros/macro-backtrace-println.stderr @@ -9,5 +9,5 @@ LL | myprintln!("{}"); | = note: this error originates in the macro `concat` which comes from the expansion of the macro `myprintln` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-crate-nonterminal-non-root.stderr b/tests/ui/macros/macro-crate-nonterminal-non-root.stderr index 1eca0186da955..10b78d6eb39f7 100644 --- a/tests/ui/macros/macro-crate-nonterminal-non-root.stderr +++ b/tests/ui/macros/macro-crate-nonterminal-non-root.stderr @@ -4,6 +4,6 @@ error[E0468]: an `extern crate` loading macros must be at the crate root LL | extern crate macro_crate_nonterminal; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0468`. diff --git a/tests/ui/macros/macro-in-expression-context-2.stderr b/tests/ui/macros/macro-in-expression-context-2.stderr index d0312c4850824..1813a2ec792b1 100644 --- a/tests/ui/macros/macro-in-expression-context-2.stderr +++ b/tests/ui/macros/macro-in-expression-context-2.stderr @@ -13,5 +13,5 @@ help: add `;` to interpret the expansion as a statement LL | _ => { empty!(); } | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-in-expression-context.stderr b/tests/ui/macros/macro-in-expression-context.stderr index 3f492b141a5f5..2eee63f307af9 100644 --- a/tests/ui/macros/macro-in-expression-context.stderr +++ b/tests/ui/macros/macro-in-expression-context.stderr @@ -29,7 +29,7 @@ LL | foo!() = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted Future incompatibility report: Future breakage diagnostic: warning: trailing semicolon in macro used in expression position diff --git a/tests/ui/macros/macro-inner-attributes.stderr b/tests/ui/macros/macro-inner-attributes.stderr index 77b6486155cd2..b6e10f45e3810 100644 --- a/tests/ui/macros/macro-inner-attributes.stderr +++ b/tests/ui/macros/macro-inner-attributes.stderr @@ -9,6 +9,6 @@ help: there is a crate or module with a similar name LL | b::bar(); | ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr index 7ef1fcbbce3e7..e6b39dfef8581 100644 --- a/tests/ui/macros/macro-interpolation.stderr +++ b/tests/ui/macros/macro-interpolation.stderr @@ -12,5 +12,5 @@ LL | let _: qpath!(ty, ::Owned); | = note: this error originates in the macro `qpath` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-invalid-fragment-spec.stderr b/tests/ui/macros/macro-invalid-fragment-spec.stderr index b047344826551..919111ede51dc 100644 --- a/tests/ui/macros/macro-invalid-fragment-spec.stderr +++ b/tests/ui/macros/macro-invalid-fragment-spec.stderr @@ -6,5 +6,5 @@ LL | ($x:foo) => () | = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-local-data-key-priv.stderr b/tests/ui/macros/macro-local-data-key-priv.stderr index 0f412bc86fb31..e93bd11046d09 100644 --- a/tests/ui/macros/macro-local-data-key-priv.stderr +++ b/tests/ui/macros/macro-local-data-key-priv.stderr @@ -11,6 +11,6 @@ LL | thread_local!(static baz: f64 = 0.0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/macros/macro-missing-delimiters.stderr b/tests/ui/macros/macro-missing-delimiters.stderr index e7c37c8ddbebd..1fe714aa7aadf 100644 --- a/tests/ui/macros/macro-missing-delimiters.stderr +++ b/tests/ui/macros/macro-missing-delimiters.stderr @@ -4,5 +4,5 @@ error: invalid macro matcher; matchers must be contained in balanced delimiters LL | baz => () | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-missing-fragment.stderr b/tests/ui/macros/macro-missing-fragment.stderr index 2aa1e58f6b155..1089f67f4336d 100644 --- a/tests/ui/macros/macro-missing-fragment.stderr +++ b/tests/ui/macros/macro-missing-fragment.stderr @@ -36,5 +36,5 @@ LL | ( $name ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 -error: aborting due to previous error; 3 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted diff --git a/tests/ui/macros/macro-name-typo.stderr b/tests/ui/macros/macro-name-typo.stderr index d7c8aaae22e1e..9059b10faaacd 100644 --- a/tests/ui/macros/macro-name-typo.stderr +++ b/tests/ui/macros/macro-name-typo.stderr @@ -7,5 +7,5 @@ LL | printlx!("oh noes!"); | = note: similarly named macro `println` defined here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-non-lifetime.stderr b/tests/ui/macros/macro-non-lifetime.stderr index e1ed87f943551..9ff3d741c01d2 100644 --- a/tests/ui/macros/macro-non-lifetime.stderr +++ b/tests/ui/macros/macro-non-lifetime.stderr @@ -13,5 +13,5 @@ note: while trying to match meta-variable `$x:lifetime` LL | macro_rules! m { ($x:lifetime) => { } } | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-outer-attributes.stderr b/tests/ui/macros/macro-outer-attributes.stderr index 0418e6116041b..87c0655a422d6 100644 --- a/tests/ui/macros/macro-outer-attributes.stderr +++ b/tests/ui/macros/macro-outer-attributes.stderr @@ -19,6 +19,6 @@ LL - a::bar(); LL + bar(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/macros/macro-parameter-span.stderr b/tests/ui/macros/macro-parameter-span.stderr index 24e3e89ea9bf3..247750a8ad705 100644 --- a/tests/ui/macros/macro-parameter-span.stderr +++ b/tests/ui/macros/macro-parameter-span.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `x` in this scope LL | x | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/macros/macro-path-prelude-fail-2.stderr b/tests/ui/macros/macro-path-prelude-fail-2.stderr index 9574b7a1e25f1..87646031cdb82 100644 --- a/tests/ui/macros/macro-path-prelude-fail-2.stderr +++ b/tests/ui/macros/macro-path-prelude-fail-2.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: partially resolved path in a macro LL | Result::Ok!(); | ^^^^^^^^^^ partially resolved path in a macro -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/macro-path-prelude-fail-3.stderr b/tests/ui/macros/macro-path-prelude-fail-3.stderr index f1c3512bc9b8e..485d7b7869a9a 100644 --- a/tests/ui/macros/macro-path-prelude-fail-3.stderr +++ b/tests/ui/macros/macro-path-prelude-fail-3.stderr @@ -9,5 +9,5 @@ LL | inline!(); | = note: `inline` is in scope, but it is an attribute: `#[inline]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-path-prelude-fail-4.stderr b/tests/ui/macros/macro-path-prelude-fail-4.stderr index 81c6722b56a82..642d9e84874bc 100644 --- a/tests/ui/macros/macro-path-prelude-fail-4.stderr +++ b/tests/ui/macros/macro-path-prelude-fail-4.stderr @@ -12,5 +12,5 @@ LL | #[derive(inline)] = help: add as non-Derive macro `#[inline]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-path-prelude-shadowing.stderr b/tests/ui/macros/macro-path-prelude-shadowing.stderr index 4a864c2e92718..e719c397ff212 100644 --- a/tests/ui/macros/macro-path-prelude-shadowing.stderr +++ b/tests/ui/macros/macro-path-prelude-shadowing.stderr @@ -14,6 +14,6 @@ LL | use m2::*; // glob-import user-defined `std` = help: consider adding an explicit import of `std` to disambiguate = help: or use `self::std` to refer to this module unambiguously -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/macro-use-bad-args-1.stderr b/tests/ui/macros/macro-use-bad-args-1.stderr index 4e5482a518c95..6d2f159a57406 100644 --- a/tests/ui/macros/macro-use-bad-args-1.stderr +++ b/tests/ui/macros/macro-use-bad-args-1.stderr @@ -4,6 +4,6 @@ error[E0466]: bad macro import LL | #[macro_use(foo(bar))] | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0466`. diff --git a/tests/ui/macros/macro-use-bad-args-2.stderr b/tests/ui/macros/macro-use-bad-args-2.stderr index c958104eac43b..364f3da6e15ab 100644 --- a/tests/ui/macros/macro-use-bad-args-2.stderr +++ b/tests/ui/macros/macro-use-bad-args-2.stderr @@ -4,6 +4,6 @@ error[E0466]: bad macro import LL | #[macro_use(foo="bar")] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0466`. diff --git a/tests/ui/macros/macro-use-undef.stderr b/tests/ui/macros/macro-use-undef.stderr index 85b86e2211f2d..adbf5274e68ec 100644 --- a/tests/ui/macros/macro-use-undef.stderr +++ b/tests/ui/macros/macro-use-undef.stderr @@ -4,6 +4,6 @@ error[E0469]: imported macro not found LL | #[macro_use(macro_two, no_way)] | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0469`. diff --git a/tests/ui/macros/macro-use-wrong-name.stderr b/tests/ui/macros/macro-use-wrong-name.stderr index 36339542ac61f..89345866be804 100644 --- a/tests/ui/macros/macro-use-wrong-name.stderr +++ b/tests/ui/macros/macro-use-wrong-name.stderr @@ -18,5 +18,5 @@ help: consider importing this macro LL + use two_macros::macro_two; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro_path_as_generic_bound.stderr b/tests/ui/macros/macro_path_as_generic_bound.stderr index 00d954d24f380..e25ff57e57f36 100644 --- a/tests/ui/macros/macro_path_as_generic_bound.stderr +++ b/tests/ui/macros/macro_path_as_generic_bound.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `m` LL | foo!(m::m2::A); | ^ use of undeclared crate or module `m` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/macro_undefined.stderr b/tests/ui/macros/macro_undefined.stderr index 4ab16bd10173d..cc3efacbc5415 100644 --- a/tests/ui/macros/macro_undefined.stderr +++ b/tests/ui/macros/macro_undefined.stderr @@ -7,5 +7,5 @@ LL | macro_rules! kl { LL | k!(); | ^ help: a macro with a similar name exists: `kl` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/malformed_macro_lhs.stderr b/tests/ui/macros/malformed_macro_lhs.stderr index adf64b089350d..0c8c4850bfa7d 100644 --- a/tests/ui/macros/malformed_macro_lhs.stderr +++ b/tests/ui/macros/malformed_macro_lhs.stderr @@ -4,5 +4,5 @@ error: invalid macro matcher; matchers must be contained in balanced delimiters LL | t => (1); | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/meta-variable-depth-outside-repeat.stderr b/tests/ui/macros/meta-variable-depth-outside-repeat.stderr index fad150cadfca6..49b5053a023cc 100644 --- a/tests/ui/macros/meta-variable-depth-outside-repeat.stderr +++ b/tests/ui/macros/meta-variable-depth-outside-repeat.stderr @@ -4,5 +4,5 @@ error: meta-variable expression `length` with depth parameter must be called ins LL | ${length(0)} | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index c2b047022ed5a..499f9a7637d22 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -1,6 +1,8 @@ error: no rules expected the token `enum E {}` --> $DIR/nonterminal-matching.rs:19:10 | +LL | macro complex_nonterminal($nt_item: item) { + | -------------- LL | macro n(a $nt_item b) { | --------------------- when calling this macro ... @@ -23,5 +25,5 @@ LL | complex_nonterminal!(enum E {}); = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/not-utf8.stderr b/tests/ui/macros/not-utf8.stderr index 7e1f2dcad11c4..bf4704285c0dd 100644 --- a/tests/ui/macros/not-utf8.stderr +++ b/tests/ui/macros/not-utf8.stderr @@ -6,5 +6,5 @@ LL | include!("not-utf8.bin") | = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/out-of-order-shadowing.stderr b/tests/ui/macros/out-of-order-shadowing.stderr index dedefac5c464c..8795f7d4345bd 100644 --- a/tests/ui/macros/out-of-order-shadowing.stderr +++ b/tests/ui/macros/out-of-order-shadowing.stderr @@ -17,6 +17,6 @@ LL | macro_rules! bar { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `define_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/recovery-allowed.stderr b/tests/ui/macros/recovery-allowed.stderr index ec036e8b1e24b..44689853dabcc 100644 --- a/tests/ui/macros/recovery-allowed.stderr +++ b/tests/ui/macros/recovery-allowed.stderr @@ -6,5 +6,5 @@ LL | please_recover! { not 1 } | | | help: use `!` to perform bitwise not -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/span-covering-argument-1.stderr b/tests/ui/macros/span-covering-argument-1.stderr index e57347b362dd4..9ad2bc73a4ff5 100644 --- a/tests/ui/macros/span-covering-argument-1.stderr +++ b/tests/ui/macros/span-covering-argument-1.stderr @@ -13,6 +13,6 @@ help: consider changing this to be mutable LL | let mut $s = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index f1bbd4a621095..c0eb7f01fdbf0 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -11,6 +11,7 @@ #![feature(decl_macro)] #![feature(explicit_tail_calls)] #![feature(more_qualified_paths)] +#![feature(never_patterns)] #![feature(raw_ref_op)] #![feature(trait_alias)] #![feature(try_blocks)] @@ -115,6 +116,7 @@ fn test_expr() { "a + b * c - d + -1 * -2 - -3", "a + b * c - d + - 1 * - 2 - - 3" ); + c2!(expr, [ x = !y ], "x = !y", "x =! y"); // FIXME // ExprKind::Unary c2!(expr, [ *expr ], "*expr", "* expr"); @@ -137,6 +139,7 @@ fn test_expr() { // ExprKind::If c1!(expr, [ if true {} ], "if true {}"); + c2!(expr, [ if !true {} ], "if !true {}", "if! true {}"); // FIXME c2!(expr, [ if ::std::blah() { } else { } ], "if ::std::blah() {} else {}", @@ -633,6 +636,10 @@ fn test_pat() { // PatKind::Rest c1!(pat, [ .. ], ".."); + // PatKind::Never + c1!(pat, [ Some(!) ], "Some(!)"); + c1!(pat, [ None | Some(!) ], "None | Some(!)"); + // PatKind::Paren c1!(pat, [ (pat) ], "(pat)"); @@ -799,3 +806,32 @@ fn test_vis() { assert_eq!(inherited_vis!(struct), ""); assert_eq!(stringify!(), ""); } + +macro_rules! p { + ([$($tt:tt)*], $s:literal) => { + assert_eq!(stringify!($($tt)*), $s); + }; +} + +#[test] +fn test_punct() { + // For all these cases, we must preserve spaces between the tokens. + // Otherwise, any old proc macro that parses pretty-printed code might glue + // together tokens that shouldn't be glued. + p!([ = = < < <= <= == == != != >= >= > > ], "= = < < <= <= == == != != >= >= > >"); + p!([ && && & & || || | | ! ! ], "&& && & & || || | |!!"); // FIXME + p!([ ~ ~ @ @ # # ], "~ ~ @ @ # #"); + p!([ . . .. .. ... ... ..= ..=], ".... .. ... ... ..= ..="); // FIXME + p!([ , , ; ; : : :: :: ], ",, ; ; : : :: ::"); // FIXME + p!([ -> -> <- <- => =>], "-> -> <- <- => =>"); + p!([ $ $ ? ? ' ' ], "$$? ? ' '"); // FIXME + p!([ + + += += - - -= -= * * *= *= / / /= /= ], "+ + += += - - -= -= * * *= *= / / /= /="); + p!([ % % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>= ], + "% % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>="); + + // For these one we must insert spaces between adjacent tokens, again due + // to proc macros. + p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ? = | > >> @ - -> <- - $$== == =>"); // FIXME + p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ", ; ;, * * @ @ $+ $> < < > ? ? += ="); // FIXME + p!([ :#!@|$=&*,+;*~? ], ": #! @ | $= & *, + ; * ~ ?"); // FIXME +} diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs index ae6de3c5046cd..f6178c137db97 100644 --- a/tests/ui/macros/syntax-error-recovery.rs +++ b/tests/ui/macros/syntax-error-recovery.rs @@ -9,7 +9,7 @@ macro_rules! values { } }; } -//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)` +//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)` //~| ERROR macro expansion ignores token `(String)` and any following values!(STRING(1) as (String) => cfg(test),); diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr index c42ee9b295e1d..6218bf43a1ef2 100644 --- a/tests/ui/macros/syntax-error-recovery.stderr +++ b/tests/ui/macros/syntax-error-recovery.stderr @@ -1,4 +1,4 @@ -error: expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)` +error: expected one of `(`, `,`, `=`, `{`, or `}`, found type `(String)` --> $DIR/syntax-error-recovery.rs:7:26 | LL | $token $($inner)? = $value, diff --git a/tests/ui/macros/trace_faulty_macros.rs b/tests/ui/macros/trace_faulty_macros.rs index b2fdd2e196581..00eb7593799e2 100644 --- a/tests/ui/macros/trace_faulty_macros.rs +++ b/tests/ui/macros/trace_faulty_macros.rs @@ -41,3 +41,14 @@ fn use_bang_macro_as_attr() {} #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s fn use_derive_macro_as_attr() {} + +macro_rules! test { + (let $p:pat = $e:expr) => {test!(($p,$e))}; + // this should be expr + // vvv + (($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found pattern `1 + 1` +} + +fn foo() { + test!(let x = 1+1); +} diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr index 21e47da075716..6a89d3bfd095e 100644 --- a/tests/ui/macros/trace_faulty_macros.stderr +++ b/tests/ui/macros/trace_faulty_macros.stderr @@ -50,7 +50,7 @@ LL | my_recursive_macro!(); = note: expanding `my_recursive_macro! { }` = note: to `my_recursive_macro! () ;` -error: expected expression, found `A { a: a, b: 0, c: _, .. }` +error: expected expression, found pattern `A { a: a, b: 0, c: _, .. }` --> $DIR/trace_faulty_macros.rs:16:9 | LL | $a @@ -69,6 +69,28 @@ LL | #[derive(Debug)] LL | fn use_derive_macro_as_attr() {} | -------------------------------- not a `struct`, `enum` or `union` +error: expected expression, found pattern `1 + 1` + --> $DIR/trace_faulty_macros.rs:49:37 + | +LL | (let $p:pat = $e:expr) => {test!(($p,$e))}; + | ------- -- this is interpreted as expression, but it is expected to be pattern + | | + | this macro fragment matcher is expression +... +LL | (($p:pat, $e:pat)) => {let $p = $e;}; + | ------ ^^ expected expression + | | + | this macro fragment matcher is pattern +... +LL | test!(let x = 1+1); + | ------------------ + | | | + | | this is expected to be expression + | in this macro invocation + | + = note: when forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type, not the underlying tokens + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + note: trace_macro --> $DIR/trace_faulty_macros.rs:36:13 | @@ -80,6 +102,17 @@ LL | let a = pat_macro!(); = note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }` = note: to `A { a: a, b: 0, c: _, .. }` -error: aborting due to 4 previous errors +note: trace_macro + --> $DIR/trace_faulty_macros.rs:53:5 + | +LL | test!(let x = 1+1); + | ^^^^^^^^^^^^^^^^^^ + | + = note: expanding `test! { let x = 1 + 1 }` + = note: to `test! ((x, 1 + 1))` + = note: expanding `test! { (x, 1 + 1) }` + = note: to `let x = 1 + 1 ;` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/macros/unreachable-arg.edition_2021.stderr b/tests/ui/macros/unreachable-arg.edition_2021.stderr index d70ef31eed65c..ddaa2b9c1efe1 100644 --- a/tests/ui/macros/unreachable-arg.edition_2021.stderr +++ b/tests/ui/macros/unreachable-arg.edition_2021.stderr @@ -9,5 +9,5 @@ help: you might be missing a string literal to format with LL | unreachable!("{}", a); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/unreachable-format-args.edition_2015.stderr b/tests/ui/macros/unreachable-format-args.edition_2015.stderr index 2cc2e134bfdf6..6a133d5e40647 100644 --- a/tests/ui/macros/unreachable-format-args.edition_2015.stderr +++ b/tests/ui/macros/unreachable-format-args.edition_2015.stderr @@ -8,5 +8,5 @@ LL | unreachable!("x is {x} and y is {y}", y = 0); = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro = note: this error originates in the macro `$crate::concat` which comes from the expansion of the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/macros/vec-macro-in-pattern.stderr b/tests/ui/macros/vec-macro-in-pattern.stderr index 7060f5d8b4791..447f5dcf8644f 100644 --- a/tests/ui/macros/vec-macro-in-pattern.stderr +++ b/tests/ui/macros/vec-macro-in-pattern.stderr @@ -6,5 +6,5 @@ LL | Some(vec![43]) => {} | = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/main-wrong-location.stderr b/tests/ui/main-wrong-location.stderr index 3d64b0a67a1df..9486a94056283 100644 --- a/tests/ui/main-wrong-location.stderr +++ b/tests/ui/main-wrong-location.stderr @@ -12,6 +12,6 @@ LL | fn main() { } = note: you have one or more functions named `main` not defined at the crate level = help: consider moving the `main` function definitions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/main-wrong-type.stderr b/tests/ui/main-wrong-type.stderr index 1e5f368758e6a..d07fc09064f2b 100644 --- a/tests/ui/main-wrong-type.stderr +++ b/tests/ui/main-wrong-type.stderr @@ -7,6 +7,6 @@ LL | fn main(foo: S) { = note: expected signature `fn()` found signature `fn(S)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr index 89e0d982eafdc..ad90aeda1d13b 100644 --- a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr +++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr @@ -8,5 +8,5 @@ LL | fn a(){{{ | |unclosed delimiter | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/malformed/issue-69341-malformed-derive-inert.stderr b/tests/ui/malformed/issue-69341-malformed-derive-inert.stderr index 04f7ebe019ea4..99f709eadb73d 100644 --- a/tests/ui/malformed/issue-69341-malformed-derive-inert.stderr +++ b/tests/ui/malformed/issue-69341-malformed-derive-inert.stderr @@ -4,5 +4,5 @@ error: expected non-macro attribute, found attribute macro `derive` LL | #[derive(parse())] | ^^^^^^ not a non-macro attribute -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/manual/manual-link-framework.stderr b/tests/ui/manual/manual-link-framework.stderr index de045d56c9ccd..38d2302a48d27 100644 --- a/tests/ui/manual/manual-link-framework.stderr +++ b/tests/ui/manual/manual-link-framework.stderr @@ -1,4 +1,4 @@ error: library kind `framework` is only supported on Apple targets -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait.stderr b/tests/ui/marker_trait_attr/overlap-marker-trait.stderr index 133bc0484ee00..cdad382d11cf4 100644 --- a/tests/ui/marker_trait_attr/overlap-marker-trait.stderr +++ b/tests/ui/marker_trait_attr/overlap-marker-trait.stderr @@ -10,6 +10,6 @@ note: required by a bound in `is_marker` LL | fn is_marker() { } | ^^^^^^ required by this bound in `is_marker` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr b/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr index 64bccda56c65e..daee4e66ad102 100644 --- a/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr +++ b/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | impl F for T {} | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/marker_trait_attr/unsound-overlap.stderr b/tests/ui/marker_trait_attr/unsound-overlap.stderr index 5ebac8270ddff..5e58f5227ed61 100644 --- a/tests/ui/marker_trait_attr/unsound-overlap.stderr +++ b/tests/ui/marker_trait_attr/unsound-overlap.stderr @@ -7,6 +7,6 @@ LL | impl TraitWithAssoc for T { LL | impl TraitWithAssoc for ((&str,),) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `((&str,),)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/match/issue-11319.stderr b/tests/ui/match/issue-11319.stderr index fc44205e81e6c..8280547af43d3 100644 --- a/tests/ui/match/issue-11319.stderr +++ b/tests/ui/match/issue-11319.stderr @@ -16,6 +16,6 @@ LL | | _ => true LL | | } | |_____- `match` arms have incompatible types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/issue-70972-dyn-trait.stderr b/tests/ui/match/issue-70972-dyn-trait.stderr index f4dc910c34a65..b0af50f8599c5 100644 --- a/tests/ui/match/issue-70972-dyn-trait.stderr +++ b/tests/ui/match/issue-70972-dyn-trait.stderr @@ -4,5 +4,5 @@ error: `dyn Send` cannot be used in patterns LL | F => panic!(), | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/match/issue-74050-end-span.stderr b/tests/ui/match/issue-74050-end-span.stderr index 0dafeae870ef6..3a311eb00ccbf 100644 --- a/tests/ui/match/issue-74050-end-span.stderr +++ b/tests/ui/match/issue-74050-end-span.stderr @@ -11,6 +11,6 @@ LL | match arg.to_str() { LL | } | - `arg` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/match/issue-91058.stderr b/tests/ui/match/issue-91058.stderr index 12f37274b6b21..e91063de8e08c 100644 --- a/tests/ui/match/issue-91058.stderr +++ b/tests/ui/match/issue-91058.stderr @@ -6,6 +6,6 @@ LL | match array { LL | [()] => {} | ^^ expected `S`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/issue-92100.stderr b/tests/ui/match/issue-92100.stderr index 0f694c587fcb4..eb9f4ba1ad698 100644 --- a/tests/ui/match/issue-92100.stderr +++ b/tests/ui/match/issue-92100.stderr @@ -3,7 +3,12 @@ error[E0425]: cannot find value `a` in this scope | LL | [a.., a] => {} | ^ not found in this scope + | +help: if you meant to collect the rest of the slice in `a`, use the at operator + | +LL | [a @ .., a] => {} + | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/match/match-arm-resolving-to-never.stderr b/tests/ui/match/match-arm-resolving-to-never.stderr index 686fbd0baa3ce..6cbdf03d4c27d 100644 --- a/tests/ui/match/match-arm-resolving-to-never.stderr +++ b/tests/ui/match/match-arm-resolving-to-never.stderr @@ -13,6 +13,6 @@ LL | | E::F => "", LL | | }; | |_____- `match` arms have incompatible types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-ill-type2.stderr b/tests/ui/match/match-ill-type2.stderr index 5078f03d6017a..9d6bb5d1dcd24 100644 --- a/tests/ui/match/match-ill-type2.stderr +++ b/tests/ui/match/match-ill-type2.stderr @@ -7,6 +7,6 @@ LL | 1i32 => 1, LL | 2u32 => 1, | ^^^^ expected `i32`, found `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-join.stderr b/tests/ui/match/match-join.stderr index 27a82c1242cc7..4feb1bef9ad59 100644 --- a/tests/ui/match/match-join.stderr +++ b/tests/ui/match/match-join.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `x` in this scope LL | println!("{}", x); | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/match/match-no-arms-unreachable-after.stderr b/tests/ui/match/match-no-arms-unreachable-after.stderr index a0a3697266d4e..65ac1bae34495 100644 --- a/tests/ui/match/match-no-arms-unreachable-after.stderr +++ b/tests/ui/match/match-no-arms-unreachable-after.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/match/match-pattern-field-mismatch-2.stderr b/tests/ui/match/match-pattern-field-mismatch-2.stderr index ba32d0e99a471..12b143dd29b91 100644 --- a/tests/ui/match/match-pattern-field-mismatch-2.stderr +++ b/tests/ui/match/match-pattern-field-mismatch-2.stderr @@ -7,6 +7,6 @@ LL | NoColor, LL | Color::NoColor(_) => { } | ^^^^^^^^^^^^^^^^^ help: use this syntax instead: `Color::NoColor` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/match/match-pattern-field-mismatch.stderr b/tests/ui/match/match-pattern-field-mismatch.stderr index c994ee4f6d4ff..cde7ac972ca88 100644 --- a/tests/ui/match/match-pattern-field-mismatch.stderr +++ b/tests/ui/match/match-pattern-field-mismatch.stderr @@ -16,6 +16,6 @@ help: use `..` to ignore all fields LL | Color::Rgb(..) => { } | ~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0023`. diff --git a/tests/ui/match/match-ref-mut-invariance.stderr b/tests/ui/match/match-ref-mut-invariance.stderr index b353d3514febb..b9878a1953242 100644 --- a/tests/ui/match/match-ref-mut-invariance.stderr +++ b/tests/ui/match/match-ref-mut-invariance.stderr @@ -13,5 +13,5 @@ LL | match self.0 { ref mut x => x } = note: mutable references are invariant over their type parameter = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/match/match-ref-mut-let-invariance.stderr b/tests/ui/match/match-ref-mut-let-invariance.stderr index bb0fcdb99905c..27968239a8e54 100644 --- a/tests/ui/match/match-ref-mut-let-invariance.stderr +++ b/tests/ui/match/match-ref-mut-let-invariance.stderr @@ -14,5 +14,5 @@ LL | x = note: mutable references are invariant over their type parameter = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/match/match-struct.stderr b/tests/ui/match/match-struct.stderr index fdc6fd77077e0..b8abeab158bac 100644 --- a/tests/ui/match/match-struct.stderr +++ b/tests/ui/match/match-struct.stderr @@ -6,6 +6,6 @@ LL | match (S { a: 1 }) { LL | E::C(_) => (), | ^^^^^^^ expected `S`, found `E` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-tag-nullary.stderr b/tests/ui/match/match-tag-nullary.stderr index aac873c760e75..c9446d164337c 100644 --- a/tests/ui/match/match-tag-nullary.stderr +++ b/tests/ui/match/match-tag-nullary.stderr @@ -9,6 +9,6 @@ LL | fn main() { let x: A = A::A; match x { B::B => { } } } | | | this expression has type `A` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-tag-unary.stderr b/tests/ui/match/match-tag-unary.stderr index 25e8152d8cf50..fb4ec26646137 100644 --- a/tests/ui/match/match-tag-unary.stderr +++ b/tests/ui/match/match-tag-unary.stderr @@ -6,6 +6,6 @@ LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } | | | this expression has type `A` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-tail-expr-never-type-error.rs b/tests/ui/match/match-tail-expr-never-type-error.rs new file mode 100644 index 0000000000000..786ed3fa904be --- /dev/null +++ b/tests/ui/match/match-tail-expr-never-type-error.rs @@ -0,0 +1,16 @@ +fn never() -> ! { + loop {} +} + +fn bar(a: bool) { + match a { + true => 1, + false => { + never() //~ ERROR `match` arms have incompatible types + } + } +} +fn main() { + bar(true); + bar(false); +} diff --git a/tests/ui/match/match-tail-expr-never-type-error.stderr b/tests/ui/match/match-tail-expr-never-type-error.stderr new file mode 100644 index 0000000000000..226d33daeb254 --- /dev/null +++ b/tests/ui/match/match-tail-expr-never-type-error.stderr @@ -0,0 +1,21 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-tail-expr-never-type-error.rs:9:13 + | +LL | fn bar(a: bool) { + | - help: try adding a return type: `-> i32` +LL | / match a { +LL | | true => 1, + | | - this is found to be of type `{integer}` +LL | | false => { +LL | | never() + | | ^^^^^^^ + | | | + | | expected integer, found `()` + | | this expression is of type `!`, but it is coerced to `()` due to its surrounding expression +LL | | } +LL | | } + | |_____- `match` arms have incompatible types + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-unresolved-one-arm.stderr b/tests/ui/match/match-unresolved-one-arm.stderr index e3b501b2fd558..44571ac5326fe 100644 --- a/tests/ui/match/match-unresolved-one-arm.stderr +++ b/tests/ui/match/match-unresolved-one-arm.stderr @@ -9,6 +9,6 @@ help: consider giving `x` an explicit type LL | let x: /* Type */ = match () { | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/match/match-vec-mismatch-2.stderr b/tests/ui/match/match-vec-mismatch-2.stderr index 5247bea62ceb9..bdfe063d5bbd0 100644 --- a/tests/ui/match/match-vec-mismatch-2.stderr +++ b/tests/ui/match/match-vec-mismatch-2.stderr @@ -4,6 +4,6 @@ error[E0529]: expected an array or slice, found `()` LL | [()] => { } | ^^^^ pattern cannot match with input type `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/match/non-first-arm-doesnt-match-expected-return-type.stderr b/tests/ui/match/non-first-arm-doesnt-match-expected-return-type.stderr index e6d93b8b5f57b..5a6c9dff75796 100644 --- a/tests/ui/match/non-first-arm-doesnt-match-expected-return-type.stderr +++ b/tests/ui/match/non-first-arm-doesnt-match-expected-return-type.stderr @@ -7,6 +7,6 @@ LL | fn test(shouldwe: Option, shouldwe2: Option) -> u32 { LL | None => (), | ^^ expected `u32`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/single-line.stderr b/tests/ui/match/single-line.stderr index ec3b76e3f4d5e..15dc672c1fd92 100644 --- a/tests/ui/match/single-line.stderr +++ b/tests/ui/match/single-line.stderr @@ -7,6 +7,6 @@ LL | let _ = match Some(42) { Some(x) => x, None => "" }; | | this is found to be of type `{integer}` | `match` arms have incompatible types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/meta/expected-error-correct-rev.a.stderr b/tests/ui/meta/expected-error-correct-rev.a.stderr index 4adeebe2a591d..d5b7603d346d5 100644 --- a/tests/ui/meta/expected-error-correct-rev.a.stderr +++ b/tests/ui/meta/expected-error-correct-rev.a.stderr @@ -11,6 +11,6 @@ help: change the type of the numeric literal from `usize` to `u32` LL | let x: u32 = 22_u32; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr b/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr index 87330155eacca..4221dd04cfaac 100644 --- a/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr +++ b/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr @@ -11,6 +11,6 @@ help: change the type of the numeric literal from `usize` to `u32` LL | let x: u32 = 22_u32; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr index a9e9c679fdb67..ccdd9a95451b6 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8 @@ -52,9 +52,9 @@ LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::CONST; +LL | ::CONST; | ~~~~~~~~~~ -LL | ::CONST; +LL | ::CONST; | ~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr index 901bfc30a3f23..4172120770c6d 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-impl.rs:34:16 diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr index 0f9c60ce243df..2778f254a5619 100644 --- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr @@ -37,12 +37,12 @@ LL | fn foo(&self); | ^^^^^^^^^^^^^^ help: disambiguate the method for candidate #1 | -LL | A::foo(t); - | ~~~~~~~~~ +LL | A::foo(&t); + | ~~~~~~~~~~ help: disambiguate the method for candidate #2 | -LL | B::foo(t); - | ~~~~~~~~~ +LL | B::foo(&t); + | ~~~~~~~~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait-2.rs:20:16 @@ -62,10 +62,10 @@ LL | const CONST: usize; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = A::CONST; - | ~~~ -LL | let _ = B::CONST; - | ~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/disambiguate-multiple-trait-2.rs:52:12 @@ -98,10 +98,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait-2.rs:49:16 @@ -121,9 +121,9 @@ LL | const CONST: usize = 1; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ error: aborting due to 6 previous errors diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr index 9a50d51245ba9..e00498ca62b43 100644 --- a/tests/ui/methods/disambiguate-multiple-trait.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait.rs:27:16 @@ -52,9 +52,9 @@ LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/methods/issue-3707.stderr b/tests/ui/methods/issue-3707.stderr index 07c8101cbc68b..b3d4dfe5aaa88 100644 --- a/tests/ui/methods/issue-3707.stderr +++ b/tests/ui/methods/issue-3707.stderr @@ -14,6 +14,6 @@ note: the candidate is defined in an impl for the type `Obj` LL | pub fn boom() -> bool { | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/issues/issue-84495.stderr b/tests/ui/methods/issues/issue-84495.stderr index b0217a7c844d7..1603c0026bedf 100644 --- a/tests/ui/methods/issues/issue-84495.stderr +++ b/tests/ui/methods/issues/issue-84495.stderr @@ -8,6 +8,6 @@ LL | println!("{:?}", x.count()); `i32: Iterator` which is required by `&mut i32: Iterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/issues/issue-94581.stderr b/tests/ui/methods/issues/issue-94581.stderr index d6be29cf582c3..ae7446d483352 100644 --- a/tests/ui/methods/issues/issue-94581.stderr +++ b/tests/ui/methods/issues/issue-94581.stderr @@ -10,6 +10,6 @@ LL | let sqsum = get_slice().map(|i| i * i).sum(); `[i32]: Iterator` which is required by `&mut [i32]: Iterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr index 5132d92777bd6..0c775612bfbfc 100644 --- a/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr +++ b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr @@ -19,6 +19,6 @@ help: disambiguate the method for candidate #2 LL | fn main() { Me2::me(&1_usize); } | ~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr index 601e6bbb006f7..690f979fa37de 100644 --- a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr +++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr @@ -16,13 +16,13 @@ LL | trait B { fn foo(&self); } | ^^^^^^^^^^^^^^ help: disambiguate the method for candidate #1 | -LL | A::foo(t); - | ~~~~~~~~~ +LL | A::foo(&t); + | ~~~~~~~~~~ help: disambiguate the method for candidate #2 | -LL | B::foo(t); - | ~~~~~~~~~ +LL | B::foo(&t); + | ~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls.stderr index 313591433918f..8be6d6d64f7e5 100644 --- a/tests/ui/methods/method-ambig-two-traits-from-impls.stderr +++ b/tests/ui/methods/method-ambig-two-traits-from-impls.stderr @@ -23,6 +23,6 @@ help: disambiguate the method for candidate #2 LL | B::foo(AB {}); | ~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr index 5bb887b4503a9..333520847f835 100644 --- a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr +++ b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr @@ -21,6 +21,6 @@ LL | ::foo(); LL | ::foo(); | ~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr index df01966b3a2cc..9da307436e9b1 100644 --- a/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr +++ b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr @@ -23,6 +23,6 @@ help: disambiguate the method for candidate #2 LL | Bar::method(&1_usize); | ~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambiguity-no-rcvr.rs b/tests/ui/methods/method-ambiguity-no-rcvr.rs new file mode 100644 index 0000000000000..8f36011d41f97 --- /dev/null +++ b/tests/ui/methods/method-ambiguity-no-rcvr.rs @@ -0,0 +1,14 @@ +struct Qux; + +trait Foo { + fn foo(); +} + +trait FooBar { + fn foo() {} +} + +fn main() { + Qux.foo(); + //~^ ERROR no method named `foo` found for struct `Qux` in the current scope +} diff --git a/tests/ui/methods/method-ambiguity-no-rcvr.stderr b/tests/ui/methods/method-ambiguity-no-rcvr.stderr new file mode 100644 index 0000000000000..73f6043f256ea --- /dev/null +++ b/tests/ui/methods/method-ambiguity-no-rcvr.stderr @@ -0,0 +1,32 @@ +error[E0599]: no method named `foo` found for struct `Qux` in the current scope + --> $DIR/method-ambiguity-no-rcvr.rs:12:9 + | +LL | struct Qux; + | ---------- method `foo` not found for this struct +... +LL | Qux.foo(); + | ^^^ this is an associated function, not a method + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: candidate #1 is defined in the trait `Foo` + --> $DIR/method-ambiguity-no-rcvr.rs:4:5 + | +LL | fn foo(); + | ^^^^^^^^^ +note: candidate #2 is defined in the trait `FooBar` + --> $DIR/method-ambiguity-no-rcvr.rs:8:5 + | +LL | fn foo() {} + | ^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | ::foo(Qux); + | ~~~~~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | ::foo(Qux); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr index 25ad360b329aa..c72e7e0cdc37f 100644 --- a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr +++ b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr @@ -19,6 +19,6 @@ LL | 0.clone::<'a>(); = note: for more information, see issue #42868 = note: `#[warn(late_bound_lifetime_arguments)]` on by default -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/methods/method-call-type-binding.stderr b/tests/ui/methods/method-call-type-binding.stderr index 4b93082ace575..54d855d340ea3 100644 --- a/tests/ui/methods/method-call-type-binding.stderr +++ b/tests/ui/methods/method-call-type-binding.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | 0.clone::(); | ^^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr index 4e83e4b77f10e..755179650bbaa 100644 --- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr +++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -54,8 +54,8 @@ LL | let z = NuisanceFoo::foo(x); | ~~~~~~~~~~~~~~~~~~~ help: disambiguate the method for candidate #3 | -LL | let z = FinalFoo::foo(x); - | ~~~~~~~~~~~~~~~~ +LL | let z = FinalFoo::foo(&x); + | ~~~~~~~~~~~~~~~~~ error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24 diff --git a/tests/ui/methods/method-macro-backtrace.stderr b/tests/ui/methods/method-macro-backtrace.stderr index dd616c4a5e75d..f0b1113798944 100644 --- a/tests/ui/methods/method-macro-backtrace.stderr +++ b/tests/ui/methods/method-macro-backtrace.stderr @@ -6,6 +6,6 @@ LL | fn bar(&self) { } LL | fn bar(&self) { } | ^^^^^^^^^^^^^ duplicate definitions for `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/methods/method-not-found-but-doc-alias.stderr b/tests/ui/methods/method-not-found-but-doc-alias.stderr index 5102a452f0c28..9746c404013d9 100644 --- a/tests/ui/methods/method-not-found-but-doc-alias.stderr +++ b/tests/ui/methods/method-not-found-but-doc-alias.stderr @@ -7,6 +7,6 @@ LL | struct Foo; LL | Foo.quux(); | ^^^^ help: there is a method with a similar name: `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/method-resolvable-path-in-pattern.stderr b/tests/ui/methods/method-resolvable-path-in-pattern.stderr index 7c454a9a777c5..070d912d1294a 100644 --- a/tests/ui/methods/method-resolvable-path-in-pattern.stderr +++ b/tests/ui/methods/method-resolvable-path-in-pattern.stderr @@ -4,6 +4,6 @@ error[E0532]: expected unit struct, unit variant or constant, found associated f LL | ::trait_bar => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.stderr b/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.stderr index 9694f80ab6d0f..86c2f6431d1b8 100644 --- a/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.stderr +++ b/tests/ui/methods/suggest-method-on-call-with-macro-rcvr.stderr @@ -10,6 +10,6 @@ LL - let hello = len(vec![]); LL + let hello = vec![].len(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/minus-string.stderr b/tests/ui/minus-string.stderr index b429ad3046e96..105274ee7d0e8 100644 --- a/tests/ui/minus-string.stderr +++ b/tests/ui/minus-string.stderr @@ -4,6 +4,6 @@ error[E0600]: cannot apply unary operator `-` to type `String` LL | fn main() { -"foo".to_string(); } | ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/mir/build-async-error-body-correctly.rs b/tests/ui/mir/build-async-error-body-correctly.rs new file mode 100644 index 0000000000000..1787f80c07e5e --- /dev/null +++ b/tests/ui/mir/build-async-error-body-correctly.rs @@ -0,0 +1,8 @@ +// edition: 2021 + +async fn asyncfn() { + let binding = match true {}; + //~^ ERROR non-exhaustive patterns: type `bool` is non-empty +} + +fn main() {} diff --git a/tests/ui/mir/build-async-error-body-correctly.stderr b/tests/ui/mir/build-async-error-body-correctly.stderr new file mode 100644 index 0000000000000..4b9cdc4f9379f --- /dev/null +++ b/tests/ui/mir/build-async-error-body-correctly.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: type `bool` is non-empty + --> $DIR/build-async-error-body-correctly.rs:4:25 + | +LL | let binding = match true {}; + | ^^^^ + | + = note: the matched value is of type `bool` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ let binding = match true { +LL + _ => todo!(), +LL ~ }; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/mir/field-projection-mutating-context.stderr b/tests/ui/mir/field-projection-mutating-context.stderr index 9b18b3427adff..62c9e55a44bb5 100644 --- a/tests/ui/mir/field-projection-mutating-context.stderr +++ b/tests/ui/mir/field-projection-mutating-context.stderr @@ -7,6 +7,6 @@ LL | let Foo(ref mut y): Foo = x; = note: expected fn pointer `for<'a> fn(&'a str)` found fn pointer `fn(&str)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mir/field-projection-mutating-context2.stderr b/tests/ui/mir/field-projection-mutating-context2.stderr index a7b66fe10ce71..1674001704194 100644 --- a/tests/ui/mir/field-projection-mutating-context2.stderr +++ b/tests/ui/mir/field-projection-mutating-context2.stderr @@ -6,5 +6,5 @@ LL | fn foo<'a>(mut x: Foo, string: &'a str) { LL | let Foo(ref mut y): Foo = x; | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr index 925dc258a4c3c..1f04d119b5668 100644 --- a/tests/ui/mir/issue-102389.stderr +++ b/tests/ui/mir/issue-102389.stderr @@ -4,6 +4,6 @@ error[E0507]: cannot move out of `*inbounds` which is behind a shared reference LL | array[*inbounds as usize] | ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/mir/issue-106062.stderr b/tests/ui/mir/issue-106062.stderr index 2f6524d03e00d..30635148dae64 100644 --- a/tests/ui/mir/issue-106062.stderr +++ b/tests/ui/mir/issue-106062.stderr @@ -11,6 +11,6 @@ LL | async fn connection_handler(handler: impl Sized) -> Result Result { | ~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/mir/issue-75053.stderr b/tests/ui/mir/issue-75053.stderr index 64e59e6c44825..bd37f0c92ad82 100644 --- a/tests/ui/mir/issue-75053.stderr +++ b/tests/ui/mir/issue-75053.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/mir/issue-92893.stderr b/tests/ui/mir/issue-92893.stderr index 6c1a9dc03173f..3bf056d152cfa 100644 --- a/tests/ui/mir/issue-92893.stderr +++ b/tests/ui/mir/issue-92893.stderr @@ -6,5 +6,5 @@ LL | struct Bug { | = note: only supported directly in conditions of `if` and `while` expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/mir/ssa_call_ret.rs b/tests/ui/mir/ssa_call_ret.rs new file mode 100644 index 0000000000000..6132a6691dea3 --- /dev/null +++ b/tests/ui/mir/ssa_call_ret.rs @@ -0,0 +1,30 @@ +// Regression test for issue #117331, where variable `a` was misidentified as +// being in SSA form (the definition occurs on the return edge only). +// +// edition:2021 +// compile-flags: --crate-type=lib +// build-pass +// needs-unwind +#![feature(custom_mir, core_intrinsics)] +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn f() -> u32 { + mir!( + let a: u32; + { + Call(a = g(), bb1, UnwindCleanup(bb2)) + } + bb1 = { + RET = a; + Return() + } + bb2 (cleanup) = { + RET = a; + UnwindResume() + } + ) +} + +#[inline(never)] +pub fn g() -> u32 { 0 } diff --git a/tests/ui/mir/validate/critical-edge.rs b/tests/ui/mir/validate/critical-edge.rs new file mode 100644 index 0000000000000..9ef655cd1bb4a --- /dev/null +++ b/tests/ui/mir/validate/critical-edge.rs @@ -0,0 +1,31 @@ +// Optimized MIR shouldn't have critical call edges +// +// build-fail +// edition: 2021 +// compile-flags: --crate-type=lib +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: encountered critical edge in `Call` terminator +#![feature(custom_mir, core_intrinsics)] +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +#[inline(always)] +pub fn f(a: u32) -> u32 { + mir!( + { + match a { + 0 => bb1, + _ => bb2, + } + } + bb1 = { + Call(RET = f(1), bb2, UnwindTerminate(ReasonAbi)) + } + + bb2 = { + RET = 2; + Return() + } + ) +} diff --git a/tests/ui/mir/validate/noncleanup-cleanup.rs b/tests/ui/mir/validate/noncleanup-cleanup.rs new file mode 100644 index 0000000000000..0a1c4528aa6d9 --- /dev/null +++ b/tests/ui/mir/validate/noncleanup-cleanup.rs @@ -0,0 +1,21 @@ +// Check that validation rejects cleanup edge to a non-cleanup block. +// +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: cleanuppad mismatch +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "built")] +pub fn main() { + mir!( + { + Call(RET = main(), block, UnwindCleanup(block)) + } + block = { + Return() + } + ) + +} diff --git a/tests/ui/mir/validate/noncleanup-resume.rs b/tests/ui/mir/validate/noncleanup-resume.rs new file mode 100644 index 0000000000000..e80d09bc90a59 --- /dev/null +++ b/tests/ui/mir/validate/noncleanup-resume.rs @@ -0,0 +1,17 @@ +// Check that validation rejects resume terminator in a non-cleanup block. +// +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: resume on non-cleanup block +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "built")] +pub fn main() { + mir!( + { + UnwindResume() + } + ) +} diff --git a/tests/ui/mir/validate/noncleanup-terminate.rs b/tests/ui/mir/validate/noncleanup-terminate.rs new file mode 100644 index 0000000000000..2a74668370d4c --- /dev/null +++ b/tests/ui/mir/validate/noncleanup-terminate.rs @@ -0,0 +1,17 @@ +// Check that validation rejects terminate terminator in a non-cleanup block. +// +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: terminate on non-cleanup block +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "built")] +pub fn main() { + mir!( + { + UnwindTerminate(ReasonAbi) + } + ) +} diff --git a/tests/ui/mismatched_types/E0631.stderr b/tests/ui/mismatched_types/E0631.stderr index 410ea4b0b3439..9ba8f5035c5f6 100644 --- a/tests/ui/mismatched_types/E0631.stderr +++ b/tests/ui/mismatched_types/E0631.stderr @@ -48,6 +48,10 @@ note: required by a bound in `foo` | LL | fn foo(_: F) {} | ^^^^^^^^^ required by this bound in `foo` +help: consider wrapping the function in a closure + | +LL | foo(|arg0: usize| f(/* u64 */)); + | +++++++++++++ +++++++++++ error[E0631]: type mismatch in function arguments --> $DIR/E0631.rs:10:9 @@ -67,6 +71,10 @@ note: required by a bound in `bar` | LL | fn bar>(_: F) {} | ^^^^^^^^^^^^ required by this bound in `bar` +help: consider wrapping the function in a closure + | +LL | bar(|arg0: usize| f(/* u64 */)); + | +++++++++++++ +++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr b/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr index 66a85c4656af5..6609fa8c07114 100644 --- a/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr +++ b/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr @@ -14,6 +14,6 @@ LL | struct Foo; note: the trait `AddAssign` must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0368`. diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr index d63cec489176b..142a52aef13d0 100644 --- a/tests/ui/mismatched_types/cast-rfc0401.stderr +++ b/tests/ui/mismatched_types/cast-rfc0401.stderr @@ -18,7 +18,7 @@ error[E0609]: no field `f` on type `fn() {main}` --> $DIR/cast-rfc0401.rs:65:18 | LL | let _ = main.f as *const u32; - | ^ + | ^ unknown field error[E0605]: non-primitive cast: `*const u8` as `&u8` --> $DIR/cast-rfc0401.rs:29:13 diff --git a/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr b/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr index d7db90e50e51b..801e8a0ff1d02 100644 --- a/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr +++ b/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr @@ -11,6 +11,6 @@ help: change the closure to accept a tuple instead of individual arguments LL | let _n = m.iter().map(|(_, b)| { | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0593`. diff --git a/tests/ui/mismatched_types/closure-mismatch.stderr b/tests/ui/mismatched_types/closure-mismatch.stderr index c5b8270ba84d5..74033c1857377 100644 --- a/tests/ui/mismatched_types/closure-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.stderr @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | baz(|_| ()); | ^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a> Fn<(&'a (),)>` - found trait `Fn<(&(),)>` + = note: expected trait `for<'a> Fn(&'a ())` + found trait `Fn(&())` note: this closure does not fulfill the lifetime requirements --> $DIR/closure-mismatch.rs:8:9 | @@ -45,8 +45,8 @@ error[E0308]: mismatched types LL | baz(|x| ()); | ^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a> Fn<(&'a (),)>` - found trait `Fn<(&(),)>` + = note: expected trait `for<'a> Fn(&'a ())` + found trait `Fn(&())` note: this closure does not fulfill the lifetime requirements --> $DIR/closure-mismatch.rs:11:9 | diff --git a/tests/ui/mismatched_types/closure-ref-114180.stderr b/tests/ui/mismatched_types/closure-ref-114180.stderr index 8a146d784e297..27649822e694f 100644 --- a/tests/ui/mismatched_types/closure-ref-114180.stderr +++ b/tests/ui/mismatched_types/closure-ref-114180.stderr @@ -12,11 +12,15 @@ LL | v.sort_by(compare); found closure signature `fn((_,), (_,)) -> _` note: required by a bound in `slice::::sort_by` --> $SRC_DIR/alloc/src/slice.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | v.sort_by(|arg0, arg1| compare(*arg0, *arg1)); + | ++++++++++++ ++++++++++++++ help: consider adjusting the signature so it borrows its arguments | LL | let compare = |&(a,), &(e,)| todo!(); | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr b/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr index 7be94ef4ad663..9d4852cff8c62 100644 --- a/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr +++ b/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr @@ -16,6 +16,6 @@ help: consider borrowing here LL | f(&()); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/fn-variance-1.stderr b/tests/ui/mismatched_types/fn-variance-1.stderr index 5794e606eeb93..fdb2e6f0097a8 100644 --- a/tests/ui/mismatched_types/fn-variance-1.stderr +++ b/tests/ui/mismatched_types/fn-variance-1.stderr @@ -16,6 +16,10 @@ note: required by a bound in `apply` | LL | fn apply(t: T, f: F) where F: FnOnce(T) { | ^^^^^^^^^ required by this bound in `apply` +help: consider wrapping the function in a closure + | +LL | apply(&3, |x| takes_mut(&mut *x)); + | +++ +++++++++ error[E0631]: type mismatch in function arguments --> $DIR/fn-variance-1.rs:15:19 @@ -35,6 +39,10 @@ note: required by a bound in `apply` | LL | fn apply(t: T, f: F) where F: FnOnce(T) { | ^^^^^^^^^ required by this bound in `apply` +help: consider wrapping the function in a closure + | +LL | apply(&mut 3, |x| takes_imm(&*x)); + | +++ +++++ error: aborting due to 2 previous errors diff --git a/tests/ui/mismatched_types/for-loop-has-unit-body.stderr b/tests/ui/mismatched_types/for-loop-has-unit-body.stderr index f36fe64bffb9d..f752447901828 100644 --- a/tests/ui/mismatched_types/for-loop-has-unit-body.stderr +++ b/tests/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | x | ^ expected `()`, found integer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-106182.stderr b/tests/ui/mismatched_types/issue-106182.stderr index 96ab3a029914e..2f33628a49164 100644 --- a/tests/ui/mismatched_types/issue-106182.stderr +++ b/tests/ui/mismatched_types/issue-106182.stderr @@ -13,6 +13,6 @@ help: consider removing `&` from the pattern LL | _S(mut _y, _v) => { | ~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-112036.stderr b/tests/ui/mismatched_types/issue-112036.stderr index a883aba35bfba..b93ce4a8674c2 100644 --- a/tests/ui/mismatched_types/issue-112036.stderr +++ b/tests/ui/mismatched_types/issue-112036.stderr @@ -10,6 +10,6 @@ LL | fn drop(self) {} = note: expected signature `fn(&mut Foo)` found signature `fn(Foo)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.fixed b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.fixed new file mode 100644 index 0000000000000..15d4e393874eb --- /dev/null +++ b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.fixed @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused, dead_code)] + +#[derive(Clone, Copy)] +struct Stuff { + count: i32, +} +struct Error; + +fn demo() -> Result { + let count = Ok(1); + Ok(Stuff { count: count? }) //~ ERROR mismatched types +} + +fn demo_unwrap() -> Stuff { + let count = Some(1); + Stuff { count: count.expect("REASON") } //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.rs b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.rs new file mode 100644 index 0000000000000..8e811caa3bdce --- /dev/null +++ b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.rs @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused, dead_code)] + +#[derive(Clone, Copy)] +struct Stuff { + count: i32, +} +struct Error; + +fn demo() -> Result { + let count = Ok(1); + Ok(Stuff { count }) //~ ERROR mismatched types +} + +fn demo_unwrap() -> Stuff { + let count = Some(1); + Stuff { count } //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.stderr b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.stderr new file mode 100644 index 0000000000000..0bcbd6f27c44b --- /dev/null +++ b/tests/ui/mismatched_types/issue-118145-unwrap-for-shorthand.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> $DIR/issue-118145-unwrap-for-shorthand.rs:12:16 + | +LL | Ok(Stuff { count }) + | ^^^^^ expected `i32`, found `Result<{integer}, _>` + | + = note: expected type `i32` + found enum `Result<{integer}, _>` +help: use the `?` operator to extract the `Result<{integer}, _>` value, propagating a `Result::Err` value to the caller + | +LL | Ok(Stuff { count: count? }) + | ++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-118145-unwrap-for-shorthand.rs:17:13 + | +LL | Stuff { count } + | ^^^^^ expected `i32`, found `Option<{integer}>` + | + = note: expected type `i32` + found enum `Option<{integer}>` +help: consider using `Option::expect` to unwrap the `Option<{integer}>` value, panicking if the value is an `Option::None` + | +LL | Stuff { count: count.expect("REASON") } + | ++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-118510.rs b/tests/ui/mismatched_types/issue-118510.rs new file mode 100644 index 0000000000000..86b9d44a37382 --- /dev/null +++ b/tests/ui/mismatched_types/issue-118510.rs @@ -0,0 +1,10 @@ +pub enum Sexpr<'a, S> { + Ident(&'a mut S), +} + +fn map T>(f: F) {} + +fn main() { + map(Sexpr::Ident); + //~^ ERROR type mismatch in function arguments +} diff --git a/tests/ui/mismatched_types/issue-118510.stderr b/tests/ui/mismatched_types/issue-118510.stderr new file mode 100644 index 0000000000000..e8bf92d90478b --- /dev/null +++ b/tests/ui/mismatched_types/issue-118510.stderr @@ -0,0 +1,26 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/issue-118510.rs:8:9 + | +LL | Ident(&'a mut S), + | ----- found signature defined here +... +LL | map(Sexpr::Ident); + | --- ^^^^^^^^^^^^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `for<'a> fn(&'a _) -> _` + found function signature `fn(&mut _) -> _` +note: required by a bound in `map` + --> $DIR/issue-118510.rs:5:19 + | +LL | fn map T>(f: F) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `map` +help: consider wrapping the function in a closure + | +LL | map(|arg0| Sexpr::Ident(&mut *arg0)); + | ++++++ ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/issue-13033.stderr b/tests/ui/mismatched_types/issue-13033.stderr index db2c1189e1e1a..4886fa30e89b1 100644 --- a/tests/ui/mismatched_types/issue-13033.stderr +++ b/tests/ui/mismatched_types/issue-13033.stderr @@ -15,6 +15,6 @@ LL | fn bar(&mut self, other: &mut dyn Foo); = note: expected signature `fn(&mut Baz, &mut dyn Foo)` found signature `fn(&mut Baz, &dyn Foo)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/mismatched_types/issue-19109.stderr b/tests/ui/mismatched_types/issue-19109.stderr index ca819d93a50a4..e769ed0c1f976 100644 --- a/tests/ui/mismatched_types/issue-19109.stderr +++ b/tests/ui/mismatched_types/issue-19109.stderr @@ -9,6 +9,6 @@ LL | t as *mut dyn Trait = note: expected unit type `()` found raw pointer `*mut dyn Trait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-35030.stderr b/tests/ui/mismatched_types/issue-35030.stderr index 881ff909722f3..62f83ce706fa6 100644 --- a/tests/ui/mismatched_types/issue-35030.stderr +++ b/tests/ui/mismatched_types/issue-35030.stderr @@ -21,6 +21,6 @@ LL | Some(true) note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-47706-trait.stderr b/tests/ui/mismatched_types/issue-47706-trait.stderr index a5f38dd536661..c54a62c5e6f71 100644 --- a/tests/ui/mismatched_types/issue-47706-trait.stderr +++ b/tests/ui/mismatched_types/issue-47706-trait.stderr @@ -11,6 +11,6 @@ LL | None::<()>.map(Self::f); note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0593`. diff --git a/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr index 88416ba4bb6dc..5c2278ddfc6af 100644 --- a/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr +++ b/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr @@ -15,5 +15,5 @@ help: the lifetime requirements from the `impl` do not correspond to the require LL | fn adjacent_edges(&self) -> Box>; | ^^^^ consider borrowing this type parameter in the trait -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/mismatched_types/main.stderr b/tests/ui/mismatched_types/main.stderr index a662741afcd9c..38146cef3475a 100644 --- a/tests/ui/mismatched_types/main.stderr +++ b/tests/ui/mismatched_types/main.stderr @@ -8,6 +8,6 @@ LL | let x: u32 = ( LL | | ); | |_____^ expected `u32`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 9dab3e5225570..be3a3e2abf14c 100644 --- a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -14,6 +14,6 @@ LL + #[derive(Debug)] LL | struct Foo; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.fixed b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.fixed new file mode 100644 index 0000000000000..e1f929e61703c --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.fixed @@ -0,0 +1,77 @@ +// run-rustfix +// edition:2021 +#![allow(dead_code)] +#![allow(unused_variables)] +use std::future::Future; +use std::pin::Pin; + +fn test1() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option: Option<&'a str>, + } + + let option: Option = Some(string.clone()); + let s = Demo { option: option.as_deref() }; //~ ERROR mismatched types +} + +fn test2() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option_ref: Option<&'a str>, + } + + let option_ref = Some(&string); + let s = Demo { option_ref: option_ref.map(|x| x.as_str()) }; //~ ERROR mismatched types +} + +fn test3() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option_ref_ref: Option<&'a str>, + } + + let option_ref = Some(&string); + let option_ref_ref = option_ref.as_ref(); + + let s = Demo { option_ref_ref: option_ref_ref.map(|x| x.as_str()) }; //~ ERROR mismatched types +} + +fn test4() { + let a = 1; + struct Demo { + a: String, + } + let s = Demo { a: a.to_string() }; //~ ERROR mismatched types +} + +type BoxFuture<'a, T> = Pin + Send + 'a>>; +fn test5() { + let a = async { 42 }; + struct Demo { + a: BoxFuture<'static, i32>, + } + let s = Demo { a: Box::pin(a) }; //~ ERROR mismatched types +} + +fn test6() { + struct A; + struct B; + + impl From for A { + fn from(_: B) -> Self { + A + } + } + + struct Demo { + a: A, + } + let a = B; + let s = Demo { a: a.into() }; //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.rs b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.rs new file mode 100644 index 0000000000000..956936c925ba0 --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.rs @@ -0,0 +1,77 @@ +// run-rustfix +// edition:2021 +#![allow(dead_code)] +#![allow(unused_variables)] +use std::future::Future; +use std::pin::Pin; + +fn test1() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option: Option<&'a str>, + } + + let option: Option = Some(string.clone()); + let s = Demo { option }; //~ ERROR mismatched types +} + +fn test2() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option_ref: Option<&'a str>, + } + + let option_ref = Some(&string); + let s = Demo { option_ref }; //~ ERROR mismatched types +} + +fn test3() { + let string = String::from("Hello, world"); + + struct Demo<'a> { + option_ref_ref: Option<&'a str>, + } + + let option_ref = Some(&string); + let option_ref_ref = option_ref.as_ref(); + + let s = Demo { option_ref_ref }; //~ ERROR mismatched types +} + +fn test4() { + let a = 1; + struct Demo { + a: String, + } + let s = Demo { a }; //~ ERROR mismatched types +} + +type BoxFuture<'a, T> = Pin + Send + 'a>>; +fn test5() { + let a = async { 42 }; + struct Demo { + a: BoxFuture<'static, i32>, + } + let s = Demo { a }; //~ ERROR mismatched types +} + +fn test6() { + struct A; + struct B; + + impl From for A { + fn from(_: B) -> Self { + A + } + } + + struct Demo { + a: A, + } + let a = B; + let s = Demo { a }; //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr new file mode 100644 index 0000000000000..1baf95d2bf781 --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-sugg-for-shorthand-field.stderr @@ -0,0 +1,80 @@ +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:16:20 + | +LL | let s = Demo { option }; + | ^^^^^^ expected `Option<&str>`, found `Option` + | + = note: expected enum `Option<&str>` + found enum `Option` +help: try using `: option.as_deref()` to convert `Option` to `Option<&str>` + | +LL | let s = Demo { option: option.as_deref() }; + | +++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:27:20 + | +LL | let s = Demo { option_ref }; + | ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>` + | + = note: expected enum `Option<&str>` + found enum `Option<&String>` +help: try converting the passed type into a `&str` + | +LL | let s = Demo { option_ref: option_ref.map(|x| x.as_str()) }; + | ++++++++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:40:20 + | +LL | let s = Demo { option_ref_ref }; + | ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>` + | + = note: expected enum `Option<&str>` + found enum `Option<&&String>` +help: try converting the passed type into a `&str` + | +LL | let s = Demo { option_ref_ref: option_ref_ref.map(|x| x.as_str()) }; + | ++++++++++++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:48:20 + | +LL | let s = Demo { a }; + | ^ expected `String`, found integer + | +help: try using a conversion method + | +LL | let s = Demo { a: a.to_string() }; + | ++ ++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:57:20 + | +LL | let a = async { 42 }; + | ------------ the found `async` block +... +LL | let s = Demo { a }; + | ^ expected `Pin>`, found `async` block + | + = note: expected struct `Pin + Send + 'static)>>` + found `async` block `{async block@$DIR/mismatch-sugg-for-shorthand-field.rs:53:13: 53:25}` +help: you need to pin and box this expression + | +LL | let s = Demo { a: Box::pin(a) }; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/mismatch-sugg-for-shorthand-field.rs:74:20 + | +LL | let s = Demo { a }; + | ^ expected `A`, found `B` + | +help: call `Into::into` on this expression to convert `B` into `A` + | +LL | let s = Demo { a: a.into() }; + | ++ +++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/normalize-fn-sig.stderr b/tests/ui/mismatched_types/normalize-fn-sig.stderr index 252e56387ba8b..2166de85f1fec 100644 --- a/tests/ui/mismatched_types/normalize-fn-sig.stderr +++ b/tests/ui/mismatched_types/normalize-fn-sig.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn needs_i32_ref_fn(_: fn(&'static i32, i32)) {} | ^^^^^^^^^^^^^^^^ ------------------------ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/recovered-block.stderr b/tests/ui/mismatched_types/recovered-block.stderr index 88d625456564f..51b5f3b1af2fc 100644 --- a/tests/ui/mismatched_types/recovered-block.stderr +++ b/tests/ui/mismatched_types/recovered-block.stderr @@ -9,5 +9,5 @@ help: add `struct` here to parse `Foo` as a public struct LL | pub struct Foo { text } | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/mismatched_types/show_module.stderr b/tests/ui/mismatched_types/show_module.stderr index 4bbeaaab93755..e95467add38cb 100644 --- a/tests/ui/mismatched_types/show_module.stderr +++ b/tests/ui/mismatched_types/show_module.stderr @@ -18,6 +18,6 @@ note: `baz::Foo` is defined in module `crate::blah::baz` of the current crate LL | pub struct Foo; | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/similar_paths.stderr b/tests/ui/mismatched_types/similar_paths.stderr index 3e44fb759296a..a7a35ec277403 100644 --- a/tests/ui/mismatched_types/similar_paths.stderr +++ b/tests/ui/mismatched_types/similar_paths.stderr @@ -15,6 +15,6 @@ note: `Option` is defined in the current crate LL | enum Option { | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr index 80e78a4e4fa3c..c9881891319d3 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.stderr +++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr @@ -19,6 +19,6 @@ note: function defined here LL | fn foo(_: bool) {} | ^^^ ------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr b/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr index 5c4c13266d030..0ed57466e9c58 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr +++ b/tests/ui/mismatched_types/suggest-option-asderef-inference-var.stderr @@ -13,12 +13,16 @@ LL | let _has_inference_vars: Option = Some(0).map(deref_int); found function signature `for<'a> fn(&'a i32) -> _` note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | let _has_inference_vars: Option = Some(0).map(|a| deref_int(&a)); + | +++ ++++ help: consider adjusting the signature so it does not borrow its argument | LL - fn deref_int(a: &i32) -> i32 { LL + fn deref_int(a: i32) -> i32 { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr index 3175a258906fe..1ac057a5f382f 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr +++ b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr @@ -13,6 +13,10 @@ LL | let _ = produces_string().and_then(takes_str_but_too_many_refs); found function signature `for<'a, 'b> fn(&'a &'b str) -> _` note: required by a bound in `Option::::and_then` --> $SRC_DIR/core/src/option.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | let _ = produces_string().and_then(|arg0: String| takes_str_but_too_many_refs(/* &&str */)); + | ++++++++++++++ +++++++++++++ error[E0277]: expected a `FnOnce(String)` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` --> $DIR/suggest-option-asderef-unfixable.rs:26:40 @@ -68,6 +72,10 @@ LL | let _ = Some(TypeWithoutDeref).and_then(takes_str_but_too_many_refs); found function signature `for<'a, 'b> fn(&'a &'b str) -> _` note: required by a bound in `Option::::and_then` --> $SRC_DIR/core/src/option.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | let _ = Some(TypeWithoutDeref).and_then(|arg0: TypeWithoutDeref| takes_str_but_too_many_refs(/* &&str */)); + | ++++++++++++++++++++++++ +++++++++++++ error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/suggest-option-asderef.fixed b/tests/ui/mismatched_types/suggest-option-asderef.fixed deleted file mode 100644 index fc488b790b3d8..0000000000000 --- a/tests/ui/mismatched_types/suggest-option-asderef.fixed +++ /dev/null @@ -1,39 +0,0 @@ -// run-rustfix - -fn produces_string() -> Option { - Some("my cool string".to_owned()) -} - -fn takes_str(_: &str) -> Option<()> { - Some(()) -} - -fn takes_str_mut(_: &mut str) -> Option<()> { - Some(()) -} - -fn generic(_: T) -> Option<()> { - Some(()) -} - -fn generic_ref(_: T) -> Option<()> { - //~^ HELP consider adjusting the signature so it does not borrow its argument - Some(()) -} - -fn main() { - let _: Option<()> = produces_string().as_deref().and_then(takes_str); - //~^ ERROR type mismatch in function arguments - //~| HELP call `Option::as_deref()` first - let _: Option> = produces_string().as_deref().map(takes_str); - //~^ ERROR type mismatch in function arguments - //~| HELP call `Option::as_deref()` first - let _: Option> = produces_string().as_deref_mut().map(takes_str_mut); - //~^ ERROR type mismatch in function arguments - //~| HELP call `Option::as_deref_mut()` first - let _ = produces_string().and_then(generic); - - let _ = produces_string().as_deref().and_then(generic_ref); - //~^ ERROR type mismatch in function arguments - //~| HELP call `Option::as_deref()` first -} diff --git a/tests/ui/mismatched_types/suggest-option-asderef.rs b/tests/ui/mismatched_types/suggest-option-asderef.rs index 28f46808a3923..5f5617e1741c4 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef.rs +++ b/tests/ui/mismatched_types/suggest-option-asderef.rs @@ -1,4 +1,4 @@ -// run-rustfix +// this isn't auto-fixable now because we produce two similar suggestions fn produces_string() -> Option { Some("my cool string".to_owned()) @@ -25,15 +25,19 @@ fn main() { let _: Option<()> = produces_string().and_then(takes_str); //~^ ERROR type mismatch in function arguments //~| HELP call `Option::as_deref()` first + //~| HELP consider wrapping the function in a closure let _: Option> = produces_string().map(takes_str); //~^ ERROR type mismatch in function arguments //~| HELP call `Option::as_deref()` first + //~| HELP consider wrapping the function in a closure let _: Option> = produces_string().map(takes_str_mut); //~^ ERROR type mismatch in function arguments //~| HELP call `Option::as_deref_mut()` first + //~| HELP consider wrapping the function in a closure let _ = produces_string().and_then(generic); let _ = produces_string().and_then(generic_ref); //~^ ERROR type mismatch in function arguments //~| HELP call `Option::as_deref()` first + //~| HELP consider wrapping the function in a closure } diff --git a/tests/ui/mismatched_types/suggest-option-asderef.stderr b/tests/ui/mismatched_types/suggest-option-asderef.stderr index bfea086735065..1702a7f1decf6 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef.stderr +++ b/tests/ui/mismatched_types/suggest-option-asderef.stderr @@ -13,13 +13,17 @@ LL | let _: Option<()> = produces_string().and_then(takes_str); found function signature `for<'a> fn(&'a str) -> _` note: required by a bound in `Option::::and_then` --> $SRC_DIR/core/src/option.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | let _: Option<()> = produces_string().and_then(|arg0: String| takes_str(/* &str */)); + | ++++++++++++++ ++++++++++++ help: call `Option::as_deref()` first | LL | let _: Option<()> = produces_string().as_deref().and_then(takes_str); | +++++++++++ error[E0631]: type mismatch in function arguments - --> $DIR/suggest-option-asderef.rs:28:55 + --> $DIR/suggest-option-asderef.rs:29:55 | LL | fn takes_str(_: &str) -> Option<()> { | ----------------------------------- found signature defined here @@ -33,13 +37,17 @@ LL | let _: Option> = produces_string().map(takes_str); found function signature `for<'a> fn(&'a str) -> _` note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | let _: Option> = produces_string().map(|arg0: String| takes_str(/* &str */)); + | ++++++++++++++ ++++++++++++ help: call `Option::as_deref()` first | LL | let _: Option> = produces_string().as_deref().map(takes_str); | +++++++++++ error[E0631]: type mismatch in function arguments - --> $DIR/suggest-option-asderef.rs:31:55 + --> $DIR/suggest-option-asderef.rs:33:55 | LL | fn takes_str_mut(_: &mut str) -> Option<()> { | ------------------------------------------- found signature defined here @@ -53,13 +61,17 @@ LL | let _: Option> = produces_string().map(takes_str_mut); found function signature `for<'a> fn(&'a mut str) -> _` note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | let _: Option> = produces_string().map(|arg0: String| takes_str_mut(/* &mut str */)); + | ++++++++++++++ ++++++++++++++++ help: call `Option::as_deref_mut()` first | LL | let _: Option> = produces_string().as_deref_mut().map(takes_str_mut); | +++++++++++++++ error[E0631]: type mismatch in function arguments - --> $DIR/suggest-option-asderef.rs:36:40 + --> $DIR/suggest-option-asderef.rs:39:40 | LL | fn generic_ref(_: &T) -> Option<()> { | -------------------------------------- found signature defined here @@ -73,6 +85,10 @@ LL | let _ = produces_string().and_then(generic_ref); found function signature `for<'a> fn(&'a _) -> _` note: required by a bound in `Option::::and_then` --> $SRC_DIR/core/src/option.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | let _ = produces_string().and_then(|arg0: String| generic_ref(&arg0)); + | ++++++++++++++ +++++++ help: consider adjusting the signature so it does not borrow its argument | LL - fn generic_ref(_: &T) -> Option<()> { diff --git a/tests/ui/mismatched_types/trait-bounds-cant-coerce.stderr b/tests/ui/mismatched_types/trait-bounds-cant-coerce.stderr index 80aef7fcbe8e2..aaa3a9f191ad3 100644 --- a/tests/ui/mismatched_types/trait-bounds-cant-coerce.stderr +++ b/tests/ui/mismatched_types/trait-bounds-cant-coerce.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn a(_x: Box) { | ^ ----------------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index 54b2200652746..d92d5dbd16fad 100644 --- a/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -16,7 +16,11 @@ note: required by a bound in `call_it` | LL | fn call_it isize>(y: isize, mut f: F) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` +help: consider wrapping the function in a closure + | +LL | let z = call_it(3, |arg0: isize, arg1: isize| f(/* usize */, arg1)); + | ++++++++++++++++++++++++++ +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr index 05d3de80d8449..f73bff51e7ad1 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.stderr +++ b/tests/ui/missing-trait-bounds/issue-35677.stderr @@ -14,6 +14,6 @@ help: consider restricting the type parameters to satisfy the trait bounds LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { | ++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/missing-trait-bounds/issue-69725.stderr b/tests/ui/missing-trait-bounds/issue-69725.stderr index 980d9dd167d20..f483ea849b0ef 100644 --- a/tests/ui/missing-trait-bounds/issue-69725.stderr +++ b/tests/ui/missing-trait-bounds/issue-69725.stderr @@ -17,6 +17,6 @@ help: consider restricting the type parameter to satisfy the trait bound LL | fn crash() where A: Clone { | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr index cde0755012594..b3089cecfbb29 100644 --- a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr +++ b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr @@ -11,6 +11,6 @@ help: consider restricting type parameter `T` LL | pub fn foo(s: &[T], t: &[T]) { | +++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/missing/missing-allocator.stderr b/tests/ui/missing/missing-allocator.stderr index 0da5651c18cb1..007c488c9d95f 100644 --- a/tests/ui/missing/missing-allocator.stderr +++ b/tests/ui/missing/missing-allocator.stderr @@ -1,4 +1,4 @@ error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/missing/missing-comma-in-match.stderr b/tests/ui/missing/missing-comma-in-match.stderr index fe210f697c446..50f74eeb5ed08 100644 --- a/tests/ui/missing/missing-comma-in-match.stderr +++ b/tests/ui/missing/missing-comma-in-match.stderr @@ -6,5 +6,5 @@ LL | &None => 1 LL | &Some(2) => { 3 } | ^^ expected one of `,`, `.`, `?`, `}`, or an operator -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/missing/missing-derivable-attr.stderr b/tests/ui/missing/missing-derivable-attr.stderr index 9b8c0c583a1c1..f2e23b62fce83 100644 --- a/tests/ui/missing/missing-derivable-attr.stderr +++ b/tests/ui/missing/missing-derivable-attr.stderr @@ -7,6 +7,6 @@ LL | fn eq(&self, other: &Self) -> bool; LL | impl MyEq for A {} | ^^^^^^^^^^^^^^^ missing `eq` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/missing/missing-fields-in-struct-pattern.stderr b/tests/ui/missing/missing-fields-in-struct-pattern.stderr index 1fe9f5299aa08..91a7bd3540e38 100644 --- a/tests/ui/missing/missing-fields-in-struct-pattern.stderr +++ b/tests/ui/missing/missing-fields-in-struct-pattern.stderr @@ -9,6 +9,6 @@ help: use the tuple variant pattern syntax instead LL | if let S(a, b, c, d) = S(1, 2, 3, 4) { | ~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0769`. diff --git a/tests/ui/missing/missing-items/m2.stderr b/tests/ui/missing/missing-items/m2.stderr index 835c9b2aa4840..c552abccee421 100644 --- a/tests/ui/missing/missing-items/m2.stderr +++ b/tests/ui/missing/missing-items/m2.stderr @@ -12,6 +12,6 @@ LL | impl m1::X for X { = help: implement the missing item: `fn method4(&self, _: &Self) -> ::Type { todo!() }` = help: implement the missing item: `fn method5(self: &Box) -> ::Type { todo!() }` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/missing/missing-items/missing-type-parameter.stderr b/tests/ui/missing/missing-items/missing-type-parameter.stderr index 722539fca6b8e..658e2c8e85eed 100644 --- a/tests/ui/missing/missing-items/missing-type-parameter.stderr +++ b/tests/ui/missing/missing-items/missing-type-parameter.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | foo::(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/missing/missing-macro-use.stderr b/tests/ui/missing/missing-macro-use.stderr index e1d80f52daddc..5d8ff486e06a3 100644 --- a/tests/ui/missing/missing-macro-use.stderr +++ b/tests/ui/missing/missing-macro-use.stderr @@ -9,5 +9,5 @@ help: consider importing this macro LL + use two_macros::macro_two; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/missing/missing-main.stderr b/tests/ui/missing/missing-main.stderr index 5113dc6ec08c4..2139981eac0d3 100644 --- a/tests/ui/missing/missing-main.stderr +++ b/tests/ui/missing/missing-main.stderr @@ -4,6 +4,6 @@ error[E0601]: `main` function not found in crate `missing_main` LL | fn mian() { } | ^ consider adding a `main` function to `$DIR/missing-main.rs` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/missing/missing-return.stderr b/tests/ui/missing/missing-return.stderr index ff7f261e03c7b..5f7fb504075ce 100644 --- a/tests/ui/missing/missing-return.stderr +++ b/tests/ui/missing/missing-return.stderr @@ -6,6 +6,6 @@ LL | fn f() -> isize { } | | | implicitly returns `()` as its body has no tail or `return` expression -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr index 5f4d19439accd..4e48799318b6b 100644 --- a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr @@ -7,6 +7,6 @@ LL | mod missing; = help: to create the module `missing`, create file "$DIR/foo/missing.rs" or "$DIR/foo/missing/mod.rs" = note: if there is a `mod missing` elsewhere in the crate already, import it with `use crate::...` instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr index d5f5ea8705971..86193dd26e041 100644 --- a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr @@ -7,6 +7,6 @@ LL | mod missing; = help: to create the module `missing`, create file "$DIR/foo_inline/inline/missing.rs" or "$DIR/foo_inline/inline/missing/mod.rs" = note: if there is a `mod missing` elsewhere in the crate already, import it with `use crate::...` instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/mod-subitem-as-enum-variant.stderr b/tests/ui/mod-subitem-as-enum-variant.stderr index cf61e94bd86cb..92d972eba42bf 100644 --- a/tests/ui/mod-subitem-as-enum-variant.stderr +++ b/tests/ui/mod-subitem-as-enum-variant.stderr @@ -6,6 +6,6 @@ LL | Mod::::FakeVariant(0); | | | not allowed on module `Mod` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/module-macro_use-arguments.stderr b/tests/ui/module-macro_use-arguments.stderr index af799cb6ddf3e..3ac645ad3a93f 100644 --- a/tests/ui/module-macro_use-arguments.stderr +++ b/tests/ui/module-macro_use-arguments.stderr @@ -4,5 +4,5 @@ error: arguments to `macro_use` are not allowed here LL | #[macro_use(foo, bar)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/modules/issue-107649.stderr b/tests/ui/modules/issue-107649.stderr index 5705e84e0d99b..0d203c1aacba4 100644 --- a/tests/ui/modules/issue-107649.stderr +++ b/tests/ui/modules/issue-107649.stderr @@ -14,6 +14,6 @@ help: consider annotating `Dummy` with `#[derive(Debug)]` 3 | pub struct Dummy; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/modules/path-invalid-form.stderr b/tests/ui/modules/path-invalid-form.stderr index 7e8aa44ef8be6..e8ded1343f780 100644 --- a/tests/ui/modules/path-invalid-form.stderr +++ b/tests/ui/modules/path-invalid-form.stderr @@ -4,5 +4,5 @@ error: malformed `path` attribute input LL | #[path = 123] | ^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/modules/path-macro.stderr b/tests/ui/modules/path-macro.stderr index 9a2e01ea26451..eb02c721edd32 100644 --- a/tests/ui/modules/path-macro.stderr +++ b/tests/ui/modules/path-macro.stderr @@ -4,5 +4,5 @@ error: malformed `path` attribute input LL | #[path = foo!()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/modules/path-no-file-name.stderr b/tests/ui/modules/path-no-file-name.stderr index 32a213c68f654..834e8ea6b03de 100644 --- a/tests/ui/modules/path-no-file-name.stderr +++ b/tests/ui/modules/path-no-file-name.stderr @@ -4,5 +4,5 @@ error: couldn't read $DIR/.: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) LL | mod m; | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/modules_and_files_visibility/mod_file_correct_spans.stderr b/tests/ui/modules_and_files_visibility/mod_file_correct_spans.stderr index 73044752b077b..3426505cd1105 100644 --- a/tests/ui/modules_and_files_visibility/mod_file_correct_spans.stderr +++ b/tests/ui/modules_and_files_visibility/mod_file_correct_spans.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `bar` in module `mod_file_aux` LL | assert!(mod_file_aux::bar() == 10); | ^^^ not found in `mod_file_aux` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.fixed b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.fixed new file mode 100644 index 0000000000000..e88ca6079ece3 --- /dev/null +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.fixed @@ -0,0 +1,30 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] +use std::collections::BTreeMap; +use std::collections::HashSet; + +#[derive(Debug,Eq,PartialEq,Hash)] +#[derive(Clone)] +enum Day { + Mon, +} + +struct Class { + days: BTreeMap> +} + +impl Class { + fn do_stuff(&self) { + for (_, v) in &self.days { + let mut x: HashSet = v.clone(); //~ ERROR + let y: Vec = x.drain().collect(); + println!("{:?}", x); + } + } +} + +fn fail() { + let c = Class { days: BTreeMap::new() }; + c.do_stuff(); +} +fn main() {} diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs new file mode 100644 index 0000000000000..ba277c4a9c490 --- /dev/null +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs @@ -0,0 +1,29 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] +use std::collections::BTreeMap; +use std::collections::HashSet; + +#[derive(Debug,Eq,PartialEq,Hash)] +enum Day { + Mon, +} + +struct Class { + days: BTreeMap> +} + +impl Class { + fn do_stuff(&self) { + for (_, v) in &self.days { + let mut x: HashSet = v.clone(); //~ ERROR + let y: Vec = x.drain().collect(); + println!("{:?}", x); + } + } +} + +fn fail() { + let c = Class { days: BTreeMap::new() }; + c.do_stuff(); +} +fn main() {} diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr new file mode 100644 index 0000000000000..821661f1a568e --- /dev/null +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39 + | +LL | let mut x: HashSet = v.clone(); + | ------------ ^^^^^^^^^ expected `HashSet`, found `&HashSet` + | | + | expected due to this + | + = note: expected struct `HashSet` + found reference `&HashSet` +note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned instead + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39 + | +LL | let mut x: HashSet = v.clone(); + | ^ + = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: consider annotating `Day` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | enum Day { + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/moves/issue-34721.stderr b/tests/ui/moves/issue-34721.stderr index f2bf22227dbe4..94780a04c1f29 100644 --- a/tests/ui/moves/issue-34721.stderr +++ b/tests/ui/moves/issue-34721.stderr @@ -23,6 +23,6 @@ help: consider further restricting this bound LL | pub fn baz(x: T) -> T { | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/issue-46099-move-in-macro.stderr b/tests/ui/moves/issue-46099-move-in-macro.stderr index 94bc9e6f45465..2865a4e2ba1c6 100644 --- a/tests/ui/moves/issue-46099-move-in-macro.stderr +++ b/tests/ui/moves/issue-46099-move-in-macro.stderr @@ -11,6 +11,6 @@ help: consider cloning the value if the performance cost is acceptable LL | test!({b.clone()}); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr index 5e427a1fcdc7d..6f04105a35edf 100644 --- a/tests/ui/moves/issue-75904-move-closure-loop.stderr +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -10,6 +10,6 @@ LL | &mut a; LL | a; | - use occurs due to use in closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/issue-99470-move-out-of-some.stderr b/tests/ui/moves/issue-99470-move-out-of-some.stderr index c5159471fe3e4..71ec5adfdeace 100644 --- a/tests/ui/moves/issue-99470-move-out-of-some.stderr +++ b/tests/ui/moves/issue-99470-move-out-of-some.stderr @@ -16,6 +16,6 @@ LL - &Some(_y) => (), LL + Some(_y) => (), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index c91a8b5efacfc..462deacbe8d6e 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -55,6 +55,10 @@ note: `Foo::use_box_self` takes ownership of the receiver `self`, which moves `b | LL | fn use_box_self(self: Box) {} | ^^^^ +help: you could `clone` the value and consume it, if the `Box: Clone` trait bound could be satisfied + | +LL | boxed_foo.clone().use_box_self(); + | ++++++++ error[E0382]: use of moved value: `pin_box_foo` --> $DIR/move-fn-self-receiver.rs:46:5 @@ -71,6 +75,10 @@ note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which move | LL | fn use_pin_box_self(self: Pin>) {} | ^^^^ +help: you could `clone` the value and consume it, if the `Box: Clone` trait bound could be satisfied + | +LL | pin_box_foo.clone().use_pin_box_self(); + | ++++++++ error[E0505]: cannot move out of `mut_foo` because it is borrowed --> $DIR/move-fn-self-receiver.rs:50:5 diff --git a/tests/ui/moves/move-guard-same-consts.stderr b/tests/ui/moves/move-guard-same-consts.stderr index 86e5f65248b97..37ddb831abe76 100644 --- a/tests/ui/moves/move-guard-same-consts.stderr +++ b/tests/ui/moves/move-guard-same-consts.stderr @@ -21,6 +21,6 @@ help: consider cloning the value if the performance cost is acceptable LL | (1, 2) if take(x.clone()) => (), | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-in-guard-1.stderr b/tests/ui/moves/move-in-guard-1.stderr index f04cb34d7c46e..0b90823884a52 100644 --- a/tests/ui/moves/move-in-guard-1.stderr +++ b/tests/ui/moves/move-in-guard-1.stderr @@ -21,6 +21,6 @@ help: consider cloning the value if the performance cost is acceptable LL | (1, _) if take(x.clone()) => (), | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-in-guard-2.stderr b/tests/ui/moves/move-in-guard-2.stderr index 26047861f55d7..6d1bd4f955310 100644 --- a/tests/ui/moves/move-in-guard-2.stderr +++ b/tests/ui/moves/move-in-guard-2.stderr @@ -19,6 +19,6 @@ help: consider cloning the value if the performance cost is acceptable LL | (_, 2) if take(x.clone()) => (), | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-into-dead-array-1.stderr b/tests/ui/moves/move-into-dead-array-1.stderr index 6db0f0bcbffee..83779fb16edb3 100644 --- a/tests/ui/moves/move-into-dead-array-1.stderr +++ b/tests/ui/moves/move-into-dead-array-1.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let mut a: [D; 4] = todo!(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/moves/move-into-dead-array-2.stderr b/tests/ui/moves/move-into-dead-array-2.stderr index 19e476c04ea07..689aecdfc8c89 100644 --- a/tests/ui/moves/move-into-dead-array-2.stderr +++ b/tests/ui/moves/move-into-dead-array-2.stderr @@ -8,6 +8,6 @@ LL | drop(a); LL | a[i] = d(); | ^^^^ value used here after move -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-of-addr-of-mut.stderr b/tests/ui/moves/move-of-addr-of-mut.stderr index ddebaa0129a43..706b52d3402b8 100644 --- a/tests/ui/moves/move-of-addr-of-mut.stderr +++ b/tests/ui/moves/move-of-addr-of-mut.stderr @@ -12,6 +12,6 @@ help: consider assigning a value LL | let mut x: S = todo!(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr index 0af083e5b5233..aa0251dbd8531 100644 --- a/tests/ui/moves/move-out-of-array-1.stderr +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -7,6 +7,6 @@ LL | a[i] | cannot move out of here | move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/moves/move-out-of-slice-1.stderr b/tests/ui/moves/move-out-of-slice-1.stderr index 5a0357cf567da..86533714474b5 100644 --- a/tests/ui/moves/move-out-of-slice-1.stderr +++ b/tests/ui/moves/move-out-of-slice-1.stderr @@ -14,6 +14,6 @@ help: consider borrowing the pattern binding LL | box [ref a] => {}, | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/moves/moves-based-on-type-access-to-field.stderr b/tests/ui/moves/moves-based-on-type-access-to-field.stderr index 7390186639662..1e656e686fd87 100644 --- a/tests/ui/moves/moves-based-on-type-access-to-field.stderr +++ b/tests/ui/moves/moves-based-on-type-access-to-field.stderr @@ -15,6 +15,6 @@ help: you can `clone` the value and consume it, but this might not be your desir LL | consume(x.clone().into_iter().next().unwrap()); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-block-bad.stderr b/tests/ui/moves/moves-based-on-type-block-bad.stderr index df09ababa5a01..431ee1c0bb1bf 100644 --- a/tests/ui/moves/moves-based-on-type-block-bad.stderr +++ b/tests/ui/moves/moves-based-on-type-block-bad.stderr @@ -15,6 +15,6 @@ help: consider borrowing here LL | match &hellothere.x { | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/moves-based-on-type-capture-clause-bad.stderr b/tests/ui/moves/moves-based-on-type-capture-clause-bad.stderr index 34b7ea6586718..5e527bf445ef4 100644 --- a/tests/ui/moves/moves-based-on-type-capture-clause-bad.stderr +++ b/tests/ui/moves/moves-based-on-type-capture-clause-bad.stderr @@ -13,6 +13,6 @@ LL | println!("{}", x); | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr b/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr index db4382b58fcb2..ec483cb3d09b4 100644 --- a/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr +++ b/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr @@ -13,6 +13,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | Some(ref right) => consume(right), | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-match-bindings.stderr b/tests/ui/moves/moves-based-on-type-match-bindings.stderr index 225935532ead7..b99b2bd9eef4e 100644 --- a/tests/ui/moves/moves-based-on-type-match-bindings.stderr +++ b/tests/ui/moves/moves-based-on-type-match-bindings.stderr @@ -13,6 +13,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | Foo {ref f} => {} | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr index 125e446c33259..513631b20604c 100644 --- a/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr +++ b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr @@ -8,6 +8,6 @@ LL | let _f = to_fn(|| test(i)); | | | captured by this `Fn` closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/moves-based-on-type-tuple.stderr b/tests/ui/moves/moves-based-on-type-tuple.stderr index 0bcce30126306..6383e4a823dae 100644 --- a/tests/ui/moves/moves-based-on-type-tuple.stderr +++ b/tests/ui/moves/moves-based-on-type-tuple.stderr @@ -14,6 +14,6 @@ help: consider cloning the value if the performance cost is acceptable LL | Box::new((x.clone(), x)) | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-sru-moved-field.stderr b/tests/ui/moves/moves-sru-moved-field.stderr index cf7213637ce19..f6a5c02ad2c1b 100644 --- a/tests/ui/moves/moves-sru-moved-field.stderr +++ b/tests/ui/moves/moves-sru-moved-field.stderr @@ -8,6 +8,6 @@ LL | let _c = Foo {noncopyable: h, ..f}; | = note: move occurs because `f.moved` has type `Box`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/needs-clone-through-deref.fixed b/tests/ui/moves/needs-clone-through-deref.fixed new file mode 100644 index 0000000000000..419718175e98c --- /dev/null +++ b/tests/ui/moves/needs-clone-through-deref.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(dead_code, noop_method_call)] +use std::ops::Deref; +struct S(Vec); +impl Deref for S { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl S { + fn foo(&self) { + // `self.clone()` returns `&S`, not `Vec` + for _ in as Clone>::clone(&self.clone()).into_iter() {} //~ ERROR cannot move out of dereference of `S` + } +} +fn main() {} diff --git a/tests/ui/moves/needs-clone-through-deref.rs b/tests/ui/moves/needs-clone-through-deref.rs new file mode 100644 index 0000000000000..8116008ffe3cb --- /dev/null +++ b/tests/ui/moves/needs-clone-through-deref.rs @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(dead_code, noop_method_call)] +use std::ops::Deref; +struct S(Vec); +impl Deref for S { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl S { + fn foo(&self) { + // `self.clone()` returns `&S`, not `Vec` + for _ in self.clone().into_iter() {} //~ ERROR cannot move out of dereference of `S` + } +} +fn main() {} diff --git a/tests/ui/moves/needs-clone-through-deref.stderr b/tests/ui/moves/needs-clone-through-deref.stderr new file mode 100644 index 0000000000000..ff92f32e8d2b3 --- /dev/null +++ b/tests/ui/moves/needs-clone-through-deref.stderr @@ -0,0 +1,18 @@ +error[E0507]: cannot move out of dereference of `S` + --> $DIR/needs-clone-through-deref.rs:15:18 + | +LL | for _ in self.clone().into_iter() {} + | ^^^^^^^^^^^^ ----------- value moved due to this method call + | | + | move occurs because value has type `Vec`, which does not implement the `Copy` trait + | +note: `into_iter` takes ownership of the receiver `self`, which moves value + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | for _ in as Clone>::clone(&self.clone()).into_iter() {} + | ++++++++++++++++++++++++++++++ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.stderr b/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.stderr index a184482a446d1..bb179e1497b4e 100644 --- a/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.stderr +++ b/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.stderr @@ -15,6 +15,6 @@ help: consider reborrowing the `Pin` instead of moving it LL | foo(r.as_mut().get_mut()); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/pin-mut-reborrow.stderr b/tests/ui/moves/pin-mut-reborrow.stderr index 4bf207e7e98e0..d3ccb0a654e3b 100644 --- a/tests/ui/moves/pin-mut-reborrow.stderr +++ b/tests/ui/moves/pin-mut-reborrow.stderr @@ -18,6 +18,6 @@ help: consider reborrowing the `Pin` instead of moving it LL | foo.as_mut().foo(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.fixed b/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.fixed new file mode 100644 index 0000000000000..a4e219e1c9bf0 --- /dev/null +++ b/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.fixed @@ -0,0 +1,28 @@ +// run-rustfix +// Issue #109429 +use std::collections::hash_map::DefaultHasher; +use std::collections::HashMap; +use std::hash::BuildHasher; +use std::hash::Hash; + +#[derive(Clone)] +pub struct Hash128_1; + +impl BuildHasher for Hash128_1 { + type Hasher = DefaultHasher; + fn build_hasher(&self) -> DefaultHasher { DefaultHasher::default() } +} + +#[allow(unused)] +pub fn hashmap_copy( + map: &HashMap, +) where T: Hash + Clone, U: Clone +{ + let mut copy: Vec = as Clone>::clone(&map.clone()).into_values().collect(); //~ ERROR +} + +pub fn make_map() -> HashMap +{ + HashMap::with_hasher(Hash128_1) +} +fn main() {} diff --git a/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.rs b/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.rs new file mode 100644 index 0000000000000..efe035ebae049 --- /dev/null +++ b/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.rs @@ -0,0 +1,27 @@ +// run-rustfix +// Issue #109429 +use std::collections::hash_map::DefaultHasher; +use std::collections::HashMap; +use std::hash::BuildHasher; +use std::hash::Hash; + +pub struct Hash128_1; + +impl BuildHasher for Hash128_1 { + type Hasher = DefaultHasher; + fn build_hasher(&self) -> DefaultHasher { DefaultHasher::default() } +} + +#[allow(unused)] +pub fn hashmap_copy( + map: &HashMap, +) where T: Hash + Clone, U: Clone +{ + let mut copy: Vec = map.clone().into_values().collect(); //~ ERROR +} + +pub fn make_map() -> HashMap +{ + HashMap::with_hasher(Hash128_1) +} +fn main() {} diff --git a/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.stderr b/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.stderr new file mode 100644 index 0000000000000..403daf8ff7c7f --- /dev/null +++ b/tests/ui/moves/suggest-clone-when-some-obligation-is-unmet.stderr @@ -0,0 +1,23 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/suggest-clone-when-some-obligation-is-unmet.rs:20:28 + | +LL | let mut copy: Vec = map.clone().into_values().collect(); + | ^^^^^^^^^^^ ------------- value moved due to this method call + | | + | move occurs because value has type `HashMap`, which does not implement the `Copy` trait + | +note: `HashMap::::into_values` takes ownership of the receiver `self`, which moves value + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL +help: you could `clone` the value and consume it, if the `Hash128_1: Clone` trait bound could be satisfied + | +LL | let mut copy: Vec = as Clone>::clone(&map.clone()).into_values().collect(); + | ++++++++++++++++++++++++++++++++++++++++++++ + +help: consider annotating `Hash128_1` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | pub struct Hash128_1; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/suggest-clone.fixed b/tests/ui/moves/suggest-clone.fixed index 204bfdb10b0b3..0c4a94d77e4be 100644 --- a/tests/ui/moves/suggest-clone.fixed +++ b/tests/ui/moves/suggest-clone.fixed @@ -7,5 +7,5 @@ impl Foo { } fn main() { let foo = &Foo; - foo.clone().foo(); //~ ERROR cannot move out + ::clone(&foo).foo(); //~ ERROR cannot move out } diff --git a/tests/ui/moves/suggest-clone.stderr b/tests/ui/moves/suggest-clone.stderr index 065acf904a435..25e89a5895531 100644 --- a/tests/ui/moves/suggest-clone.stderr +++ b/tests/ui/moves/suggest-clone.stderr @@ -13,9 +13,9 @@ LL | fn foo(self) {} | ^^^^ help: you can `clone` the value and consume it, but this might not be your desired behavior | -LL | foo.clone().foo(); - | ++++++++ +LL | ::clone(&foo).foo(); + | +++++++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/use_of_moved_value_clone_suggestions.stderr b/tests/ui/moves/use_of_moved_value_clone_suggestions.stderr index 0bb486a88937a..785329565eb9b 100644 --- a/tests/ui/moves/use_of_moved_value_clone_suggestions.stderr +++ b/tests/ui/moves/use_of_moved_value_clone_suggestions.stderr @@ -13,6 +13,6 @@ help: clone the value to increment its reference count LL | (t.clone(), t) | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/mut/mut-cant-alias.stderr b/tests/ui/mut/mut-cant-alias.stderr index d56e45db13d0e..4106ebdd1cb2b 100644 --- a/tests/ui/mut/mut-cant-alias.stderr +++ b/tests/ui/mut/mut-cant-alias.stderr @@ -8,6 +8,6 @@ LL | let b2 = &mut *b; LL | b1.use_mut(); | -- first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/mut/mut-cross-borrowing.stderr b/tests/ui/mut/mut-cross-borrowing.stderr index 8a3076db9b233..4cfe56bfab6f2 100644 --- a/tests/ui/mut/mut-cross-borrowing.stderr +++ b/tests/ui/mut/mut-cross-borrowing.stderr @@ -18,6 +18,6 @@ help: consider mutably borrowing here LL | f(&mut x) | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mut/mut-ref.stderr b/tests/ui/mut/mut-ref.stderr index e6d4901aafb17..b91392f223a8a 100644 --- a/tests/ui/mut/mut-ref.stderr +++ b/tests/ui/mut/mut-ref.stderr @@ -4,5 +4,5 @@ error: the order of `mut` and `ref` is incorrect LL | let mut ref x = 10; | ^^^^^^^ help: try switching the order: `ref mut` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/mut/mutable-class-fields-2.stderr b/tests/ui/mut/mutable-class-fields-2.stderr index c53c6ea302c67..eb0c54f885ba8 100644 --- a/tests/ui/mut/mutable-class-fields-2.stderr +++ b/tests/ui/mut/mutable-class-fields-2.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | pub fn eat(&mut self) { | ~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/mut/mutable-class-fields.stderr b/tests/ui/mut/mutable-class-fields.stderr index 1d731be8a855d..e57cce62ee43f 100644 --- a/tests/ui/mut/mutable-class-fields.stderr +++ b/tests/ui/mut/mutable-class-fields.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut nyan : Cat = cat(52, 99); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/mut/mutable-enum-indirect.stderr b/tests/ui/mut/mutable-enum-indirect.stderr index 9e1f4e1fe4ea9..0b7783b3318b1 100644 --- a/tests/ui/mut/mutable-enum-indirect.stderr +++ b/tests/ui/mut/mutable-enum-indirect.stderr @@ -19,6 +19,6 @@ note: required by a bound in `bar` LL | fn bar(_: T) {} | ^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/native-library-link-flags/link-arg-from-rs.rs b/tests/ui/native-library-link-flags/link-arg-from-rs.rs index 075e4d9e79e46..4a6017fea339a 100644 --- a/tests/ui/native-library-link-flags/link-arg-from-rs.rs +++ b/tests/ui/native-library-link-flags/link-arg-from-rs.rs @@ -1,8 +1,7 @@ -// link-arg is not supposed to be usable in #[link] attributes +#![feature(link_arg_attribute)] -// compile-flags: -// error-pattern: error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib - -#[link(kind = "link-arg")] +#[link(kind = "link-arg", name = "arg", modifiers = "+bundle")] +//~^ ERROR linking modifier `bundle` is only compatible with `static` linking kind extern "C" {} + pub fn main() {} diff --git a/tests/ui/native-library-link-flags/link-arg-from-rs.stderr b/tests/ui/native-library-link-flags/link-arg-from-rs.stderr index 69a7825c0b105..f31e15f1da615 100644 --- a/tests/ui/native-library-link-flags/link-arg-from-rs.stderr +++ b/tests/ui/native-library-link-flags/link-arg-from-rs.stderr @@ -1,16 +1,8 @@ -error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib - --> $DIR/link-arg-from-rs.rs:6:15 +error: linking modifier `bundle` is only compatible with `static` linking kind + --> $DIR/link-arg-from-rs.rs:3:53 | -LL | #[link(kind = "link-arg")] - | ^^^^^^^^^^ unknown link kind +LL | #[link(kind = "link-arg", name = "arg", modifiers = "+bundle")] + | ^^^^^^^^^ -error[E0459]: `#[link]` attribute requires a `name = "string"` argument - --> $DIR/link-arg-from-rs.rs:6:1 - | -LL | #[link(kind = "link-arg")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0458, E0459. -For more information about an error, try `rustc --explain E0458`. diff --git a/tests/ui/native-library-link-flags/modifiers-override-3.stderr b/tests/ui/native-library-link-flags/modifiers-override-3.stderr index 365e561810017..3eb9459f6f3a5 100644 --- a/tests/ui/native-library-link-flags/modifiers-override-3.stderr +++ b/tests/ui/native-library-link-flags/modifiers-override-3.stderr @@ -1,4 +1,4 @@ error: overriding linking modifiers from command line is not supported -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/native-library-link-flags/suggest-libname-only-1.stderr b/tests/ui/native-library-link-flags/suggest-libname-only-1.stderr index 64d0a9077ed15..e142835a9d64c 100644 --- a/tests/ui/native-library-link-flags/suggest-libname-only-1.stderr +++ b/tests/ui/native-library-link-flags/suggest-libname-only-1.stderr @@ -2,5 +2,5 @@ error: could not find native static library `libfoo.a`, perhaps an -L flag is mi | = help: only provide the library name `foo`, not the full filename -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/native-library-link-flags/suggest-libname-only-2.stderr b/tests/ui/native-library-link-flags/suggest-libname-only-2.stderr index e166af9ed8f03..392d2f01f619b 100644 --- a/tests/ui/native-library-link-flags/suggest-libname-only-2.stderr +++ b/tests/ui/native-library-link-flags/suggest-libname-only-2.stderr @@ -2,5 +2,5 @@ error: could not find native static library `bar.lib`, perhaps an -L flag is mis | = help: only provide the library name `bar`, not the full filename -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nested-cfg-attrs.stderr b/tests/ui/nested-cfg-attrs.stderr index f63888b2f8ad0..16c2930714353 100644 --- a/tests/ui/nested-cfg-attrs.stderr +++ b/tests/ui/nested-cfg-attrs.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `f` in this scope LL | fn main() { f() } | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr b/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr index fa3db33c9606f..bdeb2fb906c78 100644 --- a/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr +++ b/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn foo(x: !) -> ! { | ^^^ ---- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr index 283aca1b084ef..92fa9068cfd5e 100644 --- a/tests/ui/never_type/defaulted-never-note.fallback.stderr +++ b/tests/ui/never_type/defaulted-never-note.fallback.stderr @@ -15,6 +15,6 @@ note: required by a bound in `foo` LL | fn foo(_t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr index df29fe227135d..ff28480bd9958 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr +++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr @@ -17,6 +17,6 @@ note: required by a bound in `unconstrained_arg` LL | fn unconstrained_arg(_: T) {} | ^^^^ required by this bound in `unconstrained_arg` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs index 7ea97126f89c9..26c8175be638f 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs @@ -1,4 +1,4 @@ -// Variant of diverging-falllback-control-flow that tests +// Variant of diverging-fallback-control-flow that tests // the specific case of a free function with an unconstrained // return type. This captures the pattern we saw in the wild // in the objc crate, where changing the fallback from `!` to `()` @@ -9,7 +9,7 @@ // revisions: nofallback fallback #![cfg_attr(fallback, feature(never_type, never_type_fallback))] - +#![allow(unit_bindings)] fn make_unit() {} diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr index f7bf858158231..ee7d9070cd325 100644 --- a/tests/ui/never_type/exhaustive_patterns.stderr +++ b/tests/ui/never_type/exhaustive_patterns.stderr @@ -21,6 +21,6 @@ help: you might want to use `if let` to ignore the variant that isn't matched LL | if let Either::A(()) = foo() { todo!() }; | ++ +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr index 49f55db1e25cd..aa4a2760ffdc6 100644 --- a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -12,6 +12,6 @@ LL | | }) as Box); found type `!` = note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/never_type/feature-gate-never_type_fallback.stderr b/tests/ui/never_type/feature-gate-never_type_fallback.stderr index 56aafbb4ce89e..cbb670ea7083b 100644 --- a/tests/ui/never_type/feature-gate-never_type_fallback.stderr +++ b/tests/ui/never_type/feature-gate-never_type_fallback.stderr @@ -19,6 +19,6 @@ note: required by a bound in `foo` LL | fn foo(_: impl T) {} | ^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/impl_trait_fallback3.stderr b/tests/ui/never_type/impl_trait_fallback3.stderr index 821d141569ed9..e2246eea17c61 100644 --- a/tests/ui/never_type/impl_trait_fallback3.stderr +++ b/tests/ui/never_type/impl_trait_fallback3.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait T { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/impl_trait_fallback4.stderr b/tests/ui/never_type/impl_trait_fallback4.stderr index 67421ba8da757..8f6b5cfea68a9 100644 --- a/tests/ui/never_type/impl_trait_fallback4.stderr +++ b/tests/ui/never_type/impl_trait_fallback4.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait T { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-10176.stderr b/tests/ui/never_type/issue-10176.stderr index 3f381b9aea9b2..cd6473e0682aa 100644 --- a/tests/ui/never_type/issue-10176.stderr +++ b/tests/ui/never_type/issue-10176.stderr @@ -9,6 +9,6 @@ LL | (return 1, return 2) = note: expected type `isize` found tuple `(!, !)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/issue-13352.stderr b/tests/ui/never_type/issue-13352.stderr index 406785bfea0e2..91885380b1ff1 100644 --- a/tests/ui/never_type/issue-13352.stderr +++ b/tests/ui/never_type/issue-13352.stderr @@ -11,6 +11,6 @@ LL | 2_usize + (loop {}); <&'a usize as Add> <&usize as Add<&usize>> -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-51506.stderr b/tests/ui/never_type/issue-51506.stderr index 293ec3a725d89..09379257c4cca 100644 --- a/tests/ui/never_type/issue-51506.stderr +++ b/tests/ui/never_type/issue-51506.stderr @@ -11,6 +11,6 @@ note: required by a bound in `Trait::Out` LL | type Out: Iterator; | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::Out` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/never-assign-wrong-type.stderr b/tests/ui/never_type/never-assign-wrong-type.stderr index ce34d9483247f..f59de5d2a4289 100644 --- a/tests/ui/never_type/never-assign-wrong-type.stderr +++ b/tests/ui/never_type/never-assign-wrong-type.stderr @@ -9,6 +9,6 @@ LL | let x: ! = "hello"; = note: expected type `!` found reference `&'static str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/never-from-impl-is-reserved.stderr b/tests/ui/never_type/never-from-impl-is-reserved.current.stderr similarity index 86% rename from tests/ui/never_type/never-from-impl-is-reserved.stderr rename to tests/ui/never_type/never-from-impl-is-reserved.current.stderr index 871c512052821..d008f88c188b8 100644 --- a/tests/ui/never_type/never-from-impl-is-reserved.stderr +++ b/tests/ui/never_type/never-from-impl-is-reserved.current.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo` - --> $DIR/never-from-impl-is-reserved.rs:10:1 + --> $DIR/never-from-impl-is-reserved.rs:13:1 | LL | impl MyTrait for MyFoo {} | ---------------------- first implementation here @@ -9,6 +9,6 @@ LL | impl MyTrait for T where T: From {} | = note: permitting this impl would forbid us from adding `impl From for T` later; see rust-lang/rust#64715 for details -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/never_type/never-from-impl-is-reserved.next.stderr b/tests/ui/never_type/never-from-impl-is-reserved.next.stderr new file mode 100644 index 0000000000000..d008f88c188b8 --- /dev/null +++ b/tests/ui/never_type/never-from-impl-is-reserved.next.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo` + --> $DIR/never-from-impl-is-reserved.rs:13:1 + | +LL | impl MyTrait for MyFoo {} + | ---------------------- first implementation here +LL | // This will conflict with the first impl if we impl `for T: From`. +LL | impl MyTrait for T where T: From {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` + | + = note: permitting this impl would forbid us from adding `impl From for T` later; see rust-lang/rust#64715 for details + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/never_type/never-from-impl-is-reserved.rs b/tests/ui/never_type/never-from-impl-is-reserved.rs index 9d16015bdc129..f358e045cf019 100644 --- a/tests/ui/never_type/never-from-impl-is-reserved.rs +++ b/tests/ui/never_type/never-from-impl-is-reserved.rs @@ -1,5 +1,8 @@ // check that the `for T: From` impl is reserved +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next-coherence + #![feature(never_type)] pub struct MyFoo; diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr index cb37863058931..f5249814c785c 100644 --- a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr +++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -7,6 +7,6 @@ LL | >::from(never); = help: the trait `From` is implemented for `E` = help: for that trait implementation, expected `!`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/nll/borrowed-local-error.stderr b/tests/ui/nll/borrowed-local-error.stderr index 1cca4077d825a..acefdea97d3ba 100644 --- a/tests/ui/nll/borrowed-local-error.stderr +++ b/tests/ui/nll/borrowed-local-error.stderr @@ -11,6 +11,6 @@ LL | LL | }); | - `v` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/borrowed-match-issue-45045.stderr b/tests/ui/nll/borrowed-match-issue-45045.stderr index 33e3eb797969e..b2ec724f3093f 100644 --- a/tests/ui/nll/borrowed-match-issue-45045.stderr +++ b/tests/ui/nll/borrowed-match-issue-45045.stderr @@ -10,6 +10,6 @@ LL | match e { LL | *g = Xyz::B; | ----------- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/nll/borrowed-referent-issue-38899.stderr b/tests/ui/nll/borrowed-referent-issue-38899.stderr index 16588cbcfb285..7075965289bde 100644 --- a/tests/ui/nll/borrowed-referent-issue-38899.stderr +++ b/tests/ui/nll/borrowed-referent-issue-38899.stderr @@ -10,6 +10,6 @@ LL | LL | drop(x); | - mutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/borrowed-temporary-error.stderr b/tests/ui/nll/borrowed-temporary-error.stderr index 89781d96fab26..a17de890e3f67 100644 --- a/tests/ui/nll/borrowed-temporary-error.stderr +++ b/tests/ui/nll/borrowed-temporary-error.stderr @@ -11,6 +11,6 @@ LL | println!("{:?}", x); | = note: consider using a `let` binding to create a longer lived value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/nll/borrowed-universal-error-2.stderr b/tests/ui/nll/borrowed-universal-error-2.stderr index 7213ed3bafb37..aa31142b24e32 100644 --- a/tests/ui/nll/borrowed-universal-error-2.stderr +++ b/tests/ui/nll/borrowed-universal-error-2.stderr @@ -4,6 +4,6 @@ error[E0515]: cannot return reference to local variable `v` LL | &v | ^^ returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/borrowed-universal-error.stderr b/tests/ui/nll/borrowed-universal-error.stderr index 88a2d8fcf8cc0..d93e2ffc85cdb 100644 --- a/tests/ui/nll/borrowed-universal-error.stderr +++ b/tests/ui/nll/borrowed-universal-error.stderr @@ -7,6 +7,6 @@ LL | gimme(&(v,)) | | temporary value created here | returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/capture-mut-ref.stderr b/tests/ui/nll/capture-mut-ref.stderr index 4898d569235e7..d76e031466d4f 100644 --- a/tests/ui/nll/capture-mut-ref.stderr +++ b/tests/ui/nll/capture-mut-ref.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(unused_mut)] | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/capture-ref-in-struct.stderr b/tests/ui/nll/capture-ref-in-struct.stderr index 84b7ecf2f7da8..81b937051c2ab 100644 --- a/tests/ui/nll/capture-ref-in-struct.stderr +++ b/tests/ui/nll/capture-ref-in-struct.stderr @@ -13,6 +13,6 @@ LL | LL | deref(p); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr index b3cb7813e19c8..8debea6a0a2d2 100644 --- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) i32)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) i32)), (), ] @@ -27,5 +27,5 @@ LL | fn test() { | = note: defining type: test -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr index 4f0156728ac1e..b050c0566c617 100644 --- a/tests/ui/nll/closure-requirements/escape-argument.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)), (), ] @@ -33,6 +33,6 @@ LL | LL | deref(p); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr index 727df1cf890c7..aa73e91cc77e5 100644 --- a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -48,6 +48,6 @@ LL | LL | deref(p); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr index ff638f2a1eca8..949dcc78703a7 100644 --- a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -34,6 +34,6 @@ LL | LL | deref(p); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index ccf56bf6f37df..bffd365b9ccd0 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?3 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&'?2 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?3 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?4 @@ -32,5 +32,5 @@ LL | fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: | = note: defining type: supply -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr index a16433c9d374b..843d307b80b7b 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 @@ -35,5 +35,5 @@ LL | demand_y(x, y, x.get()) | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 9e0f16c0fc783..5ce3dae5a33dc 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -6,7 +6,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case1::{closure#0} with closure args [ i32, - for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), (), ] @@ -36,7 +36,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case2::{closure#0} with closure args [ i32, - for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), (), ] = note: number of external vids: 2 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index e4989e321550f..54784df527548 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?2 @@ -44,6 +44,6 @@ LL | | }); = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index be35e62d0704b..53547afbfea2d 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&'?2 &ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 @@ -44,6 +44,6 @@ LL | | }); = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr index 8880dd816a1fe..5566c76d854f4 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 @@ -35,5 +35,5 @@ LL | demand_y(outlives1, outlives2, x.get()) | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index 47774b63f8186..0dd53f81ae13c 100644 --- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 3404bb128278d..64deaa00fa321 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?2 @@ -31,5 +31,5 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { | = note: defining type: supply -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index e40648912e3cf..ee49b4dac22b0 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 @@ -31,5 +31,5 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { | = note: defining type: supply -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr index a20f885fe81f4..28c5c43a6ace8 100644 --- a/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -36,6 +36,6 @@ help: consider adding an explicit lifetime bound LL | T: Trait<'a> + 'a, | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr index 2fec9bc62d1c7..81b5f09b04157 100644 --- a/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr +++ b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr @@ -12,6 +12,6 @@ LL | z = &local_arr; LL | } | - `local_arr` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr index 7034492cee09d..0f3e9314d9336 100644 --- a/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr +++ b/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr @@ -6,5 +6,5 @@ LL | fn foo(x: &u32) -> &'static u32 { LL | &*x | ^^^ returning this value requires that `'1` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr index d0a24a267fd4f..36478e723cced 100644 --- a/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr +++ b/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr @@ -6,5 +6,5 @@ LL | fn foo<'a>(x: &'a u32) -> &'static u32 { LL | &*x | ^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr index d0ba539253248..9a0f4bb6d9aa8 100644 --- a/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr +++ b/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr @@ -10,5 +10,5 @@ LL | &*x | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 18fb7195d021f..a13caf8c298f2 100644 --- a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)) -> &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, (), ] @@ -27,5 +27,5 @@ LL | fn test() { | = note: defining type: test -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/constant-thread-locals-issue-47053.stderr b/tests/ui/nll/constant-thread-locals-issue-47053.stderr index a44acfb5fc354..1c6844d6e332a 100644 --- a/tests/ui/nll/constant-thread-locals-issue-47053.stderr +++ b/tests/ui/nll/constant-thread-locals-issue-47053.stderr @@ -4,6 +4,6 @@ error[E0594]: cannot assign to immutable static item `FOO` LL | FOO = 6; | ^^^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/continue-after-missing-main.stderr b/tests/ui/nll/continue-after-missing-main.stderr index 0df8d8d703ecd..960503e8fd5bf 100644 --- a/tests/ui/nll/continue-after-missing-main.stderr +++ b/tests/ui/nll/continue-after-missing-main.stderr @@ -4,6 +4,6 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main` LL | } | ^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/nll/coroutine-upvar-mutability.stderr b/tests/ui/nll/coroutine-upvar-mutability.stderr index 464bbc7693117..8922eae315188 100644 --- a/tests/ui/nll/coroutine-upvar-mutability.stderr +++ b/tests/ui/nll/coroutine-upvar-mutability.stderr @@ -7,6 +7,6 @@ LL | move || { LL | x = 1; | ^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/decl-macro-illegal-copy.stderr b/tests/ui/nll/decl-macro-illegal-copy.stderr index 7948485bd6866..82fb8cdc91577 100644 --- a/tests/ui/nll/decl-macro-illegal-copy.stderr +++ b/tests/ui/nll/decl-macro-illegal-copy.stderr @@ -9,6 +9,6 @@ LL | wrapper.inner, | = note: move occurs because `wrapper.inner` has type `NonCopy`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr index 862c925b468fd..6c96f474aec45 100644 --- a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr +++ b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr @@ -11,6 +11,6 @@ LL | drop(a.0); LL | } | - `s` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr index ebaf6d1244d7d..d86ede62992eb 100644 --- a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr +++ b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr @@ -11,6 +11,6 @@ LL | drop(a); LL | } | - `s` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/get_default.polonius.stderr b/tests/ui/nll/get_default.polonius.stderr index 476d86cfba9c3..613d06cce9156 100644 --- a/tests/ui/nll/get_default.polonius.stderr +++ b/tests/ui/nll/get_default.polonius.stderr @@ -13,6 +13,6 @@ LL | LL | return v; | - returning this value requires that `*map` is borrowed for `'1` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.stderr b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.stderr index a1f973e0fdf5a..a37639883d2b1 100644 --- a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.stderr +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.stderr @@ -9,6 +9,6 @@ LL | (|| { *x = None; drop(force_fn_once); })(); | | | cannot mutably borrow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.stderr b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.stderr index dd46308d14004..5cd0982526b3a 100644 --- a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.stderr +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.stderr @@ -9,6 +9,6 @@ LL | (|| { *x = None; drop(force_fn_once); })(); | | | cannot mutably borrow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.stderr b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.stderr index 4a4a25790b985..e4d0cf3111272 100644 --- a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.stderr +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.stderr @@ -9,6 +9,6 @@ LL | (|| { *x = &None; drop(force_fn_once); })(); | | | cannot mutably borrow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/nll/issue-27868.stderr b/tests/ui/nll/issue-27868.stderr index 204eda3d26796..5e70b3017d5ed 100644 --- a/tests/ui/nll/issue-27868.stderr +++ b/tests/ui/nll/issue-27868.stderr @@ -13,6 +13,6 @@ LL | | 0 LL | | }; | |_____- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/issue-30438-a.stderr b/tests/ui/nll/issue-30438-a.stderr index 53845af82fb11..73599f6b71fac 100644 --- a/tests/ui/nll/issue-30438-a.stderr +++ b/tests/ui/nll/issue-30438-a.stderr @@ -7,6 +7,6 @@ LL | return &Test { s: &self.s}; | |temporary value created here | returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-30438-b.stderr b/tests/ui/nll/issue-30438-b.stderr index fd6bd25b1da16..b8eb4632a024d 100644 --- a/tests/ui/nll/issue-30438-b.stderr +++ b/tests/ui/nll/issue-30438-b.stderr @@ -7,6 +7,6 @@ LL | &Test { s: &self.s} | |temporary value created here | returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-30438-c.stderr b/tests/ui/nll/issue-30438-c.stderr index 7c001088097ab..c8ca2bff74e50 100644 --- a/tests/ui/nll/issue-30438-c.stderr +++ b/tests/ui/nll/issue-30438-c.stderr @@ -4,6 +4,6 @@ error[E0515]: cannot return reference to local variable `x` LL | &x | ^^ returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-31567.stderr b/tests/ui/nll/issue-31567.stderr index 7d43383e89fd7..0f35fc1bf19f6 100644 --- a/tests/ui/nll/issue-31567.stderr +++ b/tests/ui/nll/issue-31567.stderr @@ -11,6 +11,6 @@ LL | &s_inner.0 LL | } | - here, drop of `v` needs exclusive access to `*v.0`, because the type `VecWrapper<'_>` implements the `Drop` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/nll/issue-45157.stderr b/tests/ui/nll/issue-45157.stderr index 57fd8d49c887c..2dbf1c47de541 100644 --- a/tests/ui/nll/issue-45157.stderr +++ b/tests/ui/nll/issue-45157.stderr @@ -12,6 +12,6 @@ LL | println!("{} {}", mref, nref) | = note: `u.z.c` is a field of the union `U`, so it overlaps the field `u.s.a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/issue-46023.stderr b/tests/ui/nll/issue-46023.stderr index ca19c2501205d..062e07407ce09 100644 --- a/tests/ui/nll/issue-46023.stderr +++ b/tests/ui/nll/issue-46023.stderr @@ -7,6 +7,6 @@ LL | let x = 0; LL | x = 1; | ^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/issue-46036.stderr b/tests/ui/nll/issue-46036.stderr index f337e23455070..69753df14f6f7 100644 --- a/tests/ui/nll/issue-46036.stderr +++ b/tests/ui/nll/issue-46036.stderr @@ -12,6 +12,6 @@ LL | loop { } LL | } | - `a` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-46589.stderr b/tests/ui/nll/issue-46589.stderr index 82cd364eeffd0..abf62aaa51088 100644 --- a/tests/ui/nll/issue-46589.stderr +++ b/tests/ui/nll/issue-46589.stderr @@ -10,6 +10,6 @@ LL | None => (*other).new_self() | second mutable borrow occurs here | first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/issue-47388.stderr b/tests/ui/nll/issue-47388.stderr index 09b9d638afb03..bd8b4c1eea00f 100644 --- a/tests/ui/nll/issue-47388.stderr +++ b/tests/ui/nll/issue-47388.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | let fancy_ref = &mut (&mut fancy); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/issue-47470.stderr b/tests/ui/nll/issue-47470.stderr index 0b1247d60ec67..ae30f4182845e 100644 --- a/tests/ui/nll/issue-47470.stderr +++ b/tests/ui/nll/issue-47470.stderr @@ -4,6 +4,6 @@ error[E0515]: cannot return reference to local variable `local` LL | &local | ^^^^^^ returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-48238.stderr b/tests/ui/nll/issue-48238.stderr index 0aa1eedad9fd9..e15fbbdcdf21f 100644 --- a/tests/ui/nll/issue-48238.stderr +++ b/tests/ui/nll/issue-48238.stderr @@ -9,5 +9,5 @@ LL | move || use_val(&orig); | = note: closure implements `Fn`, so references to captured variables can't escape the closure -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-48697.stderr b/tests/ui/nll/issue-48697.stderr index f0c29b72b4298..243a6011741e5 100644 --- a/tests/ui/nll/issue-48697.stderr +++ b/tests/ui/nll/issue-48697.stderr @@ -6,6 +6,6 @@ LL | let k = f(&z); LL | f(x) | ^^^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-48803.stderr b/tests/ui/nll/issue-48803.stderr index e24606e0b53e8..41dc7c8f9a464 100644 --- a/tests/ui/nll/issue-48803.stderr +++ b/tests/ui/nll/issue-48803.stderr @@ -10,6 +10,6 @@ LL | LL | println!("{}", w); // prints "modified" | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/issue-50716.stderr b/tests/ui/nll/issue-50716.stderr index 38dd1b5f6fe73..a09e76705156e 100644 --- a/tests/ui/nll/issue-50716.stderr +++ b/tests/ui/nll/issue-50716.stderr @@ -7,5 +7,5 @@ LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) LL | let _x = *s; | ^^ proving this value is `Sized` requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-51244.stderr b/tests/ui/nll/issue-51244.stderr index 8ccb5809e3972..610482f8b1a99 100644 --- a/tests/ui/nll/issue-51244.stderr +++ b/tests/ui/nll/issue-51244.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | let ref mut my_ref @ _ = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/issue-51268.stderr b/tests/ui/nll/issue-51268.stderr index 0483bda6379fd..b0c3d8b878d33 100644 --- a/tests/ui/nll/issue-51268.stderr +++ b/tests/ui/nll/issue-51268.stderr @@ -12,6 +12,6 @@ LL | | &self.number; LL | | }); | |__________^ mutable borrow occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/issue-51512.stderr b/tests/ui/nll/issue-51512.stderr index 072e96788b17e..ed42899dc94fc 100644 --- a/tests/ui/nll/issue-51512.stderr +++ b/tests/ui/nll/issue-51512.stderr @@ -13,6 +13,6 @@ help: consider cloning the value if the performance cost is acceptable LL | let r = range.clone(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/issue-52113.stderr b/tests/ui/nll/issue-52113.stderr index 84d4eb266f125..0a5e2e5a4b727 100644 --- a/tests/ui/nll/issue-52113.stderr +++ b/tests/ui/nll/issue-52113.stderr @@ -11,5 +11,5 @@ LL | data.push(value); | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-52213.stderr b/tests/ui/nll/issue-52213.stderr index da31bcd547507..ed3723a7f03b0 100644 --- a/tests/ui/nll/issue-52213.stderr +++ b/tests/ui/nll/issue-52213.stderr @@ -11,5 +11,5 @@ LL | ((u,),) => u, | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-52533-1.stderr b/tests/ui/nll/issue-52533-1.stderr index 20f19b2596716..b23ef3f33cc38 100644 --- a/tests/ui/nll/issue-52533-1.stderr +++ b/tests/ui/nll/issue-52533-1.stderr @@ -7,5 +7,5 @@ LL | gimme(|x, y| y) | | has type `&Foo<'_, '1, u32>` | has type `&Foo<'_, '2, u32>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-52534-2.stderr b/tests/ui/nll/issue-52534-2.stderr index 35d39bb6e908d..62715b836f685 100644 --- a/tests/ui/nll/issue-52534-2.stderr +++ b/tests/ui/nll/issue-52534-2.stderr @@ -12,6 +12,6 @@ LL | LL | println!("{}", y); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr b/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr index fb61b30f09db2..587f307102766 100644 --- a/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr +++ b/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr @@ -8,6 +8,6 @@ LL | expect_fn(|| drop(x.0)); | | | captured by this `Fn` closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/nll/issue-52663-trait-object.stderr b/tests/ui/nll/issue-52663-trait-object.stderr index 338f64841321f..fe55d8d49ad77 100644 --- a/tests/ui/nll/issue-52663-trait-object.stderr +++ b/tests/ui/nll/issue-52663-trait-object.stderr @@ -10,6 +10,6 @@ LL | Box::new(tmp1) as Box LL | }; | - `tmp0` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-52669.stderr b/tests/ui/nll/issue-52669.stderr index db53e444b9e4a..f3cba9afb5c90 100644 --- a/tests/ui/nll/issue-52669.stderr +++ b/tests/ui/nll/issue-52669.stderr @@ -9,6 +9,6 @@ LL | foo(a); LL | a.b.clone() | ^^^ value borrowed here after move -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/issue-52742.stderr b/tests/ui/nll/issue-52742.stderr index a7973829656b2..8c09e542c05cc 100644 --- a/tests/ui/nll/issue-52742.stderr +++ b/tests/ui/nll/issue-52742.stderr @@ -8,5 +8,5 @@ LL | fn take_bar(&mut self, b: Bar<'_>) { LL | self.y = b.z | ^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-53040.stderr b/tests/ui/nll/issue-53040.stderr index 87ffe9b1abf45..6c82459cc86df 100644 --- a/tests/ui/nll/issue-53040.stderr +++ b/tests/ui/nll/issue-53040.stderr @@ -13,5 +13,5 @@ LL | || &mut v; = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-53773.stderr b/tests/ui/nll/issue-53773.stderr index fc185d42d5f97..580f6727a882b 100644 --- a/tests/ui/nll/issue-53773.stderr +++ b/tests/ui/nll/issue-53773.stderr @@ -11,6 +11,6 @@ LL | } | = note: consider using a `let` binding to create a longer lived value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/nll/issue-53807.stderr b/tests/ui/nll/issue-53807.stderr index d8f58b591311d..b07e3669fe93b 100644 --- a/tests/ui/nll/issue-53807.stderr +++ b/tests/ui/nll/issue-53807.stderr @@ -10,6 +10,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | if let Some(ref thing) = maybe { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/issue-54189.stderr b/tests/ui/nll/issue-54189.stderr index 4787abd49d178..14ed2bb222d74 100644 --- a/tests/ui/nll/issue-54189.stderr +++ b/tests/ui/nll/issue-54189.stderr @@ -4,6 +4,6 @@ error[E0582]: binding for associated type `Output` references lifetime `'r`, whi LL | fn bug() -> impl for <'r> Fn() -> &'r () { || { &() } } | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/nll/issue-54302.stderr b/tests/ui/nll/issue-54302.stderr index 26c46571f9cb2..269739af6026d 100644 --- a/tests/ui/nll/issue-54302.stderr +++ b/tests/ui/nll/issue-54302.stderr @@ -7,5 +7,5 @@ LL | assert_deserialize_owned::<&'static str>(); = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`... = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr b/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr index 4a32c777a86f1..4f11394581800 100644 --- a/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr +++ b/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr @@ -21,6 +21,6 @@ help: consider adding semicolon after the expression so its temporaries are drop LL | D("other").next(&_thing1); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-niconii.stderr b/tests/ui/nll/issue-54556-niconii.stderr index ad0a2d1e3243e..015d9e1821205 100644 --- a/tests/ui/nll/issue-54556-niconii.stderr +++ b/tests/ui/nll/issue-54556-niconii.stderr @@ -21,6 +21,6 @@ help: consider adding semicolon after the expression so its temporaries are drop LL | if let Ok(_) = counter.lock() { }; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-stephaneyfx.stderr b/tests/ui/nll/issue-54556-stephaneyfx.stderr index 0dfea0fd748d4..2296407535b7a 100644 --- a/tests/ui/nll/issue-54556-stephaneyfx.stderr +++ b/tests/ui/nll/issue-54556-stephaneyfx.stderr @@ -21,6 +21,6 @@ help: for example, you could save the expression's value in a new local variable LL | let x = rows.map(|row| row).next(); x | +++++++ +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr b/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr index 4eae9fdcde0d2..b5bfdfd7f6adf 100644 --- a/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr +++ b/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr @@ -20,6 +20,6 @@ help: consider adding semicolon after the expression so its temporaries are drop LL | D(&_thing1).end(); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-wrap-it-up.stderr b/tests/ui/nll/issue-54556-wrap-it-up.stderr index adc419ae51562..59130332118f1 100644 --- a/tests/ui/nll/issue-54556-wrap-it-up.stderr +++ b/tests/ui/nll/issue-54556-wrap-it-up.stderr @@ -9,6 +9,6 @@ LL | x = 1; LL | } | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr index 64ad7a21a3c5a..92298c6617ff5 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr @@ -7,5 +7,5 @@ LL | cx: &dyn DebugContext, LL | bar.debug_with(cx); | ^^ cast requires that `'1` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-54943.stderr b/tests/ui/nll/issue-54943.stderr index 59be0f983b907..7ea736336839b 100644 --- a/tests/ui/nll/issue-54943.stderr +++ b/tests/ui/nll/issue-54943.stderr @@ -7,5 +7,5 @@ LL | fn boo<'a>() { LL | let x = foo::<&'a u32>(); | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-55394.stderr b/tests/ui/nll/issue-55394.stderr index 24b8c84b4a96a..69df901026436 100644 --- a/tests/ui/nll/issue-55394.stderr +++ b/tests/ui/nll/issue-55394.stderr @@ -8,5 +8,5 @@ LL | fn new(bar: &mut Bar) -> Self { LL | Foo { bar } | ^^^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-55401.stderr b/tests/ui/nll/issue-55401.stderr index 4f797f26a1a7c..50167dd28f9fc 100644 --- a/tests/ui/nll/issue-55401.stderr +++ b/tests/ui/nll/issue-55401.stderr @@ -7,5 +7,5 @@ LL | let (ref y, _z): (&'a u32, u32) = (&22, 44); LL | *y | ^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-55511.stderr b/tests/ui/nll/issue-55511.stderr index ecb9ef0aef96e..ac7cd54df71f2 100644 --- a/tests/ui/nll/issue-55511.stderr +++ b/tests/ui/nll/issue-55511.stderr @@ -12,6 +12,6 @@ LL | <() as Foo<'static>>::C => { } LL | } | - `a` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-57265-return-type-wf-check.stderr b/tests/ui/nll/issue-57265-return-type-wf-check.stderr index bb45575fa64c3..d6810fe093895 100644 --- a/tests/ui/nll/issue-57265-return-type-wf-check.stderr +++ b/tests/ui/nll/issue-57265-return-type-wf-check.stderr @@ -7,6 +7,6 @@ LL | let (_, z) = foo(&"hello".to_string()); | | creates a temporary value which is freed while still in use | argument requires that borrow lasts for `'static` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/nll/issue-57280-1-flipped.stderr b/tests/ui/nll/issue-57280-1-flipped.stderr index 7a2135a2ade83..81bff3ba0fbc3 100644 --- a/tests/ui/nll/issue-57280-1-flipped.stderr +++ b/tests/ui/nll/issue-57280-1-flipped.stderr @@ -7,5 +7,5 @@ LL | match x { LL | <() as Foo<'a>>::C => { } | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-57843.stderr b/tests/ui/nll/issue-57843.stderr index 2ab49ec61cf59..eed511460cac7 100644 --- a/tests/ui/nll/issue-57843.stderr +++ b/tests/ui/nll/issue-57843.stderr @@ -7,5 +7,5 @@ LL | Foo(Box::new(|_| ())); = note: closure with signature `fn(&'2 bool)` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-61424.stderr b/tests/ui/nll/issue-61424.stderr index 6de6b7f3abd0b..8dc66cbaef80f 100644 --- a/tests/ui/nll/issue-61424.stderr +++ b/tests/ui/nll/issue-61424.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(unused_mut)] | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-67007-escaping-data.stderr b/tests/ui/nll/issue-67007-escaping-data.stderr index ac9c59bf7f2b3..eb7b57c7e998a 100644 --- a/tests/ui/nll/issue-67007-escaping-data.stderr +++ b/tests/ui/nll/issue-67007-escaping-data.stderr @@ -10,5 +10,5 @@ LL | let other = self.use_fcx(fcx); | = help: consider adding the following bound: `'a: 'tcx` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-68550.stderr b/tests/ui/nll/issue-68550.stderr index 851e3628748f2..323ba7b844110 100644 --- a/tests/ui/nll/issue-68550.stderr +++ b/tests/ui/nll/issue-68550.stderr @@ -13,6 +13,6 @@ LL | let _: &'a A = &x; LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-69114-static-ty.stderr b/tests/ui/nll/issue-69114-static-ty.stderr index 9215e850f7d8f..a77ae85162187 100644 --- a/tests/ui/nll/issue-69114-static-ty.stderr +++ b/tests/ui/nll/issue-69114-static-ty.stderr @@ -12,6 +12,6 @@ LL | LL | } | - `n` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-73159-rpit-static.stderr b/tests/ui/nll/issue-73159-rpit-static.stderr index 4d3a901531614..472db30fbeb10 100644 --- a/tests/ui/nll/issue-73159-rpit-static.stderr +++ b/tests/ui/nll/issue-73159-rpit-static.stderr @@ -8,6 +8,6 @@ LL | fn make_it(&self) -> impl Iterator { LL | self.0.iter().copied() | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/nll/issue-75777.stderr b/tests/ui/nll/issue-75777.stderr index 370cd72fd558d..402c411a6380a 100644 --- a/tests/ui/nll/issue-75777.stderr +++ b/tests/ui/nll/issue-75777.stderr @@ -7,5 +7,5 @@ LL | let fut: BoxFuture<'a, A> = Box::pin(future::ready(v)); LL | Box::new(move |_| fut) | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-95272.stderr b/tests/ui/nll/issue-95272.stderr index 03edbc3a6705c..0453ef8e53ea3 100644 --- a/tests/ui/nll/issue-95272.stderr +++ b/tests/ui/nll/issue-95272.stderr @@ -13,5 +13,5 @@ LL | let f = check; = note: the function `check` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-98693.stderr b/tests/ui/nll/issue-98693.stderr index a3d87d74a8e94..b5e281538f9c6 100644 --- a/tests/ui/nll/issue-98693.stderr +++ b/tests/ui/nll/issue-98693.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | fn test() { | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/nll/loan_ends_mid_block_pair.stderr b/tests/ui/nll/loan_ends_mid_block_pair.stderr index 58e378ab02118..5f8e9d5c6ac19 100644 --- a/tests/ui/nll/loan_ends_mid_block_pair.stderr +++ b/tests/ui/nll/loan_ends_mid_block_pair.stderr @@ -10,6 +10,6 @@ LL | data.0 = 'e'; LL | capitalize(c); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/match-cfg-fake-edges2.stderr b/tests/ui/nll/match-cfg-fake-edges2.stderr index 36f2cd0b85d1c..639cba1406aef 100644 --- a/tests/ui/nll/match-cfg-fake-edges2.stderr +++ b/tests/ui/nll/match-cfg-fake-edges2.stderr @@ -10,6 +10,6 @@ LL | match y { LL | r; | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr b/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr index 55646b9dca986..56c1fce0650a7 100644 --- a/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr +++ b/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr @@ -10,6 +10,6 @@ LL | // FIXME ^ Should not error in the future with implicit dtors, only man LL | } | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr b/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr index c89f94a7894f0..e6f275a241b45 100644 --- a/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr +++ b/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr @@ -9,6 +9,6 @@ LL | x = 1; LL | } | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr b/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr index 90db13bc57849..610a0d6e9cc1e 100644 --- a/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr +++ b/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr @@ -10,6 +10,6 @@ LL | // FIXME ^ This currently errors and it should not. LL | } | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/maybe-initialized-drop.stderr b/tests/ui/nll/maybe-initialized-drop.stderr index 15a53a09af8c2..7f231c48822a5 100644 --- a/tests/ui/nll/maybe-initialized-drop.stderr +++ b/tests/ui/nll/maybe-initialized-drop.stderr @@ -8,6 +8,6 @@ LL | x = 1; LL | } | - borrow might be used here, when `wrap` is dropped and runs the `Drop` code for type `Wrap` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/mir_check_cast_closure.stderr b/tests/ui/nll/mir_check_cast_closure.stderr index 72d99aad99ee1..fcb1918914133 100644 --- a/tests/ui/nll/mir_check_cast_closure.stderr +++ b/tests/ui/nll/mir_check_cast_closure.stderr @@ -11,5 +11,5 @@ LL | g | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/mir_check_cast_reify.stderr b/tests/ui/nll/mir_check_cast_reify.stderr index 9be2670fec761..9500e474bc682 100644 --- a/tests/ui/nll/mir_check_cast_reify.stderr +++ b/tests/ui/nll/mir_check_cast_reify.stderr @@ -7,5 +7,5 @@ LL | fn bar<'a>(x: &'a u32) -> &'static u32 { LL | f(x) | ^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/mir_check_cast_unsafe_fn.stderr b/tests/ui/nll/mir_check_cast_unsafe_fn.stderr index 321d17ba6b10e..94483e94a85f9 100644 --- a/tests/ui/nll/mir_check_cast_unsafe_fn.stderr +++ b/tests/ui/nll/mir_check_cast_unsafe_fn.stderr @@ -7,5 +7,5 @@ LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { LL | unsafe { g(input) } | ^^^^^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/mir_check_cast_unsize.stderr b/tests/ui/nll/mir_check_cast_unsize.stderr index 1cd2579e4c433..84958eae5b46e 100644 --- a/tests/ui/nll/mir_check_cast_unsize.stderr +++ b/tests/ui/nll/mir_check_cast_unsize.stderr @@ -11,5 +11,5 @@ help: to declare that the trait object captures data from argument `x`, you can LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug + 'a { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index 988eee61027bc..a616d29c4fea6 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | accept(callback); | ^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a> FnOnce<(&'a (),)>` - found trait `FnOnce<(&(),)>` + = note: expected trait `for<'a> FnOnce(&'a ())` + found trait `FnOnce(&())` note: this closure does not fulfill the lifetime requirements --> $DIR/missing-universe-cause-issue-114907.rs:32:20 | @@ -46,8 +46,8 @@ error[E0308]: mismatched types LL | accept(callback); | ^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected trait `for<'a> FnOnce<(&'a (),)>` - found trait `FnOnce<(&(),)>` + = note: expected trait `for<'a> FnOnce(&'a ())` + found trait `FnOnce(&())` note: this closure does not fulfill the lifetime requirements --> $DIR/missing-universe-cause-issue-114907.rs:32:20 | diff --git a/tests/ui/nll/move-subpaths-moves-root.stderr b/tests/ui/nll/move-subpaths-moves-root.stderr index ae9287f92266f..7a7c7801643dd 100644 --- a/tests/ui/nll/move-subpaths-moves-root.stderr +++ b/tests/ui/nll/move-subpaths-moves-root.stderr @@ -8,6 +8,6 @@ LL | drop(x); | = note: partial move occurs because `x.0` has type `Vec`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/normalization-bounds-error.stderr b/tests/ui/nll/normalization-bounds-error.stderr index 0fc3670d6c523..c6f3f2fd018f7 100644 --- a/tests/ui/nll/normalization-bounds-error.stderr +++ b/tests/ui/nll/normalization-bounds-error.stderr @@ -22,6 +22,6 @@ LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} = note: expected `Visitor<'d>` found `Visitor<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr new file mode 100644 index 0000000000000..5227ca8ec17d8 --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -0,0 +1,40 @@ +error[E0597]: `a` does not live long enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 + | +LL | let b = |_| &a; + | --- -^ + | | || + | | |borrowed value does not live long enough + | | returning this value requires that `a` is borrowed for `'static` + | value captured here +... +LL | } + | - `a` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 + | +LL | fn bad &()>(_: F) {} + | ^^^ + +error: implementation of `Fn` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr new file mode 100644 index 0000000000000..5227ca8ec17d8 --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -0,0 +1,40 @@ +error[E0597]: `a` does not live long enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 + | +LL | let b = |_| &a; + | --- -^ + | | || + | | |borrowed value does not live long enough + | | returning this value requires that `a` is borrowed for `'static` + | value captured here +... +LL | } + | - `a` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 + | +LL | fn bad &()>(_: F) {} + | ^^^ + +error: implementation of `Fn` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs new file mode 100644 index 0000000000000..c165e7a1d1a53 --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs @@ -0,0 +1,20 @@ +// This is a non-regression test for issue #117146, where NLL and `-Zpolonius=next` computed +// different loan scopes when a region flowed into an SCC whose representative was an existential +// region. + +// revisions: nll polonius +// [polonius] compile-flags: -Zpolonius=next + +fn main() { + let a = (); + let b = |_| &a; + //[nll]~^ ERROR `a` does not live long enough + //[polonius]~^^ ERROR `a` does not live long enough + bad(&b); + //[nll]~^ ERROR implementation of `Fn` + //[nll]~| ERROR implementation of `FnOnce` + //[polonius]~^^^ ERROR implementation of `Fn` + //[polonius]~| ERROR implementation of `FnOnce` +} + +fn bad &()>(_: F) {} diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-liveness.rs b/tests/ui/nll/polonius/location-insensitive-scopes-liveness.rs new file mode 100644 index 0000000000000..5fabf31cecd36 --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-liveness.rs @@ -0,0 +1,46 @@ +// This is a non-regression test about differences in scopes computed by NLLs and `-Zpolonius=next` +// found during the crater run for PR #117593. +// +// Live loans were computed too early compared to some of the liveness data coming from later passes +// than `liveness::trace`, on some specific CFGs shapes: a variable was dead during tracing but its +// regions were marked live later, and live loans were not recomputed at this point. + +// check-pass +// revisions: nll polonius +// [polonius] compile-flags: -Zpolonius=next + +// minimized from wavefc-cli-3.0.0 +fn repro1() { + let a = 0; + let closure = || { + let _b = a; + }; + + let callback = if true { Some(closure) } else { None }; + do_it(callback); +} +fn do_it(_: Option) +where + F: Fn(), +{ +} + +// minimized from simple-server-0.4.0 +fn repro2() { + let mut a = &(); + let s = S(&mut a); + let _ = if true { Some(s) } else { None }; +} +struct S<'a>(&'a mut &'a ()); + +// minimized from https://github.com/SHaaD94/AICup2022 +fn repro3() { + let runner = (); + let writer = debug_interface(&runner); + let _ = if true { Some(writer) } else { None }; +} +fn debug_interface(_: &()) -> &mut dyn std::io::Write { + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/nll/polonius/subset-relations.stderr b/tests/ui/nll/polonius/subset-relations.stderr index 6df5563eabbc3..9deca6449a8f1 100644 --- a/tests/ui/nll/polonius/subset-relations.stderr +++ b/tests/ui/nll/polonius/subset-relations.stderr @@ -10,5 +10,5 @@ LL | y | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/promoted-bounds.stderr b/tests/ui/nll/promoted-bounds.stderr index d111256b8454f..73fda380522fb 100644 --- a/tests/ui/nll/promoted-bounds.stderr +++ b/tests/ui/nll/promoted-bounds.stderr @@ -11,6 +11,6 @@ LL | let b = &l; LL | }; | - `l` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/promoted-closure-pair.stderr b/tests/ui/nll/promoted-closure-pair.stderr index 000bdf85804d8..ee00b7ba51f08 100644 --- a/tests/ui/nll/promoted-closure-pair.stderr +++ b/tests/ui/nll/promoted-closure-pair.stderr @@ -7,6 +7,6 @@ LL | p.1(&z) | | `z` is borrowed here | returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/reference-carried-through-struct-field.stderr b/tests/ui/nll/reference-carried-through-struct-field.stderr index 5672b9cd7e9cc..b26f73fc70abc 100644 --- a/tests/ui/nll/reference-carried-through-struct-field.stderr +++ b/tests/ui/nll/reference-carried-through-struct-field.stderr @@ -8,6 +8,6 @@ LL | x += 1; LL | *wrapper.w += 1; | --------------- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/nll/region-ends-after-if-condition.stderr b/tests/ui/nll/region-ends-after-if-condition.stderr index c03e385790616..b7c37caa20f8d 100644 --- a/tests/ui/nll/region-ends-after-if-condition.stderr +++ b/tests/ui/nll/region-ends-after-if-condition.stderr @@ -10,6 +10,6 @@ LL | my_struct.field.push_str("Hello, world!"); LL | drop(value); | ----- immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/relate_tys/fn-subtype.stderr b/tests/ui/nll/relate_tys/fn-subtype.stderr index 21073647ea77b..0e3ab41da8716 100644 --- a/tests/ui/nll/relate_tys/fn-subtype.stderr +++ b/tests/ui/nll/relate_tys/fn-subtype.stderr @@ -7,6 +7,6 @@ LL | let y: for<'a> fn(&'a ()) = x; = note: expected fn pointer `for<'a> fn(&'a ())` found fn pointer `fn(&())` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/relate_tys/opaque-hrtb.stderr b/tests/ui/nll/relate_tys/opaque-hrtb.stderr index d75ec2b57d4a5..d48745d2d2818 100644 --- a/tests/ui/nll/relate_tys/opaque-hrtb.stderr +++ b/tests/ui/nll/relate_tys/opaque-hrtb.stderr @@ -7,5 +7,5 @@ LL | bar() = note: `impl MyTrait<&'2 str>` must implement `MyTrait<&'1 str>`, for any lifetime `'1`... = note: ...but it actually implements `MyTrait<&'2 str>`, for some specific lifetime `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/relate_tys/trait-hrtb.stderr b/tests/ui/nll/relate_tys/trait-hrtb.stderr index aa1927711b36b..7f7b94c0b3018 100644 --- a/tests/ui/nll/relate_tys/trait-hrtb.stderr +++ b/tests/ui/nll/relate_tys/trait-hrtb.stderr @@ -7,6 +7,6 @@ LL | let y: Box Foo<'a>> = x; = note: expected trait object `dyn for<'a> Foo<'a>` found trait object `dyn Foo<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/relate_tys/universe-violation.stderr b/tests/ui/nll/relate_tys/universe-violation.stderr index fe801b42c0a49..b585eee0769db 100644 --- a/tests/ui/nll/relate_tys/universe-violation.stderr +++ b/tests/ui/nll/relate_tys/universe-violation.stderr @@ -7,6 +7,6 @@ LL | let b: fn(&u32) -> &u32 = a; = note: expected fn pointer `for<'a> fn(&'a u32) -> &'a u32` found fn pointer `fn(&u32) -> &u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/relate_tys/var-appears-twice.stderr b/tests/ui/nll/relate_tys/var-appears-twice.stderr index ff6ea598ff46f..3f9a6cec0d2e5 100644 --- a/tests/ui/nll/relate_tys/var-appears-twice.stderr +++ b/tests/ui/nll/relate_tys/var-appears-twice.stderr @@ -12,6 +12,6 @@ LL | let x: DoubleCell<_> = make_cell(&b); LL | } | - `b` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/return-ref-mut-issue-46557.stderr b/tests/ui/nll/return-ref-mut-issue-46557.stderr index 720440a0ae5f8..358830fd51611 100644 --- a/tests/ui/nll/return-ref-mut-issue-46557.stderr +++ b/tests/ui/nll/return-ref-mut-issue-46557.stderr @@ -6,6 +6,6 @@ LL | let ref mut x = 1234543; LL | x | ^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/return_from_loop.stderr b/tests/ui/nll/return_from_loop.stderr index efd56ea2dd542..9fe681680c6c6 100644 --- a/tests/ui/nll/return_from_loop.stderr +++ b/tests/ui/nll/return_from_loop.stderr @@ -10,6 +10,6 @@ LL | LL | value.len(); | ----- first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/snocat-regression.stderr b/tests/ui/nll/snocat-regression.stderr index 0868984734d7b..135b69515373b 100644 --- a/tests/ui/nll/snocat-regression.stderr +++ b/tests/ui/nll/snocat-regression.stderr @@ -10,5 +10,5 @@ LL | | let _x = link; LL | | }; | |_____^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/trait-associated-constant.stderr b/tests/ui/nll/trait-associated-constant.stderr index cf1c52ba7cc43..f6277508eebf5 100644 --- a/tests/ui/nll/trait-associated-constant.stderr +++ b/tests/ui/nll/trait-associated-constant.stderr @@ -17,6 +17,6 @@ note: ...does not necessarily outlive the lifetime `'b` as defined here LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index ba885d1b97ebd..693c5b8b0a3b0 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,18 +1,18 @@ -error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a)])` captures lifetime that does not appear in bounds +error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyParam(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyParam(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a)])` captures lifetime that does not appear in bounds --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { | -- ------------ opaque type defined here | | - | hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here + | hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here LL | x | ^ | -help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:14 ~ impl_trait_captures[aeb9]::foo::{opaque#0}::'a), 2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound +help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyParam(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyParam(DefId(0:14 ~ impl_trait_captures[aeb9]::foo::{opaque#0}::'a), 2, 'a)])` captures `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound | -LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) { - | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) { + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr b/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr index 6de023ffdd416..2aab03ee7b76e 100644 --- a/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr +++ b/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | fn generic2(value: T) { | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr index 1fa74f67ccd71..f8ecc0c68267f 100644 --- a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr @@ -9,6 +9,6 @@ LL | bar::() | = help: consider adding an explicit lifetime bound `>::Output: 'a`... -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr index c8dbe4ebc6d94..13ad665e2615e 100644 --- a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr @@ -9,6 +9,6 @@ LL | bar::<>::Output>() | = help: consider adding an explicit lifetime bound `>::Output: 'a`... -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr index f78708dc48d94..b4136be36d315 100644 --- a/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr +++ b/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | T: MyTrait<'a> + 'a, | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 59e29e9a420fe..acbcb9f0b70aa 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), + for extern "rust-call" fn((std::option::Option>, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: number of external vids: 2 @@ -28,7 +28,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), + for extern "rust-call" fn((std::option::Option>, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: late-bound region is '?2 @@ -56,6 +56,6 @@ help: consider adding an explicit lifetime bound LL | fn generic_fail<'a, T: 'a>(cell: Cell<&'a ()>, value: T) { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr b/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr index 73f01ff1519a4..c884909c942e4 100644 --- a/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr @@ -11,6 +11,6 @@ help: consider adding an explicit lifetime bound LL | fn region_static<'a, T: 'a>(cell: Cell<&'a usize>, t: T) { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/unused-mut-issue-50343.stderr b/tests/ui/nll/unused-mut-issue-50343.stderr index cb02d76205c7f..582ca17cccc53 100644 --- a/tests/ui/nll/unused-mut-issue-50343.stderr +++ b/tests/ui/nll/unused-mut-issue-50343.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(unused_mut)] | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/ascribed-type-wf.stderr b/tests/ui/nll/user-annotations/ascribed-type-wf.stderr index 91e7c6b8ecf1f..2bd00a51fe23e 100644 --- a/tests/ui/nll/user-annotations/ascribed-type-wf.stderr +++ b/tests/ui/nll/user-annotations/ascribed-type-wf.stderr @@ -6,5 +6,5 @@ LL | fn extend<'a>() { LL | None::<<&'a () as Trait>::Ty>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/cast_static_lifetime.stderr b/tests/ui/nll/user-annotations/cast_static_lifetime.stderr index 3b9363c41f20f..35eec233ed5c0 100644 --- a/tests/ui/nll/user-annotations/cast_static_lifetime.stderr +++ b/tests/ui/nll/user-annotations/cast_static_lifetime.stderr @@ -11,6 +11,6 @@ LL | let y: &u32 = (&x) as &'static u32; LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr index c39301588acfa..cf699a3e476cf 100644 --- a/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr +++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr @@ -6,5 +6,5 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 { LL | >::C | ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr index 541a2cfaf299a..ee06ac7407af1 100644 --- a/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr +++ b/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr @@ -6,5 +6,5 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 { LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr index ea0fcb6d634cd..02b17a3856a74 100644 --- a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr @@ -6,5 +6,5 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 { LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr index ff549f1d88bd4..06e4848e71ced 100644 --- a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr @@ -6,5 +6,5 @@ LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { LL | >::C | ^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr index 7f160d8e398b9..754e09fe326aa 100644 --- a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr @@ -6,5 +6,5 @@ LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { LL | T::C | ^^^^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr index 7809b2470fedc..0cabc02c6b5db 100644 --- a/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr +++ b/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr @@ -4,5 +4,5 @@ error: user args: UserArgs { args: [&ReStatic u32], user_self_ty: None } LL | SomeStruct::<&'static u32> { t: &22 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/inherent-associated-constants.stderr b/tests/ui/nll/user-annotations/inherent-associated-constants.stderr index ffbfc40f5372e..c1030152814ce 100644 --- a/tests/ui/nll/user-annotations/inherent-associated-constants.stderr +++ b/tests/ui/nll/user-annotations/inherent-associated-constants.stderr @@ -6,5 +6,5 @@ LL | fn non_wf_associated_const<'a>(x: i32) { LL | A::<'a>::IC; | ^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr index fb26b8d09e179..2d2397456c94f 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr @@ -14,6 +14,6 @@ LL | LL | } | - `v` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr index 69dd1d1aaae28..99d57902d6a88 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr @@ -14,6 +14,6 @@ LL | LL | } | - `v` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/promoted-annotation.stderr b/tests/ui/nll/user-annotations/promoted-annotation.stderr index 132a00ba41581..ca99e53187091 100644 --- a/tests/ui/nll/user-annotations/promoted-annotation.stderr +++ b/tests/ui/nll/user-annotations/promoted-annotation.stderr @@ -13,6 +13,6 @@ LL | LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr index 766877f8835c4..3e2706309b342 100644 --- a/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr +++ b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr @@ -11,6 +11,6 @@ LL | let y: &u32 = type_ascribe!(&x, &'static u32); LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/wf-self-type.stderr b/tests/ui/nll/user-annotations/wf-self-type.stderr index 1d3ae7cfbd74a..dfc5410b74468 100644 --- a/tests/ui/nll/user-annotations/wf-self-type.stderr +++ b/tests/ui/nll/user-annotations/wf-self-type.stderr @@ -10,5 +10,5 @@ LL | Foo::xmute(u) | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/where_clauses_in_functions.stderr b/tests/ui/nll/where_clauses_in_functions.stderr index afb25e3bc69a3..41d7e6237b4cf 100644 --- a/tests/ui/nll/where_clauses_in_functions.stderr +++ b/tests/ui/nll/where_clauses_in_functions.stderr @@ -10,5 +10,5 @@ LL | foo(x, y) | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/nll/where_clauses_in_structs.stderr b/tests/ui/nll/where_clauses_in_structs.stderr index c46cfcb41341f..4cc7e5ab1b4c7 100644 --- a/tests/ui/nll/where_clauses_in_structs.stderr +++ b/tests/ui/nll/where_clauses_in_structs.stderr @@ -13,5 +13,5 @@ LL | Foo { x, y }; = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/no-capture-arc.stderr b/tests/ui/no-capture-arc.stderr index 296e1fb3f26fe..38432c851c522 100644 --- a/tests/ui/no-capture-arc.stderr +++ b/tests/ui/no-capture-arc.stderr @@ -14,6 +14,6 @@ LL | assert_eq!((*arc_v)[2], 3); | = note: borrow occurs due to deref coercion to `Vec` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/no-link-unknown-crate.stderr b/tests/ui/no-link-unknown-crate.stderr index 068c7139ed9e2..edc248db09eac 100644 --- a/tests/ui/no-link-unknown-crate.stderr +++ b/tests/ui/no-link-unknown-crate.stderr @@ -4,6 +4,6 @@ error[E0463]: can't find crate for `doesnt_exist` LL | extern crate doesnt_exist; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/no-reuse-move-arc.stderr b/tests/ui/no-reuse-move-arc.stderr index bcd481c33f361..cdeb6eadc174f 100644 --- a/tests/ui/no-reuse-move-arc.stderr +++ b/tests/ui/no-reuse-move-arc.stderr @@ -14,6 +14,6 @@ LL | assert_eq!((*arc_v)[2], 3); | = note: borrow occurs due to deref coercion to `Vec` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/no-send-res-ports.stderr b/tests/ui/no-send-res-ports.stderr index 33446e9d16247..9c30261e5cb73 100644 --- a/tests/ui/no-send-res-ports.stderr +++ b/tests/ui/no-send-res-ports.stderr @@ -32,6 +32,6 @@ LL | thread::spawn(move|| { note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/no_crate_type.stderr b/tests/ui/no_crate_type.stderr index 93da7c3e0ddd6..85d8f87afa673 100644 --- a/tests/ui/no_crate_type.stderr +++ b/tests/ui/no_crate_type.stderr @@ -4,5 +4,5 @@ error: malformed `crate_type` attribute input LL | #![crate_type] | ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/no_send-enum.stderr b/tests/ui/no_send-enum.stderr index b5a14b551dc2d..3b66c7db545e1 100644 --- a/tests/ui/no_send-enum.stderr +++ b/tests/ui/no_send-enum.stderr @@ -18,6 +18,6 @@ note: required by a bound in `bar` LL | fn bar(_: T) {} | ^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/no_send-rc.stderr b/tests/ui/no_send-rc.stderr index ce25da559da3f..3534167870baf 100644 --- a/tests/ui/no_send-rc.stderr +++ b/tests/ui/no_send-rc.stderr @@ -13,6 +13,6 @@ note: required by a bound in `bar` LL | fn bar(_: T) {} | ^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/no_share-enum.stderr b/tests/ui/no_share-enum.stderr index 5b453e0da3bbd..89939216d5b16 100644 --- a/tests/ui/no_share-enum.stderr +++ b/tests/ui/no_share-enum.stderr @@ -18,6 +18,6 @@ note: required by a bound in `bar` LL | fn bar(_: T) {} | ^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/no_share-struct.stderr b/tests/ui/no_share-struct.stderr index 9ce3a318f1d3b..9c7a921b8d8ba 100644 --- a/tests/ui/no_share-struct.stderr +++ b/tests/ui/no_share-struct.stderr @@ -13,6 +13,6 @@ note: required by a bound in `bar` LL | fn bar(_: T) {} | ^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/noexporttypeexe.stderr b/tests/ui/noexporttypeexe.stderr index bf88ceaa5d2a8..59759b696c7a2 100644 --- a/tests/ui/noexporttypeexe.stderr +++ b/tests/ui/noexporttypeexe.stderr @@ -13,6 +13,6 @@ help: consider using `Option::expect` to unwrap the `Option` value, panic LL | let x: isize = noexporttypelib::foo().expect("REASON"); | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/non-constant-expr-for-arr-len.stderr b/tests/ui/non-constant-expr-for-arr-len.stderr index d684b8eaabdfe..c9f977fbaa409 100644 --- a/tests/ui/non-constant-expr-for-arr-len.stderr +++ b/tests/ui/non-constant-expr-for-arr-len.stderr @@ -6,6 +6,6 @@ LL | fn bar(n: usize) { LL | let _x = [0; n]; | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/non-copyable-void.stderr b/tests/ui/non-copyable-void.stderr index 99af04e7cd97e..bef1e1077ebb4 100644 --- a/tests/ui/non-copyable-void.stderr +++ b/tests/ui/non-copyable-void.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `clone` found for enum `c_void` in the current sco LL | let _z = (*y).clone(); | ^^^^^ method not found in `c_void` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/noncopyable-class.stderr b/tests/ui/noncopyable-class.stderr index 0c696163a26c5..b8f7276c898f8 100644 --- a/tests/ui/noncopyable-class.stderr +++ b/tests/ui/noncopyable-class.stderr @@ -11,6 +11,6 @@ LL | let _y = x.clone(); = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `Clone` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/nonscalar-cast.stderr b/tests/ui/nonscalar-cast.stderr index 2a7037121876d..01b4a9a7ce026 100644 --- a/tests/ui/nonscalar-cast.stderr +++ b/tests/ui/nonscalar-cast.stderr @@ -6,6 +6,6 @@ LL | println!("{}", Foo { x: 1 } as isize); | = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/not-clone-closure.stderr b/tests/ui/not-clone-closure.stderr index 17cf938d170b0..783c165eeb21c 100644 --- a/tests/ui/not-clone-closure.stderr +++ b/tests/ui/not-clone-closure.stderr @@ -18,6 +18,6 @@ LL + #[derive(Clone)] LL | struct S(i32); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not-copy-closure.stderr b/tests/ui/not-copy-closure.stderr index 93e011ccec4fa..50e25a24d811f 100644 --- a/tests/ui/not-copy-closure.stderr +++ b/tests/ui/not-copy-closure.stderr @@ -16,6 +16,6 @@ help: consider mutably borrowing `hello` LL | let b = &mut hello; | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/not-panic/not-panic-safe-5.stderr b/tests/ui/not-panic/not-panic-safe-5.stderr index cb78370b48a6c..fbbd81d6d4c53 100644 --- a/tests/ui/not-panic/not-panic-safe-5.stderr +++ b/tests/ui/not-panic/not-panic-safe-5.stderr @@ -12,6 +12,6 @@ note: required by a bound in `assert` LL | fn assert() {} | ^^^^^^^^^^ required by this bound in `assert` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not-panic/not-panic-safe.stderr b/tests/ui/not-panic/not-panic-safe.stderr index 37a6aee390669..cd792eff92664 100644 --- a/tests/ui/not-panic/not-panic-safe.stderr +++ b/tests/ui/not-panic/not-panic-safe.stderr @@ -17,6 +17,6 @@ LL - assert::<&mut &mut &i32>(); LL + assert::<&i32>(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/numbers-arithmetic/issue-105626.rs b/tests/ui/numbers-arithmetic/issue-105626.rs index f97edd510c9e6..5466f8e18d472 100644 --- a/tests/ui/numbers-arithmetic/issue-105626.rs +++ b/tests/ui/numbers-arithmetic/issue-105626.rs @@ -1,6 +1,5 @@ // run-pass // only-x86 -// min-system-llvm-version: 16 // compile-flags: -Ctarget-feature=+sse2 use std::hint::black_box; diff --git a/tests/ui/numbers-arithmetic/location-add-assign-overflow.rs b/tests/ui/numbers-arithmetic/location-add-assign-overflow.rs new file mode 100644 index 0000000000000..2c4bdad3e919f --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-add-assign-overflow.rs @@ -0,0 +1,8 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-add-assign-overflow.rs + +fn main() { + let mut a: u8 = 255; + a += &1; +} diff --git a/tests/ui/numbers-arithmetic/location-add-overflow.rs b/tests/ui/numbers-arithmetic/location-add-overflow.rs new file mode 100644 index 0000000000000..085623c9bf764 --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-add-overflow.rs @@ -0,0 +1,7 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-add-overflow.rs + +fn main() { + let _: u8 = 255 + &1; +} diff --git a/tests/ui/numbers-arithmetic/location-divide-assign-by-zero.rs b/tests/ui/numbers-arithmetic/location-divide-assign-by-zero.rs new file mode 100644 index 0000000000000..21b5e7a8110bf --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-divide-assign-by-zero.rs @@ -0,0 +1,8 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-divide-assign-by-zero.rs + +fn main() { + let mut a = 1; + a /= &0; +} diff --git a/tests/ui/numbers-arithmetic/location-divide-by-zero.rs b/tests/ui/numbers-arithmetic/location-divide-by-zero.rs new file mode 100644 index 0000000000000..7d045fc560270 --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-divide-by-zero.rs @@ -0,0 +1,9 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-divide-by-zero.rs + +// https://github.com/rust-lang/rust/issues/114814 + +fn main() { + let _ = 1 / &0; +} diff --git a/tests/ui/numbers-arithmetic/location-mod-assign-by-zero.rs b/tests/ui/numbers-arithmetic/location-mod-assign-by-zero.rs new file mode 100644 index 0000000000000..88d602e4b6d97 --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-mod-assign-by-zero.rs @@ -0,0 +1,8 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-mod-assign-by-zero.rs + +fn main() { + let mut a = 1; + a %= &0; +} diff --git a/tests/ui/numbers-arithmetic/location-mod-by-zero.rs b/tests/ui/numbers-arithmetic/location-mod-by-zero.rs new file mode 100644 index 0000000000000..4397adb75d1f0 --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-mod-by-zero.rs @@ -0,0 +1,7 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-mod-by-zero.rs + +fn main() { + let _ = 1 % &0; +} diff --git a/tests/ui/numbers-arithmetic/location-mul-assign-overflow.rs b/tests/ui/numbers-arithmetic/location-mul-assign-overflow.rs new file mode 100644 index 0000000000000..b042751ded9a2 --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-mul-assign-overflow.rs @@ -0,0 +1,8 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-mul-assign-overflow.rs + +fn main() { + let mut a: u8 = 255; + a *= &2; +} diff --git a/tests/ui/numbers-arithmetic/location-mul-overflow.rs b/tests/ui/numbers-arithmetic/location-mul-overflow.rs new file mode 100644 index 0000000000000..6dd58874874b3 --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-mul-overflow.rs @@ -0,0 +1,7 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-mul-overflow.rs + +fn main() { + let _: u8 = 255 * &2; +} diff --git a/tests/ui/numbers-arithmetic/location-sub-assign-overflow.rs b/tests/ui/numbers-arithmetic/location-sub-assign-overflow.rs new file mode 100644 index 0000000000000..5b92ada2e0b0d --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-sub-assign-overflow.rs @@ -0,0 +1,8 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-sub-assign-overflow.rs + +fn main() { + let mut a: u8 = 0; + a -= &1; +} diff --git a/tests/ui/numbers-arithmetic/location-sub-overflow.rs b/tests/ui/numbers-arithmetic/location-sub-overflow.rs new file mode 100644 index 0000000000000..2d77cb8f55ea4 --- /dev/null +++ b/tests/ui/numbers-arithmetic/location-sub-overflow.rs @@ -0,0 +1,7 @@ +// run-fail +// ignore-wasm32 +// error-pattern:location-sub-overflow.rs + +fn main() { + let _: u8 = 0 - &1; +} diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr index 434c9d5b43daf..5d2c4a6c8e270 100644 --- a/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr index c3b44e5a04375..8ac72aefe0dc0 100644 --- a/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr index 9d6479bd7c7c6..43d541b030433 100644 --- a/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr index 2bb5b6a6d6e09..00a3581069f5b 100644 --- a/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr index b2b3114d1b4cf..62763e9e1df8b 100644 --- a/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr index ad18c3bb7f459..519e62fef7d89 100644 --- a/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr index 37d02e09dec34..de24ea1fcde93 100644 --- a/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr index 692602c07198b..47588012fb692 100644 --- a/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr index e3b5859df90fa..e9a1572d3cc9d 100644 --- a/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr index a3475c04c28cd..005f7378226c1 100644 --- a/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(arithmetic_overflow)] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr new file mode 100644 index 0000000000000..475b41388d3b4 --- /dev/null +++ b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.stderr @@ -0,0 +1,6 @@ +warning: unstable feature specified for `-Ctarget-feature`: `nontrapping-fptoint` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 1 warning emitted + diff --git a/tests/ui/numeric/len.stderr b/tests/ui/numeric/len.stderr index 55a61b5e44379..7b20d35c876d2 100644 --- a/tests/ui/numeric/len.stderr +++ b/tests/ui/numeric/len.stderr @@ -16,6 +16,6 @@ help: you can convert a `usize` to a `u32` and panic if the converted value does LL | test(array.len().try_into().unwrap()); | ++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr index f06a9da1deea5..8d44b4de55a47 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr @@ -4,6 +4,6 @@ error[E0228]: the lifetime bound for this object type cannot be deduced from con LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr index 51d8450af768b..0846dd60723a4 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr @@ -4,6 +4,6 @@ error[E0228]: the lifetime bound for this object type cannot be deduced from con LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr index f721bf39419b5..688f8af0822b4 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr @@ -4,6 +4,6 @@ error[E0228]: the lifetime bound for this object type cannot be deduced from con LL | fn bar(x: &str) -> &dyn Foo { &() } | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index 61e96f59fed91..b59956879275a 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -11,5 +11,5 @@ LL | ss | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr index 7d6f9f39d13ed..b49e506a14d1a 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr @@ -6,5 +6,5 @@ LL | fn c<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { LL | ss.t = t; | ^^^^^^^^ assignment requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr index 2bc8e097859d3..9e2422fdc77c1 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr @@ -6,5 +6,5 @@ LL | fn c<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { LL | ss.t = t; | ^^^^^^^^ assignment requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr index 110e715073371..cd2aa9fdbe3e4 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr @@ -15,6 +15,6 @@ help: consider relaxing the implicit `Sized` restriction LL | type Item: ?Sized; | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/object-safety/issue-102762.stderr b/tests/ui/object-safety/issue-102762.stderr index 5041ebe776051..2215ec677c57a 100644 --- a/tests/ui/object-safety/issue-102762.stderr +++ b/tests/ui/object-safety/issue-102762.stderr @@ -15,6 +15,6 @@ LL | pub trait Fetcher: Send + Sync { LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr b/tests/ui/object-safety/object-safety-associated-consts.curr.stderr index 5f94c9284ea66..462d3d95f13ee 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr +++ b/tests/ui/object-safety/object-safety-associated-consts.curr.stderr @@ -13,6 +13,6 @@ LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr index db3e0885a85a8..d0c78f9cd699e 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr @@ -14,6 +14,6 @@ LL | const X: usize; = help: consider moving `X` to another trait = note: required for the cast from `&T` to `&dyn Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-bounds.stderr b/tests/ui/object-safety/object-safety-bounds.stderr index 29ffb5448427d..bf3c055f4e3fd 100644 --- a/tests/ui/object-safety/object-safety-bounds.stderr +++ b/tests/ui/object-safety/object-safety-bounds.stderr @@ -12,6 +12,6 @@ LL | trait X { LL | type U: PartialEq; | ^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-by-value-self-use.stderr b/tests/ui/object-safety/object-safety-by-value-self-use.stderr index 17f4cb4d4a88c..1701f6059a8ee 100644 --- a/tests/ui/object-safety/object-safety-by-value-self-use.stderr +++ b/tests/ui/object-safety/object-safety-by-value-self-use.stderr @@ -4,6 +4,6 @@ error[E0161]: cannot move a value of type `dyn Bar` LL | t.bar() | ^ the size of `dyn Bar` cannot be statically determined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0161`. diff --git a/tests/ui/object-safety/object-safety-issue-22040.stderr b/tests/ui/object-safety/object-safety-issue-22040.stderr index 2e59d88bdaf92..c9c1437a26192 100644 --- a/tests/ui/object-safety/object-safety-issue-22040.stderr +++ b/tests/ui/object-safety/object-safety-issue-22040.stderr @@ -13,6 +13,6 @@ LL | trait Expr: Debug + PartialEq { | this trait cannot be made into an object... = help: only type `SExpr<'x>` implements the trait, consider using it directly instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-no-static.curr.stderr b/tests/ui/object-safety/object-safety-no-static.curr.stderr index b40470b457b3b..c9e076c65779c 100644 --- a/tests/ui/object-safety/object-safety-no-static.curr.stderr +++ b/tests/ui/object-safety/object-safety-no-static.curr.stderr @@ -21,6 +21,6 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() where Self: Sized {} | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr index 1eae9a9b9daf5..e155a350f8947 100644 --- a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr @@ -22,6 +22,6 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() where Self: Sized {} | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized-2.curr.stderr b/tests/ui/object-safety/object-safety-sized-2.curr.stderr index b019264128e76..7b91c4d665cfe 100644 --- a/tests/ui/object-safety/object-safety-sized-2.curr.stderr +++ b/tests/ui/object-safety/object-safety-sized-2.curr.stderr @@ -12,6 +12,6 @@ LL | trait Bar LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr index 90e5c59dd027c..69af9bfe92b9f 100644 --- a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr @@ -13,6 +13,6 @@ LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` = note: required for the cast from `&T` to `&dyn Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized.curr.stderr b/tests/ui/object-safety/object-safety-sized.curr.stderr index 97481312142fb..66b5239745b6d 100644 --- a/tests/ui/object-safety/object-safety-sized.curr.stderr +++ b/tests/ui/object-safety/object-safety-sized.curr.stderr @@ -12,6 +12,6 @@ LL | trait Bar : Sized { | | | this trait cannot be made into an object... -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr index a6c22b8747e50..1d0ffcffd0459 100644 --- a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr +++ b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr @@ -13,6 +13,6 @@ LL | trait Bar : Sized { | this trait cannot be made into an object... = note: required for the cast from `&T` to `&dyn Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr index a106ab995b0a5..08df069275a60 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr @@ -12,6 +12,6 @@ LL | trait Baz : Bar { | | | this trait cannot be made into an object... -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr index b68c3fa5bcc9c..7b6fb9fafa202 100644 --- a/tests/ui/occurs-check-2.stderr +++ b/tests/ui/occurs-check-2.stderr @@ -9,6 +9,6 @@ help: consider unboxing the value LL | f = *Box::new(g); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr index 04c404d543a95..675133b6d50bd 100644 --- a/tests/ui/occurs-check-3.stderr +++ b/tests/ui/occurs-check-3.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | fn main() { let c; c = Clam::A(c); match c { Clam::A::(_) => { } } } | ^^^^^^^^^^ cyclic type of infinite size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr index fdbbdc3abb377..1cb6b32cb2336 100644 --- a/tests/ui/occurs-check.stderr +++ b/tests/ui/occurs-check.stderr @@ -9,6 +9,6 @@ help: consider unboxing the value LL | f = *Box::new(f); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs index e8b5a08377bdd..a2d6aace47da1 100644 --- a/tests/ui/offset-of/offset-of-enum.rs +++ b/tests/ui/offset-of/offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-inference.stderr b/tests/ui/offset-of/offset-of-inference.stderr index 2a520f6f90694..1845822f11db1 100644 --- a/tests/ui/offset-of/offset-of-inference.stderr +++ b/tests/ui/offset-of/offset-of-inference.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | let _ = core::mem::offset_of!(Foo<_>, x); | ^^^^^^ cannot infer type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs index 6fa30d63fb869..b7affdb794395 100644 --- a/tests/ui/offset-of/offset-of-private.rs +++ b/tests/ui/offset-of/offset-of-private.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr index df555463f9884..2dc17189a702e 100644 --- a/tests/ui/offset-of/offset-of-self.stderr +++ b/tests/ui/offset-of/offset-of-self.stderr @@ -54,6 +54,8 @@ error[E0609]: no field `Self` on type `S` | LL | offset_of!(S, Self); | ^^^^ + | + = note: available fields are: `v`, `w` error[E0616]: field `v` of struct `T` is private --> $DIR/offset-of-self.rs:41:30 @@ -66,6 +68,8 @@ error[E0609]: no field `self` on type `S` | LL | offset_of!(S, self); | ^^^^ + | + = note: available fields are: `v`, `w` error[E0609]: no field `self` on type `u8` --> $DIR/offset-of-self.rs:56:21 diff --git a/tests/ui/on-unimplemented/expected-comma-found-token.stderr b/tests/ui/on-unimplemented/expected-comma-found-token.stderr index 048b72ee3bcdf..7c0874e36a6a9 100644 --- a/tests/ui/on-unimplemented/expected-comma-found-token.stderr +++ b/tests/ui/on-unimplemented/expected-comma-found-token.stderr @@ -6,5 +6,5 @@ LL | message="the message" LL | label="the label" | ^^^^^ unexpected token -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr index a4b33963fb0b9..45ef22f4421f0 100644 --- a/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr +++ b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr @@ -6,6 +6,6 @@ LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr index 36d80f3e681bb..e2ba2474d6c6e 100644 --- a/tests/ui/on-unimplemented/impl-substs.stderr +++ b/tests/ui/on-unimplemented/impl-substs.stderr @@ -10,6 +10,6 @@ LL | Foo::::foo((1i32, 1i32, 1i32)); = help: the trait `Foo` is implemented for `(i32, i32, i32)` = help: for that trait implementation, expected `i32`, found `usize` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/issue-104140.stderr b/tests/ui/on-unimplemented/issue-104140.stderr index ddb1f50f0bb45..4ba5475d9ecaf 100644 --- a/tests/ui/on-unimplemented/issue-104140.stderr +++ b/tests/ui/on-unimplemented/issue-104140.stderr @@ -11,5 +11,5 @@ LL | #[rustc_on_unimplemented = "message"] LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")] | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/once-cant-call-twice-on-heap.stderr b/tests/ui/once-cant-call-twice-on-heap.stderr index 335ac63382260..33dd840dbc2b9 100644 --- a/tests/ui/once-cant-call-twice-on-heap.stderr +++ b/tests/ui/once-cant-call-twice-on-heap.stderr @@ -18,6 +18,6 @@ help: consider further restricting this bound LL | fn foo(blk: F) { | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/operator-recovery/less-than-greater-than.stderr b/tests/ui/operator-recovery/less-than-greater-than.stderr index 80c921535bd08..21b2e77db9aa5 100644 --- a/tests/ui/operator-recovery/less-than-greater-than.stderr +++ b/tests/ui/operator-recovery/less-than-greater-than.stderr @@ -4,5 +4,5 @@ error: invalid comparison operator `<>` LL | println!("{}", 1 <> 2); | ^^ help: `<>` is not a valid comparison operator, use `!=` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/operator-recovery/spaceship.stderr b/tests/ui/operator-recovery/spaceship.stderr index ed6bd74c9b92e..46a81db62b42c 100644 --- a/tests/ui/operator-recovery/spaceship.stderr +++ b/tests/ui/operator-recovery/spaceship.stderr @@ -4,5 +4,5 @@ error: invalid comparison operator `<=>` LL | println!("{}", 1 <=> 2); | ^^^ `<=>` is not a valid comparison operator, use `std::cmp::Ordering` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/or-patterns/exhaustiveness-pass.rs b/tests/ui/or-patterns/exhaustiveness-pass.rs index 428b9a19fe69b..a52e08c507d8a 100644 --- a/tests/ui/or-patterns/exhaustiveness-pass.rs +++ b/tests/ui/or-patterns/exhaustiveness-pass.rs @@ -35,6 +35,17 @@ fn main() { ((0, 0) | (1, 0),) => {} _ => {} } + match ((0, 0),) { + // Note how the second one would be redundant without the guard. + ((x, y) | (y, x),) if x == 0 => {} + _ => {} + } + match 0 { + // We don't warn the second one as redundant in general because of cases like the one above. + // We could technically do it if there are no bindings. + 0 | 0 if 0 == 0 => {} + _ => {} + } // This one caused ICE https://github.com/rust-lang/rust/issues/117378 match (0u8, 0) { diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs index 8429799cabf15..20a8d7549961f 100644 --- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs @@ -1,6 +1,7 @@ #![deny(unreachable_patterns)] // We wrap patterns in a tuple because top-level or-patterns were special-cased. +#[rustfmt::skip] fn main() { match (0u8,) { (1 | 2,) => {} @@ -73,6 +74,11 @@ fn main() { | 0] => {} //~ ERROR unreachable _ => {} } + match (true, 0) { + (true, 0 | 0) => {} //~ ERROR unreachable + (_, 0 | 0) => {} //~ ERROR unreachable + _ => {} + } match &[][..] { [0] => {} [0, _] => {} @@ -149,4 +155,8 @@ fn main() { | true, //~ ERROR unreachable false | true) => {} } + match (true, true) { + (x, y) + | (y, x) => {} //~ ERROR unreachable + } } diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr index 3f7d47dcb8ceb..3616dda99812f 100644 --- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:7:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:8:9 | LL | (1,) => {} | ^^^^ @@ -11,128 +11,140 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:12:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:13:9 | LL | (2,) => {} | ^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:18:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:19:9 | LL | (1 | 2,) => {} | ^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:23:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9 | LL | (1, 3) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9 | LL | (1, 4) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9 | LL | (2, 4) => {} | ^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:27:9 | LL | (2 | 1, 4) => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:28:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:29:9 | LL | (1, 4 | 5) => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:36:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9 | LL | (Some(1),) => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:38:9 | LL | (None,) => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:42:9 + --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9 | LL | ((1..=4,),) => {} | ^^^^^^^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:47:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:48:14 | LL | (1 | 1,) => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:51:19 + --> $DIR/exhaustiveness-unreachable-pattern.rs:52:19 | LL | (0 | 1) | 1 => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:57:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:58:14 | LL | 0 | (0 | 0) => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:57:18 + --> $DIR/exhaustiveness-unreachable-pattern.rs:58:18 | LL | 0 | (0 | 0) => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:65:13 + --> $DIR/exhaustiveness-unreachable-pattern.rs:66:13 | LL | / Some( LL | | 0 | 0) => {} | |______________________^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:71:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:72:15 | LL | | 0 | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:73:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:74:15 | LL | | 0] => {} | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:81:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:78:20 + | +LL | (true, 0 | 0) => {} + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:79:17 + | +LL | (_, 0 | 0) => {} + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:87:10 | LL | [1 | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:93:10 + --> $DIR/exhaustiveness-unreachable-pattern.rs:99:10 | LL | [true | ^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:100:36 + --> $DIR/exhaustiveness-unreachable-pattern.rs:106:36 | LL | (true | false, None | Some(true | ^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:105:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:111:14 | LL | (true | ^^^^ @@ -143,28 +155,34 @@ LL | (true | false, None | Some(t_or_f!())) => {} = note: this error originates in the macro `t_or_f` (in Nightly builds, run with -Z macro-backtrace for more info) error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 + --> $DIR/exhaustiveness-unreachable-pattern.rs:122:14 | LL | Some(0 | ^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:135:19 + --> $DIR/exhaustiveness-unreachable-pattern.rs:141:19 | LL | | false) => {} | ^^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:143:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:149:15 | LL | | true) => {} | ^^^^ error: unreachable pattern - --> $DIR/exhaustiveness-unreachable-pattern.rs:149:15 + --> $DIR/exhaustiveness-unreachable-pattern.rs:155:15 | LL | | true, | ^^^^ -error: aborting due to 26 previous errors +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:160:15 + | +LL | | (y, x) => {} + | ^^^^^^ + +error: aborting due to 29 previous errors diff --git a/tests/ui/or-patterns/fn-param-wrap-parens.stderr b/tests/ui/or-patterns/fn-param-wrap-parens.stderr index 73270284131f9..1b9614a13782b 100644 --- a/tests/ui/or-patterns/fn-param-wrap-parens.stderr +++ b/tests/ui/or-patterns/fn-param-wrap-parens.stderr @@ -4,5 +4,5 @@ error: top-level or-patterns are not allowed in function parameters LL | fn fun1(A | B: E) {} | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/or-patterns/inner-or-pat.or3.stderr b/tests/ui/or-patterns/inner-or-pat.or3.stderr index 2236a38c37b2b..10ec7c202e4d6 100644 --- a/tests/ui/or-patterns/inner-or-pat.or3.stderr +++ b/tests/ui/or-patterns/inner-or-pat.or3.stderr @@ -6,6 +6,6 @@ LL | match x { LL | x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | | ^^ expected `str`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/or-patterns/inner-or-pat.or4.stderr b/tests/ui/or-patterns/inner-or-pat.or4.stderr index 058873ff5ff9e..97800161d82fe 100644 --- a/tests/ui/or-patterns/inner-or-pat.or4.stderr +++ b/tests/ui/or-patterns/inner-or-pat.or4.stderr @@ -6,6 +6,6 @@ LL | (x @ "red" | (x @ "blue" | "red")) => { | | | variable not in all patterns -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/or-patterns/while-parsing-this-or-pattern.stderr b/tests/ui/or-patterns/while-parsing-this-or-pattern.stderr index 7ad62ff99ee73..1f3d2d5d6d598 100644 --- a/tests/ui/or-patterns/while-parsing-this-or-pattern.stderr +++ b/tests/ui/or-patterns/while-parsing-this-or-pattern.stderr @@ -6,5 +6,5 @@ LL | Some(42) | .=. => {} | | | while parsing this or-pattern starting here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/order-dependent-cast-inference.stderr b/tests/ui/order-dependent-cast-inference.stderr index 9f4ac0fea36ef..ab33b703a05fc 100644 --- a/tests/ui/order-dependent-cast-inference.stderr +++ b/tests/ui/order-dependent-cast-inference.stderr @@ -6,6 +6,6 @@ LL | let mut y = 0 as *const _; | = note: the type information given here is insufficient to check whether the pointer cast is valid -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0641`. diff --git a/tests/ui/orphan-check-diagnostics.stderr b/tests/ui/orphan-check-diagnostics.stderr index 7a7cea56307de..b9fa7baf4c276 100644 --- a/tests/ui/orphan-check-diagnostics.stderr +++ b/tests/ui/orphan-check-diagnostics.stderr @@ -7,6 +7,6 @@ LL | impl RemoteTrait for T where T: LocalTrait {} = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/osx-frameworks.stderr b/tests/ui/osx-frameworks.stderr index e4a5c98dc5cd5..8582b8123bfe1 100644 --- a/tests/ui/osx-frameworks.stderr +++ b/tests/ui/osx-frameworks.stderr @@ -4,6 +4,6 @@ error[E0455]: link kind `framework` is only supported on Apple targets LL | #[link(name = "foo", kind = "framework")] | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0455`. diff --git a/tests/ui/packed/issue-118537-field-offset-ice.rs b/tests/ui/packed/issue-118537-field-offset-ice.rs new file mode 100644 index 0000000000000..657aec640032b --- /dev/null +++ b/tests/ui/packed/issue-118537-field-offset-ice.rs @@ -0,0 +1,39 @@ +// run-pass +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed(4))] +struct Slice([u32]); + +#[repr(packed(2), C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed(2), C)] +struct PackedUnsized { + f: u8, + d: Slice, +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation correctly adds exact 1 byte of padding + // in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 1 + 4*4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); +} } diff --git a/tests/ui/packed/issue-118537-field-offset.rs b/tests/ui/packed/issue-118537-field-offset.rs new file mode 100644 index 0000000000000..cd17f7679470e --- /dev/null +++ b/tests/ui/packed/issue-118537-field-offset.rs @@ -0,0 +1,36 @@ +// run-pass +#![feature(layout_for_ptr)] +use std::mem; + +#[repr(packed, C)] +struct PackedSized { + f: u8, + d: [u32; 4], +} + +#[repr(packed, C)] +struct PackedUnsized { + f: u8, + d: [u32], +} + +impl PackedSized { + fn unsize(&self) -> &PackedUnsized { + // We can't unsize via a generic type since then we get the error + // that packed structs with unsized tail don't work if the tail + // might need dropping. + let len = 4usize; + unsafe { mem::transmute((self, len)) } + } +} + +fn main() { unsafe { + let p = PackedSized { f: 0, d: [1, 2, 3, 4] }; + let p = p.unsize() as *const PackedUnsized; + // Make sure the size computation does *not* think there is + // any padding in front of the `d` field. + assert_eq!(mem::size_of_val_raw(p), 1 + 4*4); + // And likewise for the offset computation. + let d = std::ptr::addr_of!((*p).d); + assert_eq!(d.cast::().read_unaligned(), 1); +} } diff --git a/tests/ui/packed/issue-27060-2.stderr b/tests/ui/packed/issue-27060-2.stderr index cf5f4e530dc4e..7ee732217e3fe 100644 --- a/tests/ui/packed/issue-27060-2.stderr +++ b/tests/ui/packed/issue-27060-2.stderr @@ -22,6 +22,6 @@ help: the `Box` type always has a statically known size and allocates its conten LL | data: Box, | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/packed/packed-struct-borrow-element-64bit.stderr b/tests/ui/packed/packed-struct-borrow-element-64bit.stderr index 57630a4b47018..a464b18938784 100644 --- a/tests/ui/packed/packed-struct-borrow-element-64bit.stderr +++ b/tests/ui/packed/packed-struct-borrow-element-64bit.stderr @@ -8,6 +8,6 @@ LL | let brw = &foo.baz; = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0793`. diff --git a/tests/ui/packed-struct/packed-struct-generic-transmute.rs b/tests/ui/packed/packed-struct-generic-transmute.rs similarity index 100% rename from tests/ui/packed-struct/packed-struct-generic-transmute.rs rename to tests/ui/packed/packed-struct-generic-transmute.rs diff --git a/tests/ui/packed-struct/packed-struct-generic-transmute.stderr b/tests/ui/packed/packed-struct-generic-transmute.stderr similarity index 91% rename from tests/ui/packed-struct/packed-struct-generic-transmute.stderr rename to tests/ui/packed/packed-struct-generic-transmute.stderr index 744c832dbb407..e91f498842986 100644 --- a/tests/ui/packed-struct/packed-struct-generic-transmute.stderr +++ b/tests/ui/packed/packed-struct-generic-transmute.stderr @@ -7,6 +7,6 @@ LL | let oof: Oof<[u8; 5], i32> = mem::transmute(foo); = note: source type: `Foo<[u8; 5], i32>` (72 bits) = note: target type: `Oof<[u8; 5], i32>` (96 bits) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/packed-struct/packed-struct-transmute.rs b/tests/ui/packed/packed-struct-transmute.rs similarity index 100% rename from tests/ui/packed-struct/packed-struct-transmute.rs rename to tests/ui/packed/packed-struct-transmute.rs diff --git a/tests/ui/packed-struct/packed-struct-transmute.stderr b/tests/ui/packed/packed-struct-transmute.stderr similarity index 90% rename from tests/ui/packed-struct/packed-struct-transmute.stderr rename to tests/ui/packed/packed-struct-transmute.stderr index 80a8919f77b38..4d75820e9449c 100644 --- a/tests/ui/packed-struct/packed-struct-transmute.stderr +++ b/tests/ui/packed/packed-struct-transmute.stderr @@ -7,6 +7,6 @@ LL | let oof: Oof = mem::transmute(foo); = note: source type: `Foo` (N bits) = note: target type: `Oof` (N bits) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr index 85555c43906e8..812f7a0692f4b 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr +++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr @@ -7,6 +7,6 @@ LL | fn panic(info: PanicInfo) -> () {} = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !` found signature `for<'a> fn(PanicInfo<'a>)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr index 84eba2a5a63c2..736a4c7094c5d 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr +++ b/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr @@ -7,6 +7,6 @@ LL | fn panic(info: &'static PanicInfo) -> ! = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _` found signature `for<'a> fn(&'static PanicInfo<'a>) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr index cdf55ab6534ea..6cd072c639625 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr +++ b/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr @@ -7,6 +7,6 @@ LL | fn panic() -> ! { = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _` found signature `fn() -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-4.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-4.stderr index 5e46da12142ff..41a12e8dddf68 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-4.stderr +++ b/tests/ui/panic-handler/panic-handler-bad-signature-4.stderr @@ -4,5 +4,5 @@ error: should have no type parameters LL | fn panic(pi: &PanicInfo) -> ! { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr index 20c17587590ca..3dcd253d3086e 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr +++ b/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr @@ -7,6 +7,6 @@ LL | fn panic(info: &PanicInfo<'static>) -> ! = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _` found signature `for<'a> fn(&'a PanicInfo<'static>) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/panic-handler/panic-handler-duplicate.stderr b/tests/ui/panic-handler/panic-handler-duplicate.stderr index 8cdc4888d022e..5c50b7016b20d 100644 --- a/tests/ui/panic-handler/panic-handler-duplicate.stderr +++ b/tests/ui/panic-handler/panic-handler-duplicate.stderr @@ -10,6 +10,6 @@ note: the lang item is first defined here LL | fn panic(info: &PanicInfo) -> ! { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr b/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr index 2bae12efbde38..06ff8e3098aa4 100644 --- a/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr +++ b/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr @@ -1,4 +1,4 @@ error: language item required, but not found: `panic_info` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/panic-handler/panic-handler-std.stderr b/tests/ui/panic-handler/panic-handler-std.stderr index 7c7feffe76a13..ad9addec8eb4d 100644 --- a/tests/ui/panic-handler/panic-handler-std.stderr +++ b/tests/ui/panic-handler/panic-handler-std.stderr @@ -8,6 +8,6 @@ LL | fn panic(info: PanicInfo) -> ! { = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib = note: second definition in the local crate (`panic_handler_std`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.stderr b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr index 4210a4200aee8..c38feab49c3b1 100644 --- a/tests/ui/panic-handler/panic-handler-with-target-feature.stderr +++ b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr @@ -7,5 +7,5 @@ LL | LL | fn panic(info: &PanicInfo) -> ! { | ------------------------------- `panic_impl` language item function is not allowed to have `#[target_feature]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.stderr b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.stderr index 704b81ae1ce08..bea1172f0e31b 100644 --- a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.stderr +++ b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.stderr @@ -1,4 +1,4 @@ error: the linked panic runtime `panic_unwind` is not compiled with this crate's panic strategy `abort` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/panic-runtime/need-abort-got-unwind.stderr b/tests/ui/panic-runtime/need-abort-got-unwind.stderr index d29c7875fd0ff..2a13f45c1e2ec 100644 --- a/tests/ui/panic-runtime/need-abort-got-unwind.stderr +++ b/tests/ui/panic-runtime/need-abort-got-unwind.stderr @@ -1,4 +1,4 @@ error: the crate `needs_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/panic-runtime/need-unwind-got-abort.stderr b/tests/ui/panic-runtime/need-unwind-got-abort.stderr index 4c71df3ebc147..2a0647fe700ce 100644 --- a/tests/ui/panic-runtime/need-unwind-got-abort.stderr +++ b/tests/ui/panic-runtime/need-unwind-got-abort.stderr @@ -1,4 +1,4 @@ error: the crate `needs_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/panic-runtime/want-unwind-got-abort.stderr b/tests/ui/panic-runtime/want-unwind-got-abort.stderr index d306ce6c5ea28..ced0a7610e2fc 100644 --- a/tests/ui/panic-runtime/want-unwind-got-abort.stderr +++ b/tests/ui/panic-runtime/want-unwind-got-abort.stderr @@ -1,4 +1,4 @@ error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/paren-span.stderr b/tests/ui/paren-span.stderr index fc313715765c2..da2f57033a44e 100644 --- a/tests/ui/paren-span.stderr +++ b/tests/ui/paren-span.stderr @@ -4,6 +4,6 @@ error[E0616]: field `x` of struct `S` is private LL | paren!(s.x); | ^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/parser/assoc/assoc-oddities-1.stderr b/tests/ui/parser/assoc/assoc-oddities-1.stderr index acf71b4893ab0..0d49d542f7329 100644 --- a/tests/ui/parser/assoc/assoc-oddities-1.stderr +++ b/tests/ui/parser/assoc/assoc-oddities-1.stderr @@ -4,5 +4,5 @@ error: expected one of `.`, `;`, `?`, or `}`, found `[` LL | ..if c { a } else { b }[n]; | ^ expected one of `.`, `;`, `?`, or `}` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/assoc/assoc-oddities-2.stderr b/tests/ui/parser/assoc/assoc-oddities-2.stderr index d3b90c34c29a1..5ba8eb51bbca3 100644 --- a/tests/ui/parser/assoc/assoc-oddities-2.stderr +++ b/tests/ui/parser/assoc/assoc-oddities-2.stderr @@ -4,5 +4,5 @@ error: expected one of `.`, `;`, `?`, or `}`, found `[` LL | x..if c { a } else { b }[n]; | ^ expected one of `.`, `;`, `?`, or `}` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/assoc/assoc-type-in-type-arg.stderr b/tests/ui/parser/assoc/assoc-type-in-type-arg.stderr index b637702f21e90..259a836d0979a 100644 --- a/tests/ui/parser/assoc/assoc-type-in-type-arg.stderr +++ b/tests/ui/parser/assoc/assoc-type-in-type-arg.stderr @@ -4,5 +4,5 @@ error: bounds on associated types do not belong here LL | struct Bar<'a, Item: Tr, ::TrSubtype: 'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ belongs in `where` clause -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-bad-meta-2.stderr b/tests/ui/parser/attribute/attr-bad-meta-2.stderr index 6fc6fb665a807..98321827dfa77 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-2.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-2.stderr @@ -4,5 +4,5 @@ error: expected expression, found `]` LL | #[path =] | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-bad-meta-3.stderr b/tests/ui/parser/attribute/attr-bad-meta-3.stderr index 4fa420c79fcc8..13eed2e1dc8c7 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-3.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-3.stderr @@ -4,5 +4,5 @@ error: expected `]`, found `token` LL | #[path() token] | ^^^^^ expected `]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-bad-meta.stderr b/tests/ui/parser/attribute/attr-bad-meta.stderr index 8d65c423c8dab..4ca7d6d9fe6e7 100644 --- a/tests/ui/parser/attribute/attr-bad-meta.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta.stderr @@ -4,5 +4,5 @@ error: expected one of `(`, `::`, `=`, `[`, `]`, or `{`, found `*` LL | #[path*] | ^ expected one of `(`, `::`, `=`, `[`, `]`, or `{` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-before-eof.stderr b/tests/ui/parser/attribute/attr-before-eof.stderr index a2acb94372b8c..18a9d77bf719c 100644 --- a/tests/ui/parser/attribute/attr-before-eof.stderr +++ b/tests/ui/parser/attribute/attr-before-eof.stderr @@ -4,5 +4,5 @@ error: expected item after attributes LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-dangling-in-fn.stderr b/tests/ui/parser/attribute/attr-dangling-in-fn.stderr index b1bb3ab3b17ba..c7b948ea8f768 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-fn.stderr +++ b/tests/ui/parser/attribute/attr-dangling-in-fn.stderr @@ -4,5 +4,5 @@ error: expected statement after outer attribute LL | #[foo = "bar"] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-dangling-in-mod.stderr b/tests/ui/parser/attribute/attr-dangling-in-mod.stderr index 1c892eac08f3b..882400c1d6fba 100644 --- a/tests/ui/parser/attribute/attr-dangling-in-mod.stderr +++ b/tests/ui/parser/attribute/attr-dangling-in-mod.stderr @@ -4,5 +4,5 @@ error: expected item after attributes LL | #[foo = "bar"] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs index d1950087c4c2d..2c402e4c65e23 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs @@ -84,15 +84,15 @@ fn main() {} #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `=>`, `if`, or `|`, found `#` +//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `=>`, `if`, or `|`, found `#` +//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } //~^ ERROR unexpected token: `#` #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `=>`, `if`, or `|`, found `#` +//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } //~^ ERROR unexpected token: `#` diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr index e46c591080d43..a0e95c5c1ed32 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr @@ -365,11 +365,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `=>`, `if`, or `|`, found `#` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:85:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:88:35 @@ -379,11 +379,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `=>`, `if`, or `|`, found `#` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:88:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:91:39 @@ -399,11 +399,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `=>`, `if`, or `|`, found `#` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:93:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:97:34 diff --git a/tests/ui/parser/attribute/attr-with-a-semicolon.stderr b/tests/ui/parser/attribute/attr-with-a-semicolon.stderr index 0de3490b8ea98..b77f30fdb5934 100644 --- a/tests/ui/parser/attribute/attr-with-a-semicolon.stderr +++ b/tests/ui/parser/attribute/attr-with-a-semicolon.stderr @@ -10,5 +10,5 @@ LL - #[derive(Debug, Clone)]; LL + #[derive(Debug, Clone)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attr.stderr b/tests/ui/parser/attribute/attr.stderr index 7cd0ac2244afe..2e0b16efb6cea 100644 --- a/tests/ui/parser/attribute/attr.stderr +++ b/tests/ui/parser/attribute/attr.stderr @@ -13,5 +13,5 @@ LL - #![lang = "foo"] LL + #[lang = "foo"] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.stderr b/tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.stderr index 4c5964715db7e..3279e4e594347 100644 --- a/tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.stderr +++ b/tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.stderr @@ -4,5 +4,5 @@ error: attribute without generic parameters LL | fn foo<#[attr]>() {} | ^^^^^^^ attributes are only permitted when preceding parameters -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/attrs-after-extern-mod.stderr b/tests/ui/parser/attribute/attrs-after-extern-mod.stderr index 135d98457e197..f2bafa54f8dfe 100644 --- a/tests/ui/parser/attribute/attrs-after-extern-mod.stderr +++ b/tests/ui/parser/attribute/attrs-after-extern-mod.stderr @@ -8,5 +8,5 @@ LL | #[cfg(stage37)] LL | } | - the item list ends here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs new file mode 100644 index 0000000000000..d97f24a3d2949 --- /dev/null +++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs @@ -0,0 +1,19 @@ +#![feature(stmt_expr_attributes)] + +fn foo() -> String { + #[cfg(feature = "validation")] + [1, 2, 3].iter().map(|c| c.to_string()).collect::() //~ ERROR expected `;`, found `#` + #[cfg(not(feature = "validation"))] + String::new() +} + +fn bar() -> String { + #[attr] + [1, 2, 3].iter().map(|c| c.to_string()).collect::() //~ ERROR expected `;`, found `#` + #[attr] //~ ERROR cannot find attribute `attr` in this scope + String::new() +} + +fn main() { + println!("{}", foo()); +} diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr new file mode 100644 index 0000000000000..a71253a5e428c --- /dev/null +++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr @@ -0,0 +1,54 @@ +error: expected `;`, found `#` + --> $DIR/multiple-tail-expr-behind-cfg.rs:5:64 + | +LL | #[cfg(feature = "validation")] + | ------------------------------ only `;` terminated statements or tail expressions are allowed after this attribute +LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::() + | ^ expected `;` here +LL | #[cfg(not(feature = "validation"))] + | - unexpected token + | +help: add `;` here + | +LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::(); + | + +help: alternatively, consider surrounding the expression with a block + | +LL | { [1, 2, 3].iter().map(|c| c.to_string()).collect::() } + | + + +help: it seems like you are trying to provide different expressions depending on `cfg`, consider using `if cfg!(..)` + | +LL ~ if cfg!(feature = "validation") { +LL ~ [1, 2, 3].iter().map(|c| c.to_string()).collect::() +LL ~ } else if cfg!(not(feature = "validation")) { +LL ~ String::new() +LL + } + | + +error: expected `;`, found `#` + --> $DIR/multiple-tail-expr-behind-cfg.rs:12:64 + | +LL | #[attr] + | ------- only `;` terminated statements or tail expressions are allowed after this attribute +LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::() + | ^ expected `;` here +LL | #[attr] + | - unexpected token + | +help: add `;` here + | +LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::(); + | + +help: alternatively, consider surrounding the expression with a block + | +LL | { [1, 2, 3].iter().map(|c| c.to_string()).collect::() } + | + + + +error: cannot find attribute `attr` in this scope + --> $DIR/multiple-tail-expr-behind-cfg.rs:13:7 + | +LL | #[attr] + | ^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/bad-escape-suggest-raw-string.stderr b/tests/ui/parser/bad-escape-suggest-raw-string.stderr index 45d24bc0fb362..6dd4ad512a8e3 100644 --- a/tests/ui/parser/bad-escape-suggest-raw-string.stderr +++ b/tests/ui/parser/bad-escape-suggest-raw-string.stderr @@ -10,5 +10,5 @@ help: if you meant to write a literal backslash (perhaps escaping in a regular e LL | let bad = r"ab\[c"; | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bad-let-as-field.stderr b/tests/ui/parser/bad-let-as-field.stderr index 57def42b1ee30..8568036d0562c 100644 --- a/tests/ui/parser/bad-let-as-field.stderr +++ b/tests/ui/parser/bad-let-as-field.stderr @@ -11,5 +11,5 @@ help: escape `let` to use it as an identifier LL | r#let: i32, | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bad-match.stderr b/tests/ui/parser/bad-match.stderr index 13784c409cd27..8e7878c2b6c0f 100644 --- a/tests/ui/parser/bad-match.stderr +++ b/tests/ui/parser/bad-match.stderr @@ -4,5 +4,5 @@ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `x` LL | let isize x = 5; | ^ expected one of `:`, `;`, `=`, `@`, or `|` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bad-name.stderr b/tests/ui/parser/bad-name.stderr index a36b67794fa84..e133d4e4839ce 100644 --- a/tests/ui/parser/bad-name.stderr +++ b/tests/ui/parser/bad-name.stderr @@ -4,5 +4,5 @@ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.` LL | let x.y::.z foo; | ^ expected one of `:`, `;`, `=`, `@`, or `|` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bad-pointer-type.stderr b/tests/ui/parser/bad-pointer-type.stderr index b7225ca887dd4..f409d4d9901a8 100644 --- a/tests/ui/parser/bad-pointer-type.stderr +++ b/tests/ui/parser/bad-pointer-type.stderr @@ -6,10 +6,10 @@ LL | fn foo(_: *()) { | help: add `mut` or `const` here | -LL | fn foo(_: *const ()) { - | +++++ LL | fn foo(_: *mut ()) { | +++ +LL | fn foo(_: *const ()) { + | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bad-struct-following-where.stderr b/tests/ui/parser/bad-struct-following-where.stderr index bb79776dc8459..f27efc95f9137 100644 --- a/tests/ui/parser/bad-struct-following-where.stderr +++ b/tests/ui/parser/bad-struct-following-where.stderr @@ -4,5 +4,5 @@ error: expected `{` after struct name, found `!` LL | struct A where T: Sized ! | ^ expected `{` after struct name -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bad-value-ident-false.stderr b/tests/ui/parser/bad-value-ident-false.stderr index 30c05ecf30a99..9712194967450 100644 --- a/tests/ui/parser/bad-value-ident-false.stderr +++ b/tests/ui/parser/bad-value-ident-false.stderr @@ -9,5 +9,5 @@ help: escape `false` to use it as an identifier LL | fn r#false() { } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bad-value-ident-true.stderr b/tests/ui/parser/bad-value-ident-true.stderr index 74137fa7001ac..b7b73e5f814a6 100644 --- a/tests/ui/parser/bad-value-ident-true.stderr +++ b/tests/ui/parser/bad-value-ident-true.stderr @@ -9,5 +9,5 @@ help: escape `true` to use it as an identifier LL | fn r#true() { } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/better-expected.stderr b/tests/ui/parser/better-expected.stderr index 21bf8d19a721e..6cb9a49605ff4 100644 --- a/tests/ui/parser/better-expected.stderr +++ b/tests/ui/parser/better-expected.stderr @@ -6,5 +6,5 @@ LL | let x: [isize 3]; | | | while parsing the type for `x` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bind-struct-early-modifiers.stderr b/tests/ui/parser/bind-struct-early-modifiers.stderr index b35762a887c78..6b366a99569c6 100644 --- a/tests/ui/parser/bind-struct-early-modifiers.stderr +++ b/tests/ui/parser/bind-struct-early-modifiers.stderr @@ -6,5 +6,5 @@ LL | Foo { ref x: ref x } => {}, | | | while parsing the fields for this pattern -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bound-single-question-mark.stderr b/tests/ui/parser/bound-single-question-mark.stderr index 82937a517b5e9..f339c2022751b 100644 --- a/tests/ui/parser/bound-single-question-mark.stderr +++ b/tests/ui/parser/bound-single-question-mark.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `>` LL | fn f() {} | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bounds-lifetime-1.stderr b/tests/ui/parser/bounds-lifetime-1.stderr index 000e84f635b7b..101704f6442cc 100644 --- a/tests/ui/parser/bounds-lifetime-1.stderr +++ b/tests/ui/parser/bounds-lifetime-1.stderr @@ -4,5 +4,5 @@ error: expected one of `,`, `:`, or `>`, found `'b` LL | type A = for<'a 'b> fn(); | ^^ expected one of `,`, `:`, or `>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bounds-lifetime-2.stderr b/tests/ui/parser/bounds-lifetime-2.stderr index dd3e69c11396d..f39cc604eec48 100644 --- a/tests/ui/parser/bounds-lifetime-2.stderr +++ b/tests/ui/parser/bounds-lifetime-2.stderr @@ -4,5 +4,5 @@ error: expected one of `,`, `:`, or `>`, found `+` LL | type A = for<'a + 'b> fn(); | ^ expected one of `,`, `:`, or `>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bounds-lifetime-where-1.stderr b/tests/ui/parser/bounds-lifetime-where-1.stderr index b6bd866938bed..f79b4fa033834 100644 --- a/tests/ui/parser/bounds-lifetime-where-1.stderr +++ b/tests/ui/parser/bounds-lifetime-where-1.stderr @@ -4,5 +4,5 @@ error: expected `:`, found `;` LL | type A where 'a; | ^ expected `:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bounds-lifetime-where.stderr b/tests/ui/parser/bounds-lifetime-where.stderr index 785a1fb679324..9dd963afc7963 100644 --- a/tests/ui/parser/bounds-lifetime-where.stderr +++ b/tests/ui/parser/bounds-lifetime-where.stderr @@ -4,5 +4,5 @@ error: expected one of `;`, `=`, `where`, lifetime, or type, found `,` LL | type A where , = u8; | ^ expected one of `;`, `=`, `where`, lifetime, or type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bounds-lifetime.stderr b/tests/ui/parser/bounds-lifetime.stderr index e47a21d892b2f..26a3e78633a9a 100644 --- a/tests/ui/parser/bounds-lifetime.stderr +++ b/tests/ui/parser/bounds-lifetime.stderr @@ -4,5 +4,5 @@ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` LL | type A = for<,> fn(); | ^ expected one of `#`, `>`, `const`, identifier, or lifetime -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/bounds-type-where.stderr b/tests/ui/parser/bounds-type-where.stderr index 5636ee75c97a8..709d31430984b 100644 --- a/tests/ui/parser/bounds-type-where.stderr +++ b/tests/ui/parser/bounds-type-where.stderr @@ -4,5 +4,5 @@ error: expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` LL | type A where T, = u8; | ^ expected one of 8 possible tokens -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/brace-in-let-chain.rs b/tests/ui/parser/brace-in-let-chain.rs new file mode 100644 index 0000000000000..1f34c73a2c3bd --- /dev/null +++ b/tests/ui/parser/brace-in-let-chain.rs @@ -0,0 +1,58 @@ +// issue #117766 + +#![feature(let_chains)] +fn main() { + if let () = () + && let () = () { //~ERROR: found a `{` in the middle of a let-chain + && let () = () + { + } +} + +fn quux() { + while let () = () + && let () = () { //~ERROR: found a `{` in the middle of a let-chain + && let () = () + { + } +} + +fn foobar() { + while false {} + { + && let () = () +} + +fn fubar() { + while false { + { + && let () = () + } +} + +fn qux() { + let foo = false; + match foo { + _ if foo => { + && let () = () + _ => {} + } +} + +fn foo() { + { + && let () = () +} + +fn bar() { + if false {} + { + && let () = () +} + +fn baz() { + if false { + { + && let () = () + } +} //~ERROR: this file contains an unclosed delimiter diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr new file mode 100644 index 0000000000000..7182d86d001d0 --- /dev/null +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -0,0 +1,65 @@ +error: this file contains an unclosed delimiter + --> $DIR/brace-in-let-chain.rs:58:54 + | +LL | fn main() { + | - unclosed delimiter +... +LL | fn quux() { + | - unclosed delimiter +... +LL | fn foobar() { + | - unclosed delimiter +... +LL | fn fubar() { + | - unclosed delimiter +... +LL | fn qux() { + | - unclosed delimiter +... +LL | fn foo() { + | - unclosed delimiter +... +LL | fn bar() { + | - unclosed delimiter +... +LL | fn baz() { + | - unclosed delimiter +LL | if false { +LL | { + | - this delimiter might not be properly closed... +LL | && let () = () +LL | } + | - ...as it matches this but it has different indentation +LL | } + | ^ + +error: found a `{` in the middle of a let-chain + --> $DIR/brace-in-let-chain.rs:14:24 + | +LL | && let () = () { + | ^ +LL | && let () = () + | ------ you might have meant to continue the let-chain here + | +help: consider removing this brace to parse the `let` as part of the same chain + | +LL - && let () = () { +LL + && let () = () + | + +error: found a `{` in the middle of a let-chain + --> $DIR/brace-in-let-chain.rs:6:24 + | +LL | && let () = () { + | ^ +LL | && let () = () + | ------ you might have meant to continue the let-chain here + | +help: consider removing this brace to parse the `let` as part of the same chain + | +LL - && let () = () { +LL + && let () = () + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/can-begin-expr-check.stderr b/tests/ui/parser/can-begin-expr-check.stderr index 9569ababad8d5..247009be0cbdd 100644 --- a/tests/ui/parser/can-begin-expr-check.stderr +++ b/tests/ui/parser/can-begin-expr-check.stderr @@ -4,5 +4,5 @@ error: expected one of `;`, `}`, or an operator, found keyword `enum` LL | return enum; | ^^^^ expected one of `;`, `}`, or an operator -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/char/whitespace-character-literal.stderr b/tests/ui/parser/char/whitespace-character-literal.stderr index d73de41a8099b..3bd048f8f622b 100644 --- a/tests/ui/parser/char/whitespace-character-literal.stderr +++ b/tests/ui/parser/char/whitespace-character-literal.stderr @@ -12,5 +12,5 @@ note: there are non-printing characters, the full sequence is `\u{200a}x\u{200b} LL | let _hair_space_around = ' x​'; | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/class-implements-bad-trait.stderr b/tests/ui/parser/class-implements-bad-trait.stderr index 3a4dea95d5ddc..5290e3594d553 100644 --- a/tests/ui/parser/class-implements-bad-trait.stderr +++ b/tests/ui/parser/class-implements-bad-trait.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `cat` LL | class cat : nonexistent { | ^^^ expected one of `!` or `::` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr index 3d16a2067ccae..eb8428854afb9 100644 --- a/tests/ui/parser/closure-return-syntax.stderr +++ b/tests/ui/parser/closure-return-syntax.stderr @@ -9,5 +9,5 @@ help: try placing this code inside a block LL | let x = || -> i32 { 22 }; | + + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/column-offset-1-based.stderr b/tests/ui/parser/column-offset-1-based.stderr index 766d72a0a5a93..d837466d9af18 100644 --- a/tests/ui/parser/column-offset-1-based.stderr +++ b/tests/ui/parser/column-offset-1-based.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `[`, found `` LL | # | ^ expected one of `!` or `[` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/deep-unmatched-angle-brackets.stderr b/tests/ui/parser/deep-unmatched-angle-brackets.stderr index 1f28503748282..7c9033f2f3220 100644 --- a/tests/ui/parser/deep-unmatched-angle-brackets.stderr +++ b/tests/ui/parser/deep-unmatched-angle-brackets.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | >(); | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/deli-ident-issue-1.stderr b/tests/ui/parser/deli-ident-issue-1.stderr index eb5073e14cfd9..78f5d7b63b954 100644 --- a/tests/ui/parser/deli-ident-issue-1.stderr +++ b/tests/ui/parser/deli-ident-issue-1.stderr @@ -13,5 +13,5 @@ LL | } LL | fn main() { } | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/enum-2.stderr b/tests/ui/parser/diff-markers/enum-2.stderr index 63da5c2a6e1f3..20e551c2f959a 100644 --- a/tests/ui/parser/diff-markers/enum-2.stderr +++ b/tests/ui/parser/diff-markers/enum-2.stderr @@ -17,5 +17,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/enum.stderr b/tests/ui/parser/diff-markers/enum.stderr index abbf3fb41e790..be94331dce528 100644 --- a/tests/ui/parser/diff-markers/enum.stderr +++ b/tests/ui/parser/diff-markers/enum.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/fn-arg.stderr b/tests/ui/parser/diff-markers/fn-arg.stderr index 933a206410e10..aabcb826c1283 100644 --- a/tests/ui/parser/diff-markers/fn-arg.stderr +++ b/tests/ui/parser/diff-markers/fn-arg.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/item-with-attr.stderr b/tests/ui/parser/diff-markers/item-with-attr.stderr index 850e2368e55d1..eefb2792e90bc 100644 --- a/tests/ui/parser/diff-markers/item-with-attr.stderr +++ b/tests/ui/parser/diff-markers/item-with-attr.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/item.stderr b/tests/ui/parser/diff-markers/item.stderr index 9ab3631a60e89..a3092ebfcfd36 100644 --- a/tests/ui/parser/diff-markers/item.stderr +++ b/tests/ui/parser/diff-markers/item.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/statement.stderr b/tests/ui/parser/diff-markers/statement.stderr index 7ca2495b829e4..c6c6cae876594 100644 --- a/tests/ui/parser/diff-markers/statement.stderr +++ b/tests/ui/parser/diff-markers/statement.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/struct-expr.stderr b/tests/ui/parser/diff-markers/struct-expr.stderr index d70476a983310..bdea8c841c638 100644 --- a/tests/ui/parser/diff-markers/struct-expr.stderr +++ b/tests/ui/parser/diff-markers/struct-expr.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/struct.stderr b/tests/ui/parser/diff-markers/struct.stderr index cc0b3da664e7b..749941290cb82 100644 --- a/tests/ui/parser/diff-markers/struct.stderr +++ b/tests/ui/parser/diff-markers/struct.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/trait-item.stderr b/tests/ui/parser/diff-markers/trait-item.stderr index cdc19f8e0765a..f01bbe8ba0340 100644 --- a/tests/ui/parser/diff-markers/trait-item.stderr +++ b/tests/ui/parser/diff-markers/trait-item.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/tuple-struct.stderr b/tests/ui/parser/diff-markers/tuple-struct.stderr index d673db89837e7..8dae123c96dca 100644 --- a/tests/ui/parser/diff-markers/tuple-struct.stderr +++ b/tests/ui/parser/diff-markers/tuple-struct.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr index e0b6f1b5eb805..6995b8e6f2370 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr +++ b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> 7a4f13c blah blah blah = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/unclosed-delims.stderr b/tests/ui/parser/diff-markers/unclosed-delims.stderr index 67199179b3922..d4636150e66b7 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims.stderr +++ b/tests/ui/parser/diff-markers/unclosed-delims.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> 7a4f13c blah blah blah = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/use-statement.stderr b/tests/ui/parser/diff-markers/use-statement.stderr index 12e6f57dd501b..6d376166a7f7a 100644 --- a/tests/ui/parser/diff-markers/use-statement.stderr +++ b/tests/ui/parser/diff-markers/use-statement.stderr @@ -14,5 +14,5 @@ LL | >>>>>>> branch = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased = note: for an explanation on these markers from the `git` documentation, visit -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr b/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr index 7b43c77005ed4..0227439ce066d 100644 --- a/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr +++ b/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr @@ -6,5 +6,5 @@ LL | [1, 3) | | | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr b/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr index 2fe6a28eeb412..2796312f4ad17 100644 --- a/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr +++ b/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr @@ -4,5 +4,5 @@ error: expected one of `.`, `?`, `]`, or an operator, found `,` LL | let _x = vec[1, 2, 3]; | ^ expected one of `.`, `?`, `]`, or an operator -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/doc-before-attr.stderr b/tests/ui/parser/doc-before-attr.stderr index 14fd01af2f98a..0298b9b60d2f3 100644 --- a/tests/ui/parser/doc-before-attr.stderr +++ b/tests/ui/parser/doc-before-attr.stderr @@ -6,5 +6,5 @@ LL | /// hi LL | #[derive(Debug)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/doc-before-eof.stderr b/tests/ui/parser/doc-before-eof.stderr index 82756626765b0..e41d02f0ea4d4 100644 --- a/tests/ui/parser/doc-before-eof.stderr +++ b/tests/ui/parser/doc-before-eof.stderr @@ -4,5 +4,5 @@ error: expected item after doc comment LL | /// hi | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/doc-before-extern-rbrace.stderr b/tests/ui/parser/doc-before-extern-rbrace.stderr index 8fa12ec261e09..4d952e294262f 100644 --- a/tests/ui/parser/doc-before-extern-rbrace.stderr +++ b/tests/ui/parser/doc-before-extern-rbrace.stderr @@ -6,6 +6,6 @@ LL | /// hi | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0584`. diff --git a/tests/ui/parser/doc-before-fn-rbrace.stderr b/tests/ui/parser/doc-before-fn-rbrace.stderr index 6ea68e42b4cd3..bbe6b71441703 100644 --- a/tests/ui/parser/doc-before-fn-rbrace.stderr +++ b/tests/ui/parser/doc-before-fn-rbrace.stderr @@ -6,6 +6,6 @@ LL | /// document | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-identifier.stderr b/tests/ui/parser/doc-before-identifier.stderr index 940d293b6786c..501b05c5a9480 100644 --- a/tests/ui/parser/doc-before-identifier.stderr +++ b/tests/ui/parser/doc-before-identifier.stderr @@ -4,5 +4,5 @@ error: expected identifier, found doc comment `/// document` LL | fn /// document | ^^^^^^^^^^^^ expected identifier, found doc comment -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/doc-before-mod-rbrace.stderr b/tests/ui/parser/doc-before-mod-rbrace.stderr index d5749c66cd290..00aa40b621137 100644 --- a/tests/ui/parser/doc-before-mod-rbrace.stderr +++ b/tests/ui/parser/doc-before-mod-rbrace.stderr @@ -4,5 +4,5 @@ error: expected item after doc comment LL | /// document | ^^^^^^^^^^^^ this doc comment doesn't document anything -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/doc-before-rbrace.stderr b/tests/ui/parser/doc-before-rbrace.stderr index 4d4741dfe59cd..3c4ea5375b53c 100644 --- a/tests/ui/parser/doc-before-rbrace.stderr +++ b/tests/ui/parser/doc-before-rbrace.stderr @@ -6,6 +6,6 @@ LL | println!("Hi"); /// hi | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-semi.stderr b/tests/ui/parser/doc-before-semi.stderr index a879e13ffbd62..f3454d30d1975 100644 --- a/tests/ui/parser/doc-before-semi.stderr +++ b/tests/ui/parser/doc-before-semi.stderr @@ -6,6 +6,6 @@ LL | /// hi | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-struct-rbrace-1.stderr b/tests/ui/parser/doc-before-struct-rbrace-1.stderr index 94934f734b394..62a27740f56f9 100644 --- a/tests/ui/parser/doc-before-struct-rbrace-1.stderr +++ b/tests/ui/parser/doc-before-struct-rbrace-1.stderr @@ -9,6 +9,6 @@ LL | /// document | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-struct-rbrace-2.stderr b/tests/ui/parser/doc-before-struct-rbrace-2.stderr index 6b5c8c1f8b531..66c6ce8940ad9 100644 --- a/tests/ui/parser/doc-before-struct-rbrace-2.stderr +++ b/tests/ui/parser/doc-before-struct-rbrace-2.stderr @@ -6,6 +6,6 @@ LL | a: u8 /// document | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-inside-trait-item.stderr b/tests/ui/parser/doc-inside-trait-item.stderr index 900124adcc3b8..df1ebc1106fd5 100644 --- a/tests/ui/parser/doc-inside-trait-item.stderr +++ b/tests/ui/parser/doc-inside-trait-item.stderr @@ -6,6 +6,6 @@ LL | /// empty doc | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0584`. diff --git a/tests/ui/parser/dotdotdot-expr.stderr b/tests/ui/parser/dotdotdot-expr.stderr index e7203f24d3f8d..208c04bd3df50 100644 --- a/tests/ui/parser/dotdotdot-expr.stderr +++ b/tests/ui/parser/dotdotdot-expr.stderr @@ -13,5 +13,5 @@ help: or `..=` for an inclusive range LL | let _redemptive = 1..=21; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/double-pointer.stderr b/tests/ui/parser/double-pointer.stderr index 28037f9326552..25403c5b027d1 100644 --- a/tests/ui/parser/double-pointer.stderr +++ b/tests/ui/parser/double-pointer.stderr @@ -6,10 +6,10 @@ LL | let dptr: **const i32 = &ptr; | help: add `mut` or `const` here | -LL | let dptr: *const *const i32 = &ptr; - | +++++ LL | let dptr: *mut *const i32 = &ptr; | +++ +LL | let dptr: *const *const i32 = &ptr; + | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/duplicate-visibility.stderr b/tests/ui/parser/duplicate-visibility.stderr index 8ecebf01f17a3..b578b1fe26e8d 100644 --- a/tests/ui/parser/duplicate-visibility.stderr +++ b/tests/ui/parser/duplicate-visibility.stderr @@ -18,5 +18,5 @@ note: explicit visibility first seen here LL | pub pub fn foo(); | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/emoji-identifiers.stderr b/tests/ui/parser/emoji-identifiers.stderr index e645b68ba87c6..8250dd1ea2e92 100644 --- a/tests/ui/parser/emoji-identifiers.stderr +++ b/tests/ui/parser/emoji-identifiers.stderr @@ -75,6 +75,12 @@ LL | 👀::full_of✨() | | | function or associated item not found in `👀` | help: there is an associated function with a similar name: `full_of_✨` + | +note: if you're trying to build a new `👀`, consider using `👀::full_of_✨` which returns `👀` + --> $DIR/emoji-identifiers.rs:4:5 + | +LL | fn full_of_✨() -> 👀 { + | ^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope --> $DIR/emoji-identifiers.rs:13:13 diff --git a/tests/ui/parser/empty-impl-semicolon.stderr b/tests/ui/parser/empty-impl-semicolon.stderr index 6ed309eba9392..cb15c36e6491c 100644 --- a/tests/ui/parser/empty-impl-semicolon.stderr +++ b/tests/ui/parser/empty-impl-semicolon.stderr @@ -6,5 +6,5 @@ LL | impl Foo; | = help: try using `{}` instead -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/extern-crate-unexpected-token.stderr b/tests/ui/parser/extern-crate-unexpected-token.stderr index e9d287ac0e927..f83bb3e3e35ae 100644 --- a/tests/ui/parser/extern-crate-unexpected-token.stderr +++ b/tests/ui/parser/extern-crate-unexpected-token.stderr @@ -4,5 +4,5 @@ error: expected one of `crate` or `{`, found `crte` LL | extern crte foo; | ^^^^ expected one of `crate` or `{` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/extern-expected-fn-or-brace.stderr b/tests/ui/parser/extern-expected-fn-or-brace.stderr index 258a2c2680aaf..c2200e0376340 100644 --- a/tests/ui/parser/extern-expected-fn-or-brace.stderr +++ b/tests/ui/parser/extern-expected-fn-or-brace.stderr @@ -4,5 +4,5 @@ error: expected `{`, found keyword `mod` LL | extern "C" mod foo; | ^^^ expected `{` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/extern-foreign-crate.stderr b/tests/ui/parser/extern-foreign-crate.stderr index eb75c0fc9c6aa..10c58aeb571de 100644 --- a/tests/ui/parser/extern-foreign-crate.stderr +++ b/tests/ui/parser/extern-foreign-crate.stderr @@ -4,5 +4,5 @@ error: expected one of `;` or `as`, found `{` LL | extern crate foo {} | ^ expected one of `;` or `as` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/extern-no-fn.stderr b/tests/ui/parser/extern-no-fn.stderr index d9183d5646360..2e434afb218c9 100644 --- a/tests/ui/parser/extern-no-fn.stderr +++ b/tests/ui/parser/extern-no-fn.stderr @@ -8,5 +8,5 @@ LL | f(); LL | } | - the item list ends here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/float-field-interpolated.rs b/tests/ui/parser/float-field-interpolated.rs index a30532035365b..990f2926dc861 100644 --- a/tests/ui/parser/float-field-interpolated.rs +++ b/tests/ui/parser/float-field-interpolated.rs @@ -6,9 +6,9 @@ macro_rules! generate_field_accesses { s.$a; // OK { s.$b; } //~ ERROR unexpected token: `1.1` - //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1` { s.$c; } //~ ERROR unexpected token: `1.1` - //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1` }; } diff --git a/tests/ui/parser/float-field-interpolated.stderr b/tests/ui/parser/float-field-interpolated.stderr index 664adb35818aa..2a1a4926cb3c6 100644 --- a/tests/ui/parser/float-field-interpolated.stderr +++ b/tests/ui/parser/float-field-interpolated.stderr @@ -9,7 +9,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` +error: expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1` --> $DIR/float-field-interpolated.rs:8:13 | LL | { s.$b; } @@ -31,7 +31,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` +error: expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1` --> $DIR/float-field-interpolated.rs:10:13 | LL | { s.$c; } diff --git a/tests/ui/parser/float-field.stderr b/tests/ui/parser/float-field.stderr index 7090efc5014b3..d67d270ef7b93 100644 --- a/tests/ui/parser/float-field.stderr +++ b/tests/ui/parser/float-field.stderr @@ -274,7 +274,7 @@ error[E0609]: no field `1e1` on type `(u8, u8)` --> $DIR/float-field.rs:9:9 | LL | s.1.1e1; - | ^^^ + | ^^^ unknown field error[E0609]: no field `0x1e1` on type `S` --> $DIR/float-field.rs:24:7 @@ -336,13 +336,13 @@ error[E0609]: no field `f32` on type `(u8, u8)` --> $DIR/float-field.rs:44:9 | LL | s.1.f32; - | ^^^ + | ^^^ unknown field error[E0609]: no field `1e1` on type `(u8, u8)` --> $DIR/float-field.rs:46:7 | LL | s.1.1e1f32; - | ^^^^^^^^ + | ^^^^^^^^ unknown field error: aborting due to 55 previous errors diff --git a/tests/ui/parser/fn-colon-return-type.stderr b/tests/ui/parser/fn-colon-return-type.stderr index 1de9187820560..b61a62a17f7e2 100644 --- a/tests/ui/parser/fn-colon-return-type.stderr +++ b/tests/ui/parser/fn-colon-return-type.stderr @@ -4,5 +4,5 @@ error: return types are denoted using `->` LL | fn foo(x: i32): i32 { | ^ help: use `->` instead -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/fn-defined-using-def.stderr b/tests/ui/parser/fn-defined-using-def.stderr index f34329012a02f..972c861c75024 100644 --- a/tests/ui/parser/fn-defined-using-def.stderr +++ b/tests/ui/parser/fn-defined-using-def.stderr @@ -6,5 +6,5 @@ LL | def foo() {} | | | help: write `fn` instead of `def` to declare a function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/fn-defined-using-fun.stderr b/tests/ui/parser/fn-defined-using-fun.stderr index 2f6cfff350c90..3c8e586c0e8c3 100644 --- a/tests/ui/parser/fn-defined-using-fun.stderr +++ b/tests/ui/parser/fn-defined-using-fun.stderr @@ -6,5 +6,5 @@ LL | fun foo() {} | | | help: write `fn` instead of `fun` to declare a function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/fn-defined-using-func.stderr b/tests/ui/parser/fn-defined-using-func.stderr index 355741e8949a9..9dd90798d9261 100644 --- a/tests/ui/parser/fn-defined-using-func.stderr +++ b/tests/ui/parser/fn-defined-using-func.stderr @@ -6,5 +6,5 @@ LL | func foo() {} | | | help: write `fn` instead of `func` to declare a function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/fn-defined-using-function.stderr b/tests/ui/parser/fn-defined-using-function.stderr index 43c33a2cdd7e8..504ab1bb93d75 100644 --- a/tests/ui/parser/fn-defined-using-function.stderr +++ b/tests/ui/parser/fn-defined-using-function.stderr @@ -6,5 +6,5 @@ LL | function foo() {} | | | help: write `fn` instead of `function` to declare a function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/generic-statics.stderr b/tests/ui/parser/generic-statics.stderr index c757232b061c4..eb2e273602ec1 100644 --- a/tests/ui/parser/generic-statics.stderr +++ b/tests/ui/parser/generic-statics.stderr @@ -4,5 +4,5 @@ error: static items may not have generic parameters LL | static S: i32 = 0; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/if-in-in.stderr b/tests/ui/parser/if-in-in.stderr index 0e69bc4b2ce53..6117370c0ce68 100644 --- a/tests/ui/parser/if-in-in.stderr +++ b/tests/ui/parser/if-in-in.stderr @@ -6,5 +6,5 @@ LL | for i in in 1..2 { | | | help: remove the duplicated `in` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/impl-item-const-semantic-fail.stderr b/tests/ui/parser/impl-item-const-semantic-fail.stderr index ec3bee0ce6824..579f4c29c5260 100644 --- a/tests/ui/parser/impl-item-const-semantic-fail.stderr +++ b/tests/ui/parser/impl-item-const-semantic-fail.stderr @@ -6,5 +6,5 @@ LL | const Y: u8; | | | help: provide a definition for the constant: `= ;` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr b/tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr index 1acb727368bce..1704d99cf29f6 100644 --- a/tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr +++ b/tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr @@ -6,5 +6,5 @@ LL | fn f(); | | | help: provide a definition for the function: `{ }` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/impl-on-unsized-typo.stderr b/tests/ui/parser/impl-on-unsized-typo.stderr index 23dcc1efd68b1..62e0d085e275c 100644 --- a/tests/ui/parser/impl-on-unsized-typo.stderr +++ b/tests/ui/parser/impl-on-unsized-typo.stderr @@ -4,5 +4,5 @@ error: expected one of `,`, `:`, `=`, or `>`, found `?` LL | impl Tr for T {} | ^ expected one of `,`, `:`, `=`, or `>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/import-from-path.stderr b/tests/ui/parser/import-from-path.stderr index 93bdf82d0f576..b63e48d6679a6 100644 --- a/tests/ui/parser/import-from-path.stderr +++ b/tests/ui/parser/import-from-path.stderr @@ -6,5 +6,5 @@ LL | use foo::{bar}::baz | = note: glob-like brace syntax must be last on the path -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/import-from-rename.stderr b/tests/ui/parser/import-from-rename.stderr index d78f6de9222cf..2f267a8d02694 100644 --- a/tests/ui/parser/import-from-rename.stderr +++ b/tests/ui/parser/import-from-rename.stderr @@ -6,5 +6,5 @@ LL | use foo::{bar} as baz; | = note: glob-like brace syntax must be last on the path -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/import-glob-path.stderr b/tests/ui/parser/import-glob-path.stderr index a93ef255c94b2..3bde32d1ea4d3 100644 --- a/tests/ui/parser/import-glob-path.stderr +++ b/tests/ui/parser/import-glob-path.stderr @@ -6,5 +6,5 @@ LL | use foo::*::bar | = note: the wildcard token must be last on the path -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/import-glob-rename.stderr b/tests/ui/parser/import-glob-rename.stderr index e1a026b639e7e..24e6c3f000632 100644 --- a/tests/ui/parser/import-glob-rename.stderr +++ b/tests/ui/parser/import-glob-rename.stderr @@ -6,5 +6,5 @@ LL | use foo::* as baz; | = note: the wildcard token must be last on the path -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/inner-attr-after-doc-comment.stderr b/tests/ui/parser/inner-attr-after-doc-comment.stderr index 3ec3ad8e977a8..6dbc0fd93fd42 100644 --- a/tests/ui/parser/inner-attr-after-doc-comment.stderr +++ b/tests/ui/parser/inner-attr-after-doc-comment.stderr @@ -19,5 +19,5 @@ LL - #![recursion_limit="100"] LL + #[recursion_limit="100"] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/inner-attr.stderr b/tests/ui/parser/inner-attr.stderr index 331c254a52b48..57ca164fc15a2 100644 --- a/tests/ui/parser/inner-attr.stderr +++ b/tests/ui/parser/inner-attr.stderr @@ -16,5 +16,5 @@ LL - #![recursion_limit="100"] LL + #[recursion_limit="100"] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/int-literal-too-large-span.stderr b/tests/ui/parser/int-literal-too-large-span.stderr index 49d6aa5eff8ce..d65a3052ba933 100644 --- a/tests/ui/parser/int-literal-too-large-span.stderr +++ b/tests/ui/parser/int-literal-too-large-span.stderr @@ -6,5 +6,5 @@ LL | 99999999999999999999999999999999999999999999999999999999999999999999999 | = note: value exceeds limit of `340282366920938463463374607431768211455` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/integer-literal-start-ident.stderr b/tests/ui/parser/integer-literal-start-ident.stderr index b2c6612965608..27f0baec80c33 100644 --- a/tests/ui/parser/integer-literal-start-ident.stderr +++ b/tests/ui/parser/integer-literal-start-ident.stderr @@ -10,5 +10,5 @@ help: identifiers cannot start with a number LL | fn 1main() {} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/intersection-patterns-2.stderr b/tests/ui/parser/intersection-patterns-2.stderr index f7e78814ca57c..df34e2a42a9a1 100644 --- a/tests/ui/parser/intersection-patterns-2.stderr +++ b/tests/ui/parser/intersection-patterns-2.stderr @@ -9,5 +9,5 @@ LL | Some(x) @ Some(y) => {} | = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-100197-mut-let.stderr b/tests/ui/parser/issues/issue-100197-mut-let.stderr index 86658e4f39f1f..07d136881408e 100644 --- a/tests/ui/parser/issues/issue-100197-mut-let.stderr +++ b/tests/ui/parser/issues/issue-100197-mut-let.stderr @@ -4,5 +4,5 @@ error: invalid variable declaration LL | mut let _x = 123; | ^^^^^^^ help: switch the order of `mut` and `let`: `let mut` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-101477-let.stderr b/tests/ui/parser/issues/issue-101477-let.stderr index 1b30d4b17861a..56348357397fc 100644 --- a/tests/ui/parser/issues/issue-101477-let.stderr +++ b/tests/ui/parser/issues/issue-101477-let.stderr @@ -4,5 +4,5 @@ error: unexpected `==` LL | let x == 2; | ^^ help: try using `=` instead -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-101540.stderr b/tests/ui/parser/issues/issue-101540.stderr index 8af887050023c..40f1d339a45c2 100644 --- a/tests/ui/parser/issues/issue-101540.stderr +++ b/tests/ui/parser/issues/issue-101540.stderr @@ -8,5 +8,5 @@ LL | struct S2 { | = help: consider creating a new `struct` definition instead of nesting -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-102182-impl-trait-recover.stderr b/tests/ui/parser/issues/issue-102182-impl-trait-recover.stderr index 52b6ae5df359a..cf05337f26c06 100644 --- a/tests/ui/parser/issues/issue-102182-impl-trait-recover.stderr +++ b/tests/ui/parser/issues/issue-102182-impl-trait-recover.stderr @@ -10,5 +10,5 @@ LL - fn foo() {} LL + fn foo() {} | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-103451.stderr b/tests/ui/parser/issues/issue-103451.stderr index 6aacd5012c14f..7ad816e451eab 100644 --- a/tests/ui/parser/issues/issue-103451.stderr +++ b/tests/ui/parser/issues/issue-103451.stderr @@ -8,5 +8,5 @@ LL | x: [u8; R | | | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-10392-2.stderr b/tests/ui/parser/issues/issue-10392-2.stderr index 4154ecfeb71c3..3e5d5062bee34 100644 --- a/tests/ui/parser/issues/issue-10392-2.stderr +++ b/tests/ui/parser/issues/issue-10392-2.stderr @@ -8,5 +8,5 @@ LL | let A { .., } = a(); | | help: remove this comma | `..` must be at the end and cannot have a trailing comma -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-10392.stderr b/tests/ui/parser/issues/issue-10392.stderr index 438ea67d33cdd..85090d054e8e0 100644 --- a/tests/ui/parser/issues/issue-10392.stderr +++ b/tests/ui/parser/issues/issue-10392.stderr @@ -6,5 +6,5 @@ LL | let A { , } = a(); | | | while parsing the fields for this pattern -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-104620.stderr b/tests/ui/parser/issues/issue-104620.stderr index d06a6b2554bb5..fa20b5f8b1625 100644 --- a/tests/ui/parser/issues/issue-104620.stderr +++ b/tests/ui/parser/issues/issue-104620.stderr @@ -4,5 +4,5 @@ error: unexpected expression: `5z` LL | #![rustc_dummy=5z] | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-105366.stderr b/tests/ui/parser/issues/issue-105366.stderr index 0a7408e2c173f..18c04dfaf2088 100644 --- a/tests/ui/parser/issues/issue-105366.stderr +++ b/tests/ui/parser/issues/issue-105366.stderr @@ -9,5 +9,5 @@ help: replace `fn` with `impl` here LL | impl From for Foo { | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-10636-1.stderr b/tests/ui/parser/issues/issue-10636-1.stderr index 1e6294ebe1691..a7402e0717b70 100644 --- a/tests/ui/parser/issues/issue-10636-1.stderr +++ b/tests/ui/parser/issues/issue-10636-1.stderr @@ -7,5 +7,5 @@ LL | struct Obj { LL | ) | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-10636-2.stderr b/tests/ui/parser/issues/issue-10636-2.stderr index 4cd4be1803e12..2dc615246a799 100644 --- a/tests/ui/parser/issues/issue-10636-2.stderr +++ b/tests/ui/parser/issues/issue-10636-2.stderr @@ -9,5 +9,5 @@ LL | option.map(|some| 42; LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-107705.stderr b/tests/ui/parser/issues/issue-107705.stderr index d2d6134611863..2d0c3e0e675c7 100644 --- a/tests/ui/parser/issues/issue-107705.stderr +++ b/tests/ui/parser/issues/issue-107705.stderr @@ -6,5 +6,5 @@ LL | fn f() {a(b:&, | | | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed new file mode 100644 index 0000000000000..eaae288864a3d --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn func() where F: FnOnce() -> () {} +//~^ ERROR expected one of +//~| NOTE expected one of +//~| NOTE `Fn` bounds require arguments in parentheses + +fn main() {} diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs new file mode 100644 index 0000000000000..ea5c71150e83c --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn func() where F: FnOnce -> () {} +//~^ ERROR expected one of +//~| NOTE expected one of +//~| NOTE `Fn` bounds require arguments in parentheses + +fn main() {} diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr new file mode 100644 index 0000000000000..78017babbf609 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr @@ -0,0 +1,11 @@ +error: expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->` + --> $DIR/issue-108109-fn-trait-missing-paren.rs:3:34 + | +LL | pub fn func() where F: FnOnce -> () {} + | -------^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{` + | | | + | | help: try adding parentheses + | `Fn` bounds require arguments in parentheses + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/issues/issue-108242-semicolon-recovery.stderr b/tests/ui/parser/issues/issue-108242-semicolon-recovery.stderr index f68d6d5010d6d..e12283b25ad34 100644 --- a/tests/ui/parser/issues/issue-108242-semicolon-recovery.stderr +++ b/tests/ui/parser/issues/issue-108242-semicolon-recovery.stderr @@ -9,5 +9,5 @@ LL | foo(; LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-111148.stderr b/tests/ui/parser/issues/issue-111148.stderr index e6595a5cbcc45..bcfca981d256f 100644 --- a/tests/ui/parser/issues/issue-111148.stderr +++ b/tests/ui/parser/issues/issue-111148.stderr @@ -4,5 +4,5 @@ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `<` LL | fn a<# | ^ expected one of `#`, `>`, `const`, identifier, or lifetime -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-111416.stderr b/tests/ui/parser/issues/issue-111416.stderr index ddacf4d6dfc31..36f6c5b018fe8 100644 --- a/tests/ui/parser/issues/issue-111416.stderr +++ b/tests/ui/parser/issues/issue-111416.stderr @@ -14,5 +14,5 @@ LL - let my = monad_bind(mx, T: Try); LL + let my = monad_bind(mx, Try); | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-113110-non-item-at-module-root.stderr b/tests/ui/parser/issues/issue-113110-non-item-at-module-root.stderr index 0789c4548a08e..a47dd41036997 100644 --- a/tests/ui/parser/issues/issue-113110-non-item-at-module-root.stderr +++ b/tests/ui/parser/issues/issue-113110-non-item-at-module-root.stderr @@ -6,5 +6,5 @@ LL | 5 | = note: for a full list of items that can appear in modules, see -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-113203.stderr b/tests/ui/parser/issues/issue-113203.stderr index 97304a89c9e49..5db628d59776a 100644 --- a/tests/ui/parser/issues/issue-113203.stderr +++ b/tests/ui/parser/issues/issue-113203.stderr @@ -4,5 +4,5 @@ error: incorrect use of `await` LL | await {}() | ^^^^^^^^ help: `await` is a postfix operation: `{}.await` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-113342.stderr b/tests/ui/parser/issues/issue-113342.stderr index a0c5e665ff8f7..6d9f22f6a7ce8 100644 --- a/tests/ui/parser/issues/issue-113342.stderr +++ b/tests/ui/parser/issues/issue-113342.stderr @@ -7,5 +7,5 @@ LL | extern "C" pub fn id(x: i32) -> i32 { x } | | expected `fn` | help: visibility `pub` must come before `extern "C"`: `pub extern "C"` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-114219.stderr b/tests/ui/parser/issues/issue-114219.stderr index 90dcdc427757b..02323cb99cbf3 100644 --- a/tests/ui/parser/issues/issue-114219.stderr +++ b/tests/ui/parser/issues/issue-114219.stderr @@ -4,5 +4,5 @@ error: `async move` blocks are only allowed in Rust 2018 or later LL | async move {}; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-118530-ice.rs b/tests/ui/parser/issues/issue-118530-ice.rs new file mode 100644 index 0000000000000..e758e5af4d9ec --- /dev/null +++ b/tests/ui/parser/issues/issue-118530-ice.rs @@ -0,0 +1,15 @@ +fn bar() -> String { + #[cfg] + [1, 2, 3].iter() //~ ERROR expected `;`, found `#` + #[feature] + attr::fn bar() -> String { //~ ERROR expected identifier, found keyword `fn` + //~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `->` + //~| ERROR expected `;`, found `bar` + #[attr] + [1, 2, 3].iter().map().collect::() + #[attr] + +}() +} + +fn main() { } diff --git a/tests/ui/parser/issues/issue-118530-ice.stderr b/tests/ui/parser/issues/issue-118530-ice.stderr new file mode 100644 index 0000000000000..ef573fb7ba3de --- /dev/null +++ b/tests/ui/parser/issues/issue-118530-ice.stderr @@ -0,0 +1,43 @@ +error: expected `;`, found `#` + --> $DIR/issue-118530-ice.rs:3:21 + | +LL | #[cfg] + | ------ only `;` terminated statements or tail expressions are allowed after this attribute +LL | [1, 2, 3].iter() + | ^ expected `;` here +LL | #[feature] + | - unexpected token + | +help: add `;` here + | +LL | [1, 2, 3].iter(); + | + +help: alternatively, consider surrounding the expression with a block + | +LL | { [1, 2, 3].iter() } + | + + + +error: expected identifier, found keyword `fn` + --> $DIR/issue-118530-ice.rs:5:11 + | +LL | attr::fn bar() -> String { + | ^^ expected identifier, found keyword + +error: expected `;`, found `bar` + --> $DIR/issue-118530-ice.rs:5:13 + | +LL | #[feature] + | ---------- only `;` terminated statements or tail expressions are allowed after this attribute +LL | attr::fn bar() -> String { + | ^--- unexpected token + | | + | help: add `;` here + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `->` + --> $DIR/issue-118530-ice.rs:5:20 + | +LL | attr::fn bar() -> String { + | ^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/issues/issue-118531-ice.rs b/tests/ui/parser/issues/issue-118531-ice.rs new file mode 100644 index 0000000000000..24794f06052c9 --- /dev/null +++ b/tests/ui/parser/issues/issue-118531-ice.rs @@ -0,0 +1,10 @@ +fn bar() -> String { + #[cfg(feature = )] + [1, 2, 3].iter().map().collect::() //~ ERROR expected `;`, found `#` + + #[attr] //~ ERROR attributes on expressions are experimental [E0658] + //~^ ERROR cannot find attribute `attr` in this scope + String::new() +} + +fn main() { } diff --git a/tests/ui/parser/issues/issue-118531-ice.stderr b/tests/ui/parser/issues/issue-118531-ice.stderr new file mode 100644 index 0000000000000..a32292dcb0de5 --- /dev/null +++ b/tests/ui/parser/issues/issue-118531-ice.stderr @@ -0,0 +1,38 @@ +error: expected `;`, found `#` + --> $DIR/issue-118531-ice.rs:3:47 + | +LL | #[cfg(feature = )] + | ------------------ only `;` terminated statements or tail expressions are allowed after this attribute +LL | [1, 2, 3].iter().map().collect::() + | ^ expected `;` here +LL | +LL | #[attr] + | - unexpected token + | +help: add `;` here + | +LL | [1, 2, 3].iter().map().collect::(); + | + +help: alternatively, consider surrounding the expression with a block + | +LL | { [1, 2, 3].iter().map().collect::() } + | + + + +error[E0658]: attributes on expressions are experimental + --> $DIR/issue-118531-ice.rs:5:5 + | +LL | #[attr] + | ^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: cannot find attribute `attr` in this scope + --> $DIR/issue-118531-ice.rs:5:7 + | +LL | #[attr] + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/parser/issues/issue-14303-fncall.full.stderr b/tests/ui/parser/issues/issue-14303-fncall.full.stderr index 0c152516abcf4..1986f70bf672d 100644 --- a/tests/ui/parser/issues/issue-14303-fncall.full.stderr +++ b/tests/ui/parser/issues/issue-14303-fncall.full.stderr @@ -4,6 +4,6 @@ error[E0747]: type provided when a lifetime was expected LL | .collect::>>(); | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr b/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr index 57181577600bc..2de59b8c746c2 100644 --- a/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr +++ b/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr @@ -4,6 +4,6 @@ error[E0747]: inferred provided when a lifetime was expected LL | .collect::>>(); | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/parser/issues/issue-15914.stderr b/tests/ui/parser/issues/issue-15914.stderr index ea26453f80897..c88fd4e55e26e 100644 --- a/tests/ui/parser/issues/issue-15914.stderr +++ b/tests/ui/parser/issues/issue-15914.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `(` LL | (); | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-15980.stderr b/tests/ui/parser/issues/issue-15980.stderr index cf8d011478766..c3c56c46a6d55 100644 --- a/tests/ui/parser/issues/issue-15980.stderr +++ b/tests/ui/parser/issues/issue-15980.stderr @@ -16,5 +16,5 @@ help: you might have meant to start a match arm after the match guard LL | Err(ref e) if e.kind == io::EndOfFile => { | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-1655.stderr b/tests/ui/parser/issues/issue-1655.stderr index 0c390a0ec563c..536b583aaa32d 100644 --- a/tests/ui/parser/issues/issue-1655.stderr +++ b/tests/ui/parser/issues/issue-1655.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `[`, found `vec` LL | #vec[doc( | ^^^ expected one of `!` or `[` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-17718-const-mut.stderr b/tests/ui/parser/issues/issue-17718-const-mut.stderr index 8251ce9993fa9..a27f517086efa 100644 --- a/tests/ui/parser/issues/issue-17718-const-mut.stderr +++ b/tests/ui/parser/issues/issue-17718-const-mut.stderr @@ -6,5 +6,5 @@ LL | const LL | mut | ^^^ cannot be mutable -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-17904-2.stderr b/tests/ui/parser/issues/issue-17904-2.stderr index 7185a5e5752c3..211ffcedd582e 100644 --- a/tests/ui/parser/issues/issue-17904-2.stderr +++ b/tests/ui/parser/issues/issue-17904-2.stderr @@ -6,5 +6,5 @@ LL | struct Bar { x: T } where T: Copy | = note: for a full list of items that can appear in modules, see -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-17904.stderr b/tests/ui/parser/issues/issue-17904.stderr index aa343975dcac5..81c6e3bed1cbc 100644 --- a/tests/ui/parser/issues/issue-17904.stderr +++ b/tests/ui/parser/issues/issue-17904.stderr @@ -13,5 +13,5 @@ LL - struct Foo where T: Copy, (T); LL + struct Foo(T) where T: Copy; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-1802-1.stderr b/tests/ui/parser/issues/issue-1802-1.stderr index 954cc0beeef3e..5ddc5ae58d9df 100644 --- a/tests/ui/parser/issues/issue-1802-1.stderr +++ b/tests/ui/parser/issues/issue-1802-1.stderr @@ -4,6 +4,6 @@ error[E0768]: no valid digits found for number LL | log(error, 0b); | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0768`. diff --git a/tests/ui/parser/issues/issue-1802-2.stderr b/tests/ui/parser/issues/issue-1802-2.stderr index 49043d07b35eb..7c802e4bdf7b6 100644 --- a/tests/ui/parser/issues/issue-1802-2.stderr +++ b/tests/ui/parser/issues/issue-1802-2.stderr @@ -4,6 +4,6 @@ error[E0768]: no valid digits found for number LL | log(error, 0b); | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0768`. diff --git a/tests/ui/parser/issues/issue-19398.stderr b/tests/ui/parser/issues/issue-19398.stderr index 1da00960adfe4..236fac673b6b3 100644 --- a/tests/ui/parser/issues/issue-19398.stderr +++ b/tests/ui/parser/issues/issue-19398.stderr @@ -9,5 +9,5 @@ LL | LL | } | - the item list ends here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-1.stderr b/tests/ui/parser/issues/issue-20616-1.stderr index 816046237854a..b7a8d22d8ff09 100644 --- a/tests/ui/parser/issues/issue-20616-1.stderr +++ b/tests/ui/parser/issues/issue-20616-1.stderr @@ -4,5 +4,5 @@ error: expected one of `,`, `:`, or `>`, found `T` LL | type Type_1<'a T> = &'a T; | ^ expected one of `,`, `:`, or `>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-2.stderr b/tests/ui/parser/issues/issue-20616-2.stderr index 42059685c5cc4..038b2ffc72b39 100644 --- a/tests/ui/parser/issues/issue-20616-2.stderr +++ b/tests/ui/parser/issues/issue-20616-2.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | type Type_2 = Type_1_<'static> ()>; | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-3.stderr b/tests/ui/parser/issues/issue-20616-3.stderr index dbff116e505f2..10e5befe2a749 100644 --- a/tests/ui/parser/issues/issue-20616-3.stderr +++ b/tests/ui/parser/issues/issue-20616-3.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | type Type_3 = Box,,>; | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-4.stderr b/tests/ui/parser/issues/issue-20616-4.stderr index 48a06e00b24dd..df619b4c79b09 100644 --- a/tests/ui/parser/issues/issue-20616-4.stderr +++ b/tests/ui/parser/issues/issue-20616-4.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | type Type_4 = Type_1_<'static>,, T>; | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-5.stderr b/tests/ui/parser/issues/issue-20616-5.stderr index 84bee2ad18425..709a5467deff5 100644 --- a/tests/ui/parser/issues/issue-20616-5.stderr +++ b/tests/ui/parser/issues/issue-20616-5.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | type Type_5<'a> = Type_1_<'a, ()>,,>; | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-6.stderr b/tests/ui/parser/issues/issue-20616-6.stderr index 67de41b9747cb..7fe1f1c456f4f 100644 --- a/tests/ui/parser/issues/issue-20616-6.stderr +++ b/tests/ui/parser/issues/issue-20616-6.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | type Type_6 = Type_5_<'a>,,>; | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-7.stderr b/tests/ui/parser/issues/issue-20616-7.stderr index 3b8e07fa0d05d..d9e97301f5d72 100644 --- a/tests/ui/parser/issues/issue-20616-7.stderr +++ b/tests/ui/parser/issues/issue-20616-7.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | type Type_7 = Box<()>,,>; | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-8.stderr b/tests/ui/parser/issues/issue-20616-8.stderr index e9f37e50fffec..f8d7dc63c94d6 100644 --- a/tests/ui/parser/issues/issue-20616-8.stderr +++ b/tests/ui/parser/issues/issue-20616-8.stderr @@ -4,5 +4,5 @@ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` LL | type Type_8<'a,,> = &'a (); | ^ expected one of `#`, `>`, `const`, identifier, or lifetime -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20616-9.stderr b/tests/ui/parser/issues/issue-20616-9.stderr index dc309d1bce158..5dccacdb61036 100644 --- a/tests/ui/parser/issues/issue-20616-9.stderr +++ b/tests/ui/parser/issues/issue-20616-9.stderr @@ -4,5 +4,5 @@ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` LL | type Type_9 = Box; | ^ expected one of `#`, `>`, `const`, identifier, or lifetime -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20711-2.stderr b/tests/ui/parser/issues/issue-20711-2.stderr index 12b18bbc59416..9fb7298955b38 100644 --- a/tests/ui/parser/issues/issue-20711-2.stderr +++ b/tests/ui/parser/issues/issue-20711-2.stderr @@ -10,5 +10,5 @@ LL | LL | } | - the item list ends here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-20711.stderr b/tests/ui/parser/issues/issue-20711.stderr index 4af4b22bee292..256fb0ade7212 100644 --- a/tests/ui/parser/issues/issue-20711.stderr +++ b/tests/ui/parser/issues/issue-20711.stderr @@ -9,5 +9,5 @@ LL | LL | } | - the item list ends here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-21146.stderr b/tests/ui/parser/issues/issue-21146.stderr index c71fda3d63fe9..e83c62afe799d 100644 --- a/tests/ui/parser/issues/issue-21146.stderr +++ b/tests/ui/parser/issues/issue-21146.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `` LL | parse_error | ^^^^^^^^^^^ expected one of `!` or `::` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-21153.stderr b/tests/ui/parser/issues/issue-21153.stderr index cbfa9ded3c393..8839eed8485f8 100644 --- a/tests/ui/parser/issues/issue-21153.stderr +++ b/tests/ui/parser/issues/issue-21153.stderr @@ -9,5 +9,5 @@ LL | LL | } | - the item list ends here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-22647.stderr b/tests/ui/parser/issues/issue-22647.stderr index 585e70266619a..bdf74af6393e3 100644 --- a/tests/ui/parser/issues/issue-22647.stderr +++ b/tests/ui/parser/issues/issue-22647.stderr @@ -9,5 +9,5 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let caller:: = |f: F| | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-22712.stderr b/tests/ui/parser/issues/issue-22712.stderr index 7f9d99d8edfa1..aeca95ed68ee4 100644 --- a/tests/ui/parser/issues/issue-22712.stderr +++ b/tests/ui/parser/issues/issue-22712.stderr @@ -9,5 +9,5 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let Foo::> | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-2354-1.stderr b/tests/ui/parser/issues/issue-2354-1.stderr index 7ea0f2a982855..edd64ecf31e02 100644 --- a/tests/ui/parser/issues/issue-2354-1.stderr +++ b/tests/ui/parser/issues/issue-2354-1.stderr @@ -4,5 +4,5 @@ error: unexpected closing delimiter: `}` LL | static foo: isize = 2; } | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-2354.stderr b/tests/ui/parser/issues/issue-2354.stderr index b89ed3958357d..fd649a575c6c6 100644 --- a/tests/ui/parser/issues/issue-2354.stderr +++ b/tests/ui/parser/issues/issue-2354.stderr @@ -12,5 +12,5 @@ LL | } LL | | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-24197.stderr b/tests/ui/parser/issues/issue-24197.stderr index fd7015ccd3907..3ef707f3953cf 100644 --- a/tests/ui/parser/issues/issue-24197.stderr +++ b/tests/ui/parser/issues/issue-24197.stderr @@ -4,5 +4,5 @@ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` LL | let buf[0] = 0; | ^ expected one of `:`, `;`, `=`, `@`, or `|` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-24375.rs b/tests/ui/parser/issues/issue-24375.rs index 1d128d33e4f49..8d1bc579e7b84 100644 --- a/tests/ui/parser/issues/issue-24375.rs +++ b/tests/ui/parser/issues/issue-24375.rs @@ -3,7 +3,7 @@ static tmp : [&'static str; 2] = ["hello", "he"]; fn main() { let z = "hello"; match z { - tmp[0] => {} //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `[` + tmp[0] => {} //~ ERROR expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `[` _ => {} } } diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index 7aed88768a074..2b980a5520fdb 100644 --- a/tests/ui/parser/issues/issue-24375.stderr +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -1,8 +1,8 @@ -error: expected one of `=>`, `@`, `if`, or `|`, found `[` +error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `[` --> $DIR/issue-24375.rs:6:12 | LL | tmp[0] => {} - | ^ expected one of `=>`, `@`, `if`, or `|` + | ^ expected one of `,`, `=>`, `@`, `if`, `|`, or `}` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-24780.stderr b/tests/ui/parser/issues/issue-24780.stderr index d9470191b25a4..43e2001022591 100644 --- a/tests/ui/parser/issues/issue-24780.stderr +++ b/tests/ui/parser/issues/issue-24780.stderr @@ -4,5 +4,5 @@ error: expected one of `!`, `+`, `::`, `where`, or `{`, found `>` LL | fn foo() -> Vec> { | ^ expected one of `!`, `+`, `::`, `where`, or `{` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-3036.stderr b/tests/ui/parser/issues/issue-3036.stderr index e02223931c114..3dd89b7e828df 100644 --- a/tests/ui/parser/issues/issue-3036.stderr +++ b/tests/ui/parser/issues/issue-3036.stderr @@ -6,5 +6,5 @@ LL | let _x = 3 LL | } | - unexpected token -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-31804.stderr b/tests/ui/parser/issues/issue-31804.stderr index 76e68b0b3524d..d3d2c2a0f9e94 100644 --- a/tests/ui/parser/issues/issue-31804.stderr +++ b/tests/ui/parser/issues/issue-31804.stderr @@ -4,5 +4,5 @@ error: expected pattern, found `}` LL | } | ^ expected pattern -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-32214.stderr b/tests/ui/parser/issues/issue-32214.stderr index d0a9b529983b1..2ef4305dfd0e8 100644 --- a/tests/ui/parser/issues/issue-32214.stderr +++ b/tests/ui/parser/issues/issue-32214.stderr @@ -11,5 +11,5 @@ help: move the constraint after the generic argument LL | pub fn test >() {} | ~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-32446.stderr b/tests/ui/parser/issues/issue-32446.stderr index 7515369aaa0b9..7319e839b934a 100644 --- a/tests/ui/parser/issues/issue-32446.stderr +++ b/tests/ui/parser/issues/issue-32446.stderr @@ -7,5 +7,5 @@ LL | trait T { ... } | | non-item starts here | item list starts here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-32501.stderr b/tests/ui/parser/issues/issue-32501.stderr index d53302449a806..c0513a64039e6 100644 --- a/tests/ui/parser/issues/issue-32501.stderr +++ b/tests/ui/parser/issues/issue-32501.stderr @@ -2,9 +2,9 @@ error: `mut` must be followed by a named binding --> $DIR/issue-32501.rs:7:9 | LL | let mut _ = 0; - | ^^^^^ help: remove the `mut` prefix: `_` + | ^^^^ help: remove the `mut` prefix | = note: `mut` may be followed by `variable` and `variable @ pattern` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-33262.stderr b/tests/ui/parser/issues/issue-33262.stderr index 2aff328393538..ec4934eb7221c 100644 --- a/tests/ui/parser/issues/issue-33262.stderr +++ b/tests/ui/parser/issues/issue-33262.stderr @@ -4,5 +4,5 @@ error: expected type, found `{` LL | for i in 0..a as { } | ^ expected type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-33455.stderr b/tests/ui/parser/issues/issue-33455.stderr index c535ef23b2296..573614a5e995a 100644 --- a/tests/ui/parser/issues/issue-33455.stderr +++ b/tests/ui/parser/issues/issue-33455.stderr @@ -4,5 +4,5 @@ error: expected one of `::`, `;`, or `as`, found `.` LL | use foo.bar; | ^ expected one of `::`, `;`, or `as` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-34222-1.stderr b/tests/ui/parser/issues/issue-34222-1.stderr index b451484ba224b..b2a6ae93a45d6 100644 --- a/tests/ui/parser/issues/issue-34222-1.stderr +++ b/tests/ui/parser/issues/issue-34222-1.stderr @@ -6,6 +6,6 @@ LL | /// comment | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/issues/issue-34255-1.stderr b/tests/ui/parser/issues/issue-34255-1.stderr index 0e2b0d62ef6d3..1e72f040b0366 100644 --- a/tests/ui/parser/issues/issue-34255-1.stderr +++ b/tests/ui/parser/issues/issue-34255-1.stderr @@ -14,5 +14,5 @@ LL - Test::Drill(field: 42); LL + Test::Drill(42); | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-39616.stderr b/tests/ui/parser/issues/issue-39616.stderr index 393d1f2e2ce67..da85bcb446cc3 100644 --- a/tests/ui/parser/issues/issue-39616.stderr +++ b/tests/ui/parser/issues/issue-39616.stderr @@ -4,5 +4,5 @@ error: expected type, found `0` LL | fn foo(a: [0; 1]) {} | ^ expected type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-43692.stderr b/tests/ui/parser/issues/issue-43692.stderr index baf998035178b..1ce3aa6713593 100644 --- a/tests/ui/parser/issues/issue-43692.stderr +++ b/tests/ui/parser/issues/issue-43692.stderr @@ -4,5 +4,5 @@ error: invalid start of unicode escape: `_` LL | '\u{_10FFFF}'; | ^ invalid start of unicode escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-44021.stderr b/tests/ui/parser/issues/issue-44021.stderr index b888cd989a67c..8a9326f90c681 100644 --- a/tests/ui/parser/issues/issue-44021.stderr +++ b/tests/ui/parser/issues/issue-44021.stderr @@ -4,5 +4,5 @@ error: expected one of `:`, `@`, or `|`, found `}` LL | fn f() {|x, y} | ^ expected one of `:`, `@`, or `|` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-44406.stderr b/tests/ui/parser/issues/issue-44406.stderr index 69ff64c2772de..d005f116e124b 100644 --- a/tests/ui/parser/issues/issue-44406.stderr +++ b/tests/ui/parser/issues/issue-44406.stderr @@ -18,5 +18,5 @@ LL - bar(baz: $rest) LL + bar(: $rest) | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-45296.stderr b/tests/ui/parser/issues/issue-45296.stderr index 081a72054e8da..1d2281df108d9 100644 --- a/tests/ui/parser/issues/issue-45296.stderr +++ b/tests/ui/parser/issues/issue-45296.stderr @@ -13,5 +13,5 @@ LL - #![allow(unused_variables)] LL + #[allow(unused_variables)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-46186.stderr b/tests/ui/parser/issues/issue-46186.stderr index 0766c8a33df14..c67c271e19ae5 100644 --- a/tests/ui/parser/issues/issue-46186.stderr +++ b/tests/ui/parser/issues/issue-46186.stderr @@ -6,5 +6,5 @@ LL | }; | = help: braced struct declarations are not followed by a semicolon -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-48508.rs b/tests/ui/parser/issues/issue-48508.rs index 1e7db9df814b4..b66e09620f4eb 100644 --- a/tests/ui/parser/issues/issue-48508.rs +++ b/tests/ui/parser/issues/issue-48508.rs @@ -7,7 +7,6 @@ // issue-48508-aux.rs // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet #![allow(uncommon_codepoints)] diff --git a/tests/ui/parser/issues/issue-48636.stderr b/tests/ui/parser/issues/issue-48636.stderr index 6177870d1cee9..488a046a54900 100644 --- a/tests/ui/parser/issues/issue-48636.stderr +++ b/tests/ui/parser/issues/issue-48636.stderr @@ -10,6 +10,6 @@ LL | /// The ID of the parent core | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/issues/issue-51602.stderr b/tests/ui/parser/issues/issue-51602.stderr index 4a5653fdb513e..7b50e0ad0fae5 100644 --- a/tests/ui/parser/issues/issue-51602.stderr +++ b/tests/ui/parser/issues/issue-51602.stderr @@ -10,5 +10,5 @@ note: the `if` expression is missing a block after this condition LL | if i in 1..10 { | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-5544-a.stderr b/tests/ui/parser/issues/issue-5544-a.stderr index 6e68c75850afe..aeb13460092b5 100644 --- a/tests/ui/parser/issues/issue-5544-a.stderr +++ b/tests/ui/parser/issues/issue-5544-a.stderr @@ -6,5 +6,5 @@ LL | let __isize = 340282366920938463463374607431768211456; // 2^128 | = note: value exceeds limit of `340282366920938463463374607431768211455` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-5544-b.stderr b/tests/ui/parser/issues/issue-5544-b.stderr index 5d0e76d5d9445..65e6f196b0910 100644 --- a/tests/ui/parser/issues/issue-5544-b.stderr +++ b/tests/ui/parser/issues/issue-5544-b.stderr @@ -6,5 +6,5 @@ LL | let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff; | = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-56031.stderr b/tests/ui/parser/issues/issue-56031.stderr index 2fa05dd2dfbb3..8031bf82fd1ac 100644 --- a/tests/ui/parser/issues/issue-56031.stderr +++ b/tests/ui/parser/issues/issue-56031.stderr @@ -14,5 +14,5 @@ LL - impl for T {} LL + impl T {} | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-57198.stderr b/tests/ui/parser/issues/issue-57198.stderr index dd70b40224cef..dca0d3ea48632 100644 --- a/tests/ui/parser/issues/issue-57198.stderr +++ b/tests/ui/parser/issues/issue-57198.stderr @@ -9,5 +9,5 @@ help: escape `for` to use it as an identifier LL | m::r#for(); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-5806.stderr b/tests/ui/parser/issues/issue-5806.stderr index bdb5c91ff91eb..4b025bd19a048 100644 --- a/tests/ui/parser/issues/issue-5806.stderr +++ b/tests/ui/parser/issues/issue-5806.stderr @@ -4,5 +4,5 @@ error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED LL | mod foo; | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs index a596a9f2de3a2..a2ea8ad368baa 100644 --- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs @@ -1,5 +1,5 @@ // Fixed in #66054. // ignore-tidy-trailing-newlines // error-pattern: this file contains an unclosed delimiter -// error-pattern: aborting due to previous error +// error-pattern: aborting due to 1 previous error #[Ѕ \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr index c79e8b4fb7082..14f5469f6af94 100644 --- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr @@ -6,5 +6,5 @@ LL | #[Ѕ | | | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-58856-1.stderr b/tests/ui/parser/issues/issue-58856-1.stderr index 77ad8acbd43b5..2c33343919789 100644 --- a/tests/ui/parser/issues/issue-58856-1.stderr +++ b/tests/ui/parser/issues/issue-58856-1.stderr @@ -8,5 +8,5 @@ LL | fn b(self> LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-58856-2.stderr b/tests/ui/parser/issues/issue-58856-2.stderr index 5fcf5bcc17e83..d3255fca02104 100644 --- a/tests/ui/parser/issues/issue-58856-2.stderr +++ b/tests/ui/parser/issues/issue-58856-2.stderr @@ -9,5 +9,5 @@ LL | fn how_are_you(&self -> Empty { LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-60075.stderr b/tests/ui/parser/issues/issue-60075.stderr index cd8f1231fad0a..b40412aba5586 100644 --- a/tests/ui/parser/issues/issue-60075.stderr +++ b/tests/ui/parser/issues/issue-60075.stderr @@ -7,5 +7,5 @@ LL | let _ = if true { LL | }); | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-61858.stderr b/tests/ui/parser/issues/issue-61858.stderr index 03f51c6e3a8f4..6bdfec9384ecb 100644 --- a/tests/ui/parser/issues/issue-61858.stderr +++ b/tests/ui/parser/issues/issue-61858.stderr @@ -10,5 +10,5 @@ note: the `if` expression is missing a block after this condition LL | (if foobar) | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs index fa7c626f5cc12..dd86fc9a7f851 100644 --- a/tests/ui/parser/issues/issue-62524.rs +++ b/tests/ui/parser/issues/issue-62524.rs @@ -1,5 +1,5 @@ // ignore-tidy-trailing-newlines -// error-pattern: aborting due to previous error +// error-pattern: aborting due to 1 previous error #![allow(uncommon_codepoints)] y![ diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr index 0cbaacd4c64be..d83a49aedd6e8 100644 --- a/tests/ui/parser/issues/issue-62524.stderr +++ b/tests/ui/parser/issues/issue-62524.stderr @@ -6,5 +6,5 @@ LL | y![ LL | Ϥ, | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62546.stderr b/tests/ui/parser/issues/issue-62546.stderr index 80c1c71689d15..6889cb3b8e9d2 100644 --- a/tests/ui/parser/issues/issue-62546.stderr +++ b/tests/ui/parser/issues/issue-62546.stderr @@ -4,5 +4,5 @@ error: this file contains an unclosed delimiter LL | pub t(# | - unclosed delimiter ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr index 4637c795ae5ec..37314dd39c7fd 100644 --- a/tests/ui/parser/issues/issue-62554.stderr +++ b/tests/ui/parser/issues/issue-62554.stderr @@ -9,5 +9,5 @@ LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s | | | unclosed delimiter | unclosed delimiter unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62660.stderr b/tests/ui/parser/issues/issue-62660.stderr index 14c0bdcb111b8..310b433f2dfc2 100644 --- a/tests/ui/parser/issues/issue-62660.stderr +++ b/tests/ui/parser/issues/issue-62660.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | pub fn foo(_: i32, self: Box) {} | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62881.stderr b/tests/ui/parser/issues/issue-62881.stderr index e57cbd1810a47..2165a81a0482d 100644 --- a/tests/ui/parser/issues/issue-62881.stderr +++ b/tests/ui/parser/issues/issue-62881.stderr @@ -4,5 +4,5 @@ error: this file contains an unclosed delimiter LL | fn f() -> isize { fn f() -> isize {} pub f< | - unclosed delimiter ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62894.stderr b/tests/ui/parser/issues/issue-62894.stderr index 700479076dfe8..870633fc96f85 100644 --- a/tests/ui/parser/issues/issue-62894.stderr +++ b/tests/ui/parser/issues/issue-62894.stderr @@ -10,5 +10,5 @@ LL | LL | fn main() {} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-63135.rs b/tests/ui/parser/issues/issue-63135.rs index d61197dc566ac..2e1ac080bc5f7 100644 --- a/tests/ui/parser/issues/issue-63135.rs +++ b/tests/ui/parser/issues/issue-63135.rs @@ -1,3 +1,3 @@ // error-pattern: this file contains an unclosed delimiter -// error-pattern: aborting due to previous error +// error-pattern: aborting due to 1 previous error fn i(n{...,f # diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr index ff9d99c28fe7d..9204f561e965f 100644 --- a/tests/ui/parser/issues/issue-63135.stderr +++ b/tests/ui/parser/issues/issue-63135.stderr @@ -7,5 +7,5 @@ LL | fn i(n{...,f # | | unclosed delimiter | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr index 8c032e588e31d..2bd87ee0c38fa 100644 --- a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr +++ b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr @@ -2,7 +2,7 @@ error: `mut` must be followed by a named binding --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:13 | LL | let mut $eval = (); - | ^^^^^^^^^ help: remove the `mut` prefix: `does_not_exist!()` + | ^^^^ help: remove the `mut` prefix ... LL | mac1! { does_not_exist!() } | --------------------------- in this macro invocation @@ -25,7 +25,7 @@ error: `mut` must be followed by a named binding --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:13 | LL | let mut $eval = (); - | ^^^ help: remove the `mut` prefix: `does_not_exist!()` + | ^^^ help: remove the `mut` prefix ... LL | mac2! { does_not_exist!() } | --------------------------- in this macro invocation diff --git a/tests/ui/parser/issues/issue-6610.stderr b/tests/ui/parser/issues/issue-6610.stderr index 4a3bc752553b9..83fc029967c57 100644 --- a/tests/ui/parser/issues/issue-6610.stderr +++ b/tests/ui/parser/issues/issue-6610.stderr @@ -6,5 +6,5 @@ LL | trait Foo { fn a() } | | | while parsing this `fn` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr index 079fff37ea4f8..a265cbf70a659 100644 --- a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr +++ b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr @@ -7,5 +7,5 @@ LL | fn f() { |[](* } | | unclosed delimiter | closing delimiter possibly meant for this -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-68091-unicode-ident-after-if.stderr b/tests/ui/parser/issues/issue-68091-unicode-ident-after-if.stderr index 6674b924e9c4b..2423a7526be13 100644 --- a/tests/ui/parser/issues/issue-68091-unicode-ident-after-if.stderr +++ b/tests/ui/parser/issues/issue-68091-unicode-ident-after-if.stderr @@ -6,5 +6,5 @@ LL | $($c)ö* {} | | | expected condition here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr b/tests/ui/parser/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr index 0b9c364f1f1fb..43047ff88020e 100644 --- a/tests/ui/parser/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr +++ b/tests/ui/parser/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr @@ -4,5 +4,5 @@ error: macro expansion ends with an incomplete expression: expected expression LL | $($c)ö* | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-68890.stderr b/tests/ui/parser/issues/issue-68890.stderr index 0d7b53a67c581..43ed69dcf249a 100644 --- a/tests/ui/parser/issues/issue-68890.stderr +++ b/tests/ui/parser/issues/issue-68890.stderr @@ -8,7 +8,11 @@ error: expected one of `)`, `+`, or `,`, found `a` --> $DIR/issue-68890.rs:1:15 | LL | enum e{A((?'a a+?+l))} - | ^ expected one of `)`, `+`, or `,` + | - ^ expected one of `)`, `+`, or `,` + | | + | while parsing this enum + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` error: expected item, found `)` --> $DIR/issue-68890.rs:1:21 diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-1.stderr b/tests/ui/parser/issues/issue-68987-unmatch-issue-1.stderr index 2d873b46193ce..5b5d45a7e8724 100644 --- a/tests/ui/parser/issues/issue-68987-unmatch-issue-1.stderr +++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-1.stderr @@ -12,5 +12,5 @@ LL | } LL | } | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue.stderr b/tests/ui/parser/issues/issue-68987-unmatch-issue.stderr index cabd133242f60..782b85f09404d 100644 --- a/tests/ui/parser/issues/issue-68987-unmatch-issue.stderr +++ b/tests/ui/parser/issues/issue-68987-unmatch-issue.stderr @@ -12,5 +12,5 @@ LL | } LL | } | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-69259.stderr b/tests/ui/parser/issues/issue-69259.stderr index 604b7de331946..a8487b5f4bec4 100644 --- a/tests/ui/parser/issues/issue-69259.stderr +++ b/tests/ui/parser/issues/issue-69259.stderr @@ -4,5 +4,5 @@ error: unexpected closing delimiter: `)` LL | fn f) {} | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr b/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr index f03c92e1b1f17..14cf52ce672ac 100644 --- a/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr +++ b/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr @@ -4,5 +4,5 @@ error: expected expression, found `:` LL | expr as fun()(:); | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr b/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr index 46cbb056d1d88..c4621b2b84adf 100644 --- a/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr +++ b/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr @@ -9,5 +9,5 @@ LL | } LL | } | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr b/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr index c590e04bb3ded..a21cd4875f6a6 100644 --- a/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr +++ b/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr @@ -12,5 +12,5 @@ LL | ErrorHandled::Reported => {}} LL | } | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-72253.stderr b/tests/ui/parser/issues/issue-72253.stderr index 477fa09f495e2..c4fc662f5d9e7 100644 --- a/tests/ui/parser/issues/issue-72253.stderr +++ b/tests/ui/parser/issues/issue-72253.stderr @@ -6,5 +6,5 @@ LL | .arg("1") LL | ,arg("2") | ^ unexpected token -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-72373.stderr b/tests/ui/parser/issues/issue-72373.stderr index 0bb99a01e55a3..c596c6abda553 100644 --- a/tests/ui/parser/issues/issue-72373.stderr +++ b/tests/ui/parser/issues/issue-72373.stderr @@ -9,5 +9,5 @@ help: if you meant to bind the contents of the rest of the array pattern into `t LL | [h, ref ts @ ..] => foo(c, n - h) + foo(ts, n), | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76437-async.stderr b/tests/ui/parser/issues/issue-76437-async.stderr index 2c9c2a8cfba9b..7f2df5c873643 100644 --- a/tests/ui/parser/issues/issue-76437-async.stderr +++ b/tests/ui/parser/issues/issue-76437-async.stderr @@ -7,5 +7,5 @@ LL | async pub fn t() {} | | expected one of `extern`, `fn`, or `unsafe` | help: visibility `pub` must come before `async`: `pub async` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76437-const-async-unsafe.stderr b/tests/ui/parser/issues/issue-76437-const-async-unsafe.stderr index 2e91beda1165d..a703fc4e8a452 100644 --- a/tests/ui/parser/issues/issue-76437-const-async-unsafe.stderr +++ b/tests/ui/parser/issues/issue-76437-const-async-unsafe.stderr @@ -7,5 +7,5 @@ LL | const async unsafe pub fn t() {} | | expected one of `extern` or `fn` | help: visibility `pub` must come before `const async unsafe`: `pub const async unsafe` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76437-const-async.stderr b/tests/ui/parser/issues/issue-76437-const-async.stderr index 21b96c14d7de0..a9acccdce1824 100644 --- a/tests/ui/parser/issues/issue-76437-const-async.stderr +++ b/tests/ui/parser/issues/issue-76437-const-async.stderr @@ -7,5 +7,5 @@ LL | const async pub fn t() {} | | expected one of `extern`, `fn`, or `unsafe` | help: visibility `pub` must come before `const async`: `pub const async` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76437-const.stderr b/tests/ui/parser/issues/issue-76437-const.stderr index cf80d9a9037c9..4c36d773d60e6 100644 --- a/tests/ui/parser/issues/issue-76437-const.stderr +++ b/tests/ui/parser/issues/issue-76437-const.stderr @@ -7,5 +7,5 @@ LL | const pub fn t() {} | | expected one of `async`, `extern`, `fn`, or `unsafe` | help: visibility `pub` must come before `const`: `pub const` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr b/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr index fa8f13721c894..4ea76179be3f6 100644 --- a/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr +++ b/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr @@ -7,5 +7,5 @@ LL | unsafe pub(crate) fn t() {} | | expected one of `extern` or `fn` | help: visibility `pub(crate)` must come before `unsafe`: `pub(crate) unsafe` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76437-unsafe.stderr b/tests/ui/parser/issues/issue-76437-unsafe.stderr index c63292ef85395..69f7927750bf0 100644 --- a/tests/ui/parser/issues/issue-76437-unsafe.stderr +++ b/tests/ui/parser/issues/issue-76437-unsafe.stderr @@ -7,5 +7,5 @@ LL | unsafe pub fn t() {} | | expected one of `extern` or `fn` | help: visibility `pub` must come before `unsafe`: `pub unsafe` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76597.stderr b/tests/ui/parser/issues/issue-76597.stderr index 50b23329f0ceb..25858981cff0f 100644 --- a/tests/ui/parser/issues/issue-76597.stderr +++ b/tests/ui/parser/issues/issue-76597.stderr @@ -9,5 +9,5 @@ LL | ... x: u8 LL | ... y: u8, | ^ unexpected token -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-7970b.stderr b/tests/ui/parser/issues/issue-7970b.stderr index a62226a8a4de2..b23b09e752ce0 100644 --- a/tests/ui/parser/issues/issue-7970b.stderr +++ b/tests/ui/parser/issues/issue-7970b.stderr @@ -4,5 +4,5 @@ error: unexpected end of macro invocation LL | macro_rules! test {} | ^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-81806.stderr b/tests/ui/parser/issues/issue-81806.stderr index 40873388dfb8a..f1287b82fa57e 100644 --- a/tests/ui/parser/issues/issue-81806.stderr +++ b/tests/ui/parser/issues/issue-81806.stderr @@ -13,5 +13,5 @@ help: escape `impl` to use it as an identifier LL | r#impl | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-83639.stderr b/tests/ui/parser/issues/issue-83639.stderr index 4c10df1917c9f..87218a4487b9d 100644 --- a/tests/ui/parser/issues/issue-83639.stderr +++ b/tests/ui/parser/issues/issue-83639.stderr @@ -4,5 +4,5 @@ error: expected one of `.`, `;`, `?`, `}`, or an operator, found `" "` LL | """ " | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-84104.stderr b/tests/ui/parser/issues/issue-84104.stderr index 7ad59f8450efa..e866d39226751 100644 --- a/tests/ui/parser/issues/issue-84104.stderr +++ b/tests/ui/parser/issues/issue-84104.stderr @@ -6,5 +6,5 @@ LL | #[i=i::<ښܖ< | | | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-84148-2.stderr b/tests/ui/parser/issues/issue-84148-2.stderr index 20761180e77c4..d9b6b336a2ce8 100644 --- a/tests/ui/parser/issues/issue-84148-2.stderr +++ b/tests/ui/parser/issues/issue-84148-2.stderr @@ -6,5 +6,5 @@ LL | fn f(t:for<>t? | | | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-8537.stderr b/tests/ui/parser/issues/issue-8537.stderr index 523cc9dc588f4..0d636bd28a50b 100644 --- a/tests/ui/parser/issues/issue-8537.stderr +++ b/tests/ui/parser/issues/issue-8537.stderr @@ -6,6 +6,6 @@ LL | "invalid-ab_isize" | = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/parser/issues/issue-86895.stderr b/tests/ui/parser/issues/issue-86895.stderr index 575d857c0ed4f..dcde7242d3987 100644 --- a/tests/ui/parser/issues/issue-86895.stderr +++ b/tests/ui/parser/issues/issue-86895.stderr @@ -4,5 +4,5 @@ error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` LL | const pub () {} | ^^^ expected one of `async`, `extern`, `fn`, or `unsafe` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs index df0cd54399a53..099178a7d50f8 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs @@ -7,3 +7,8 @@ const async const fn test() {} //~| NOTE expected one of `extern`, `fn`, or `unsafe` //~| HELP `const` already used earlier, remove this one //~| NOTE `const` first seen here +//~| ERROR functions cannot be both `const` and `async` +//~| NOTE `const` because of this +//~| NOTE `async` because of this + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr index 977c6ebfef352..4c55179ce2379 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr @@ -13,5 +13,14 @@ note: `const` first seen here LL | const async const fn test() {} | ^^^^^ -error: aborting due to previous error +error: functions cannot be both `const` and `async` + --> $DIR/const-async-const.rs:5:1 + | +LL | const async const fn test() {} + | ^^^^^-^^^^^------------------- + | | | + | | `async` because of this + | `const` because of this + +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/recovery.rs b/tests/ui/parser/issues/issue-87217-keyword-order/recovery.rs new file mode 100644 index 0000000000000..9d7fe43893e76 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/recovery.rs @@ -0,0 +1,22 @@ +// test for #115714 + +struct Misplaced; + +impl Misplaced { + unsafe const fn from_u32(val: u32) {} + //~^ ERROR expected one of `extern` or `fn` + fn oof(self){} +} + +struct Duplicated; + +impl Duplicated { + unsafe unsafe fn from_u32(val: u32) {} + //~^ ERROR expected one of `extern` or `fn` + fn oof(self){} +} + +fn main() { + Misplaced.oof(); + Duplicated.oof(); +} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/recovery.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/recovery.stderr new file mode 100644 index 0000000000000..3f504a9ebfc49 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/recovery.stderr @@ -0,0 +1,28 @@ +error: expected one of `extern` or `fn`, found keyword `const` + --> $DIR/recovery.rs:6:12 + | +LL | unsafe const fn from_u32(val: u32) {} + | -------^^^^^ + | | | + | | expected one of `extern` or `fn` + | help: `const` must come before `unsafe`: `const unsafe` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: expected one of `extern` or `fn`, found keyword `unsafe` + --> $DIR/recovery.rs:14:12 + | +LL | unsafe unsafe fn from_u32(val: u32) {} + | ^^^^^^ + | | + | expected one of `extern` or `fn` + | help: `unsafe` already used earlier, remove this one + | +note: `unsafe` first seen here + --> $DIR/recovery.rs:14:5 + | +LL | unsafe unsafe fn from_u32(val: u32) {} + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs index bbebc99e94b82..479426626858b 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs @@ -12,3 +12,8 @@ async unsafe const fn test() {} //~| HELP `const` must come before `async unsafe` //~| SUGGESTION const async unsafe //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` +//~| ERROR functions cannot be both `const` and `async` +//~| NOTE `const` because of this +//~| NOTE `async` because of this + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr index f455caba158c7..489e8eefb052e 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr +++ b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr @@ -9,5 +9,14 @@ LL | async unsafe const fn test() {} | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` -error: aborting due to previous error +error: functions cannot be both `const` and `async` + --> $DIR/several-kw-jump.rs:9:1 + | +LL | async unsafe const fn test() {} + | ^^^^^--------^^^^^------------- + | | | + | | `const` because of this + | `async` because of this + +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs index 4ff4cf5c8ca87..867f71c12040e 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs @@ -12,3 +12,5 @@ unsafe async fn test() {} //~| HELP `async` must come before `unsafe` //~| SUGGESTION async unsafe //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr index e9eb14bf00e77..74989502e7f5d 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr @@ -9,5 +9,5 @@ LL | unsafe async fn test() {} | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs index 2f5fbc513ee36..9a7f28210f930 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs @@ -12,3 +12,5 @@ unsafe const fn test() {} //~| HELP `const` must come before `unsafe` //~| SUGGESTION const unsafe //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr index 0d2bc3472965f..5958f0c7d2ddd 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr @@ -9,5 +9,5 @@ LL | unsafe const fn test() {} | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs index df2412e3e9b32..8305ff4f62387 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs @@ -12,3 +12,5 @@ extern unsafe fn test() {} //~| HELP `unsafe` must come before `extern` //~| SUGGESTION unsafe extern //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr index 4224713ccb53a..0e9f7c51e1a45 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr @@ -9,5 +9,5 @@ LL | extern unsafe fn test() {} | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr b/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr index 8d242bc9de585..a210238652abb 100644 --- a/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr +++ b/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr @@ -13,5 +13,5 @@ note: explicit visibility first seen here LL | pub const pub fn test() {} | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr b/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr index 94c6a29efcb3b..6f686a7e50437 100644 --- a/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr +++ b/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr @@ -7,5 +7,5 @@ LL | const pub fn test() {} | | expected one of `async`, `extern`, `fn`, or `unsafe` | help: visibility `pub` must come before `const`: `pub const` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-87812-path.stderr b/tests/ui/parser/issues/issue-87812-path.stderr index d045f4821ff35..fbe26ea39595a 100644 --- a/tests/ui/parser/issues/issue-87812-path.stderr +++ b/tests/ui/parser/issues/issue-87812-path.stderr @@ -11,6 +11,6 @@ LL | foo!(Baz); | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-87812.stderr b/tests/ui/parser/issues/issue-87812.stderr index d61ee23a50b5b..35dc66a528a99 100644 --- a/tests/ui/parser/issues/issue-87812.stderr +++ b/tests/ui/parser/issues/issue-87812.stderr @@ -18,5 +18,5 @@ help: wrap this expression in parentheses LL | break '_l ($f); | + + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr index 836f44953d4a8..60ef025fa8bfd 100644 --- a/tests/ui/parser/issues/issue-88770.stderr +++ b/tests/ui/parser/issues/issue-88770.stderr @@ -10,5 +10,5 @@ LL | fn m(){print!("",(c for&g LL | e | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-88818.stderr b/tests/ui/parser/issues/issue-88818.stderr index 6e624c5a284e8..10e0161066d56 100644 --- a/tests/ui/parser/issues/issue-88818.stderr +++ b/tests/ui/parser/issues/issue-88818.stderr @@ -14,5 +14,5 @@ LL - impl for S { } LL + impl S { } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-89388.stderr b/tests/ui/parser/issues/issue-89388.stderr index 366d05c2d9480..d4987234a49e4 100644 --- a/tests/ui/parser/issues/issue-89388.stderr +++ b/tests/ui/parser/issues/issue-89388.stderr @@ -9,5 +9,5 @@ help: types that don't start with an identifier need to be surrounded with angle LL | let _ = option.map(<[_]>::to_vec); | + + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-89574.stderr b/tests/ui/parser/issues/issue-89574.stderr index fb1312c782aab..5f8f6f9396938 100644 --- a/tests/ui/parser/issues/issue-89574.stderr +++ b/tests/ui/parser/issues/issue-89574.stderr @@ -4,5 +4,5 @@ error: missing type for `const` item LL | const EMPTY_ARRAY = []; | ^ help: provide a type for the item: `: ` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr index a5ee244452007..51df17c7cc670 100644 --- a/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr +++ b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr @@ -14,5 +14,5 @@ LL - #![deny(missing_docs)] LL + #[deny(missing_docs)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-91421.stderr b/tests/ui/parser/issues/issue-91421.stderr index 2d9652051dd56..99339a285edee 100644 --- a/tests/ui/parser/issues/issue-91421.stderr +++ b/tests/ui/parser/issues/issue-91421.stderr @@ -10,5 +10,5 @@ help: this binary operation is possibly unfinished LL | let value = if true && { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-93867.stderr b/tests/ui/parser/issues/issue-93867.stderr index ee0cb4efd74c1..c653c8dd4a424 100644 --- a/tests/ui/parser/issues/issue-93867.stderr +++ b/tests/ui/parser/issues/issue-93867.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | pub fn entry<'a, K, V>() -> Entry<'a> K, V> { | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-98601-delimiter-error-1.stderr b/tests/ui/parser/issues/issue-98601-delimiter-error-1.stderr index d568a4c583af1..7dd059c6e3b02 100644 --- a/tests/ui/parser/issues/issue-98601-delimiter-error-1.stderr +++ b/tests/ui/parser/issues/issue-98601-delimiter-error-1.stderr @@ -12,5 +12,5 @@ LL | } LL | } | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.stderr b/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.stderr index 81dd39bb7695c..5e4b4dd3001a5 100644 --- a/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.stderr +++ b/tests/ui/parser/issues/issue-98601-delimiter-error-unexpected-close.stderr @@ -10,5 +10,5 @@ LL | LL | fn other(_: i32)) {} | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-99625-enum-struct-mutually-exclusive.stderr b/tests/ui/parser/issues/issue-99625-enum-struct-mutually-exclusive.stderr index edc640bf5ec22..c503bc3ccfcb7 100644 --- a/tests/ui/parser/issues/issue-99625-enum-struct-mutually-exclusive.stderr +++ b/tests/ui/parser/issues/issue-99625-enum-struct-mutually-exclusive.stderr @@ -4,5 +4,5 @@ error: `enum` and `struct` are mutually exclusive LL | pub enum struct Range { | ^^^^^^^^^^^ help: replace `enum struct` with: `enum` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/recover-ge-as-fat-arrow.fixed b/tests/ui/parser/issues/recover-ge-as-fat-arrow.fixed new file mode 100644 index 0000000000000..7b73dfb02df89 --- /dev/null +++ b/tests/ui/parser/issues/recover-ge-as-fat-arrow.fixed @@ -0,0 +1,7 @@ +// run-rustfix +fn main() { + match 1 { + 1 => {} //~ ERROR + _ => { let _: u16 = 2u16; } //~ ERROR + } +} diff --git a/tests/ui/parser/issues/recover-ge-as-fat-arrow.rs b/tests/ui/parser/issues/recover-ge-as-fat-arrow.rs new file mode 100644 index 0000000000000..92143fcf3f767 --- /dev/null +++ b/tests/ui/parser/issues/recover-ge-as-fat-arrow.rs @@ -0,0 +1,7 @@ +// run-rustfix +fn main() { + match 1 { + 1 >= {} //~ ERROR + _ => { let _: u16 = 2u8; } //~ ERROR + } +} diff --git a/tests/ui/parser/issues/recover-ge-as-fat-arrow.stderr b/tests/ui/parser/issues/recover-ge-as-fat-arrow.stderr new file mode 100644 index 0000000000000..2df5cca24f06c --- /dev/null +++ b/tests/ui/parser/issues/recover-ge-as-fat-arrow.stderr @@ -0,0 +1,25 @@ +error: expected one of `...`, `..=`, `..`, `=>`, `if`, or `|`, found `>=` + --> $DIR/recover-ge-as-fat-arrow.rs:4:11 + | +LL | 1 >= {} + | ^^ + | | + | expected one of `...`, `..=`, `..`, `=>`, `if`, or `|` + | help: use a fat arrow to start a match arm: `=>` + +error[E0308]: mismatched types + --> $DIR/recover-ge-as-fat-arrow.rs:5:29 + | +LL | _ => { let _: u16 = 2u8; } + | --- ^^^ expected `u16`, found `u8` + | | + | expected due to this + | +help: change the type of the numeric literal from `u8` to `u16` + | +LL | _ => { let _: u16 = 2u16; } + | ~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/keyword-abstract.stderr b/tests/ui/parser/keyword-abstract.stderr index b7d1ce7cd7c2b..156e098dab934 100644 --- a/tests/ui/parser/keyword-abstract.stderr +++ b/tests/ui/parser/keyword-abstract.stderr @@ -9,5 +9,5 @@ help: escape `abstract` to use it as an identifier LL | let r#abstract = (); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-as-as-identifier.stderr b/tests/ui/parser/keyword-as-as-identifier.stderr index 3c5ad950db87a..bc654cbc7c3a5 100644 --- a/tests/ui/parser/keyword-as-as-identifier.stderr +++ b/tests/ui/parser/keyword-as-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `as` to use it as an identifier LL | let r#as = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-break-as-identifier.stderr b/tests/ui/parser/keyword-break-as-identifier.stderr index a4535eb40a158..63a9cbae5193d 100644 --- a/tests/ui/parser/keyword-break-as-identifier.stderr +++ b/tests/ui/parser/keyword-break-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `break` to use it as an identifier LL | let r#break = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-const-as-identifier.stderr b/tests/ui/parser/keyword-const-as-identifier.stderr index 31922f150e538..61e454174dd78 100644 --- a/tests/ui/parser/keyword-const-as-identifier.stderr +++ b/tests/ui/parser/keyword-const-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `const` to use it as an identifier LL | let r#const = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-continue-as-identifier.stderr b/tests/ui/parser/keyword-continue-as-identifier.stderr index 81285633faa10..2519000d28e76 100644 --- a/tests/ui/parser/keyword-continue-as-identifier.stderr +++ b/tests/ui/parser/keyword-continue-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `continue` to use it as an identifier LL | let r#continue = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-else-as-identifier.stderr b/tests/ui/parser/keyword-else-as-identifier.stderr index 2125fe84aedd4..e3eafa8fbbba1 100644 --- a/tests/ui/parser/keyword-else-as-identifier.stderr +++ b/tests/ui/parser/keyword-else-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `else` to use it as an identifier LL | let r#else = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-enum-as-identifier.stderr b/tests/ui/parser/keyword-enum-as-identifier.stderr index 92d092ccb65b4..280f8a2e1a118 100644 --- a/tests/ui/parser/keyword-enum-as-identifier.stderr +++ b/tests/ui/parser/keyword-enum-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `enum` to use it as an identifier LL | let r#enum = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-final.stderr b/tests/ui/parser/keyword-final.stderr index f1f9f2e2c90e4..74866c9e7f933 100644 --- a/tests/ui/parser/keyword-final.stderr +++ b/tests/ui/parser/keyword-final.stderr @@ -9,5 +9,5 @@ help: escape `final` to use it as an identifier LL | let r#final = (); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-fn-as-identifier.stderr b/tests/ui/parser/keyword-fn-as-identifier.stderr index 645efbcae7136..32fff1a6189f8 100644 --- a/tests/ui/parser/keyword-fn-as-identifier.stderr +++ b/tests/ui/parser/keyword-fn-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `fn` to use it as an identifier LL | let r#fn = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-for-as-identifier.stderr b/tests/ui/parser/keyword-for-as-identifier.stderr index 26407cc4d3ad2..813bb3f3bd302 100644 --- a/tests/ui/parser/keyword-for-as-identifier.stderr +++ b/tests/ui/parser/keyword-for-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `for` to use it as an identifier LL | let r#for = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-if-as-identifier.stderr b/tests/ui/parser/keyword-if-as-identifier.stderr index 26f9a15a7d00c..245ff8977b311 100644 --- a/tests/ui/parser/keyword-if-as-identifier.stderr +++ b/tests/ui/parser/keyword-if-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `if` to use it as an identifier LL | let r#if = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-impl-as-identifier.stderr b/tests/ui/parser/keyword-impl-as-identifier.stderr index 73a50bc38bcf1..fe840ba3d22db 100644 --- a/tests/ui/parser/keyword-impl-as-identifier.stderr +++ b/tests/ui/parser/keyword-impl-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `impl` to use it as an identifier LL | let r#impl = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-in-as-identifier.stderr b/tests/ui/parser/keyword-in-as-identifier.stderr index 98332b723f277..12fc0479f7067 100644 --- a/tests/ui/parser/keyword-in-as-identifier.stderr +++ b/tests/ui/parser/keyword-in-as-identifier.stderr @@ -4,5 +4,5 @@ error: expected pattern, found keyword `in` LL | let in = "foo"; | ^^ expected pattern -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-let-as-identifier.stderr b/tests/ui/parser/keyword-let-as-identifier.stderr index 86faaed382f03..69f570aa83854 100644 --- a/tests/ui/parser/keyword-let-as-identifier.stderr +++ b/tests/ui/parser/keyword-let-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `let` to use it as an identifier LL | let r#let = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-loop-as-identifier.stderr b/tests/ui/parser/keyword-loop-as-identifier.stderr index 304ad61ccafc9..ff14af0c7d740 100644 --- a/tests/ui/parser/keyword-loop-as-identifier.stderr +++ b/tests/ui/parser/keyword-loop-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `loop` to use it as an identifier LL | let r#loop = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-match-as-identifier.stderr b/tests/ui/parser/keyword-match-as-identifier.stderr index 25ac397fb7e2e..3811ef058b98d 100644 --- a/tests/ui/parser/keyword-match-as-identifier.stderr +++ b/tests/ui/parser/keyword-match-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `match` to use it as an identifier LL | let r#match = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-mod-as-identifier.stderr b/tests/ui/parser/keyword-mod-as-identifier.stderr index d5688e871b2d7..c60d6f1295b2c 100644 --- a/tests/ui/parser/keyword-mod-as-identifier.stderr +++ b/tests/ui/parser/keyword-mod-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `mod` to use it as an identifier LL | let r#mod = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-move-as-identifier.stderr b/tests/ui/parser/keyword-move-as-identifier.stderr index 75653cffc13e7..91cded8e9fbd2 100644 --- a/tests/ui/parser/keyword-move-as-identifier.stderr +++ b/tests/ui/parser/keyword-move-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `move` to use it as an identifier LL | let r#move = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-mut-as-identifier.stderr b/tests/ui/parser/keyword-mut-as-identifier.stderr index 040960835d811..335b31a20e11e 100644 --- a/tests/ui/parser/keyword-mut-as-identifier.stderr +++ b/tests/ui/parser/keyword-mut-as-identifier.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `=` LL | let mut = "foo"; | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-override.stderr b/tests/ui/parser/keyword-override.stderr index cdb5736866d31..108a621a24e7b 100644 --- a/tests/ui/parser/keyword-override.stderr +++ b/tests/ui/parser/keyword-override.stderr @@ -9,5 +9,5 @@ help: escape `override` to use it as an identifier LL | let r#override = (); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-pub-as-identifier.stderr b/tests/ui/parser/keyword-pub-as-identifier.stderr index 8d513507c810c..ec62fd4cfdef1 100644 --- a/tests/ui/parser/keyword-pub-as-identifier.stderr +++ b/tests/ui/parser/keyword-pub-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `pub` to use it as an identifier LL | let r#pub = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-ref-as-identifier.stderr b/tests/ui/parser/keyword-ref-as-identifier.stderr index 618043d89ffaa..54c258d7ad978 100644 --- a/tests/ui/parser/keyword-ref-as-identifier.stderr +++ b/tests/ui/parser/keyword-ref-as-identifier.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `=` LL | let ref = "foo"; | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-return-as-identifier.stderr b/tests/ui/parser/keyword-return-as-identifier.stderr index eeb8e468ba621..9e41d0ccbf69c 100644 --- a/tests/ui/parser/keyword-return-as-identifier.stderr +++ b/tests/ui/parser/keyword-return-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `return` to use it as an identifier LL | let r#return = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-static-as-identifier.stderr b/tests/ui/parser/keyword-static-as-identifier.stderr index a3213e2f29740..76fb3afd681a7 100644 --- a/tests/ui/parser/keyword-static-as-identifier.stderr +++ b/tests/ui/parser/keyword-static-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `static` to use it as an identifier LL | let r#static = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-struct-as-identifier.stderr b/tests/ui/parser/keyword-struct-as-identifier.stderr index b73361a5585d4..89eb644e106f9 100644 --- a/tests/ui/parser/keyword-struct-as-identifier.stderr +++ b/tests/ui/parser/keyword-struct-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `struct` to use it as an identifier LL | let r#struct = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-trait-as-identifier.stderr b/tests/ui/parser/keyword-trait-as-identifier.stderr index 56ef5f60690d2..3f19f6f3c81c0 100644 --- a/tests/ui/parser/keyword-trait-as-identifier.stderr +++ b/tests/ui/parser/keyword-trait-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `trait` to use it as an identifier LL | let r#trait = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-try-as-identifier-edition2018.stderr b/tests/ui/parser/keyword-try-as-identifier-edition2018.stderr index 94a106d47d710..ded65230262d3 100644 --- a/tests/ui/parser/keyword-try-as-identifier-edition2018.stderr +++ b/tests/ui/parser/keyword-try-as-identifier-edition2018.stderr @@ -9,5 +9,5 @@ help: escape `try` to use it as an identifier LL | let r#try = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-type-as-identifier.stderr b/tests/ui/parser/keyword-type-as-identifier.stderr index 624c1006b12fc..5e6c6d9e1d51c 100644 --- a/tests/ui/parser/keyword-type-as-identifier.stderr +++ b/tests/ui/parser/keyword-type-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `type` to use it as an identifier LL | let r#type = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-typeof.stderr b/tests/ui/parser/keyword-typeof.stderr index 4c5324505e96a..c671ba94c4e10 100644 --- a/tests/ui/parser/keyword-typeof.stderr +++ b/tests/ui/parser/keyword-typeof.stderr @@ -9,5 +9,5 @@ help: escape `typeof` to use it as an identifier LL | let r#typeof = (); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-unsafe-as-identifier.stderr b/tests/ui/parser/keyword-unsafe-as-identifier.stderr index b552c9cd38659..25a8001c68161 100644 --- a/tests/ui/parser/keyword-unsafe-as-identifier.stderr +++ b/tests/ui/parser/keyword-unsafe-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `unsafe` to use it as an identifier LL | let r#unsafe = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-use-as-identifier.stderr b/tests/ui/parser/keyword-use-as-identifier.stderr index 630798659a8a4..26bf2b4f64b78 100644 --- a/tests/ui/parser/keyword-use-as-identifier.stderr +++ b/tests/ui/parser/keyword-use-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `use` to use it as an identifier LL | let r#use = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-where-as-identifier.stderr b/tests/ui/parser/keyword-where-as-identifier.stderr index 9e72f7940428c..5243f04888fa5 100644 --- a/tests/ui/parser/keyword-where-as-identifier.stderr +++ b/tests/ui/parser/keyword-where-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `where` to use it as an identifier LL | let r#where = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword-while-as-identifier.stderr b/tests/ui/parser/keyword-while-as-identifier.stderr index 2bb62105d170e..ea396c61384ec 100644 --- a/tests/ui/parser/keyword-while-as-identifier.stderr +++ b/tests/ui/parser/keyword-while-as-identifier.stderr @@ -9,5 +9,5 @@ help: escape `while` to use it as an identifier LL | let r#while = "foo"; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/keyword.stderr b/tests/ui/parser/keyword.stderr index ee7d72b3996b7..54539519ec156 100644 --- a/tests/ui/parser/keyword.stderr +++ b/tests/ui/parser/keyword.stderr @@ -9,5 +9,5 @@ help: escape `break` to use it as an identifier LL | pub mod r#break { | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/lifetime-semicolon.stderr b/tests/ui/parser/lifetime-semicolon.stderr index ee486c2366c95..4f8e2835e085b 100644 --- a/tests/ui/parser/lifetime-semicolon.stderr +++ b/tests/ui/parser/lifetime-semicolon.stderr @@ -9,5 +9,5 @@ help: use a comma to separate type parameters LL | fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {} | ~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/lit-err-in-macro.stderr b/tests/ui/parser/lit-err-in-macro.stderr index a61fb5c85d492..12e6d51906030 100644 --- a/tests/ui/parser/lit-err-in-macro.stderr +++ b/tests/ui/parser/lit-err-in-macro.stderr @@ -4,5 +4,5 @@ error: suffixes on string literals are invalid LL | f!("Foo"__); | ^^^^^^^ invalid suffix `__` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro-bad-delimiter-ident.stderr b/tests/ui/parser/macro-bad-delimiter-ident.stderr index f2365fed273b1..06f72cdecf2a6 100644 --- a/tests/ui/parser/macro-bad-delimiter-ident.stderr +++ b/tests/ui/parser/macro-bad-delimiter-ident.stderr @@ -4,5 +4,5 @@ error: expected one of `(`, `[`, or `{`, found `bar` LL | foo! bar < | ^^^ expected one of `(`, `[`, or `{` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro-keyword.stderr b/tests/ui/parser/macro-keyword.stderr index d794671f8ab2f..bfe89e320e01c 100644 --- a/tests/ui/parser/macro-keyword.stderr +++ b/tests/ui/parser/macro-keyword.stderr @@ -9,5 +9,5 @@ help: escape `macro` to use it as an identifier LL | fn r#macro() { | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro-mismatched-delim-brace-paren.stderr b/tests/ui/parser/macro-mismatched-delim-brace-paren.stderr index 077d318004896..f9a3072229f65 100644 --- a/tests/ui/parser/macro-mismatched-delim-brace-paren.stderr +++ b/tests/ui/parser/macro-mismatched-delim-brace-paren.stderr @@ -7,5 +7,5 @@ LL | bar, "baz", 1, 2.0 LL | ) | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/bad-macro-argument.stderr b/tests/ui/parser/macro/bad-macro-argument.stderr index 3cd8accb66294..ba6499d712e5c 100644 --- a/tests/ui/parser/macro/bad-macro-argument.stderr +++ b/tests/ui/parser/macro/bad-macro-argument.stderr @@ -4,5 +4,5 @@ error: expected expression, found end of macro arguments LL | println!("Hello, {}", message/); | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/issue-37113.stderr b/tests/ui/parser/macro/issue-37113.stderr index da9e743a0b44f..1f2fe23106ae3 100644 --- a/tests/ui/parser/macro/issue-37113.stderr +++ b/tests/ui/parser/macro/issue-37113.stderr @@ -12,5 +12,5 @@ LL | test_macro!(String,); = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` = note: this error originates in the macro `test_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/issue-37234.stderr b/tests/ui/parser/macro/issue-37234.stderr index d7919620449f4..cd91ea441226a 100644 --- a/tests/ui/parser/macro/issue-37234.stderr +++ b/tests/ui/parser/macro/issue-37234.stderr @@ -9,5 +9,5 @@ LL | failed!(); | = note: this error originates in the macro `failed` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/macro-doc-comments-1.stderr b/tests/ui/parser/macro/macro-doc-comments-1.stderr index eaeb62d2cfd98..9d2d1bc00725a 100644 --- a/tests/ui/parser/macro/macro-doc-comments-1.stderr +++ b/tests/ui/parser/macro/macro-doc-comments-1.stderr @@ -16,5 +16,5 @@ note: while trying to match `[` LL | (#[$outer:meta]) => () | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/macro-doc-comments-2.stderr b/tests/ui/parser/macro/macro-doc-comments-2.stderr index 1dcd95f6fad4f..22efd995b463c 100644 --- a/tests/ui/parser/macro/macro-doc-comments-2.stderr +++ b/tests/ui/parser/macro/macro-doc-comments-2.stderr @@ -16,5 +16,5 @@ note: while trying to match `!` LL | (#![$inner:meta]) => () | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs index 39d1d065ed986..db38fa0d7bc65 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs @@ -1,6 +1,9 @@ macro_rules! arm { ($pattern:pat => $block:block) => { $pattern => $block + //~^ ERROR macro expansion ignores token `=>` and any following + //~| NOTE the usage of `arm!` is likely invalid in pattern context + //~| NOTE macros cannot expand to match arms }; } @@ -9,9 +12,8 @@ fn main() { match x { Some(1) => {}, arm!(None => {}), - //~^ NOTE macros cannot expand to match arms - //~| ERROR unexpected `,` in pattern - // doesn't recover + //~^ NOTE caused by the macro expansion here + //~| ERROR `match` arm with no body Some(2) => {}, _ => {}, }; diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr index 1a5f4696858cf..e3e7ff89c8134 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr @@ -1,10 +1,20 @@ -error: unexpected `,` in pattern - --> $DIR/macro-expand-to-match-arm.rs:11:25 +error: macro expansion ignores token `=>` and any following + --> $DIR/macro-expand-to-match-arm.rs:3:18 | +LL | $pattern => $block + | ^^ +... LL | arm!(None => {}), - | ^ + | ---------------- caused by the macro expansion here | + = note: the usage of `arm!` is likely invalid in pattern context = note: macros cannot expand to match arms -error: aborting due to previous error +error: `match` arm with no body + --> $DIR/macro-expand-to-match-arm.rs:14:9 + | +LL | arm!(None => {}), + | ^^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/match-arm-without-body.rs b/tests/ui/parser/match-arm-without-body.rs new file mode 100644 index 0000000000000..c3487c2c658ba --- /dev/null +++ b/tests/ui/parser/match-arm-without-body.rs @@ -0,0 +1,79 @@ +macro_rules! pat { + () => { Some(_) } +} + +fn main() { + match Some(false) { + Some(_) + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + Some(_) + _ => {} + //~^ ERROR expected one of + } + match Some(false) { + Some(_), + //~^ ERROR unexpected `,` in pattern + //~| HELP try adding parentheses to match on a tuple + //~| HELP or a vertical bar to match on multiple alternatives + } + match Some(false) { + Some(_), + //~^ ERROR unexpected `,` in pattern + //~| HELP try adding parentheses to match on a tuple + //~| HELP or a vertical bar to match on multiple alternatives + _ => {} + } + match Some(false) { + Some(_) if true + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + Some(_) if true + _ => {} + //~^ ERROR expected one of + } + match Some(false) { + Some(_) if true, + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + Some(_) if true, + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + _ => {} + } + match Some(false) { + pat!() + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + pat!(), + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + pat!() if true, + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + pat!() + //~^ ERROR expected `,` following `match` arm + //~| HELP missing a comma here + //~| ERROR `match` arm with no body + //~| HELP add a body after the pattern + _ => {} + } + match Some(false) { + pat!(), + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + _ => {} + } +} diff --git a/tests/ui/parser/match-arm-without-body.stderr b/tests/ui/parser/match-arm-without-body.stderr new file mode 100644 index 0000000000000..3a06ed050b562 --- /dev/null +++ b/tests/ui/parser/match-arm-without-body.stderr @@ -0,0 +1,116 @@ +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found reserved identifier `_` + --> $DIR/match-arm-without-body.rs:13:9 + | +LL | Some(_) + | - expected one of `,`, `=>`, `if`, `|`, or `}` +LL | _ => {} + | ^ unexpected token + +error: unexpected `,` in pattern + --> $DIR/match-arm-without-body.rs:17:16 + | +LL | Some(_), + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL | (Some(_),) + | + + +help: ...or a vertical bar to match on multiple alternatives + | +LL | Some(_) | + | + +error: unexpected `,` in pattern + --> $DIR/match-arm-without-body.rs:23:16 + | +LL | Some(_), + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL ~ (Some(_), +LL | +LL | +LL | +LL ~ _) => {} + | +help: ...or a vertical bar to match on multiple alternatives + | +LL ~ Some(_) | +LL + +LL + +LL + +LL ~ _ => {} + | + +error: expected one of `,`, `.`, `=>`, `?`, `}`, or an operator, found reserved identifier `_` + --> $DIR/match-arm-without-body.rs:36:9 + | +LL | Some(_) if true + | - expected one of `,`, `.`, `=>`, `?`, `}`, or an operator +LL | _ => {} + | ^ unexpected token + +error: expected `,` following `match` arm + --> $DIR/match-arm-without-body.rs:66:15 + | +LL | pat!() + | ^ help: missing a comma here to end this `match` arm: `,` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:7:9 + | +LL | Some(_) + | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:30:9 + | +LL | Some(_) if true + | ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:40:9 + | +LL | Some(_) if true, + | ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:45:9 + | +LL | Some(_) if true, + | ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:51:9 + | +LL | pat!() + | ^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:56:9 + | +LL | pat!(), + | ^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:61:9 + | +LL | pat!() if true, + | ^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:66:9 + | +LL | pat!() + | ^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:74:9 + | +LL | pat!(), + | ^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: aborting due to 14 previous errors + diff --git a/tests/ui/parser/match-arrows-block-then-binop.stderr b/tests/ui/parser/match-arrows-block-then-binop.stderr index cb361a3db5380..7ef5228a8edfb 100644 --- a/tests/ui/parser/match-arrows-block-then-binop.stderr +++ b/tests/ui/parser/match-arrows-block-then-binop.stderr @@ -11,5 +11,5 @@ LL | 0 LL ~ }) + 5 | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/match-refactor-to-expr.stderr b/tests/ui/parser/match-refactor-to-expr.stderr index 851bef8f2c7e8..72dfcd7dd7da7 100644 --- a/tests/ui/parser/match-refactor-to-expr.stderr +++ b/tests/ui/parser/match-refactor-to-expr.stderr @@ -12,5 +12,5 @@ LL | LL | ; | ^ unexpected token -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/mbe_missing_right_paren.stderr b/tests/ui/parser/mbe_missing_right_paren.stderr index d2af94683eff4..d45a2e3ab5298 100644 --- a/tests/ui/parser/mbe_missing_right_paren.stderr +++ b/tests/ui/parser/mbe_missing_right_paren.stderr @@ -6,5 +6,5 @@ LL | macro_rules! abc(ؼ | | | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr index dedbad9094594..f7822ba11246b 100644 --- a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr +++ b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr @@ -9,5 +9,5 @@ help: you might need to surround the struct literal with parentheses LL | if (Example { a: one(), }).is_pos() { | + + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index d91a7f0542d38..97aac661d4658 100644 --- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -7,5 +7,5 @@ LL | impl T for () { LL | | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr index d01d9ed60e411..f70dac443e55f 100644 --- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr @@ -7,5 +7,5 @@ LL | pub(crate) struct Bar { LL | fn main() {} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index 7418dd64c9e91..a565ad49b221c 100644 --- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,5 +7,5 @@ LL | trait T { LL | fn main() {} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/mismatched-delim-brace-empty-block.stderr b/tests/ui/parser/mismatched-delim-brace-empty-block.stderr index 165eb8ae93282..180798788df21 100644 --- a/tests/ui/parser/mismatched-delim-brace-empty-block.stderr +++ b/tests/ui/parser/mismatched-delim-brace-empty-block.stderr @@ -10,5 +10,5 @@ LL | let _ = (); LL | } | ^ unexpected closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr index b2448774ae9d3..e40d985826282 100644 --- a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr +++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -2,9 +2,8 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:23 | LL | let v : Vec<(u32,_) = vec![]; - | - - ^ expected one of `,`, `:`, or `>` - | | | - | | maybe try to close unmatched angle bracket + | - ^ expected one of `,`, `:`, or `>` + | | | while parsing the type for `v` | help: you might have meant to end the type parameters here @@ -29,9 +28,8 @@ error: expected one of `,`, `:`, or `>`, found `=` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:18 | LL | let v : Vec<'a = vec![]; - | - -- ^ expected one of `,`, `:`, or `>` - | | | - | | maybe try to close unmatched angle bracket + | - ^ expected one of `,`, `:`, or `>` + | | | while parsing the type for `v` | help: you might have meant to end the type parameters here diff --git a/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr b/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr index 6d8b0c3fccde3..29a5dbb737af1 100644 --- a/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr +++ b/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr @@ -14,5 +14,5 @@ help: you might have meant to end the type parameters here LL | b: Arc>, | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/missing-expression-in-for-loop.stderr b/tests/ui/parser/missing-expression-in-for-loop.stderr index 74a7c4224fae1..74acfc829a43b 100644 --- a/tests/ui/parser/missing-expression-in-for-loop.stderr +++ b/tests/ui/parser/missing-expression-in-for-loop.stderr @@ -9,5 +9,5 @@ help: try adding an expression to the `for` loop LL | for i in /* expression */ { | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/missing-semicolon.stderr b/tests/ui/parser/missing-semicolon.stderr index e0d5e84ec3177..4108cced366a6 100644 --- a/tests/ui/parser/missing-semicolon.stderr +++ b/tests/ui/parser/missing-semicolon.stderr @@ -9,5 +9,5 @@ LL | fn main() { m!(0, 0; 0, 0); } | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs index e240f8c6739ee..cc6d30c9cac12 100644 --- a/tests/ui/parser/missing_right_paren.rs +++ b/tests/ui/parser/missing_right_paren.rs @@ -1,4 +1,4 @@ // ignore-tidy-trailing-newlines // error-pattern: this file contains an unclosed delimiter -// error-pattern: aborting due to previous error +// error-pattern: aborting due to 1 previous error fn main((ؼ \ No newline at end of file diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr index 994ce4d8541c0..4815f04fbce07 100644 --- a/tests/ui/parser/missing_right_paren.stderr +++ b/tests/ui/parser/missing_right_paren.stderr @@ -7,5 +7,5 @@ LL | fn main((ؼ | |unclosed delimiter | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-macro-rules.stderr b/tests/ui/parser/misspelled-macro-rules.stderr index 56df712381920..fc718d8556dfe 100644 --- a/tests/ui/parser/misspelled-macro-rules.stderr +++ b/tests/ui/parser/misspelled-macro-rules.stderr @@ -6,5 +6,5 @@ LL | marco_rules! thing { | | | help: perhaps you meant to define a macro: `macro_rules` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/mod_file_with_path_attr.stderr b/tests/ui/parser/mod_file_with_path_attr.stderr index cd1add73d5840..9ccb775daab13 100644 --- a/tests/ui/parser/mod_file_with_path_attr.stderr +++ b/tests/ui/parser/mod_file_with_path_attr.stderr @@ -4,5 +4,5 @@ error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2) LL | mod m; | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/multiline-comment-line-tracking.stderr b/tests/ui/parser/multiline-comment-line-tracking.stderr index cac0c801a5998..450a91207b724 100644 --- a/tests/ui/parser/multiline-comment-line-tracking.stderr +++ b/tests/ui/parser/multiline-comment-line-tracking.stderr @@ -4,5 +4,5 @@ error: expected expression, found `%` LL | %; | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/multitrait.stderr b/tests/ui/parser/multitrait.stderr index 5a8bb2f7a457c..6100f64e3ecd8 100644 --- a/tests/ui/parser/multitrait.stderr +++ b/tests/ui/parser/multitrait.stderr @@ -4,5 +4,5 @@ error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found ` LL | impl Cmp, ToString for S { | ^ expected one of 8 possible tokens -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/mut-patterns.rs b/tests/ui/parser/mut-patterns.rs index 8b83d6ab2f8c8..f2d2df0af29d9 100644 --- a/tests/ui/parser/mut-patterns.rs +++ b/tests/ui/parser/mut-patterns.rs @@ -27,7 +27,7 @@ pub fn main() { struct r#yield(u8, u8); let mut mut yield(become, await) = r#yield(0, 0); //~^ ERROR `mut` on a binding may not be repeated - //~| ERROR `mut` must be attached to each individual binding + //~| ERROR `mut` must be followed by a named binding //~| ERROR expected identifier, found reserved keyword `yield` //~| ERROR expected identifier, found reserved keyword `become` //~| ERROR expected identifier, found keyword `await` diff --git a/tests/ui/parser/mut-patterns.stderr b/tests/ui/parser/mut-patterns.stderr index f179d8c9e0a83..6559cf09cdfcf 100644 --- a/tests/ui/parser/mut-patterns.stderr +++ b/tests/ui/parser/mut-patterns.stderr @@ -2,7 +2,7 @@ error: `mut` must be followed by a named binding --> $DIR/mut-patterns.rs:9:9 | LL | let mut _ = 0; - | ^^^^^ help: remove the `mut` prefix: `_` + | ^^^^ help: remove the `mut` prefix | = note: `mut` may be followed by `variable` and `variable @ pattern` @@ -10,7 +10,7 @@ error: `mut` must be followed by a named binding --> $DIR/mut-patterns.rs:10:9 | LL | let mut (_, _) = (0, 0); - | ^^^^^^^^^^ help: remove the `mut` prefix: `(_, _)` + | ^^^^ help: remove the `mut` prefix | = note: `mut` may be followed by `variable` and `variable @ pattern` @@ -83,11 +83,11 @@ help: escape `await` to use it as an identifier LL | let mut mut yield(become, r#await) = r#yield(0, 0); | ++ -error: `mut` must be attached to each individual binding +error: `mut` must be followed by a named binding --> $DIR/mut-patterns.rs:28:9 | LL | let mut mut yield(become, await) = r#yield(0, 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)` + | ^^^^^^^^ help: remove the `mut` prefix | = note: `mut` may be followed by `variable` and `variable @ pattern` diff --git a/tests/ui/parser/nested-bad-turbofish.stderr b/tests/ui/parser/nested-bad-turbofish.stderr index d82fa80e594ad..a23c23c41df29 100644 --- a/tests/ui/parser/nested-bad-turbofish.stderr +++ b/tests/ui/parser/nested-bad-turbofish.stderr @@ -7,5 +7,5 @@ LL | foo<::V>(); = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments = help: or use `(...)` if you meant to specify fn arguments -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/nested-missing-closing-angle-bracket.stderr b/tests/ui/parser/nested-missing-closing-angle-bracket.stderr index b85bc02568c77..8d69125f8e957 100644 --- a/tests/ui/parser/nested-missing-closing-angle-bracket.stderr +++ b/tests/ui/parser/nested-missing-closing-angle-bracket.stderr @@ -4,5 +4,5 @@ error: expected one of `,` or `>`, found `;` LL | let v : Vec:: = vec![vec![]]; | - while parsing the type for `v` ^ expected one of `,` or `>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/new-unicode-escapes-1.stderr b/tests/ui/parser/new-unicode-escapes-1.stderr index d133e46b4b0d2..491915c89cc4a 100644 --- a/tests/ui/parser/new-unicode-escapes-1.stderr +++ b/tests/ui/parser/new-unicode-escapes-1.stderr @@ -9,5 +9,5 @@ help: terminate the unicode escape LL | let s = "\u{2603}"; | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/new-unicode-escapes-2.stderr b/tests/ui/parser/new-unicode-escapes-2.stderr index 2f3f8c0f9dae5..e0bdf533d3e0c 100644 --- a/tests/ui/parser/new-unicode-escapes-2.stderr +++ b/tests/ui/parser/new-unicode-escapes-2.stderr @@ -4,5 +4,5 @@ error: overlong unicode escape LL | let s = "\u{260311111111}"; | ^^^^^^^^^^^^^^^^ must have at most 6 hex digits -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/new-unicode-escapes-4.stderr b/tests/ui/parser/new-unicode-escapes-4.stderr index 514591af17e6e..d62afee7f009b 100644 --- a/tests/ui/parser/new-unicode-escapes-4.stderr +++ b/tests/ui/parser/new-unicode-escapes-4.stderr @@ -4,5 +4,5 @@ error: invalid character in unicode escape: `l` LL | let s = "\u{lol}"; | ^ invalid character in unicode escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/obsolete-syntax-impl-for-dotdot.stderr b/tests/ui/parser/obsolete-syntax-impl-for-dotdot.stderr index b7108ced0d763..d5f404bed3108 100644 --- a/tests/ui/parser/obsolete-syntax-impl-for-dotdot.stderr +++ b/tests/ui/parser/obsolete-syntax-impl-for-dotdot.stderr @@ -6,5 +6,5 @@ LL | impl Trait2 for .. {} | = help: use `auto trait Trait {}` instead -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/omitted-arg-in-item-fn.stderr b/tests/ui/parser/omitted-arg-in-item-fn.stderr index ce2eab051addd..6f2a9f64c94bb 100644 --- a/tests/ui/parser/omitted-arg-in-item-fn.stderr +++ b/tests/ui/parser/omitted-arg-in-item-fn.stderr @@ -18,5 +18,5 @@ help: if this is a type, explicitly ignore the parameter name LL | fn foo(_: x) { | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/paamayim-nekudotayim.stderr b/tests/ui/parser/paamayim-nekudotayim.stderr index 6ceba07f46918..7d40cd63ffb73 100644 --- a/tests/ui/parser/paamayim-nekudotayim.stderr +++ b/tests/ui/parser/paamayim-nekudotayim.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `;` LL | ::; | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/parser-recovery-1.stderr b/tests/ui/parser/parser-recovery-1.stderr index 7045b6f5b7869..8162db3d8e5d6 100644 --- a/tests/ui/parser/parser-recovery-1.stderr +++ b/tests/ui/parser/parser-recovery-1.stderr @@ -12,5 +12,5 @@ LL | } LL | } | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/parser-recovery-2.stderr b/tests/ui/parser/parser-recovery-2.stderr index f396e5fde5bad..d3d6c9b081023 100644 --- a/tests/ui/parser/parser-recovery-2.stderr +++ b/tests/ui/parser/parser-recovery-2.stderr @@ -7,5 +7,5 @@ LL | let x = foo(); LL | ) | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-lt-bracket-1.rs b/tests/ui/parser/pat-lt-bracket-1.rs index 2e2001434f28c..33da15adb9e40 100644 --- a/tests/ui/parser/pat-lt-bracket-1.rs +++ b/tests/ui/parser/pat-lt-bracket-1.rs @@ -1,7 +1,7 @@ fn main() { match 42 { x < 7 => (), - //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<` + //~^ error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `<` _ => () } } diff --git a/tests/ui/parser/pat-lt-bracket-1.stderr b/tests/ui/parser/pat-lt-bracket-1.stderr index e8ccbad668a2b..f39487052ade4 100644 --- a/tests/ui/parser/pat-lt-bracket-1.stderr +++ b/tests/ui/parser/pat-lt-bracket-1.stderr @@ -1,8 +1,8 @@ -error: expected one of `=>`, `@`, `if`, or `|`, found `<` +error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `<` --> $DIR/pat-lt-bracket-1.rs:3:7 | LL | x < 7 => (), - | ^ expected one of `=>`, `@`, `if`, or `|` + | ^ expected one of `,`, `=>`, `@`, `if`, `|`, or `}` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-lt-bracket-2.stderr b/tests/ui/parser/pat-lt-bracket-2.stderr index c78f96e1addcb..5fe97b2ef4c79 100644 --- a/tests/ui/parser/pat-lt-bracket-2.stderr +++ b/tests/ui/parser/pat-lt-bracket-2.stderr @@ -14,5 +14,5 @@ help: if this is a type, explicitly ignore the parameter name LL | fn a(_: B<) {} | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-lt-bracket-3.stderr b/tests/ui/parser/pat-lt-bracket-3.stderr index afdf1e9a55762..cdb1b31773530 100644 --- a/tests/ui/parser/pat-lt-bracket-3.stderr +++ b/tests/ui/parser/pat-lt-bracket-3.stderr @@ -9,5 +9,5 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | Foo::(x, y) => { | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-lt-bracket-4.stderr b/tests/ui/parser/pat-lt-bracket-4.stderr index b71a5ad939e59..92d16564ab4f9 100644 --- a/tests/ui/parser/pat-lt-bracket-4.stderr +++ b/tests/ui/parser/pat-lt-bracket-4.stderr @@ -9,5 +9,5 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | Foo::::A(value) => value, | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-lt-bracket-5.stderr b/tests/ui/parser/pat-lt-bracket-5.stderr index e23674bcec587..e556e6c0206fb 100644 --- a/tests/ui/parser/pat-lt-bracket-5.stderr +++ b/tests/ui/parser/pat-lt-bracket-5.stderr @@ -4,5 +4,5 @@ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` LL | let v[0] = v[1]; | ^ expected one of `:`, `;`, `=`, `@`, or `|` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-ranges-1.stderr b/tests/ui/parser/pat-ranges-1.stderr index b64a3ce5c083d..e4d4e145c0659 100644 --- a/tests/ui/parser/pat-ranges-1.stderr +++ b/tests/ui/parser/pat-ranges-1.stderr @@ -4,5 +4,5 @@ error: expected one of `:`, `;`, `=`, or `|`, found `..=` LL | let macropus!() ..= 11 = 12; | ^^^ expected one of `:`, `;`, `=`, or `|` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-ranges-2.stderr b/tests/ui/parser/pat-ranges-2.stderr index 1a9e33bebe914..c27436a81c5df 100644 --- a/tests/ui/parser/pat-ranges-2.stderr +++ b/tests/ui/parser/pat-ranges-2.stderr @@ -4,5 +4,5 @@ error: expected one of `::`, `:`, `;`, `=`, or `|`, found `!` LL | let 10 ..= makropulos!() = 12; | ^ expected one of `::`, `:`, `;`, `=`, or `|` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-ranges-3.stderr b/tests/ui/parser/pat-ranges-3.stderr index c9787b789a88b..611b35a650280 100644 --- a/tests/ui/parser/pat-ranges-3.stderr +++ b/tests/ui/parser/pat-ranges-3.stderr @@ -4,5 +4,5 @@ error: expected one of `:`, `;`, `=`, or `|`, found `+` LL | let 10 ..= 10 + 3 = 12; | ^ expected one of `:`, `;`, `=`, or `|` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-ranges-4.stderr b/tests/ui/parser/pat-ranges-4.stderr index 69084b5a41475..c30160291d608 100644 --- a/tests/ui/parser/pat-ranges-4.stderr +++ b/tests/ui/parser/pat-ranges-4.stderr @@ -4,5 +4,5 @@ error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` LL | let 10 - 3 ..= 10 = 8; | ^ expected one of 7 possible tokens -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-ref-enum.stderr b/tests/ui/parser/pat-ref-enum.stderr index a3bce3372646f..ecda487d0c55e 100644 --- a/tests/ui/parser/pat-ref-enum.stderr +++ b/tests/ui/parser/pat-ref-enum.stderr @@ -4,5 +4,5 @@ error: expected identifier, found enum pattern LL | ref Some(i) => {} | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-tuple-1.stderr b/tests/ui/parser/pat-tuple-1.stderr index 391f2c428bf2e..579365730c34c 100644 --- a/tests/ui/parser/pat-tuple-1.stderr +++ b/tests/ui/parser/pat-tuple-1.stderr @@ -4,5 +4,5 @@ error: expected pattern, found `,` LL | (, ..) => {} | ^ expected pattern -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pat-tuple-3.stderr b/tests/ui/parser/pat-tuple-3.stderr index 9ac0611c5c933..7ce00462be229 100644 --- a/tests/ui/parser/pat-tuple-3.stderr +++ b/tests/ui/parser/pat-tuple-3.stderr @@ -6,5 +6,5 @@ LL | (.., pat, ..) => {} | | | previously used here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/pub-method-macro.stderr b/tests/ui/parser/pub-method-macro.stderr index 7c7a909267a1c..35cbf42307913 100644 --- a/tests/ui/parser/pub-method-macro.stderr +++ b/tests/ui/parser/pub-method-macro.stderr @@ -6,5 +6,5 @@ LL | pub defn!(f); | = help: try adjusting the macro to put `pub` inside the invocation -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/public-instead-of-pub-1.stderr b/tests/ui/parser/public-instead-of-pub-1.stderr index 795a5bcf5dfa6..3fbe8d0b164e8 100644 --- a/tests/ui/parser/public-instead-of-pub-1.stderr +++ b/tests/ui/parser/public-instead-of-pub-1.stderr @@ -9,5 +9,5 @@ help: write `pub` instead of `public` to make the item public LL | pub enum Test { | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/public-instead-of-pub-2.stderr b/tests/ui/parser/public-instead-of-pub-2.stderr index efe225656fd7f..09d564d7a39b8 100644 --- a/tests/ui/parser/public-instead-of-pub-2.stderr +++ b/tests/ui/parser/public-instead-of-pub-2.stderr @@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found keyword `let` LL | public let x = 1; | ^^^ expected one of `!` or `::` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/public-instead-of-pub-3.stderr b/tests/ui/parser/public-instead-of-pub-3.stderr index 72efae08dda8e..b9b924e670a46 100644 --- a/tests/ui/parser/public-instead-of-pub-3.stderr +++ b/tests/ui/parser/public-instead-of-pub-3.stderr @@ -9,5 +9,5 @@ help: write `pub` instead of `public` to make the item public LL | pub const X: i32 = 123; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/public-instead-of-pub.stderr b/tests/ui/parser/public-instead-of-pub.stderr index af875491e85cb..c98f8a9914e62 100644 --- a/tests/ui/parser/public-instead-of-pub.stderr +++ b/tests/ui/parser/public-instead-of-pub.stderr @@ -9,5 +9,5 @@ help: write `pub` instead of `public` to make the item public LL | pub struct X; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/qualified-path-in-turbofish.stderr b/tests/ui/parser/qualified-path-in-turbofish.stderr index 8857d2ef30cfc..6e5af8cc1f0cc 100644 --- a/tests/ui/parser/qualified-path-in-turbofish.stderr +++ b/tests/ui/parser/qualified-path-in-turbofish.stderr @@ -4,5 +4,5 @@ error: found single colon before projection in qualified path LL | template::<:Ty>(); | ^ help: use double colon: `::` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/range-3.stderr b/tests/ui/parser/range-3.stderr index 340167f1804e3..c8f26a3ba1b03 100644 --- a/tests/ui/parser/range-3.stderr +++ b/tests/ui/parser/range-3.stderr @@ -4,5 +4,5 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `..` LL | let r = 1..2..3; | ^^ expected one of `.`, `;`, `?`, `else`, or an operator -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/range-4.stderr b/tests/ui/parser/range-4.stderr index 720d489389bfb..a797fa319c47e 100644 --- a/tests/ui/parser/range-4.stderr +++ b/tests/ui/parser/range-4.stderr @@ -4,5 +4,5 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `..` LL | let r = ..1..2; | ^^ expected one of `.`, `;`, `?`, `else`, or an operator -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/range-inclusive-extra-equals.stderr b/tests/ui/parser/range-inclusive-extra-equals.stderr index d37b6be4fa113..83df719dd3cc5 100644 --- a/tests/ui/parser/range-inclusive-extra-equals.stderr +++ b/tests/ui/parser/range-inclusive-extra-equals.stderr @@ -6,5 +6,5 @@ LL | if let 1..==3 = 1 {} | = note: inclusive ranges end with a single equals sign (`..=`) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/range_inclusive.stderr b/tests/ui/parser/range_inclusive.stderr index 8a91782639f45..0fd7f28db317f 100644 --- a/tests/ui/parser/range_inclusive.stderr +++ b/tests/ui/parser/range_inclusive.stderr @@ -6,6 +6,6 @@ LL | for _ in 1..= {} | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr b/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr index 3a7e2a4b14afb..796b1324a5f92 100644 --- a/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr +++ b/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr @@ -4,6 +4,6 @@ error[E0748]: unterminated raw string LL | r" | ^ unterminated raw string -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/raw-byte-string-eof.stderr b/tests/ui/parser/raw/raw-byte-string-eof.stderr index a76668e8051b5..88fd53904c43f 100644 --- a/tests/ui/parser/raw/raw-byte-string-eof.stderr +++ b/tests/ui/parser/raw/raw-byte-string-eof.stderr @@ -8,6 +8,6 @@ LL | br##"a"#; | = note: this raw string should be terminated with `"##` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/raw-literal-self.stderr b/tests/ui/parser/raw/raw-literal-self.stderr index 2a40dfe200cde..f42c3e8e70c02 100644 --- a/tests/ui/parser/raw/raw-literal-self.stderr +++ b/tests/ui/parser/raw/raw-literal-self.stderr @@ -4,5 +4,5 @@ error: `self` cannot be a raw identifier LL | let r#self: (); | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/raw/raw-literal-underscore.stderr b/tests/ui/parser/raw/raw-literal-underscore.stderr index d7a364d8579ef..2edba430d1d62 100644 --- a/tests/ui/parser/raw/raw-literal-underscore.stderr +++ b/tests/ui/parser/raw/raw-literal-underscore.stderr @@ -4,5 +4,5 @@ error: `_` cannot be a raw identifier LL | let r#_: (); | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/raw/raw-str-delim.stderr b/tests/ui/parser/raw/raw-str-delim.stderr index 8a04f99a126da..5edd18cb4a998 100644 --- a/tests/ui/parser/raw/raw-str-delim.stderr +++ b/tests/ui/parser/raw/raw-str-delim.stderr @@ -4,5 +4,5 @@ error: found invalid character; only `#` is allowed in raw string delimitation: LL | r#~"#"~# | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/raw/raw-str-unterminated.stderr b/tests/ui/parser/raw/raw-str-unterminated.stderr index 077f763f154c5..9d15a28173a8a 100644 --- a/tests/ui/parser/raw/raw-str-unterminated.stderr +++ b/tests/ui/parser/raw/raw-str-unterminated.stderr @@ -6,6 +6,6 @@ LL | r#" string literal goes on | = note: this raw string should be terminated with `"#` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/raw-string-2.stderr b/tests/ui/parser/raw/raw-string-2.stderr index 8bbac9d7bd0bd..90dd9775e62e4 100644 --- a/tests/ui/parser/raw/raw-string-2.stderr +++ b/tests/ui/parser/raw/raw-string-2.stderr @@ -6,6 +6,6 @@ LL | let x = r###"here's a long string"# "# "##; | = note: this raw string should be terminated with `"###` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/raw-string.stderr b/tests/ui/parser/raw/raw-string.stderr index b2b853a89e751..6654ef7a75a42 100644 --- a/tests/ui/parser/raw/raw-string.stderr +++ b/tests/ui/parser/raw/raw-string.stderr @@ -8,6 +8,6 @@ LL | let x = r##"lol"#; | = note: this raw string should be terminated with `"##` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/too-many-hash.stderr b/tests/ui/parser/raw/too-many-hash.stderr index 29ec17842aacc..1c46b5385cd9c 100644 --- a/tests/ui/parser/raw/too-many-hash.stderr +++ b/tests/ui/parser/raw/too-many-hash.stderr @@ -4,5 +4,5 @@ error: too many `#` symbols: raw strings may be delimited by up to 255 `#` symbo LL | ... = r################################################################################################################################################################################################################################################################"very raw"##############################################################################################################################################################################################################################################################... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover-enum2.stderr b/tests/ui/parser/recover-enum2.stderr deleted file mode 100644 index 7634bca921c86..0000000000000 --- a/tests/ui/parser/recover-enum2.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: expected type, found `{` - --> $DIR/recover-enum2.rs:6:18 - | -LL | Var3 { - | ---- while parsing this struct -LL | abc: {}, - | ^ expected type - -error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{` - --> $DIR/recover-enum2.rs:25:22 - | -LL | Nope(i32 {}) - | ^ expected one of 7 possible tokens - -error: aborting due to 2 previous errors - diff --git a/tests/ui/parser/recover-for-loop-parens-around-head.stderr b/tests/ui/parser/recover-for-loop-parens-around-head.stderr deleted file mode 100644 index 3bad29f20afc5..0000000000000 --- a/tests/ui/parser/recover-for-loop-parens-around-head.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` - --> $DIR/recover-for-loop-parens-around-head.rs:10:16 - | -LL | for ( elem in vec ) { - | ^^ expected one of `)`, `,`, `@`, or `|` - -error: unexpected parentheses surrounding `for` loop head - --> $DIR/recover-for-loop-parens-around-head.rs:10:9 - | -LL | for ( elem in vec ) { - | ^ ^ - | -help: remove parentheses in `for` loop - | -LL - for ( elem in vec ) { -LL + for elem in vec { - | - -error[E0308]: mismatched types - --> $DIR/recover-for-loop-parens-around-head.rs:13:38 - | -LL | const RECOVERY_WITNESS: () = 0; - | ^ expected `()`, found integer - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs new file mode 100644 index 0000000000000..b9e3c5783ebd7 --- /dev/null +++ b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs @@ -0,0 +1,13 @@ +trait Trait {} + +fn test(_: &for<'a> dyn Trait) {} +//~^ ERROR `for<...>` expected after `dyn`, not before + +fn test2(_: for<'a> impl Trait) {} +//~^ ERROR `for<...>` expected after `impl`, not before + +// Issue #118564 +type A2 = dyn dyn>; +//~^ ERROR expected identifier, found `>` + +fn main() {} diff --git a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr new file mode 100644 index 0000000000000..a012220e8c7c9 --- /dev/null +++ b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr @@ -0,0 +1,32 @@ +error: `for<...>` expected after `dyn`, not before + --> $DIR/recover-hrtb-before-dyn-impl-kw.rs:3:21 + | +LL | fn test(_: &for<'a> dyn Trait) {} + | ^^^ + | +help: move `dyn` before the `for<...>` + | +LL - fn test(_: &for<'a> dyn Trait) {} +LL + fn test(_: &dyn for<'a> Trait) {} + | + +error: `for<...>` expected after `impl`, not before + --> $DIR/recover-hrtb-before-dyn-impl-kw.rs:6:21 + | +LL | fn test2(_: for<'a> impl Trait) {} + | ^^^^ + | +help: move `impl` before the `for<...>` + | +LL - fn test2(_: for<'a> impl Trait) {} +LL + fn test2(_: impl for<'a> Trait) {} + | + +error: expected identifier, found `>` + --> $DIR/recover-hrtb-before-dyn-impl-kw.rs:10:24 + | +LL | type A2 = dyn dyn>; + | ^ expected identifier + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-104088.rs b/tests/ui/parser/recover/binding-name-starting-with-number.rs similarity index 93% rename from tests/ui/parser/issues/issue-104088.rs rename to tests/ui/parser/recover/binding-name-starting-with-number.rs index 3dc636b6a33bd..6b279c5539e6a 100644 --- a/tests/ui/parser/issues/issue-104088.rs +++ b/tests/ui/parser/recover/binding-name-starting-with-number.rs @@ -8,10 +8,12 @@ fn 1234test() { let 23name = 123; //~^ ERROR expected identifier, found `23name` - +} +fn foo() { let 2x: i32 = 123; //~^ ERROR expected identifier, found `2x` - +} +fn bar() { let 1x = 123; //~^ ERROR expected identifier, found `1x` } diff --git a/tests/ui/parser/issues/issue-104088.stderr b/tests/ui/parser/recover/binding-name-starting-with-number.stderr similarity index 70% rename from tests/ui/parser/issues/issue-104088.stderr rename to tests/ui/parser/recover/binding-name-starting-with-number.stderr index 8b751759d69a6..de59a7de04381 100644 --- a/tests/ui/parser/issues/issue-104088.stderr +++ b/tests/ui/parser/recover/binding-name-starting-with-number.stderr @@ -1,53 +1,53 @@ error: expected identifier, found `1234test` - --> $DIR/issue-104088.rs:1:4 + --> $DIR/binding-name-starting-with-number.rs:1:4 | LL | fn 1234test() { | ^^^^^^^^ expected identifier | help: identifiers cannot start with a number - --> $DIR/issue-104088.rs:1:4 + --> $DIR/binding-name-starting-with-number.rs:1:4 | LL | fn 1234test() { | ^^^^ error: expected identifier, found `23name` - --> $DIR/issue-104088.rs:9:9 + --> $DIR/binding-name-starting-with-number.rs:9:9 | LL | let 23name = 123; | ^^^^^^ expected identifier | help: identifiers cannot start with a number - --> $DIR/issue-104088.rs:9:9 + --> $DIR/binding-name-starting-with-number.rs:9:9 | LL | let 23name = 123; | ^^ error: expected identifier, found `2x` - --> $DIR/issue-104088.rs:12:9 + --> $DIR/binding-name-starting-with-number.rs:13:9 | LL | let 2x: i32 = 123; | ^^ expected identifier | help: identifiers cannot start with a number - --> $DIR/issue-104088.rs:12:9 + --> $DIR/binding-name-starting-with-number.rs:13:9 | LL | let 2x: i32 = 123; | ^ error: expected identifier, found `1x` - --> $DIR/issue-104088.rs:15:9 + --> $DIR/binding-name-starting-with-number.rs:17:9 | LL | let 1x = 123; | ^^ expected identifier | help: identifiers cannot start with a number - --> $DIR/issue-104088.rs:15:9 + --> $DIR/binding-name-starting-with-number.rs:17:9 | LL | let 1x = 123; | ^ error[E0308]: mismatched types - --> $DIR/issue-104088.rs:5:12 + --> $DIR/binding-name-starting-with-number.rs:5:12 | LL | if let 2e1 = 123 { | ^^^ --- this expression has type `{integer}` diff --git a/tests/ui/parser/recover-assoc-const-constraint.rs b/tests/ui/parser/recover/recover-assoc-const-constraint.rs similarity index 100% rename from tests/ui/parser/recover-assoc-const-constraint.rs rename to tests/ui/parser/recover/recover-assoc-const-constraint.rs diff --git a/tests/ui/parser/recover-assoc-const-constraint.stderr b/tests/ui/parser/recover/recover-assoc-const-constraint.stderr similarity index 100% rename from tests/ui/parser/recover-assoc-const-constraint.stderr rename to tests/ui/parser/recover/recover-assoc-const-constraint.stderr diff --git a/tests/ui/parser/recover-assoc-eq-missing-term.rs b/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs similarity index 100% rename from tests/ui/parser/recover-assoc-eq-missing-term.rs rename to tests/ui/parser/recover/recover-assoc-eq-missing-term.rs diff --git a/tests/ui/parser/recover-assoc-eq-missing-term.stderr b/tests/ui/parser/recover/recover-assoc-eq-missing-term.stderr similarity index 90% rename from tests/ui/parser/recover-assoc-eq-missing-term.stderr rename to tests/ui/parser/recover/recover-assoc-eq-missing-term.stderr index 152f7f2fb0626..cf50c026665b5 100644 --- a/tests/ui/parser/recover-assoc-eq-missing-term.stderr +++ b/tests/ui/parser/recover/recover-assoc-eq-missing-term.stderr @@ -14,5 +14,5 @@ LL - bar::(); LL + bar::(); | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover-assoc-lifetime-constraint.rs b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs similarity index 100% rename from tests/ui/parser/recover-assoc-lifetime-constraint.rs rename to tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs diff --git a/tests/ui/parser/recover-assoc-lifetime-constraint.stderr b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr similarity index 88% rename from tests/ui/parser/recover-assoc-lifetime-constraint.stderr rename to tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr index 79437533d7c0b..39a6682fcaeef 100644 --- a/tests/ui/parser/recover-assoc-lifetime-constraint.stderr +++ b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr @@ -8,5 +8,5 @@ LL | bar::(); | = help: if you meant to specify a trait object, write `dyn Trait + 'lifetime` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover-const-async-fn-ptr.rs b/tests/ui/parser/recover/recover-const-async-fn-ptr.rs similarity index 100% rename from tests/ui/parser/recover-const-async-fn-ptr.rs rename to tests/ui/parser/recover/recover-const-async-fn-ptr.rs diff --git a/tests/ui/parser/recover-const-async-fn-ptr.stderr b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr similarity index 100% rename from tests/ui/parser/recover-const-async-fn-ptr.stderr rename to tests/ui/parser/recover/recover-const-async-fn-ptr.stderr diff --git a/tests/ui/parser/recover-enum.rs b/tests/ui/parser/recover/recover-enum.rs similarity index 100% rename from tests/ui/parser/recover-enum.rs rename to tests/ui/parser/recover/recover-enum.rs diff --git a/tests/ui/parser/recover-enum.stderr b/tests/ui/parser/recover/recover-enum.stderr similarity index 100% rename from tests/ui/parser/recover-enum.stderr rename to tests/ui/parser/recover/recover-enum.stderr diff --git a/tests/ui/parser/recover-enum2.rs b/tests/ui/parser/recover/recover-enum2.rs similarity index 81% rename from tests/ui/parser/recover-enum2.rs rename to tests/ui/parser/recover/recover-enum2.rs index 0c9420889553b..56b57f625ba08 100644 --- a/tests/ui/parser/recover-enum2.rs +++ b/tests/ui/parser/recover/recover-enum2.rs @@ -8,7 +8,7 @@ fn main() { } // recover... - let a = 1; + let () = 1; //~ ERROR mismatched types enum Test2 { Fine, } @@ -24,5 +24,6 @@ fn main() { enum Test4 { Nope(i32 {}) //~ ERROR: found `{` } + let () = 1; //~ ERROR mismatched types } } diff --git a/tests/ui/parser/recover/recover-enum2.stderr b/tests/ui/parser/recover/recover-enum2.stderr new file mode 100644 index 0000000000000..132f84cc76b2f --- /dev/null +++ b/tests/ui/parser/recover/recover-enum2.stderr @@ -0,0 +1,37 @@ +error: expected type, found `{` + --> $DIR/recover-enum2.rs:6:18 + | +LL | Var3 { + | ---- while parsing this struct +LL | abc: {}, + | ^ expected type + +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{` + --> $DIR/recover-enum2.rs:25:22 + | +LL | enum Test4 { + | ----- while parsing this enum +LL | Nope(i32 {}) + | ^ expected one of 7 possible tokens + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + +error[E0308]: mismatched types + --> $DIR/recover-enum2.rs:11:9 + | +LL | let () = 1; + | ^^ - this expression has type `{integer}` + | | + | expected integer, found `()` + +error[E0308]: mismatched types + --> $DIR/recover-enum2.rs:27:13 + | +LL | let () = 1; + | ^^ - this expression has type `{integer}` + | | + | expected integer, found `()` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.rs b/tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.rs similarity index 100% rename from tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.rs rename to tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.rs diff --git a/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr b/tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr similarity index 85% rename from tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr rename to tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr index 17237c930979f..2b56498c50d3c 100644 --- a/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr +++ b/tests/ui/parser/recover/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr @@ -7,5 +7,5 @@ LL | | LL | | } | |_ help: remove extra angle bracket -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover-field-extra-angle-brackets.rs b/tests/ui/parser/recover/recover-field-extra-angle-brackets.rs similarity index 100% rename from tests/ui/parser/recover-field-extra-angle-brackets.rs rename to tests/ui/parser/recover/recover-field-extra-angle-brackets.rs diff --git a/tests/ui/parser/recover-field-extra-angle-brackets.stderr b/tests/ui/parser/recover/recover-field-extra-angle-brackets.stderr similarity index 81% rename from tests/ui/parser/recover-field-extra-angle-brackets.stderr rename to tests/ui/parser/recover/recover-field-extra-angle-brackets.stderr index 318e55f6e99ac..628626926a784 100644 --- a/tests/ui/parser/recover-field-extra-angle-brackets.stderr +++ b/tests/ui/parser/recover/recover-field-extra-angle-brackets.stderr @@ -4,5 +4,5 @@ error: unmatched angle bracket LL | first: Vec>, | ^ help: remove extra angle bracket -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover-field-semi.rs b/tests/ui/parser/recover/recover-field-semi.rs similarity index 100% rename from tests/ui/parser/recover-field-semi.rs rename to tests/ui/parser/recover/recover-field-semi.rs diff --git a/tests/ui/parser/recover-field-semi.stderr b/tests/ui/parser/recover/recover-field-semi.stderr similarity index 100% rename from tests/ui/parser/recover-field-semi.stderr rename to tests/ui/parser/recover/recover-field-semi.stderr diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.rs b/tests/ui/parser/recover/recover-fn-ptr-with-generics.rs similarity index 100% rename from tests/ui/parser/recover-fn-ptr-with-generics.rs rename to tests/ui/parser/recover/recover-fn-ptr-with-generics.rs diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.stderr b/tests/ui/parser/recover/recover-fn-ptr-with-generics.stderr similarity index 100% rename from tests/ui/parser/recover-fn-ptr-with-generics.stderr rename to tests/ui/parser/recover/recover-fn-ptr-with-generics.stderr diff --git a/tests/ui/parser/recover-fn-trait-from-fn-kw.rs b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.rs similarity index 100% rename from tests/ui/parser/recover-fn-trait-from-fn-kw.rs rename to tests/ui/parser/recover/recover-fn-trait-from-fn-kw.rs diff --git a/tests/ui/parser/recover-fn-trait-from-fn-kw.stderr b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr similarity index 100% rename from tests/ui/parser/recover-fn-trait-from-fn-kw.stderr rename to tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr diff --git a/tests/ui/parser/recover/recover-for-loop-parens-around-head.fixed b/tests/ui/parser/recover/recover-for-loop-parens-around-head.fixed new file mode 100644 index 0000000000000..6afc2d9935517 --- /dev/null +++ b/tests/ui/parser/recover/recover-for-loop-parens-around-head.fixed @@ -0,0 +1,15 @@ +// run-rustfix +// Here we test that the parser is able to recover in a situation like +// `for ( $pat in $expr )` since that is familiar syntax in other languages. +// Instead we suggest that the user writes `for $pat in $expr`. + +#![deny(unused)] // Make sure we don't trigger `unused_parens`. + +fn main() { + let vec = vec![1, 2, 3]; + + for _elem in vec { + //~^ ERROR unexpected parentheses surrounding `for` loop head + const _RECOVERY_WITNESS: u32 = 0u32; //~ ERROR mismatched types + } +} diff --git a/tests/ui/parser/recover-for-loop-parens-around-head.rs b/tests/ui/parser/recover/recover-for-loop-parens-around-head.rs similarity index 58% rename from tests/ui/parser/recover-for-loop-parens-around-head.rs rename to tests/ui/parser/recover/recover-for-loop-parens-around-head.rs index 053b428bd12cc..b1716900c49d0 100644 --- a/tests/ui/parser/recover-for-loop-parens-around-head.rs +++ b/tests/ui/parser/recover/recover-for-loop-parens-around-head.rs @@ -1,3 +1,4 @@ +// run-rustfix // Here we test that the parser is able to recover in a situation like // `for ( $pat in $expr )` since that is familiar syntax in other languages. // Instead we suggest that the user writes `for $pat in $expr`. @@ -7,9 +8,8 @@ fn main() { let vec = vec![1, 2, 3]; - for ( elem in vec ) { - //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found keyword `in` - //~| ERROR unexpected parentheses surrounding `for` loop head - const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types + for ( _elem in vec ) { + //~^ ERROR unexpected parentheses surrounding `for` loop head + const _RECOVERY_WITNESS: u32 = 0u8; //~ ERROR mismatched types } } diff --git a/tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr b/tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr new file mode 100644 index 0000000000000..beaa346e76c50 --- /dev/null +++ b/tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr @@ -0,0 +1,26 @@ +error: unexpected parentheses surrounding `for` loop head + --> $DIR/recover-for-loop-parens-around-head.rs:11:9 + | +LL | for ( _elem in vec ) { + | ^ ^ + | +help: remove parentheses in `for` loop + | +LL - for ( _elem in vec ) { +LL + for _elem in vec { + | + +error[E0308]: mismatched types + --> $DIR/recover-for-loop-parens-around-head.rs:13:40 + | +LL | const _RECOVERY_WITNESS: u32 = 0u8; + | ^^^ expected `u32`, found `u8` + | +help: change the type of the numeric literal from `u8` to `u32` + | +LL | const _RECOVERY_WITNESS: u32 = 0u32; + | ~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-from-bad-variant.rs b/tests/ui/parser/recover/recover-from-bad-variant.rs similarity index 100% rename from tests/ui/parser/recover-from-bad-variant.rs rename to tests/ui/parser/recover/recover-from-bad-variant.rs diff --git a/tests/ui/parser/recover-from-bad-variant.stderr b/tests/ui/parser/recover/recover-from-bad-variant.stderr similarity index 100% rename from tests/ui/parser/recover-from-bad-variant.stderr rename to tests/ui/parser/recover/recover-from-bad-variant.stderr diff --git a/tests/ui/parser/recover-from-homoglyph.rs b/tests/ui/parser/recover/recover-from-homoglyph.rs similarity index 100% rename from tests/ui/parser/recover-from-homoglyph.rs rename to tests/ui/parser/recover/recover-from-homoglyph.rs diff --git a/tests/ui/parser/recover-from-homoglyph.stderr b/tests/ui/parser/recover/recover-from-homoglyph.stderr similarity index 100% rename from tests/ui/parser/recover-from-homoglyph.stderr rename to tests/ui/parser/recover/recover-from-homoglyph.stderr diff --git a/tests/ui/parser/recover-labeled-non-block-expr.fixed b/tests/ui/parser/recover/recover-labeled-non-block-expr.fixed similarity index 100% rename from tests/ui/parser/recover-labeled-non-block-expr.fixed rename to tests/ui/parser/recover/recover-labeled-non-block-expr.fixed diff --git a/tests/ui/parser/recover-labeled-non-block-expr.rs b/tests/ui/parser/recover/recover-labeled-non-block-expr.rs similarity index 100% rename from tests/ui/parser/recover-labeled-non-block-expr.rs rename to tests/ui/parser/recover/recover-labeled-non-block-expr.rs diff --git a/tests/ui/parser/recover-labeled-non-block-expr.stderr b/tests/ui/parser/recover/recover-labeled-non-block-expr.stderr similarity index 100% rename from tests/ui/parser/recover-labeled-non-block-expr.stderr rename to tests/ui/parser/recover/recover-labeled-non-block-expr.stderr diff --git a/tests/ui/parser/recover-missing-semi-before-item.fixed b/tests/ui/parser/recover/recover-missing-semi-before-item.fixed similarity index 100% rename from tests/ui/parser/recover-missing-semi-before-item.fixed rename to tests/ui/parser/recover/recover-missing-semi-before-item.fixed diff --git a/tests/ui/parser/recover-missing-semi-before-item.rs b/tests/ui/parser/recover/recover-missing-semi-before-item.rs similarity index 100% rename from tests/ui/parser/recover-missing-semi-before-item.rs rename to tests/ui/parser/recover/recover-missing-semi-before-item.rs diff --git a/tests/ui/parser/recover-missing-semi-before-item.stderr b/tests/ui/parser/recover/recover-missing-semi-before-item.stderr similarity index 100% rename from tests/ui/parser/recover-missing-semi-before-item.stderr rename to tests/ui/parser/recover/recover-missing-semi-before-item.stderr diff --git a/tests/ui/parser/recover-missing-semi.rs b/tests/ui/parser/recover/recover-missing-semi.rs similarity index 100% rename from tests/ui/parser/recover-missing-semi.rs rename to tests/ui/parser/recover/recover-missing-semi.rs diff --git a/tests/ui/parser/recover-missing-semi.stderr b/tests/ui/parser/recover/recover-missing-semi.stderr similarity index 100% rename from tests/ui/parser/recover-missing-semi.stderr rename to tests/ui/parser/recover/recover-missing-semi.stderr diff --git a/tests/ui/parser/recover/recover-parens-around-match-arm-head.fixed b/tests/ui/parser/recover/recover-parens-around-match-arm-head.fixed new file mode 100644 index 0000000000000..6b9b7fa882a07 --- /dev/null +++ b/tests/ui/parser/recover/recover-parens-around-match-arm-head.fixed @@ -0,0 +1,12 @@ +// run-rustfix +fn main() { + let val = 42; + let x = match val { + 0 if true => { + //~^ ERROR unexpected parentheses surrounding `match` arm pattern + 42u8 + } + _ => 0u8, + }; + let _y: u32 = x.into(); //~ ERROR mismatched types +} diff --git a/tests/ui/parser/recover/recover-parens-around-match-arm-head.rs b/tests/ui/parser/recover/recover-parens-around-match-arm-head.rs new file mode 100644 index 0000000000000..f523581e2da19 --- /dev/null +++ b/tests/ui/parser/recover/recover-parens-around-match-arm-head.rs @@ -0,0 +1,12 @@ +// run-rustfix +fn main() { + let val = 42; + let x = match val { + (0 if true) => { + //~^ ERROR unexpected parentheses surrounding `match` arm pattern + 42u8 + } + _ => 0u8, + }; + let _y: u32 = x; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/recover/recover-parens-around-match-arm-head.stderr b/tests/ui/parser/recover/recover-parens-around-match-arm-head.stderr new file mode 100644 index 0000000000000..bad4d7d2f19f5 --- /dev/null +++ b/tests/ui/parser/recover/recover-parens-around-match-arm-head.stderr @@ -0,0 +1,28 @@ +error: unexpected parentheses surrounding `match` arm pattern + --> $DIR/recover-parens-around-match-arm-head.rs:5:9 + | +LL | (0 if true) => { + | ^ ^ + | +help: remove parentheses surrounding the pattern + | +LL - (0 if true) => { +LL + 0 if true => { + | + +error[E0308]: mismatched types + --> $DIR/recover-parens-around-match-arm-head.rs:11:19 + | +LL | let _y: u32 = x; + | --- ^ expected `u32`, found `u8` + | | + | expected due to this + | +help: you can convert a `u8` to a `u32` + | +LL | let _y: u32 = x.into(); + | +++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-quantified-closure.rs b/tests/ui/parser/recover/recover-quantified-closure.rs similarity index 100% rename from tests/ui/parser/recover-quantified-closure.rs rename to tests/ui/parser/recover/recover-quantified-closure.rs diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover/recover-quantified-closure.stderr similarity index 100% rename from tests/ui/parser/recover-quantified-closure.stderr rename to tests/ui/parser/recover/recover-quantified-closure.stderr diff --git a/tests/ui/parser/recover-range-pats.rs b/tests/ui/parser/recover/recover-range-pats.rs similarity index 100% rename from tests/ui/parser/recover-range-pats.rs rename to tests/ui/parser/recover/recover-range-pats.rs diff --git a/tests/ui/parser/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr similarity index 100% rename from tests/ui/parser/recover-range-pats.stderr rename to tests/ui/parser/recover/recover-range-pats.stderr diff --git a/tests/ui/parser/recover-ref-dyn-mut.rs b/tests/ui/parser/recover/recover-ref-dyn-mut.rs similarity index 100% rename from tests/ui/parser/recover-ref-dyn-mut.rs rename to tests/ui/parser/recover/recover-ref-dyn-mut.rs diff --git a/tests/ui/parser/recover-ref-dyn-mut.stderr b/tests/ui/parser/recover/recover-ref-dyn-mut.stderr similarity index 100% rename from tests/ui/parser/recover-ref-dyn-mut.stderr rename to tests/ui/parser/recover/recover-ref-dyn-mut.stderr diff --git a/tests/ui/parser/recover-struct.rs b/tests/ui/parser/recover/recover-struct.rs similarity index 100% rename from tests/ui/parser/recover-struct.rs rename to tests/ui/parser/recover/recover-struct.rs diff --git a/tests/ui/parser/recover-struct.stderr b/tests/ui/parser/recover/recover-struct.stderr similarity index 85% rename from tests/ui/parser/recover-struct.stderr rename to tests/ui/parser/recover/recover-struct.stderr index 9f6fb06caa34d..51a9e707756d8 100644 --- a/tests/ui/parser/recover-struct.stderr +++ b/tests/ui/parser/recover/recover-struct.stderr @@ -8,5 +8,5 @@ LL | Very LL | Bad | ^^^ unexpected token -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover-tuple-pat.rs b/tests/ui/parser/recover/recover-tuple-pat.rs similarity index 100% rename from tests/ui/parser/recover-tuple-pat.rs rename to tests/ui/parser/recover/recover-tuple-pat.rs diff --git a/tests/ui/parser/recover-tuple-pat.stderr b/tests/ui/parser/recover/recover-tuple-pat.stderr similarity index 80% rename from tests/ui/parser/recover-tuple-pat.stderr rename to tests/ui/parser/recover/recover-tuple-pat.stderr index 93a6a66a63082..e181f07201e59 100644 --- a/tests/ui/parser/recover-tuple-pat.stderr +++ b/tests/ui/parser/recover/recover-tuple-pat.stderr @@ -4,5 +4,5 @@ error: expected pattern, found `.` LL | (1, .=., 4) => { let _: usize = ""; } | ^ expected pattern -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover-tuple.rs b/tests/ui/parser/recover/recover-tuple.rs similarity index 100% rename from tests/ui/parser/recover-tuple.rs rename to tests/ui/parser/recover/recover-tuple.rs diff --git a/tests/ui/parser/recover-tuple.stderr b/tests/ui/parser/recover/recover-tuple.stderr similarity index 100% rename from tests/ui/parser/recover-tuple.stderr rename to tests/ui/parser/recover/recover-tuple.stderr diff --git a/tests/ui/parser/recover-unticked-labels.fixed b/tests/ui/parser/recover/recover-unticked-labels.fixed similarity index 100% rename from tests/ui/parser/recover-unticked-labels.fixed rename to tests/ui/parser/recover/recover-unticked-labels.fixed diff --git a/tests/ui/parser/recover-unticked-labels.rs b/tests/ui/parser/recover/recover-unticked-labels.rs similarity index 100% rename from tests/ui/parser/recover-unticked-labels.rs rename to tests/ui/parser/recover/recover-unticked-labels.rs diff --git a/tests/ui/parser/recover-unticked-labels.stderr b/tests/ui/parser/recover/recover-unticked-labels.stderr similarity index 100% rename from tests/ui/parser/recover-unticked-labels.stderr rename to tests/ui/parser/recover/recover-unticked-labels.stderr diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.fixed b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.fixed rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.rs b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.rs rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.stderr b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.stderr rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.rs b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-1.rs similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.rs rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-1.rs diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.stderr b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-1.stderr similarity index 100% rename from tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.stderr rename to tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-1.stderr diff --git a/tests/ui/parser/recovered-struct-variant.stderr b/tests/ui/parser/recovered-struct-variant.stderr index 78c67866fb0f1..f0050394ba0e7 100644 --- a/tests/ui/parser/recovered-struct-variant.stderr +++ b/tests/ui/parser/recovered-struct-variant.stderr @@ -6,5 +6,5 @@ LL | A { a, b: usize } | | | while parsing this struct -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/regions-out-of-scope-slice.stderr b/tests/ui/parser/regions-out-of-scope-slice.stderr index bbc657ffd614c..5d8f6af166bd4 100644 --- a/tests/ui/parser/regions-out-of-scope-slice.stderr +++ b/tests/ui/parser/regions-out-of-scope-slice.stderr @@ -7,5 +7,5 @@ LL | x = &'blk [1,2,3]; | annotated with lifetime here | help: remove the lifetime annotation -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.stderr b/tests/ui/parser/removed-syntax-closure-lifetime.stderr index e107c6b78b313..4c991d67ea75b 100644 --- a/tests/ui/parser/removed-syntax-closure-lifetime.stderr +++ b/tests/ui/parser/removed-syntax-closure-lifetime.stderr @@ -9,5 +9,5 @@ help: you might have meant to end the type parameters here LL | type closure = Box/fn()>; | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-enum-newtype.stderr b/tests/ui/parser/removed-syntax-enum-newtype.stderr index 8f7ca356798e2..5b917e93853da 100644 --- a/tests/ui/parser/removed-syntax-enum-newtype.stderr +++ b/tests/ui/parser/removed-syntax-enum-newtype.stderr @@ -6,5 +6,5 @@ LL | enum e = isize; | | | while parsing this enum -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-field-let.stderr b/tests/ui/parser/removed-syntax-field-let.stderr index 9bc18dabd6ead..339d056e6360f 100644 --- a/tests/ui/parser/removed-syntax-field-let.stderr +++ b/tests/ui/parser/removed-syntax-field-let.stderr @@ -10,5 +10,5 @@ LL | let foo: (), = note: the `let` keyword is not allowed in `struct` fields = note: see for more information -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-field-semicolon.stderr b/tests/ui/parser/removed-syntax-field-semicolon.stderr index 532d4fb2b61f0..522912a9e1c6d 100644 --- a/tests/ui/parser/removed-syntax-field-semicolon.stderr +++ b/tests/ui/parser/removed-syntax-field-semicolon.stderr @@ -6,5 +6,5 @@ LL | struct S { LL | bar: (); | ^ help: replace `;` with `,` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-fixed-vec.stderr b/tests/ui/parser/removed-syntax-fixed-vec.stderr index a2b97544f9e55..5bc9c2ccf00ad 100644 --- a/tests/ui/parser/removed-syntax-fixed-vec.stderr +++ b/tests/ui/parser/removed-syntax-fixed-vec.stderr @@ -4,5 +4,5 @@ error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` LL | type v = [isize * 3]; | ^ expected one of 7 possible tokens -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-mode.stderr b/tests/ui/parser/removed-syntax-mode.stderr index d0393b379f06d..fd964c4b7f046 100644 --- a/tests/ui/parser/removed-syntax-mode.stderr +++ b/tests/ui/parser/removed-syntax-mode.stderr @@ -4,5 +4,5 @@ error: expected parameter name, found `+` LL | fn f(+x: isize) {} | ^ expected parameter name -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.stderr b/tests/ui/parser/removed-syntax-mut-vec-expr.stderr index 313420fb9a4fd..a1aa1ae49e36a 100644 --- a/tests/ui/parser/removed-syntax-mut-vec-expr.stderr +++ b/tests/ui/parser/removed-syntax-mut-vec-expr.stderr @@ -4,5 +4,5 @@ error: expected expression, found keyword `mut` LL | let v = [mut 1, 2, 3, 4]; | ^^^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.stderr b/tests/ui/parser/removed-syntax-mut-vec-ty.stderr index 02b518e251678..beaae7cddaa91 100644 --- a/tests/ui/parser/removed-syntax-mut-vec-ty.stderr +++ b/tests/ui/parser/removed-syntax-mut-vec-ty.stderr @@ -4,5 +4,5 @@ error: expected type, found keyword `mut` LL | type v = [mut isize]; | ^^^ expected type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr b/tests/ui/parser/removed-syntax-ptr-lifetime.stderr index 914de43e62d66..5c74efffabff5 100644 --- a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr +++ b/tests/ui/parser/removed-syntax-ptr-lifetime.stderr @@ -4,5 +4,5 @@ error: expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` LL | type bptr = &lifetime/isize; | ^ expected one of `!`, `(`, `::`, `;`, `<`, or `where` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-record.stderr b/tests/ui/parser/removed-syntax-record.stderr index 0a1655840b550..dbf09f1c75b0d 100644 --- a/tests/ui/parser/removed-syntax-record.stderr +++ b/tests/ui/parser/removed-syntax-record.stderr @@ -4,5 +4,5 @@ error: expected type, found `{` LL | type t = { f: () }; | ^ expected type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr b/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr index 63d2fdb8cd4a9..7aaedad19d86e 100644 --- a/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr +++ b/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr @@ -4,5 +4,5 @@ error: expected expression, found keyword `mut` LL | let a_box = box mut 42; | ^^^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr b/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr index 39db0be9fbbd6..5ae1f4f587e6d 100644 --- a/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr +++ b/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr @@ -4,5 +4,5 @@ error: expected one of `>`, a const expression, lifetime, or type, found keyword LL | type mut_box = Box; | ^^^ expected one of `>`, a const expression, lifetime, or type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/removed-syntax-with-1.stderr b/tests/ui/parser/removed-syntax-with-1.stderr index c3f747b61b99f..78042678a87bb 100644 --- a/tests/ui/parser/removed-syntax-with-1.stderr +++ b/tests/ui/parser/removed-syntax-with-1.stderr @@ -7,5 +7,5 @@ LL | let b = S { foo: () with a, bar: () }; | | help: try adding a comma: `,` | while parsing this struct -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/self-in-function-arg.stderr b/tests/ui/parser/self-in-function-arg.stderr index 47d8381b0b1da..9ceec8d46d389 100644 --- a/tests/ui/parser/self-in-function-arg.stderr +++ b/tests/ui/parser/self-in-function-arg.stderr @@ -4,5 +4,5 @@ error: unexpected `self` parameter in function LL | fn foo(x:i32, self: i32) -> i32 { self } | ^^^^ must be the first parameter of an associated function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/semi-in-let-chain.rs b/tests/ui/parser/semi-in-let-chain.rs new file mode 100644 index 0000000000000..9c21af0372d25 --- /dev/null +++ b/tests/ui/parser/semi-in-let-chain.rs @@ -0,0 +1,27 @@ +// Issue #117720 + +#![feature(let_chains)] + +fn main() { + if let () = () + && let () = (); //~ERROR + && let () = () + { + } +} + +fn foo() { + if let () = () + && () == (); //~ERROR + && 1 < 0 + { + } +} + +fn bar() { + if let () = () + && () == (); //~ERROR + && let () = () + { + } +} diff --git a/tests/ui/parser/semi-in-let-chain.stderr b/tests/ui/parser/semi-in-let-chain.stderr new file mode 100644 index 0000000000000..c1a8f92965eb8 --- /dev/null +++ b/tests/ui/parser/semi-in-let-chain.stderr @@ -0,0 +1,50 @@ +error: expected `{`, found `;` + --> $DIR/semi-in-let-chain.rs:7:23 + | +LL | && let () = (); + | ^ expected `{` + | +note: you likely meant to continue parsing the let-chain starting here + --> $DIR/semi-in-let-chain.rs:8:9 + | +LL | && let () = () + | ^^^^^^ +help: consider removing this semicolon to parse the `let` as part of the same chain + | +LL - && let () = (); +LL + && let () = () + | + +error: expected `{`, found `;` + --> $DIR/semi-in-let-chain.rs:15:20 + | +LL | && () == (); + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/semi-in-let-chain.rs:14:8 + | +LL | if let () = () + | ________^ +LL | | && () == (); + | |___________________^ + +error: expected `{`, found `;` + --> $DIR/semi-in-let-chain.rs:23:20 + | +LL | && () == (); + | ^ expected `{` + | +note: you likely meant to continue parsing the let-chain starting here + --> $DIR/semi-in-let-chain.rs:24:9 + | +LL | && let () = () + | ^^^^^^ +help: consider removing this semicolon to parse the `let` as part of the same chain + | +LL - && () == (); +LL + && () == () + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/shebang/issue-71471-ignore-tidy.stderr b/tests/ui/parser/shebang/issue-71471-ignore-tidy.stderr index 896a9dc83d8b9..41cd4fb93faa0 100644 --- a/tests/ui/parser/shebang/issue-71471-ignore-tidy.stderr +++ b/tests/ui/parser/shebang/issue-71471-ignore-tidy.stderr @@ -4,5 +4,5 @@ error: expected `[`, found `B` LL | #!B | ^ expected `[` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/shebang/shebang-doc-comment.stderr b/tests/ui/parser/shebang/shebang-doc-comment.stderr index a36b2a2f72b4e..92fefded55a50 100644 --- a/tests/ui/parser/shebang/shebang-doc-comment.stderr +++ b/tests/ui/parser/shebang/shebang-doc-comment.stderr @@ -6,5 +6,5 @@ LL | [allow(unused_variables)] | = note: for a full list of items that can appear in modules, see -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/shebang/shebang-must-start-file.stderr b/tests/ui/parser/shebang/shebang-must-start-file.stderr index 50543e8bdb816..56991c96b7a0a 100644 --- a/tests/ui/parser/shebang/shebang-must-start-file.stderr +++ b/tests/ui/parser/shebang/shebang-must-start-file.stderr @@ -4,5 +4,5 @@ error: expected `[`, found `/` LL | #!/bin/bash | ^ expected `[` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/similar-tokens.stderr b/tests/ui/parser/similar-tokens.stderr index 90acfc052ddd4..7070232c1423a 100644 --- a/tests/ui/parser/similar-tokens.stderr +++ b/tests/ui/parser/similar-tokens.stderr @@ -7,5 +7,5 @@ LL | use x::{A. B}; | expected one of `,`, `::`, `as`, or `}` | help: missing `,` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/struct-filed-with-attr.stderr b/tests/ui/parser/struct-filed-with-attr.stderr index c2cd7e82ead41..d850ed620de43 100644 --- a/tests/ui/parser/struct-filed-with-attr.stderr +++ b/tests/ui/parser/struct-filed-with-attr.stderr @@ -4,5 +4,5 @@ error: expected `,`, or `}`, found `#` LL | owo: bool | ^ help: try adding a comma: `,` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/struct-literal-in-match-discriminant.stderr b/tests/ui/parser/struct-literal-in-match-discriminant.stderr index 692b4d73503a4..5177f5f126e0b 100644 --- a/tests/ui/parser/struct-literal-in-match-discriminant.stderr +++ b/tests/ui/parser/struct-literal-in-match-discriminant.stderr @@ -14,5 +14,5 @@ LL | x: 3 LL ~ }) { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest-assoc-const.stderr b/tests/ui/parser/suggest-assoc-const.stderr index 2ddfa07c5be47..7ba1dbdff7e59 100644 --- a/tests/ui/parser/suggest-assoc-const.stderr +++ b/tests/ui/parser/suggest-assoc-const.stderr @@ -4,5 +4,5 @@ error: non-item in item list LL | let _X: i32; | ^^^ help: consider using `const` instead of `let` for associated const: `const` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest-const-for-global-var.stderr b/tests/ui/parser/suggest-const-for-global-var.stderr index 94e44ec7f6ce1..235e621d8827b 100644 --- a/tests/ui/parser/suggest-const-for-global-var.stderr +++ b/tests/ui/parser/suggest-const-for-global-var.stderr @@ -4,5 +4,5 @@ error: expected item, found keyword `let` LL | let X: i32 = 12; | ^^^ consider using `const` or `static` instead of `let` for global variables -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr index 396e0c130f11b..c716d5908ea11 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -11,5 +11,5 @@ LL | fn bar() {}; LL | } | - item list ends here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest-semi-in-array.stderr b/tests/ui/parser/suggest-semi-in-array.stderr index d7cd6efae41d3..25b0679957ea5 100644 --- a/tests/ui/parser/suggest-semi-in-array.stderr +++ b/tests/ui/parser/suggest-semi-in-array.stderr @@ -6,5 +6,5 @@ LL | let v = [1 LL | 2]; | ^ unexpected token -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest-semicolon-before-array.stderr b/tests/ui/parser/suggest-semicolon-before-array.stderr index 8a33321fbd563..f5573f5e4e34f 100644 --- a/tests/ui/parser/suggest-semicolon-before-array.stderr +++ b/tests/ui/parser/suggest-semicolon-before-array.stderr @@ -9,5 +9,5 @@ help: consider adding `;` here LL | foo(); | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest_misplaced_generics/enum.stderr b/tests/ui/parser/suggest_misplaced_generics/enum.stderr index 5f5947627ee5c..7bef9d7098800 100644 --- a/tests/ui/parser/suggest_misplaced_generics/enum.stderr +++ b/tests/ui/parser/suggest_misplaced_generics/enum.stderr @@ -10,5 +10,5 @@ LL - enum Foo { Variant(T) } LL + enum Foo { Variant(T) } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest_misplaced_generics/existing_generics.stderr b/tests/ui/parser/suggest_misplaced_generics/existing_generics.stderr index 89716e6f1ed0a..e887c08815110 100644 --- a/tests/ui/parser/suggest_misplaced_generics/existing_generics.stderr +++ b/tests/ui/parser/suggest_misplaced_generics/existing_generics.stderr @@ -6,5 +6,5 @@ LL | fn<'a, B: 'a + std::ops::Add> f(_x: B) { } | = help: place the generic parameter name after the fn name -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr b/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr index 061d0910a742d..18e173a9db01f 100644 --- a/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr +++ b/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr @@ -10,5 +10,5 @@ LL - fn<'a, B: 'a + std::ops::Add> f(_x: B) { } LL + fn f<'a, B: 'a + std::ops::Add>(_x: B) { } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr b/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr index 47e12016938d8..cde69083593b1 100644 --- a/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr +++ b/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `<` LL | fn<~>()> id(x: T) -> T { x } | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-simple.stderr b/tests/ui/parser/suggest_misplaced_generics/fn-simple.stderr index e749f1a0d00d6..e77df69eeb1d5 100644 --- a/tests/ui/parser/suggest_misplaced_generics/fn-simple.stderr +++ b/tests/ui/parser/suggest_misplaced_generics/fn-simple.stderr @@ -10,5 +10,5 @@ LL - fn id(x: T) -> T { x } LL + fn id(x: T) -> T { x } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest_misplaced_generics/struct.stderr b/tests/ui/parser/suggest_misplaced_generics/struct.stderr index 2b650907092d1..09e176adb4d87 100644 --- a/tests/ui/parser/suggest_misplaced_generics/struct.stderr +++ b/tests/ui/parser/suggest_misplaced_generics/struct.stderr @@ -10,5 +10,5 @@ LL - struct Foo { x: T } LL + struct Foo { x: T } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest_misplaced_generics/trait.stderr b/tests/ui/parser/suggest_misplaced_generics/trait.stderr index ac86cfa469704..0d0b780d41f70 100644 --- a/tests/ui/parser/suggest_misplaced_generics/trait.stderr +++ b/tests/ui/parser/suggest_misplaced_generics/trait.stderr @@ -10,5 +10,5 @@ LL - trait Foo { LL + trait Foo { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/suggest_misplaced_generics/type.stderr b/tests/ui/parser/suggest_misplaced_generics/type.stderr index 22744f6cf37fb..3034535d55620 100644 --- a/tests/ui/parser/suggest_misplaced_generics/type.stderr +++ b/tests/ui/parser/suggest_misplaced_generics/type.stderr @@ -10,5 +10,5 @@ LL - type Foo = T; LL + type Foo = T; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/trailing-carriage-return-in-string.stderr b/tests/ui/parser/trailing-carriage-return-in-string.stderr index 8a44e02707ce5..fa2677921b32d 100644 --- a/tests/ui/parser/trailing-carriage-return-in-string.stderr +++ b/tests/ui/parser/trailing-carriage-return-in-string.stderr @@ -6,5 +6,5 @@ LL | let bad = "This is \ a test"; | = help: this is an isolated carriage return; consider checking your editor and version control settings -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/trailing-question-in-macro-type.stderr b/tests/ui/parser/trailing-question-in-macro-type.stderr index c096ae04fbbb6..e3d33bf251d66 100644 --- a/tests/ui/parser/trailing-question-in-macro-type.stderr +++ b/tests/ui/parser/trailing-question-in-macro-type.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `o` in this scope LL | fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) }; | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/trait-bounds-not-on-impl.stderr b/tests/ui/parser/trait-bounds-not-on-impl.stderr index 8d2d5e3d7ddd2..7f51bd97e5d9e 100644 --- a/tests/ui/parser/trait-bounds-not-on-impl.stderr +++ b/tests/ui/parser/trait-bounds-not-on-impl.stderr @@ -4,5 +4,5 @@ error: expected a trait, found type LL | impl Foo + Owned for Bar {} | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/trait-object-polytrait-priority.stderr b/tests/ui/parser/trait-object-polytrait-priority.stderr index a6add6079cece..23ec1e9cf3d45 100644 --- a/tests/ui/parser/trait-object-polytrait-priority.stderr +++ b/tests/ui/parser/trait-object-polytrait-priority.stderr @@ -4,6 +4,6 @@ error[E0178]: expected a path on the left-hand side of `+`, not `&for<'a> Trait< LL | let _: &for<'a> Trait<'a> + 'static; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try adding parentheses: `&(for<'a> Trait<'a> + 'static)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0178`. diff --git a/tests/ui/parser/trait-pub-assoc-const.stderr b/tests/ui/parser/trait-pub-assoc-const.stderr index c14a2f2eea527..436f6a3909c32 100644 --- a/tests/ui/parser/trait-pub-assoc-const.stderr +++ b/tests/ui/parser/trait-pub-assoc-const.stderr @@ -6,6 +6,6 @@ LL | pub const Foo: u32; | = note: trait items always share the visibility of their trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/parser/trait-pub-assoc-ty.stderr b/tests/ui/parser/trait-pub-assoc-ty.stderr index 7f6e7350ca7a2..279e3a95354b5 100644 --- a/tests/ui/parser/trait-pub-assoc-ty.stderr +++ b/tests/ui/parser/trait-pub-assoc-ty.stderr @@ -6,6 +6,6 @@ LL | pub type Foo; | = note: trait items always share the visibility of their trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/parser/trait-pub-method.stderr b/tests/ui/parser/trait-pub-method.stderr index 2bf1d468a8535..ee8b6f7cb62eb 100644 --- a/tests/ui/parser/trait-pub-method.stderr +++ b/tests/ui/parser/trait-pub-method.stderr @@ -6,6 +6,6 @@ LL | pub fn foo(); | = note: trait items always share the visibility of their trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr index 94b300a7bd765..d40b982da7c39 100644 --- a/tests/ui/parser/unbalanced-doublequote.stderr +++ b/tests/ui/parser/unbalanced-doublequote.stderr @@ -5,6 +5,6 @@ LL | / " LL | | } | |__^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0765`. diff --git a/tests/ui/parser/unclosed-braces.stderr b/tests/ui/parser/unclosed-braces.stderr index cbc5f8de4c3a7..acd92ac792597 100644 --- a/tests/ui/parser/unclosed-braces.stderr +++ b/tests/ui/parser/unclosed-braces.stderr @@ -13,5 +13,5 @@ LL | } LL | | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.stderr b/tests/ui/parser/unclosed-delimiter-in-dep.stderr index a46d020b9672e..1231decd9ddfe 100644 --- a/tests/ui/parser/unclosed-delimiter-in-dep.stderr +++ b/tests/ui/parser/unclosed-delimiter-in-dep.stderr @@ -9,5 +9,5 @@ LL | } LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unclosed_delim_mod.stderr b/tests/ui/parser/unclosed_delim_mod.stderr index a46d020b9672e..1231decd9ddfe 100644 --- a/tests/ui/parser/unclosed_delim_mod.stderr +++ b/tests/ui/parser/unclosed_delim_mod.stderr @@ -9,5 +9,5 @@ LL | } LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr b/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr index 430a13e6e0713..c6960892b2bc8 100644 --- a/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr +++ b/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr @@ -4,5 +4,5 @@ error: this file contains an unclosed delimiter LL | fn foo() { | - unclosed delimiter ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unmatched-langle-2.stderr b/tests/ui/parser/unmatched-langle-2.stderr index 773bb33d8d3f3..9881c6ba51baa 100644 --- a/tests/ui/parser/unmatched-langle-2.stderr +++ b/tests/ui/parser/unmatched-langle-2.stderr @@ -4,5 +4,5 @@ error: expected `::`, found `(` LL | foo::(); | ^ expected `::` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr index 4acf72c5dae89..77f6e93be10bb 100644 --- a/tests/ui/parser/unsafe-foreign-mod.stderr +++ b/tests/ui/parser/unsafe-foreign-mod.stderr @@ -4,5 +4,5 @@ error: extern block cannot be declared unsafe LL | unsafe extern "C" { | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unsized.stderr b/tests/ui/parser/unsized.stderr index 3d4ed526b6ace..1bb4aa97d8b1c 100644 --- a/tests/ui/parser/unsized.stderr +++ b/tests/ui/parser/unsized.stderr @@ -4,5 +4,5 @@ error: expected `where`, `{`, `(`, or `;` after struct name, found keyword `for` LL | struct S1 for type; | ^^^ expected `where`, `{`, `(`, or `;` after struct name -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unsized2.stderr b/tests/ui/parser/unsized2.stderr index 17e39b292005a..10f4c8332a369 100644 --- a/tests/ui/parser/unsized2.stderr +++ b/tests/ui/parser/unsized2.stderr @@ -4,5 +4,5 @@ error: expected expression, found keyword `type` LL | f(); | ^^^^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/use-ends-with-mod-sep.stderr b/tests/ui/parser/use-ends-with-mod-sep.stderr index bd0d881a06c35..2f8e09c07e182 100644 --- a/tests/ui/parser/use-ends-with-mod-sep.stderr +++ b/tests/ui/parser/use-ends-with-mod-sep.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `;` LL | use std::any::; | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/use-unclosed-brace.stderr b/tests/ui/parser/use-unclosed-brace.stderr index ad5bb2de1b256..6e624cb913163 100644 --- a/tests/ui/parser/use-unclosed-brace.stderr +++ b/tests/ui/parser/use-unclosed-brace.stderr @@ -7,5 +7,5 @@ LL | use foo::{bar, baz; LL | fn main() {} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/virtual-structs.stderr b/tests/ui/parser/virtual-structs.stderr index 268fc10579634..7b45e77ba9c97 100644 --- a/tests/ui/parser/virtual-structs.stderr +++ b/tests/ui/parser/virtual-structs.stderr @@ -6,5 +6,5 @@ LL | virtual struct SuperStruct { | = note: for a full list of items that can appear in modules, see -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/where-clauses-no-bounds-or-predicates.stderr b/tests/ui/parser/where-clauses-no-bounds-or-predicates.stderr index b80b0a409065b..4bd0cc885c99b 100644 --- a/tests/ui/parser/where-clauses-no-bounds-or-predicates.stderr +++ b/tests/ui/parser/where-clauses-no-bounds-or-predicates.stderr @@ -4,5 +4,5 @@ error: expected `:`, found `{` LL | fn foo<'a>() where 'a {} | ^ expected `:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/parser/while-if-let-without-body.stderr b/tests/ui/parser/while-if-let-without-body.stderr index 2dac45c115d11..0bd68b7b9aec9 100644 --- a/tests/ui/parser/while-if-let-without-body.stderr +++ b/tests/ui/parser/while-if-let-without-body.stderr @@ -14,5 +14,5 @@ LL | | } LL | } | ^ expected `{` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr index a481ca4683382..4a6d36a4e0c19 100644 --- a/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr @@ -8,6 +8,6 @@ LL | fn f(a @ A(u): A) -> Box { | = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr index c440f4619f52a..815a4ade9956e 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr @@ -12,5 +12,5 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref a @ ref b = U; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr index e0e623fa544f7..d0ffb59a6ec16 100644 --- a/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr +++ b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr @@ -12,6 +12,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref a @ NC(b, ref c @ NC(d, e)) = NC(C, NC(C, C)); | +++ +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/issue-114896.stderr b/tests/ui/pattern/issue-114896.stderr index ffeb7bc136508..285c9109e1b88 100644 --- a/tests/ui/pattern/issue-114896.stderr +++ b/tests/ui/pattern/issue-114896.stderr @@ -6,6 +6,6 @@ LL | let &b = a; LL | b.make_ascii_uppercase(); | ^ cannot borrow as mutable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr index e6cb6c1ddac77..c1e85d0bb48a9 100644 --- a/tests/ui/pattern/issue-115599.stderr +++ b/tests/ui/pattern/issue-115599.stderr @@ -7,5 +7,5 @@ LL | if let CONST_STRING = empty_str {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/issue-52240.stderr b/tests/ui/pattern/issue-52240.stderr index 69b663b17d340..dcf3da45e5358 100644 --- a/tests/ui/pattern/issue-52240.stderr +++ b/tests/ui/pattern/issue-52240.stderr @@ -4,6 +4,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | if let (Some(Foo::Bar(ref mut val)), _) = (&arr.get(0), 0) { | ^^^^^^^^^^^ cannot borrow as mutable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr b/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr index f40642f300cdf..087ff513bb328 100644 --- a/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr +++ b/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr @@ -6,5 +6,5 @@ LL | struct Bug { LL | incorrect_field: 0, | ^ expected type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/issue-72565.stderr b/tests/ui/pattern/issue-72565.stderr index 0519720694d70..b503a17fe849f 100644 --- a/tests/ui/pattern/issue-72565.stderr +++ b/tests/ui/pattern/issue-72565.stderr @@ -4,5 +4,5 @@ error: `dyn PartialEq` cannot be used in patterns LL | F => panic!(), | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr b/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr index 75b6c163b2cc3..167016397d212 100644 --- a/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr +++ b/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr @@ -6,5 +6,5 @@ LL | let mut &x = &0; | = note: `mut` may be followed by `variable` and `variable @ pattern` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/issue-94866.stderr b/tests/ui/pattern/issue-94866.stderr index dee4b3f557c7d..8edb95f76f07c 100644 --- a/tests/ui/pattern/issue-94866.stderr +++ b/tests/ui/pattern/issue-94866.stderr @@ -16,6 +16,6 @@ LL ~ Enum::A => m!(), LL + Enum::B => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/issue-95878.stderr b/tests/ui/pattern/issue-95878.stderr index e0eea06e0a3c3..e938c67f30878 100644 --- a/tests/ui/pattern/issue-95878.stderr +++ b/tests/ui/pattern/issue-95878.stderr @@ -4,5 +4,5 @@ error: expected identifier, found keyword `Self` LL | ref Self => (), | ^^^^ expected identifier, found keyword -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr index d3ab533e35e4a..85379d6605bca 100644 --- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr @@ -12,6 +12,6 @@ help: consider borrowing the pattern binding LL | let (a, ref mut b) = &mut p; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr index 65030b6225001..494e5e2b2e85f 100644 --- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr @@ -12,6 +12,6 @@ help: consider borrowing the pattern binding LL | let (a, ref mut b) = &p; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs new file mode 100644 index 0000000000000..915f3e75e7bf3 --- /dev/null +++ b/tests/ui/pattern/never_patterns.rs @@ -0,0 +1,99 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn main() {} + +// The classic use for empty types. +fn safe_unwrap_result(res: Result) { + let Ok(_x) = res; + // FIXME(never_patterns): These should be allowed + let (Ok(_x) | Err(!)) = &res; + //~^ ERROR: is not bound in all patterns + let (Ok(_x) | Err(&!)) = res.as_ref(); + //~^ ERROR: is not bound in all patterns +} + +// Check we only accept `!` where we want to. +fn never_pattern_location(void: Void) { + // FIXME(never_patterns): Don't accept on a non-empty type. + match Some(0) { + None => {} + Some(!), + } + // FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches. + match () { + () => {} + !, + } + // FIXME(never_patterns): Don't accept even on an empty branch. + match None:: { + None => {} + !, + } + // FIXME(never_patterns): Let alone if the emptiness is behind a reference. + match None::<&Void> { + None => {} + !, + } + // Participate in match ergonomics. + match &void { + ! + } + match &&void { + ! + } + match &&void { + &! + } + match &None:: { + None => {} + Some(!) + } + match None::<&Void> { + None => {} + Some(!), + } + // Accept on a composite empty type. + match None::<&(u32, Void)> { + None => {} + Some(&!), + } + // Accept on an simple empty type. + match None:: { + None => {} + Some(!), + } + match None::<&Void> { + None => {} + Some(&!), + } + match None::<&(u32, Void)> { + None => {} + Some(&(_, !)), + } +} + +fn never_and_bindings() { + let x: Result = Ok(false); + + // FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings. + match x { + Ok(_x) | Err(&!) => {} + //~^ ERROR: is not bound in all patterns + } + let (Ok(_x) | Err(&!)) = x; + //~^ ERROR: is not bound in all patterns + + // FIXME(never_patterns): A never pattern mustn't have bindings. + match x { + Ok(_) => {} + Err(&(_b, !)), + } + match x { + Ok(_a) | Err(&(_b, !)) => {} + //~^ ERROR: is not bound in all patterns + //~| ERROR: is not bound in all patterns + } +} diff --git a/tests/ui/pattern/never_patterns.stderr b/tests/ui/pattern/never_patterns.stderr new file mode 100644 index 0000000000000..11e50debfd39a --- /dev/null +++ b/tests/ui/pattern/never_patterns.stderr @@ -0,0 +1,51 @@ +error[E0408]: variable `_x` is not bound in all patterns + --> $DIR/never_patterns.rs:12:19 + | +LL | let (Ok(_x) | Err(!)) = &res; + | -- ^^^^^^ pattern doesn't bind `_x` + | | + | variable not in all patterns + +error[E0408]: variable `_x` is not bound in all patterns + --> $DIR/never_patterns.rs:14:19 + | +LL | let (Ok(_x) | Err(&!)) = res.as_ref(); + | -- ^^^^^^^ pattern doesn't bind `_x` + | | + | variable not in all patterns + +error[E0408]: variable `_x` is not bound in all patterns + --> $DIR/never_patterns.rs:83:18 + | +LL | Ok(_x) | Err(&!) => {} + | -- ^^^^^^^ pattern doesn't bind `_x` + | | + | variable not in all patterns + +error[E0408]: variable `_x` is not bound in all patterns + --> $DIR/never_patterns.rs:86:19 + | +LL | let (Ok(_x) | Err(&!)) = x; + | -- ^^^^^^^ pattern doesn't bind `_x` + | | + | variable not in all patterns + +error[E0408]: variable `_b` is not bound in all patterns + --> $DIR/never_patterns.rs:95:9 + | +LL | Ok(_a) | Err(&(_b, !)) => {} + | ^^^^^^ -- variable not in all patterns + | | + | pattern doesn't bind `_b` + +error[E0408]: variable `_a` is not bound in all patterns + --> $DIR/never_patterns.rs:95:18 + | +LL | Ok(_a) | Err(&(_b, !)) => {} + | -- ^^^^^^^^^^^^^ pattern doesn't bind `_a` + | | + | variable not in all patterns + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/pattern/pat-shadow-in-nested-binding.stderr b/tests/ui/pattern/pat-shadow-in-nested-binding.stderr index 0c5824be95df1..ad175710b096a 100644 --- a/tests/ui/pattern/pat-shadow-in-nested-binding.stderr +++ b/tests/ui/pattern/pat-shadow-in-nested-binding.stderr @@ -7,6 +7,6 @@ LL | struct foo(usize); LL | let (foo, _) = (2, 3); | ^^^ cannot be named the same as a tuple struct -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/pattern/pat-struct-field-expr-has-type.stderr b/tests/ui/pattern/pat-struct-field-expr-has-type.stderr index 0290752931067..80bedfe7859ac 100644 --- a/tests/ui/pattern/pat-struct-field-expr-has-type.stderr +++ b/tests/ui/pattern/pat-struct-field-expr-has-type.stderr @@ -9,6 +9,6 @@ LL | S { f: Ok(_) } => {} = note: expected type `u8` found enum `Result<_, _>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/pat-type-err-formal-param.stderr b/tests/ui/pattern/pat-type-err-formal-param.stderr index 4f482c52a98f8..c100aa6070f7e 100644 --- a/tests/ui/pattern/pat-type-err-formal-param.stderr +++ b/tests/ui/pattern/pat-type-err-formal-param.stderr @@ -6,6 +6,6 @@ LL | fn foo(Tuple(_): String) {} | | | expected `String`, found `Tuple` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.fixed b/tests/ui/pattern/pattern-bad-ref-box-order.fixed new file mode 100644 index 0000000000000..8825744a08b1d --- /dev/null +++ b/tests/ui/pattern/pattern-bad-ref-box-order.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +#![feature(box_patterns)] +#![allow(dead_code)] + +fn foo(f: Option>) { + match f { + Some(box ref _i) => {}, + //~^ ERROR switch the order of `ref` and `box` + None => {} + } +} + +fn main() { } diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.rs b/tests/ui/pattern/pattern-bad-ref-box-order.rs new file mode 100644 index 0000000000000..f3fcf0ceacf0b --- /dev/null +++ b/tests/ui/pattern/pattern-bad-ref-box-order.rs @@ -0,0 +1,14 @@ +// run-rustfix + +#![feature(box_patterns)] +#![allow(dead_code)] + +fn foo(f: Option>) { + match f { + Some(ref box _i) => {}, + //~^ ERROR switch the order of `ref` and `box` + None => {} + } +} + +fn main() { } diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.stderr b/tests/ui/pattern/pattern-bad-ref-box-order.stderr new file mode 100644 index 0000000000000..a49f05c1028d8 --- /dev/null +++ b/tests/ui/pattern/pattern-bad-ref-box-order.stderr @@ -0,0 +1,8 @@ +error: switch the order of `ref` and `box` + --> $DIR/pattern-bad-ref-box-order.rs:8:14 + | +LL | Some(ref box _i) => {}, + | ^^^^^^^ help: swap them: `box ref` + +error: aborting due to 1 previous error + diff --git a/tests/ui/pattern/pattern-ident-path-generics.stderr b/tests/ui/pattern/pattern-ident-path-generics.stderr index 62283dfe9b64f..942a42650751b 100644 --- a/tests/ui/pattern/pattern-ident-path-generics.stderr +++ b/tests/ui/pattern/pattern-ident-path-generics.stderr @@ -9,6 +9,6 @@ LL | None:: => {} = note: expected enum `Option<&str>` found enum `Option` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/pattern-tyvar-2.stderr b/tests/ui/pattern/pattern-tyvar-2.stderr index 121817e705690..c6540e795589f 100644 --- a/tests/ui/pattern/pattern-tyvar-2.stderr +++ b/tests/ui/pattern/pattern-tyvar-2.stderr @@ -6,6 +6,6 @@ LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; | | | Vec -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/pattern/pattern-tyvar.stderr b/tests/ui/pattern/pattern-tyvar.stderr index 4eb00254861d5..492b34cd29207 100644 --- a/tests/ui/pattern/pattern-tyvar.stderr +++ b/tests/ui/pattern/pattern-tyvar.stderr @@ -9,6 +9,6 @@ LL | Bar::T1(_, Some::(x)) => { = note: expected enum `Option>` found enum `Option` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs new file mode 100644 index 0000000000000..a619fcafc8614 --- /dev/null +++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs @@ -0,0 +1,9 @@ +fn main() { + match &[1, 2, 3][..] { + [1, rest..] => println!("{rest:?}"), + //~^ ERROR cannot find value `rest` in this scope + //~| ERROR cannot find value `rest` in this scope + //~| ERROR `X..` patterns in slices are experimental + _ => {} + } +} diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr new file mode 100644 index 0000000000000..cddd01212798e --- /dev/null +++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr @@ -0,0 +1,30 @@ +error[E0425]: cannot find value `rest` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13 + | +LL | [1, rest..] => println!("{rest:?}"), + | ^^^^ not found in this scope + | +help: if you meant to collect the rest of the slice in `rest`, use the at operator + | +LL | [1, rest @ ..] => println!("{rest:?}"), + | + + +error[E0425]: cannot find value `rest` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:35 + | +LL | [1, rest..] => println!("{rest:?}"), + | ^^^^ not found in this scope + +error[E0658]: `X..` patterns in slices are experimental + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13 + | +LL | [1, rest..] => println!("{rest:?}"), + | ^^^^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0658. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/pattern/slice-patterns-irrefutable.stderr b/tests/ui/pattern/slice-patterns-irrefutable.stderr index e98ee28d68686..9b46f8a885468 100644 --- a/tests/ui/pattern/slice-patterns-irrefutable.stderr +++ b/tests/ui/pattern/slice-patterns-irrefutable.stderr @@ -12,6 +12,6 @@ help: consider giving `b` an explicit type, where the placeholders `_` are speci LL | let b: [_; 3]; | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr index 5f2c89246e396..77d552b0cf651 100644 --- a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr +++ b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr @@ -16,6 +16,6 @@ LL ~ Some(_) => {}, LL + None => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr index dbd46da441316..2352ecd0a470d 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -7,5 +7,5 @@ LL | if let CONSTANT = &&MyType { = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs index 6dc1425cf037e..27e305a397242 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.rs +++ b/tests/ui/pattern/usefulness/consts-opaque.rs @@ -95,8 +95,10 @@ fn main() { const QUUX: Quux = quux; match QUUX { - QUUX => {} - QUUX => {} + QUUX => {} //~WARN behave unpredictably + //~| previously accepted + QUUX => {} //~WARN behave unpredictably + //~| previously accepted _ => {} } @@ -105,14 +107,17 @@ fn main() { const WRAPQUUX: Wrap = Wrap(quux); match WRAPQUUX { - WRAPQUUX => {} - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} } match WRAPQUUX { Wrap(_) => {} - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted } match WRAPQUUX { @@ -121,7 +126,8 @@ fn main() { match WRAPQUUX { //~^ ERROR: non-exhaustive patterns: `Wrap(_)` not covered - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted } #[derive(PartialEq, Eq)] @@ -132,9 +138,11 @@ fn main() { const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); match WHOKNOWSQUUX { - WHOKNOWSQUUX => {} + WHOKNOWSQUUX => {} //~WARN behave unpredictably + //~| previously accepted WhoKnows::Yay(_) => {} - WHOKNOWSQUUX => {} + WHOKNOWSQUUX => {} //~WARN behave unpredictably + //~| previously accepted WhoKnows::Nope => {} } } diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 51f2f276bbe2e..09f72ba927e1f 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -91,24 +91,96 @@ LL | BAZ => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:98:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:100:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:110:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:112:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:119:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:129:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:141:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:144:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + error[E0004]: non-exhaustive patterns: `Wrap(_)` not covered - --> $DIR/consts-opaque.rs:122:11 + --> $DIR/consts-opaque.rs:127:11 | LL | match WRAPQUUX { | ^^^^^^^^ pattern `Wrap(_)` not covered | note: `Wrap usize>` defined here - --> $DIR/consts-opaque.rs:104:12 + --> $DIR/consts-opaque.rs:106:12 | LL | struct Wrap(T); | ^^^^ = note: the matched value is of type `Wrap usize>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ WRAPQUUX => {}, -LL + Wrap(_) => todo!() - | +LL | WRAPQUUX => {}, Wrap(_) => todo!() + | ++++++++++++++++++++ -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 10 previous errors; 9 warnings emitted For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/guards.stderr b/tests/ui/pattern/usefulness/guards.stderr index fc6748958de5b..ad9046fe24828 100644 --- a/tests/ui/pattern/usefulness/guards.stderr +++ b/tests/ui/pattern/usefulness/guards.stderr @@ -11,6 +11,6 @@ LL ~ 128 ..= 255 if true => {}, LL + 128_u8..=u8::MAX => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr deleted file mode 100644 index 7f26c93aa28a0..0000000000000 --- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0004]: non-exhaustive patterns: type `usize` is non-empty - --> $DIR/pointer-sized-int.rs:54:11 - | -LL | match 7usize {} - | ^^^^^^ - | - = note: the matched value is of type `usize` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match 7usize { -LL + _ => todo!(), -LL + } - | - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr index d16ec5412db16..416523213c098 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr @@ -1,162 +1,150 @@ error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:14:11 + --> $DIR/pointer-sized-int.rs:13:11 | LL | match 0usize { | ^^^^^^ pattern `usize::MAX..` not covered | = note: the matched value is of type `usize` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ 0 ..= usize::MAX => {}, +LL ~ 0..=usize::MAX => {}, LL + usize::MAX.. => todo!() | error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:19:11 + --> $DIR/pointer-sized-int.rs:18:11 | LL | match 0isize { | ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered | = note: the matched value is of type `isize` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching 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 ~ isize::MIN ..= isize::MAX => {}, +LL ~ isize::MIN..=isize::MAX => {}, LL + ..isize::MIN | isize::MAX.. => todo!() | error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:25:8 + --> $DIR/pointer-sized-int.rs:23:8 | LL | m!(0usize, 0..=usize::MAX); | ^^^^^^ pattern `usize::MAX..` not covered | = note: the matched value is of type `usize` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:27:8 + --> $DIR/pointer-sized-int.rs:25:8 | LL | m!(0usize, 0..5 | 5..=usize::MAX); | ^^^^^^ pattern `usize::MAX..` not covered | = note: the matched value is of type `usize` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:29:8 + --> $DIR/pointer-sized-int.rs:27:8 | LL | m!(0usize, 0..usize::MAX | usize::MAX); | ^^^^^^ pattern `usize::MAX..` not covered | = note: the matched value is of type `usize` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `(usize::MAX.., _)` not covered - --> $DIR/pointer-sized-int.rs:31:8 + --> $DIR/pointer-sized-int.rs:29:8 | LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false)); | ^^^^^^^^^^^^^^ pattern `(usize::MAX.., _)` not covered | = note: the matched value is of type `(usize, bool)` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match $s { $($t)+ => {}, (usize::MAX.., _) => todo!() } | ++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:36:8 + --> $DIR/pointer-sized-int.rs:38:8 | LL | m!(0isize, isize::MIN..=isize::MAX); | ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered | = note: the matched value is of type `isize` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() } | ++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:38:8 + --> $DIR/pointer-sized-int.rs:40:8 | LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX); | ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered | = note: the matched value is of type `isize` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() } | ++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:40:8 + --> $DIR/pointer-sized-int.rs:42:8 | -LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX); +LL | m!(0isize, isize::MIN..=-1 | 0 | 1..=isize::MAX); | ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered | = note: the matched value is of type `isize` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() } | ++++++++++++++++++++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered - --> $DIR/pointer-sized-int.rs:42:8 +error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered + --> $DIR/pointer-sized-int.rs:44:8 | -LL | m!((0isize, true), (isize::MIN..5, true) - | ^^^^^^^^^^^^^^ patterns `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered +LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX); + | ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered | - = note: the matched value is of type `(isize, bool)` + = note: the matched value is of type `isize` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL | match $s { $($t)+ => {}, (..isize::MIN, _) | (isize::MAX.., _) => todo!() } - | ++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() } + | ++++++++++++++++++++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered - --> $DIR/pointer-sized-int.rs:47:11 +error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered + --> $DIR/pointer-sized-int.rs:47:9 | -LL | match 0isize { - | ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered +LL | (0isize, true), + | ^^^^^^^^^^^^^^ patterns `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered | - = note: the matched value is of type `isize` + = note: the matched value is of type `(isize, bool)` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching 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 ~ 1 ..= isize::MAX => {}, -LL + ..isize::MIN | isize::MAX.. => todo!() - | +LL | match $s { $($t)+ => {}, (..isize::MIN, _) | (isize::MAX.., _) => todo!() } + | ++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: type `usize` is non-empty - --> $DIR/pointer-sized-int.rs:54:11 + --> $DIR/pointer-sized-int.rs:58:11 | LL | match 7usize {} | ^^^^^^ diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs index 20a3cbe127f42..3778dede721f2 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs @@ -1,6 +1,5 @@ -// revisions: allow deny +// revisions: deny #![feature(exclusive_range_pattern)] -#![cfg_attr(allow, feature(precise_pointer_size_matching))] #![allow(overlapping_range_endpoints)] macro_rules! m { @@ -12,44 +11,49 @@ macro_rules! m { #[rustfmt::skip] fn main() { match 0usize { - //[deny]~^ ERROR non-exhaustive patterns - 0 ..= usize::MAX => {} + //~^ ERROR non-exhaustive patterns + 0..=usize::MAX => {} } match 0isize { - //[deny]~^ ERROR non-exhaustive patterns - isize::MIN ..= isize::MAX => {} + //~^ ERROR non-exhaustive patterns + isize::MIN..=isize::MAX => {} } - m!(0usize, 0..); m!(0usize, 0..=usize::MAX); - //[deny]~^ ERROR non-exhaustive patterns + //~^ ERROR non-exhaustive patterns m!(0usize, 0..5 | 5..=usize::MAX); - //[deny]~^ ERROR non-exhaustive patterns + //~^ ERROR non-exhaustive patterns m!(0usize, 0..usize::MAX | usize::MAX); - //[deny]~^ ERROR non-exhaustive patterns + //~^ ERROR non-exhaustive patterns m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false)); - //[deny]~^ ERROR non-exhaustive patterns + //~^ ERROR non-exhaustive patterns + + m!(0usize, 0..); + m!(0usize, 0..5 | 5..); + m!(0usize, ..5 | 5..); + m!((0usize, true), (0..5, true) | (5.., true) | (0.., false)); m!(0usize, 0..=usize::MAX | usize::MAX..); - m!(0isize, ..0 | 0..); m!(0isize, isize::MIN..=isize::MAX); - //[deny]~^ ERROR non-exhaustive patterns + //~^ ERROR non-exhaustive patterns m!(0isize, isize::MIN..5 | 5..=isize::MAX); - //[deny]~^ ERROR non-exhaustive patterns + //~^ ERROR non-exhaustive patterns + m!(0isize, isize::MIN..=-1 | 0 | 1..=isize::MAX); + //~^ ERROR non-exhaustive patterns m!(0isize, isize::MIN..isize::MAX | isize::MAX); - //[deny]~^ ERROR non-exhaustive patterns - m!((0isize, true), (isize::MIN..5, true) - | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false)); - //[deny]~^^ ERROR non-exhaustive patterns - m!(0isize, ..=isize::MIN | isize::MIN..=isize::MAX | isize::MAX..); + //~^ ERROR non-exhaustive patterns + m!( + (0isize, true), + (isize::MIN..5, true) | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false) + ); + //~^^^ ERROR non-exhaustive patterns - match 0isize { - //[deny]~^ ERROR non-exhaustive patterns - isize::MIN ..= -1 => {} - 0 => {} - 1 ..= isize::MAX => {} - } + m!(0isize, ..0 | 0..); + m!(0isize, ..5 | 5..); + m!((0isize, true), (..5, true) + | (5.., true) | (..0 | 0.., false)); + m!(0isize, ..=isize::MIN | isize::MIN..=isize::MAX | isize::MAX..); match 7usize {} //~^ ERROR non-exhaustive patterns diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr index a7f93648ed3dd..36743aa810296 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr @@ -6,7 +6,6 @@ LL | match 0usize { | = note: the matched value is of type `usize` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ 0..=usize::MAX => {}, @@ -21,7 +20,6 @@ LL | match 0isize { | = note: the matched value is of type `isize` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching 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 ~ isize::MIN..=isize::MAX => {}, diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs index fb4d59b05780e..247fdd91572cd 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs @@ -9,9 +9,10 @@ macro_rules! m { $t2 => {} _ => {} } - } + }; } +#[rustfmt::skip] fn main() { m!(0u8, 42, 41); m!(0u8, 42, 42); //~ ERROR unreachable pattern @@ -85,7 +86,7 @@ fn main() { match 'a' { '\u{0}'..='\u{D7FF}' => {}, '\u{E000}'..='\u{10_FFFF}' => {}, - '\u{D7FF}'..='\u{E000}' => {}, // FIXME should be unreachable + '\u{D7FF}'..='\u{E000}' => {}, //~ ERROR unreachable pattern } match (0u8, true) { diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr index 0ffb0ffd82aa0..c5b028d2038c3 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/reachability.rs:17:17 + --> $DIR/reachability.rs:18:17 | LL | m!(0u8, 42, 42); | ^^ @@ -11,127 +11,127 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:21:22 + --> $DIR/reachability.rs:22:22 | LL | m!(0u8, 20..=30, 20); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:22:22 + --> $DIR/reachability.rs:23:22 | LL | m!(0u8, 20..=30, 21); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:23:22 + --> $DIR/reachability.rs:24:22 | LL | m!(0u8, 20..=30, 25); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:24:22 + --> $DIR/reachability.rs:25:22 | LL | m!(0u8, 20..=30, 29); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:25:22 + --> $DIR/reachability.rs:26:22 | LL | m!(0u8, 20..=30, 30); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:28:21 + --> $DIR/reachability.rs:29:21 | LL | m!(0u8, 20..30, 20); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:29:21 + --> $DIR/reachability.rs:30:21 | LL | m!(0u8, 20..30, 21); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:30:21 + --> $DIR/reachability.rs:31:21 | LL | m!(0u8, 20..30, 25); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:31:21 + --> $DIR/reachability.rs:32:21 | LL | m!(0u8, 20..30, 29); | ^^ error: unreachable pattern - --> $DIR/reachability.rs:35:22 + --> $DIR/reachability.rs:36:22 | LL | m!(0u8, 20..=30, 20..=30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:36:22 + --> $DIR/reachability.rs:37:22 | LL | m!(0u8, 20.. 30, 20.. 30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:37:22 + --> $DIR/reachability.rs:38:22 | LL | m!(0u8, 20..=30, 20.. 30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:39:22 + --> $DIR/reachability.rs:40:22 | LL | m!(0u8, 20..=30, 21..=30); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:40:22 + --> $DIR/reachability.rs:41:22 | LL | m!(0u8, 20..=30, 20..=29); | ^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:42:24 + --> $DIR/reachability.rs:43:24 | LL | m!('a', 'A'..='z', 'a'..='z'); | ^^^^^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:49:9 + --> $DIR/reachability.rs:50:9 | LL | 5..=8 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:55:9 + --> $DIR/reachability.rs:56:9 | LL | 5..15 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:62:9 + --> $DIR/reachability.rs:63:9 | LL | 5..25 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:70:9 + --> $DIR/reachability.rs:71:9 | LL | 5..25 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:76:9 + --> $DIR/reachability.rs:77:9 | LL | 5..15 => {}, | ^^^^^ error: unreachable pattern - --> $DIR/reachability.rs:83:9 + --> $DIR/reachability.rs:84:9 | LL | _ => {}, | - matches any value @@ -139,16 +139,22 @@ LL | '\u{D7FF}'..='\u{E000}' => {}, | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern - --> $DIR/reachability.rs:104:9 + --> $DIR/reachability.rs:89:9 + | +LL | '\u{D7FF}'..='\u{E000}' => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:105:9 | LL | &FOO => {} | ^^^^ error: unreachable pattern - --> $DIR/reachability.rs:105:9 + --> $DIR/reachability.rs:106:9 | LL | BAR => {} | ^^^ -error: aborting due to 24 previous errors +error: aborting due to 25 previous errors diff --git a/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr index 771fc320a13f6..96500ddb9ccaf 100644 --- a/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/issue-105479-str-non-exhaustiveness.stderr @@ -12,6 +12,6 @@ LL ~ ("c", "d") => {}, LL + (&_, _) => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-12116.stderr b/tests/ui/pattern/usefulness/issue-12116.stderr index 7f15c4703a31c..199bdc6ac978c 100644 --- a/tests/ui/pattern/usefulness/issue-12116.stderr +++ b/tests/ui/pattern/usefulness/issue-12116.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/issue-12369.stderr b/tests/ui/pattern/usefulness/issue-12369.stderr index aab2be78c9a4c..2b6e2e14b7ca8 100644 --- a/tests/ui/pattern/usefulness/issue-12369.stderr +++ b/tests/ui/pattern/usefulness/issue-12369.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/issue-13727.stderr b/tests/ui/pattern/usefulness/issue-13727.stderr index 07ca56a566ff1..ab80c56ea88a0 100644 --- a/tests/ui/pattern/usefulness/issue-13727.stderr +++ b/tests/ui/pattern/usefulness/issue-13727.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/issue-15129.stderr b/tests/ui/pattern/usefulness/issue-15129.stderr index ee8410b765089..cd6c30511969e 100644 --- a/tests/ui/pattern/usefulness/issue-15129.stderr +++ b/tests/ui/pattern/usefulness/issue-15129.stderr @@ -11,6 +11,6 @@ LL ~ (T::T2(()), V::V2(b)) => (), LL ~ (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!(), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-2111.stderr b/tests/ui/pattern/usefulness/issue-2111.stderr index 7f7c5a0f19def..18ce7cc58c56f 100644 --- a/tests/ui/pattern/usefulness/issue-2111.stderr +++ b/tests/ui/pattern/usefulness/issue-2111.stderr @@ -11,6 +11,6 @@ LL ~ (Some(_), None) | (None, Some(_)) => {}, LL + (None, None) | (Some(_), Some(_)) => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-30240-b.stderr b/tests/ui/pattern/usefulness/issue-30240-b.stderr index 59d64bc256b50..74d39eba98c9d 100644 --- a/tests/ui/pattern/usefulness/issue-30240-b.stderr +++ b/tests/ui/pattern/usefulness/issue-30240-b.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/issue-3096-1.stderr b/tests/ui/pattern/usefulness/issue-3096-1.stderr index d8884394f8e96..8a81116f0dda8 100644 --- a/tests/ui/pattern/usefulness/issue-3096-1.stderr +++ b/tests/ui/pattern/usefulness/issue-3096-1.stderr @@ -12,6 +12,6 @@ LL + _ => todo!(), LL ~ } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-3096-2.stderr b/tests/ui/pattern/usefulness/issue-3096-2.stderr index 2df8911badcda..3eff2ee9bb1ce 100644 --- a/tests/ui/pattern/usefulness/issue-3096-2.stderr +++ b/tests/ui/pattern/usefulness/issue-3096-2.stderr @@ -12,6 +12,6 @@ LL + _ => todo!(), LL ~ } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-31561.stderr b/tests/ui/pattern/usefulness/issue-31561.stderr index 5367de5e513c7..cc72056582844 100644 --- a/tests/ui/pattern/usefulness/issue-31561.stderr +++ b/tests/ui/pattern/usefulness/issue-31561.stderr @@ -22,6 +22,6 @@ help: you might want to use `let else` to handle the variants that aren't matche LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() }; | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/usefulness/issue-3601.rs b/tests/ui/pattern/usefulness/issue-3601.rs index a6d2b11f4eee2..868e8c7102724 100644 --- a/tests/ui/pattern/usefulness/issue-3601.rs +++ b/tests/ui/pattern/usefulness/issue-3601.rs @@ -31,7 +31,7 @@ fn main() { //~^ ERROR non-exhaustive patterns //~| NOTE the matched value is of type //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE pattern `box _` not covered + //~| NOTE pattern `box ElementKind::HTMLImageElement(_)` not covered //~| NOTE `Box` defined here box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true, }, diff --git a/tests/ui/pattern/usefulness/issue-3601.stderr b/tests/ui/pattern/usefulness/issue-3601.stderr index b8c9874310125..a3fcaa79b066f 100644 --- a/tests/ui/pattern/usefulness/issue-3601.stderr +++ b/tests/ui/pattern/usefulness/issue-3601.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `box _` not covered +error[E0004]: non-exhaustive patterns: `box ElementKind::HTMLImageElement(_)` not covered --> $DIR/issue-3601.rs:30:44 | LL | box NodeKind::Element(ed) => match ed.kind { - | ^^^^^^^ pattern `box _` not covered + | ^^^^^^^ pattern `box ElementKind::HTMLImageElement(_)` not covered | note: `Box` defined here --> $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -11,9 +11,9 @@ note: `Box` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true, -LL ~ box _ => todo!(), +LL ~ box ElementKind::HTMLImageElement(_) => todo!(), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-39362.stderr b/tests/ui/pattern/usefulness/issue-39362.stderr index 8dc534916061b..9cce87a1c65cf 100644 --- a/tests/ui/pattern/usefulness/issue-39362.stderr +++ b/tests/ui/pattern/usefulness/issue-39362.stderr @@ -18,6 +18,6 @@ LL ~ Foo::Bar { bar: Bar::B, .. } => (), LL ~ _ => todo!(), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-40221.stderr b/tests/ui/pattern/usefulness/issue-40221.stderr index 40b42af26b347..894cb95c7bb8c 100644 --- a/tests/ui/pattern/usefulness/issue-40221.stderr +++ b/tests/ui/pattern/usefulness/issue-40221.stderr @@ -18,6 +18,6 @@ LL ~ P::C(PC::Q) => (), LL ~ P::C(PC::QA) => todo!(), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-4321.stderr b/tests/ui/pattern/usefulness/issue-4321.stderr index 2932731741016..a38f360c88ab1 100644 --- a/tests/ui/pattern/usefulness/issue-4321.stderr +++ b/tests/ui/pattern/usefulness/issue-4321.stderr @@ -11,6 +11,6 @@ LL ~ (true, true) => "baz", LL + (true, false) => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-50900.stderr b/tests/ui/pattern/usefulness/issue-50900.stderr index 7880c89256714..90df1fb764486 100644 --- a/tests/ui/pattern/usefulness/issue-50900.stderr +++ b/tests/ui/pattern/usefulness/issue-50900.stderr @@ -16,6 +16,6 @@ LL ~ Tag::ExifIFDPointer => {}, LL + Tag(Context::Exif, _) => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr index 50e13bdfdfede..ea21ee4e504bc 100644 --- a/tests/ui/pattern/usefulness/issue-56379.stderr +++ b/tests/ui/pattern/usefulness/issue-56379.stderr @@ -22,6 +22,6 @@ LL ~ Foo::C(true) => {}, LL + Foo::A(false) | Foo::B(false) | Foo::C(false) => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-72377.stderr b/tests/ui/pattern/usefulness/issue-72377.stderr index 123dd051d2495..1eaee1bd35213 100644 --- a/tests/ui/pattern/usefulness/issue-72377.stderr +++ b/tests/ui/pattern/usefulness/issue-72377.stderr @@ -11,6 +11,6 @@ LL ~ (X::A, Some(X::C)) | (X::C, Some(X::A)) => false, LL ~ _ => todo!(), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr index bf05d616d6ed1..2acde84965066 100644 --- a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr +++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr @@ -18,6 +18,6 @@ LL + _ => todo!(), LL + } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr index 2c8c85bb1e005..ba7573839ed29 100644 --- a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr +++ b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr @@ -4,6 +4,6 @@ error[E0451]: field `1` of struct `Box` is private LL | let Box { 1: _, .. }: Box<()>; | ^^^^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr index 556efcda516ab..c31411018bc46 100644 --- a/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr +++ b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr @@ -6,7 +6,6 @@ LL | match 0 { | = note: the matched value is of type `usize` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ 1..=usize::MAX => (), @@ -21,7 +20,6 @@ LL | match (0usize, 0usize) { | = note: the matched value is of type `(usize, usize)` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ (1..=usize::MAX, 1..=usize::MAX) => (), @@ -36,7 +34,6 @@ LL | match (0isize, 0usize) { | = note: the matched value is of type `(isize, usize)` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching 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 ~ (isize::MIN..=isize::MAX, 1..=usize::MAX) => (), @@ -74,7 +71,6 @@ note: `Option` defined here = note: not covered = note: the matched value is of type `Option` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => (), @@ -98,7 +94,6 @@ note: `Option>>` defined here = note: not covered = note: the matched value is of type `Option>>` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => (), @@ -118,7 +113,6 @@ LL | struct A { | ^ = note: the matched value is of type `A` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ A { a: 1..=usize::MAX } => (), @@ -138,7 +132,6 @@ LL | struct B(T, U); | ^ = note: the matched value is of type `B` = note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching 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 ~ B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (), @@ -158,7 +151,6 @@ LL | struct B(T, U); | ^ = note: the matched value is of type `B` = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively - = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ B(_, 1..=usize::MAX) => (), diff --git a/tests/ui/pattern/usefulness/match-non-exhaustive.stderr b/tests/ui/pattern/usefulness/match-non-exhaustive.stderr index 4fa3a729212b2..1a0cc58f35df3 100644 --- a/tests/ui/pattern/usefulness/match-non-exhaustive.stderr +++ b/tests/ui/pattern/usefulness/match-non-exhaustive.stderr @@ -10,18 +10,18 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | match 0 { 1 => (), i32::MIN..=0_i32 | 2_i32..=i32::MAX => todo!() } | ++++++++++++++++++++++++++++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered --> $DIR/match-non-exhaustive.rs:3:11 | LL | match 0 { 0 if false => () } - | ^ pattern `_` not covered + | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered | = note: the matched value is of type `i32` = note: match arms with guards don't count towards exhaustivity -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL | match 0 { 0 if false => (), _ => todo!() } - | ++++++++++++++ +LL | match 0 { 0 if false => (), i32::MIN..=-1_i32 | 1_i32..=i32::MAX => todo!() } + | +++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.stderr index 45352f09417f0..d760790dff6fe 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.stderr +++ b/tests/ui/pattern/usefulness/match-privately-empty.stderr @@ -16,6 +16,6 @@ LL ~ }) => {}, LL + Some(Private { misc: true, .. }) => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-ref-ice.stderr b/tests/ui/pattern/usefulness/match-ref-ice.stderr index fad0940baa441..0dbfa776f6959 100644 --- a/tests/ui/pattern/usefulness/match-ref-ice.stderr +++ b/tests/ui/pattern/usefulness/match-ref-ice.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.stderr b/tests/ui/pattern/usefulness/match-slice-patterns.stderr index 63d1f38e9db43..30828ab6c90b8 100644 --- a/tests/ui/pattern/usefulness/match-slice-patterns.stderr +++ b/tests/ui/pattern/usefulness/match-slice-patterns.stderr @@ -11,6 +11,6 @@ LL ~ &[.., Some(_), _] => {}, LL ~ &[_, Some(_), .., None, _] => todo!(), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr b/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr index 9fbd871db7c9d..a966444159bbd 100644 --- a/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr +++ b/tests/ui/pattern/usefulness/nested-non-exhaustive-enums.stderr @@ -17,6 +17,6 @@ LL ~ None => {}, LL + Some(_) => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr index 01f077909e8f7..bd6c5002e63e8 100644 --- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr @@ -10,6 +10,6 @@ help: alternatively, you could prepend the pattern with an underscore to define LL | let f = |_3: isize| println!("hello"); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs index 46e0da5be9b4f..97ded70fc927b 100644 --- a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs +++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs @@ -43,6 +43,10 @@ fn main() { //~^ ERROR `&[_, ..]` not covered [] => {} } + match s { + //~^ ERROR `&[]` and `&[_, ..]` not covered + [..] if false => {} + } match s { //~^ ERROR `&[_, _, ..]` not covered [] => {} diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr index fb6ecda3c4dff..a8786d02414c8 100644 --- a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr @@ -89,9 +89,23 @@ LL ~ [] => {}, LL + &[_, ..] => todo!() | -error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered --> $DIR/slice-patterns-exhaustiveness.rs:46:11 | +LL | match s { + | ^ patterns `&[]` and `&[_, ..]` not covered + | + = note: the matched value is of type `&[bool]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ [..] if false => {}, +LL + &[] | &[_, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:50:11 + | LL | match s { | ^ pattern `&[_, _, ..]` not covered | @@ -103,7 +117,7 @@ LL + &[_, _, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:51:11 + --> $DIR/slice-patterns-exhaustiveness.rs:55:11 | LL | match s { | ^ pattern `&[false, ..]` not covered @@ -116,7 +130,7 @@ LL + &[false, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:56:11 + --> $DIR/slice-patterns-exhaustiveness.rs:60:11 | LL | match s { | ^ pattern `&[false, _, ..]` not covered @@ -129,7 +143,7 @@ LL + &[false, _, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:62:11 + --> $DIR/slice-patterns-exhaustiveness.rs:66:11 | LL | match s { | ^ pattern `&[_, .., false]` not covered @@ -142,7 +156,7 @@ LL + &[_, .., false] => todo!() | error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:69:11 + --> $DIR/slice-patterns-exhaustiveness.rs:73:11 | LL | match s { | ^ pattern `&[_, _, .., true]` not covered @@ -155,7 +169,7 @@ LL + &[_, _, .., true] => todo!() | error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:76:11 + --> $DIR/slice-patterns-exhaustiveness.rs:80:11 | LL | match s { | ^ pattern `&[true, _, .., _]` not covered @@ -168,7 +182,7 @@ LL + &[true, _, .., _] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:85:11 + --> $DIR/slice-patterns-exhaustiveness.rs:89:11 | LL | match s { | ^ patterns `&[]` and `&[_, _, ..]` not covered @@ -181,7 +195,7 @@ LL + &[] | &[_, _, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:89:11 + --> $DIR/slice-patterns-exhaustiveness.rs:93:11 | LL | match s { | ^ patterns `&[]` and `&[_, _, ..]` not covered @@ -194,7 +208,7 @@ LL + &[] | &[_, _, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:93:11 + --> $DIR/slice-patterns-exhaustiveness.rs:97:11 | LL | match s { | ^ patterns `&[]` and `&[_, _, ..]` not covered @@ -207,7 +221,7 @@ LL + &[] | &[_, _, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:98:11 + --> $DIR/slice-patterns-exhaustiveness.rs:102:11 | LL | match s { | ^ patterns `&[]` and `&[_, _, ..]` not covered @@ -220,7 +234,7 @@ LL + &[] | &[_, _, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:103:11 + --> $DIR/slice-patterns-exhaustiveness.rs:107:11 | LL | match s { | ^ pattern `&[_, _, ..]` not covered @@ -233,7 +247,7 @@ LL + &[_, _, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[false]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:108:11 + --> $DIR/slice-patterns-exhaustiveness.rs:112:11 | LL | match s { | ^ pattern `&[false]` not covered @@ -246,7 +260,7 @@ LL + &[false] => todo!() | error[E0004]: non-exhaustive patterns: `&[false]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:121:11 + --> $DIR/slice-patterns-exhaustiveness.rs:125:11 | LL | match s1 { | ^^ pattern `&[false]` not covered @@ -258,6 +272,6 @@ LL ~ CONST1 => {}, LL + &[false] => todo!() | -error: aborting due to 20 previous errors +error: aborting due to 21 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr index 3d2b540a9f57a..17d937bd528ef 100644 --- a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr +++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr @@ -18,6 +18,6 @@ LL ~ A::B { x: None } => {}, LL + A::B { x: Some(_) } => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr index fbee33de6f30a..cc29c42e4d689 100644 --- a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr +++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr index ef707ed4aa40f..0b21bd3f5f06a 100644 --- a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr +++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr @@ -16,6 +16,6 @@ LL ~ Foo(2, b) => println!("{}", b), LL + Foo(..=0_isize, _) | Foo(3_isize.., _) => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr index 4a4945156f73c..5f3e5a7398d9a 100644 --- a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -19,6 +19,6 @@ LL ~ UnstableEnum::Stable2 => {}, LL + UnstableEnum::Unstable => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr index d43027657f046..9af1cd2a16c93 100644 --- a/tests/ui/pin-macro/cant_access_internals.stderr +++ b/tests/ui/pin-macro/cant_access_internals.stderr @@ -6,6 +6,6 @@ LL | mem::take(phantom_pinned.pointer); | = help: add `#![feature(unsafe_pin_internals)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr b/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr index a8d0d62360406..34aaea5b70bbe 100644 --- a/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr +++ b/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr @@ -7,6 +7,6 @@ LL | let value: &bool = unsafe { &42 }; = note: expected reference `&bool` found reference `&{integer}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/polymorphization/const_parameters/functions.stderr b/tests/ui/polymorphization/const_parameters/functions.stderr index 9d0922ac7ca03..a3033d1dcab61 100644 --- a/tests/ui/polymorphization/const_parameters/functions.stderr +++ b/tests/ui/polymorphization/const_parameters/functions.stderr @@ -13,5 +13,5 @@ error: item has unused generic parameters LL | pub fn unused() { | ^^^^^^ -------------- generic parameter `T` is unused -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/polymorphization/promoted-function-1.stderr b/tests/ui/polymorphization/promoted-function-1.stderr index fcbb86949232b..8ab0320aafea5 100644 --- a/tests/ui/polymorphization/promoted-function-1.stderr +++ b/tests/ui/polymorphization/promoted-function-1.stderr @@ -4,5 +4,5 @@ error: item has unused generic parameters LL | pub fn test() { | ^^^^ - generic parameter `T` is unused -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/polymorphization/promoted-function-2.stderr b/tests/ui/polymorphization/promoted-function-2.stderr index 547569df7dcef..a5d3bee11d94c 100644 --- a/tests/ui/polymorphization/promoted-function-2.stderr +++ b/tests/ui/polymorphization/promoted-function-2.stderr @@ -13,5 +13,5 @@ error: item has unused generic parameters LL | fn test() { | ^^^^ - generic parameter `T` is unused -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs index 5e620f248b65d..5ee5085ddc8e1 100644 --- a/tests/ui/print_type_sizes/niche-filling.rs +++ b/tests/ui/print_type_sizes/niche-filling.rs @@ -1,4 +1,5 @@ // compile-flags: -Z print-type-sizes --crate-type=lib +// ignore-debug debug assertions will print more types // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. diff --git a/tests/ui/privacy/decl-macro.stderr b/tests/ui/privacy/decl-macro.stderr index 5bc6f07fffac3..1ca75ec36ca4b 100644 --- a/tests/ui/privacy/decl-macro.stderr +++ b/tests/ui/privacy/decl-macro.stderr @@ -10,6 +10,6 @@ note: the macro `mac` is defined here LL | macro mac() {} | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/export-tag-variant.stderr b/tests/ui/privacy/export-tag-variant.stderr index e8906985e059d..778ded2df991a 100644 --- a/tests/ui/privacy/export-tag-variant.stderr +++ b/tests/ui/privacy/export-tag-variant.stderr @@ -12,6 +12,6 @@ note: the enum `Y` is defined here LL | enum Y { Y1 } | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr index 231a4da8b5f7f..eda42c24c1e2b 100644 --- a/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr +++ b/tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.stderr @@ -4,6 +4,6 @@ error[E0603]: tuple struct constructor `A` is private LL | let Self(a) = self; | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr index df5968ba323b3..93a39edbb8232 100644 --- a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr @@ -22,12 +22,18 @@ note: consider marking `Full` as `pub` in the imported module LL | pub use self::Lieutenant::{JuniorGrade, Full}; | ^^^^ -error: glob import doesn't reexport anything because no candidate is public enough +error: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough --> $DIR/issue-46209-private-enum-variant-reexport.rs:3:13 | LL | pub use self::Professor::*; | ^^^^^^^^^^^^^^^^^^ | +note: the most public imported item is `pub(self)` + --> $DIR/issue-46209-private-enum-variant-reexport.rs:3:13 + | +LL | pub use self::Professor::*; + | ^^^^^^^^^^^^^^^^^^ + = help: reduce the glob import's visibility or increase visibility of imported items note: the lint level is defined here --> $DIR/issue-46209-private-enum-variant-reexport.rs:1:8 | @@ -46,11 +52,18 @@ error: unused imports: `Full`, `JuniorGrade` LL | pub use self::Lieutenant::{JuniorGrade, Full}; | ^^^^^^^^^^^ ^^^^ -error: glob import doesn't reexport anything because no candidate is public enough +error: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough + --> $DIR/issue-46209-private-enum-variant-reexport.rs:10:13 + | +LL | pub use self::PettyOfficer::*; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the most public imported item is `pub(self)` --> $DIR/issue-46209-private-enum-variant-reexport.rs:10:13 | LL | pub use self::PettyOfficer::*; | ^^^^^^^^^^^^^^^^^^^^^ + = help: reduce the glob import's visibility or increase visibility of imported items error: unused import: `self::PettyOfficer::*` --> $DIR/issue-46209-private-enum-variant-reexport.rs:10:13 @@ -58,11 +71,18 @@ error: unused import: `self::PettyOfficer::*` LL | pub use self::PettyOfficer::*; | ^^^^^^^^^^^^^^^^^^^^^ -error: glob import doesn't reexport anything because no candidate is public enough +error: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough + --> $DIR/issue-46209-private-enum-variant-reexport.rs:13:13 + | +LL | pub use self::Crewman::*; + | ^^^^^^^^^^^^^^^^ + | +note: the most public imported item is `pub(crate)` --> $DIR/issue-46209-private-enum-variant-reexport.rs:13:13 | LL | pub use self::Crewman::*; | ^^^^^^^^^^^^^^^^ + = help: reduce the glob import's visibility or increase visibility of imported items error: unused import: `self::Crewman::*` --> $DIR/issue-46209-private-enum-variant-reexport.rs:13:13 diff --git a/tests/ui/privacy/issue-75062-fieldless-tuple-struct.stderr b/tests/ui/privacy/issue-75062-fieldless-tuple-struct.stderr index 14a12003e2de8..b00e566f8f9c7 100644 --- a/tests/ui/privacy/issue-75062-fieldless-tuple-struct.stderr +++ b/tests/ui/privacy/issue-75062-fieldless-tuple-struct.stderr @@ -10,6 +10,6 @@ note: the tuple struct `Bar` is defined here LL | struct Bar(); | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/issue-75906.stderr b/tests/ui/privacy/issue-75906.stderr index 600dc7c876ff3..c5bbef97c3440 100644 --- a/tests/ui/privacy/issue-75906.stderr +++ b/tests/ui/privacy/issue-75906.stderr @@ -14,6 +14,6 @@ help: consider making the field publicly accessible LL | pub struct Bar(pub u8); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/privacy/issue-79593.stderr b/tests/ui/privacy/issue-79593.stderr index 21ba760ad0bcc..5bb69836f609f 100644 --- a/tests/ui/privacy/issue-79593.stderr +++ b/tests/ui/privacy/issue-79593.stderr @@ -16,7 +16,7 @@ error: cannot construct `Pub` with struct literal syntax due to private fields LL | foo::Pub {}; | ^^^^^^^^ | - = note: ... and other private field `private` that was not provided + = note: private field `private` that was not provided error[E0063]: missing field `y` in initializer of `Enum` --> $DIR/issue-79593.rs:23:5 diff --git a/tests/ui/privacy/legacy-ctor-visibility.stderr b/tests/ui/privacy/legacy-ctor-visibility.stderr index c8057d85ed1d0..78c79fc951e06 100644 --- a/tests/ui/privacy/legacy-ctor-visibility.stderr +++ b/tests/ui/privacy/legacy-ctor-visibility.stderr @@ -4,6 +4,6 @@ error[E0423]: expected function, tuple struct or tuple variant, found struct `S` LL | S(10); | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/privacy/privacy-ufcs.stderr b/tests/ui/privacy/privacy-ufcs.stderr index f45f3d8ec3720..5c986895d64f2 100644 --- a/tests/ui/privacy/privacy-ufcs.stderr +++ b/tests/ui/privacy/privacy-ufcs.stderr @@ -12,6 +12,6 @@ note: the trait `Bar` is defined here LL | trait Bar { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/privacy2.stderr b/tests/ui/privacy/privacy2.stderr index e7135d3fd8a61..46bb9823dbf8f 100644 --- a/tests/ui/privacy/privacy2.stderr +++ b/tests/ui/privacy/privacy2.stderr @@ -19,7 +19,7 @@ note: ...and refers to the function `foo` which is defined here --> $DIR/privacy2.rs:16:1 | LL | pub fn foo() {} - | ^^^^^^^^^^^^ consider importing it directly + | ^^^^^^^^^^^^ you could import this directly error: requires `sized` lang_item diff --git a/tests/ui/privacy/privacy4.stderr b/tests/ui/privacy/privacy4.stderr index 7552fa71a3a3a..4aa3ae964c0ca 100644 --- a/tests/ui/privacy/privacy4.stderr +++ b/tests/ui/privacy/privacy4.stderr @@ -10,6 +10,6 @@ note: the module `glob` is defined here LL | mod glob { | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/private-field-ty-err.stderr b/tests/ui/privacy/private-field-ty-err.stderr index 98ba7856e57e3..17d50f24a945f 100644 --- a/tests/ui/privacy/private-field-ty-err.stderr +++ b/tests/ui/privacy/private-field-ty-err.stderr @@ -4,6 +4,6 @@ error[E0616]: field `len` of struct `Foo` is private LL | if x.len { | ^^^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/privacy/private-impl-method.stderr b/tests/ui/privacy/private-impl-method.stderr index 18e4531d11256..c53232e4c8c0e 100644 --- a/tests/ui/privacy/private-impl-method.stderr +++ b/tests/ui/privacy/private-impl-method.stderr @@ -7,6 +7,6 @@ LL | fn foo(&self) {} LL | s.foo(); | ^^^ private method -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/privacy/private-in-public-non-principal-2.stderr b/tests/ui/privacy/private-in-public-non-principal-2.stderr index 7cc8bf0de2b9c..d3da2326abc92 100644 --- a/tests/ui/privacy/private-in-public-non-principal-2.stderr +++ b/tests/ui/privacy/private-in-public-non-principal-2.stderr @@ -4,5 +4,5 @@ error: trait `PrivNonPrincipal` is private LL | m::leak_dyn_nonprincipal(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/privacy/private-in-public-non-principal.stderr b/tests/ui/privacy/private-in-public-non-principal.stderr index 63512f462f518..73f2249bc6c05 100644 --- a/tests/ui/privacy/private-in-public-non-principal.stderr +++ b/tests/ui/privacy/private-in-public-non-principal.stderr @@ -23,5 +23,5 @@ note: the lint level is defined here LL | #[deny(missing_docs)] | ^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/privacy/private-item-simple.stderr b/tests/ui/privacy/private-item-simple.stderr index e3d90150e2e3e..330d892e939d0 100644 --- a/tests/ui/privacy/private-item-simple.stderr +++ b/tests/ui/privacy/private-item-simple.stderr @@ -10,6 +10,6 @@ note: the function `f` is defined here LL | fn f() {} | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/private-method-cross-crate.stderr b/tests/ui/privacy/private-method-cross-crate.stderr index e644440c827ab..9c524e2bd377b 100644 --- a/tests/ui/privacy/private-method-cross-crate.stderr +++ b/tests/ui/privacy/private-method-cross-crate.stderr @@ -9,6 +9,6 @@ LL | nyan.nap(); LL | fn nap(&self) {} | ------------- private method defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/privacy/private-method-inherited.stderr b/tests/ui/privacy/private-method-inherited.stderr index 0104a1b27e485..dd36afe8b36d1 100644 --- a/tests/ui/privacy/private-method-inherited.stderr +++ b/tests/ui/privacy/private-method-inherited.stderr @@ -7,6 +7,6 @@ LL | fn f(self) {} LL | x.f(); | ^ private method -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/privacy/private-method.stderr b/tests/ui/privacy/private-method.stderr index 42fec76226584..076a149e1a1a4 100644 --- a/tests/ui/privacy/private-method.stderr +++ b/tests/ui/privacy/private-method.stderr @@ -7,6 +7,6 @@ LL | fn nap(&self) {} LL | nyan.nap(); | ^^^ private method -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/privacy/private-struct-field-cross-crate.stderr b/tests/ui/privacy/private-struct-field-cross-crate.stderr index 40cf3448d6f48..ed4c83f159b55 100644 --- a/tests/ui/privacy/private-struct-field-cross-crate.stderr +++ b/tests/ui/privacy/private-struct-field-cross-crate.stderr @@ -4,6 +4,6 @@ error[E0616]: field `meows` of struct `cat` is private LL | assert_eq!(nyan.meows, 52); | ^^^^^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/privacy/private-struct-field-ctor.stderr b/tests/ui/privacy/private-struct-field-ctor.stderr index 9dc9db0eaca41..2a35537237a3e 100644 --- a/tests/ui/privacy/private-struct-field-ctor.stderr +++ b/tests/ui/privacy/private-struct-field-ctor.stderr @@ -4,6 +4,6 @@ error[E0451]: field `x` of struct `Foo` is private LL | let s = a::Foo { x: 1 }; | ^^^^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/privacy/private-struct-field-pattern.stderr b/tests/ui/privacy/private-struct-field-pattern.stderr index 6305530368327..de24d1e09622b 100644 --- a/tests/ui/privacy/private-struct-field-pattern.stderr +++ b/tests/ui/privacy/private-struct-field-pattern.stderr @@ -4,6 +4,6 @@ error[E0451]: field `x` of struct `Foo` is private LL | Foo { x: _ } => {} | ^^^^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/privacy/private-struct-field.stderr b/tests/ui/privacy/private-struct-field.stderr index facf4e82fd622..cc5a966bc9b31 100644 --- a/tests/ui/privacy/private-struct-field.stderr +++ b/tests/ui/privacy/private-struct-field.stderr @@ -4,6 +4,6 @@ error[E0616]: field `meows` of struct `Cat` is private LL | assert_eq!(nyan.meows, 52); | ^^^^^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/privacy/private-variant-reexport.stderr b/tests/ui/privacy/private-variant-reexport.stderr index 2f041934a8171..d73bd1a8cc29f 100644 --- a/tests/ui/privacy/private-variant-reexport.stderr +++ b/tests/ui/privacy/private-variant-reexport.stderr @@ -30,12 +30,18 @@ LL | pub use ::E::V::{self}; | = note: consider declaring type or module `V` with `pub` -error: glob import doesn't reexport anything because no candidate is public enough +error: glob import doesn't reexport anything with visibility `pub` because no imported item is public enough --> $DIR/private-variant-reexport.rs:15:13 | LL | pub use ::E::*; | ^^^^^^ | +note: the most public imported item is `pub(crate)` + --> $DIR/private-variant-reexport.rs:15:13 + | +LL | pub use ::E::*; + | ^^^^^^ + = help: reduce the glob import's visibility or increase visibility of imported items note: the lint level is defined here --> $DIR/private-variant-reexport.rs:13:8 | diff --git a/tests/ui/privacy/restricted/struct-literal-field.stderr b/tests/ui/privacy/restricted/struct-literal-field.stderr index eee964f022ac1..dcdadf1da4bf7 100644 --- a/tests/ui/privacy/restricted/struct-literal-field.stderr +++ b/tests/ui/privacy/restricted/struct-literal-field.stderr @@ -4,6 +4,6 @@ error[E0451]: field `x` of struct `S` is private LL | S { x: 0 }; | ^^^^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr b/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr index 2949997986674..e6b76322f9641 100644 --- a/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr +++ b/tests/ui/privacy/sealed-traits/private-trait-non-local.stderr @@ -7,6 +7,6 @@ LL | use core::slice::index::private_slice_index::Sealed; note: the module `index` is defined here --> $SRC_DIR/core/src/slice/mod.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/sealed-traits/private-trait.stderr b/tests/ui/privacy/sealed-traits/private-trait.stderr index c7ec72ff1662c..e8d88906f1f57 100644 --- a/tests/ui/privacy/sealed-traits/private-trait.stderr +++ b/tests/ui/privacy/sealed-traits/private-trait.stderr @@ -12,6 +12,6 @@ note: the module `b` is defined here LL | mod b { | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr index b630565d0237f..9f2291e6825a6 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr @@ -14,6 +14,6 @@ help: consider importing this trait through its public re-export instead LL | impl a::Trait for S {} | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/suggest-box-new.fixed b/tests/ui/privacy/suggest-box-new.fixed deleted file mode 100644 index f5ae5c2abfd99..0000000000000 --- a/tests/ui/privacy/suggest-box-new.fixed +++ /dev/null @@ -1,15 +0,0 @@ -// run-rustfix -#![allow(dead_code)] -struct U { - wtf: Option>>, - x: T, -} -fn main() { - U { - wtf: Some(Box::new(U { //~ ERROR cannot initialize a tuple struct which contains private fields - wtf: None, - x: (), - })), - x: () - }; -} diff --git a/tests/ui/privacy/suggest-box-new.rs b/tests/ui/privacy/suggest-box-new.rs index 2e18dba8b9fb2..7125285fc7764 100644 --- a/tests/ui/privacy/suggest-box-new.rs +++ b/tests/ui/privacy/suggest-box-new.rs @@ -1,4 +1,3 @@ -// run-rustfix #![allow(dead_code)] struct U { wtf: Option>>, @@ -12,4 +11,9 @@ fn main() { })), x: () }; + let _ = std::collections::HashMap(); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `std::collections::HashMap` + let _ = std::collections::HashMap {}; + //~^ ERROR cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields + let _ = Box {}; //~ ERROR cannot construct `Box<_, _>` with struct literal syntax due to private fields } diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr index ed7fa036408a4..8b01e8c3c10ef 100644 --- a/tests/ui/privacy/suggest-box-new.stderr +++ b/tests/ui/privacy/suggest-box-new.stderr @@ -1,5 +1,29 @@ +error[E0423]: expected function, tuple struct or tuple variant, found struct `std::collections::HashMap` + --> $DIR/suggest-box-new.rs:14:13 + | +LL | let _ = std::collections::HashMap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL + | + = note: `std::collections::HashMap` defined here + | +help: you might have meant to use an associated function to build this type + | +LL | let _ = std::collections::HashMap::new(); + | ~~~~~~~ +LL | let _ = std::collections::HashMap::with_capacity(_); + | ~~~~~~~~~~~~~~~~~~ +LL | let _ = std::collections::HashMap::with_hasher(_); + | ~~~~~~~~~~~~~~~~ +LL | let _ = std::collections::HashMap::with_capacity_and_hasher(_, _); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: consider using the `Default` trait + | +LL | let _ = ::default(); + | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + error[E0423]: cannot initialize a tuple struct which contains private fields - --> $DIR/suggest-box-new.rs:9:19 + --> $DIR/suggest-box-new.rs:8:19 | LL | wtf: Some(Box(U { | ^^^ @@ -10,11 +34,67 @@ note: constructor is not visible here due to private fields = note: private field | = note: private field -help: you might have meant to use the `new` associated function +help: you might have meant to use an associated function to build this type + | +LL | wtf: Some(Box::new(_)), + | ~~~~~~~~ +LL | wtf: Some(Box::new_uninit()), + | ~~~~~~~~~~~~~~ +LL | wtf: Some(Box::new_zeroed()), + | ~~~~~~~~~~~~~~ +LL | wtf: Some(Box::new_in(_, _)), + | ~~~~~~~~~~~~~~ + and 10 other candidates +help: consider using the `Default` trait + | +LL | wtf: Some(::default()), + | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields + --> $DIR/suggest-box-new.rs:16:13 + | +LL | let _ = std::collections::HashMap {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: private field `base` that was not provided +help: you might have meant to use an associated function to build this type + | +LL | let _ = std::collections::HashMap::new(); + | ~~~~~~~ +LL | let _ = std::collections::HashMap::with_capacity(_); + | ~~~~~~~~~~~~~~~~~~ +LL | let _ = std::collections::HashMap::with_hasher(_); + | ~~~~~~~~~~~~~~~~ +LL | let _ = std::collections::HashMap::with_capacity_and_hasher(_, _); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: consider using the `Default` trait + | +LL | let _ = ::default(); + | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: cannot construct `Box<_, _>` with struct literal syntax due to private fields + --> $DIR/suggest-box-new.rs:18:13 + | +LL | let _ = Box {}; + | ^^^ + | + = note: private fields `0` and `1` that were not provided +help: you might have meant to use an associated function to build this type + | +LL | let _ = Box::new(_); + | ~~~~~~~~ +LL | let _ = Box::new_uninit(); + | ~~~~~~~~~~~~~~ +LL | let _ = Box::new_zeroed(); + | ~~~~~~~~~~~~~~ +LL | let _ = Box::new_in(_, _); + | ~~~~~~~~~~~~~~ + and 10 other candidates +help: consider using the `Default` trait | -LL | wtf: Some(Box::new(U { - | +++++ +LL | let _ = ::default(); + | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/privacy/union-field-privacy-2.stderr b/tests/ui/privacy/union-field-privacy-2.stderr index bf6a2b625d5bb..7b6b84bfd4c8a 100644 --- a/tests/ui/privacy/union-field-privacy-2.stderr +++ b/tests/ui/privacy/union-field-privacy-2.stderr @@ -4,6 +4,6 @@ error[E0616]: field `c` of union `U` is private LL | let c = u.c; | ^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr index 650766458465d..126330b14a63f 100644 --- a/tests/ui/privacy/where-priv-type.stderr +++ b/tests/ui/privacy/where-priv-type.stderr @@ -77,6 +77,6 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private -error: aborting due to previous error; 5 warnings emitted +error: aborting due to 1 previous error; 5 warnings emitted For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs-test.stderr b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.stderr index 316eb636ba825..346cebf639d17 100644 --- a/tests/ui/proc-macro/ambiguous-builtin-attrs-test.stderr +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `NonExistent` in this scope LL | NonExistent; | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs b/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs new file mode 100644 index 0000000000000..ce7e60356f279 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs @@ -0,0 +1,39 @@ +// force-host +// no-prefer-dynamic + +// Proc macro helper for issue #89699, used by tests/ui/proc-macro/edition-gated-async-move- +// syntax-issue89699.rs, emitting an `async move` closure. This syntax is only available in +// editions 2018 and up, but is used in edition 2015 in the test. + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +pub fn foo(_attr: TokenStream, item: TokenStream) -> TokenStream { + let tt = item.into_iter().next().unwrap(); + let sp = tt.span(); + let mut arg = TokenStream::new(); + let mut g = Group::new(Delimiter::Brace, TokenStream::new()); + g.set_span(sp); + arg.extend([ + TokenTree::Ident(Ident::new("async", sp)), + TokenTree::Ident(Ident::new("move", sp)), + TokenTree::Group(g), + ]); + let mut body = TokenStream::new(); + body.extend([ + TokenTree::Ident(Ident::new("async_main", sp)), + TokenTree::Group(Group::new(Delimiter::Parenthesis, arg)), + ]); + + let mut ret = TokenStream::new(); + ret.extend([ + TokenTree::Ident(Ident::new("fn", sp)), + TokenTree::Ident(Ident::new("main", sp)), + TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), + TokenTree::Group(Group::new(Delimiter::Brace, body)), + ]); + ret +} diff --git a/tests/ui/proc-macro/cfg-eval-fail.stderr b/tests/ui/proc-macro/cfg-eval-fail.stderr index df8b6d5f382a1..945ad46bf33c3 100644 --- a/tests/ui/proc-macro/cfg-eval-fail.stderr +++ b/tests/ui/proc-macro/cfg-eval-fail.stderr @@ -4,5 +4,5 @@ error: removing an expression is not supported in this position LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0; | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/define-two.stderr b/tests/ui/proc-macro/define-two.stderr index bf1bd8427c833..a39ce366f75eb 100644 --- a/tests/ui/proc-macro/define-two.stderr +++ b/tests/ui/proc-macro/define-two.stderr @@ -9,6 +9,6 @@ LL | #[proc_macro_derive(A)] | = note: `A` must be defined only once in the macro namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/proc-macro/derive-helper-legacy-limits.stderr b/tests/ui/proc-macro/derive-helper-legacy-limits.stderr index 186f38a00f917..f5cd455435d4a 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-limits.stderr +++ b/tests/ui/proc-macro/derive-helper-legacy-limits.stderr @@ -4,5 +4,5 @@ error: cannot find attribute `empty_helper` in this scope LL | #[empty_helper] | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/derive-still-gated.stderr b/tests/ui/proc-macro/derive-still-gated.stderr index 99289fdfe7fd5..25777f72b8d11 100644 --- a/tests/ui/proc-macro/derive-still-gated.stderr +++ b/tests/ui/proc-macro/derive-still-gated.stderr @@ -4,5 +4,5 @@ error: cannot find attribute `derive_Empty` in this scope LL | #[derive_Empty] | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/disappearing-resolution.stderr b/tests/ui/proc-macro/disappearing-resolution.stderr index 5b969549a117c..e6d0868687e27 100644 --- a/tests/ui/proc-macro/disappearing-resolution.stderr +++ b/tests/ui/proc-macro/disappearing-resolution.stderr @@ -19,7 +19,11 @@ note: ...and refers to the derive macro `Empty` which is defined here --> $DIR/auxiliary/test-macros.rs:25:1 | LL | pub fn empty_derive(_: TokenStream) -> TokenStream { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly +help: import `Empty` directly + | +LL | use test_macros::Empty; + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs b/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs new file mode 100644 index 0000000000000..1a9d4601acafe --- /dev/null +++ b/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs @@ -0,0 +1,10 @@ +// aux-build:edition-gated-async-move-syntax.rs +// edition: 2015 + +// Non-regression test for issue #89699, where a proc-macro emitting syntax only available in +// edition 2018 and up (`async move`) is used on edition 2015 + +extern crate edition_gated_async_move_syntax; + +#[edition_gated_async_move_syntax::foo] +fn foo() {} //~ ERROR `async move` blocks are only allowed in Rust 2018 or later diff --git a/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.stderr b/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.stderr new file mode 100644 index 0000000000000..5123b823fb87a --- /dev/null +++ b/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.stderr @@ -0,0 +1,8 @@ +error: `async move` blocks are only allowed in Rust 2018 or later + --> $DIR/edition-gated-async-move-syntax-issue89699.rs:10:1 + | +LL | fn foo() {} + | ^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/proc-macro/expand-to-unstable.stderr b/tests/ui/proc-macro/expand-to-unstable.stderr index b27dcd7e6cdba..dda590ee8c7e8 100644 --- a/tests/ui/proc-macro/expand-to-unstable.stderr +++ b/tests/ui/proc-macro/expand-to-unstable.stderr @@ -7,6 +7,6 @@ LL | #[derive(Unstable)] = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable = note: this error originates in the derive macro `Unstable` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/proc-macro/export-macro.stderr b/tests/ui/proc-macro/export-macro.stderr index 36a6a9bb3e72b..410770eca08a3 100644 --- a/tests/ui/proc-macro/export-macro.stderr +++ b/tests/ui/proc-macro/export-macro.stderr @@ -4,5 +4,5 @@ error: cannot export macro_rules! macros from a `proc-macro` crate type currentl LL | macro_rules! foo { | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr index 9441cdcc8cf2a..1c12a2804c6d3 100644 --- a/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr +++ b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr @@ -30,6 +30,6 @@ LL | #[derive(Empty)] = note: for more information, see issue #79202 = note: `#[warn(legacy_derive_helpers)]` on by default -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/proc-macro/import.stderr b/tests/ui/proc-macro/import.stderr index aae621193ab9f..c5d1648abfe10 100644 --- a/tests/ui/proc-macro/import.stderr +++ b/tests/ui/proc-macro/import.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `test_macros::empty_derive` LL | use test_macros::empty_derive; | ^^^^^^^^^^^^^^^^^^^^^^^^^ no `empty_derive` in the root -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/proc-macro/invalid-punct-ident-1.stderr b/tests/ui/proc-macro/invalid-punct-ident-1.stderr index 78aa84401a505..0013bfd16a819 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-1.stderr +++ b/tests/ui/proc-macro/invalid-punct-ident-1.stderr @@ -6,5 +6,5 @@ LL | invalid_punct!(); | = help: message: unsupported character `'`'` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/invalid-punct-ident-2.stderr b/tests/ui/proc-macro/invalid-punct-ident-2.stderr index 66979e756aec0..3de2139d5d7c3 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-2.stderr +++ b/tests/ui/proc-macro/invalid-punct-ident-2.stderr @@ -6,5 +6,5 @@ LL | invalid_ident!(); | = help: message: `"*"` is not a valid identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/invalid-punct-ident-3.stderr b/tests/ui/proc-macro/invalid-punct-ident-3.stderr index c096bc8c04396..158ba0d4fb744 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-3.stderr +++ b/tests/ui/proc-macro/invalid-punct-ident-3.stderr @@ -6,5 +6,5 @@ LL | invalid_raw_ident!(); | = help: message: `self` cannot be a raw identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/issue-107113-wrap.stderr b/tests/ui/proc-macro/issue-107113-wrap.stderr index 4122253d22fc5..b541051147d53 100644 --- a/tests/ui/proc-macro/issue-107113-wrap.stderr +++ b/tests/ui/proc-macro/issue-107113-wrap.stderr @@ -11,6 +11,6 @@ LL | #[issue_107113::main] found unit type `()` = note: this error originates in the attribute macro `issue_107113::main` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/issue-37788.stderr b/tests/ui/proc-macro/issue-37788.stderr index 0a116d6f80d35..9ce783073fdca 100644 --- a/tests/ui/proc-macro/issue-37788.stderr +++ b/tests/ui/proc-macro/issue-37788.stderr @@ -12,6 +12,6 @@ LL | std::cell::Cell::new(0) = note: expected unit type `()` found struct `Cell<{integer}>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/issue-38586.stderr b/tests/ui/proc-macro/issue-38586.stderr index ddd0a0874dd3e..0049155645078 100644 --- a/tests/ui/proc-macro/issue-38586.stderr +++ b/tests/ui/proc-macro/issue-38586.stderr @@ -6,6 +6,6 @@ LL | #[derive(A)] | = note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/issue-50493.stderr b/tests/ui/proc-macro/issue-50493.stderr index 23e103dbfcbd9..1cd3583135bfc 100644 --- a/tests/ui/proc-macro/issue-50493.stderr +++ b/tests/ui/proc-macro/issue-50493.stderr @@ -4,6 +4,6 @@ error[E0742]: visibilities can only be restricted to ancestor modules LL | pub(in restricted) field: usize, | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0742`. diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr index f7516c7d377da..08e679a7c559a 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr @@ -1,4 +1,4 @@ error: requires `sized` lang_item -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/issue-66286.stderr b/tests/ui/proc-macro/issue-66286.stderr index fe2464b3b8115..fc4c2062fd7bc 100644 --- a/tests/ui/proc-macro/issue-66286.stderr +++ b/tests/ui/proc-macro/issue-66286.stderr @@ -9,6 +9,6 @@ help: use angle brackets instead LL | pub extern fn foo(_: Vec) -> u32 { | ~ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/proc-macro/issue-75801.stderr b/tests/ui/proc-macro/issue-75801.stderr index ee0a9bd7783e6..3b5f9e3b5b079 100644 --- a/tests/ui/proc-macro/issue-75801.stderr +++ b/tests/ui/proc-macro/issue-75801.stderr @@ -7,6 +7,6 @@ LL | let _bar: u32 = $arg; LL | foo!("baz"); | ^^^^^ expected `u32`, found `&str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr index d69de23a4c0ac..7bf85104db3e7 100644 --- a/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr +++ b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr @@ -6,5 +6,5 @@ LL | proc_macro_panic::panic_in_libproc_macro!(); | = help: message: `""` is not a valid identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/issue-79148.stderr b/tests/ui/proc-macro/issue-79148.stderr index a3b2de01ddfbb..8adc4c6e0dbe4 100644 --- a/tests/ui/proc-macro/issue-79148.stderr +++ b/tests/ui/proc-macro/issue-79148.stderr @@ -11,6 +11,6 @@ LL | cause_ice!(); | ^^^^^^^^^^^^ = note: this error originates in the macro `cause_ice` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/proc-macro/issue-81543-item-parse-err.stderr b/tests/ui/proc-macro/issue-81543-item-parse-err.stderr index ca524176035b8..50f9c71eb2847 100644 --- a/tests/ui/proc-macro/issue-81543-item-parse-err.stderr +++ b/tests/ui/proc-macro/issue-81543-item-parse-err.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `32` LL | fn 32() {} | ^^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr b/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr index ec0e3c4c7546f..02fcaf542970e 100644 --- a/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr +++ b/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr @@ -4,5 +4,5 @@ error: allocators must be statics LL | fn inner() {} | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/issue-86781-bad-inner-doc.stderr b/tests/ui/proc-macro/issue-86781-bad-inner-doc.stderr index a92f07522e5f2..aeb824303e715 100644 --- a/tests/ui/proc-macro/issue-86781-bad-inner-doc.stderr +++ b/tests/ui/proc-macro/issue-86781-bad-inner-doc.stderr @@ -12,6 +12,6 @@ help: to annotate the struct, change the doc comment from inner to outer style LL | /// Inner doc comment | ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0753`. diff --git a/tests/ui/proc-macro/item-error.stderr b/tests/ui/proc-macro/item-error.stderr index b544be6e96a27..71d0ee10aa2ae 100644 --- a/tests/ui/proc-macro/item-error.stderr +++ b/tests/ui/proc-macro/item-error.stderr @@ -10,6 +10,6 @@ LL ~ struct A<'a> { LL ~ a: &'a u64 | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/proc-macro/lifetimes.stderr b/tests/ui/proc-macro/lifetimes.stderr index 0c99809ed5c13..315b4c5917243 100644 --- a/tests/ui/proc-macro/lifetimes.stderr +++ b/tests/ui/proc-macro/lifetimes.stderr @@ -9,5 +9,5 @@ LL | type A = single_quote_alone!(); | = note: this error originates in the macro `single_quote_alone` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/lints_in_proc_macros.stderr b/tests/ui/proc-macro/lints_in_proc_macros.stderr index 4dd8be7d9b6ef..244d218608be7 100644 --- a/tests/ui/proc-macro/lints_in_proc_macros.stderr +++ b/tests/ui/proc-macro/lints_in_proc_macros.stderr @@ -6,6 +6,6 @@ LL | bang_proc_macro2!(); | = note: this error originates in the macro `bang_proc_macro2` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/literal-to-string.rs b/tests/ui/proc-macro/literal-to-string.rs index 494d17cbeeaff..eb009036a9a83 100644 --- a/tests/ui/proc-macro/literal-to-string.rs +++ b/tests/ui/proc-macro/literal-to-string.rs @@ -1,6 +1,5 @@ // check-pass // edition: 2021 -#![feature(c_str_literals)] // aux-build: print-tokens.rs extern crate print_tokens; diff --git a/tests/ui/proc-macro/literal-to-string.stdout b/tests/ui/proc-macro/literal-to-string.stdout index 7b27fcf798b12..ec6427545f45c 100644 --- a/tests/ui/proc-macro/literal-to-string.stdout +++ b/tests/ui/proc-macro/literal-to-string.stdout @@ -3,91 +3,91 @@ TokenStream [ kind: Integer, symbol: "1", suffix: None, - span: #0 bytes(172..173), + span: #0 bytes(144..145), }, Literal { kind: Integer, symbol: "17", suffix: Some("u8"), - span: #0 bytes(182..186), + span: #0 bytes(154..158), }, Literal { kind: Float, symbol: "42.", suffix: None, - span: #0 bytes(195..198), + span: #0 bytes(167..170), }, Literal { kind: Float, symbol: "3.14", suffix: Some("f32"), - span: #0 bytes(207..214), + span: #0 bytes(179..186), }, Literal { kind: Byte, symbol: "a", suffix: None, - span: #0 bytes(223..227), + span: #0 bytes(195..199), }, Literal { kind: Byte, symbol: "\xFF", suffix: None, - span: #0 bytes(236..243), + span: #0 bytes(208..215), }, Literal { kind: Char, symbol: "c", suffix: None, - span: #0 bytes(252..255), + span: #0 bytes(224..227), }, Literal { kind: Char, symbol: "\x32", suffix: None, - span: #0 bytes(264..270), + span: #0 bytes(236..242), }, Literal { kind: Str, symbol: "\\"str\\"", suffix: None, - span: #0 bytes(279..288), + span: #0 bytes(251..260), }, Literal { kind: StrRaw(1), symbol: "\"raw\" str", suffix: None, - span: #0 bytes(297..311), + span: #0 bytes(269..283), }, Literal { kind: StrRaw(3), symbol: "very ##\"raw\"## str", suffix: None, - span: #0 bytes(320..347), + span: #0 bytes(292..319), }, Literal { kind: ByteStr, symbol: "\\"byte\\" str", suffix: None, - span: #0 bytes(356..371), + span: #0 bytes(328..343), }, Literal { kind: ByteStrRaw(1), symbol: "\"raw\" \"byte\" str", suffix: None, - span: #0 bytes(380..402), + span: #0 bytes(352..374), }, Literal { kind: CStr, symbol: "\\"c\\" str", suffix: None, - span: #0 bytes(411..423), + span: #0 bytes(383..395), }, Literal { kind: CStrRaw(1), symbol: "\"raw\" \"c\" str", suffix: None, - span: #0 bytes(432..451), + span: #0 bytes(404..423), }, ] 1 diff --git a/tests/ui/proc-macro/load-panic-backtrace.stderr b/tests/ui/proc-macro/load-panic-backtrace.stderr index c1a642713d29f..18f5135867262 100644 --- a/tests/ui/proc-macro/load-panic-backtrace.stderr +++ b/tests/ui/proc-macro/load-panic-backtrace.stderr @@ -8,5 +8,5 @@ LL | #[derive(Panic)] | = help: message: panic-derive -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/load-panic.stderr b/tests/ui/proc-macro/load-panic.stderr index f0d62f690fd3c..bb429ad631db8 100644 --- a/tests/ui/proc-macro/load-panic.stderr +++ b/tests/ui/proc-macro/load-panic.stderr @@ -6,5 +6,5 @@ LL | #[derive(Panic)] | = help: message: panic-derive -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/macro-brackets.stderr b/tests/ui/proc-macro/macro-brackets.stderr index d3516375291b9..f14b5fed6b9eb 100644 --- a/tests/ui/proc-macro/macro-brackets.stderr +++ b/tests/ui/proc-macro/macro-brackets.stderr @@ -9,6 +9,6 @@ help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes LL | id![static X: u32 = 'a' as u32;]; | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/macro-rules-derive.stderr b/tests/ui/proc-macro/macro-rules-derive.stderr index 517cbabd5c65a..e7cd4474618fe 100644 --- a/tests/ui/proc-macro/macro-rules-derive.stderr +++ b/tests/ui/proc-macro/macro-rules-derive.stderr @@ -9,6 +9,6 @@ LL | produce_it!(MyName); | = note: this error originates in the macro `produce_it` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/proc-macro/macros-in-extern-derive.stderr b/tests/ui/proc-macro/macros-in-extern-derive.stderr index efd9ff22506ce..c7d2881ad2138 100644 --- a/tests/ui/proc-macro/macros-in-extern-derive.stderr +++ b/tests/ui/proc-macro/macros-in-extern-derive.stderr @@ -6,6 +6,6 @@ LL | #[derive(Copy)] LL | fn f(); | ------- not a `struct`, `enum` or `union` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/proc-macro/no-macro-use-attr.stderr b/tests/ui/proc-macro/no-macro-use-attr.stderr index a9e5256a0a95d..3dda3cc7d5a5b 100644 --- a/tests/ui/proc-macro/no-macro-use-attr.stderr +++ b/tests/ui/proc-macro/no-macro-use-attr.stderr @@ -16,5 +16,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/proc-macro/non-root.stderr b/tests/ui/proc-macro/non-root.stderr index 90f94b677e90f..ecc0202c106af 100644 --- a/tests/ui/proc-macro/non-root.stderr +++ b/tests/ui/proc-macro/non-root.stderr @@ -4,5 +4,5 @@ error: functions tagged with `#[proc_macro]` must currently reside in the root o LL | pub fn foo(arg: TokenStream) -> TokenStream { arg } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/raw-ident.stderr b/tests/ui/proc-macro/raw-ident.stderr index 905a5f9463af8..a72067021cb31 100644 --- a/tests/ui/proc-macro/raw-ident.stderr +++ b/tests/ui/proc-macro/raw-ident.stderr @@ -6,5 +6,5 @@ LL | make_bad_struct!(S); | = note: this error originates in the macro `make_bad_struct` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/shadow.stderr b/tests/ui/proc-macro/shadow.stderr index e7d95cc835811..6f50d89f500f4 100644 --- a/tests/ui/proc-macro/shadow.stderr +++ b/tests/ui/proc-macro/shadow.stderr @@ -9,6 +9,6 @@ LL | extern crate test_macros; | = note: `test_macros` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/proc-macro/signature.stderr b/tests/ui/proc-macro/signature.stderr index ba5c8c1571e58..2a53145a6436f 100644 --- a/tests/ui/proc-macro/signature.stderr +++ b/tests/ui/proc-macro/signature.stderr @@ -7,5 +7,5 @@ LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 { = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream` found signature `unsafe extern "C" fn(i32, u32) -> u32` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/test-same-crate.stderr b/tests/ui/proc-macro/test-same-crate.stderr index 5d12e149c3c4c..3cab0ae679005 100644 --- a/tests/ui/proc-macro/test-same-crate.stderr +++ b/tests/ui/proc-macro/test-same-crate.stderr @@ -6,5 +6,5 @@ LL | fn t() { crate::mac!(A) } | = help: you can define integration tests in a directory named `tests` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/two-crate-types-1.stderr b/tests/ui/proc-macro/two-crate-types-1.stderr index deaba1cf272fd..a7524fd3b0afd 100644 --- a/tests/ui/proc-macro/two-crate-types-1.stderr +++ b/tests/ui/proc-macro/two-crate-types-1.stderr @@ -1,4 +1,4 @@ error: cannot mix `proc-macro` crate type with others -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/two-crate-types-2.stderr b/tests/ui/proc-macro/two-crate-types-2.stderr index deaba1cf272fd..a7524fd3b0afd 100644 --- a/tests/ui/proc-macro/two-crate-types-2.stderr +++ b/tests/ui/proc-macro/two-crate-types-2.stderr @@ -1,4 +1,4 @@ error: cannot mix `proc-macro` crate type with others -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-fn-2.stderr b/tests/ui/pub/pub-ident-fn-2.stderr index b5b667b41b67b..e724278b23390 100644 --- a/tests/ui/pub/pub-ident-fn-2.stderr +++ b/tests/ui/pub/pub-ident-fn-2.stderr @@ -9,5 +9,5 @@ help: add `fn` here to parse `foo` as a public function LL | pub fn foo(_s: usize) { bar() } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-fn-or-struct.stderr b/tests/ui/pub/pub-ident-fn-or-struct.stderr index c4a196eb2c265..a8fa4bd3bd3b4 100644 --- a/tests/ui/pub/pub-ident-fn-or-struct.stderr +++ b/tests/ui/pub/pub-ident-fn-or-struct.stderr @@ -4,5 +4,5 @@ error: missing `fn` or `struct` for function or struct definition LL | pub S (foo) bar | ---^- help: if you meant to call a macro, try: `S!` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr b/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr index 6a9aeaf4a56ac..b0d5ce9de5c98 100644 --- a/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr +++ b/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr @@ -9,5 +9,5 @@ help: add `fn` here to parse `bar` as a public method LL | pub fn bar<'a>(&self, _s: &'a usize) -> bool { true } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime.stderr b/tests/ui/pub/pub-ident-fn-with-lifetime.stderr index c1ca0136b18fb..63fcf6bf5d59a 100644 --- a/tests/ui/pub/pub-ident-fn-with-lifetime.stderr +++ b/tests/ui/pub/pub-ident-fn-with-lifetime.stderr @@ -9,5 +9,5 @@ help: add `fn` here to parse `foo` as a public function LL | pub fn foo<'a>(_s: &'a usize) -> bool { true } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-fn.stderr b/tests/ui/pub/pub-ident-fn.stderr index cb94c48add4be..06dac616443b8 100644 --- a/tests/ui/pub/pub-ident-fn.stderr +++ b/tests/ui/pub/pub-ident-fn.stderr @@ -9,5 +9,5 @@ help: add `fn` here to parse `foo` as a public function LL | pub fn foo(_s: usize) -> bool { true } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-struct-2.stderr b/tests/ui/pub/pub-ident-struct-2.stderr index 6969a376a5e76..5e0f328d98616 100644 --- a/tests/ui/pub/pub-ident-struct-2.stderr +++ b/tests/ui/pub/pub-ident-struct-2.stderr @@ -9,5 +9,5 @@ help: add `struct` here to parse `bar` as a public struct LL | pub struct bar(); | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-struct-3.stderr b/tests/ui/pub/pub-ident-struct-3.stderr index d94198a6b6deb..d08e5120570c8 100644 --- a/tests/ui/pub/pub-ident-struct-3.stderr +++ b/tests/ui/pub/pub-ident-struct-3.stderr @@ -9,5 +9,5 @@ help: add `struct` here to parse `S` as a public struct LL | pub struct S(); | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-struct-4.stderr b/tests/ui/pub/pub-ident-struct-4.stderr index 90c7138e5cee0..470874e06378c 100644 --- a/tests/ui/pub/pub-ident-struct-4.stderr +++ b/tests/ui/pub/pub-ident-struct-4.stderr @@ -9,5 +9,5 @@ help: add `struct` here to parse `T` as a public struct LL | pub struct T(String); | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-struct-with-lifetime.stderr b/tests/ui/pub/pub-ident-struct-with-lifetime.stderr index 562b68e354249..0e08a5ff44922 100644 --- a/tests/ui/pub/pub-ident-struct-with-lifetime.stderr +++ b/tests/ui/pub/pub-ident-struct-with-lifetime.stderr @@ -9,5 +9,5 @@ help: add `struct` here to parse `S` as a public struct LL | pub struct S<'a> { | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-struct.stderr b/tests/ui/pub/pub-ident-struct.stderr index d3a378786e4d2..2d5d61d938107 100644 --- a/tests/ui/pub/pub-ident-struct.stderr +++ b/tests/ui/pub/pub-ident-struct.stderr @@ -9,5 +9,5 @@ help: add `struct` here to parse `S` as a public struct LL | pub struct S { | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr b/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr index 0e0b127054d1d..750e2d17e0ad1 100644 --- a/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr +++ b/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr @@ -4,5 +4,5 @@ error: missing `fn` or `struct` for function or struct definition LL | pub foo<'a> | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-restricted-error.stderr b/tests/ui/pub/pub-restricted-error.stderr index b47328f34e6eb..4db8487831796 100644 --- a/tests/ui/pub/pub-restricted-error.stderr +++ b/tests/ui/pub/pub-restricted-error.stderr @@ -6,5 +6,5 @@ LL | struct Foo { LL | pub(crate) () foo: usize, | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/pub/pub-restricted-non-path.stderr b/tests/ui/pub/pub-restricted-non-path.stderr index e0ea50621f752..1402ec231cd21 100644 --- a/tests/ui/pub/pub-restricted-non-path.stderr +++ b/tests/ui/pub/pub-restricted-non-path.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `.` LL | pub (.) fn afn() {} | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/qualified/qualified-path-params-2.stderr b/tests/ui/qualified/qualified-path-params-2.stderr index b6cf19b8286cc..56644bdd46a8d 100644 --- a/tests/ui/qualified/qualified-path-params-2.stderr +++ b/tests/ui/qualified/qualified-path-params-2.stderr @@ -9,6 +9,6 @@ help: if there were a trait named `Example` with associated type `f` implemented LL | type A = <::A as Example>::f; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/query-system/fn-sig-cycle-arity.stderr b/tests/ui/query-system/fn-sig-cycle-arity.stderr index 67e0c2545515e..fa1d033754e87 100644 --- a/tests/ui/query-system/fn-sig-cycle-arity.stderr +++ b/tests/ui/query-system/fn-sig-cycle-arity.stderr @@ -4,6 +4,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | fn dance(&self) -> _ { | ^ not allowed in type signatures -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr b/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr index 35e608b6b232b..e86e38225a368 100644 --- a/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr +++ b/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr @@ -4,6 +4,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | fn a() -> _ { | ^ not allowed in type signatures -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/query-system/query_depth.stderr b/tests/ui/query-system/query_depth.stderr index 43a18b4e07455..d455e0e4ff8fa 100644 --- a/tests/ui/query-system/query_depth.stderr +++ b/tests/ui/query-system/query_depth.stderr @@ -7,5 +7,5 @@ LL | fn main() { = help: consider increasing the recursion limit by adding a `#![recursion_limit = "128"]` attribute to your crate (`query_depth`) = note: query depth increased by 66 when computing layout of `core::option::Option>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/range/range-inclusive-pattern-precedence.stderr b/tests/ui/range/range-inclusive-pattern-precedence.stderr index f6788d034e6f7..2e2d7983c03a8 100644 --- a/tests/ui/range/range-inclusive-pattern-precedence.stderr +++ b/tests/ui/range/range-inclusive-pattern-precedence.stderr @@ -18,5 +18,5 @@ note: the lint level is defined here LL | #![warn(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/range/range-inclusive-pattern-precedence2.stderr b/tests/ui/range/range-inclusive-pattern-precedence2.stderr index bb4e3a13a5cf7..84294604c80f1 100644 --- a/tests/ui/range/range-inclusive-pattern-precedence2.stderr +++ b/tests/ui/range/range-inclusive-pattern-precedence2.stderr @@ -18,5 +18,5 @@ note: the lint level is defined here LL | #![warn(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr index 0829fc2ce9b8c..04778eecf569d 100644 --- a/tests/ui/range/range_traits-2.stderr +++ b/tests/ui/range/range_traits-2.stderr @@ -8,6 +8,6 @@ LL | struct R(Range); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr index db19d1baec994..094cc146b6c1d 100644 --- a/tests/ui/range/range_traits-3.stderr +++ b/tests/ui/range/range_traits-3.stderr @@ -8,6 +8,6 @@ LL | struct R(RangeFrom); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr index dfc74f87ca715..7c66d1c749c2e 100644 --- a/tests/ui/range/range_traits-6.stderr +++ b/tests/ui/range/range_traits-6.stderr @@ -8,6 +8,6 @@ LL | struct R(RangeInclusive); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/reachable/expr_add.stderr b/tests/ui/reachable/expr_add.stderr index 692bd20f50940..f4a56fcbcb2cc 100644 --- a/tests/ui/reachable/expr_add.stderr +++ b/tests/ui/reachable/expr_add.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/expr_again.stderr b/tests/ui/reachable/expr_again.stderr index a3c54e135604c..5dec512ba5def 100644 --- a/tests/ui/reachable/expr_again.stderr +++ b/tests/ui/reachable/expr_again.stderr @@ -13,5 +13,5 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/expr_repeat.stderr b/tests/ui/reachable/expr_repeat.stderr index defa870461028..1949af2a9a0cc 100644 --- a/tests/ui/reachable/expr_repeat.stderr +++ b/tests/ui/reachable/expr_repeat.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/expr_return.stderr b/tests/ui/reachable/expr_return.stderr index 3791559f44000..c9766f14d2cfa 100644 --- a/tests/ui/reachable/expr_return.stderr +++ b/tests/ui/reachable/expr_return.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/expr_return_in_macro.stderr b/tests/ui/reachable/expr_return_in_macro.stderr index 3c562a7ee6f01..68ba6529a1dde 100644 --- a/tests/ui/reachable/expr_return_in_macro.stderr +++ b/tests/ui/reachable/expr_return_in_macro.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/expr_type.stderr b/tests/ui/reachable/expr_type.stderr index 3cb4a32e02fac..70536326fd842 100644 --- a/tests/ui/reachable/expr_type.stderr +++ b/tests/ui/reachable/expr_type.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/unreachable-arm.stderr b/tests/ui/reachable/unreachable-arm.stderr index 1cbea8288d465..60db8217640fd 100644 --- a/tests/ui/reachable/unreachable-arm.stderr +++ b/tests/ui/reachable/unreachable-arm.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/unreachable-code-ret.stderr b/tests/ui/reachable/unreachable-code-ret.stderr index 263a1b5a960fc..824515a2271f1 100644 --- a/tests/ui/reachable/unreachable-code-ret.stderr +++ b/tests/ui/reachable/unreachable-code-ret.stderr @@ -13,5 +13,5 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/unreachable-code.stderr b/tests/ui/reachable/unreachable-code.stderr index cb1b760c282b5..52be0277c00c5 100644 --- a/tests/ui/reachable/unreachable-code.stderr +++ b/tests/ui/reachable/unreachable-code.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr index 80ffa5d73f034..1dea9d813f9b4 100644 --- a/tests/ui/reachable/unreachable-loop-patterns.stderr +++ b/tests/ui/reachable/unreachable-loop-patterns.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/reachable/unreachable-variant.stderr b/tests/ui/reachable/unreachable-variant.stderr index ca1d2be65ce52..81faa59a07bb7 100644 --- a/tests/ui/reachable/unreachable-variant.stderr +++ b/tests/ui/reachable/unreachable-variant.stderr @@ -10,6 +10,6 @@ note: the module `super_sekrit` is defined here LL | mod super_sekrit { | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/recursion/issue-26548-recursion-via-normalize.stderr b/tests/ui/recursion/issue-26548-recursion-via-normalize.stderr index 514bed607003b..e77fb025bcf19 100644 --- a/tests/ui/recursion/issue-26548-recursion-via-normalize.stderr +++ b/tests/ui/recursion/issue-26548-recursion-via-normalize.stderr @@ -6,6 +6,6 @@ error[E0391]: cycle detected when computing layout of `core::option::Option` = note: cycle used when computing layout of `core::option::Option<::It>` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr index 4b4fc4fb7d189..ff1a127e63e3e 100644 --- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr +++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr @@ -11,5 +11,5 @@ LL | pub unsafe fn drop_in_place(to_drop: *mut T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-38591-non-regular-dropck-recursion.polonius/issue-38591-non-regular-dropck-recursion.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index 002dfe115b03f..a5bbc5499a887 100644 --- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -6,6 +6,6 @@ LL | fn f(x: S) {} | = note: overflowed on S -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0320`. diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr index 5df8af484a9d1..783f9cf763254 100644 --- a/tests/ui/recursion/issue-83150.stderr +++ b/tests/ui/recursion/issue-83150.stderr @@ -16,6 +16,6 @@ error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range, = note: 65 redundant requirements hidden = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>, {closure@$DIR/issue-83150.rs:13:24: 13:27}>` to implement `Iterator` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/recursion/recursion.polonius.stderr b/tests/ui/recursion/recursion.polonius.stderr index c727fe551e3bc..737e71e884518 100644 --- a/tests/ui/recursion/recursion.polonius.stderr +++ b/tests/ui/recursion/recursion.polonius.stderr @@ -11,5 +11,5 @@ LL | fn test (n:isize, i:isize, first:T, second:T) ->isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/recursion.polonius/recursion.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/recursion/recursion.stderr b/tests/ui/recursion/recursion.stderr index cf08095372b07..7a9f04d4bd6d3 100644 --- a/tests/ui/recursion/recursion.stderr +++ b/tests/ui/recursion/recursion.stderr @@ -11,5 +11,5 @@ LL | fn test (n:isize, i:isize, first:T, second:T) ->isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/recursion/recursion.long-type.txt' -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/recursion/recursive-enum.stderr b/tests/ui/recursion/recursive-enum.stderr index d662d1022038d..b584cb466968b 100644 --- a/tests/ui/recursion/recursive-enum.stderr +++ b/tests/ui/recursion/recursive-enum.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum List { Cons(T, Box>), Nil } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/recursion/recursive-reexports.stderr b/tests/ui/recursion/recursive-reexports.stderr index f39d0a0d5e6f3..71653d26a18d7 100644 --- a/tests/ui/recursion/recursive-reexports.stderr +++ b/tests/ui/recursion/recursive-reexports.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `S` in crate `recursive_reexports` LL | fn f() -> recursive_reexports::S {} | ^ not found in `recursive_reexports` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/recursion/recursive-static-definition.stderr b/tests/ui/recursion/recursive-static-definition.stderr index b112228d4039a..570d203d07f7c 100644 --- a/tests/ui/recursion/recursive-static-definition.stderr +++ b/tests/ui/recursion/recursive-static-definition.stderr @@ -20,6 +20,6 @@ LL | | fn main() {} | |____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr b/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr index 1b4d80d90571c..5abec88eeff00 100644 --- a/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -12,6 +12,6 @@ help: you might want to use `let else` to handle the variant that isn't matched LL | let Ok(x) = res else { todo!() }; | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/recursion_limit/invalid_digit_type.stderr b/tests/ui/recursion_limit/invalid_digit_type.stderr index 6d1409bb39065..94442b5747fc3 100644 --- a/tests/ui/recursion_limit/invalid_digit_type.stderr +++ b/tests/ui/recursion_limit/invalid_digit_type.stderr @@ -4,5 +4,5 @@ error: malformed `recursion_limit` attribute input LL | #![recursion_limit = 123] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/recursion_limit/invalid_macro.stderr b/tests/ui/recursion_limit/invalid_macro.stderr index 0189e99da3714..aa4894ec4d8eb 100644 --- a/tests/ui/recursion_limit/invalid_macro.stderr +++ b/tests/ui/recursion_limit/invalid_macro.stderr @@ -4,5 +4,5 @@ error: malformed `recursion_limit` attribute input LL | #![recursion_limit = foo!()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/recursion_limit/issue-105700.stderr b/tests/ui/recursion_limit/issue-105700.stderr index 9b1114e9ce62b..fd53d248c4e0f 100644 --- a/tests/ui/recursion_limit/issue-105700.stderr +++ b/tests/ui/recursion_limit/issue-105700.stderr @@ -6,5 +6,5 @@ LL | #![invalid_attribute] | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`issue_105700`) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/recursion_limit/no-value.stderr b/tests/ui/recursion_limit/no-value.stderr index 35ac2c4cd17b3..b2e8c46c372a1 100644 --- a/tests/ui/recursion_limit/no-value.stderr +++ b/tests/ui/recursion_limit/no-value.stderr @@ -4,5 +4,5 @@ error: malformed `recursion_limit` attribute input LL | #![recursion_limit] | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/recursion_limit/zero-overflow.stderr b/tests/ui/recursion_limit/zero-overflow.stderr index 9007ec0d78444..fc03cc5b604b7 100644 --- a/tests/ui/recursion_limit/zero-overflow.stderr +++ b/tests/ui/recursion_limit/zero-overflow.stderr @@ -2,6 +2,6 @@ error[E0275]: overflow evaluating the requirement `&mut Self: DispatchFromDyn<&m | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`zero_overflow`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/recursion_limit/zero.stderr b/tests/ui/recursion_limit/zero.stderr index b43565909a3f4..f97eff19338c9 100644 --- a/tests/ui/recursion_limit/zero.stderr +++ b/tests/ui/recursion_limit/zero.stderr @@ -6,5 +6,5 @@ LL | test!(test); | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`zero`) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr b/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr index d76a83b025809..509863eaf886c 100644 --- a/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr +++ b/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr @@ -11,6 +11,6 @@ LL | S(&x) LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/forall-wf-ref-reflexive.stderr b/tests/ui/regions/forall-wf-ref-reflexive.stderr index 3d059ccec7296..5ee7cc7866c98 100644 --- a/tests/ui/regions/forall-wf-ref-reflexive.stderr +++ b/tests/ui/regions/forall-wf-ref-reflexive.stderr @@ -4,5 +4,5 @@ error: `T` does not live long enough LL | self_wf2::(); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/issue-101280.stderr b/tests/ui/regions/issue-101280.stderr index 320d008aeff2f..70953808b8168 100644 --- a/tests/ui/regions/issue-101280.stderr +++ b/tests/ui/regions/issue-101280.stderr @@ -9,6 +9,6 @@ LL | f = note: expected fn pointer `for<'r> fn(Cell<(&'r i32, &'r i32)>)` found fn pointer `for<'a> fn(Cell<(&'r i32, &'a i32)>)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/issue-102374.stderr b/tests/ui/regions/issue-102374.stderr index a4230cf8b5a21..e07dca0c7ee23 100644 --- a/tests/ui/regions/issue-102374.stderr +++ b/tests/ui/regions/issue-102374.stderr @@ -9,6 +9,6 @@ LL | f = note: expected type `i32` found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/issue-102392.stderr b/tests/ui/regions/issue-102392.stderr index 56f4c0c5db4b7..fb3373091c220 100644 --- a/tests/ui/regions/issue-102392.stderr +++ b/tests/ui/regions/issue-102392.stderr @@ -9,6 +9,6 @@ LL | f = note: expected type `bool` found fn pointer `for<'a> fn(for<'b> fn(&'b str, &'a str))` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/issue-12470.stderr b/tests/ui/regions/issue-12470.stderr index c97e59195ed05..e6e629321e52b 100644 --- a/tests/ui/regions/issue-12470.stderr +++ b/tests/ui/regions/issue-12470.stderr @@ -6,6 +6,6 @@ LL | let bb: &B = &*b; LL | make_a(bb) | ^^^^^^^^^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/issue-28848.stderr b/tests/ui/regions/issue-28848.stderr index a29dac4c9c87c..0582295832f7a 100644 --- a/tests/ui/regions/issue-28848.stderr +++ b/tests/ui/regions/issue-28848.stderr @@ -10,5 +10,5 @@ LL | Foo::<'a, 'b>::xmute(u) | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/issue-78262.base.stderr b/tests/ui/regions/issue-78262.base.stderr index 7f232e4a7b254..113c84c656287 100644 --- a/tests/ui/regions/issue-78262.base.stderr +++ b/tests/ui/regions/issue-78262.base.stderr @@ -9,6 +9,6 @@ LL | let f = |x: &dyn TT| x.func(); | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/issue-78262.polonius.stderr b/tests/ui/regions/issue-78262.polonius.stderr index 7f232e4a7b254..113c84c656287 100644 --- a/tests/ui/regions/issue-78262.polonius.stderr +++ b/tests/ui/regions/issue-78262.polonius.stderr @@ -9,6 +9,6 @@ LL | let f = |x: &dyn TT| x.func(); | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/outlives-with-missing.stderr b/tests/ui/regions/outlives-with-missing.stderr index e204c918724fe..0e3aaaf5fdbd0 100644 --- a/tests/ui/regions/outlives-with-missing.stderr +++ b/tests/ui/regions/outlives-with-missing.stderr @@ -7,6 +7,6 @@ LL | impl HandlerWrapper { LL | T: Send + Sync + 'static, | ^ help: a type parameter with a similar name exists: `H` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/regions/region-bound-on-closure-outlives-call.stderr b/tests/ui/regions/region-bound-on-closure-outlives-call.stderr index ea43dde11f805..96d0cb80a7430 100644 --- a/tests/ui/regions/region-bound-on-closure-outlives-call.stderr +++ b/tests/ui/regions/region-bound-on-closure-outlives-call.stderr @@ -19,6 +19,6 @@ LL | (|x| f(x))(call_rec(f)) | | borrow occurs due to use in closure | borrow of `f` occurs here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/regions/region-invariant-static-error-reporting.stderr b/tests/ui/regions/region-invariant-static-error-reporting.stderr index 2ad39b0007170..834d5c6cf5a8b 100644 --- a/tests/ui/regions/region-invariant-static-error-reporting.stderr +++ b/tests/ui/regions/region-invariant-static-error-reporting.stderr @@ -16,6 +16,6 @@ LL | x.unwrap() = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index a9a92b7a695eb..03d5a0be7235e 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -9,6 +9,6 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index e96559937d421..250571f1556d8 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -9,6 +9,6 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)` found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-object-lifetime-2.stderr b/tests/ui/regions/region-object-lifetime-2.stderr index d95289f3f9def..7eb5d39ecfa4c 100644 --- a/tests/ui/regions/region-object-lifetime-2.stderr +++ b/tests/ui/regions/region-object-lifetime-2.stderr @@ -10,5 +10,5 @@ LL | x.borrowed() | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/region-object-lifetime-4.stderr b/tests/ui/regions/region-object-lifetime-4.stderr index fda66a2412ccb..713252dbc08cb 100644 --- a/tests/ui/regions/region-object-lifetime-4.stderr +++ b/tests/ui/regions/region-object-lifetime-4.stderr @@ -10,5 +10,5 @@ LL | x.borrowed() | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/region-object-lifetime-5.stderr b/tests/ui/regions/region-object-lifetime-5.stderr index b86f6e3a2a122..e8960fcc65693 100644 --- a/tests/ui/regions/region-object-lifetime-5.stderr +++ b/tests/ui/regions/region-object-lifetime-5.stderr @@ -7,6 +7,6 @@ LL | x.borrowed() | returns a value referencing data owned by the current function | `*x` is borrowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-addr-of-self.stderr b/tests/ui/regions/regions-addr-of-self.stderr index 3d7aac74bd4f7..75e1abdda206c 100644 --- a/tests/ui/regions/regions-addr-of-self.stderr +++ b/tests/ui/regions/regions-addr-of-self.stderr @@ -6,5 +6,5 @@ LL | pub fn chase_cat(&mut self) { LL | let p: &'static mut usize = &mut self.cats_chased; | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr b/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr index 2a26252036181..2a5831aad255a 100644 --- a/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr +++ b/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr @@ -11,5 +11,5 @@ LL | let _: &'a WithAssoc> = loop { }; | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr index a96f5612fa23d..6ffe416ca5f10 100644 --- a/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr +++ b/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -10,6 +10,6 @@ note: type must satisfy the static lifetime as required by this binding LL | type Value: 'static; | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr b/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr index 6193bf02f6d0d..bd8640b9d34fd 100644 --- a/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr +++ b/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr @@ -14,5 +14,5 @@ LL | a.bigger_region(b) = note: the struct `Inv<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr b/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr index 0e0086be9ea8d..df37df99bf279 100644 --- a/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr +++ b/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr @@ -14,5 +14,5 @@ LL | f.method(b); = note: the struct `Inv<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-bounded-method-type-parameters.stderr b/tests/ui/regions/regions-bounded-method-type-parameters.stderr index b6d7b8aac5f19..f1375404443d7 100644 --- a/tests/ui/regions/regions-bounded-method-type-parameters.stderr +++ b/tests/ui/regions/regions-bounded-method-type-parameters.stderr @@ -6,5 +6,5 @@ LL | fn caller<'a>(x: &isize) { LL | Foo.some_method::<&'a isize>(); | ^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-close-object-into-object-1.stderr b/tests/ui/regions/regions-close-object-into-object-1.stderr index 5bfaeb295c352..8353587c6463e 100644 --- a/tests/ui/regions/regions-close-object-into-object-1.stderr +++ b/tests/ui/regions/regions-close-object-into-object-1.stderr @@ -7,6 +7,6 @@ LL | Box::new(B(&*v)) as Box | | `*v` is borrowed here | returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-close-object-into-object-3.stderr b/tests/ui/regions/regions-close-object-into-object-3.stderr index 9f92c40e1e18d..706595ae87f7b 100644 --- a/tests/ui/regions/regions-close-object-into-object-3.stderr +++ b/tests/ui/regions/regions-close-object-into-object-3.stderr @@ -7,6 +7,6 @@ LL | Box::new(B(&*v)) as Box | | `*v` is borrowed here | returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-close-over-type-parameter-multiple.stderr b/tests/ui/regions/regions-close-over-type-parameter-multiple.stderr index baa0506d04ca7..a353ff89b80ed 100644 --- a/tests/ui/regions/regions-close-over-type-parameter-multiple.stderr +++ b/tests/ui/regions/regions-close-over-type-parameter-multiple.stderr @@ -11,5 +11,5 @@ LL | Box::new(v) as Box | = help: consider adding the following bound: `'a: 'c` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-creating-enums3.stderr b/tests/ui/regions/regions-creating-enums3.stderr index 41d609b56d233..93a0a1dc7c271 100644 --- a/tests/ui/regions/regions-creating-enums3.stderr +++ b/tests/ui/regions/regions-creating-enums3.stderr @@ -10,5 +10,5 @@ LL | Ast::Add(x, y) | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-creating-enums4.stderr b/tests/ui/regions/regions-creating-enums4.stderr index 91cf57e099df9..fee2b77795ab4 100644 --- a/tests/ui/regions/regions-creating-enums4.stderr +++ b/tests/ui/regions/regions-creating-enums4.stderr @@ -10,5 +10,5 @@ LL | Ast::Add(x, y) | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-early-bound-error-method.stderr b/tests/ui/regions/regions-early-bound-error-method.stderr index a7746d8981e83..8c79eb222be89 100644 --- a/tests/ui/regions/regions-early-bound-error-method.stderr +++ b/tests/ui/regions/regions-early-bound-error-method.stderr @@ -10,5 +10,5 @@ LL | g2.get() | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-early-bound-error.stderr b/tests/ui/regions/regions-early-bound-error.stderr index eb4cd5ca72ea1..5ad16069ab974 100644 --- a/tests/ui/regions/regions-early-bound-error.stderr +++ b/tests/ui/regions/regions-early-bound-error.stderr @@ -10,5 +10,5 @@ LL | g1.get() | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-escape-method.stderr b/tests/ui/regions/regions-escape-method.stderr index 9f425125b9896..aeda923b0ba98 100644 --- a/tests/ui/regions/regions-escape-method.stderr +++ b/tests/ui/regions/regions-escape-method.stderr @@ -7,5 +7,5 @@ LL | s.f(|p| p) | |return type of closure is &'2 i32 | has type `&'1 i32` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-escape-via-trait-or-not.stderr b/tests/ui/regions/regions-escape-via-trait-or-not.stderr index cae6c33ac6e17..4d185e52d01be 100644 --- a/tests/ui/regions/regions-escape-via-trait-or-not.stderr +++ b/tests/ui/regions/regions-escape-via-trait-or-not.stderr @@ -7,5 +7,5 @@ LL | with(|o| o) | |return type of closure is &'2 isize | has type `&'1 isize` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr b/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr index 8d82ff958ff3a..2ccdd65f295d4 100644 --- a/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr +++ b/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn want_G(f: G) {} | ^^^^^^ ---- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-free-region-ordering-callee-4.stderr b/tests/ui/regions/regions-free-region-ordering-callee-4.stderr index 1df7ca0e3e900..1c8f1c1e472f2 100644 --- a/tests/ui/regions/regions-free-region-ordering-callee-4.stderr +++ b/tests/ui/regions/regions-free-region-ordering-callee-4.stderr @@ -15,6 +15,6 @@ note: but the referenced data is only valid for the lifetime `'b` as defined her LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/regions/regions-free-region-ordering-incorrect.stderr b/tests/ui/regions/regions-free-region-ordering-incorrect.stderr index d0ceaec3b67d5..9025f0c3cbd21 100644 --- a/tests/ui/regions/regions-free-region-ordering-incorrect.stderr +++ b/tests/ui/regions/regions-free-region-ordering-incorrect.stderr @@ -13,5 +13,5 @@ LL | | } | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-glb-free-free.stderr b/tests/ui/regions/regions-glb-free-free.stderr index 575037a0a4d63..727669f26835e 100644 --- a/tests/ui/regions/regions-glb-free-free.stderr +++ b/tests/ui/regions/regions-glb-free-free.stderr @@ -11,6 +11,6 @@ LL | | value: self.value LL | | } | |_____________^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr index 8c1791fc11d76..7d9f9121a48ba 100644 --- a/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | fn func<'x, T:Trait1<'x> + 'x>(t: &'x T::Foo) | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index 6844e86653299..1555e5981c5c7 100644 --- a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `T` LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) | ++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/regions/regions-in-enums-anon.stderr b/tests/ui/regions/regions-in-enums-anon.stderr index ed547aa9c4100..86a6d33d6d35d 100644 --- a/tests/ui/regions/regions-in-enums-anon.stderr +++ b/tests/ui/regions/regions-in-enums-anon.stderr @@ -10,6 +10,6 @@ LL ~ enum Foo<'a> { LL ~ Bar(&'a isize) | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/regions/regions-in-structs-anon.stderr b/tests/ui/regions/regions-in-structs-anon.stderr index 992d25c9fd124..2679ef93b97b4 100644 --- a/tests/ui/regions/regions-in-structs-anon.stderr +++ b/tests/ui/regions/regions-in-structs-anon.stderr @@ -10,6 +10,6 @@ LL ~ struct Foo<'a> { LL ~ x: &'a isize | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/regions/regions-infer-at-fn-not-param.stderr b/tests/ui/regions/regions-infer-at-fn-not-param.stderr index 8cfc44f6abd28..4c7660276f2dd 100644 --- a/tests/ui/regions/regions-infer-at-fn-not-param.stderr +++ b/tests/ui/regions/regions-infer-at-fn-not-param.stderr @@ -6,6 +6,6 @@ LL | fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p } | | | help: add explicit lifetime `'a` to the type of `p`: `Parameterized1<'a>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/regions/regions-infer-borrow-scope-too-big.stderr b/tests/ui/regions/regions-infer-borrow-scope-too-big.stderr index 2c7a6e8b5c0b9..15dc1cef83ccd 100644 --- a/tests/ui/regions/regions-infer-borrow-scope-too-big.stderr +++ b/tests/ui/regions/regions-infer-borrow-scope-too-big.stderr @@ -7,6 +7,6 @@ LL | assert_eq!(*xc, 3); LL | return xc; | ^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-infer-bound-from-trait-self.stderr b/tests/ui/regions/regions-infer-bound-from-trait-self.stderr index d0c4b9a57e096..7bf112dc7212a 100644 --- a/tests/ui/regions/regions-infer-bound-from-trait-self.stderr +++ b/tests/ui/regions/regions-infer-bound-from-trait-self.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | trait InheritsFromNothing<'a> : Sized where Self: 'a { | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/regions/regions-infer-call-3.stderr b/tests/ui/regions/regions-infer-call-3.stderr index ca51555a07749..14d1ce7ae8b38 100644 --- a/tests/ui/regions/regions-infer-call-3.stderr +++ b/tests/ui/regions/regions-infer-call-3.stderr @@ -7,5 +7,5 @@ LL | let z = with(|y| { select(x, y) }); | |return type of closure is &'2 isize | has type `&'1 isize` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-infer-contravariance-due-to-decl.stderr b/tests/ui/regions/regions-infer-contravariance-due-to-decl.stderr index 94b80852d0124..56ee07bdebd1d 100644 --- a/tests/ui/regions/regions-infer-contravariance-due-to-decl.stderr +++ b/tests/ui/regions/regions-infer-contravariance-due-to-decl.stderr @@ -11,5 +11,5 @@ LL | let _: Contravariant<'long> = c; | = help: consider adding the following bound: `'short: 'long` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-infer-covariance-due-to-decl.stderr b/tests/ui/regions/regions-infer-covariance-due-to-decl.stderr index f44a0fad59b2e..013475c26914a 100644 --- a/tests/ui/regions/regions-infer-covariance-due-to-decl.stderr +++ b/tests/ui/regions/regions-infer-covariance-due-to-decl.stderr @@ -11,5 +11,5 @@ LL | let _: Covariant<'short> = c; | = help: consider adding the following bound: `'short: 'long` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-infer-invariance-due-to-decl.stderr b/tests/ui/regions/regions-infer-invariance-due-to-decl.stderr index c8c7808e06c5f..2b17f74ad1b89 100644 --- a/tests/ui/regions/regions-infer-invariance-due-to-decl.stderr +++ b/tests/ui/regions/regions-infer-invariance-due-to-decl.stderr @@ -10,5 +10,5 @@ LL | b_isize = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr b/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr index 1165011c1f4fc..9cb9dac4fdfd7 100644 --- a/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr +++ b/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr @@ -10,5 +10,5 @@ LL | b_isize = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr b/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr index f3973a93bad84..098a9c11de448 100644 --- a/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr +++ b/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr @@ -10,5 +10,5 @@ LL | b_isize = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-infer-paramd-indirect.stderr b/tests/ui/regions/regions-infer-paramd-indirect.stderr index afabdc1de1c7d..4a1cd111936e1 100644 --- a/tests/ui/regions/regions-infer-paramd-indirect.stderr +++ b/tests/ui/regions/regions-infer-paramd-indirect.stderr @@ -9,5 +9,5 @@ LL | fn set_f_bad(&mut self, b: Box) { LL | self.f = b; | ^^^^^^ assignment requires that `'1` must outlive `'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-infer-proc-static-upvar.stderr b/tests/ui/regions/regions-infer-proc-static-upvar.stderr index c8a33bbc52236..919fcffdc531e 100644 --- a/tests/ui/regions/regions-infer-proc-static-upvar.stderr +++ b/tests/ui/regions/regions-infer-proc-static-upvar.stderr @@ -12,6 +12,6 @@ LL | | }); LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr index 53a5612d24f25..31dd7efe067cf 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -9,6 +9,6 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-name-duplicated.stderr b/tests/ui/regions/regions-name-duplicated.stderr index cef73c18d371e..8b0cc925a8660 100644 --- a/tests/ui/regions/regions-name-duplicated.stderr +++ b/tests/ui/regions/regions-name-duplicated.stderr @@ -6,6 +6,6 @@ LL | struct Foo<'a, 'a> { | | | first use of `'a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/regions/regions-name-static.stderr b/tests/ui/regions/regions-name-static.stderr index 4b7026e65eacc..6d334b498affb 100644 --- a/tests/ui/regions/regions-name-static.stderr +++ b/tests/ui/regions/regions-name-static.stderr @@ -4,6 +4,6 @@ error[E0262]: invalid lifetime parameter name: `'static` LL | struct Foo<'static> { | ^^^^^^^ 'static is a reserved lifetime name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0262`. diff --git a/tests/ui/regions/regions-nested-fns-2.stderr b/tests/ui/regions/regions-nested-fns-2.stderr index 43c8d1272c744..254497639a179 100644 --- a/tests/ui/regions/regions-nested-fns-2.stderr +++ b/tests/ui/regions/regions-nested-fns-2.stderr @@ -12,6 +12,6 @@ LL | if false { &y } else { z } LL | } | - `y` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-normalize-in-where-clause-list.stderr b/tests/ui/regions/regions-normalize-in-where-clause-list.stderr index 5672837290cb1..2e76333e26f00 100644 --- a/tests/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/tests/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -22,6 +22,6 @@ LL | fn bar<'a, 'b>() = note: expected `Project<'a, 'b>` found `Project<'_, '_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/regions/regions-outlives-projection-container-wc.stderr b/tests/ui/regions/regions-outlives-projection-container-wc.stderr index eba2a0d585346..1c270d6c366f5 100644 --- a/tests/ui/regions/regions-outlives-projection-container-wc.stderr +++ b/tests/ui/regions/regions-outlives-projection-container-wc.stderr @@ -11,5 +11,5 @@ LL | let _: &'a WithAssoc> = loop { }; | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-pattern-typing-issue-19552.stderr b/tests/ui/regions/regions-pattern-typing-issue-19552.stderr index 18aec29ad0b74..1d3d5e831c39c 100644 --- a/tests/ui/regions/regions-pattern-typing-issue-19552.stderr +++ b/tests/ui/regions/regions-pattern-typing-issue-19552.stderr @@ -11,6 +11,6 @@ LL | } LL | } | - `line` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-pattern-typing-issue-19997.stderr b/tests/ui/regions/regions-pattern-typing-issue-19997.stderr index 0abe77a86977f..b2f63b3b8f27e 100644 --- a/tests/ui/regions/regions-pattern-typing-issue-19997.stderr +++ b/tests/ui/regions/regions-pattern-typing-issue-19997.stderr @@ -9,6 +9,6 @@ LL | a1 = &f; LL | drop(b0); | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/regions/regions-proc-bound-capture.stderr b/tests/ui/regions/regions-proc-bound-capture.stderr index 60c5246e24070..3fe497bf2e99f 100644 --- a/tests/ui/regions/regions-proc-bound-capture.stderr +++ b/tests/ui/regions/regions-proc-bound-capture.stderr @@ -16,5 +16,5 @@ help: alternatively, add an explicit `'static` bound to this reference LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> { | ~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr index dc905d076bb7d..40d4f1652796d 100644 --- a/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr +++ b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr @@ -10,5 +10,5 @@ LL | &mut ***p | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr index c98ec477417bd..fd23fce76c82a 100644 --- a/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr +++ b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr @@ -10,5 +10,5 @@ LL | &mut **p | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-ret-borrowed-1.stderr b/tests/ui/regions/regions-ret-borrowed-1.stderr index 0784e894ea920..4ad526602df6b 100644 --- a/tests/ui/regions/regions-ret-borrowed-1.stderr +++ b/tests/ui/regions/regions-ret-borrowed-1.stderr @@ -7,5 +7,5 @@ LL | with(|o| o) | |return type of closure is &'2 isize | has type `&'1 isize` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-ret-borrowed.stderr b/tests/ui/regions/regions-ret-borrowed.stderr index d9be5ef89cceb..f16a4a2e8c154 100644 --- a/tests/ui/regions/regions-ret-borrowed.stderr +++ b/tests/ui/regions/regions-ret-borrowed.stderr @@ -7,5 +7,5 @@ LL | with(|o| o) | |return type of closure is &'2 isize | has type `&'1 isize` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-ret.stderr b/tests/ui/regions/regions-ret.stderr index 0e4875ac9855b..470b6ab06dd31 100644 --- a/tests/ui/regions/regions-ret.stderr +++ b/tests/ui/regions/regions-ret.stderr @@ -7,6 +7,6 @@ LL | return &id(3); | |temporary value created here | returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr index b087e03b464b3..be9ffbe8d91a0 100644 --- a/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr +++ b/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr @@ -13,5 +13,5 @@ LL | let mut f = || &mut x; = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-return-stack-allocated-vec.stderr b/tests/ui/regions/regions-return-stack-allocated-vec.stderr index 9d87fe266b158..68631c74e7797 100644 --- a/tests/ui/regions/regions-return-stack-allocated-vec.stderr +++ b/tests/ui/regions/regions-return-stack-allocated-vec.stderr @@ -7,6 +7,6 @@ LL | &[x] | |temporary value created here | returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-steal-closure.stderr b/tests/ui/regions/regions-steal-closure.stderr index 5b0efaf95597d..9324eb892a67d 100644 --- a/tests/ui/regions/regions-steal-closure.stderr +++ b/tests/ui/regions/regions-steal-closure.stderr @@ -11,6 +11,6 @@ LL | box_it(Box::new(|| i += 1)) LL | }; | - `i` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-trait-variance.stderr b/tests/ui/regions/regions-trait-variance.stderr index 56c9f89e1f597..235950c2e0a7d 100644 --- a/tests/ui/regions/regions-trait-variance.stderr +++ b/tests/ui/regions/regions-trait-variance.stderr @@ -6,6 +6,6 @@ LL | let bb: &B = &*b; LL | make_a(bb) | ^^^^^^^^^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-var-type-out-of-scope.stderr b/tests/ui/regions/regions-var-type-out-of-scope.stderr index c32bbe0ee1fb4..b261f5a41b684 100644 --- a/tests/ui/regions/regions-var-type-out-of-scope.stderr +++ b/tests/ui/regions/regions-var-type-out-of-scope.stderr @@ -10,6 +10,6 @@ LL | assert_eq!(*x, 3); | = note: consider using a `let` binding to create a longer lived value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr b/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr index 5352be430fbc5..5e952ee57715c 100644 --- a/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr +++ b/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr @@ -11,5 +11,5 @@ LL | let _: S<'long, 'long> = c; | = help: consider adding the following bound: `'short: 'long` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-variance-contravariant-use-covariant.stderr b/tests/ui/regions/regions-variance-contravariant-use-covariant.stderr index 22c9b915bb9ee..bb96bf5970c69 100644 --- a/tests/ui/regions/regions-variance-contravariant-use-covariant.stderr +++ b/tests/ui/regions/regions-variance-contravariant-use-covariant.stderr @@ -11,5 +11,5 @@ LL | let _: Contravariant<'long> = c; | = help: consider adding the following bound: `'short: 'long` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-variance-covariant-use-contravariant.stderr b/tests/ui/regions/regions-variance-covariant-use-contravariant.stderr index a07181ad553e6..b544bf5ecb201 100644 --- a/tests/ui/regions/regions-variance-covariant-use-contravariant.stderr +++ b/tests/ui/regions/regions-variance-covariant-use-contravariant.stderr @@ -11,5 +11,5 @@ LL | let _: Covariant<'short> = c; | = help: consider adding the following bound: `'short: 'long` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-variance-invariant-use-contravariant.stderr b/tests/ui/regions/regions-variance-invariant-use-contravariant.stderr index b35a2cb905dc3..4695045bbb737 100644 --- a/tests/ui/regions/regions-variance-invariant-use-contravariant.stderr +++ b/tests/ui/regions/regions-variance-invariant-use-contravariant.stderr @@ -14,5 +14,5 @@ LL | let _: Invariant<'short> = c; = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-variance-invariant-use-covariant.stderr b/tests/ui/regions/regions-variance-invariant-use-covariant.stderr index 761e78d179e41..5945f9ba1ba5d 100644 --- a/tests/ui/regions/regions-variance-invariant-use-covariant.stderr +++ b/tests/ui/regions/regions-variance-invariant-use-covariant.stderr @@ -11,5 +11,5 @@ LL | let _: Invariant<'static> = c; = note: the struct `Invariant<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-wf-trait-object.stderr b/tests/ui/regions/regions-wf-trait-object.stderr index f6006ca046a88..2099615082083 100644 --- a/tests/ui/regions/regions-wf-trait-object.stderr +++ b/tests/ui/regions/regions-wf-trait-object.stderr @@ -15,6 +15,6 @@ note: but lifetime parameter must outlive the lifetime `'a` as defined here LL | struct Foo<'a,'b> { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr b/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr index 1bf8e6e062f2e..2e3ede46eca5d 100644 --- a/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr +++ b/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr @@ -11,6 +11,6 @@ LL + #[derive(Copy)] LL | struct Foo { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/repr/issue-83921-ice.rs b/tests/ui/repr/malformed-repr-hints.rs similarity index 76% rename from tests/ui/repr/issue-83921-ice.rs rename to tests/ui/repr/malformed-repr-hints.rs index 70583eb9bd332..27840b5f835d8 100644 --- a/tests/ui/repr/issue-83921-ice.rs +++ b/tests/ui/repr/malformed-repr-hints.rs @@ -19,6 +19,15 @@ struct S3; //~^ ERROR: incorrect `repr(align)` attribute format struct S4; +// Regression test for issue #118334: +#[repr(Rust(u8))] +//~^ ERROR: invalid representation hint +#[repr(Rust(0))] +//~^ ERROR: invalid representation hint +#[repr(Rust = 0)] +//~^ ERROR: invalid representation hint +struct S5; + #[repr(i8())] //~^ ERROR: invalid representation hint enum E1 { A, B } diff --git a/tests/ui/repr/issue-83921-ice.stderr b/tests/ui/repr/malformed-repr-hints.stderr similarity index 58% rename from tests/ui/repr/issue-83921-ice.stderr rename to tests/ui/repr/malformed-repr-hints.stderr index 32c450410eace..6fb927557619f 100644 --- a/tests/ui/repr/issue-83921-ice.stderr +++ b/tests/ui/repr/malformed-repr-hints.stderr @@ -1,46 +1,64 @@ error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all - --> $DIR/issue-83921-ice.rs:6:8 + --> $DIR/malformed-repr-hints.rs:6:8 | LL | #[repr(packed())] | ^^^^^^^^ error[E0589]: invalid `repr(align)` attribute: `align` needs an argument - --> $DIR/issue-83921-ice.rs:10:8 + --> $DIR/malformed-repr-hints.rs:10:8 | LL | #[repr(align)] | ^^^^^ help: supply an argument here: `align(...)` error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/issue-83921-ice.rs:14:8 + --> $DIR/malformed-repr-hints.rs:14:8 | LL | #[repr(align(2, 4))] | ^^^^^^^^^^^ error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/issue-83921-ice.rs:18:8 + --> $DIR/malformed-repr-hints.rs:18:8 | LL | #[repr(align())] | ^^^^^^^ +error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list + --> $DIR/malformed-repr-hints.rs:23:8 + | +LL | #[repr(Rust(u8))] + | ^^^^^^^^ + +error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list + --> $DIR/malformed-repr-hints.rs:25:8 + | +LL | #[repr(Rust(0))] + | ^^^^^^^ + +error[E0552]: invalid representation hint: `Rust` does not take a value + --> $DIR/malformed-repr-hints.rs:27:8 + | +LL | #[repr(Rust = 0)] + | ^^^^^^^^ + error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list - --> $DIR/issue-83921-ice.rs:22:8 + --> $DIR/malformed-repr-hints.rs:31:8 | LL | #[repr(i8())] | ^^^^ error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list - --> $DIR/issue-83921-ice.rs:26:8 + --> $DIR/malformed-repr-hints.rs:35:8 | LL | #[repr(u32(42))] | ^^^^^^^ error[E0552]: invalid representation hint: `i64` does not take a value - --> $DIR/issue-83921-ice.rs:30:8 + --> $DIR/malformed-repr-hints.rs:39:8 | LL | #[repr(i64 = 2)] | ^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0552, E0589, E0693. For more information about an error, try `rustc --explain E0552`. diff --git a/tests/ui/repr/repr-disallow-on-variant.stderr b/tests/ui/repr/repr-disallow-on-variant.stderr index f7e4dcc9d81be..ebdb851b7a64f 100644 --- a/tests/ui/repr/repr-disallow-on-variant.stderr +++ b/tests/ui/repr/repr-disallow-on-variant.stderr @@ -7,6 +7,6 @@ LL | LL | Variant, | ------- not an enum -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/repr/transparent-enum-too-many-variants.stderr b/tests/ui/repr/transparent-enum-too-many-variants.stderr index 1a500257f48c5..1e434d22b1070 100644 --- a/tests/ui/repr/transparent-enum-too-many-variants.stderr +++ b/tests/ui/repr/transparent-enum-too-many-variants.stderr @@ -8,6 +8,6 @@ LL | A(u8), B(u8), | | | variant here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0731`. diff --git a/tests/ui/reserved/reserved-become.stderr b/tests/ui/reserved/reserved-become.stderr index 0703b76d6de4a..8e9fa18557c16 100644 --- a/tests/ui/reserved/reserved-become.stderr +++ b/tests/ui/reserved/reserved-become.stderr @@ -9,5 +9,5 @@ help: escape `become` to use it as an identifier LL | let r#become = 0; | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/resolve/bad-type-env-capture.stderr b/tests/ui/resolve/bad-type-env-capture.stderr index 941b6b7a68c35..3f9bc9149c24a 100644 --- a/tests/ui/resolve/bad-type-env-capture.stderr +++ b/tests/ui/resolve/bad-type-env-capture.stderr @@ -8,6 +8,6 @@ LL | fn bar(b: T) { } | | | help: try introducing a local generic parameter here: `` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/crate-called-as-function.stderr b/tests/ui/resolve/crate-called-as-function.stderr index eb42349aff1b6..1d6eb8ad6f5e0 100644 --- a/tests/ui/resolve/crate-called-as-function.stderr +++ b/tests/ui/resolve/crate-called-as-function.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find external crate `foo` in the crate root LL | ::foo() | ^^^ not found in the crate root -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/crate-in-paths.stderr b/tests/ui/resolve/crate-in-paths.stderr index 07fb5dcc035c1..9eb735a3aab53 100644 --- a/tests/ui/resolve/crate-in-paths.stderr +++ b/tests/ui/resolve/crate-in-paths.stderr @@ -9,6 +9,6 @@ help: consider importing this unit struct LL + use crate::bar::Foo; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/disambiguate-identical-names.stderr b/tests/ui/resolve/disambiguate-identical-names.stderr index 7d8293018d27b..9900ade3d8e8b 100644 --- a/tests/ui/resolve/disambiguate-identical-names.stderr +++ b/tests/ui/resolve/disambiguate-identical-names.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn test(_v: &Vec>) { | ^^^^ ------------------ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/resolve/enums-pats-not-idents.stderr b/tests/ui/resolve/enums-pats-not-idents.stderr index 072b88716ad7c..6bb6e152c800c 100644 --- a/tests/ui/resolve/enums-pats-not-idents.stderr +++ b/tests/ui/resolve/enums-pats-not-idents.stderr @@ -4,6 +4,6 @@ error[E0531]: cannot find tuple struct or tuple variant `a` in this scope LL | let a(1) = 13; | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0531`. diff --git a/tests/ui/resolve/explicit-self-lowercase-param.stderr b/tests/ui/resolve/explicit-self-lowercase-param.stderr index cd64dbb3854af..6daa6f5d7af58 100644 --- a/tests/ui/resolve/explicit-self-lowercase-param.stderr +++ b/tests/ui/resolve/explicit-self-lowercase-param.stderr @@ -4,5 +4,5 @@ error: attempt to use a non-constant value in a constant LL | fn do_nothing(self: Box) {} | ^^^^ help: try using `Self` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/resolve/export-fully-qualified-2018.stderr b/tests/ui/resolve/export-fully-qualified-2018.stderr index b724da930dfa0..378d9832a657a 100644 --- a/tests/ui/resolve/export-fully-qualified-2018.stderr +++ b/tests/ui/resolve/export-fully-qualified-2018.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` LL | pub fn bar() { foo::baz(); } | ^^^ use of undeclared crate or module `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr index a8af0c7c9b823..869149d8d3c65 100644 --- a/tests/ui/resolve/export-fully-qualified.stderr +++ b/tests/ui/resolve/export-fully-qualified.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` LL | pub fn bar() { foo::baz(); } | ^^^ use of undeclared crate or module `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/fn-new-doesnt-exist.rs b/tests/ui/resolve/fn-new-doesnt-exist.rs new file mode 100644 index 0000000000000..4f6290808fc03 --- /dev/null +++ b/tests/ui/resolve/fn-new-doesnt-exist.rs @@ -0,0 +1,5 @@ +use std::net::TcpStream; + +fn main() { + let stream = TcpStream::new(); //~ ERROR no function or associated item named `new` found +} diff --git a/tests/ui/resolve/fn-new-doesnt-exist.stderr b/tests/ui/resolve/fn-new-doesnt-exist.stderr new file mode 100644 index 0000000000000..418dd9ea6b846 --- /dev/null +++ b/tests/ui/resolve/fn-new-doesnt-exist.stderr @@ -0,0 +1,14 @@ +error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope + --> $DIR/fn-new-doesnt-exist.rs:4:28 + | +LL | let stream = TcpStream::new(); + | ^^^ function or associated item not found in `TcpStream` + | +note: if you're trying to build a new `TcpStream` consider using one of the following associated functions: + TcpStream::connect + TcpStream::connect_timeout + --> $SRC_DIR/std/src/net/tcp.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/resolve/impl-items-vis-unresolved.stderr b/tests/ui/resolve/impl-items-vis-unresolved.stderr index f2293d28ea151..cccffdcbf541b 100644 --- a/tests/ui/resolve/impl-items-vis-unresolved.stderr +++ b/tests/ui/resolve/impl-items-vis-unresolved.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: there are too many leading `super` keywords LL | pub(super) fn new() {} | ^^^^^ there are too many leading `super` keywords -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-101749-2.stderr b/tests/ui/resolve/issue-101749-2.stderr index 370d4b14540d6..300aaf26cb7d8 100644 --- a/tests/ui/resolve/issue-101749-2.stderr +++ b/tests/ui/resolve/issue-101749-2.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `rect` LL | let _ = rect::area(); | ^^^^ use of undeclared crate or module `rect` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-101749.stderr b/tests/ui/resolve/issue-101749.stderr index dd29d7fc05103..05515b1b46052 100644 --- a/tests/ui/resolve/issue-101749.stderr +++ b/tests/ui/resolve/issue-101749.stderr @@ -9,6 +9,6 @@ help: you may have meant to call an instance method LL | let _ = rect.area(); | ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-10200.stderr b/tests/ui/resolve/issue-10200.stderr index e60489f5b82f4..7b218694b269e 100644 --- a/tests/ui/resolve/issue-10200.stderr +++ b/tests/ui/resolve/issue-10200.stderr @@ -7,6 +7,6 @@ LL | struct Foo(bool); LL | foo(x) | ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/resolve/issue-103202.stderr b/tests/ui/resolve/issue-103202.stderr index d4d141fb06f39..87fa940ac3b25 100644 --- a/tests/ui/resolve/issue-103202.stderr +++ b/tests/ui/resolve/issue-103202.stderr @@ -9,6 +9,6 @@ help: if there were a trait named `Example` with associated type `x` implemented LL | fn f(self: &::x) {} | ~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/resolve/issue-105069.stderr b/tests/ui/resolve/issue-105069.stderr index a049cac830ab4..5e87ccf41327d 100644 --- a/tests/ui/resolve/issue-105069.stderr +++ b/tests/ui/resolve/issue-105069.stderr @@ -18,6 +18,6 @@ LL | use self::B::*; | ^^^^^^^^^^ = help: consider adding an explicit import of `V` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/resolve/issue-108529.stderr b/tests/ui/resolve/issue-108529.stderr index cf4e4759c3702..ef1a6c919eebf 100644 --- a/tests/ui/resolve/issue-108529.stderr +++ b/tests/ui/resolve/issue-108529.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `f::f` LL | use f::f::f; | ^ expected type, found associated function `f` in `f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/resolve/issue-109153.stderr b/tests/ui/resolve/issue-109153.stderr index 1a345d2a3e3a7..da95029f6e783 100644 --- a/tests/ui/resolve/issue-109153.stderr +++ b/tests/ui/resolve/issue-109153.stderr @@ -18,6 +18,6 @@ LL | use bar::*; | ^^^^^^ = help: consider adding an explicit import of `bar` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/resolve/issue-109250.stderr b/tests/ui/resolve/issue-109250.stderr index d5b8c08ced7d7..ad6cc6986229a 100644 --- a/tests/ui/resolve/issue-109250.stderr +++ b/tests/ui/resolve/issue-109250.stderr @@ -9,6 +9,6 @@ help: consider importing this struct LL + use std::collections::HashMap; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr index 4c864029c9870..7e7ef22ae6195 100644 --- a/tests/ui/resolve/issue-111312.stderr +++ b/tests/ui/resolve/issue-111312.stderr @@ -10,6 +10,6 @@ note: `Has` defines an item `has` LL | trait Has { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr index bd748211ed321..b58168d0e7581 100644 --- a/tests/ui/resolve/issue-111727.stderr +++ b/tests/ui/resolve/issue-111727.stderr @@ -4,6 +4,6 @@ error[E0599]: no function or associated item named `create` found for trait `Any LL | std::any::Any::create(); | ^^^^^^ function or associated item not found in `Any` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/resolve/issue-116164.stderr b/tests/ui/resolve/issue-116164.stderr index 5820a189fd572..8880242c19561 100644 --- a/tests/ui/resolve/issue-116164.stderr +++ b/tests/ui/resolve/issue-116164.stderr @@ -9,6 +9,6 @@ help: consider importing this unit variant LL + use inner::Example::ExOne; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-117920.rs b/tests/ui/resolve/issue-117920.rs new file mode 100644 index 0000000000000..928f194c59c3f --- /dev/null +++ b/tests/ui/resolve/issue-117920.rs @@ -0,0 +1,11 @@ +#![crate_type = "lib"] + +use super::A; //~ ERROR failed to resolve + +mod b { + pub trait A {} + pub trait B {} +} + +/// [`A`] +pub use b::*; diff --git a/tests/ui/resolve/issue-117920.stderr b/tests/ui/resolve/issue-117920.stderr new file mode 100644 index 0000000000000..c4528d467e9f5 --- /dev/null +++ b/tests/ui/resolve/issue-117920.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: there are too many leading `super` keywords + --> $DIR/issue-117920.rs:3:5 + | +LL | use super::A; + | ^^^^^ there are too many leading `super` keywords + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-118295.rs b/tests/ui/resolve/issue-118295.rs new file mode 100644 index 0000000000000..b97681d956341 --- /dev/null +++ b/tests/ui/resolve/issue-118295.rs @@ -0,0 +1,5 @@ +macro_rules! {} +//~^ ERROR cannot find macro `macro_rules` in this scope +//~| NOTE maybe you have forgotten to define a name for this `macro_rules!` + +fn main() {} diff --git a/tests/ui/resolve/issue-118295.stderr b/tests/ui/resolve/issue-118295.stderr new file mode 100644 index 0000000000000..d60d7d9185db4 --- /dev/null +++ b/tests/ui/resolve/issue-118295.stderr @@ -0,0 +1,14 @@ +error: cannot find macro `macro_rules` in this scope + --> $DIR/issue-118295.rs:1:1 + | +LL | macro_rules! {} + | ^^^^^^^^^^^ + | +note: maybe you have forgotten to define a name for this `macro_rules!` + --> $DIR/issue-118295.rs:1:1 + | +LL | macro_rules! {} + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/resolve/issue-12796.stderr b/tests/ui/resolve/issue-12796.stderr index ef59d00360b88..6809fd50f7475 100644 --- a/tests/ui/resolve/issue-12796.stderr +++ b/tests/ui/resolve/issue-12796.stderr @@ -7,6 +7,6 @@ LL | fn inner(_: &Self) { | use of generic parameter from outer item | can't use `Self` here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/issue-16058.stderr b/tests/ui/resolve/issue-16058.stderr index 710002a154efd..914990c35ff76 100644 --- a/tests/ui/resolve/issue-16058.stderr +++ b/tests/ui/resolve/issue-16058.stderr @@ -13,6 +13,6 @@ LL + use std::io::Result; LL + use std::thread::Result; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/resolve/issue-17518.stderr b/tests/ui/resolve/issue-17518.stderr index 492e3b34a1798..3eba715188b40 100644 --- a/tests/ui/resolve/issue-17518.stderr +++ b/tests/ui/resolve/issue-17518.stderr @@ -9,6 +9,6 @@ help: consider importing this variant LL + use SomeEnum::E; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/resolve/issue-18252.stderr b/tests/ui/resolve/issue-18252.stderr index d9006c0a6c269..511b8da716fd4 100644 --- a/tests/ui/resolve/issue-18252.stderr +++ b/tests/ui/resolve/issue-18252.stderr @@ -4,6 +4,6 @@ error[E0533]: expected value, found struct variant `Foo::Variant` LL | let f = Foo::Variant(42); | ^^^^^^^^^^^^ not a value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0533`. diff --git a/tests/ui/resolve/issue-21221-2.stderr b/tests/ui/resolve/issue-21221-2.stderr index 9beb626623e4e..3bd4c1a5d1315 100644 --- a/tests/ui/resolve/issue-21221-2.stderr +++ b/tests/ui/resolve/issue-21221-2.stderr @@ -11,6 +11,6 @@ LL + use baz::T; LL + use foo::bar::T; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/issue-21221-3.stderr b/tests/ui/resolve/issue-21221-3.stderr index 0dabdfd9b3900..ed3eb2dfb237f 100644 --- a/tests/ui/resolve/issue-21221-3.stderr +++ b/tests/ui/resolve/issue-21221-3.stderr @@ -9,6 +9,6 @@ help: consider importing this trait LL + use issue_21221_3::outer::OuterTrait; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/issue-21221-4.stderr b/tests/ui/resolve/issue-21221-4.stderr index 5af14b1b68d36..482a3bd54a33e 100644 --- a/tests/ui/resolve/issue-21221-4.stderr +++ b/tests/ui/resolve/issue-21221-4.stderr @@ -9,6 +9,6 @@ help: consider importing this trait LL + use issue_21221_4::T; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/issue-2330.stderr b/tests/ui/resolve/issue-2330.stderr index 877cf68b5866c..8ac8a6dc41130 100644 --- a/tests/ui/resolve/issue-2330.stderr +++ b/tests/ui/resolve/issue-2330.stderr @@ -4,6 +4,6 @@ error[E0404]: expected trait, found enum `Chan` LL | impl Chan for isize { | ^^^^ not a trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/issue-23305.stderr b/tests/ui/resolve/issue-23305.stderr index aad1b583a3244..e522e461efc05 100644 --- a/tests/ui/resolve/issue-23305.stderr +++ b/tests/ui/resolve/issue-23305.stderr @@ -6,5 +6,5 @@ LL | impl dyn ToNbt {} | = note: replace `Self` with a different type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-26545.stderr b/tests/ui/resolve/issue-26545.stderr index 42a7531c5b940..ced19ea1819cd 100644 --- a/tests/ui/resolve/issue-26545.stderr +++ b/tests/ui/resolve/issue-26545.stderr @@ -9,6 +9,6 @@ help: consider importing this tuple struct LL + use foo::B; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-3021.stderr b/tests/ui/resolve/issue-3021.stderr index d5b015eec3509..5dc4f9542fee5 100644 --- a/tests/ui/resolve/issue-3021.stderr +++ b/tests/ui/resolve/issue-3021.stderr @@ -6,6 +6,6 @@ LL | self.v0 = k0 ^ 0x736f6d6570736575; | = help: use the `|| { ... }` closure form instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/resolve/issue-30535.stderr b/tests/ui/resolve/issue-30535.stderr index e3692934b62ad..0fa96a87482cc 100644 --- a/tests/ui/resolve/issue-30535.stderr +++ b/tests/ui/resolve/issue-30535.stderr @@ -7,6 +7,6 @@ LL | _: foo::Foo::FooV | not a type | help: try using the variant's enum: `foo::Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/resolve/issue-3099-a.stderr b/tests/ui/resolve/issue-3099-a.stderr index e3733cebba58e..a092f562d3881 100644 --- a/tests/ui/resolve/issue-3099-a.stderr +++ b/tests/ui/resolve/issue-3099-a.stderr @@ -9,6 +9,6 @@ LL | enum A { D, E } | = note: `A` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/resolve/issue-3099-b.stderr b/tests/ui/resolve/issue-3099-b.stderr index c0cfefeb940f4..7817ab40172ee 100644 --- a/tests/ui/resolve/issue-3099-b.stderr +++ b/tests/ui/resolve/issue-3099-b.stderr @@ -9,6 +9,6 @@ LL | pub mod a {} | = note: `a` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/resolve/issue-31845.stderr b/tests/ui/resolve/issue-31845.stderr index 56281938559d0..e65b911151f07 100644 --- a/tests/ui/resolve/issue-31845.stderr +++ b/tests/ui/resolve/issue-31845.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `g` in this scope LL | g(); | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-33876.stderr b/tests/ui/resolve/issue-33876.stderr index 52308f2a7f028..12e1b4b0bd3c3 100644 --- a/tests/ui/resolve/issue-33876.stderr +++ b/tests/ui/resolve/issue-33876.stderr @@ -4,6 +4,6 @@ error[E0423]: expected value, found trait `Bar` LL | let any: &dyn Any = &Bar; | ^^^ not a value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-3907-2.stderr b/tests/ui/resolve/issue-3907-2.stderr index 782cfeec4bcaf..2693daa3c7a5c 100644 --- a/tests/ui/resolve/issue-3907-2.stderr +++ b/tests/ui/resolve/issue-3907-2.stderr @@ -10,6 +10,6 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all LL | fn bar(); | ^^^ the trait cannot be made into an object because associated function `bar` has no `self` parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/resolve/issue-3907.stderr b/tests/ui/resolve/issue-3907.stderr index 70631a13cdf86..e9dc344496e51 100644 --- a/tests/ui/resolve/issue-3907.stderr +++ b/tests/ui/resolve/issue-3907.stderr @@ -13,6 +13,6 @@ help: consider importing this trait instead LL + use issue_3907::Foo; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/issue-39226.stderr b/tests/ui/resolve/issue-39226.stderr index 5045ec6c30e35..857f6a735178e 100644 --- a/tests/ui/resolve/issue-39226.stderr +++ b/tests/ui/resolve/issue-39226.stderr @@ -16,6 +16,6 @@ help: a local variable with a similar name exists LL | handle: handle | ~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-39559.stderr b/tests/ui/resolve/issue-39559.stderr index 7626f827fc5eb..0aab54fe59d5b 100644 --- a/tests/ui/resolve/issue-39559.stderr +++ b/tests/ui/resolve/issue-39559.stderr @@ -5,7 +5,7 @@ LL | entries: [T; D::dim()], | ^^^^^^ cannot perform const operation using `D` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-5035-2.stderr b/tests/ui/resolve/issue-5035-2.stderr index 558e6b7b118d8..8eeb398f077ea 100644 --- a/tests/ui/resolve/issue-5035-2.stderr +++ b/tests/ui/resolve/issue-5035-2.stderr @@ -15,6 +15,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn foo(_x: &K) {} | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr index d58b6ca5b5c42..25e98b4746b79 100644 --- a/tests/ui/resolve/issue-50599.stderr +++ b/tests/ui/resolve/issue-50599.stderr @@ -16,6 +16,6 @@ LL - const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; LL + const M: usize = (f64::from(N) * LOG10_2) as usize; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr index 3e9c3fd11b74d..363bb55647827 100644 --- a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr +++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr @@ -7,6 +7,6 @@ LL | extern "C" { LL | static baz: *const A; | ^ use of generic parameter from outer item -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/issue-6642.stderr b/tests/ui/resolve/issue-6642.stderr index 6668108d0245e..7f1a1aa44766f 100644 --- a/tests/ui/resolve/issue-6642.stderr +++ b/tests/ui/resolve/issue-6642.stderr @@ -6,6 +6,6 @@ LL | self.m() | = help: use the `|| { ... }` closure form instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/resolve/issue-6702.stderr b/tests/ui/resolve/issue-6702.stderr index a118f94191df3..d1ceee3e56e82 100644 --- a/tests/ui/resolve/issue-6702.stderr +++ b/tests/ui/resolve/issue-6702.stderr @@ -9,6 +9,6 @@ LL | | } LL | let _m = Monster(); | ^^^^^^^^^ help: use struct literal syntax instead: `Monster { damage: val }` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr b/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr index 109409d2731c5..60ef13551a17c 100644 --- a/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr +++ b/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `b` in this scope LL | fn fn_with_type_named_same_as_local_in_param(b: b); | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/issue-80079.stderr b/tests/ui/resolve/issue-80079.stderr index 93e8c0341a13a..e300ee964bee7 100644 --- a/tests/ui/resolve/issue-80079.stderr +++ b/tests/ui/resolve/issue-80079.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `Foo` in this scope LL | let _ = Foo; | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-82156.stderr b/tests/ui/resolve/issue-82156.stderr index d53599dcce61b..3894b9573a45c 100644 --- a/tests/ui/resolve/issue-82156.stderr +++ b/tests/ui/resolve/issue-82156.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: there are too many leading `super` keywords LL | super(); | ^^^^^ there are too many leading `super` keywords -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr index 730fd6d602645..9d0439d9d8763 100644 --- a/tests/ui/resolve/issue-82865.stderr +++ b/tests/ui/resolve/issue-82865.stderr @@ -15,6 +15,13 @@ LL | Box::z LL | mac!(); | ------ in this macro invocation | +note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions: + Box::::new + Box::::new_uninit + Box::::new_zeroed + Box::::try_new + and 18 others + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/issue-90113.stderr b/tests/ui/resolve/issue-90113.stderr index 5f55d9c241a58..d25c67825e3a1 100644 --- a/tests/ui/resolve/issue-90113.stderr +++ b/tests/ui/resolve/issue-90113.stderr @@ -9,6 +9,6 @@ help: consider importing this tuple variant LL + use list::List::Cons; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0531`. diff --git a/tests/ui/resolve/missing-in-namespace.stderr b/tests/ui/resolve/missing-in-namespace.stderr index 7a7b749aebb7b..35585e4240a2b 100644 --- a/tests/ui/resolve/missing-in-namespace.stderr +++ b/tests/ui/resolve/missing-in-namespace.stderr @@ -14,6 +14,6 @@ LL - let _map = std::hahmap::HashMap::new(); LL + let _map = HashMap::new(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/name-clash-nullary.stderr b/tests/ui/resolve/name-clash-nullary.stderr index fffd3027afdb3..08e7fe9a678a1 100644 --- a/tests/ui/resolve/name-clash-nullary.stderr +++ b/tests/ui/resolve/name-clash-nullary.stderr @@ -9,6 +9,6 @@ LL | let None: isize = 42; = note: expected type `isize` found enum `Option<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr b/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr index 5790e425c0a23..a7770e1e7e498 100644 --- a/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr +++ b/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr @@ -10,6 +10,6 @@ LL | impl Foo for Bar { LL | Baz { num } => num, | ^^^ not a struct, variant or union type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/resolve/raw-ident-in-path.stderr b/tests/ui/resolve/raw-ident-in-path.stderr index 771dacbbb20d9..7d2aa69113638 100644 --- a/tests/ui/resolve/raw-ident-in-path.stderr +++ b/tests/ui/resolve/raw-ident-in-path.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `r#break` in the crate root LL | type A = crate::r#break; | ^^^^^^^ not found in the crate root -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/resolve-bad-import-prefix.stderr b/tests/ui/resolve/resolve-bad-import-prefix.stderr index 852b9c6afff3e..36eb3148ab510 100644 --- a/tests/ui/resolve/resolve-bad-import-prefix.stderr +++ b/tests/ui/resolve/resolve-bad-import-prefix.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `Nonexistent` LL | use Nonexistent::{}; | ^^^^^^^^^^^^^^^ no `Nonexistent` in the root -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr b/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr index ea6cb9eb00d8f..999e9a47d6c5f 100644 --- a/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr +++ b/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr @@ -6,6 +6,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate std as other_std; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr b/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr index abf068a1f68b7..e22e636adb6b5 100644 --- a/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr +++ b/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr @@ -10,6 +10,6 @@ help: you can use `as` to change the binding name of the import LL | use std::slice as other_std; | ~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/resolve/resolve-conflict-import-vs-import.stderr b/tests/ui/resolve/resolve-conflict-import-vs-import.stderr index 632be50f4c4bf..de33addcb235d 100644 --- a/tests/ui/resolve/resolve-conflict-import-vs-import.stderr +++ b/tests/ui/resolve/resolve-conflict-import-vs-import.stderr @@ -8,6 +8,6 @@ LL | use std::mem::transmute; | = note: `transmute` must be defined only once in the value namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr b/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr index 7b9fb6c63f677..1097dab415ed2 100644 --- a/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr +++ b/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr @@ -6,6 +6,6 @@ LL | mod std {} | = note: `std` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0260`. diff --git a/tests/ui/resolve/resolve-conflict-item-vs-import.stderr b/tests/ui/resolve/resolve-conflict-item-vs-import.stderr index 5e5c9f6b3d8e2..3b1b5f1ad001e 100644 --- a/tests/ui/resolve/resolve-conflict-item-vs-import.stderr +++ b/tests/ui/resolve/resolve-conflict-item-vs-import.stderr @@ -13,6 +13,6 @@ help: you can use `as` to change the binding name of the import LL | use std::mem::transmute as other_transmute; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/resolve/resolve-conflict-type-vs-import.stderr b/tests/ui/resolve/resolve-conflict-type-vs-import.stderr index 198ef10311ee9..c5cb4e078620a 100644 --- a/tests/ui/resolve/resolve-conflict-type-vs-import.stderr +++ b/tests/ui/resolve/resolve-conflict-type-vs-import.stderr @@ -13,6 +13,6 @@ help: you can use `as` to change the binding name of the import LL | use std::slice::Iter as OtherIter; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/resolve/resolve-dont-hint-macro.rs b/tests/ui/resolve/resolve-dont-hint-macro.rs new file mode 100644 index 0000000000000..da1752b337ebf --- /dev/null +++ b/tests/ui/resolve/resolve-dont-hint-macro.rs @@ -0,0 +1,4 @@ +fn main() { + let zero = assert_eq::<()>(); + //~^ ERROR expected function, found macro `assert_eq` +} diff --git a/tests/ui/resolve/resolve-dont-hint-macro.stderr b/tests/ui/resolve/resolve-dont-hint-macro.stderr new file mode 100644 index 0000000000000..597e014d255dc --- /dev/null +++ b/tests/ui/resolve/resolve-dont-hint-macro.stderr @@ -0,0 +1,9 @@ +error[E0423]: expected function, found macro `assert_eq` + --> $DIR/resolve-dont-hint-macro.rs:2:16 + | +LL | let zero = assert_eq::<()>(); + | ^^^^^^^^^^^^^^^ not a function + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/resolve-label.stderr b/tests/ui/resolve/resolve-label.stderr index 5729348ef2104..4c93cf9ea3ffe 100644 --- a/tests/ui/resolve/resolve-label.stderr +++ b/tests/ui/resolve/resolve-label.stderr @@ -9,6 +9,6 @@ LL | break 'l; | = note: labels are unreachable through functions, closures, async blocks and modules -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0767`. diff --git a/tests/ui/resolve/suggest-import-without-clobbering-attrs.stderr b/tests/ui/resolve/suggest-import-without-clobbering-attrs.stderr index d3574851d5c11..de65d695dd23d 100644 --- a/tests/ui/resolve/suggest-import-without-clobbering-attrs.stderr +++ b/tests/ui/resolve/suggest-import-without-clobbering-attrs.stderr @@ -9,6 +9,6 @@ help: consider importing this function LL + use y::z; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/token-error-correct-2.stderr b/tests/ui/resolve/token-error-correct-2.stderr index be5fb18a5d88a..662b849da9e60 100644 --- a/tests/ui/resolve/token-error-correct-2.stderr +++ b/tests/ui/resolve/token-error-correct-2.stderr @@ -6,5 +6,5 @@ LL | if foo { LL | ) | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/resolve/token-error-correct-3.stderr b/tests/ui/resolve/token-error-correct-3.stderr index 79d1d4883a13f..d4ca6c6b75cdc 100644 --- a/tests/ui/resolve/token-error-correct-3.stderr +++ b/tests/ui/resolve/token-error-correct-3.stderr @@ -9,5 +9,5 @@ LL | fs::create_dir_all(path.as_ref()).map(|()| true) LL | } else { | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/resolve/token-error-correct-4.stderr b/tests/ui/resolve/token-error-correct-4.stderr index 3ec97171fd327..c4e50cdbfad1d 100644 --- a/tests/ui/resolve/token-error-correct-4.stderr +++ b/tests/ui/resolve/token-error-correct-4.stderr @@ -8,5 +8,5 @@ LL | setsuna(kazusa(); LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/resolve/token-error-correct.stderr b/tests/ui/resolve/token-error-correct.stderr index 35b2d0b323bca..5fa3703fdc380 100644 --- a/tests/ui/resolve/token-error-correct.stderr +++ b/tests/ui/resolve/token-error-correct.stderr @@ -8,5 +8,5 @@ LL | foo(bar(; LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/resolve/tool-import.stderr b/tests/ui/resolve/tool-import.stderr index d3bdfc93d4923..b070439d72b77 100644 --- a/tests/ui/resolve/tool-import.stderr +++ b/tests/ui/resolve/tool-import.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: `clippy` is a tool module, not a module LL | use clippy::time::Instant; | ^^^^^^ `clippy` is a tool module, not a module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/unresolved-segments-visibility.stderr b/tests/ui/resolve/unresolved-segments-visibility.stderr index 0a11549cdbf39..09f3c50258d93 100644 --- a/tests/ui/resolve/unresolved-segments-visibility.stderr +++ b/tests/ui/resolve/unresolved-segments-visibility.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: `String` is a struct, not a module LL | pub(in b::string::String::newy) extern crate alloc as e; | ^^^^^^ `String` is a struct, not a module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/unresolved_static_type_field.stderr b/tests/ui/resolve/unresolved_static_type_field.stderr index 035dc9b9656ad..e3de0a3fb74b3 100644 --- a/tests/ui/resolve/unresolved_static_type_field.stderr +++ b/tests/ui/resolve/unresolved_static_type_field.stderr @@ -7,6 +7,6 @@ LL | cx: bool, LL | f(cx); | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/use-self-in-inner-fn.stderr b/tests/ui/resolve/use-self-in-inner-fn.stderr index 832aaacaf49c8..165e100bf2f5c 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.stderr +++ b/tests/ui/resolve/use-self-in-inner-fn.stderr @@ -10,6 +10,6 @@ LL | fn peach(this: &Self) { | use of generic parameter from outer item | refer to the type directly here instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/ret-non-nil.stderr b/tests/ui/ret-non-nil.stderr index 2029c6d9d81d4..17567c6016a3a 100644 --- a/tests/ui/ret-non-nil.stderr +++ b/tests/ui/ret-non-nil.stderr @@ -6,6 +6,6 @@ LL | fn g() -> isize { return; } | | | expected `isize` because of this return type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0069`. diff --git a/tests/ui/return-disjoint-regions.stderr b/tests/ui/return-disjoint-regions.stderr index ed159298804ae..7b5b032579a28 100644 --- a/tests/ui/return-disjoint-regions.stderr +++ b/tests/ui/return-disjoint-regions.stderr @@ -6,6 +6,6 @@ LL | let y = &x; LL | (y, y) | ^^^^^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/return/issue-64620.stderr b/tests/ui/return/issue-64620.stderr index 3210a67d41805..3c5583da68265 100644 --- a/tests/ui/return/issue-64620.stderr +++ b/tests/ui/return/issue-64620.stderr @@ -4,6 +4,6 @@ error[E0572]: return statement outside of function body LL | V1 = return [0][0], | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/return/issue-82612-return-mutable-reference.stderr b/tests/ui/return/issue-82612-return-mutable-reference.stderr index eb2322d51fd51..59a6bb85d0fd3 100644 --- a/tests/ui/return/issue-82612-return-mutable-reference.stderr +++ b/tests/ui/return/issue-82612-return-mutable-reference.stderr @@ -23,6 +23,6 @@ help: you might have meant to return this value LL | return value.get_or_insert_with(func); | ++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/return/return-from-diverging.stderr b/tests/ui/return/return-from-diverging.stderr index 0c1fb4d9c593a..2eeed960ddbbe 100644 --- a/tests/ui/return/return-from-diverging.stderr +++ b/tests/ui/return/return-from-diverging.stderr @@ -9,6 +9,6 @@ LL | return "wow"; = note: expected type `!` found reference `&'static str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/return/return-type.stderr b/tests/ui/return/return-type.stderr index 60d538eba882a..1757fcac6e258 100644 --- a/tests/ui/return/return-type.stderr +++ b/tests/ui/return/return-type.stderr @@ -15,6 +15,6 @@ help: try adding a return type LL | fn bar() -> S { | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/return/return-unit-from-diverging.stderr b/tests/ui/return/return-unit-from-diverging.stderr index befc57563a9c5..0ce161e24b3c8 100644 --- a/tests/ui/return/return-unit-from-diverging.stderr +++ b/tests/ui/return/return-unit-from-diverging.stderr @@ -6,6 +6,6 @@ LL | fn fail() -> ! { LL | return; | ^^^^^^ return type is not `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0069`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs new file mode 100644 index 0000000000000..e298112244a22 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs @@ -0,0 +1,33 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn main() {} + +macro_rules! never { + () => { ! } +} + +fn no_arms_or_guards(x: Void) { + match None:: { + Some(!) => {} + //~^ ERROR a never pattern is always unreachable + None => {} + } + match None:: { + Some(!) if true, + //~^ ERROR guard on a never pattern + None => {} + } + match None:: { + Some(!) if true => {} + //~^ ERROR a never pattern is always unreachable + None => {} + } + match None:: { + Some(never!()) => {}, + //~^ ERROR a never pattern is always unreachable + None => {} + } +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr new file mode 100644 index 0000000000000..bfbc7a1b5340c --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr @@ -0,0 +1,35 @@ +error: a never pattern is always unreachable + --> $DIR/check.rs:14:20 + | +LL | Some(!) => {} + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: a guard on a never pattern will never be run + --> $DIR/check.rs:19:20 + | +LL | Some(!) if true, + | ^^^^ help: remove this guard + +error: a never pattern is always unreachable + --> $DIR/check.rs:24:28 + | +LL | Some(!) if true => {} + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: a never pattern is always unreachable + --> $DIR/check.rs:29:27 + | +LL | Some(never!()) => {}, + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: aborting due to 4 previous errors + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs new file mode 100644 index 0000000000000..1b23e60e0cac7 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs @@ -0,0 +1,71 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn main() {} + +macro_rules! never { + () => { ! } +} + +fn parse(x: Void) { + match None:: { + None => {} + Some(!), + } + match None:: { + Some(!), + None => {} + } + match None:: { + None => {} + Some(!) + } + match None:: { + Some(!) + //~^ ERROR expected `,` following `match` arm + None => {} + } + match None:: { + Some(!) if true + //~^ ERROR expected `,` following `match` arm + //~| ERROR guard on a never pattern + None => {} + } + match None:: { + Some(!) if true, + //~^ ERROR guard on a never pattern + None => {} + } + match None:: { + Some(!) <= + //~^ ERROR expected one of + } + match x { + never!(), + } + match x { + never!() if true, + //~^ ERROR guard on a never pattern + } + match x { + never!() + } + match &x { + &never!(), + } + match None:: { + Some(never!()), + None => {} + } + match x { ! } + match &x { &! } + + let res: Result = Ok(false); + let Ok(_) = res; + let Ok(_) | Err(!) = &res; // Disallowed; see #82048. + //~^ ERROR top-level or-patterns are not allowed in `let` bindings + let (Ok(_) | Err(!)) = &res; + let (Ok(_) | Err(&!)) = res.as_ref(); +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr new file mode 100644 index 0000000000000..e81a13a3967cb --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr @@ -0,0 +1,44 @@ +error: expected `,` following `match` arm + --> $DIR/parse.rs:26:16 + | +LL | Some(!) + | ^ help: missing a comma here to end this `match` arm: `,` + +error: expected `,` following `match` arm + --> $DIR/parse.rs:31:24 + | +LL | Some(!) if true + | ^ help: missing a comma here to end this `match` arm: `,` + +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `<=` + --> $DIR/parse.rs:42:17 + | +LL | Some(!) <= + | ^^ expected one of `,`, `=>`, `if`, `|`, or `}` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/parse.rs:67:9 + | +LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048. + | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))` + +error: a guard on a never pattern will never be run + --> $DIR/parse.rs:31:20 + | +LL | Some(!) if true + | ^^^^ help: remove this guard + +error: a guard on a never pattern will never be run + --> $DIR/parse.rs:37:20 + | +LL | Some(!) if true, + | ^^^^ help: remove this guard + +error: a guard on a never pattern will never be run + --> $DIR/parse.rs:49:21 + | +LL | never!() if true, + | ^^^^ help: remove this guard + +error: aborting due to 7 previous errors + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr index f08ba522a937c..334bd7618ad84 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr @@ -7,5 +7,5 @@ LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself") = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr index 012ccab176cfa..58bfcbb451d70 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr @@ -7,5 +7,5 @@ LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr index 623fd585accb6..505b7d79cadb8 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs index 2b3fbd2a4d28a..e591b2a93e12b 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs @@ -40,7 +40,8 @@ fn main() { const CFN1: Wrap = Wrap(trivial); let input: Wrap = Wrap(trivial); match Wrap(input) { - Wrap(CFN1) => count += 1, + Wrap(CFN1) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -48,7 +49,8 @@ fn main() { const CFN2: Wrap = Wrap(sm_to); let input: Wrap = Wrap(sm_to); match Wrap(input) { - Wrap(CFN2) => count += 1, + Wrap(CFN2) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -56,7 +58,8 @@ fn main() { const CFN3: Wrap SM> = Wrap(to_sm); let input: Wrap SM> = Wrap(to_sm); match Wrap(input) { - Wrap(CFN3) => count += 1, + Wrap(CFN3) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -64,7 +67,8 @@ fn main() { const CFN4: Wrap = Wrap(not_sm_to); let input: Wrap = Wrap(not_sm_to); match Wrap(input) { - Wrap(CFN4) => count += 1, + Wrap(CFN4) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -72,7 +76,8 @@ fn main() { const CFN5: Wrap NotSM> = Wrap(to_not_sm); let input: Wrap NotSM> = Wrap(to_not_sm); match Wrap(input) { - Wrap(CFN5) => count += 1, + Wrap(CFN5) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -80,7 +85,8 @@ fn main() { const CFN6: Wrap = Wrap(r_sm_to); let input: Wrap = Wrap(r_sm_to); match Wrap(input) { - Wrap(CFN6) => count += 1, + Wrap(CFN6) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -88,7 +94,8 @@ fn main() { const CFN7: Wrap &SM> = Wrap(r_to_r_sm); let input: Wrap &SM> = Wrap(r_to_r_sm); match Wrap(input) { - Wrap(CFN7) => count += 1, + Wrap(CFN7) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -96,7 +103,8 @@ fn main() { const CFN8: Wrap = Wrap(r_not_sm_to); let input: Wrap = Wrap(r_not_sm_to); match Wrap(input) { - Wrap(CFN8) => count += 1, + Wrap(CFN8) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -104,7 +112,8 @@ fn main() { const CFN9: Wrap &NotSM> = Wrap(r_to_r_not_sm); let input: Wrap &NotSM> = Wrap(r_to_r_not_sm); match Wrap(input) { - Wrap(CFN9) => count += 1, + Wrap(CFN9) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -126,7 +135,8 @@ fn main() { let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm }; match input { - CFOO => count += 1, + CFOO => count += 1, //~WARN behave unpredictably + //~| previously accepted Foo { .. } => {} }; diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr new file mode 100644 index 0000000000000..080bf5885ba75 --- /dev/null +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr @@ -0,0 +1,93 @@ +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:43:14 + | +LL | Wrap(CFN1) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:52:14 + | +LL | Wrap(CFN2) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 + | +LL | Wrap(CFN3) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 + | +LL | Wrap(CFN4) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 + | +LL | Wrap(CFN5) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 + | +LL | Wrap(CFN6) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 + | +LL | Wrap(CFN7) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 + | +LL | Wrap(CFN8) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 + | +LL | Wrap(CFN9) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 + | +LL | CFOO => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: 10 warnings emitted + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr index 46600e7b215a8..729e747def310 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr @@ -7,5 +7,5 @@ LL | A => (), = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs index 567685950e9e4..b05b8c8da1f39 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs @@ -26,6 +26,7 @@ fn my_fn(_args: &[A]) { } const TEST: Fn = my_fn; +const TEST2: (Fn, u8) = (TEST, 0); struct B(Fn); @@ -33,8 +34,14 @@ fn main() { let s = B(my_fn); match s { B(TEST) => println!("matched"), - //~^ WARN pointers in patterns behave unpredictably + //~^ WARN behave unpredictably //~| WARN this was previously accepted by the compiler but is being phased out _ => panic!("didn't match") }; + match (s.0, 0) { + TEST2 => println!("matched"), + //~^ WARN behave unpredictably + //~| WARN this was previously accepted by the compiler but is being phased out + _ => panic!("didn't match") + } } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index d6afc0255ec4c..4fdfce60bb861 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -1,5 +1,5 @@ -warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. - --> $DIR/issue-63479-match-fnptr.rs:35:7 +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:36:7 | LL | B(TEST) => println!("matched"), | ^^^^ @@ -12,5 +12,14 @@ note: the lint level is defined here LL | #![warn(pointer_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 1 warning emitted +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:42:5 + | +LL | TEST2 => println!("matched"), + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: 2 warnings emitted diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr index 1c4fb914688f6..c2000df88f6d0 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr @@ -17,5 +17,5 @@ LL | f32::INFINITY => { } = note: for more information, see issue #41620 = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr index 6adebada0437d..477789f33df16 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr @@ -7,5 +7,5 @@ LL | FOO => { } = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr index f5b10f0626b32..b806046db1422 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr @@ -7,5 +7,5 @@ LL | FOO => { } = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr index 5f8c5dbe61938..52c700c326e30 100644 --- a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr +++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | f: &id, | ^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>` - found trait `Fn<(&Foo<'_>,)>` + = note: expected trait `for<'a, 'b> Fn(&'a Foo<'b>)` + found trait `Fn(&Foo<'_>)` error[E0308]: mismatched types --> $DIR/rfc1623-2.rs:28:8 @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | f: &id, | ^^^ one type is more general than the other | - = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>` - found trait `Fn<(&Foo<'_>,)>` + = note: expected trait `for<'a, 'b> Fn(&'a Foo<'b>)` + found trait `Fn(&Foo<'_>)` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `FnOnce` is not general enough diff --git a/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.stderr b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.stderr index d4410e147503a..4218ef31e2010 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.stderr +++ b/tests/ui/rfcs/rfc-1717-dllimport/missing-link-attr.stderr @@ -1,4 +1,4 @@ error: renaming of the library `foo` was specified, however this crate contains no `#[link(...)]` attributes referencing this library -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.stderr b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.stderr index a6fec9c4e2b5f..d931e23c75683 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.stderr +++ b/tests/ui/rfcs/rfc-1717-dllimport/multiple-renames.stderr @@ -1,4 +1,4 @@ error: multiple renamings were specified for library `foo` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr index bee639bf26cb5..ce145689f9014 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr +++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-modifiers.stderr @@ -4,5 +4,5 @@ error: overriding linking modifiers from command line is not supported LL | extern "C" {} | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.stderr b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.stderr index aca839d804fc9..c208e050320c1 100644 --- a/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.stderr +++ b/tests/ui/rfcs/rfc-1717-dllimport/rename-to-empty.stderr @@ -1,4 +1,4 @@ error: an empty renaming target was specified for library `foo` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.stderr index 409dede1a90ac..6c3d576cfbab4 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-1.stderr @@ -12,6 +12,6 @@ note: required by a bound in `receive` LL | fn receive(_: impl std::process::Termination) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `receive` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr index f72b3ab0234e9..f2727336bc56b 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr @@ -10,6 +10,6 @@ note: required by a bound in `Main::main::{opaque#0}` LL | fn main() -> impl std::process::Termination; | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr index 8b01941b4c623..4bb420664f7f4 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr @@ -10,6 +10,6 @@ note: required by a bound in `Main::{opaque#0}` LL | fn main() -> impl std::process::Termination; | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr index 40f736c215d5a..3fbbfd0fd0dbf 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr @@ -10,6 +10,6 @@ note: required by a bound in `Main::{opaque#0}` LL | fn main() -> impl std::process::Termination; | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.stderr index 5ee6d127e85e3..f562b97c3446a 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-impl-trait.stderr @@ -6,6 +6,6 @@ LL | fn main() -> impl Copy { } | = help: consider using `()`, or a `Result` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr index 7f6749fc9ccb5..534599b74dff0 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr @@ -8,5 +8,5 @@ LL | | Ok(()) LL | | } | |_^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.stderr index 53779d365f3f3..fdbb0e6559d1a 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-i32.stderr @@ -6,6 +6,6 @@ LL | fn main() -> i32 { | = help: consider using `()`, or a `Result` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr index bc8fd92ce5864..7ed17dff10c28 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr @@ -6,6 +6,6 @@ LL | fn main() -> char { | = help: consider using `()`, or a `Result` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr index cb329548d86d8..1b842c206ee5e 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr @@ -6,6 +6,6 @@ LL | fn main() -> ReturnType { | = help: consider using `()`, or a `Result` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index a19750cc73aa5..0a703367d969d 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -11,6 +11,6 @@ note: required by a bound in `assert_test_result` --> $SRC_DIR/test/src/lib.rs:LL:COL = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr index 04572920ee414..a9c9eb2a5cbec 100644 --- a/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr @@ -9,6 +9,6 @@ LL | LL | println!("foo={:?}", *string); | ------- immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/const.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/const.stderr index fc06de90a0031..1c8e8d5b0a7db 100644 --- a/tests/ui/rfcs/rfc-2005-default-binding-mode/const.stderr +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/const.stderr @@ -13,6 +13,6 @@ LL | FOO => {}, | `FOO` is interpreted as a constant, not a new binding | help: introduce a new binding instead: `other_foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr index 07991af6ef97c..8f720daf11ee6 100644 --- a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr @@ -12,6 +12,6 @@ help: consider borrowing the pattern binding LL | for (n, ref mut m) in &tups { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.stderr index e1e1bf7f6d971..84ba69703da1b 100644 --- a/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.stderr +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.stderr @@ -4,6 +4,6 @@ error[E0409]: variable `x` is bound inconsistently across alternatives separated LL | Some((x, 3)) | &Some((ref x, 5)) => x, | - first binding ^ bound in different ways -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0409`. diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.stderr index c672acee040b6..6000507c58974 100644 --- a/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.stderr +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/no-double-error.stderr @@ -4,6 +4,6 @@ error[E0599]: no associated item named `XXX` found for type `u32` in the current LL | u32::XXX => { } | ^^^ associated item not found in `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.stderr index 5b51dc5acc4e4..a83c58e700700 100644 --- a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.stderr +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.stderr @@ -11,6 +11,6 @@ LL ~ [first, remainder @ ..] => {}, LL ~ &[] => todo!(), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr index ad84ebe3a504c..70f5b2b84d86f 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr @@ -9,6 +9,6 @@ LL | match x { LL | drop(y); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.stderr index a61dcf8399f17..c8dad8b807aa4 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum-as-cast.stderr @@ -6,6 +6,6 @@ LL | let d = e as u8; | = note: cannot cast an enum with a non-exhaustive variant when it's defined in another crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr index 46093eb9fb35f..2535e0518078b 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr @@ -27,5 +27,5 @@ LL + #[deny(non_exhaustive_omitted_patterns)] LL | match val { | -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs index e0a6051a81fab..a6c1dc53f8b20 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs @@ -1,6 +1,7 @@ // Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly. #![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)] +#![deny(unreachable_patterns)] // aux-build:enums.rs extern crate enums; @@ -31,11 +32,21 @@ pub enum Bar { C, } +fn no_lint() { + let non_enum = NonExhaustiveEnum::Unit; + // Ok: without the attribute + match non_enum { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } +} + +#[deny(non_exhaustive_omitted_patterns)] fn main() { let enumeration = Bar::A; // Ok: this is a crate local non_exhaustive enum - #[deny(non_exhaustive_omitted_patterns)] match enumeration { Bar::A => {} Bar::B => {} @@ -44,14 +55,13 @@ fn main() { let non_enum = NonExhaustiveEnum::Unit; - // Ok: without the attribute + #[allow(non_exhaustive_omitted_patterns)] match non_enum { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match non_enum { //~^ some variants are not matched explicitly NonExhaustiveEnum::Unit => {} @@ -59,7 +69,6 @@ fn main() { _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match non_enum { //~^ some variants are not matched explicitly NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {} @@ -68,7 +77,6 @@ fn main() { let x = 5; // We ignore the guard. - #[deny(non_exhaustive_omitted_patterns)] match non_enum { NonExhaustiveEnum::Unit if x > 10 => {} NonExhaustiveEnum::Tuple(_) => {} @@ -76,14 +84,12 @@ fn main() { _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match (non_enum, true) { (NonExhaustiveEnum::Unit, true) => {} (NonExhaustiveEnum::Tuple(_), false) => {} (NonExhaustiveEnum::Struct { .. }, false) => {} _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match (non_enum, true) { //~^ some variants are not matched explicitly (NonExhaustiveEnum::Unit, true) => {} @@ -91,14 +97,12 @@ fn main() { _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match (true, non_enum) { (true, NonExhaustiveEnum::Unit) => {} (false, NonExhaustiveEnum::Tuple(_)) => {} (false, NonExhaustiveEnum::Struct { .. }) => {} _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match (true, non_enum) { //~^ some variants are not matched explicitly (true, NonExhaustiveEnum::Unit) => {} @@ -106,7 +110,6 @@ fn main() { _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match Some(non_enum) { //~^ some variants are not matched explicitly Some(NonExhaustiveEnum::Unit) => {} @@ -116,7 +119,6 @@ fn main() { // Ok: all covered and not `unreachable-patterns` #[deny(unreachable_patterns)] - #[deny(non_exhaustive_omitted_patterns)] match non_enum { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} @@ -124,7 +126,6 @@ fn main() { _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match NestedNonExhaustive::B { //~^ some variants are not matched explicitly NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {} @@ -133,54 +134,53 @@ fn main() { _ => {} } - #[warn(non_exhaustive_omitted_patterns)] match VariantNonExhaustive::Baz(1, 2) { VariantNonExhaustive::Baz(_, _) => {} VariantNonExhaustive::Bar { x, .. } => {} } //~^^ some fields are not explicitly listed - #[warn(non_exhaustive_omitted_patterns)] let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default(); //~^ some fields are not explicitly listed // Ok: this is local - #[warn(non_exhaustive_omitted_patterns)] let Foo { a, b, .. } = Foo::default(); - #[warn(non_exhaustive_omitted_patterns)] let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); //~^ some fields are not explicitly listed //~^^ some fields are not explicitly listed // Ok: this tests https://github.com/rust-lang/rust/issues/89382 - #[warn(non_exhaustive_omitted_patterns)] let MixedVisFields { a, b, .. } = MixedVisFields::default(); // Ok: this only has 1 variant - #[deny(non_exhaustive_omitted_patterns)] match NonExhaustiveSingleVariant::A(true) { NonExhaustiveSingleVariant::A(true) => {} _ => {} } // We can't catch the case below, so for consistency we don't catch this one either. - #[deny(non_exhaustive_omitted_patterns)] match NonExhaustiveSingleVariant::A(true) { _ => {} } // We can't catch this case, because this would require digging fully through all the values of // any type we encounter. We need to be able to only consider present constructors. - #[deny(non_exhaustive_omitted_patterns)] match &NonExhaustiveSingleVariant::A(true) { _ => {} } + match Some(NonExhaustiveSingleVariant::A(true)) { + Some(_) => {} + None => {} + } + match Some(&NonExhaustiveSingleVariant::A(true)) { + Some(_) => {} + None => {} + } + // Ok: we don't lint on `if let` expressions - #[deny(non_exhaustive_omitted_patterns)] if let NonExhaustiveEnum::Tuple(_) = non_enum {} - #[deny(non_exhaustive_omitted_patterns)] match UnstableEnum::Stable { //~^ some variants are not matched explicitly UnstableEnum::Stable => {} @@ -189,7 +189,6 @@ fn main() { } // Ok: the feature is on and all variants are matched - #[deny(non_exhaustive_omitted_patterns)] match UnstableEnum::Stable { UnstableEnum::Stable => {} UnstableEnum::Stable2 => {} @@ -198,52 +197,66 @@ fn main() { } // Ok: the feature is on and both variants are matched - #[deny(non_exhaustive_omitted_patterns)] match OnlyUnstableEnum::Unstable { OnlyUnstableEnum::Unstable => {} OnlyUnstableEnum::Unstable2 => {} _ => {} } - #[deny(non_exhaustive_omitted_patterns)] match OnlyUnstableEnum::Unstable { //~^ some variants are not matched explicitly OnlyUnstableEnum::Unstable => {} _ => {} } - #[warn(non_exhaustive_omitted_patterns)] let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new(); //~^ some fields are not explicitly listed // OK: both unstable fields are matched with feature on - #[warn(non_exhaustive_omitted_patterns)] let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new(); - #[warn(non_exhaustive_omitted_patterns)] let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); //~^ some fields are not explicitly listed // OK: both unstable and stable fields are matched with feature on - #[warn(non_exhaustive_omitted_patterns)] let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default(); // Ok: local bindings are allowed - #[deny(non_exhaustive_omitted_patterns)] let local = NonExhaustiveEnum::Unit; // Ok: missing patterns will be blocked by the pattern being refutable - #[deny(non_exhaustive_omitted_patterns)] let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit; //~^ refutable pattern in local binding - #[deny(non_exhaustive_omitted_patterns)] + // Check that matching on a reference results in a correct diagnostic match &non_enum { //~^ some variants are not matched explicitly + //~| pattern `&NonExhaustiveEnum::Struct { .. }` not covered NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} _ => {} } + + match (true, &non_enum) { + //~^ some variants are not matched explicitly + //~| patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered + (true, NonExhaustiveEnum::Unit) => {} + _ => {} + } + + match (&non_enum, true) { + //~^ some variants are not matched explicitly + //~| patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered + (NonExhaustiveEnum::Unit, true) => {} + _ => {} + } + + match Some(&non_enum) { + //~^ some variants are not matched explicitly + //~| pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered + Some(NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_)) => {} + _ => {} + } } #[deny(non_exhaustive_omitted_patterns)] diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr index 7db61f1241eae..1037033c4b74b 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -1,4 +1,4 @@ -warning: some fields are not explicitly listed +error: some fields are not explicitly listed --> $DIR/omitted-patterns.rs:139:9 | LL | VariantNonExhaustive::Bar { x, .. } => {} @@ -7,41 +7,31 @@ LL | VariantNonExhaustive::Bar { x, .. } => {} = help: ensure that all fields are mentioned explicitly by adding the suggested fields = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found note: the lint level is defined here - --> $DIR/omitted-patterns.rs:136:12 + --> $DIR/omitted-patterns.rs:45:8 | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: some fields are not explicitly listed - --> $DIR/omitted-patterns.rs:144:9 +error: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:143:9 | LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed | = help: ensure that all fields are mentioned explicitly by adding the suggested fields = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:143:12 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: some fields are not explicitly listed - --> $DIR/omitted-patterns.rs:152:29 +error: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:149:29 | LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed | = help: ensure that all fields are mentioned explicitly by adding the suggested fields = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:151:12 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: some fields are not explicitly listed - --> $DIR/omitted-patterns.rs:152:9 +error: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:149:9 | LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed @@ -49,117 +39,77 @@ LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = Nested = help: ensure that all fields are mentioned explicitly by adding the suggested fields = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found -warning: some fields are not explicitly listed - --> $DIR/omitted-patterns.rs:216:9 +error: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:212:9 | LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed | = help: ensure that all fields are mentioned explicitly by adding the suggested fields = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:215:12 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: some fields are not explicitly listed - --> $DIR/omitted-patterns.rs:224:9 +error: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:218:9 | LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed | = help: ensure that all fields are mentioned explicitly by adding the suggested fields = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:223:12 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:55:11 + --> $DIR/omitted-patterns.rs:65:11 | LL | match non_enum { | ^^^^^^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:54:12 - | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:63:11 + --> $DIR/omitted-patterns.rs:72:11 | LL | match non_enum { | ^^^^^^^^ pattern `NonExhaustiveEnum::Tuple(_)` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:62:12 - | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:87:11 + --> $DIR/omitted-patterns.rs:93:11 | LL | match (non_enum, true) { | ^^^^^^^^^^^^^^^^ pattern `(NonExhaustiveEnum::Struct { .. }, _)` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `(NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:86:12 - | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:102:11 + --> $DIR/omitted-patterns.rs:106:11 | LL | match (true, non_enum) { | ^^^^^^^^^^^^^^^^ pattern `(_, NonExhaustiveEnum::Struct { .. })` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `(bool, NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:101:12 - | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:110:11 + --> $DIR/omitted-patterns.rs:113:11 | LL | match Some(non_enum) { | ^^^^^^^^^^^^^^ pattern `Some(NonExhaustiveEnum::Struct { .. })` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `Option` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:109:12 - | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:128:11 + --> $DIR/omitted-patterns.rs:129:11 | LL | match NestedNonExhaustive::B { | ^^^^^^^^^^^^^^^^^^^^^^ patterns `NestedNonExhaustive::C`, `NestedNonExhaustive::A(NonExhaustiveEnum::Tuple(_))` and `NestedNonExhaustive::A(NonExhaustiveEnum::Struct { .. })` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:127:12 - | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:184:11 @@ -169,28 +119,18 @@ LL | match UnstableEnum::Stable { | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:183:12 - | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:209:11 + --> $DIR/omitted-patterns.rs:206:11 | LL | match OnlyUnstableEnum::Unstable { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `OnlyUnstableEnum::Unstable2` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:208:12 - | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0005]: refutable pattern in local binding - --> $DIR/omitted-patterns.rs:237:9 + --> $DIR/omitted-patterns.rs:228:9 | LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit; | ^^^^^^^^^^^^^^^ pattern `_` not covered @@ -204,19 +144,41 @@ LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit | ++++++++++++++++ error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:241:11 + --> $DIR/omitted-patterns.rs:232:11 | LL | match &non_enum { | ^^^^^^^^^ pattern `&NonExhaustiveEnum::Struct { .. }` not covered | = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `&NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found -note: the lint level is defined here - --> $DIR/omitted-patterns.rs:240:12 + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:240:11 + | +LL | match (true, &non_enum) { + | ^^^^^^^^^^^^^^^^^ patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered | -LL | #[deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `(bool, &NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:247:11 + | +LL | match (&non_enum, true) { + | ^^^^^^^^^^^^^^^^^ patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `(&NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:254:11 + | +LL | match Some(&non_enum) { + | ^^^^^^^^^^^^^^^ pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `Option<&NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found -error: aborting due to 10 previous errors; 6 warnings emitted +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr index 27939176f75ed..2658b20a7269d 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr @@ -26,5 +26,5 @@ note: the lint level is defined here LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr index f39e6ee298544..3034a67dc43b3 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr index e7ddf8df4ab53..e22d812c8b038 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-odd-syntax.stderr @@ -4,5 +4,5 @@ error: malformed `track_caller` attribute input LL | #[track_caller(1)] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.stderr index 6d6562dae3b67..4626544a5cd2b 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-main.stderr @@ -6,5 +6,5 @@ LL | #[track_caller] LL | fn main() { | --------- `main` function is not allowed to be `#[track_caller]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr index b6ef6215275e8..2738444f21f64 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr @@ -6,5 +6,5 @@ LL | #[track_caller] LL | fn start(_argc: isize, _argv: *const *const u8) -> isize { | -------------------------------------------------------- `#[start]` function is not allowed to be `#[track_caller]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr index b36597bded941..f976b7f5210b8 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr @@ -6,6 +6,6 @@ LL | #[track_caller] LL | struct S; | --------- not a function definition -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0739`. diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr index 76300cce55cd4..e2a92cf72d565 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'a, T> { | = note: T: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr index 041f7ebc0aa1d..b0f1d7b33e405 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/dont-infer-static.stderr @@ -17,6 +17,6 @@ help: consider adding an explicit lifetime bound LL | struct Foo { | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr index 595a5c28088d6..30d1b3e77b1ca 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'a, A> | = note: A: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr index 3059f95aefbd1..afc044d88482a 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr @@ -6,5 +6,5 @@ LL | enum Foo<'a, U> { | = note: U: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr index 589e95899132d..1c39c984a2a68 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'a, A, B> where A: Trait<'a, B> | = note: B: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr index 9912e36b29c1a..4ec3087acffec 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'b, U> { | = note: U: 'b -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr index 16b64bdc29dd3..bbb48ef1f2610 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr @@ -6,5 +6,5 @@ LL | union Foo<'b, U: Copy> { | = note: U: 'b -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr index 4350e6e8beec2..b584d17ae8534 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr @@ -6,5 +6,5 @@ LL | enum Foo<'a, T> { | = note: T: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr index c08add7ededec..59df869c47a6b 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr @@ -8,5 +8,5 @@ LL | struct Foo<'a, 'b, T> { = note: T: 'a = note: T: 'b -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr index 7695552344370..7e5af7fe6ed54 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'a, T> { | = note: T: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr index a785c63ce3d99..bb0eea027d5a9 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr @@ -6,5 +6,5 @@ LL | union Foo<'a, T: Copy> { | = note: T: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr index d9342013f554f..47f3458e0867e 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'a, T: Iterator> { | = note: ::Item: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr index 5081143578177..329d5ff06abc4 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'a, T> { | = note: T: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr index 5dff4c8fffcaf..591585c88f5dd 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr @@ -15,6 +15,6 @@ note: but the referenced data is only valid for the lifetime `'b` as defined her LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr index 975776cddffb4..0404b52d9efe6 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr @@ -15,6 +15,6 @@ note: but the referenced data is only valid for the lifetime `'b` as defined her LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr index be05ecec0c9b0..62415e250eca9 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr @@ -15,6 +15,6 @@ note: but the referenced data is only valid for the lifetime `'b` as defined her LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr index 4ba1778d6443f..464d7968b740d 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr @@ -15,6 +15,6 @@ note: but the referenced data is only valid for the lifetime `'b` as defined her LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr index 9c836b190cff9..8f8ee92054718 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'a, 'b, A> | = note: A: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr b/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr index 2b4625f77a5e3..7fef81c261972 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr @@ -6,5 +6,5 @@ LL | struct Foo<'a, 'b, T> { | = note: T: 'a -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr b/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr index c39a70f66a97a..771a09abedc6e 100644 --- a/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr +++ b/tests/ui/rfcs/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr @@ -4,6 +4,6 @@ error[E0532]: expected unit struct, unit variant or constant, found module `crat LL | let crate = 0; | ^^^^^ not a unit struct, unit variant or constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr index 81891572179b0..1047dbe1063e8 100644 --- a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr +++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `xcrate` LL | use xcrate::S; | ^^^^^^ use of undeclared crate or module `xcrate` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.stderr index 7df4f06d1c7e5..e3875fd843b62 100644 --- a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.stderr +++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-2.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: could not find `xcrate` in the list of imported LL | let s = ::xcrate::S; | ^^^^^^ could not find `xcrate` in the list of imported crates -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.stderr index bd6778cf3d63d..c321f3ede2d7f 100644 --- a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.stderr +++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-3.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `ycrate` LL | use ycrate; | ^^^^^^ no external crate `ycrate` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr index 122e8fd350cb2..7f989c15f1c05 100644 --- a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr +++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr @@ -11,6 +11,6 @@ LL | use core::alloc; LL | use std::alloc; | ~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr index b8e1bb324b1f1..741ae7c92d78b 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr @@ -10,6 +10,6 @@ LL | LL | let _z: &String = z; | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr index 009d153387e32..98285f5c3e1c8 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr @@ -6,6 +6,6 @@ LL | Some(mut y) if let Some(ref mut z) = y => { | = note: variables bound in patterns are immutable until the end of the pattern guard -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr index 07e7c6a2c07e7..31df8a922ace2 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr @@ -6,6 +6,6 @@ LL | Some(ref mut y) if let Some(ref mut z) = *y => { | = note: variables bound in patterns are immutable until the end of the pattern guard -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr index 00c1c303d2b02..b8065b9f55607 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr @@ -10,5 +10,5 @@ LL | () if m!(Some(5)) => {} = note: only supported directly in conditions of `if` and `while` expressions = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr index 9dc339abc06ba..c2b9899e20db3 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr @@ -10,6 +10,6 @@ LL | let _ = dbg!(a); | = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr index ce165e6463292..7ec018a95cc72 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr @@ -13,6 +13,6 @@ LL + #[derive(Debug)] LL | struct NotDebug; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr index 18917fd2556cf..06c6c90533893 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr @@ -9,6 +9,6 @@ LL | fn foo() {} = note: see issue #69098 for more information = help: add `#![feature(target_feature_11)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr index e08ffe42d6aab..7bbd4e158982f 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr @@ -18,6 +18,6 @@ help: consider casting to a fn pointer LL | let foo: fn() = foo as fn(); | ~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr index e08ffe42d6aab..7bbd4e158982f 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr @@ -18,6 +18,6 @@ help: consider casting to a fn pointer LL | let foo: fn() = foo as fn(); | ~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr index cfafbd52286a7..57ad1cc8d0802 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.stderr @@ -4,5 +4,5 @@ error: `main` function is not allowed to have `#[target_feature]` LL | fn main() {} | ^^^^^^^^^ `main` function is not allowed to have `#[target_feature]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr index b49f8afd960da..d0a67c4f6a8d0 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr @@ -7,5 +7,5 @@ LL | LL | fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } | -------------------------------------------------------- `#[start]` function is not allowed to have `#[target_feature]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr index 0ef7b8b09f11f..cabc475fa61cf 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr @@ -1,83 +1,115 @@ error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:23:5 + --> $DIR/safe-calls.rs:28:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:26:5 + --> $DIR/safe-calls.rs:31:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:29:5 + --> $DIR/safe-calls.rs:34:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:36:5 + --> $DIR/safe-calls.rs:41:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:39:5 + --> $DIR/safe-calls.rs:44:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:46:5 + --> $DIR/safe-calls.rs:51:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:49:5 + --> $DIR/safe-calls.rs:54:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:52:5 + --> $DIR/safe-calls.rs:57:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:60:5 + --> $DIR/safe-calls.rs:65:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:65:18 + --> $DIR/safe-calls.rs:70:15 | -LL | const name: () = sse2(); - | ^^^^^^ call to function with `#[target_feature]` +LL | const _: () = sse2(); + | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` -error: aborting due to 10 previous errors +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:74:15 + | +LL | const _: () = sse2_and_fxsr(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr + = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` + +error: call to function with `#[target_feature]` is unsafe and requires unsafe block (error E0133) + --> $DIR/safe-calls.rs:82:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/safe-calls.rs:81:1 + | +LL | unsafe fn needs_unsafe_block() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/safe-calls.rs:78:8 + | +LL | #[deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs index cebc6f9478404..f17dab269bc4b 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs @@ -7,6 +7,11 @@ #[target_feature(enable = "sse2")] const fn sse2() {} +#[target_feature(enable = "sse2")] +#[target_feature(enable = "fxsr")] +const fn sse2_and_fxsr() {} + + #[target_feature(enable = "avx")] #[target_feature(enable = "bmi2")] fn avx_bmi2() {} @@ -62,8 +67,21 @@ fn qux() { //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe } -const name: () = sse2(); +const _: () = sse2(); //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe +const _: () = sse2_and_fxsr(); +//[mir]~^ ERROR call to function with `#[target_feature]` is unsafe +//[thir]~^^ ERROR call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe + +#[deny(unsafe_op_in_unsafe_fn)] +#[target_feature(enable = "avx")] +#[target_feature(enable = "bmi2")] +unsafe fn needs_unsafe_block() { + sse2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe +} + fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr index c75ac6e8b9ae0..13b58fde862d5 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr @@ -1,83 +1,115 @@ error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:23:5 + --> $DIR/safe-calls.rs:28:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:26:5 + --> $DIR/safe-calls.rs:31:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:29:5 + --> $DIR/safe-calls.rs:34:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:36:5 + --> $DIR/safe-calls.rs:41:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:39:5 + --> $DIR/safe-calls.rs:44:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:46:5 + --> $DIR/safe-calls.rs:51:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:49:5 + --> $DIR/safe-calls.rs:54:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:52:5 + --> $DIR/safe-calls.rs:57:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:60:5 + --> $DIR/safe-calls.rs:65:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:65:18 + --> $DIR/safe-calls.rs:70:15 | -LL | const name: () = sse2(); - | ^^^^^^ call to function with `#[target_feature]` +LL | const _: () = sse2(); + | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` -error: aborting due to 10 previous errors +error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:74:15 + | +LL | const _: () = sse2_and_fxsr(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr + = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` + +error: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) + --> $DIR/safe-calls.rs:82:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/safe-calls.rs:81:1 + | +LL | unsafe fn needs_unsafe_block() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/safe-calls.rs:78:8 + | +LL | #[deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr index a3e559054f9bc..6af1d4533b7c2 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr @@ -20,6 +20,6 @@ note: required by a bound in `stuff` LL | fn stuff(_: T) {} | ^^^ required by this bound in `stuff` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.stderr index 1597e5be45f8c..b2c1406d09397 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.stderr +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/unstable-feature.stderr @@ -7,6 +7,6 @@ LL | #[do_not_recommend] = note: see issue #51992 for more information = help: add `#![feature(do_not_recommend)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr index 5aade17cba52d..cb663401e1e6b 100644 --- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr +++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr @@ -4,5 +4,5 @@ error: cannot load a crate with a non-ascii name `ьаг` LL | extern crate ьаг; | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr index 3eaccde3b745c..606f808f09369 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr @@ -6,5 +6,5 @@ LL | !let y = 42; | = note: only supported directly in conditions of `if` and `while` expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr index 247fad2e99295..f3726166eba71 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr @@ -29,6 +29,10 @@ LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some( | ^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions +help: you might have meant to compare for equality + | +LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] == 1 { + | + error: expected expression, found `let` statement --> $DIR/invalid-let-in-a-valid-let-context.rs:24:23 @@ -53,6 +57,10 @@ LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 { | ^^^^^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions +help: you might have meant to compare for equality + | +LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] == 1 { + | + error: expected expression, found `let` statement --> $DIR/invalid-let-in-a-valid-let-context.rs:42:21 diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr index 831731ba47419..61aae850a9438 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr @@ -7,6 +7,6 @@ LL | fn y(&self, y: f64) -> Self { P{y, .. self.clone() } } = note: expected struct `P` found reference `&P` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr index 1c26eb8803d7f..8ae7691a48480 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr @@ -13,6 +13,6 @@ LL | let m2: Machine<'static, State1> = Machine { LL | } | - `s` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.stderr index 593821bf96128..0c269a23f49c3 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.stderr +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -18,5 +18,5 @@ help: if this is a type, explicitly ignore the parameter name LL | trait Trait2015 { fn foo(#[allow(C)] _: i32); } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr index cc532ccc4510f..0c5a06e68b89f 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr @@ -2,5 +2,5 @@ error: Dlltool could not create import library with $DLLTOOL -d $DEF_FILE -D foo $DLLTOOL: Syntax error in def file $DEF_FILE:1 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr index fb70b987fc7d9..d2cf7a0ba1f4f 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr @@ -4,5 +4,5 @@ error: import name type must be of the form `import_name_type = "string"` LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr index 9533061892fee..8e65baf65dff1 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr @@ -4,5 +4,5 @@ error: multiple `import_name_type` arguments in a single `#[link]` attribute LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr index 2bce9758e997c..4b8b90eb6e27a 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr @@ -4,5 +4,5 @@ error: unknown import name type `unknown`, expected one of: decorated, noprefix, LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr index b56449299b71e..757f1f7994e49 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr @@ -4,5 +4,5 @@ error: import name type is only supported on x86 LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr index 3ae901e0dbc94..9dbeee49f5345 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr @@ -1,4 +1,4 @@ error: Error calling dlltool 'does_not_exit.exe': program not found -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr index dfd24566953fb..7866af594449f 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr @@ -4,5 +4,5 @@ error: multiple declarations of external function `f` from library `foo.dll` hav LL | fn f(x: i32); | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr index b635a09afba4e..ede20cb8c3f76 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr @@ -4,6 +4,6 @@ error[E0455]: link kind `raw-dylib` is only supported on Windows targets LL | #[link(name = "foo", kind = "raw-dylib")] | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0455`. diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr index f69275a01253f..d7c7344b596db 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr @@ -4,5 +4,5 @@ error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture LL | fn f(x: i32); | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr index 6d436018bf4b3..1b88839984f4d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr @@ -1,3 +1,11 @@ +error: `~const` is not allowed here + --> $DIR/assoc-type-const-bound-usage.rs:7:17 + | +LL | type Assoc: ~const Foo; + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + error[E0308]: mismatched types --> $DIR/assoc-type-const-bound-usage.rs:12:5 | @@ -7,6 +15,6 @@ LL | ::Assoc::foo(); = note: expected constant `host` found constant `true` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index 0cffae1da8d97..290ef6e2f5fa0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,8 +1,16 @@ +error: `~const` is not allowed here + --> $DIR/assoc-type.rs:17:15 + | +LL | type Bar: ~const std::ops::Add; + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + error: ~const can only be applied to `#[const_trait]` traits --> $DIR/assoc-type.rs:17:22 | LL | type Bar: ~const std::ops::Add; | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 452bf757df769..8d809907a5357 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -6,6 +6,6 @@ LL | a.plus(b) | = help: the trait `Plus` is implemented for `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr index 02d53cc78ee56..4007fd455f88c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr @@ -4,5 +4,5 @@ error: ~const can only be applied to `#[const_trait]` traits LL | impl const MyPartialEq for T { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs index eada4ceafe92e..b9331caaf8efb 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -1,7 +1,4 @@ -// check-pass -// known-bug: #110395 - -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] struct S; @@ -24,6 +21,7 @@ const fn equals_self(t: &T) -> bool { // it not using the impl. pub const EQ: bool = equals_self(&S); -// FIXME(effects) ~^ ERROR +//~^ ERROR +// FIXME(effects) the diagnostics here isn't ideal, we shouldn't get `` fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr new file mode 100644 index 0000000000000..4fe296d4d3fa9 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `S: ~const Foo` is not satisfied + --> $DIR/call-generic-method-nonconst.rs:23:34 + | +LL | pub const EQ: bool = equals_self(&S); + | ----------- ^^ the trait `Foo` is not implemented for `S` + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is implemented for `S` +note: required by a bound in `equals_self` + --> $DIR/call-generic-method-nonconst.rs:16:25 + | +LL | const fn equals_self(t: &T) -> bool { + | ^^^^^^^^^^ required by this bound in `equals_self` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr index bea1846e79be7..1f7cf689e9581 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr @@ -4,5 +4,5 @@ error: ~const can only be applied to `#[const_trait]` traits LL | const fn equals_self(t: &T) -> bool { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs similarity index 92% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs rename to tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs index 1e22ddcea8d3e..0025449c4921f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait MyTrait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr similarity index 88% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr rename to tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr index 9210f6427064f..db48c170d1c02 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr @@ -2,7 +2,7 @@ error: `~const` is not allowed here --> $DIR/const-bound-on-not-const-associated-fn.rs:9:40 | LL | fn do_something_else() where Self: ~const MyTrait; - | ^^^^^^^^^^^^^^ + | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds --> $DIR/const-bound-on-not-const-associated-fn.rs:9:8 @@ -14,7 +14,7 @@ error: `~const` is not allowed here --> $DIR/const-bound-on-not-const-associated-fn.rs:20:32 | LL | pub fn foo(&self) where T: ~const MyTrait { - | ^^^^^^^^^^^^^^ + | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds --> $DIR/const-bound-on-not-const-associated-fn.rs:20:12 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr index c8783de4c3eed..ae035b26ec582 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr @@ -6,6 +6,6 @@ LL | fn foo() { non_const() } | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr index f25390a9070e1..fc9b5557a6496 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr @@ -4,5 +4,5 @@ error: ~const can only be applied to `#[const_trait]` traits LL | const fn test() -> impl ~const Fn() { | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index 4c45b0e56c601..73ee0f2151a73 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -4,5 +4,5 @@ error: ~const can only be applied to `#[const_trait]` traits LL | const fn need_const_closure i32>(x: T) -> i32 { | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr index a8ef244ea3092..33ae7131b928e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -4,5 +4,5 @@ error: ~const can only be applied to `#[const_trait]` traits LL | const fn need_const_closure i32>(x: T) -> i32 { | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr index 7b558e3f773c4..111a6a3fc7f81 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -6,6 +6,6 @@ LL | NonConstImpl.a(); | = help: the trait `ConstDefaultFn` is implemented for `NonConstImpl` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr index f5147dc74b873..16ed615907b13 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-bound.stderr @@ -4,6 +4,6 @@ error[E0493]: destructor of `E` cannot be evaluated at compile-time LL | Err(_e) => None, | ^^ the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr index 100d1df87d697..6f75924f0aa64 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stderr @@ -6,6 +6,6 @@ LL | const fn check(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr index dfa5ea8c4afa9..8997e7ade6c17 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -4,6 +4,6 @@ error[E0493]: destructor of `T` cannot be evaluated at compile-time LL | const fn check(_: T) {} | ^ the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr index 8af38b792e668..09ebf55c57c7a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -6,6 +6,6 @@ LL | const fn check(_: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr index 23e368870258e..daaba08d7dde9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -1,19 +1,10 @@ -error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:19:32 +error: `~const` is not allowed here + --> $DIR/const-drop.rs:67:38 | -LL | const fn a(_: T) {} - | ^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions - -error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:24:13 +LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); + | ^^^^^^ | -LL | let _ = S(&mut c); - | ^^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions + = note: this item cannot have `~const` trait bounds -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs index 0a9cf638a2d25..9da84cdb0525b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs @@ -63,6 +63,7 @@ mod t { fn foo() {} } + // FIXME(effects): This should be a `const` bound instead of a `~const` one. pub struct ConstDropWithBound(pub core::marker::PhantomData); impl const Drop for ConstDropWithBound { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index 23e368870258e..daaba08d7dde9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -1,19 +1,10 @@ -error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:19:32 +error: `~const` is not allowed here + --> $DIR/const-drop.rs:67:38 | -LL | const fn a(_: T) {} - | ^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions - -error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:24:13 +LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); + | ^^^^^^ | -LL | let _ = S(&mut c); - | ^^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions + = note: this item cannot have `~const` trait bounds -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.stderr index 603f6b7d2835e..efa72463c5e9a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-norecover.stderr @@ -4,5 +4,5 @@ error: expected identifier, found keyword `impl` LL | const impl Foo { | ^^^^ expected identifier, found keyword -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr index c45af1a9f8ac2..f0b6e2b1c2552 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr @@ -10,5 +10,5 @@ LL | impl const A for () {} = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr index cc9bdd2715f70..2dd96f548fed3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr @@ -6,6 +6,6 @@ LL | #[derive_const(Default)] | = help: add `#![feature(derive_const)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr index 1c69ad4317142..dfe8fa79e2649 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr @@ -8,5 +8,5 @@ LL | #[derive_const(Default)] = note: adding a non-const method body in the future would be a breaking change = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr index 37d123e4ccc4d..3a8c4833414b8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr @@ -6,5 +6,5 @@ LL | #[derive_const(PartialEq)] | = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr index 428286e0b12ad..ed647aee8c370 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr @@ -6,6 +6,6 @@ LL | NonConst.func(); | = help: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr index 22f13a7416e92..ab039397edc23 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -7,6 +7,6 @@ LL | Const.func(); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr index a6881b8fed51e..d8e2c0ffb813a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -6,6 +6,6 @@ LL | ().a() | = help: the trait `Tr` is implemented for `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs new file mode 100644 index 0000000000000..6598d1da0f866 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs @@ -0,0 +1,15 @@ +#![feature(const_closures, const_trait_impl, effects)] +#![allow(incomplete_features)] + +trait Foo { + fn foo(&self); +} + +impl Foo for () { + fn foo(&self) {} +} + +fn main() { + (const || { (()).foo() })(); + //~^ ERROR: cannot call non-const fn +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr new file mode 100644 index 0000000000000..413e217020d4a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions + --> $DIR/const_closure-const_trait_impl-ice-113381.rs:13:22 + | +LL | (const || { (()).foo() })(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs new file mode 100644 index 0000000000000..e216f68791334 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/effect-param-infer.rs @@ -0,0 +1,15 @@ +// Ensure that we don't get a mismatch error when inserting the host param +// at the end of generic args when the generics have defaulted params. +// +// check-pass + +#![feature(const_trait_impl, effects)] + +#[const_trait] +pub trait Foo { + /* stuff */ +} + +impl const Foo for () {} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs index e7ba0505d9b71..17f203e1565ec 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/helloworld.rs @@ -3,15 +3,16 @@ // gate-test-effects // ^ effects doesn't have a gate so we will trick tidy into thinking this is a gate test -#![feature(const_trait_impl, effects, rustc_attrs)] +#![feature(const_trait_impl, effects, core_intrinsics, const_eval_select)] // ensure we are passing in the correct host effect in always const contexts. -pub const fn hmm() -> usize { - if host { - 1 - } else { - 0 +pub const fn hmm() -> usize { + // FIXME(const_trait_impl): maybe we should have a way to refer to the (hidden) effect param + fn one() -> usize { 1 } + const fn zero() -> usize { 0 } + unsafe { + std::intrinsics::const_eval_select((), zero, one) } } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs new file mode 100644 index 0000000000000..1954d2942e0bb --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs @@ -0,0 +1,18 @@ +// check-pass + +// effects ice https://github.com/rust-lang/rust/issues/113375 index out of bounds + +#![allow(incomplete_features, unused)] +#![feature(effects, adt_const_params)] + +struct Bar(T); + +impl Bar { + const fn value() -> usize { + 42 + } +} + +struct Foo::value()]>; + +pub fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index c38b4b3f1a2ee..2a2e8cec3f084 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -1,3 +1,5 @@ +// check-pass + #![crate_type = "lib"] #![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs)] #![feature(fundamental)] @@ -6,8 +8,6 @@ #![no_std] #![no_core] -// known-bug: #110395 - #[lang = "sized"] trait Sized {} #[lang = "copy"] @@ -21,8 +21,7 @@ trait Add { fn add(self, rhs: Rhs) -> Self::Output; } -// FIXME we shouldn't need to have to specify `Rhs`. -impl const Add for i32 { +impl const Add for i32 { type Output = i32; fn add(self, rhs: i32) -> i32 { loop {} @@ -344,8 +343,16 @@ trait PartialEq { } } -// FIXME(effects): again, this should not error without Rhs specified -impl PartialEq for str { +impl const PartialEq<&B> for &A +where + A: ~const PartialEq, +{ + fn eq(&self, other: &&B) -> bool { + PartialEq::eq(*self, *other) + } +} + +impl PartialEq for str { fn eq(&self, other: &str) -> bool { loop {} } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr deleted file mode 100644 index 0242937421890..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error[E0369]: cannot add `i32` to `i32` - --> $DIR/minicore.rs:33:20 - | -LL | let x = 42_i32 + 43_i32; - | ------ ^ ------ i32 - | | - | i32 - -error[E0369]: cannot add `i32` to `i32` - --> $DIR/minicore.rs:37:20 - | -LL | let x = 42_i32 + 43_i32; - | ------ ^ ------ i32 - | | - | i32 - -error[E0600]: cannot apply unary operator `!` to type `bool` - --> $DIR/minicore.rs:343:9 - | -LL | !self.eq(other) - | ^^^^^^^^^^^^^^^ cannot apply unary operator `!` - -error[E0600]: cannot apply unary operator `!` to type `bool` - --> $DIR/minicore.rs:365:9 - | -LL | !self - | ^^^^^ cannot apply unary operator `!` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0369, E0600. -For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr index 4c630d33c5516..663cdd1fe57bb 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr index 6a177592b6453..1e8a70ffd2914 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/generic-bound.stderr @@ -11,6 +11,6 @@ LL | impl const std::ops::Add for S { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr index 6d2be1daa3727..90f30ea635f1e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/hir-const-check.stderr @@ -7,6 +7,6 @@ LL | Some(())?; = note: see issue #74935 for more information = help: add `#![feature(const_try)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr index 0a91719e1f15b..4695728f8caac 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr @@ -4,5 +4,5 @@ error: expected a trait, found type LL | impl ~const T for S {} | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr index 6c6ca9f5db820..36c8163f1c567 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr @@ -7,6 +7,6 @@ LL | fn req(&self); LL | impl const Tr for u16 { | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr index e8ae7e4e36cef..c331236a4601c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr @@ -2,17 +2,20 @@ error[E0433]: failed to resolve: maybe a missing crate `core`? --> $DIR/issue-102156.rs:4:5 | LL | use core::convert::{From, TryFrom}; - | ^^^^ maybe a missing crate `core`? - | - = help: consider adding `extern crate core` to use the `core` crate + | ^^^^ + | | + | maybe a missing crate `core`? + | help: try using `std` instead of `core`: `std` error[E0433]: failed to resolve: maybe a missing crate `core`? --> $DIR/issue-102156.rs:4:5 | LL | use core::convert::{From, TryFrom}; - | ^^^^ maybe a missing crate `core`? + | ^^^^ + | | + | maybe a missing crate `core`? + | help: try using `std` instead of `core`: `std` | - = help: consider adding `extern crate core` to use the `core` crate = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr index f0c61cf9dd982..077f6c7b2348a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102985.stderr @@ -6,6 +6,6 @@ LL | n => n(), | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr index 082c0333fbfcd..85996c212118f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-79450.stderr @@ -7,6 +7,6 @@ LL | println!("lul"); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr index d8cb10c65174f..157b54214fa73 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-88155.stderr @@ -6,6 +6,6 @@ LL | T::assoc() | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs deleted file mode 100644 index 21ddf4ab4e5f4..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(const_trait_impl)] - -#[const_trait] -trait Bar {} - -fn foo() where T: ~const Bar {} -//~^ ERROR `~const` is not allowed - -fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr deleted file mode 100644 index b2a9365378b33..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: `~const` is not allowed here - --> $DIR/issue-90052.rs:6:22 - | -LL | fn foo() where T: ~const Bar {} - | ^^^^^^^^^^ - | -note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/issue-90052.rs:6:4 - | -LL | fn foo() where T: ~const Bar {} - | ^^^ - -error: aborting due to previous error - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr index b27f94f99ed74..2edaca606235b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-92111.stderr @@ -6,6 +6,6 @@ LL | const fn a(t: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr index 4fe8a372e0703..89e59e5db6ed3 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr @@ -7,6 +7,6 @@ LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr index c36142dac9283..5431116a1a701 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr @@ -8,6 +8,6 @@ LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr index 979d7febbcaf8..97ad83130d444 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr @@ -6,6 +6,6 @@ LL | (const || { (()).foo() })(); | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr index cfdda4713a793..b2e09d82a905e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr @@ -4,5 +4,5 @@ error: ~const can only be applied to `#[const_trait]` traits LL | impl const Convert for A where B: ~const From { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs index 3db59631ef8da..234b0dd006380 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs @@ -18,11 +18,7 @@ trait Bar { fn bar(); } -// bgr360: I was only able to exercise the code path that raises the -// "missing ~const qualifier" error by making this base impl non-const, even -// though that doesn't really make sense to do. As seen below, if the base impl -// is made const, rustc fails earlier with an overlapping impl failure. -impl Bar for T +impl const Bar for T where T: ~const Foo, { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr index 24766804708a3..e356621ba47ed 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr @@ -4,5 +4,5 @@ error: cannot specialize on const impl with non-const impl LL | impl Value for FortyTwo { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr index 4734cee7f9a18..68eac990aaab0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr @@ -7,6 +7,6 @@ LL | impl Value for T { LL | impl const Value for FortyTwo { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr index 92bc9815e963a..0b35feddc5533 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -6,6 +6,6 @@ LL | ::a(); | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr index 08258fd1a572c..21e21c2cb71aa 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness.stderr @@ -4,5 +4,5 @@ error: cannot specialize on const impl with non-const impl LL | impl A for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.stderr index d7aa0d95cfc77..1346c4c4ae292 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api-user-crate.stderr @@ -7,6 +7,6 @@ LL | Unstable::func(); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr index 78aab9469e822..bf53b995bb673 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr @@ -4,6 +4,6 @@ error[E0635]: unknown feature `const_default_impls` LL | #![cfg_attr(gated, feature(const_trait_impl, const_default_impls))] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0635`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr index 6a3396401d2b9..6d624def27693 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr @@ -7,6 +7,6 @@ LL | Default::default() = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index b60399c57dca9..12bcdb034bc23 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -1,3 +1,15 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-2.rs:11:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-2.rs:11:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: ~const can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-2.rs:11:19 | @@ -12,5 +24,5 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr index 5d34156a51962..e465ebaffa84e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -1,11 +1,14 @@ -error[E0015]: cannot call non-const fn `::a` in constant functions - --> $DIR/super-traits-fail-2.rs:16:7 +error: `~const` is not allowed here + --> $DIR/super-traits-fail-2.rs:11:12 | -LL | x.a(); - | ^^^ +LL | trait Bar: ~const Foo {} + | ^^^^^^ | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-2.rs:11:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr index 5d34156a51962..1faa5b4dd2c40 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr @@ -6,6 +6,6 @@ LL | x.a(); | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index eb12a236d8c30..e10c51ef45aba 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -1,3 +1,15 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-3.rs:13:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-3.rs:13:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: ~const can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:13:19 | @@ -13,10 +25,10 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:17:24 + --> $DIR/super-traits-fail-3.rs:18:24 | LL | const fn foo(x: &T) { | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs index 16c592830d783..5994057b2db2e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -13,6 +13,7 @@ trait Foo { trait Bar: ~const Foo {} //[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` //[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` +//[yn,nn]~^^^ ERROR: `~const` is not allowed here const fn foo(x: &T) { //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index 58225b945912f..34f6515b572ec 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -1,8 +1,20 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-3.rs:13:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-3.rs:13:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:17:24 + --> $DIR/super-traits-fail-3.rs:18:24 | LL | const fn foo(x: &T) { | ^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr index 6bc643e68710e..5cccc025161be 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr @@ -1,11 +1,11 @@ error[E0015]: cannot call non-const fn `::a` in constant functions - --> $DIR/super-traits-fail-3.rs:19:7 + --> $DIR/super-traits-fail-3.rs:20:7 | LL | x.a(); | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr index be7a83dc18411..b479793814cb9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr @@ -2,7 +2,7 @@ error: `~const` is not allowed here --> $DIR/tilde-const-and-const-params.rs:9:15 | LL | fn add(self) -> Foo<{ A::add(N) }> { - | ^^^^^^^^^^^^ + | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds --> $DIR/tilde-const-and-const-params.rs:9:8 @@ -14,7 +14,7 @@ error: `~const` is not allowed here --> $DIR/tilde-const-and-const-params.rs:27:11 | LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { - | ^^^^^^^^^^^^ + | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds --> $DIR/tilde-const-and-const-params.rs:27:4 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs index 95f7aaba0fc38..bbe1194f7a315 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -1,7 +1,55 @@ #![feature(const_trait_impl)] -#![feature(associated_type_bounds)] -struct TildeQuestion(std::marker::PhantomData); -//~^ ERROR `~const` and `?` are mutually exclusive +#[const_trait] +trait Trait {} + +// Regression test for issue #90052. +fn non_const_function() {} //~ ERROR `~const` is not allowed + +struct Struct { field: T } //~ ERROR `~const` is not allowed here +struct TupleStruct(T); //~ ERROR `~const` is not allowed here +struct UnitStruct; //~ ERROR `~const` is not allowed here + +enum Enum { Variant(T) } //~ ERROR `~const` is not allowed here + +union Union { field: T } //~ ERROR `~const` is not allowed here + +type Type = T; //~ ERROR `~const` is not allowed here + +const CONSTANT: () = (); //~ ERROR `~const` is not allowed here +//~^ ERROR generic const items are experimental + +trait NonConstTrait { + type Type: ~const Trait; + //~^ ERROR `~const` is not allowed + //~| ERROR `~const` is not allowed + fn non_const_function(); //~ ERROR `~const` is not allowed + const CONSTANT: (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +impl NonConstTrait for () { + type Type = (); //~ ERROR `~const` is not allowed + fn non_const_function() {} //~ ERROR `~const` is not allowed + const CONSTANT: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +struct Implementor; + +impl Implementor { + type Type = (); //~ ERROR `~const` is not allowed + //~^ ERROR inherent associated types are unstable + fn non_const_function() {} //~ ERROR `~const` is not allowed + const CONSTANT: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +// non-const traits +trait Child0: ~const Trait {} //~ ERROR `~const` is not allowed +trait Child1 where Self: ~const Trait {} //~ ERROR `~const` is not allowed + +// non-const impl +impl Trait for T {} //~ ERROR `~const` is not allowed fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index d20f146df3f1a..c6e18924fd81c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -1,8 +1,244 @@ -error: `~const` and `?` are mutually exclusive - --> $DIR/tilde-const-invalid-places.rs:4:25 +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:7:26 | -LL | struct TildeQuestion(std::marker::PhantomData); - | ^^^^^^^^^^^^^ +LL | fn non_const_function() {} + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:7:4 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:9:18 + | +LL | struct Struct { field: T } + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:10:23 + | +LL | struct TupleStruct(T); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:11:22 + | +LL | struct UnitStruct; + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:13:14 + | +LL | enum Enum { Variant(T) } + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:15:16 + | +LL | union Union { field: T } + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:17:14 + | +LL | type Type = T; + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:19:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:23:18 + | +LL | type Type: ~const Trait; + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:23:33 + | +LL | type Type: ~const Trait; + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:26:30 + | +LL | fn non_const_function(); + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:26:8 + | +LL | fn non_const_function(); + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:27:23 + | +LL | const CONSTANT: (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:32:18 + | +LL | type Type = (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:33:30 + | +LL | fn non_const_function() {} + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:33:8 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:34:23 + | +LL | const CONSTANT: () = (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:41:18 + | +LL | type Type = (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:43:30 + | +LL | fn non_const_function() {} + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:43:8 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:44:23 + | +LL | const CONSTANT: () = (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:49:15 + | +LL | trait Child0: ~const Trait {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:49:1 + | +LL | trait Child0: ~const Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:50:26 + | +LL | trait Child1 where Self: ~const Trait {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:50:1 + | +LL | trait Child1 where Self: ~const Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:53:9 + | +LL | impl Trait for T {} + | ^^^^^^ + | +note: this impl is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:53:1 + | +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:19:15 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:27:19 + | +LL | const CONSTANT: (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:34:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:44:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: inherent associated types are unstable + --> $DIR/tilde-const-invalid-places.rs:41:5 + | +LL | type Type = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 26 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs new file mode 100644 index 0000000000000..ed911d965d631 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs @@ -0,0 +1,6 @@ +#![feature(const_trait_impl)] + +const fn tilde_question() {} +//~^ ERROR `~const` and `?` are mutually exclusive + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr new file mode 100644 index 0000000000000..5850ab41c6ba6 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr @@ -0,0 +1,8 @@ +error: `~const` and `?` are mutually exclusive + --> $DIR/tilde-const-maybe-trait.rs:3:28 + | +LL | const fn tilde_question() {} + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.stderr index 928d23e8a424d..a809736a4f824 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-twice.stderr @@ -4,5 +4,5 @@ error: expected identifier, found `~` LL | struct S; | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr index f77672f3e71b5..0925bfa7e576e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr @@ -7,6 +7,6 @@ LL | self.0.foo() = note: expected constant `host` found constant `true` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr index 3d6fedbabbf60..abe24b662a27f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -2,7 +2,7 @@ error: `~const` is not allowed here --> $DIR/trait-where-clause.rs:8:24 | LL | fn b() where Self: ~const Bar; - | ^^^^^^^^^^ + | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds --> $DIR/trait-where-clause.rs:8:8 @@ -14,7 +14,7 @@ error: `~const` is not allowed here --> $DIR/trait-where-clause.rs:10:13 | LL | fn c(); - | ^^^^^^^^^^ + | ^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds --> $DIR/trait-where-clause.rs:10:8 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr index 31300354a5737..646cdfc78f971 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr @@ -6,5 +6,5 @@ LL | struct S; | | | help: add `~`: `~` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs index 5037396000bf0..5609dc51a67ed 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs @@ -1,8 +1,6 @@ // run-pass // edition: 2021 -#![feature(c_str_literals)] - fn main() { assert_eq!(b"test\0", c"test".to_bytes_with_nul()); } diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs deleted file mode 100644 index ddd6d9a25daad..0000000000000 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs +++ /dev/null @@ -1,15 +0,0 @@ -// gate-test-c_str_literals -// known-bug: #113333 -// edition: 2021 - -macro_rules! m { - ($t:tt) => {} -} - -fn main() { - c"foo"; - // FIXME(c_str_literals): This should be ``c".."` literals are experimental` - - m!(c"test"); - // FIXME(c_str_literals): This should be ``c".."` literals are experimental` -} diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr deleted file mode 100644 index ea666e4330830..0000000000000 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0658]: `c".."` literals are experimental - --> $DIR/gate.rs:10:5 - | -LL | c"foo"; - | ^^^^^^ - | - = note: see issue #105723 for more information - = help: add `#![feature(c_str_literals)]` to the crate attributes to enable - -error[E0658]: `c".."` literals are experimental - --> $DIR/gate.rs:13:8 - | -LL | m!(c"test"); - | ^^^^^^^ - | - = note: see issue #105723 for more information - = help: add `#![feature(c_str_literals)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs index 369173e23184e..a7e36b2233ec5 100644 Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs differ diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr index 82d9f9cb32091..ff9006f6f97f1 100644 Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr differ diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs index 380445d7a7fb9..8a5f514db7f61 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs @@ -1,8 +1,6 @@ // run-pass // edition: 2021 -#![feature(c_str_literals)] - fn main() { assert_eq!( c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), diff --git a/tests/ui/rmeta/emit-artifact-notifications.stderr b/tests/ui/rmeta/emit-artifact-notifications.stderr index b2f0aa7575c06..4f68a2d74ed31 100644 --- a/tests/ui/rmeta/emit-artifact-notifications.stderr +++ b/tests/ui/rmeta/emit-artifact-notifications.stderr @@ -1 +1 @@ -{"artifact":"$TEST_BUILD_DIR/rmeta/emit-artifact-notifications/libemit_artifact_notifications.rmeta","emit":"metadata"} +{"$message_type":"artifact","artifact":"$TEST_BUILD_DIR/rmeta/emit-artifact-notifications/libemit_artifact_notifications.rmeta","emit":"metadata"} diff --git a/tests/ui/rmeta/no_optitimized_mir.stderr b/tests/ui/rmeta/no_optitimized_mir.stderr index a17024c5310d1..92f22d7800050 100644 --- a/tests/ui/rmeta/no_optitimized_mir.stderr +++ b/tests/ui/rmeta/no_optitimized_mir.stderr @@ -6,5 +6,5 @@ note: missing optimized MIR for this item (was the crate `rmeta_meta` compiled w LL | pub fn missing_optimized_mir() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rmeta/rmeta.stderr b/tests/ui/rmeta/rmeta.stderr index d15caeb669811..85452ea41d313 100644 --- a/tests/ui/rmeta/rmeta.stderr +++ b/tests/ui/rmeta/rmeta.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `Foo` in this scope LL | let _ = Foo; | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/rmeta/rmeta_lib.stderr b/tests/ui/rmeta/rmeta_lib.stderr index 8a9179cca6bc3..830169e032a1b 100644 --- a/tests/ui/rmeta/rmeta_lib.stderr +++ b/tests/ui/rmeta/rmeta_lib.stderr @@ -1,4 +1,4 @@ error: crate `rmeta_meta` required to be available in rlib format, but was not found in this form -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rmeta/rmeta_meta_main.stderr b/tests/ui/rmeta/rmeta_meta_main.stderr index 0c6ed9afd3587..af11c88d9282e 100644 --- a/tests/ui/rmeta/rmeta_meta_main.stderr +++ b/tests/ui/rmeta/rmeta_meta_main.stderr @@ -2,8 +2,13 @@ error[E0560]: struct `Foo` has no field named `field2` --> $DIR/rmeta_meta_main.rs:13:19 | LL | let _ = Foo { field2: 42 }; - | ^^^^^^ help: a field with a similar name exists: `field` + | ^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = Foo { field: 42 }; + | ~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/rust-2018/async-ident-allowed.stderr b/tests/ui/rust-2018/async-ident-allowed.stderr index 992b2975009ab..b413c0fd9ba8f 100644 --- a/tests/ui/rust-2018/async-ident-allowed.stderr +++ b/tests/ui/rust-2018/async-ident-allowed.stderr @@ -13,5 +13,5 @@ LL | #![deny(rust_2018_compatibility)] | ^^^^^^^^^^^^^^^^^^^^^^^ = note: `#[deny(keyword_idents)]` implied by `#[deny(rust_2018_compatibility)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/dyn-keyword.stderr b/tests/ui/rust-2018/dyn-keyword.stderr index b6f5b10cf03ec..6f9a5ddb14fe1 100644 --- a/tests/ui/rust-2018/dyn-keyword.stderr +++ b/tests/ui/rust-2018/dyn-keyword.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr index bb50ec3f57dd6..a68d99c14cead 100644 --- a/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr +++ b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr @@ -11,5 +11,5 @@ LL | #![deny(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ = note: `#[deny(unused_extern_crates)]` implied by `#[deny(rust_2018_idioms)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/extern-crate-rename.stderr b/tests/ui/rust-2018/extern-crate-rename.stderr index eb040f5de5440..36986c89c62bc 100644 --- a/tests/ui/rust-2018/extern-crate-rename.stderr +++ b/tests/ui/rust-2018/extern-crate-rename.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/extern-crate-submod.stderr b/tests/ui/rust-2018/extern-crate-submod.stderr index 1a9aa75787a39..85e26d72a673b 100644 --- a/tests/ui/rust-2018/extern-crate-submod.stderr +++ b/tests/ui/rust-2018/extern-crate-submod.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr index 9933b92439c13..49736205f204b 100644 --- a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr +++ b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr @@ -16,6 +16,6 @@ LL + use std::collections::hash_set::Drain; | and 3 other candidates -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr index 2ef97e7f20e9f..801d16af82dba 100644 --- a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr +++ b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr @@ -14,5 +14,5 @@ LL | #![deny(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ = note: `#[deny(unused_extern_crates)]` implied by `#[deny(rust_2018_idioms)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/local-path-suggestions-2015.stderr b/tests/ui/rust-2018/local-path-suggestions-2015.stderr index 666864a18af88..e726b1e3e8182 100644 --- a/tests/ui/rust-2018/local-path-suggestions-2015.stderr +++ b/tests/ui/rust-2018/local-path-suggestions-2015.stderr @@ -7,6 +7,6 @@ LL | use foobar::Baz; | unresolved import | help: a similar path exists: `aux_baz::foobar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr index a5c79366bf0dc..f2536c1a1e988 100644 --- a/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr @@ -20,6 +20,6 @@ LL | m!(); = help: use `self::std` to refer to this module unambiguously = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr index 8045f3a45b607..3400183df6f41 100644 --- a/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr @@ -20,6 +20,6 @@ LL | m!(); = help: use `crate::std` to refer to this module unambiguously = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/issue-54253.stderr b/tests/ui/rust-2018/uniform-paths/issue-54253.stderr index adde635903515..7a1c55a8b2b93 100644 --- a/tests/ui/rust-2018/uniform-paths/issue-54253.stderr +++ b/tests/ui/rust-2018/uniform-paths/issue-54253.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `crate::version` LL | use crate::version; | ^^^^^^^^^^^^^^ no `version` in the root -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/uniform-paths/issue-56596.stderr b/tests/ui/rust-2018/uniform-paths/issue-56596.stderr index 849d6275eb85b..363d7a7a25fa6 100644 --- a/tests/ui/rust-2018/uniform-paths/issue-56596.stderr +++ b/tests/ui/rust-2018/uniform-paths/issue-56596.stderr @@ -15,6 +15,6 @@ LL | use m::*; = help: consider adding an explicit import of `issue_56596` to disambiguate = help: or use `crate::issue_56596` to refer to this module unambiguously -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/issue-87932.stderr b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr index ac2baa3595bd3..4a874a834bb7e 100644 --- a/tests/ui/rust-2018/uniform-paths/issue-87932.stderr +++ b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr @@ -13,6 +13,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use ::deserialize::_a::Deserialize; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/rust-2018/uniform-paths/macro-rules.stderr b/tests/ui/rust-2018/uniform-paths/macro-rules.stderr index 8a978c98a443e..661d667eb9a54 100644 --- a/tests/ui/rust-2018/uniform-paths/macro-rules.stderr +++ b/tests/ui/rust-2018/uniform-paths/macro-rules.stderr @@ -10,6 +10,6 @@ help: consider adding a `#[macro_export]` to the macro in the imported module LL | macro_rules! legacy_macro { () => () } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/rust-2018/uniform-paths/prelude-fail.stderr b/tests/ui/rust-2018/uniform-paths/prelude-fail.stderr index 97d4c736751aa..a0d272dc658bc 100644 --- a/tests/ui/rust-2018/uniform-paths/prelude-fail.stderr +++ b/tests/ui/rust-2018/uniform-paths/prelude-fail.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `rustfmt` LL | use rustfmt::skip as imported_rustfmt_skip; | ^^^^^^^ `rustfmt` is a tool module, not a module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/unresolved-asterisk-imports.stderr b/tests/ui/rust-2018/unresolved-asterisk-imports.stderr index 09e9edc638d1d..b6bf109824f70 100644 --- a/tests/ui/rust-2018/unresolved-asterisk-imports.stderr +++ b/tests/ui/rust-2018/unresolved-asterisk-imports.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `not_existing_crate` LL | use not_existing_crate::*; | ^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `not_existing_crate` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2021/future-prelude-collision-shadow.stderr b/tests/ui/rust-2021/future-prelude-collision-shadow.stderr index 9dfaf13e2ecdc..d2b2e5b2fd774 100644 --- a/tests/ui/rust-2021/future-prelude-collision-shadow.stderr +++ b/tests/ui/rust-2021/future-prelude-collision-shadow.stderr @@ -13,6 +13,6 @@ LL + use crate::m::TryIntoU32; LL + use std::convert::TryInto; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/rustc-error.stderr b/tests/ui/rustc-error.stderr index de27e9b8f086d..67451195b64f3 100644 --- a/tests/ui/rustc-error.stderr +++ b/tests/ui/rustc-error.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/cfg-rustdoc.stderr b/tests/ui/rustdoc/cfg-rustdoc.stderr index c687d186989c0..340a8e22482ce 100644 --- a/tests/ui/rustdoc/cfg-rustdoc.stderr +++ b/tests/ui/rustdoc/cfg-rustdoc.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `Foo` in this scope LL | let f = Foo; | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr b/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr index e9a4c1dd52f4f..bf104f48be0e8 100644 --- a/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr +++ b/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/doc-alias-same-name.stderr b/tests/ui/rustdoc/doc-alias-same-name.stderr index 5ba09a2eae1c7..a9da75c0171c0 100644 --- a/tests/ui/rustdoc/doc-alias-same-name.stderr +++ b/tests/ui/rustdoc/doc-alias-same-name.stderr @@ -4,5 +4,5 @@ error: `#[doc(alias = "...")]` is the same as the item's name LL | #[doc(alias = "Foo")] | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/doc-inline-extern-crate.stderr b/tests/ui/rustdoc/doc-inline-extern-crate.stderr index 41518295b1224..df0c4cb6b6317 100644 --- a/tests/ui/rustdoc/doc-inline-extern-crate.stderr +++ b/tests/ui/rustdoc/doc-inline-extern-crate.stderr @@ -9,5 +9,5 @@ LL | #[doc(no_inline)] | = help: remove one of the conflicting attributes -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/doc-primitive.stderr b/tests/ui/rustdoc/doc-primitive.stderr index d61eb38164795..5f535206d2679 100644 --- a/tests/ui/rustdoc/doc-primitive.stderr +++ b/tests/ui/rustdoc/doc-primitive.stderr @@ -12,5 +12,5 @@ note: the lint level is defined here LL | #![deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/feature-gate-doc_primitive.stderr b/tests/ui/rustdoc/feature-gate-doc_primitive.stderr index 5920880675d7e..0f5665f1fb9d8 100644 --- a/tests/ui/rustdoc/feature-gate-doc_primitive.stderr +++ b/tests/ui/rustdoc/feature-gate-doc_primitive.stderr @@ -6,6 +6,6 @@ LL | #[rustc_doc_primitive = "usize"] | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rustdoc/unterminated-doc-comment.stderr b/tests/ui/rustdoc/unterminated-doc-comment.stderr index 2d5e537973ea8..2d96c606b1636 100644 --- a/tests/ui/rustdoc/unterminated-doc-comment.stderr +++ b/tests/ui/rustdoc/unterminated-doc-comment.stderr @@ -4,6 +4,6 @@ error[E0758]: unterminated block doc-comment LL | /*! | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0758`. diff --git a/tests/ui/sanitize/cfg-kasan.rs b/tests/ui/sanitize/cfg-kasan.rs index d721011f3ee51..fb9a6f549ce0c 100644 --- a/tests/ui/sanitize/cfg-kasan.rs +++ b/tests/ui/sanitize/cfg-kasan.rs @@ -8,10 +8,8 @@ //[aarch64] needs-llvm-components: aarch64 //[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf //[riscv64imac] needs-llvm-components: riscv -//[riscv64imac] min-llvm-version: 16 //[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf //[riscv64gc] needs-llvm-components: riscv -//[riscv64gc] min-llvm-version: 16 //[x86_64] compile-flags: --target x86_64-unknown-none //[x86_64] needs-llvm-components: x86 diff --git a/tests/ui/sanitize/crt-static.stderr b/tests/ui/sanitize/crt-static.stderr index 9f74235fea5d2..98b0ed82e80ea 100644 --- a/tests/ui/sanitize/crt-static.stderr +++ b/tests/ui/sanitize/crt-static.stderr @@ -1,4 +1,4 @@ error: sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/incompatible.stderr b/tests/ui/sanitize/incompatible.stderr index f86db41bac717..4dff813ee1be6 100644 --- a/tests/ui/sanitize/incompatible.stderr +++ b/tests/ui/sanitize/incompatible.stderr @@ -1,4 +1,4 @@ error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/sanitizer-cfi-canonical-jump-tables-require-cfi.stderr b/tests/ui/sanitize/sanitizer-cfi-canonical-jump-tables-require-cfi.stderr index 3ee95634b16a1..de67d6a6b7f06 100644 --- a/tests/ui/sanitize/sanitizer-cfi-canonical-jump-tables-require-cfi.stderr +++ b/tests/ui/sanitize/sanitizer-cfi-canonical-jump-tables-require-cfi.stderr @@ -1,4 +1,4 @@ error: `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/sanitizer-cfi-generalize-pointers-require-cfi.stderr b/tests/ui/sanitize/sanitizer-cfi-generalize-pointers-require-cfi.stderr index 6eb09a53b4862..621708de241c2 100644 --- a/tests/ui/sanitize/sanitizer-cfi-generalize-pointers-require-cfi.stderr +++ b/tests/ui/sanitize/sanitizer-cfi-generalize-pointers-require-cfi.stderr @@ -1,4 +1,4 @@ error: `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/sanitizer-cfi-invalid-attr-cfi-encoding.stderr b/tests/ui/sanitize/sanitizer-cfi-invalid-attr-cfi-encoding.stderr index e23bafb181468..b9e9722da2300 100644 --- a/tests/ui/sanitize/sanitizer-cfi-invalid-attr-cfi-encoding.stderr +++ b/tests/ui/sanitize/sanitizer-cfi-invalid-attr-cfi-encoding.stderr @@ -4,5 +4,5 @@ error: malformed `cfi_encoding` attribute input LL | #[cfi_encoding] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/sanitizer-cfi-normalize-integers-require-cfi.stderr b/tests/ui/sanitize/sanitizer-cfi-normalize-integers-require-cfi.stderr index e31642054343c..748fb60dad92e 100644 --- a/tests/ui/sanitize/sanitizer-cfi-normalize-integers-require-cfi.stderr +++ b/tests/ui/sanitize/sanitizer-cfi-normalize-integers-require-cfi.stderr @@ -1,4 +1,4 @@ error: `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/sanitizer-cfi-requires-lto.stderr b/tests/ui/sanitize/sanitizer-cfi-requires-lto.stderr index 8cd9c544417f3..efc0c43138e12 100644 --- a/tests/ui/sanitize/sanitizer-cfi-requires-lto.stderr +++ b/tests/ui/sanitize/sanitizer-cfi-requires-lto.stderr @@ -1,4 +1,4 @@ error: `-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/sanitizer-cfi-with-rustc-lto-requires-single-codegen-unit.stderr b/tests/ui/sanitize/sanitizer-cfi-with-rustc-lto-requires-single-codegen-unit.stderr index 136f49360849f..8d6dc1d8f1ea4 100644 --- a/tests/ui/sanitize/sanitizer-cfi-with-rustc-lto-requires-single-codegen-unit.stderr +++ b/tests/ui/sanitize/sanitizer-cfi-with-rustc-lto-requires-single-codegen-unit.stderr @@ -1,4 +1,4 @@ error: `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/split-lto-unit-requires-lto.stderr b/tests/ui/sanitize/split-lto-unit-requires-lto.stderr index ab8f4f4f35153..0da06b7f8b18a 100644 --- a/tests/ui/sanitize/split-lto-unit-requires-lto.stderr +++ b/tests/ui/sanitize/split-lto-unit-requires-lto.stderr @@ -1,4 +1,4 @@ error: `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sanitize/unsupported-target.stderr b/tests/ui/sanitize/unsupported-target.stderr index 9bb8405020d73..bebbf3884ae67 100644 --- a/tests/ui/sanitize/unsupported-target.stderr +++ b/tests/ui/sanitize/unsupported-target.stderr @@ -1,4 +1,4 @@ error: leak sanitizer is not supported for this target -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr index cbf5e6c541a39..a415aa3d7b49e 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr @@ -8,6 +8,6 @@ LL | fn get>(self: R) -> u32 { = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

    ` (where P is one of the previous types except `Self`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr index 7378d53c37387..44e553f1a06ca 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | foo.get::<&Foo>(); | ^^^ expected `&Foo`, found `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr index 0a567ddcc2e81..363ba072c8169 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr @@ -17,6 +17,6 @@ LL | fn foo(self: &Rc) -> usize; = help: only type `usize` implements the trait, consider using it directly instead = note: required for the cast from `Rc` to `Rc` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr index 5dcb5861120a8..f33b9ec68b978 100644 --- a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr +++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr @@ -13,6 +13,6 @@ LL ~ let mut pinned = std::pin::pin!(S); LL ~ pinned.as_mut().x(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 944cdc5f55de6..e04ec8bb3bca4 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -12,6 +12,6 @@ help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` l LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 8a9b397ca7005..a2964881d58a7 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -12,6 +12,6 @@ help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` l LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/self/issue-61882-2.stderr b/tests/ui/self/issue-61882-2.stderr index 6faa4477d8c5d..7d5214421e320 100644 --- a/tests/ui/self/issue-61882-2.stderr +++ b/tests/ui/self/issue-61882-2.stderr @@ -12,6 +12,6 @@ LL | LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/self/point-at-arbitrary-self-type-method.stderr b/tests/ui/self/point-at-arbitrary-self-type-method.stderr index 3c7cccfc9a16e..14bd6ca6b014f 100644 --- a/tests/ui/self/point-at-arbitrary-self-type-method.stderr +++ b/tests/ui/self/point-at-arbitrary-self-type-method.stderr @@ -15,6 +15,6 @@ help: consider wrapping the receiver expression with the appropriate type LL | Box::new(A).foo(); | +++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/tests/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 366c14f7616a3..29510190c814a 100644 --- a/tests/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/tests/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -16,6 +16,6 @@ help: consider wrapping the receiver expression with the appropriate type LL | Box::new(A).foo() | +++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/self/self-vs-path-ambiguity.stderr b/tests/ui/self/self-vs-path-ambiguity.stderr index 2beef50cdb5c6..9e140e21023f3 100644 --- a/tests/ui/self/self-vs-path-ambiguity.stderr +++ b/tests/ui/self/self-vs-path-ambiguity.stderr @@ -4,5 +4,5 @@ error: unexpected lifetime `'a` in pattern LL | fn i(&'a self::S: &S) {} | ^^ help: remove the lifetime -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr index 6e65fae808ded..fed853a7e1fd8 100644 --- a/tests/ui/self/self_type_keyword.stderr +++ b/tests/ui/self/self_type_keyword.stderr @@ -14,7 +14,7 @@ error: `mut` must be followed by a named binding --> $DIR/self_type_keyword.rs:16:9 | LL | mut Self => (), - | ^^^^^^^^ help: remove the `mut` prefix: `Self` + | ^^^^ help: remove the `mut` prefix | = note: `mut` may be followed by `variable` and `variable @ pattern` diff --git a/tests/ui/sepcomp/sepcomp-lib-lto.rs b/tests/ui/sepcomp/sepcomp-lib-lto.rs index 51a572899f819..164ae79c254fa 100644 --- a/tests/ui/sepcomp/sepcomp-lib-lto.rs +++ b/tests/ui/sepcomp/sepcomp-lib-lto.rs @@ -4,7 +4,6 @@ // aux-build:sepcomp_lib.rs // compile-flags: -C lto -g -// ignore-asmjs wasm2js does not support source maps yet // no-prefer-dynamic extern crate sepcomp_lib; diff --git a/tests/ui/shadowed/shadowed-trait-methods.stderr b/tests/ui/shadowed/shadowed-trait-methods.stderr index 1af0400c88619..0bcf32790bcc1 100644 --- a/tests/ui/shadowed/shadowed-trait-methods.stderr +++ b/tests/ui/shadowed/shadowed-trait-methods.stderr @@ -13,6 +13,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use foo::T; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/simd/libm_no_std_cant_float.rs b/tests/ui/simd/libm_no_std_cant_float.rs index 50ac8e208390f..f54a1faf4f928 100644 --- a/tests/ui/simd/libm_no_std_cant_float.rs +++ b/tests/ui/simd/libm_no_std_cant_float.rs @@ -2,7 +2,7 @@ #![no_std] #![feature(portable_simd)] use core::simd::f32x4; -use core::simd::SimdFloat; +use core::simd::num::SimdFloat; // For SIMD float ops, the LLIR version which is used to implement the portable // forms of them may become calls to math.h AKA libm. So, we can't guarantee diff --git a/tests/ui/simd/libm_std_can_float.rs b/tests/ui/simd/libm_std_can_float.rs index 1c520856e9818..78bd0c14022e4 100644 --- a/tests/ui/simd/libm_std_can_float.rs +++ b/tests/ui/simd/libm_std_can_float.rs @@ -3,7 +3,7 @@ // This is the converse of the other libm test. #![feature(portable_simd)] use std::simd::f32x4; -use std::simd::{SimdFloat, StdFloat}; +use std::simd::{num::SimdFloat, StdFloat}; // For SIMD float ops, the LLIR version which is used to implement the portable // forms of them may become calls to math.h AKA libm. So, we can't guarantee diff --git a/tests/ui/simd/monomorphize-heterogeneous.stderr b/tests/ui/simd/monomorphize-heterogeneous.stderr index e7b41cd787cd2..58e2b7c834766 100644 --- a/tests/ui/simd/monomorphize-heterogeneous.stderr +++ b/tests/ui/simd/monomorphize-heterogeneous.stderr @@ -4,6 +4,6 @@ error[E0076]: SIMD vector should be homogeneous LL | struct I64F64(i64, f64); | ^^^^^^^^^^^^^ SIMD elements must have the same type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0076`. diff --git a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr index fc66b195674c6..c4cfca7be1d5e 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr +++ b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr @@ -8,5 +8,5 @@ LL | return simd_shuffle_generic::<_, _, { &Self::I }>(a, b); | = help: consider moving this anonymous constant into a `const` function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/simd/portable-intrinsics-arent-exposed.stderr b/tests/ui/simd/portable-intrinsics-arent-exposed.stderr index f8b3e6d65afb6..a6f27af428b51 100644 --- a/tests/ui/simd/portable-intrinsics-arent-exposed.stderr +++ b/tests/ui/simd/portable-intrinsics-arent-exposed.stderr @@ -2,9 +2,10 @@ error[E0433]: failed to resolve: maybe a missing crate `core`? --> $DIR/portable-intrinsics-arent-exposed.rs:4:5 | LL | use core::simd::intrinsics; - | ^^^^ maybe a missing crate `core`? - | - = help: consider adding `extern crate core` to use the `core` crate + | ^^^^ + | | + | maybe a missing crate `core`? + | help: try using `std` instead of `core`: `std` error[E0432]: unresolved import `std::simd::intrinsics` --> $DIR/portable-intrinsics-arent-exposed.rs:5:5 diff --git a/tests/ui/simd/type-generic-monomorphisation-empty.stderr b/tests/ui/simd/type-generic-monomorphisation-empty.stderr index b334b1f4b5893..fc294607ae310 100644 --- a/tests/ui/simd/type-generic-monomorphisation-empty.stderr +++ b/tests/ui/simd/type-generic-monomorphisation-empty.stderr @@ -1,4 +1,4 @@ error: monomorphising SIMD type `Simd<0>` of zero length -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/simd/type-generic-monomorphisation-non-primitive.stderr b/tests/ui/simd/type-generic-monomorphisation-non-primitive.stderr index 9e8f06b824ccf..249a14098c331 100644 --- a/tests/ui/simd/type-generic-monomorphisation-non-primitive.stderr +++ b/tests/ui/simd/type-generic-monomorphisation-non-primitive.stderr @@ -1,4 +1,4 @@ error: monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `E` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/simd/type-generic-monomorphisation-oversized.stderr b/tests/ui/simd/type-generic-monomorphisation-oversized.stderr index a2dba1222eecd..39ff36799cc92 100644 --- a/tests/ui/simd/type-generic-monomorphisation-oversized.stderr +++ b/tests/ui/simd/type-generic-monomorphisation-oversized.stderr @@ -1,4 +1,4 @@ error: monomorphising SIMD type `Simd<65536>` of length greater than 32768 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr index 3888e7a0f38f5..7ac8d71536034 100644 --- a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr @@ -1,4 +1,4 @@ error: monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/simd/type-generic-monomorphisation.stderr b/tests/ui/simd/type-generic-monomorphisation.stderr index 7f23893ac8536..35297e17d370d 100644 --- a/tests/ui/simd/type-generic-monomorphisation.stderr +++ b/tests/ui/simd/type-generic-monomorphisation.stderr @@ -1,4 +1,4 @@ error: monomorphising SIMD type `Simd2` with a non-primitive-scalar (integer/float/pointer) element type `X` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/simd/type-wide-ptr.stderr b/tests/ui/simd/type-wide-ptr.stderr index 51d3c00507205..d2ce0fdd2024b 100644 --- a/tests/ui/simd/type-wide-ptr.stderr +++ b/tests/ui/simd/type-wide-ptr.stderr @@ -1,4 +1,4 @@ error: monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr index 94129560f4043..e151269d7312e 100644 --- a/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr +++ b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr @@ -17,5 +17,5 @@ LL - impl<'f> Foo<'f> { LL + impl Foo<'_> { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr index 69578fe2f8830..bc86e36f308c8 100644 --- a/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr +++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr @@ -17,5 +17,5 @@ LL - impl<'f> Foo<'f> { LL + impl Foo<'_> { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr index 1a6e8310d303a..0e67180a8ee43 100644 --- a/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr +++ b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr @@ -17,5 +17,5 @@ LL - fn next<'g>(&'g mut self) -> Option { LL + fn next(&mut self) -> Option { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr index 4794566eae4dc..4cc46524a9253 100644 --- a/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr +++ b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr @@ -17,5 +17,5 @@ LL - impl<'f> Foo<'f> { LL + impl Foo<'_> { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr b/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr index b6e42d3e717f0..554a19afbcd32 100644 --- a/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr +++ b/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_lifetimes)] | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sized-cycle-note.stderr b/tests/ui/sized-cycle-note.stderr index 06c87b61f41f6..21e54c12fedad 100644 --- a/tests/ui/sized-cycle-note.stderr +++ b/tests/ui/sized-cycle-note.stderr @@ -14,6 +14,6 @@ LL | LL ~ struct Foo { q: Option> } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/sized/recursive-type-2.stderr b/tests/ui/sized/recursive-type-2.stderr index 0f72f74145e8d..4e7f40a01533c 100644 --- a/tests/ui/sized/recursive-type-2.stderr +++ b/tests/ui/sized/recursive-type-2.stderr @@ -9,6 +9,6 @@ LL | fn main() { | ^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/sized/unsized-binding.stderr b/tests/ui/sized/unsized-binding.stderr index af306685021e0..7c3276032c2b4 100644 --- a/tests/ui/sized/unsized-binding.stderr +++ b/tests/ui/sized/unsized-binding.stderr @@ -8,6 +8,6 @@ LL | let x = *""; = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/E0046.stderr b/tests/ui/span/E0046.stderr index 1323524f20850..416873a425721 100644 --- a/tests/ui/span/E0046.stderr +++ b/tests/ui/span/E0046.stderr @@ -7,6 +7,6 @@ LL | fn foo(); LL | impl Foo for Bar {} | ^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/E0072.stderr b/tests/ui/span/E0072.stderr index 20f2e0df05efe..c8599b4ebe510 100644 --- a/tests/ui/span/E0072.stderr +++ b/tests/ui/span/E0072.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | tail: Option>, | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/E0493.stderr b/tests/ui/span/E0493.stderr index 9db627562d6eb..0f2e2d7b3fb8e 100644 --- a/tests/ui/span/E0493.stderr +++ b/tests/ui/span/E0493.stderr @@ -6,6 +6,6 @@ LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; | | | the destructor for this type cannot be evaluated in constants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/span/E0535.stderr b/tests/ui/span/E0535.stderr index b1411bc436ae2..9060b687f508c 100644 --- a/tests/ui/span/E0535.stderr +++ b/tests/ui/span/E0535.stderr @@ -6,6 +6,6 @@ LL | #[inline(unknown)] | = help: valid inline arguments are `always` and `never` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0535`. diff --git a/tests/ui/span/E0536.stderr b/tests/ui/span/E0536.stderr index 820b0d7441b4a..b0f652208c4a9 100644 --- a/tests/ui/span/E0536.stderr +++ b/tests/ui/span/E0536.stderr @@ -4,6 +4,6 @@ error[E0536]: expected 1 cfg-pattern LL | #[cfg(not())] | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0536`. diff --git a/tests/ui/span/E0537.stderr b/tests/ui/span/E0537.stderr index 5478c3fbcdda3..4254d3893b83f 100644 --- a/tests/ui/span/E0537.stderr +++ b/tests/ui/span/E0537.stderr @@ -4,6 +4,6 @@ error[E0537]: invalid predicate `unknown` LL | #[cfg(unknown())] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0537`. diff --git a/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr index 3f033f5e47b5b..39e7279fb77d0 100644 --- a/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr +++ b/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | fn b(x: &mut Foo) { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-fn-in-const-b.stderr b/tests/ui/span/borrowck-fn-in-const-b.stderr index 9298780262902..d4a8ba2698da0 100644 --- a/tests/ui/span/borrowck-fn-in-const-b.stderr +++ b/tests/ui/span/borrowck-fn-in-const-b.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | fn broken(x: &mut Vec) { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-ref-into-rvalue.stderr b/tests/ui/span/borrowck-ref-into-rvalue.stderr index 25e344fedfb25..c0edeeae20b10 100644 --- a/tests/ui/span/borrowck-ref-into-rvalue.stderr +++ b/tests/ui/span/borrowck-ref-into-rvalue.stderr @@ -15,6 +15,6 @@ LL ~ let binding = Some("Hello".to_string()); LL ~ match binding { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/destructor-restrictions.stderr b/tests/ui/span/destructor-restrictions.stderr index b923cee5f0ec6..a80a89fb632ae 100644 --- a/tests/ui/span/destructor-restrictions.stderr +++ b/tests/ui/span/destructor-restrictions.stderr @@ -20,6 +20,6 @@ help: for example, you could save the expression's value in a new local variable LL | let x = *a.borrow() + 1; x | +++++++ +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index 1ec8ca4275b37..004a057bbcdaf 100644 --- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -4,5 +4,5 @@ error: this file contains an unclosed delimiter LL | trait C{async fn new(val: T) {} | - unclosed delimiter ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/span/dropck-object-cycle.stderr b/tests/ui/span/dropck-object-cycle.stderr index 097fb6219f1fd..6e05f901ab241 100644 --- a/tests/ui/span/dropck-object-cycle.stderr +++ b/tests/ui/span/dropck-object-cycle.stderr @@ -12,6 +12,6 @@ LL | } | `*m` dropped here while still borrowed | borrow might be used here, when `m` is dropped and runs the destructor for type `Box>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/gated-features-attr-spans.stderr b/tests/ui/span/gated-features-attr-spans.stderr index c8b8f346b9879..5376d7799aaa6 100644 --- a/tests/ui/span/gated-features-attr-spans.stderr +++ b/tests/ui/span/gated-features-attr-spans.stderr @@ -7,6 +7,6 @@ LL | #[repr(simd)] = note: see issue #27731 for more information = help: add `#![feature(repr_simd)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/span/issue-11925.stderr b/tests/ui/span/issue-11925.stderr index 1d317fc331f73..c7f9573593b7e 100644 --- a/tests/ui/span/issue-11925.stderr +++ b/tests/ui/span/issue-11925.stderr @@ -4,6 +4,6 @@ error[E0515]: cannot return reference to local data `x` LL | let f = to_fn_once(move|| &x); | ^^ returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/span/issue-15480.stderr b/tests/ui/span/issue-15480.stderr index d9cce2254dd95..45a5d7dfbecb0 100644 --- a/tests/ui/span/issue-15480.stderr +++ b/tests/ui/span/issue-15480.stderr @@ -16,6 +16,6 @@ LL ~ let v = vec![ LL ~ &binding | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/issue-23729.stderr b/tests/ui/span/issue-23729.stderr index cd854e61f2f47..6baec60d50c6c 100644 --- a/tests/ui/span/issue-23729.stderr +++ b/tests/ui/span/issue-23729.stderr @@ -6,6 +6,6 @@ LL | impl Iterator for Recurrence { | = help: implement the missing item: `type Item = /* Type */;` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-23827.stderr b/tests/ui/span/issue-23827.stderr index 83a9e8c9b9876..fe7c7794c9c7a 100644 --- a/tests/ui/span/issue-23827.stderr +++ b/tests/ui/span/issue-23827.stderr @@ -6,6 +6,6 @@ LL | impl FnOnce<(C,)> for Prototype { | = help: implement the missing item: `type Output = /* Type */;` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-24356.stderr b/tests/ui/span/issue-24356.stderr index cf666e8b4a7a6..609991f2b5b0f 100644 --- a/tests/ui/span/issue-24356.stderr +++ b/tests/ui/span/issue-24356.stderr @@ -6,6 +6,6 @@ LL | impl Deref for Thing { | = help: implement the missing item: `type Target = /* Type */;` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr index c3b6d7580b4e0..f7564f8c72ec8 100644 --- a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr +++ b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr @@ -15,6 +15,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-24895-copy-clone-dropck.stderr b/tests/ui/span/issue-24895-copy-clone-dropck.stderr index 83db4d509d499..2252a241b73fe 100644 --- a/tests/ui/span/issue-24895-copy-clone-dropck.stderr +++ b/tests/ui/span/issue-24895-copy-clone-dropck.stderr @@ -14,6 +14,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-25199.stderr b/tests/ui/span/issue-25199.stderr index 1e0276f0c3694..7a6910065fc3e 100644 --- a/tests/ui/span/issue-25199.stderr +++ b/tests/ui/span/issue-25199.stderr @@ -12,6 +12,6 @@ LL | } | `container` dropped here while still borrowed | borrow might be used here, when `container` is dropped and runs the destructor for type `Container<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-26656.stderr b/tests/ui/span/issue-26656.stderr index fea6e001238b5..586eca25473cb 100644 --- a/tests/ui/span/issue-26656.stderr +++ b/tests/ui/span/issue-26656.stderr @@ -14,6 +14,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr index 8a254a9685543..c2de1562841c5 100644 --- a/tests/ui/span/issue-27522.stderr +++ b/tests/ui/span/issue-27522.stderr @@ -7,6 +7,6 @@ LL | fn handler(self: &SomeType); = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

    ` (where P is one of the previous types except `Self`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/span/issue-29595.stderr b/tests/ui/span/issue-29595.stderr index 7d603cdbfe5ca..c782875469098 100644 --- a/tests/ui/span/issue-29595.stderr +++ b/tests/ui/span/issue-29595.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait Tr { | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/issue-33884.stderr b/tests/ui/span/issue-33884.stderr index 8cece07cd48c2..29490d86fffe7 100644 --- a/tests/ui/span/issue-33884.stderr +++ b/tests/ui/span/issue-33884.stderr @@ -6,6 +6,6 @@ LL | stream.write_fmt(format!("message received")) | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/span/issue-35987.stderr b/tests/ui/span/issue-35987.stderr index 88c86d2a91b58..4c4b100da3dd8 100644 --- a/tests/ui/span/issue-35987.stderr +++ b/tests/ui/span/issue-35987.stderr @@ -14,6 +14,6 @@ help: consider importing this trait instead LL + use std::ops::Add; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/span/issue-36537.stderr b/tests/ui/span/issue-36537.stderr index 8dfee8d644be2..eeb4e9a0e4fa0 100644 --- a/tests/ui/span/issue-36537.stderr +++ b/tests/ui/span/issue-36537.stderr @@ -11,6 +11,6 @@ LL | } LL | p.use_ref(); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr index b612fdf16fc8c..457870821a19a 100644 --- a/tests/ui/span/issue-37767.stderr +++ b/tests/ui/span/issue-37767.stderr @@ -16,12 +16,12 @@ LL | fn foo(&mut self) {} | ^^^^^^^^^^^^^^^^^ help: disambiguate the method for candidate #1 | -LL | A::foo(&a) - | ~~~~~~~~~~ +LL | A::foo(&mut a) + | ~~~~~~~~~~~~~~ help: disambiguate the method for candidate #2 | -LL | B::foo(&a) - | ~~~~~~~~~~ +LL | B::foo(&mut a) + | ~~~~~~~~~~~~~~ error[E0034]: multiple applicable items in scope --> $DIR/issue-37767.rs:22:7 diff --git a/tests/ui/span/issue-40157.stderr b/tests/ui/span/issue-40157.stderr index 2168767178d82..7b2ce292cfc56 100644 --- a/tests/ui/span/issue-40157.stderr +++ b/tests/ui/span/issue-40157.stderr @@ -7,6 +7,6 @@ LL | {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x } | | borrowed value does not live long enough | binding `foo` declared here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue28498-reject-ex1.stderr b/tests/ui/span/issue28498-reject-ex1.stderr index 86e2d8c56b08f..7b8af23a6cd7b 100644 --- a/tests/ui/span/issue28498-reject-ex1.stderr +++ b/tests/ui/span/issue28498-reject-ex1.stderr @@ -12,6 +12,6 @@ LL | } | = note: consider using a `let` binding to create a longer lived value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/span/issue28498-reject-lifetime-param.stderr b/tests/ui/span/issue28498-reject-lifetime-param.stderr index 94c450c7b1ece..4b66dc76c443e 100644 --- a/tests/ui/span/issue28498-reject-lifetime-param.stderr +++ b/tests/ui/span/issue28498-reject-lifetime-param.stderr @@ -15,6 +15,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue28498-reject-passed-to-fn.stderr b/tests/ui/span/issue28498-reject-passed-to-fn.stderr index e133f75d57bb7..fe43657bd4003 100644 --- a/tests/ui/span/issue28498-reject-passed-to-fn.stderr +++ b/tests/ui/span/issue28498-reject-passed-to-fn.stderr @@ -15,6 +15,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue28498-reject-trait-bound.stderr b/tests/ui/span/issue28498-reject-trait-bound.stderr index 9ab3cdd1343a1..aafa29e5eae7c 100644 --- a/tests/ui/span/issue28498-reject-trait-bound.stderr +++ b/tests/ui/span/issue28498-reject-trait-bound.stderr @@ -15,6 +15,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/move-closure.stderr b/tests/ui/span/move-closure.stderr index 2127b82020562..2e9cef32e7e67 100644 --- a/tests/ui/span/move-closure.stderr +++ b/tests/ui/span/move-closure.stderr @@ -13,6 +13,6 @@ help: use parentheses to call this closure LL | let x: () = (move || ())(); | + +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/span/multiline-span-E0072.stderr b/tests/ui/span/multiline-span-E0072.stderr index fc2f6e6622c2a..9e675d56ee59a 100644 --- a/tests/ui/span/multiline-span-E0072.stderr +++ b/tests/ui/span/multiline-span-E0072.stderr @@ -13,6 +13,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | tail: Option>, | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/multiline-span-simple.stderr b/tests/ui/span/multiline-span-simple.stderr index b6052a209bf50..f0eec632aa1c3 100644 --- a/tests/ui/span/multiline-span-simple.stderr +++ b/tests/ui/span/multiline-span-simple.stderr @@ -11,6 +11,6 @@ LL | foo(1 as u32 + <&'a u32 as Add> <&u32 as Add<&u32>> -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/mut-ptr-cant-outlive-ref.stderr b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr index 395b6ec67918b..1624b80e72217 100644 --- a/tests/ui/span/mut-ptr-cant-outlive-ref.stderr +++ b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr @@ -11,6 +11,6 @@ LL | LL | p.use_ref(); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/non-existing-module-import.stderr b/tests/ui/span/non-existing-module-import.stderr index 25c09959047a1..7da9e32b31f25 100644 --- a/tests/ui/span/non-existing-module-import.stderr +++ b/tests/ui/span/non-existing-module-import.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `std::bar` LL | use std::bar::{foo1, foo2}; | ^^^ could not find `bar` in `std` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/span/recursive-type-field.stderr b/tests/ui/span/recursive-type-field.stderr index 10af4c36ba4b4..30ba8cde463b3 100644 --- a/tests/ui/span/recursive-type-field.stderr +++ b/tests/ui/span/recursive-type-field.stderr @@ -22,6 +22,6 @@ LL | struct Bar<'a> { LL ~ y: (Box>, Box>), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr index 9b5ec84614cf8..225f83b6e6662 100644 --- a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -11,6 +11,6 @@ LL | } LL | f.use_mut(); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr index 81e858fa0ce01..b7ca491f22cbe 100644 --- a/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr +++ b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -11,6 +11,6 @@ LL | } | = note: consider using a `let` binding to create a longer lived value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/regions-close-over-type-parameter-2.stderr b/tests/ui/span/regions-close-over-type-parameter-2.stderr index fed40a4fdd2a5..3849b9eef08fb 100644 --- a/tests/ui/span/regions-close-over-type-parameter-2.stderr +++ b/tests/ui/span/regions-close-over-type-parameter-2.stderr @@ -10,6 +10,6 @@ LL | repeater3(tmp1) LL | }; | - `tmp0` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-escape-loop-via-variable.stderr b/tests/ui/span/regions-escape-loop-via-variable.stderr index e5c7d8b26ab00..e32cc10c00cce 100644 --- a/tests/ui/span/regions-escape-loop-via-variable.stderr +++ b/tests/ui/span/regions-escape-loop-via-variable.stderr @@ -10,6 +10,6 @@ LL | p = &x; LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr index 47931db84cabe..746be04560828 100644 --- a/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr +++ b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr @@ -12,6 +12,6 @@ LL | } LL | assert!(*y != 0); | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/slice-borrow.stderr b/tests/ui/span/slice-borrow.stderr index b271c9ae6f616..48ac20feea721 100644 --- a/tests/ui/span/slice-borrow.stderr +++ b/tests/ui/span/slice-borrow.stderr @@ -12,6 +12,6 @@ LL | y.use_ref(); = note: consider using a `let` binding to create a longer lived value = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/suggestion-non-ascii.stderr b/tests/ui/span/suggestion-non-ascii.stderr index 21f8bb62a0c73..6e6e31a5698b8 100644 --- a/tests/ui/span/suggestion-non-ascii.stderr +++ b/tests/ui/span/suggestion-non-ascii.stderr @@ -4,6 +4,6 @@ error[E0608]: cannot index into a value of type `({integer},)` LL | println!("☃{}", tup[0]); | ^^^ help: to access tuple elements, use: `.0` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/span/transitive-dep-span.stderr b/tests/ui/span/transitive-dep-span.stderr index 4dc3e57211605..c0f3f3a65c781 100644 --- a/tests/ui/span/transitive-dep-span.stderr +++ b/tests/ui/span/transitive-dep-span.stderr @@ -14,5 +14,5 @@ LL | transitive_dep_two::parse_error!(); | in this macro invocation | in this macro invocation -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/span/type-annotations-needed-expr.stderr b/tests/ui/span/type-annotations-needed-expr.stderr index 65a90318a3c25..a548df052b822 100644 --- a/tests/ui/span/type-annotations-needed-expr.stderr +++ b/tests/ui/span/type-annotations-needed-expr.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | let _ = (vec![1,2,3]).into_iter().sum::() as f64; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/type-binding.stderr b/tests/ui/span/type-binding.stderr index cb0aefe06090a..5df74fa2fa2da 100644 --- a/tests/ui/span/type-binding.stderr +++ b/tests/ui/span/type-binding.stderr @@ -4,6 +4,6 @@ error[E0220]: associated type `Trget` not found for `Deref` LL | fn homura>(_: T) {} | ^^^^^ help: there is an associated type with a similar name: `Target` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/span/wf-method-late-bound-regions.stderr b/tests/ui/span/wf-method-late-bound-regions.stderr index 64c2d0f160665..09d6714e777fb 100644 --- a/tests/ui/span/wf-method-late-bound-regions.stderr +++ b/tests/ui/span/wf-method-late-bound-regions.stderr @@ -10,6 +10,6 @@ LL | f2.xmute(&pointer) LL | }; | - `pointer` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/specialization/default-associated-type-bound-1.stderr b/tests/ui/specialization/default-associated-type-bound-1.stderr index e498187c0a112..516df555a0d5f 100644 --- a/tests/ui/specialization/default-associated-type-bound-1.stderr +++ b/tests/ui/specialization/default-associated-type-bound-1.stderr @@ -21,6 +21,6 @@ note: required by a bound in `X::U` LL | type U: Clone; | ^^^^^ required by this bound in `X::U` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-associated-type-bound-2.stderr b/tests/ui/specialization/default-associated-type-bound-2.stderr index 4dbe251ed5ea3..e02a945d9a9ba 100644 --- a/tests/ui/specialization/default-associated-type-bound-2.stderr +++ b/tests/ui/specialization/default-associated-type-bound-2.stderr @@ -25,6 +25,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | impl X for T where &'static B: PartialEq { | ++++++++++++++++++++++++++++++ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr index c597eed379097..afdbe2eb22677 100644 --- a/tests/ui/specialization/default-generic-associated-type-bound.stderr +++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr @@ -25,6 +25,6 @@ help: consider further restricting this bound LL | impl X for T { | +++++++++++++++++++++ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr index 64e14f5800f25..18edcad0a47b5 100644 --- a/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr @@ -9,6 +9,6 @@ LL | | } = note: see issue #31844 for more information = help: add `#![feature(specialization)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr index f19975060a46b..d3441b0e8b921 100644 --- a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr @@ -17,6 +17,6 @@ LL | fn foo_two(&self) -> &'static str; LL | impl Foo for MyStruct {} | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 37788612f4371..75c91e4806f77 100644 --- a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -39,6 +39,6 @@ note: `Foo` defines an item `foo_one`, perhaps you need to implement it LL | trait Foo { | ^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr index e7801603493d2..01188e293bd97 100644 --- a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -24,6 +24,6 @@ help: consider restricting type parameter `U` LL | default impl Foo<'static, U> for () {} | ++++++++++++++ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-111232.stderr b/tests/ui/specialization/issue-111232.stderr index 27ee42fc00c00..ed392e4f9152b 100644 --- a/tests/ui/specialization/issue-111232.stderr +++ b/tests/ui/specialization/issue-111232.stderr @@ -6,6 +6,6 @@ LL | fn from(s: S) -> S { | = note: parent implementation is in crate `core` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/issue-33017.stderr b/tests/ui/specialization/issue-33017.stderr index 78e94cec2c0d5..2c20077078fd3 100644 --- a/tests/ui/specialization/issue-33017.stderr +++ b/tests/ui/specialization/issue-33017.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | impl UncheckedCopy for T { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-38091-2.stderr b/tests/ui/specialization/issue-38091-2.stderr index 5a05f9c270ab9..828a8e933994b 100644 --- a/tests/ui/specialization/issue-38091-2.stderr +++ b/tests/ui/specialization/issue-38091-2.stderr @@ -19,6 +19,6 @@ LL | where LL | T: Check, | ----- unsatisfied trait bound introduced here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-38091.stderr b/tests/ui/specialization/issue-38091.stderr index 4d840482b46b5..eb64383e18bbd 100644 --- a/tests/ui/specialization/issue-38091.stderr +++ b/tests/ui/specialization/issue-38091.stderr @@ -25,6 +25,6 @@ note: required by a bound in `Iterate::Ty` LL | type Ty: Valid; | ^^^^^ required by this bound in `Iterate::Ty` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-39448.stderr b/tests/ui/specialization/issue-39448.stderr index 9ce51d1136d0e..dc5db4f4285cd 100644 --- a/tests/ui/specialization/issue-39448.stderr +++ b/tests/ui/specialization/issue-39448.stderr @@ -30,6 +30,6 @@ LL | where LL | U: FromA, | -------- unsatisfied trait bound introduced here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-43037.current.stderr b/tests/ui/specialization/issue-43037.current.stderr index 26db9d7c99749..2711350925716 100644 --- a/tests/ui/specialization/issue-43037.current.stderr +++ b/tests/ui/specialization/issue-43037.current.stderr @@ -7,6 +7,6 @@ LL | impl From< as Z>::Assoc> for T {} = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/specialization/issue-43037.negative.stderr b/tests/ui/specialization/issue-43037.negative.stderr index 26db9d7c99749..2711350925716 100644 --- a/tests/ui/specialization/issue-43037.negative.stderr +++ b/tests/ui/specialization/issue-43037.negative.stderr @@ -7,6 +7,6 @@ LL | impl From< as Z>::Assoc> for T {} = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/specialization/issue-44861.stderr b/tests/ui/specialization/issue-44861.stderr index 1941d40fee8b9..d184c4468b685 100644 --- a/tests/ui/specialization/issue-44861.stderr +++ b/tests/ui/specialization/issue-44861.stderr @@ -10,6 +10,6 @@ note: required by a bound in `Smartass::Data2` LL | type Data2: CoerceUnsized<*const [u8]>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Smartass::Data2` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-45814.current.stderr b/tests/ui/specialization/issue-45814.current.stderr index 5013559b80ea9..da0dff78e2630 100644 --- a/tests/ui/specialization/issue-45814.current.stderr +++ b/tests/ui/specialization/issue-45814.current.stderr @@ -9,6 +9,6 @@ LL | default impl Trait for U {} = note: 128 redundant requirements hidden = note: required for `T` to implement `Trait<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-45814.negative.stderr b/tests/ui/specialization/issue-45814.negative.stderr index 5013559b80ea9..da0dff78e2630 100644 --- a/tests/ui/specialization/issue-45814.negative.stderr +++ b/tests/ui/specialization/issue-45814.negative.stderr @@ -9,6 +9,6 @@ LL | default impl Trait for U {} = note: 128 redundant requirements hidden = note: required for `T` to implement `Trait<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-50452-fail.stderr b/tests/ui/specialization/issue-50452-fail.stderr index 3fc29fff230a3..7ac4b39993cda 100644 --- a/tests/ui/specialization/issue-50452-fail.stderr +++ b/tests/ui/specialization/issue-50452-fail.stderr @@ -19,6 +19,6 @@ LL | impl Foo for T { | = note: to specialize, `foo` in the parent `impl` must be marked `default` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/issue-51892.stderr b/tests/ui/specialization/issue-51892.stderr index cb46db83606b2..9553a04c8f6bf 100644 --- a/tests/ui/specialization/issue-51892.stderr +++ b/tests/ui/specialization/issue-51892.stderr @@ -6,5 +6,5 @@ LL | type Type = [u8; std::mem::size_of::<::Type>()]; | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<::Type>()]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/issue-52050.stderr b/tests/ui/specialization/issue-52050.stderr index 85aac16f6d036..3b0cac5146438 100644 --- a/tests/ui/specialization/issue-52050.stderr +++ b/tests/ui/specialization/issue-52050.stderr @@ -21,6 +21,6 @@ LL | impl IntoPyDictPointer for () | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/issue-59435.stderr b/tests/ui/specialization/issue-59435.stderr index e8a12e4d928e1..60522e0f587b6 100644 --- a/tests/ui/specialization/issue-59435.stderr +++ b/tests/ui/specialization/issue-59435.stderr @@ -15,6 +15,6 @@ LL + #[derive(Default)] LL | struct MyStruct {} | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr index 833f61dca8cac..0ecec03a023eb 100644 --- a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr +++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `MissingType` in this scope LL | err: MissingType | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr index 83f311efd39d7..def4a413af111 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr @@ -10,5 +10,5 @@ note: required by a bound in `S` LL | struct S; | ^^^^^^^^^^^^^^ required by this bound in `S` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr b/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr index b032ccbe53ffc..85b492c0503b2 100644 --- a/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr +++ b/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `NonExistent` in this scope LL | impl Trait for NonExistent {} | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr b/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr index 934103d49dc0e..553bee2d2dd97 100644 --- a/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr +++ b/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr @@ -6,5 +6,5 @@ LL | impl specialization_trait::SpecTrait for A { | = help: add `#![feature(min_specialization)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/repeated_projection_type.stderr b/tests/ui/specialization/min_specialization/repeated_projection_type.stderr index a751ba793472e..01fd04dd3d021 100644 --- a/tests/ui/specialization/min_specialization/repeated_projection_type.stderr +++ b/tests/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -4,5 +4,5 @@ error: cannot specialize on associated type `::This == (I,)` LL | impl> X for V { | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr b/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr index 16dccb10b4530..d80ee7b579d04 100644 --- a/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr +++ b/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr @@ -4,5 +4,5 @@ error: specializing impl repeats parameter `'a` LL | impl<'a> X for (&'a u8, &'a u8) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/repeating_param.stderr b/tests/ui/specialization/min_specialization/repeating_param.stderr index 5e6adf723b54e..90ec4b945e05f 100644 --- a/tests/ui/specialization/min_specialization/repeating_param.stderr +++ b/tests/ui/specialization/min_specialization/repeating_param.stderr @@ -4,5 +4,5 @@ error: specializing impl repeats parameter `T` LL | impl X for (T, T) { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr index ba9d6bbe30011..42c0de85e52f0 100644 --- a/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr +++ b/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr @@ -4,5 +4,5 @@ error: cannot specialize on trait `HasMethod` LL | impl Spec for T { | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/specialization_super_trait.stderr b/tests/ui/specialization/min_specialization/specialization_super_trait.stderr index e935786624b4b..1fc064a0a3df7 100644 --- a/tests/ui/specialization/min_specialization/specialization_super_trait.stderr +++ b/tests/ui/specialization/min_specialization/specialization_super_trait.stderr @@ -4,5 +4,5 @@ error: cannot specialize on trait `Default` LL | impl SpecMarker for T { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/specialize_nothing.stderr b/tests/ui/specialization/min_specialization/specialize_nothing.stderr index 65f73781cae22..8e7dc9c5ef3f4 100644 --- a/tests/ui/specialization/min_specialization/specialize_nothing.stderr +++ b/tests/ui/specialization/min_specialization/specialize_nothing.stderr @@ -10,5 +10,5 @@ note: impl is a specialization of this impl LL | impl Special for T { | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/specialize_on_static.stderr b/tests/ui/specialization/min_specialization/specialize_on_static.stderr index 9a16798f15cd1..8c2bf6c2da09d 100644 --- a/tests/ui/specialization/min_specialization/specialize_on_static.stderr +++ b/tests/ui/specialization/min_specialization/specialize_on_static.stderr @@ -4,5 +4,5 @@ error: cannot specialize on `'static` lifetime LL | impl X for &'static u8 { | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/specialize_on_trait.stderr b/tests/ui/specialization/min_specialization/specialize_on_trait.stderr index 7b79c7eb4ad1c..c86b4ac3915c7 100644 --- a/tests/ui/specialization/min_specialization/specialize_on_trait.stderr +++ b/tests/ui/specialization/min_specialization/specialize_on_trait.stderr @@ -4,5 +4,5 @@ error: cannot specialize on trait `SpecMarker` LL | impl X for T { | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/min_specialization/specialize_on_type_error.stderr b/tests/ui/specialization/min_specialization/specialize_on_type_error.stderr index cc12302bd8cf1..1686f6f0cd67b 100644 --- a/tests/ui/specialization/min_specialization/specialize_on_type_error.stderr +++ b/tests/ui/specialization/min_specialization/specialize_on_type_error.stderr @@ -7,6 +7,6 @@ LL | type Assoc: Y; LL | impl Z for A {} | ^^^^^^^^^^^^^^^^^^^^^ missing `Assoc` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.coherence.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.coherence.stderr index 578db0cc65e89..e9498a003179b 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.coherence.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.coherence.stderr @@ -7,6 +7,6 @@ LL | impl Overlap for u32 { LL | impl Overlap for ::Id { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr index 578db0cc65e89..e9498a003179b 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -7,6 +7,6 @@ LL | impl Overlap for u32 { LL | impl Overlap for ::Id { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-feature-gate-default.stderr b/tests/ui/specialization/specialization-feature-gate-default.stderr index 42dbb200c247e..35e5e3bc51253 100644 --- a/tests/ui/specialization/specialization-feature-gate-default.stderr +++ b/tests/ui/specialization/specialization-feature-gate-default.stderr @@ -7,6 +7,6 @@ LL | default fn foo(&self) {} = note: see issue #31844 for more information = help: add `#![feature(specialization)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/specialization/specialization-feature-gate-overlap.stderr b/tests/ui/specialization/specialization-feature-gate-overlap.stderr index 9157ad0d46a1a..f42289fb96287 100644 --- a/tests/ui/specialization/specialization-feature-gate-overlap.stderr +++ b/tests/ui/specialization/specialization-feature-gate-overlap.stderr @@ -7,6 +7,6 @@ LL | impl Foo for T { LL | impl Foo for u8 { | ^^^^^^^^^^^^^^^ conflicting implementation for `u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-overlap-hygiene.stderr b/tests/ui/specialization/specialization-overlap-hygiene.stderr index 81efd46cc7fa5..b143f888f235a 100644 --- a/tests/ui/specialization/specialization-overlap-hygiene.stderr +++ b/tests/ui/specialization/specialization-overlap-hygiene.stderr @@ -7,6 +7,6 @@ LL | fn f() {} LL | fn f() {} | ^^^^^^ duplicate definitions for `f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/specialization/specialization-overlap-negative.stderr b/tests/ui/specialization/specialization-overlap-negative.stderr index 1fe4869ff548d..a8e99953e2b65 100644 --- a/tests/ui/specialization/specialization-overlap-negative.stderr +++ b/tests/ui/specialization/specialization-overlap-negative.stderr @@ -16,6 +16,6 @@ LL | unsafe impl Send for TestType {} LL | impl !Send for TestType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr index ff733822cab98..f85b3c6eb665e 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr @@ -6,6 +6,6 @@ LL | use core::unicode::UNICODE_VERSION; | = help: add `#![feature(unicode_internals)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr index 132c00b89b229..f09289bfb898f 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.stderr +++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr @@ -7,6 +7,6 @@ LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowe = note: see issue #1 for more information = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr index 6d8b01a549523..232de41c769e2 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr @@ -4,5 +4,5 @@ error: feature `const_bar` implying `const_foobar` does not exist LL | #[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr index 8ef5a364ecc45..0a5f58288fa33 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr @@ -6,5 +6,5 @@ LL | foobar(); | = help: add `#![feature(const_foobar)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.stderr index f6a099cd25e7a..050834ab67609 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.stderr @@ -18,5 +18,5 @@ help: if you are using features which are now stable, remove this line LL - #![feature(const_foo)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.stderr index 0638566765822..50cc14c3b4f65 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-using-unstable.stderr @@ -18,5 +18,5 @@ help: if you are using features which are now stable, remove this line LL - #![feature(const_foo)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/generics-default-stability-where.stderr b/tests/ui/stability-attribute/generics-default-stability-where.stderr index 61253adc892b9..ce34f96771c42 100644 --- a/tests/ui/stability-attribute/generics-default-stability-where.stderr +++ b/tests/ui/stability-attribute/generics-default-stability-where.stderr @@ -6,6 +6,6 @@ LL | impl Trait3 for T where T: Trait2 { | = help: add `#![feature(unstable_default)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/issue-28075.stderr b/tests/ui/stability-attribute/issue-28075.stderr index 7e53bb54457a4..e16eae88b01d2 100644 --- a/tests/ui/stability-attribute/issue-28075.stderr +++ b/tests/ui/stability-attribute/issue-28075.stderr @@ -6,6 +6,6 @@ LL | use lint_stability::{unstable, deprecated}; | = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/issue-28388-3.stderr b/tests/ui/stability-attribute/issue-28388-3.stderr index d2e46683b9034..0fb62ece31360 100644 --- a/tests/ui/stability-attribute/issue-28388-3.stderr +++ b/tests/ui/stability-attribute/issue-28388-3.stderr @@ -6,6 +6,6 @@ LL | use lint_stability::UnstableEnum::{}; | = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr index c7ade234d3dcc..3af1e82d207a5 100644 --- a/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr +++ b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr @@ -7,5 +7,5 @@ LL | | LL | | fn main() {} | |____________^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/stability-attribute-implies-missing.stderr index ff1856f1763f9..63890092ebcb1 100644 --- a/tests/ui/stability-attribute/stability-attribute-implies-missing.stderr +++ b/tests/ui/stability-attribute/stability-attribute-implies-missing.stderr @@ -4,5 +4,5 @@ error: feature `bar` implying `foobar` does not exist LL | #[unstable(feature = "foobar", issue = "1", implied_by = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/stability-attribute-implies-using-stable.stderr b/tests/ui/stability-attribute/stability-attribute-implies-using-stable.stderr index c9b3f07cc70b1..d783f1e8e4044 100644 --- a/tests/ui/stability-attribute/stability-attribute-implies-using-stable.stderr +++ b/tests/ui/stability-attribute/stability-attribute-implies-using-stable.stderr @@ -18,5 +18,5 @@ help: if you are using features which are now stable, remove this line LL - #![feature(foo)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr b/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr index 9a5c7ef5a4762..4940650fd4261 100644 --- a/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr +++ b/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr @@ -18,5 +18,5 @@ help: if you are using features which are now stable, remove this line LL - #![feature(foo)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr index b1c56ef224ae7..a6d1ebf29458e 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr +++ b/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr @@ -6,5 +6,5 @@ LL | | () => () LL | | } | |_^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/stability-attribute/stability-in-private-module.stderr b/tests/ui/stability-attribute/stability-in-private-module.stderr index cc8758714fc92..9eb4d3efc8bd2 100644 --- a/tests/ui/stability-attribute/stability-in-private-module.stderr +++ b/tests/ui/stability-attribute/stability-in-private-module.stderr @@ -9,6 +9,6 @@ LL | let _ = std::thread::thread_info::current_thread(); note: the module `thread_info` is defined here --> $SRC_DIR/std/src/thread/mod.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/stability-attribute/unresolved_stability_lint.stderr b/tests/ui/stability-attribute/unresolved_stability_lint.stderr index 11d6abcaf361f..51780d2088099 100644 --- a/tests/ui/stability-attribute/unresolved_stability_lint.stderr +++ b/tests/ui/stability-attribute/unresolved_stability_lint.stderr @@ -4,6 +4,6 @@ error[E0405]: cannot find trait `Foo` in this scope LL | impl Foo for () {} | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/static/bad-const-type.stderr b/tests/ui/static/bad-const-type.stderr index 2e930f4596e04..807cd2f7a25a7 100644 --- a/tests/ui/static/bad-const-type.stderr +++ b/tests/ui/static/bad-const-type.stderr @@ -6,6 +6,6 @@ LL | static i: String = 10; | | | expected `String`, found integer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/static/issue-18118-2.stderr b/tests/ui/static/issue-18118-2.stderr index 4fc3ca78f961c..6231a276f9913 100644 --- a/tests/ui/static/issue-18118-2.stderr +++ b/tests/ui/static/issue-18118-2.stderr @@ -6,6 +6,6 @@ LL | &p | = help: consider extracting the value of the `static` to a `const`, and referring to that -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/static/issue-18118.stderr b/tests/ui/static/issue-18118.stderr index 035be2b1202fd..1c53abaa29507 100644 --- a/tests/ui/static/issue-18118.stderr +++ b/tests/ui/static/issue-18118.stderr @@ -11,6 +11,6 @@ LL | &p LL | }; | - `p` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/static/static-closures.stderr b/tests/ui/static/static-closures.stderr index 99235e26e15e7..b11c0b5a530c5 100644 --- a/tests/ui/static/static-closures.stderr +++ b/tests/ui/static/static-closures.stderr @@ -4,6 +4,6 @@ error[E0697]: closures cannot be static LL | static || {}; | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0697`. diff --git a/tests/ui/static/static-items-cant-move.stderr b/tests/ui/static/static-items-cant-move.stderr index 235e9ee9b919d..1361e7089e834 100644 --- a/tests/ui/static/static-items-cant-move.stderr +++ b/tests/ui/static/static-items-cant-move.stderr @@ -4,6 +4,6 @@ error[E0507]: cannot move out of static item `BAR` LL | test(BAR); | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/static/static-lifetime-bound.stderr b/tests/ui/static/static-lifetime-bound.stderr index 19e55a6582e86..8b0d3a0bf4cf4 100644 --- a/tests/ui/static/static-lifetime-bound.stderr +++ b/tests/ui/static/static-lifetime-bound.stderr @@ -11,6 +11,6 @@ LL | f(&x); LL | } | - `x` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr index 4af3370c79944..8c9434ce3cb0b 100644 --- a/tests/ui/static/static-lifetime.stderr +++ b/tests/ui/static/static-lifetime.stderr @@ -11,6 +11,6 @@ LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} | ^^ = note: but lifetime parameter must outlive the static lifetime -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/static/static-method-privacy.stderr b/tests/ui/static/static-method-privacy.stderr index 4be1b22fc6b4f..3c77b9000fd11 100644 --- a/tests/ui/static/static-method-privacy.stderr +++ b/tests/ui/static/static-method-privacy.stderr @@ -7,6 +7,6 @@ LL | fn new() -> S { S } LL | let _ = a::S::new(); | ^^^ private associated function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/static/static-mut-bad-types.stderr b/tests/ui/static/static-mut-bad-types.stderr index 983e1026f91e9..f71701ca7a401 100644 --- a/tests/ui/static/static-mut-bad-types.stderr +++ b/tests/ui/static/static-mut-bad-types.stderr @@ -7,6 +7,6 @@ LL | static mut a: isize = 3; LL | a = true; | ^^^^ expected `isize`, found `bool` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/static/static-mut-not-constant.stderr b/tests/ui/static/static-mut-not-constant.stderr index 8411a1557b4f1..d125bec594359 100644 --- a/tests/ui/static/static-mut-not-constant.stderr +++ b/tests/ui/static/static-mut-not-constant.stderr @@ -7,6 +7,6 @@ LL | static mut a: Box = Box::new(3); = note: calls in statics are limited to constant functions, tuple structs and tuple variants = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/static/static-reference-to-fn-1.stderr b/tests/ui/static/static-reference-to-fn-1.stderr index 86c4eaa7eb432..ce9b6a739cfcc 100644 --- a/tests/ui/static/static-reference-to-fn-1.stderr +++ b/tests/ui/static/static-reference-to-fn-1.stderr @@ -12,6 +12,6 @@ help: consider casting to a fn pointer LL | func: &(foo as fn() -> Option), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/static/static-region-bound.stderr b/tests/ui/static/static-region-bound.stderr index 1a607e3c014a3..a47c94571022d 100644 --- a/tests/ui/static/static-region-bound.stderr +++ b/tests/ui/static/static-region-bound.stderr @@ -8,6 +8,6 @@ LL | f(x); LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/static/static-vec-repeat-not-constant.stderr b/tests/ui/static/static-vec-repeat-not-constant.stderr index dec0123184d70..db0c7eb8d35f1 100644 --- a/tests/ui/static/static-vec-repeat-not-constant.stderr +++ b/tests/ui/static/static-vec-repeat-not-constant.stderr @@ -7,6 +7,6 @@ LL | static a: [isize; 2] = [foo(); 2]; = note: calls in statics are limited to constant functions, tuple structs and tuple variants = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/statics/issue-14227.mir.stderr b/tests/ui/statics/issue-14227.mir.stderr index 8e7a2514dd6ab..ab50b97d63f4f 100644 --- a/tests/ui/statics/issue-14227.mir.stderr +++ b/tests/ui/statics/issue-14227.mir.stderr @@ -6,6 +6,6 @@ LL | static CRASH: u32 = symbol; | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/statics/issue-14227.thir.stderr b/tests/ui/statics/issue-14227.thir.stderr index 8e7a2514dd6ab..ab50b97d63f4f 100644 --- a/tests/ui/statics/issue-14227.thir.stderr +++ b/tests/ui/statics/issue-14227.thir.stderr @@ -6,6 +6,6 @@ LL | static CRASH: u32 = symbol; | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/statics/issue-17718-static-sync.stderr b/tests/ui/statics/issue-17718-static-sync.stderr index bc6e45e59258f..96f894146c5ff 100644 --- a/tests/ui/statics/issue-17718-static-sync.stderr +++ b/tests/ui/statics/issue-17718-static-sync.stderr @@ -7,6 +7,6 @@ LL | static BAR: Foo = Foo; = help: the trait `Sync` is not implemented for `Foo` = note: shared static variables must have a type that implements `Sync` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/statics/issue-44373.stderr b/tests/ui/statics/issue-44373.stderr index 2d29dec888e8d..3bbcfdd853479 100644 --- a/tests/ui/statics/issue-44373.stderr +++ b/tests/ui/statics/issue-44373.stderr @@ -8,6 +8,6 @@ LL | let _val: &'static [&'static u32] = &[&FOO]; LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index 813e65e45a255..e6da83296ce16 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -21,31 +21,31 @@ ast-stats-1 - Local 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.5%) 3 ast-stats-1 Param 160 ( 2.5%) 4 40 -ast-stats-1 Block 192 ( 3.0%) 6 32 +ast-stats-1 Block 192 ( 2.9%) 6 32 ast-stats-1 Variant 208 ( 3.2%) 2 104 -ast-stats-1 GenericBound 224 ( 3.5%) 4 56 -ast-stats-1 - Trait 224 ( 3.5%) 4 +ast-stats-1 GenericBound 256 ( 3.9%) 4 64 +ast-stats-1 - Trait 256 ( 3.9%) 4 ast-stats-1 AssocItem 352 ( 5.4%) 4 88 ast-stats-1 - Type 176 ( 2.7%) 2 ast-stats-1 - Fn 176 ( 2.7%) 2 ast-stats-1 GenericParam 480 ( 7.4%) 5 96 -ast-stats-1 Pat 504 ( 7.8%) 7 72 +ast-stats-1 Pat 504 ( 7.7%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 ast-stats-1 - Ident 360 ( 5.5%) 5 -ast-stats-1 Expr 576 ( 8.9%) 8 72 +ast-stats-1 Expr 576 ( 8.8%) 8 72 ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Lit 144 ( 2.2%) 2 ast-stats-1 - Block 216 ( 3.3%) 3 -ast-stats-1 PathSegment 720 (11.1%) 30 24 -ast-stats-1 Ty 896 (13.8%) 14 64 +ast-stats-1 PathSegment 720 (11.0%) 30 24 +ast-stats-1 Ty 896 (13.7%) 14 64 ast-stats-1 - Ptr 64 ( 1.0%) 1 ast-stats-1 - Ref 64 ( 1.0%) 1 ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2 -ast-stats-1 - Path 640 ( 9.9%) 10 -ast-stats-1 Item 1_224 (18.9%) 9 136 +ast-stats-1 - Path 640 ( 9.8%) 10 +ast-stats-1 Item 1_224 (18.8%) 9 136 ast-stats-1 - Trait 136 ( 2.1%) 1 ast-stats-1 - Enum 136 ( 2.1%) 1 ast-stats-1 - ForeignMod 136 ( 2.1%) 1 @@ -53,7 +53,7 @@ ast-stats-1 - Impl 136 ( 2.1%) 1 ast-stats-1 - Fn 272 ( 4.2%) 2 ast-stats-1 - Use 408 ( 6.3%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_488 +ast-stats-1 Total 6_520 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -65,28 +65,28 @@ ast-stats-2 ExprField 48 ( 0.7%) 1 48 ast-stats-2 WherePredicate 56 ( 0.8%) 1 56 ast-stats-2 - BoundPredicate 56 ( 0.8%) 1 ast-stats-2 Local 72 ( 1.0%) 1 72 -ast-stats-2 Arm 96 ( 1.4%) 2 48 -ast-stats-2 ForeignItem 96 ( 1.4%) 1 96 -ast-stats-2 - Fn 96 ( 1.4%) 1 +ast-stats-2 Arm 96 ( 1.3%) 2 48 +ast-stats-2 ForeignItem 96 ( 1.3%) 1 96 +ast-stats-2 - Fn 96 ( 1.3%) 1 ast-stats-2 InlineAsm 120 ( 1.7%) 1 120 ast-stats-2 FnDecl 120 ( 1.7%) 5 24 ast-stats-2 Attribute 128 ( 1.8%) 4 32 -ast-stats-2 - DocComment 32 ( 0.5%) 1 -ast-stats-2 - Normal 96 ( 1.4%) 3 -ast-stats-2 FieldDef 160 ( 2.3%) 2 80 -ast-stats-2 Stmt 160 ( 2.3%) 5 32 -ast-stats-2 - Local 32 ( 0.5%) 1 -ast-stats-2 - Semi 32 ( 0.5%) 1 -ast-stats-2 - Expr 96 ( 1.4%) 3 -ast-stats-2 Param 160 ( 2.3%) 4 40 +ast-stats-2 - DocComment 32 ( 0.4%) 1 +ast-stats-2 - Normal 96 ( 1.3%) 3 +ast-stats-2 FieldDef 160 ( 2.2%) 2 80 +ast-stats-2 Stmt 160 ( 2.2%) 5 32 +ast-stats-2 - Local 32 ( 0.4%) 1 +ast-stats-2 - Semi 32 ( 0.4%) 1 +ast-stats-2 - Expr 96 ( 1.3%) 3 +ast-stats-2 Param 160 ( 2.2%) 4 40 ast-stats-2 Block 192 ( 2.7%) 6 32 ast-stats-2 Variant 208 ( 2.9%) 2 104 -ast-stats-2 GenericBound 224 ( 3.2%) 4 56 -ast-stats-2 - Trait 224 ( 3.2%) 4 -ast-stats-2 AssocItem 352 ( 5.0%) 4 88 +ast-stats-2 GenericBound 256 ( 3.6%) 4 64 +ast-stats-2 - Trait 256 ( 3.6%) 4 +ast-stats-2 AssocItem 352 ( 4.9%) 4 88 ast-stats-2 - Type 176 ( 2.5%) 2 ast-stats-2 - Fn 176 ( 2.5%) 2 -ast-stats-2 GenericParam 480 ( 6.8%) 5 96 +ast-stats-2 GenericParam 480 ( 6.7%) 5 96 ast-stats-2 Pat 504 ( 7.1%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 @@ -98,22 +98,22 @@ ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Lit 144 ( 2.0%) 2 ast-stats-2 - Block 216 ( 3.0%) 3 -ast-stats-2 PathSegment 792 (11.2%) 33 24 +ast-stats-2 PathSegment 792 (11.1%) 33 24 ast-stats-2 Ty 896 (12.6%) 14 64 ast-stats-2 - Ptr 64 ( 0.9%) 1 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2 ast-stats-2 - Path 640 ( 9.0%) 10 -ast-stats-2 Item 1_496 (21.1%) 11 136 +ast-stats-2 Item 1_496 (21.0%) 11 136 ast-stats-2 - Trait 136 ( 1.9%) 1 ast-stats-2 - Enum 136 ( 1.9%) 1 ast-stats-2 - ExternCrate 136 ( 1.9%) 1 ast-stats-2 - ForeignMod 136 ( 1.9%) 1 ast-stats-2 - Impl 136 ( 1.9%) 1 ast-stats-2 - Fn 272 ( 3.8%) 2 -ast-stats-2 - Use 544 ( 7.7%) 4 +ast-stats-2 - Use 544 ( 7.6%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_088 +ast-stats-2 Total 7_120 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size diff --git a/tests/ui/str/str-as-char.stderr b/tests/ui/str/str-as-char.stderr index c3cb488e3d1bb..44ec079e92918 100644 --- a/tests/ui/str/str-as-char.stderr +++ b/tests/ui/str/str-as-char.stderr @@ -9,5 +9,5 @@ help: if you meant to write a `str` literal, use double quotes LL | println!("●●"); | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/str/str-concat-on-double-ref.stderr b/tests/ui/str/str-concat-on-double-ref.stderr index bd354679f7888..85a1db8adcc80 100644 --- a/tests/ui/str/str-concat-on-double-ref.stderr +++ b/tests/ui/str/str-concat-on-double-ref.stderr @@ -13,6 +13,6 @@ help: create an owned `String` from a string reference LL | let c = a.to_owned() + b; | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr index e0a8225507e5a..e34eb04bc04fa 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum Foo { X(Mutex>>) } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr index ecf072b8e8aea..792ef4428e3ec 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum Foo { Voo(Option>>) } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/issue-103869.stderr b/tests/ui/structs-enums/issue-103869.stderr index 4665ebf89a3c9..2334e5e9712c4 100644 --- a/tests/ui/structs-enums/issue-103869.stderr +++ b/tests/ui/structs-enums/issue-103869.stderr @@ -13,5 +13,5 @@ help: perhaps you meant to use `struct` here LL | struct VecOrMap { | ~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/structs-enums/issue-2718-a.stderr b/tests/ui/structs-enums/issue-2718-a.stderr index 7ea620f386a20..4253fae03c078 100644 --- a/tests/ui/structs-enums/issue-2718-a.stderr +++ b/tests/ui/structs-enums/issue-2718-a.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | pub struct Pong(Box>); | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/issue-3008-1.stderr b/tests/ui/structs-enums/issue-3008-1.stderr index be25b9091d589..d7464dc56a749 100644 --- a/tests/ui/structs-enums/issue-3008-1.stderr +++ b/tests/ui/structs-enums/issue-3008-1.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | BarSome(Box) | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/issue-3008-2.stderr b/tests/ui/structs-enums/issue-3008-2.stderr index 858a8fd6af808..4ed1c1816eacf 100644 --- a/tests/ui/structs-enums/issue-3008-2.stderr +++ b/tests/ui/structs-enums/issue-3008-2.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | struct Bar { x: Box } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/issue-3008-3.stderr b/tests/ui/structs-enums/issue-3008-3.stderr index a1a81e2936775..9358060a87b30 100644 --- a/tests/ui/structs-enums/issue-3008-3.stderr +++ b/tests/ui/structs-enums/issue-3008-3.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum E2 { V2(Box>, marker::PhantomData), } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr index 2f3a150e5cba9..664a00e3303e0 100644 --- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr +++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr @@ -9,5 +9,5 @@ help: to omit remaining fields, use `..` LL | if let Some(Foo::Bar {..}) = foo {} | ~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr index e3af8976cee91..b28c3de241796 100644 --- a/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | struct Foo { foo: Option>> } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr index 39a99ec1ef739..cdf51632acd0e 100644 --- a/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr @@ -15,6 +15,6 @@ LL | LL ~ struct Foo { q: Option> } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr index 394134c78556b..e788b2ed0f8aa 100644 --- a/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | struct Foo { foo: Mutex>> } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr index 3d141e44babf4..3208effc00030 100644 --- a/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | struct Foo { foo: Option>>>, marker: marker::PhantomData } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr index 44a90a6fe3898..1b943bf895697 100644 --- a/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr @@ -9,6 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | struct Bar { x: Box> , marker: marker::PhantomData } | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-74224.stderr b/tests/ui/structs-enums/struct-rec/issue-74224.stderr index f1d50bc8af5ac..550b078a6a292 100644 --- a/tests/ui/structs-enums/struct-rec/issue-74224.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-74224.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | y: Box>>, | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-84611.stderr b/tests/ui/structs-enums/struct-rec/issue-84611.stderr index 536f54e3e9611..2d971cfc8b6fa 100644 --- a/tests/ui/structs-enums/struct-rec/issue-84611.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-84611.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | x: Box>, | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs/incomplete-fn-in-struct-definition.stderr b/tests/ui/structs/incomplete-fn-in-struct-definition.stderr index 0d12ba9c91688..15850962bbc51 100644 --- a/tests/ui/structs/incomplete-fn-in-struct-definition.stderr +++ b/tests/ui/structs/incomplete-fn-in-struct-definition.stderr @@ -11,5 +11,5 @@ help: escape `fn` to use it as an identifier LL | r#fn: u8 | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/structs/issue-80853.stderr b/tests/ui/structs/issue-80853.stderr index 1c7d52b6d6054..9930efab730ac 100644 --- a/tests/ui/structs/issue-80853.stderr +++ b/tests/ui/structs/issue-80853.stderr @@ -8,6 +8,6 @@ LL | thing(); | | | call expression requires function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/structs/method-chain-expression-failure.rs b/tests/ui/structs/method-chain-expression-failure.rs new file mode 100644 index 0000000000000..43ebc5bac8cbe --- /dev/null +++ b/tests/ui/structs/method-chain-expression-failure.rs @@ -0,0 +1,31 @@ +struct A; +struct B; +struct C; +struct D; +struct E; + +impl A { + fn b(&self) -> B { B } + fn foo(&self) {} +} + +impl B { + fn c(&self) -> C { C } +} + +impl C { + fn d(&self) -> D { D } + fn foo(&self) {} +} + +impl D { + fn e(&self) -> E { E } +} + +impl E { + fn f(&self) {} +} +fn main() { + A.b().c().d().e().foo(); +//~^ ERROR no method named `foo` found for struct `E` in the current scope +} diff --git a/tests/ui/structs/method-chain-expression-failure.stderr b/tests/ui/structs/method-chain-expression-failure.stderr new file mode 100644 index 0000000000000..a0bcef6b0310e --- /dev/null +++ b/tests/ui/structs/method-chain-expression-failure.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `foo` found for struct `E` in the current scope + --> $DIR/method-chain-expression-failure.rs:29:23 + | +LL | struct E; + | -------- method `foo` not found for this struct +... +LL | A.b().c().d().e().foo(); + | - --- ^^^ method not found in `E` + | | | + | | method `foo` is available on `&C` + | method `foo` is available on `&A` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/structs/multi-line-fru-suggestion.stderr b/tests/ui/structs/multi-line-fru-suggestion.stderr index 8bbd3ace7d29e..5b4b532fcaa0c 100644 --- a/tests/ui/structs/multi-line-fru-suggestion.stderr +++ b/tests/ui/structs/multi-line-fru-suggestion.stderr @@ -20,6 +20,6 @@ help: to set the remaining fields from `Default::default()`, separate the last n LL | }, | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/structs/struct-duplicate-comma.stderr b/tests/ui/structs/struct-duplicate-comma.stderr index 834b3c5c17164..4ac3fc9fe6b24 100644 --- a/tests/ui/structs/struct-duplicate-comma.stderr +++ b/tests/ui/structs/struct-duplicate-comma.stderr @@ -9,5 +9,5 @@ LL | a: 0,, | expected identifier | help: remove this comma -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/structs/struct-fields-decl-dupe.stderr b/tests/ui/structs/struct-fields-decl-dupe.stderr index d7ce9bb892260..3c25708a3de17 100644 --- a/tests/ui/structs/struct-fields-decl-dupe.stderr +++ b/tests/ui/structs/struct-fields-decl-dupe.stderr @@ -6,6 +6,6 @@ LL | foo: isize, LL | foo: isize, | ^^^^^^^^^^ field already declared -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/structs/struct-fields-dupe.stderr b/tests/ui/structs/struct-fields-dupe.stderr index aaf2533dc011a..ee38743471f6f 100644 --- a/tests/ui/structs/struct-fields-dupe.stderr +++ b/tests/ui/structs/struct-fields-dupe.stderr @@ -6,6 +6,6 @@ LL | foo: 0, LL | foo: 0 | ^^^ used more than once -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0062`. diff --git a/tests/ui/structs/struct-fields-hints-no-dupe.stderr b/tests/ui/structs/struct-fields-hints-no-dupe.stderr index 1a88f269347c2..2b88d802833c3 100644 --- a/tests/ui/structs/struct-fields-hints-no-dupe.stderr +++ b/tests/ui/structs/struct-fields-hints-no-dupe.stderr @@ -2,8 +2,13 @@ error[E0560]: struct `A` has no field named `bar` --> $DIR/struct-fields-hints-no-dupe.rs:10:9 | LL | bar : 42, - | ^^^ help: a field with a similar name exists: `barr` + | ^^^ unknown field + | +help: a field with a similar name exists + | +LL | barr : 42, + | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/struct-fields-hints.stderr b/tests/ui/structs/struct-fields-hints.stderr index 3b8a2b5c7bad0..8217d7a6e811d 100644 --- a/tests/ui/structs/struct-fields-hints.stderr +++ b/tests/ui/structs/struct-fields-hints.stderr @@ -2,8 +2,13 @@ error[E0560]: struct `A` has no field named `bar` --> $DIR/struct-fields-hints.rs:10:9 | LL | bar : 42, - | ^^^ help: a field with a similar name exists: `car` + | ^^^ unknown field + | +help: a field with a similar name exists + | +LL | car : 42, + | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/struct-fields-missing.stderr b/tests/ui/structs/struct-fields-missing.stderr index b3e42a94809d7..eba095fd35a32 100644 --- a/tests/ui/structs/struct-fields-missing.stderr +++ b/tests/ui/structs/struct-fields-missing.stderr @@ -4,6 +4,6 @@ error[E0063]: missing field `bar` in initializer of `BuildData` LL | let foo = BuildData { | ^^^^^^^^^ missing `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/structs/struct-fields-shorthand-unresolved.stderr b/tests/ui/structs/struct-fields-shorthand-unresolved.stderr index 09fc4f7ee586a..b485c17c1b270 100644 --- a/tests/ui/structs/struct-fields-shorthand-unresolved.stderr +++ b/tests/ui/structs/struct-fields-shorthand-unresolved.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `y` in this scope LL | y | ^ help: a local variable with a similar name exists: `x` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/structs/struct-fields-shorthand.stderr b/tests/ui/structs/struct-fields-shorthand.stderr index d89d45b39033a..c4d804aaf9d8c 100644 --- a/tests/ui/structs/struct-fields-shorthand.stderr +++ b/tests/ui/structs/struct-fields-shorthand.stderr @@ -6,6 +6,6 @@ LL | x, y, z | = note: all struct fields are already assigned -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/struct-fields-too-many.stderr b/tests/ui/structs/struct-fields-too-many.stderr index 9342607ebce25..838917474e6c5 100644 --- a/tests/ui/structs/struct-fields-too-many.stderr +++ b/tests/ui/structs/struct-fields-too-many.stderr @@ -6,6 +6,6 @@ LL | bar: 0 | = note: all struct fields are already assigned -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/struct-fields-typo.stderr b/tests/ui/structs/struct-fields-typo.stderr index 6949a0a4a6828..d87bace727736 100644 --- a/tests/ui/structs/struct-fields-typo.stderr +++ b/tests/ui/structs/struct-fields-typo.stderr @@ -2,8 +2,13 @@ error[E0609]: no field `baa` on type `BuildData` --> $DIR/struct-fields-typo.rs:11:17 | LL | let x = foo.baa; - | ^^^ help: a field with a similar name exists: `bar` + | ^^^ unknown field + | +help: a field with a similar name exists + | +LL | let x = foo.bar; + | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/structs/struct-missing-comma.stderr b/tests/ui/structs/struct-missing-comma.stderr index eceec65e76346..4fdd47a480651 100644 --- a/tests/ui/structs/struct-missing-comma.stderr +++ b/tests/ui/structs/struct-missing-comma.stderr @@ -4,5 +4,5 @@ error: expected `,`, or `}`, found keyword `pub` LL | pub foo: u32 | ^ help: try adding a comma: `,` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/structs/struct-pat-derived-error.stderr b/tests/ui/structs/struct-pat-derived-error.stderr index a91e47657ab91..78bb018cb4be7 100644 --- a/tests/ui/structs/struct-pat-derived-error.stderr +++ b/tests/ui/structs/struct-pat-derived-error.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `d` on type `&A` --> $DIR/struct-pat-derived-error.rs:8:31 | LL | let A { x, y } = self.d; - | ^ help: a field with a similar name exists: `b` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | let A { x, y } = self.b; + | ~ error[E0026]: struct `A` does not have fields named `x`, `y` --> $DIR/struct-pat-derived-error.rs:8:17 diff --git a/tests/ui/structs/struct-path-alias-bounds.stderr b/tests/ui/structs/struct-path-alias-bounds.stderr index 5b01208c56fbf..621496bb43003 100644 --- a/tests/ui/structs/struct-path-alias-bounds.stderr +++ b/tests/ui/structs/struct-path-alias-bounds.stderr @@ -15,6 +15,6 @@ LL + #[derive(Clone)] LL | struct NoClone; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/structs/struct-path-self-type-mismatch.stderr b/tests/ui/structs/struct-path-self-type-mismatch.stderr index cddc1356194bf..bbe5bae29bbe1 100644 --- a/tests/ui/structs/struct-path-self-type-mismatch.stderr +++ b/tests/ui/structs/struct-path-self-type-mismatch.stderr @@ -24,7 +24,9 @@ error[E0308]: mismatched types --> $DIR/struct-path-self-type-mismatch.rs:13:9 | LL | impl Foo { - | - found type parameter + | - ------ this is the type of the `Self` literal + | | + | found type parameter LL | fn new(u: U) -> Foo { | - ------ expected `Foo` because of return type | | @@ -40,6 +42,10 @@ LL | | } found struct `Foo` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +help: use the type name directly + | +LL | Foo:: { + | ~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/structs/suggest-private-fields.stderr b/tests/ui/structs/suggest-private-fields.stderr index d628bd1620833..f67a4ed78e290 100644 --- a/tests/ui/structs/suggest-private-fields.stderr +++ b/tests/ui/structs/suggest-private-fields.stderr @@ -2,7 +2,12 @@ error[E0560]: struct `B` has no field named `aa` --> $DIR/suggest-private-fields.rs:15:9 | LL | aa: 20, - | ^^ help: a field with a similar name exists: `a` + | ^^ unknown field + | +help: a field with a similar name exists + | +LL | a: 20, + | ~ error[E0560]: struct `B` has no field named `bb` --> $DIR/suggest-private-fields.rs:17:9 @@ -16,13 +21,23 @@ error[E0560]: struct `A` has no field named `aa` --> $DIR/suggest-private-fields.rs:22:9 | LL | aa: 20, - | ^^ help: a field with a similar name exists: `a` + | ^^ unknown field + | +help: a field with a similar name exists + | +LL | a: 20, + | ~ error[E0560]: struct `A` has no field named `bb` --> $DIR/suggest-private-fields.rs:24:9 | LL | bb: 20, - | ^^ help: a field with a similar name exists: `b` + | ^^ unknown field + | +help: a field with a similar name exists + | +LL | b: 20, + | ~ error: aborting due to 4 previous errors diff --git a/tests/ui/structs/unresolved-struct-with-fru.stderr b/tests/ui/structs/unresolved-struct-with-fru.stderr index a5796a222256d..9902c3ed35711 100644 --- a/tests/ui/structs/unresolved-struct-with-fru.stderr +++ b/tests/ui/structs/unresolved-struct-with-fru.stderr @@ -4,6 +4,6 @@ error[E0422]: cannot find struct, variant or union type `Oops` in this scope LL | let s2 = Oops { a: 2, ..s1 }; | ^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/suggestions/abi-typo.stderr b/tests/ui/suggestions/abi-typo.stderr index 67a84f119f6c7..ea474e3212532 100644 --- a/tests/ui/suggestions/abi-typo.stderr +++ b/tests/ui/suggestions/abi-typo.stderr @@ -9,6 +9,6 @@ LL | extern "cdedl" fn cdedl() {} | = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/suggestions/as-ref-2.stderr b/tests/ui/suggestions/as-ref-2.stderr index e2129b4502abe..309285775374b 100644 --- a/tests/ui/suggestions/as-ref-2.stderr +++ b/tests/ui/suggestions/as-ref-2.stderr @@ -12,7 +12,16 @@ LL | let _y = foo; | note: `Option::::map` takes ownership of the receiver `self`, which moves `foo` --> $SRC_DIR/core/src/option.rs:LL:COL +help: you could `clone` the value and consume it, if the `Struct: Clone` trait bound could be satisfied + | +LL | let _x: Option = foo.clone().map(|s| bar(&s)); + | ++++++++ +help: consider annotating `Struct` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Struct; + | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/suggestions/assoc-const-as-field.stderr b/tests/ui/suggestions/assoc-const-as-field.stderr index 78e5634b2de2a..0f58ce65049e9 100644 --- a/tests/ui/suggestions/assoc-const-as-field.stderr +++ b/tests/ui/suggestions/assoc-const-as-field.stderr @@ -4,6 +4,6 @@ error[E0423]: expected value, found struct `Mod::Foo` LL | foo(Mod::Foo.Bar); | ^^^^^^^^- help: use the path separator to refer to an item: `::` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/suggestions/assoc-const-as-fn.stderr b/tests/ui/suggestions/assoc-const-as-fn.stderr index d55d968b600aa..69e9af726479e 100644 --- a/tests/ui/suggestions/assoc-const-as-fn.stderr +++ b/tests/ui/suggestions/assoc-const-as-fn.stderr @@ -9,6 +9,6 @@ help: consider further restricting this bound LL | pub fn foo(value: T) { | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/assoc-const-without-self.stderr b/tests/ui/suggestions/assoc-const-without-self.stderr index 05528d277be5b..5a9fba8a0e47b 100644 --- a/tests/ui/suggestions/assoc-const-without-self.stderr +++ b/tests/ui/suggestions/assoc-const-without-self.stderr @@ -9,6 +9,6 @@ help: consider using the associated constant on `Self` LL | Self::A_CONST | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/assoc-type-in-method-return.stderr b/tests/ui/suggestions/assoc-type-in-method-return.stderr index df3828ad411e1..f83da79097009 100644 --- a/tests/ui/suggestions/assoc-type-in-method-return.stderr +++ b/tests/ui/suggestions/assoc-type-in-method-return.stderr @@ -9,6 +9,6 @@ help: you might have meant to use the associated type LL | fn to_bla(&self) -> Self::Bla; | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/suggestions/bad-infer-in-trait-impl.stderr b/tests/ui/suggestions/bad-infer-in-trait-impl.stderr index 418690ff85fa2..d96ee33a9146d 100644 --- a/tests/ui/suggestions/bad-infer-in-trait-impl.stderr +++ b/tests/ui/suggestions/bad-infer-in-trait-impl.stderr @@ -9,6 +9,6 @@ help: use type parameters instead LL | fn bar(s: T) {} | +++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/suggestions/box-future-wrong-output.stderr b/tests/ui/suggestions/box-future-wrong-output.stderr index e0c57af25b3d2..6a232c3444d93 100644 --- a/tests/ui/suggestions/box-future-wrong-output.stderr +++ b/tests/ui/suggestions/box-future-wrong-output.stderr @@ -9,6 +9,6 @@ LL | let _: BoxFuture<'static, bool> = async {}.boxed(); = note: expected struct `Pin + Send + 'static)>>` found struct `Pin + Send>>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/boxed-variant-field.stderr b/tests/ui/suggestions/boxed-variant-field.stderr index 1adbc05406cbe..c5fe9630b9b6a 100644 --- a/tests/ui/suggestions/boxed-variant-field.stderr +++ b/tests/ui/suggestions/boxed-variant-field.stderr @@ -18,6 +18,6 @@ help: consider unboxing the value LL | Ty::List(elem) => foo(*elem), | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/call-boxed.stderr b/tests/ui/suggestions/call-boxed.stderr index 11823ff09d318..08fa1a698d6d0 100644 --- a/tests/ui/suggestions/call-boxed.stderr +++ b/tests/ui/suggestions/call-boxed.stderr @@ -15,6 +15,6 @@ help: use parentheses to call this closure LL | x = y(); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/call-on-missing.stderr b/tests/ui/suggestions/call-on-missing.stderr index ca9abc7e90689..1bab075dc9c1c 100644 --- a/tests/ui/suggestions/call-on-missing.stderr +++ b/tests/ui/suggestions/call-on-missing.stderr @@ -13,7 +13,7 @@ error[E0609]: no field `i` on type `fn() -> Foo {foo}` --> $DIR/call-on-missing.rs:16:9 | LL | foo.i; - | ^ + | ^ unknown field | help: use parentheses to call this function | @@ -62,7 +62,7 @@ LL | fn type_param Foo>(t: T) { | - type parameter 'T' declared here ... LL | t.i; - | ^ + | ^ unknown field | help: use parentheses to call this type parameter | diff --git a/tests/ui/suggestions/call-on-unimplemented-ctor.stderr b/tests/ui/suggestions/call-on-unimplemented-ctor.stderr index 58612cbfb239e..4124a0061726f 100644 --- a/tests/ui/suggestions/call-on-unimplemented-ctor.stderr +++ b/tests/ui/suggestions/call-on-unimplemented-ctor.stderr @@ -16,6 +16,6 @@ help: use parentheses to construct this tuple struct LL | insert_resource(Time(/* u32 */)); | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr index 167f7e592a97c..f20596a80a6f9 100644 --- a/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr +++ b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr @@ -16,6 +16,6 @@ help: use parentheses to call this function pointer LL | needs_bar(f()); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr index 90f44cce06e44..f804c66aafe22 100644 --- a/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr +++ b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr @@ -16,6 +16,6 @@ help: use parentheses to call this trait object LL | needs_foo(x()); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr index 128160f10adb3..2dd6fb6a3bf6d 100644 --- a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr +++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr @@ -18,7 +18,10 @@ error[E0599]: no method named `sort` found for unit type `()` in the current sco --> $DIR/chain-method-call-mutation-in-place.rs:3:72 | LL | vec![1, 2, 3].into_iter().collect::>().sort_by_key(|i| i).sort(); - | ^^^^ method not found in `()` + | ------------- --------------------- ^^^^ method not found in `()` + | | | + | | method `sort` is available on `&mut [i32]` + | method `sort` is available on `Vec` | note: method `sort_by_key` modifies its receiver in-place, it is not meant to be used in method chains. --> $DIR/chain-method-call-mutation-in-place.rs:3:53 diff --git a/tests/ui/suggestions/const-in-struct-pat.stderr b/tests/ui/suggestions/const-in-struct-pat.stderr index f344ac06db1f8..d4056e09cc364 100644 --- a/tests/ui/suggestions/const-in-struct-pat.stderr +++ b/tests/ui/suggestions/const-in-struct-pat.stderr @@ -15,6 +15,6 @@ help: bind the struct field to a different name instead LL | let Thing { foo: other_foo } = t; | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr index 9ee3e6eb2c827..b6c286128023d 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -12,6 +12,6 @@ LL | let A = 3; = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/suggestions/constrain-suggest-ice.stderr b/tests/ui/suggestions/constrain-suggest-ice.stderr index 9b92091de9f54..96f1f86058867 100644 --- a/tests/ui/suggestions/constrain-suggest-ice.stderr +++ b/tests/ui/suggestions/constrain-suggest-ice.stderr @@ -9,5 +9,5 @@ LL | A: [(); { LL | } | ^ mismatched closing delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.stderr b/tests/ui/suggestions/core-std-import-order-issue-83564.stderr index 48ee44a74f2d3..c2634e3070ea9 100644 --- a/tests/ui/suggestions/core-std-import-order-issue-83564.stderr +++ b/tests/ui/suggestions/core-std-import-order-issue-83564.stderr @@ -11,6 +11,6 @@ LL + use core::num::NonZeroU32; LL + use std::num::NonZeroU32; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/correct-binder-for-arbitrary-bound-sugg.stderr b/tests/ui/suggestions/correct-binder-for-arbitrary-bound-sugg.stderr index 2298e7f4e0c3c..2cd3fba871548 100644 --- a/tests/ui/suggestions/correct-binder-for-arbitrary-bound-sugg.stderr +++ b/tests/ui/suggestions/correct-binder-for-arbitrary-bound-sugg.stderr @@ -17,6 +17,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn foo() where for<'a> &'a T: Bar {} | ++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/crate-or-module-typo.rs b/tests/ui/suggestions/crate-or-module-typo.rs index 2471b11c61efd..b12ad495e9fd5 100644 --- a/tests/ui/suggestions/crate-or-module-typo.rs +++ b/tests/ui/suggestions/crate-or-module-typo.rs @@ -3,7 +3,7 @@ use st::cell::Cell; //~ ERROR failed to resolve: use of undeclared crate or module `st` mod bar { - pub fn bar() { bar::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `bar` + pub fn bar() { bar::baz(); } //~ ERROR failed to resolve: function `bar` is not a crate or module fn baz() {} } diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr index 9ece31e76f005..457d779064682 100644 --- a/tests/ui/suggestions/crate-or-module-typo.stderr +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -42,11 +42,11 @@ LL - bar: st::cell::Cell LL + bar: cell::Cell | -error[E0433]: failed to resolve: use of undeclared crate or module `bar` +error[E0433]: failed to resolve: function `bar` is not a crate or module --> $DIR/crate-or-module-typo.rs:6:20 | LL | pub fn bar() { bar::baz(); } - | ^^^ use of undeclared crate or module `bar` + | ^^^ function `bar` is not a crate or module error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index 1cc37d61151ca..a2b68fa966fcb 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -4,11 +4,18 @@ error[E0599]: no function or associated item named `contains` found for struct ` LL | Vec::contains(&vec, &0); | ^^^^^^^^ function or associated item not found in `Vec<_, _>` | +note: if you're trying to build a new `Vec<_, _>` consider using one of the following associated functions: + Vec::::new + Vec::::with_capacity + Vec::::from_raw_parts + Vec::::new_in + and 2 others + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | LL | <[_]>::contains(&vec, &0); | ~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index 9d843c2514b9b..eb95f729d1e7c 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -19,6 +19,6 @@ help: consider restricting type parameter `T` LL | pub struct Struct(T); | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr index c6867270ad81e..46613e8e1b487 100644 --- a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr +++ b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr @@ -8,6 +8,6 @@ LL | | }; | = note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr index 866d3fab46e73..00d001f6bee2d 100644 --- a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr +++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr @@ -13,6 +13,6 @@ help: try wrapping the expression in `hidden_child::__private::Some` LL | let x: Option = hidden_child::__private::Some(1i32); | ++++++++++++++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr index f8029e452bb77..ef08282702e0d 100644 --- a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr +++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr @@ -13,6 +13,6 @@ help: try wrapping the expression in `Some` LL | let x: Option = Some(1i32); | +++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr index c66da3ea6d976..8f738465d38d7 100644 --- a/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr +++ b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `set` found for array `[u8; 1]` in the current sco LL | a.set(0, 3); | ^^^ help: there is a method with a similar name: `get` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr index 319d866003ba8..348f7e00d468e 100644 --- a/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr +++ b/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr @@ -9,6 +9,6 @@ help: change the type of the numeric literal from `usize` to `u64` LL | assert_eq!(10u64, 10u64); | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr b/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr index 0d9543e0b8fa2..6aa187bfbd3df 100644 --- a/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr +++ b/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `MAX` found for type `u32` in the current scope LL | 1_u32.MAX(); | ^^^ method not found in `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr index 85fbb8b88e81a..974aedd13cf54 100644 --- a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr +++ b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr @@ -15,6 +15,6 @@ LL + use banana::Apple; LL + use banana::Peach; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/enum-variant-arg-mismatch.stderr b/tests/ui/suggestions/enum-variant-arg-mismatch.stderr index f76019b700011..16f03d16d8c02 100644 --- a/tests/ui/suggestions/enum-variant-arg-mismatch.stderr +++ b/tests/ui/suggestions/enum-variant-arg-mismatch.stderr @@ -16,7 +16,11 @@ note: required by a bound in `map` | LL | fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` +help: consider wrapping the function in a closure + | +LL | map(|arg0: String| Sexpr::Ident(/* &str */)); + | ++++++++++++++ ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/suggestions/field-access-considering-privacy.stderr b/tests/ui/suggestions/field-access-considering-privacy.stderr index cbf6f3d100258..2b1f459238366 100644 --- a/tests/ui/suggestions/field-access-considering-privacy.stderr +++ b/tests/ui/suggestions/field-access-considering-privacy.stderr @@ -9,6 +9,6 @@ help: one of the expressions' fields has a field of the same name LL | tcx.sess.opts; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/field-has-method.stderr b/tests/ui/suggestions/field-has-method.stderr index def16401750d5..daff2db64189a 100644 --- a/tests/ui/suggestions/field-has-method.stderr +++ b/tests/ui/suggestions/field-has-method.stderr @@ -12,6 +12,6 @@ help: one of the expressions' fields has a method of the same name LL | let k = i.value.kind(); | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr b/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr index 9dea667fb961e..47a7ac895bf69 100644 --- a/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr +++ b/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | let _ = f::; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr index fc5a521746a51..2733bbff36b54 100644 --- a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr +++ b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr @@ -17,6 +17,6 @@ LL | where LL | for<'b> &'b X: Trait, | ^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/imm-ref-trait-object.stderr b/tests/ui/suggestions/imm-ref-trait-object.stderr index f7f7902c17d16..6cd21fcabfaa9 100644 --- a/tests/ui/suggestions/imm-ref-trait-object.stderr +++ b/tests/ui/suggestions/imm-ref-trait-object.stderr @@ -9,5 +9,5 @@ help: you need `&mut dyn Iterator` instead of `&dyn Iterator) -> u64 { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr index 20f8e65f769a4..3a6052448cb0f 100644 --- a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr +++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -12,6 +12,6 @@ help: the following trait defines an item `hello`, perhaps you need to restrict LL | fn test(foo: impl Foo + Bar) { | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/import-trait-for-method-call.rs b/tests/ui/suggestions/import-trait-for-method-call.rs index 4dbadbdf98206..feb2c7e84f1d5 100644 --- a/tests/ui/suggestions/import-trait-for-method-call.rs +++ b/tests/ui/suggestions/import-trait-for-method-call.rs @@ -1,7 +1,7 @@ use std::hash::BuildHasher; fn next_u64() -> u64 { - let bh = std::collections::hash_map::RandomState::new(); + let bh = std::hash::RandomState::new(); let h = bh.build_hasher(); h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher` } diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr index 7e24150e7f447..d6efc8173cb7c 100644 --- a/tests/ui/suggestions/into-str.stderr +++ b/tests/ui/suggestions/into-str.stderr @@ -21,6 +21,6 @@ note: required by a bound in `foo` LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} | ^^^^^^^^^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/invalid-bin-op.stderr b/tests/ui/suggestions/invalid-bin-op.stderr index 570afcea6434b..018250c8c1b60 100644 --- a/tests/ui/suggestions/invalid-bin-op.stderr +++ b/tests/ui/suggestions/invalid-bin-op.stderr @@ -21,6 +21,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | pub fn foo(s: S, t: S) where S: PartialEq { | +++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/suggestions/issue-101065.stderr b/tests/ui/suggestions/issue-101065.stderr index 9f77ead42944f..8a7ecc801784d 100644 --- a/tests/ui/suggestions/issue-101065.stderr +++ b/tests/ui/suggestions/issue-101065.stderr @@ -18,6 +18,6 @@ help: try wrapping the expression in `FakeResult::Ok` LL | FakeResult::Ok(FakeResult::Ok(())) | +++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-101421.stderr b/tests/ui/suggestions/issue-101421.stderr index 2656ab3db0bc3..ececba5fb1baa 100644 --- a/tests/ui/suggestions/issue-101421.stderr +++ b/tests/ui/suggestions/issue-101421.stderr @@ -12,6 +12,6 @@ note: method defined here, with 0 generic parameters LL | fn f(&self, _: ()); | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/issue-101465.stderr b/tests/ui/suggestions/issue-101465.stderr index 2aec3c863af55..0dad813b389a4 100644 --- a/tests/ui/suggestions/issue-101465.stderr +++ b/tests/ui/suggestions/issue-101465.stderr @@ -20,6 +20,6 @@ LL ~ true => Box::new(B), LL ~ false => Box::new(C), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr index 9f00de17484fb..4de91a1b99500 100644 --- a/tests/ui/suggestions/issue-101623.stderr +++ b/tests/ui/suggestions/issue-101623.stderr @@ -10,6 +10,6 @@ LL | Trait::do_stuff({ fun(&mut *inner) }); = help: the trait `Trait<'_>` is implemented for `()` = help: for that trait implementation, expected `()`, found `*mut ()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-101984.stderr b/tests/ui/suggestions/issue-101984.stderr index 151587d422230..c19cda20402ff 100644 --- a/tests/ui/suggestions/issue-101984.stderr +++ b/tests/ui/suggestions/issue-101984.stderr @@ -9,6 +9,6 @@ LL | let (cmp, router) = self.router.at()?; = note: expected struct `Match<&(for<'a> fn(&'a ()), Box)>` found tuple `(_, _)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-102354.stderr b/tests/ui/suggestions/issue-102354.stderr index 08d4b99559031..8340d9340f9b2 100644 --- a/tests/ui/suggestions/issue-102354.stderr +++ b/tests/ui/suggestions/issue-102354.stderr @@ -14,6 +14,6 @@ note: the candidate is defined in the trait `Trait` LL | fn func() {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/issue-103112.stderr b/tests/ui/suggestions/issue-103112.stderr index 4ca7fdf9b5a2a..b7de57bfd90ed 100644 --- a/tests/ui/suggestions/issue-103112.stderr +++ b/tests/ui/suggestions/issue-103112.stderr @@ -10,6 +10,6 @@ LL - std::process::abort!(); LL + std::process::abort(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/issue-103646.stderr b/tests/ui/suggestions/issue-103646.stderr index 3ae9813d4914c..8d0e8652392d6 100644 --- a/tests/ui/suggestions/issue-103646.stderr +++ b/tests/ui/suggestions/issue-103646.stderr @@ -16,6 +16,6 @@ note: the candidate is defined in the trait `Cat` LL | fn nya() {} | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/issue-104327.stderr b/tests/ui/suggestions/issue-104327.stderr index acec3a55d526e..325b6b6eb4b63 100644 --- a/tests/ui/suggestions/issue-104327.stderr +++ b/tests/ui/suggestions/issue-104327.stderr @@ -12,6 +12,6 @@ help: use the fully-qualified path to the only available implementation LL | <(dyn Bar + 'static) as Foo>::f(); | +++++++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/suggestions/issue-104328.stderr b/tests/ui/suggestions/issue-104328.stderr index b31b84781bacb..a592621834127 100644 --- a/tests/ui/suggestions/issue-104328.stderr +++ b/tests/ui/suggestions/issue-104328.stderr @@ -12,6 +12,6 @@ help: use the fully-qualified path to the only available implementation LL | <(dyn Sized + 'static) as Foo>::f(); | +++++++++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/suggestions/issue-105645.stderr b/tests/ui/suggestions/issue-105645.stderr index 895f5ffd1e1c7..f717f8f4e6570 100644 --- a/tests/ui/suggestions/issue-105645.stderr +++ b/tests/ui/suggestions/issue-105645.stderr @@ -13,6 +13,6 @@ note: required by a bound in `foo` LL | fn foo(_: &mut impl std::io::Write) {} | ^^^^^^^^^^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-107860.stderr b/tests/ui/suggestions/issue-107860.stderr index 92e3cf8c43b3b..4be495da46b1f 100644 --- a/tests/ui/suggestions/issue-107860.stderr +++ b/tests/ui/suggestions/issue-107860.stderr @@ -7,6 +7,6 @@ LL | async fn str(T: &str) -> &str { &str } = note: expected reference `&str` found reference `&for<'a> fn(&'a str) -> impl Future {str::<_>}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-109291.stderr b/tests/ui/suggestions/issue-109291.stderr index 4ef5948d9bf2b..c787be4de7c56 100644 --- a/tests/ui/suggestions/issue-109291.stderr +++ b/tests/ui/suggestions/issue-109291.stderr @@ -6,7 +6,14 @@ LL | println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capt | | | function or associated item not found in `Backtrace` | help: there is an associated function with a similar name: `force_capture` + | +note: if you're trying to build a new `Backtrace` consider using one of the following associated functions: + Backtrace::capture + Backtrace::force_capture + Backtrace::disabled + Backtrace::create + --> $SRC_DIR/std/src/backtrace.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/issue-109436.stderr b/tests/ui/suggestions/issue-109436.stderr index c479326f93534..4425ce84b6d38 100644 --- a/tests/ui/suggestions/issue-109436.stderr +++ b/tests/ui/suggestions/issue-109436.stderr @@ -10,6 +10,6 @@ help: consider borrowing here LL | let b: Bar = (&foo).into(); | ++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-109854.stderr b/tests/ui/suggestions/issue-109854.stderr index 621a3897165b8..52444cd4c45a9 100644 --- a/tests/ui/suggestions/issue-109854.stderr +++ b/tests/ui/suggestions/issue-109854.stderr @@ -26,6 +26,6 @@ LL - generate_setter, LL + /* usize */, | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/suggestions/issue-114701.stderr b/tests/ui/suggestions/issue-114701.stderr index 67462a09c78da..d2a7806b7c123 100644 --- a/tests/ui/suggestions/issue-114701.stderr +++ b/tests/ui/suggestions/issue-114701.stderr @@ -10,6 +10,6 @@ LL | assert!(if let Enum::$variant::<()> $matcher = $expr () { true } el LL | is_variant!(UVariant, Enum::<()>::UVariant); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/suggestions/issue-117669.rs b/tests/ui/suggestions/issue-117669.rs new file mode 100644 index 0000000000000..09b4f2bd47cae --- /dev/null +++ b/tests/ui/suggestions/issue-117669.rs @@ -0,0 +1,4 @@ +fn main() { + let abs: i32 = 3i32.checked_abs(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/suggestions/issue-117669.stderr b/tests/ui/suggestions/issue-117669.stderr new file mode 100644 index 0000000000000..01783ea4ef629 --- /dev/null +++ b/tests/ui/suggestions/issue-117669.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-117669.rs:2:20 + | +LL | let abs: i32 = 3i32.checked_abs(); + | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found `Option` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option` +help: consider using `Option::expect` to unwrap the `Option` value, panicking if the value is an `Option::None` + | +LL | let abs: i32 = 3i32.checked_abs().expect("REASON"); + | +++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr index bb8b9b37067eb..3c3bc2305e079 100644 --- a/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr +++ b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr @@ -11,6 +11,6 @@ LL | vindictive() LL | | (1, 2) | |__________- call expression requires function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/suggestions/issue-61226.stderr b/tests/ui/suggestions/issue-61226.stderr index cda962a904530..890950b1ae9db 100644 --- a/tests/ui/suggestions/issue-61226.stderr +++ b/tests/ui/suggestions/issue-61226.stderr @@ -7,6 +7,6 @@ LL | fn main() { LL | let _ = vec![X]; //… | ^ help: use struct literal syntax instead: `X {}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/suggestions/issue-62843.stderr b/tests/ui/suggestions/issue-62843.stderr index ead8f18547b67..f3a9f6b7913aa 100644 --- a/tests/ui/suggestions/issue-62843.stderr +++ b/tests/ui/suggestions/issue-62843.stderr @@ -15,6 +15,6 @@ help: consider borrowing here LL | println!("{:?}", line.find(&pattern)); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr b/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr index d7b33ea41f79a..ce0087fbfcbab 100644 --- a/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr +++ b/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `a_variable_longer_name` in this scope LL | println!("{}", a_variable_longer_name); | ^^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `a_longer_variable_name` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/issue-68049-1.stderr b/tests/ui/suggestions/issue-68049-1.stderr index 7f931f0cdc9e8..760f83d548f0f 100644 --- a/tests/ui/suggestions/issue-68049-1.stderr +++ b/tests/ui/suggestions/issue-68049-1.stderr @@ -4,6 +4,6 @@ error[E0594]: cannot assign to `self.0`, which is behind a `&` reference LL | self.0 += 1; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index 80be252a0a51b..b9b72e0e63f14 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -5,7 +5,7 @@ LL | let _: &[i8] = data.into(); | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` | = help: the following other types implement trait `From`: - <[bool; LANES] as From>> + <[bool; N] as From>> <[T; N] as From>> <[T; 1] as From<(T,)>> <[T; 2] as From<(T, T)>> @@ -16,6 +16,6 @@ LL | let _: &[i8] = data.into(); and 6 others = note: required for `&[u8]` to implement `Into<&[i8]>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-72766.stderr b/tests/ui/suggestions/issue-72766.stderr index f257bb9b0e887..f0680dfe19f7e 100644 --- a/tests/ui/suggestions/issue-72766.stderr +++ b/tests/ui/suggestions/issue-72766.stderr @@ -10,6 +10,6 @@ help: consider `await`ing on the `Future` LL | SadGirl {}.call().await?; | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-81839.stderr b/tests/ui/suggestions/issue-81839.stderr index 238ee637c7d4b..de1ea98554bee 100644 --- a/tests/ui/suggestions/issue-81839.stderr +++ b/tests/ui/suggestions/issue-81839.stderr @@ -21,6 +21,6 @@ help: consider using a semicolon here, but this will discard any values in the m LL | }; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-83892.stderr b/tests/ui/suggestions/issue-83892.stderr index 5e471819b27b8..7dbffcfca4ede 100644 --- a/tests/ui/suggestions/issue-83892.stderr +++ b/tests/ui/suggestions/issue-83892.stderr @@ -9,6 +9,6 @@ LL | () => func() LL | } | - help: consider using a semicolon here: `;` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-83943.stderr b/tests/ui/suggestions/issue-83943.stderr index c73667f09cbeb..1a085368485cf 100644 --- a/tests/ui/suggestions/issue-83943.stderr +++ b/tests/ui/suggestions/issue-83943.stderr @@ -12,6 +12,6 @@ LL | | "B" LL | | }; | |_____- `if` and `else` have incompatible types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-84592.stderr b/tests/ui/suggestions/issue-84592.stderr index 70c96feb1de4c..fe0a7b6731e2a 100644 --- a/tests/ui/suggestions/issue-84592.stderr +++ b/tests/ui/suggestions/issue-84592.stderr @@ -12,6 +12,6 @@ help: consider introducing a named lifetime parameter LL | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> { | ++++ ++ ++ ~~ ~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/issue-84973-2.stderr b/tests/ui/suggestions/issue-84973-2.stderr index 513bf28fb5878..74995a0500acd 100644 --- a/tests/ui/suggestions/issue-84973-2.stderr +++ b/tests/ui/suggestions/issue-84973-2.stderr @@ -16,6 +16,6 @@ help: consider mutably borrowing here LL | foo(&mut a); | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-84973.stderr b/tests/ui/suggestions/issue-84973.stderr index 55c89884a5f6c..c5e1958e030f2 100644 --- a/tests/ui/suggestions/issue-84973.stderr +++ b/tests/ui/suggestions/issue-84973.stderr @@ -19,6 +19,6 @@ help: consider borrowing here LL | let o = Other::new(&f); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr index 752533cdc1213..21b568b02ad25 100644 --- a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr +++ b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr @@ -18,6 +18,6 @@ LL | struct A(T) where T: Send; | | | this could be changed to `T: ?Sized`... -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr index 92be9f764cc4b..77e5dcd91a1ea 100644 --- a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr +++ b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr @@ -13,6 +13,6 @@ note: required by a bound in `foo` LL | fn foo(_: &T) where T: Sized {} | ^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-88696.stderr b/tests/ui/suggestions/issue-88696.stderr index 4947269d75934..b4f0793c225ff 100644 --- a/tests/ui/suggestions/issue-88696.stderr +++ b/tests/ui/suggestions/issue-88696.stderr @@ -6,6 +6,6 @@ LL | a().into() | = note: required for `Result` to implement `Into>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-89333.stderr b/tests/ui/suggestions/issue-89333.stderr index 4739f11ddadbf..761de7f252184 100644 --- a/tests/ui/suggestions/issue-89333.stderr +++ b/tests/ui/suggestions/issue-89333.stderr @@ -15,6 +15,6 @@ note: required by a bound in `test` LL | fn test(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {} | ^^^^^ required by this bound in `test` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-89640.stderr b/tests/ui/suggestions/issue-89640.stderr index 8ff4ef4f0ecf0..3252cd6bba4f1 100644 --- a/tests/ui/suggestions/issue-89640.stderr +++ b/tests/ui/suggestions/issue-89640.stderr @@ -9,5 +9,5 @@ help: consider removing the space to spell keyword `let` LL | let x: i32 = 3; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr index 7d1da7d24eeb8..96fb1f3c68da7 100644 --- a/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr +++ b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr @@ -19,6 +19,6 @@ help: store this in the heap by calling `Box::new` LL | Self::foo(Box::new(None)) | +++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-90974.stderr b/tests/ui/suggestions/issue-90974.stderr index e1fb479a3a7a0..1a732ecaf944c 100644 --- a/tests/ui/suggestions/issue-90974.stderr +++ b/tests/ui/suggestions/issue-90974.stderr @@ -9,6 +9,6 @@ help: you must specify a concrete type for this numeric value, like `f32` LL | println!("{}", (3_f32).recip()); | ~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0689`. diff --git a/tests/ui/suggestions/issue-96223.stderr b/tests/ui/suggestions/issue-96223.stderr index d4e9433dfda04..a54a4e7b3be4d 100644 --- a/tests/ui/suggestions/issue-96223.stderr +++ b/tests/ui/suggestions/issue-96223.stderr @@ -26,6 +26,6 @@ note: required by a bound in `icey_bounds` LL | fn icey_bounds>(p: &D) {} | ^^^^^^^^^^^^^^^^^^ required by this bound in `icey_bounds` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-97677.stderr b/tests/ui/suggestions/issue-97677.stderr index 575d79267f20d..0e95167d8515b 100644 --- a/tests/ui/suggestions/issue-97677.stderr +++ b/tests/ui/suggestions/issue-97677.stderr @@ -11,6 +11,6 @@ help: consider restricting type parameter `N` LL | fn add_ten>(n: N) -> N { | ++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/suggestions/issue-97704.stderr b/tests/ui/suggestions/issue-97704.stderr index ca017be45ac47..a7284db1d9569 100644 --- a/tests/ui/suggestions/issue-97704.stderr +++ b/tests/ui/suggestions/issue-97704.stderr @@ -10,6 +10,6 @@ help: consider `await`ing on the `Future` LL | func(async { Ok::<_, i32>(()) }).await?; | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-97760.stderr b/tests/ui/suggestions/issue-97760.stderr index 5415c247c8fff..c3cf7e13987b6 100644 --- a/tests/ui/suggestions/issue-97760.stderr +++ b/tests/ui/suggestions/issue-97760.stderr @@ -13,6 +13,6 @@ LL ~ pub fn print_values(values: &I) LL ~ where ::Item: std::fmt::Display { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-98500.stderr b/tests/ui/suggestions/issue-98500.stderr index e7251d735e38e..aa66a9aa1e7fa 100644 --- a/tests/ui/suggestions/issue-98500.stderr +++ b/tests/ui/suggestions/issue-98500.stderr @@ -19,6 +19,6 @@ LL | pub trait B where = help: consider moving `f` to another trait = help: consider moving `f2` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/issue-98562.stderr b/tests/ui/suggestions/issue-98562.stderr index 7897fa441a24f..578eb284c2662 100644 --- a/tests/ui/suggestions/issue-98562.stderr +++ b/tests/ui/suggestions/issue-98562.stderr @@ -6,6 +6,6 @@ LL | impl TraitA for X { | = help: implement the missing item: `fn baz + TraitD, V: TraitD>(_: U, _: V) -> Self where U: TraitE, U: TraitB, ::Item: Copy { todo!() }` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/suggestions/issue-99080.stderr b/tests/ui/suggestions/issue-99080.stderr index d1908dd9d0d86..9c385a7a408d0 100644 --- a/tests/ui/suggestions/issue-99080.stderr +++ b/tests/ui/suggestions/issue-99080.stderr @@ -15,6 +15,6 @@ note: required by a bound in `needs_meow` LL | fn needs_meow(t: T) {} | ^^^^ required by this bound in `needs_meow` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-99240-2.stderr b/tests/ui/suggestions/issue-99240-2.stderr index a2b5597847846..00bffee652938 100644 --- a/tests/ui/suggestions/issue-99240-2.stderr +++ b/tests/ui/suggestions/issue-99240-2.stderr @@ -16,6 +16,6 @@ LL - Unit(); LL + Unit; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/suggestions/issue-99240.stderr b/tests/ui/suggestions/issue-99240.stderr index f1bea688b4ed5..ea819067a23a2 100644 --- a/tests/ui/suggestions/issue-99240.stderr +++ b/tests/ui/suggestions/issue-99240.stderr @@ -6,6 +6,6 @@ LL | (it.0.take())() | | | call expression requires function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/suggestions/issue-99597.stderr b/tests/ui/suggestions/issue-99597.stderr index bdf2a07c143b4..e1d7aac267c4c 100644 --- a/tests/ui/suggestions/issue-99597.stderr +++ b/tests/ui/suggestions/issue-99597.stderr @@ -10,6 +10,6 @@ help: the following trait defines an item `test`, perhaps you need to restrict t LL | fn go(s: &(impl T1 + T2)) { | + +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr index 6adefe3de371e..9ef28bc261597 100644 --- a/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr +++ b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr @@ -4,5 +4,5 @@ error: expected expression, found `=` LL | if 1 == = 1 { | ^ expected expression -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr index a03d4e8ce9f70..ee924522564a8 100644 --- a/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr +++ b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr @@ -16,11 +16,15 @@ note: required by a bound in `Trader::<'a>::set_closure` | LL | pub fn set_closure(&mut self, function: impl Fn(&mut Trader) + 'a) { | ^^^^^^^^^^^^^^^ required by this bound in `Trader::<'a>::set_closure` +help: consider wrapping the function in a closure + | +LL | trader.set_closure(|arg0: &mut Trader<'_>| closure(*arg0)); + | +++++++++++++++++++++++ +++++++ help: consider adjusting the signature so it borrows its argument | LL | let closure = |trader : &mut Trader| { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr index 6c63e1ada6138..2677b7943ccca 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -14,6 +14,6 @@ help: consider adding an explicit lifetime bound LL | fn func<'a, T: Test + 'a>(_dummy: &Foo, foo: &Foo<'a>, t: T) { | +++ ++++ ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr index 7b126c90ee797..00bc43d5e464d 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr @@ -10,6 +10,6 @@ help: consider introducing a named lifetime parameter LL | fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { | +++ ++ ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.fixed b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.fixed new file mode 100644 index 0000000000000..84315ad917327 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.fixed @@ -0,0 +1,11 @@ +// run-rustfix +use std::any::Any; + +fn foo(value: &T) -> Box { + Box::new(value) as Box + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let _ = foo(&5); +} diff --git a/tests/ui/issues/issue-16922.rs b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs similarity index 92% rename from tests/ui/issues/issue-16922.rs rename to tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs index bbbbf72dbd5d3..fa7e72ff2a738 100644 --- a/tests/ui/issues/issue-16922.rs +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs @@ -1,3 +1,4 @@ +// run-rustfix use std::any::Any; fn foo(value: &T) -> Box { diff --git a/tests/ui/issues/issue-16922.stderr b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr similarity index 81% rename from tests/ui/issues/issue-16922.stderr rename to tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr index 9d9f32a97c065..73fa5ddb146e7 100644 --- a/tests/ui/issues/issue-16922.stderr +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-16922.rs:4:5 + --> $DIR/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs:5:5 | LL | fn foo(value: &T) -> Box { | - let's call the lifetime of this reference `'1` @@ -11,5 +11,5 @@ help: to declare that the trait object captures data from argument `value`, you LL | fn foo(value: &T) -> Box { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/many-type-ascription.stderr b/tests/ui/suggestions/many-type-ascription.stderr index e36919c82f832..feddc7d62a754 100644 --- a/tests/ui/suggestions/many-type-ascription.stderr +++ b/tests/ui/suggestions/many-type-ascription.stderr @@ -6,5 +6,5 @@ LL | let _ = 0: i32; | = note: type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/mismatched-types-numeric-from.stderr b/tests/ui/suggestions/mismatched-types-numeric-from.stderr index 4d44d893a86d9..93024b1f0b11f 100644 --- a/tests/ui/suggestions/mismatched-types-numeric-from.stderr +++ b/tests/ui/suggestions/mismatched-types-numeric-from.stderr @@ -6,6 +6,6 @@ LL | let _: u32 = i32::from(0_u8); | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr index 4c2d2776d3d81..3cf5c6e7b7497 100644 --- a/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr +++ b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr @@ -9,6 +9,6 @@ LL | impl TraitA<()> for S { = help: implement the missing item: `fn baz(_: T) -> Self where T: TraitB, ::Item: Copy { todo!() }` = help: implement the missing item: `const A: usize = 42;` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 03082be690fbf..f9db1e1ec008f 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -14,6 +14,6 @@ help: consider further restricting this bound LL | pub struct AABB{ | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index 09696e0613e7c..ed1bde5f83e53 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -18,6 +18,6 @@ help: consider further restricting this bound LL | pub struct AABB{ | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 8585fe47bf345..03db737fa8761 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -18,6 +18,6 @@ help: consider restricting type parameter `K` LL | pub struct AABB{ | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr index 856d8db381bd8..6dc512223d1b0 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -17,6 +17,6 @@ help: consider restricting type parameter `S` LL | impl Copy for Wrapper> {} | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr index ec3e4f23a649e..fd38d4c64b44c 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -12,6 +12,6 @@ help: consider restricting type parameter `S` LL | impl Copy for Wrapper {} | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-type-param-used-in-param.stderr b/tests/ui/suggestions/missing-type-param-used-in-param.stderr index 3116c5a0a1cd7..d667fc36539e1 100644 --- a/tests/ui/suggestions/missing-type-param-used-in-param.stderr +++ b/tests/ui/suggestions/missing-type-param-used-in-param.stderr @@ -16,6 +16,6 @@ help: add missing generic argument LL | two_type_params::(100); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr index bfdb35947ef5a..aa11bc7cf1d9c 100644 --- a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr +++ b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr @@ -19,6 +19,6 @@ LL - 1.bar::(0); LL + 1.bar(0); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/no-extern-crate-in-type.stderr b/tests/ui/suggestions/no-extern-crate-in-type.stderr index 68100e56cbc82..384b17d1e2b48 100644 --- a/tests/ui/suggestions/no-extern-crate-in-type.stderr +++ b/tests/ui/suggestions/no-extern-crate-in-type.stderr @@ -9,6 +9,6 @@ help: consider importing this struct LL + use foo::Foo; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr index b294f4da7db33..278bfc60b55fd 100644 --- a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr @@ -6,6 +6,6 @@ LL | let test = fooer.f; | = note: available fields are: `first`, `second`, `third` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr index cc991b915d339..65353ed923e0e 100644 --- a/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr @@ -4,7 +4,6 @@ error[E0609]: no field `c` on type `Foo` LL | let _test = &fooer.c; | ^ unknown field | - = note: available fields are: `first`, `_second`, `_third` help: one of the expressions' fields has a field of the same name | LL | let _test = &fooer.first.bar.c; @@ -16,7 +15,6 @@ error[E0609]: no field `test` on type `Foo` LL | let _test2 = fooer.test; | ^^^^ unknown field | - = note: available fields are: `first`, `_second`, `_third` help: one of the expressions' fields has a field of the same name | LL | let _test2 = fooer.first.bar.c.test; diff --git a/tests/ui/suggestions/non_ascii_ident.rs b/tests/ui/suggestions/non_ascii_ident.rs new file mode 100644 index 0000000000000..9c89714751826 --- /dev/null +++ b/tests/ui/suggestions/non_ascii_ident.rs @@ -0,0 +1,7 @@ +fn main() { + // There shall be no suggestions here. In particular not `Ok`. + let _ = 读文; //~ ERROR cannot find value `读文` in this scope + + let f = 0f32; // Important line to make this an ICE regression test + 读文(f); //~ ERROR cannot find function `读文` in this scope +} diff --git a/tests/ui/suggestions/non_ascii_ident.stderr b/tests/ui/suggestions/non_ascii_ident.stderr new file mode 100644 index 0000000000000..fdcc64aef3681 --- /dev/null +++ b/tests/ui/suggestions/non_ascii_ident.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find value `读文` in this scope + --> $DIR/non_ascii_ident.rs:3:13 + | +LL | let _ = 读文; + | ^^^^ not found in this scope + +error[E0425]: cannot find function `读文` in this scope + --> $DIR/non_ascii_ident.rs:6:5 + | +LL | 读文(f); + | ^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/opaque-type-error.stderr b/tests/ui/suggestions/opaque-type-error.stderr index 5c90d3012abf9..3ce45c7b67456 100644 --- a/tests/ui/suggestions/opaque-type-error.stderr +++ b/tests/ui/suggestions/opaque-type-error.stderr @@ -24,6 +24,6 @@ LL | } else { LL ~ thing_two().await | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/option-content-move-from-tuple-match.stderr b/tests/ui/suggestions/option-content-move-from-tuple-match.stderr index 97d05d9dcffaf..63314acb87cbf 100644 --- a/tests/ui/suggestions/option-content-move-from-tuple-match.stderr +++ b/tests/ui/suggestions/option-content-move-from-tuple-match.stderr @@ -15,6 +15,6 @@ help: consider borrowing the pattern binding LL | (None, &ref c) => &c.unwrap(), | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/option-content-move.fixed b/tests/ui/suggestions/option-content-move.fixed new file mode 100644 index 0000000000000..5e79cf71d823f --- /dev/null +++ b/tests/ui/suggestions/option-content-move.fixed @@ -0,0 +1,38 @@ +// run-rustfix +pub struct LipogramCorpora { + selections: Vec<(char, Option)>, +} + +impl LipogramCorpora { + pub fn validate_all(&mut self) -> Result<(), char> { + for selection in &self.selections { + if selection.1.is_some() { + if as Clone>::clone(&selection.1).unwrap().contains(selection.0) { + //~^ ERROR cannot move out of `selection.1` + return Err(selection.0); + } + } + } + Ok(()) + } +} + +pub struct LipogramCorpora2 { + selections: Vec<(char, Result)>, +} + +impl LipogramCorpora2 { + pub fn validate_all(&mut self) -> Result<(), char> { + for selection in &self.selections { + if selection.1.is_ok() { + if as Clone>::clone(&selection.1).unwrap().contains(selection.0) { + //~^ ERROR cannot move out of `selection.1` + return Err(selection.0); + } + } + } + Ok(()) + } +} + +fn main() {} diff --git a/tests/ui/suggestions/option-content-move.rs b/tests/ui/suggestions/option-content-move.rs index 46c895b95f536..58efbe71f2786 100644 --- a/tests/ui/suggestions/option-content-move.rs +++ b/tests/ui/suggestions/option-content-move.rs @@ -1,3 +1,4 @@ +// run-rustfix pub struct LipogramCorpora { selections: Vec<(char, Option)>, } diff --git a/tests/ui/suggestions/option-content-move.stderr b/tests/ui/suggestions/option-content-move.stderr index 5060606d842a7..e5de150275dbb 100644 --- a/tests/ui/suggestions/option-content-move.stderr +++ b/tests/ui/suggestions/option-content-move.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `selection.1` which is behind a shared reference - --> $DIR/option-content-move.rs:9:20 + --> $DIR/option-content-move.rs:10:20 | LL | if selection.1.unwrap().contains(selection.0) { | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call @@ -11,11 +11,11 @@ note: `Option::::unwrap` takes ownership of the receiver `self`, which moves --> $SRC_DIR/core/src/option.rs:LL:COL help: you can `clone` the value and consume it, but this might not be your desired behavior | -LL | if selection.1.clone().unwrap().contains(selection.0) { - | ++++++++ +LL | if as Clone>::clone(&selection.1).unwrap().contains(selection.0) { + | ++++++++++++++++++++++++++++++++++ + error[E0507]: cannot move out of `selection.1` which is behind a shared reference - --> $DIR/option-content-move.rs:27:20 + --> $DIR/option-content-move.rs:28:20 | LL | if selection.1.unwrap().contains(selection.0) { | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call @@ -27,8 +27,8 @@ note: `Result::::unwrap` takes ownership of the receiver `self`, which mov --> $SRC_DIR/core/src/result.rs:LL:COL help: you can `clone` the value and consume it, but this might not be your desired behavior | -LL | if selection.1.clone().unwrap().contains(selection.0) { - | ++++++++ +LL | if as Clone>::clone(&selection.1).unwrap().contains(selection.0) { + | ++++++++++++++++++++++++++++++++++++++++++ + error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/option-content-move2.stderr b/tests/ui/suggestions/option-content-move2.stderr index 94acda73c4efe..0297c031eccaf 100644 --- a/tests/ui/suggestions/option-content-move2.stderr +++ b/tests/ui/suggestions/option-content-move2.stderr @@ -15,6 +15,6 @@ LL | var = Some(NotCopyable); | variable moved due to use in closure | move occurs because `var` has type `Option`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/option-to-bool.stderr b/tests/ui/suggestions/option-to-bool.stderr index e042f07daeb1c..e16d829ca7a83 100644 --- a/tests/ui/suggestions/option-to-bool.stderr +++ b/tests/ui/suggestions/option-to-bool.stderr @@ -13,6 +13,6 @@ help: use `Option::is_some` to test if the `Option` has a value LL | if true && x.is_some() {} | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/parenthesized-deref-suggestion.stderr b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr index cafddbe262424..9f185f5dd52b3 100644 --- a/tests/ui/suggestions/parenthesized-deref-suggestion.stderr +++ b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `opts` on type `*const Session` --> $DIR/parenthesized-deref-suggestion.rs:7:30 | LL | (sess as *const Session).opts; - | ^^^^ + | ^^^^ unknown field | help: `(sess as *const Session)` is a raw pointer; try dereferencing it | @@ -14,7 +14,8 @@ error[E0609]: no field `0` on type `[u32; 1]` | LL | (x as [u32; 1]).0; | ----------------^ - | | + | | | + | | unknown field | help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]` error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/path-by-value.stderr b/tests/ui/suggestions/path-by-value.stderr index fd3646b8c3c6a..567d9d5b9e7a4 100644 --- a/tests/ui/suggestions/path-by-value.stderr +++ b/tests/ui/suggestions/path-by-value.stderr @@ -13,6 +13,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn f(p: &Path) { } | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/private-field.stderr b/tests/ui/suggestions/private-field.stderr index c38c795e07ae8..0d73af03865f6 100644 --- a/tests/ui/suggestions/private-field.stderr +++ b/tests/ui/suggestions/private-field.stderr @@ -4,8 +4,8 @@ error[E0609]: no field `cap` on type `S` LL | dbg!(s.cap) | ^^^ unknown field | - = note: available fields are: `val` + = note: available field is: `val` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs new file mode 100644 index 0000000000000..3267527ecf2a7 --- /dev/null +++ b/tests/ui/suggestions/range-index-instead-of-colon.rs @@ -0,0 +1,7 @@ +// edition:2021 + +fn main() { + &[1, 2, 3][1:2]; + //~^ ERROR: expected one of + //~| HELP: you might have meant a range expression +} diff --git a/tests/ui/suggestions/range-index-instead-of-colon.stderr b/tests/ui/suggestions/range-index-instead-of-colon.stderr new file mode 100644 index 0000000000000..df29356cc16b3 --- /dev/null +++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr @@ -0,0 +1,13 @@ +error: expected one of `.`, `?`, `]`, or an operator, found `:` + --> $DIR/range-index-instead-of-colon.rs:4:17 + | +LL | &[1, 2, 3][1:2]; + | ^ expected one of `.`, `?`, `]`, or an operator + | +help: you might have meant a range expression + | +LL | &[1, 2, 3][1..2]; + | ~~ + +error: aborting due to 1 previous error + diff --git a/tests/ui/suggestions/remove-question-symbol-with-paren.stderr b/tests/ui/suggestions/remove-question-symbol-with-paren.stderr index 40b9cf2dcd4d4..bdea727a09816 100644 --- a/tests/ui/suggestions/remove-question-symbol-with-paren.stderr +++ b/tests/ui/suggestions/remove-question-symbol-with-paren.stderr @@ -20,6 +20,6 @@ help: try wrapping the expression in `Some` LL | (Some(x?)) | +++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/restrict-type-not-param.stderr b/tests/ui/suggestions/restrict-type-not-param.stderr index 3c7d42888d833..6d9780a871c57 100644 --- a/tests/ui/suggestions/restrict-type-not-param.stderr +++ b/tests/ui/suggestions/restrict-type-not-param.stderr @@ -18,6 +18,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn qux(a: Wrapper, b: T) -> T where Wrapper: Add { | ++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/suggestions/return-cycle-2.stderr b/tests/ui/suggestions/return-cycle-2.stderr index 3a1a0f7f4f543..23de2309e8778 100644 --- a/tests/ui/suggestions/return-cycle-2.stderr +++ b/tests/ui/suggestions/return-cycle-2.stderr @@ -7,6 +7,6 @@ LL | fn as_ref(_: i32, _: i32) -> _ { | not allowed in type signatures | help: replace with the correct return type: `Token<&'static T>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/suggestions/return-cycle.stderr b/tests/ui/suggestions/return-cycle.stderr index 63fa9e040874d..604704904410b 100644 --- a/tests/ui/suggestions/return-cycle.stderr +++ b/tests/ui/suggestions/return-cycle.stderr @@ -7,6 +7,6 @@ LL | fn new() -> _ { | not allowed in type signatures | help: replace with the correct return type: `Token<()>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/suggestions/shadowed-lplace-method-2.stderr b/tests/ui/suggestions/shadowed-lplace-method-2.stderr index 2956360980ec7..088da83f589dc 100644 --- a/tests/ui/suggestions/shadowed-lplace-method-2.stderr +++ b/tests/ui/suggestions/shadowed-lplace-method-2.stderr @@ -20,6 +20,6 @@ help: try wrapping the expression in `X` LL | *x.foo(0) = X { x: () }; | ++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/shadowed-lplace-method.stderr b/tests/ui/suggestions/shadowed-lplace-method.stderr index 33824c4cbc750..3e49716b03150 100644 --- a/tests/ui/suggestions/shadowed-lplace-method.stderr +++ b/tests/ui/suggestions/shadowed-lplace-method.stderr @@ -21,6 +21,6 @@ help: you might have meant to call the other method; you can use the fully-quali LL | *std::cell::RefCell::<_>::borrow_mut(&rc) = false; | +++++++++++++++++++++++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/silenced-binding-typo.stderr b/tests/ui/suggestions/silenced-binding-typo.stderr index 9c0e6e2656904..8dbd94208d614 100644 --- a/tests/ui/suggestions/silenced-binding-typo.stderr +++ b/tests/ui/suggestions/silenced-binding-typo.stderr @@ -9,6 +9,6 @@ help: a local variable with a similar name exists, consider changing it LL | let x = 42; | ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr index 80ad3f9e41bf2..fda5ac4e4f07a 100644 --- a/tests/ui/suggestions/sugg-else-for-closure.stderr +++ b/tests/ui/suggestions/sugg-else-for-closure.stderr @@ -22,6 +22,6 @@ help: try calling `unwrap_or_else` instead LL | let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap()); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr index 850f69f2d9853..be458f3bd53f2 100644 --- a/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr +++ b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr @@ -17,5 +17,5 @@ help: use the named argument by name to avoid ambiguity LL | println!("hello {world:?}", world = "world"); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr index 00fb96f032668..a30b78692146b 100644 --- a/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr +++ b/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr @@ -14,6 +14,6 @@ note: the candidate is defined in an impl for the type `Foo` LL | fn test() -> i32 { 1 } | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr index c247e73b39cb6..6e4c77deac50f 100644 --- a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr @@ -17,6 +17,6 @@ note: the candidate is defined in an impl for the type `GenericAssocMethod` LL | fn default_hello() {} | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr index 7c9f0b6c212e1..1bc2592944699 100644 --- a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr @@ -14,6 +14,6 @@ note: the candidate is defined in an impl for the type `HasAssocMethod` LL | fn hello() {} | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-box.stderr b/tests/ui/suggestions/suggest-box.stderr index e5d5ecc0be276..58f8774fe9ddd 100644 --- a/tests/ui/suggestions/suggest-box.stderr +++ b/tests/ui/suggestions/suggest-box.stderr @@ -21,6 +21,6 @@ LL | Ok(()) LL ~ }); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/suggest-closure-return-type-1.stderr b/tests/ui/suggestions/suggest-closure-return-type-1.stderr index f4c2eb7ff34ae..be473d3cfa28f 100644 --- a/tests/ui/suggestions/suggest-closure-return-type-1.stderr +++ b/tests/ui/suggestions/suggest-closure-return-type-1.stderr @@ -9,6 +9,6 @@ help: try giving this closure an explicit return type LL | unbound_drop(|| -> [_; 0] { [] }); | ~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/suggestions/suggest-closure-return-type-2.stderr b/tests/ui/suggestions/suggest-closure-return-type-2.stderr index 88bf263043d2c..f6c2a79b62bae 100644 --- a/tests/ui/suggestions/suggest-closure-return-type-2.stderr +++ b/tests/ui/suggestions/suggest-closure-return-type-2.stderr @@ -9,6 +9,6 @@ help: try giving this closure an explicit return type LL | unbound_drop(|| -> [_; 0] { [] }) | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/suggestions/suggest-closure-return-type-3.stderr b/tests/ui/suggestions/suggest-closure-return-type-3.stderr index bc4107528d274..d02e20eb7b74c 100644 --- a/tests/ui/suggestions/suggest-closure-return-type-3.stderr +++ b/tests/ui/suggestions/suggest-closure-return-type-3.stderr @@ -9,6 +9,6 @@ help: try giving this closure an explicit return type LL | unbound_drop(|| -> [_; 0] { [] }); | +++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index adf01339972e5..2316acbe9da28 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -8,11 +8,13 @@ LL | let one_item_please: i32 = [1, 2, 3][i]; = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `&usize` = note: required for `[{integer}]` to implement `Index<&usize>` + = note: 1 redundant requirement hidden + = note: required for `[{integer}; 3]` to implement `Index<&usize>` help: dereference this index | LL | let one_item_please: i32 = [1, 2, 3][*i]; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-field-through-deref.fixed b/tests/ui/suggestions/suggest-field-through-deref.fixed new file mode 100644 index 0000000000000..07ba3aa911f4e --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.fixed @@ -0,0 +1,21 @@ +// run-rustfix +#![allow(dead_code)] +use std::sync::Arc; +struct S { + long_name: (), + foo: (), +} +fn main() { + let x = Arc::new(S { long_name: (), foo: () }); + let _ = x.long_name; //~ ERROR no field `longname` + let y = S { long_name: (), foo: () }; + let _ = y.long_name; //~ ERROR no field `longname` + let a = Some(Arc::new(S { long_name: (), foo: () })); + let _ = a.unwrap().long_name; //~ ERROR no field `longname` + let b = Some(S { long_name: (), foo: () }); + let _ = b.unwrap().long_name; //~ ERROR no field `long_name` + let c = Ok::<_, ()>(Arc::new(S { long_name: (), foo: () })); + let _ = c.unwrap().long_name; //~ ERROR no field `longname` + let d = Ok::<_, ()>(S { long_name: (), foo: () }); + let _ = d.unwrap().long_name; //~ ERROR no field `long_name` +} diff --git a/tests/ui/suggestions/suggest-field-through-deref.rs b/tests/ui/suggestions/suggest-field-through-deref.rs new file mode 100644 index 0000000000000..6e24b425e9565 --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.rs @@ -0,0 +1,21 @@ +// run-rustfix +#![allow(dead_code)] +use std::sync::Arc; +struct S { + long_name: (), + foo: (), +} +fn main() { + let x = Arc::new(S { long_name: (), foo: () }); + let _ = x.longname; //~ ERROR no field `longname` + let y = S { long_name: (), foo: () }; + let _ = y.longname; //~ ERROR no field `longname` + let a = Some(Arc::new(S { long_name: (), foo: () })); + let _ = a.longname; //~ ERROR no field `longname` + let b = Some(S { long_name: (), foo: () }); + let _ = b.long_name; //~ ERROR no field `long_name` + let c = Ok::<_, ()>(Arc::new(S { long_name: (), foo: () })); + let _ = c.longname; //~ ERROR no field `longname` + let d = Ok::<_, ()>(S { long_name: (), foo: () }); + let _ = d.long_name; //~ ERROR no field `long_name` +} diff --git a/tests/ui/suggestions/suggest-field-through-deref.stderr b/tests/ui/suggestions/suggest-field-through-deref.stderr new file mode 100644 index 0000000000000..cc9fe2044c91e --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.stderr @@ -0,0 +1,69 @@ +error[E0609]: no field `longname` on type `Arc` + --> $DIR/suggest-field-through-deref.rs:10:15 + | +LL | let _ = x.longname; + | ^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = x.long_name; + | ~~~~~~~~~ + +error[E0609]: no field `longname` on type `S` + --> $DIR/suggest-field-through-deref.rs:12:15 + | +LL | let _ = y.longname; + | ^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = y.long_name; + | ~~~~~~~~~ + +error[E0609]: no field `longname` on type `Option>` + --> $DIR/suggest-field-through-deref.rs:14:15 + | +LL | let _ = a.longname; + | ^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = a.unwrap().long_name; + | ~~~~~~~~~~~~~~~~~~ + +error[E0609]: no field `long_name` on type `Option` + --> $DIR/suggest-field-through-deref.rs:16:15 + | +LL | let _ = b.long_name; + | ^^^^^^^^^ unknown field + | +help: one of the expressions' fields has a field of the same name + | +LL | let _ = b.unwrap().long_name; + | +++++++++ + +error[E0609]: no field `longname` on type `Result, ()>` + --> $DIR/suggest-field-through-deref.rs:18:15 + | +LL | let _ = c.longname; + | ^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = c.unwrap().long_name; + | ~~~~~~~~~~~~~~~~~~ + +error[E0609]: no field `long_name` on type `Result` + --> $DIR/suggest-field-through-deref.rs:20:15 + | +LL | let _ = d.long_name; + | ^^^^^^^^^ unknown field + | +help: one of the expressions' fields has a field of the same name + | +LL | let _ = d.unwrap().long_name; + | +++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr index 347a038525b60..bf7790e2307e0 100644 --- a/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr +++ b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr @@ -7,6 +7,6 @@ LL | fn bar() -> _ { Wrapper(foo) } | not allowed in type signatures | help: replace with the correct return type: `Wrapper` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr index 3fb3047d866c6..866162bab01e2 100644 --- a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr +++ b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr @@ -13,6 +13,6 @@ help: try wrapping the expression in `option::O::Some` LL | let _: option::O<()> = option::O::Some(()); | ++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr b/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr index 1660db1aa83c7..de2485b7be0c9 100644 --- a/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr +++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | fn foo(d: impl Debug + 'static) { | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/suggestions/suggest-let-for-assignment.fixed b/tests/ui/suggestions/suggest-let-for-assignment.fixed index 3a25e25eede62..76dc1dad80a90 100644 --- a/tests/ui/suggestions/suggest-let-for-assignment.fixed +++ b/tests/ui/suggestions/suggest-let-for-assignment.fixed @@ -7,6 +7,12 @@ fn main() { let x = "x"; //~ ERROR cannot find value `x` in this scope println!("x: {}", x); //~ ERROR cannot find value `x` in this scope + let some_variable = 6; //~ cannot find value `let_some_variable` in this scope + println!("some_variable: {}", some_variable); //~ ERROR cannot find value `some_variable` in this scope + + let other_variable = 6; //~ cannot find value `letother_variable` in this scope + println!("other_variable: {}", other_variable); //~ ERROR cannot find value `other_variable` in this scope + if x == "x" { //~^ ERROR cannot find value `x` in this scope println!("x is 1"); diff --git a/tests/ui/suggestions/suggest-let-for-assignment.rs b/tests/ui/suggestions/suggest-let-for-assignment.rs index 67705fe063a79..f1edf65a72614 100644 --- a/tests/ui/suggestions/suggest-let-for-assignment.rs +++ b/tests/ui/suggestions/suggest-let-for-assignment.rs @@ -7,6 +7,12 @@ fn main() { x = "x"; //~ ERROR cannot find value `x` in this scope println!("x: {}", x); //~ ERROR cannot find value `x` in this scope + let_some_variable = 6; //~ cannot find value `let_some_variable` in this scope + println!("some_variable: {}", some_variable); //~ ERROR cannot find value `some_variable` in this scope + + letother_variable = 6; //~ cannot find value `letother_variable` in this scope + println!("other_variable: {}", other_variable); //~ ERROR cannot find value `other_variable` in this scope + if x == "x" { //~^ ERROR cannot find value `x` in this scope println!("x is 1"); diff --git a/tests/ui/suggestions/suggest-let-for-assignment.stderr b/tests/ui/suggestions/suggest-let-for-assignment.stderr index 3f6a3da4be2b3..8d97dbeb14a7a 100644 --- a/tests/ui/suggestions/suggest-let-for-assignment.stderr +++ b/tests/ui/suggestions/suggest-let-for-assignment.stderr @@ -32,14 +32,48 @@ error[E0425]: cannot find value `x` in this scope LL | println!("x: {}", x); | ^ not found in this scope +error[E0425]: cannot find value `let_some_variable` in this scope + --> $DIR/suggest-let-for-assignment.rs:10:5 + | +LL | let_some_variable = 6; + | ^^^^^^^^^^^^^^^^^ + | +help: you might have meant to introduce a new binding + | +LL | let some_variable = 6; + | ~~~~~~~~~~~~~~~~~ + +error[E0425]: cannot find value `some_variable` in this scope + --> $DIR/suggest-let-for-assignment.rs:11:35 + | +LL | println!("some_variable: {}", some_variable); + | ^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `letother_variable` in this scope + --> $DIR/suggest-let-for-assignment.rs:13:5 + | +LL | letother_variable = 6; + | ^^^^^^^^^^^^^^^^^ + | +help: you might have meant to introduce a new binding + | +LL | let other_variable = 6; + | ~~~~~~~~~~~~~~~~~~ + +error[E0425]: cannot find value `other_variable` in this scope + --> $DIR/suggest-let-for-assignment.rs:14:36 + | +LL | println!("other_variable: {}", other_variable); + | ^^^^^^^^^^^^^^ not found in this scope + error[E0425]: cannot find value `x` in this scope - --> $DIR/suggest-let-for-assignment.rs:10:8 + --> $DIR/suggest-let-for-assignment.rs:16:8 | LL | if x == "x" { | ^ not found in this scope error[E0425]: cannot find value `y` in this scope - --> $DIR/suggest-let-for-assignment.rs:15:5 + --> $DIR/suggest-let-for-assignment.rs:21:5 | LL | y = 1 + 2; | ^ @@ -50,11 +84,11 @@ LL | let y = 1 + 2; | +++ error[E0425]: cannot find value `y` in this scope - --> $DIR/suggest-let-for-assignment.rs:16:23 + --> $DIR/suggest-let-for-assignment.rs:22:23 | LL | println!("y: {}", y); | ^ not found in this scope -error: aborting due to 7 previous errors +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-closure.stderr b/tests/ui/suggestions/suggest-mut-method-for-loop-closure.stderr index 8a2df8d7cc1ad..0bd286e0a6228 100644 --- a/tests/ui/suggestions/suggest-mut-method-for-loop-closure.stderr +++ b/tests/ui/suggestions/suggest-mut-method-for-loop-closure.stderr @@ -10,6 +10,6 @@ LL | for mut t in buzz.values() { LL | t.v += 1; | ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr index c442ed6377a8c..1be14aa8f55d6 100644 --- a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr +++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr @@ -10,6 +10,6 @@ LL | for (_k, v) in map.iter() { LL | v.v += 1; | ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop.stderr b/tests/ui/suggestions/suggest-mut-method-for-loop.stderr index 3eb9e1031d706..37bb25b300f3b 100644 --- a/tests/ui/suggestions/suggest-mut-method-for-loop.stderr +++ b/tests/ui/suggestions/suggest-mut-method-for-loop.stderr @@ -10,6 +10,6 @@ LL | for mut t in buzz.values() { LL | t.v += 1; | ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/suggest-pin-macro.stderr b/tests/ui/suggestions/suggest-pin-macro.stderr index 1220cf650cc3e..a761a454ad5a3 100644 --- a/tests/ui/suggestions/suggest-pin-macro.stderr +++ b/tests/ui/suggestions/suggest-pin-macro.stderr @@ -14,6 +14,6 @@ LL | struct Test { note: required by a bound in `Pin::<&'a mut T>::get_mut` --> $SRC_DIR/core/src/pin.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-remove-refs-1.stderr b/tests/ui/suggestions/suggest-remove-refs-1.stderr index 387770535f689..523f78dffcc67 100644 --- a/tests/ui/suggestions/suggest-remove-refs-1.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-1.stderr @@ -12,6 +12,6 @@ LL - for (i, _) in &v.iter().enumerate() { LL + for (i, _) in v.iter().enumerate() { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-remove-refs-2.stderr b/tests/ui/suggestions/suggest-remove-refs-2.stderr index 1632b2abb2f87..bbe3261e14869 100644 --- a/tests/ui/suggestions/suggest-remove-refs-2.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-2.stderr @@ -12,6 +12,6 @@ LL - for (i, _) in & & & & &v.iter().enumerate() { LL + for (i, _) in v.iter().enumerate() { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-remove-refs-3.stderr b/tests/ui/suggestions/suggest-remove-refs-3.stderr index 7bf421a7729df..a3e142563ff84 100644 --- a/tests/ui/suggestions/suggest-remove-refs-3.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-3.stderr @@ -16,6 +16,6 @@ LL - for (i, _) in & & & LL + for (i, _) in v | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-remove-refs-4.stderr b/tests/ui/suggestions/suggest-remove-refs-4.stderr index e4ad17e06716f..ed9fc2dd2568b 100644 --- a/tests/ui/suggestions/suggest-remove-refs-4.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-4.stderr @@ -12,6 +12,6 @@ LL ~ let foo = [1,2,3].iter(); LL ~ for _i in foo {} | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr index 352f6da3607bc..0da0241fe82c9 100644 --- a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr +++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr @@ -6,6 +6,6 @@ LL | async fn ice(_: &i32) { LL | true | ^^^^ expected `()`, found `bool` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr index c5df72c4a477f..12da91c20b3c5 100644 --- a/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr +++ b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr @@ -6,5 +6,5 @@ LL | fn foo() LL | } | - unexpected token -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/suggest-split-at-mut.stderr b/tests/ui/suggestions/suggest-split-at-mut.stderr index bb185138383f4..c42f09e3201db 100644 --- a/tests/ui/suggestions/suggest-split-at-mut.stderr +++ b/tests/ui/suggestions/suggest-split-at-mut.stderr @@ -11,6 +11,6 @@ LL | *a = 5; = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices = help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr index 0d1eed67c55e0..c0f0c41422736 100644 --- a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr +++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr @@ -4,6 +4,6 @@ error[E0223]: ambiguous associated type LL | impl Foo for Bar where for<'a> <&'a S>::Item: Foo {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'a S as IntoIterator>::Item` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr index 671f5efddd979..057e37dbe109f 100644 --- a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr +++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr @@ -4,8 +4,8 @@ error[E0433]: failed to resolve: use of undeclared type `TryFrom` LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap(); | ^^^^^^^ use of undeclared type `TryFrom` | - = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 + = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 help: consider importing one of these items | LL + use core::convert::TryFrom; @@ -19,8 +19,8 @@ error[E0433]: failed to resolve: use of undeclared type `TryInto` LL | let _i: i16 = TryInto::try_into(0_i32).unwrap(); | ^^^^^^^ use of undeclared type `TryInto` | - = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021 + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 help: consider importing one of these items | LL + use core::convert::TryInto; @@ -34,8 +34,8 @@ error[E0433]: failed to resolve: use of undeclared type `FromIterator` LL | let _v: Vec<_> = FromIterator::from_iter(&[1]); | ^^^^^^^^^^^^ use of undeclared type `FromIterator` | - = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 + = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 help: a trait with a similar name exists | LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]); diff --git a/tests/ui/suggestions/suggest_print_over_printf.stderr b/tests/ui/suggestions/suggest_print_over_printf.stderr index 1214bec16ce03..8a79745133c93 100644 --- a/tests/ui/suggestions/suggest_print_over_printf.stderr +++ b/tests/ui/suggestions/suggest_print_over_printf.stderr @@ -9,6 +9,6 @@ help: you may have meant to use the `print` macro LL | print!("%d", x); | ~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/too-many-field-suggestions.stderr b/tests/ui/suggestions/too-many-field-suggestions.stderr index 63ad6fdb16994..ac5c8cb60ccdc 100644 --- a/tests/ui/suggestions/too-many-field-suggestions.stderr +++ b/tests/ui/suggestions/too-many-field-suggestions.stderr @@ -25,7 +25,6 @@ error[E0609]: no field `field` on type `Thing` LL | t.field; | ^^^^^ unknown field | - = note: available fields are: `a0`, `a1`, `a2`, `a3`, `a4` ... and 5 others help: some of the expressions' fields have a field of the same name | LL | t.a0.field; diff --git a/tests/ui/suggestions/type-ascription-and-other-error.stderr b/tests/ui/suggestions/type-ascription-and-other-error.stderr index eadf634bb14fd..4efddca4b4714 100644 --- a/tests/ui/suggestions/type-ascription-and-other-error.stderr +++ b/tests/ui/suggestions/type-ascription-and-other-error.stderr @@ -4,5 +4,5 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found LL | not rust; | ^^^^ expected one of 8 possible tokens -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/type-ascription-instead-of-let.stderr b/tests/ui/suggestions/type-ascription-instead-of-let.stderr index 065b1f4d3538e..939990d744053 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-let.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-let.stderr @@ -9,5 +9,5 @@ help: you might have meant to introduce a new binding LL | let temp: i32 = fun(5i32); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.stderr b/tests/ui/suggestions/type-ascription-instead-of-method.stderr index b3799101cf0a5..3242b028d5d3e 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-method.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-method.stderr @@ -6,5 +6,5 @@ LL | let _ = Box:new("foo".to_string()); | = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr index 43d00591e74c0..ba0682cda3212 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr @@ -10,5 +10,5 @@ help: maybe write a path separator here LL | let _ = vec![Ok(2)].into_iter().collect::,_>>()?; | ~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/type-ascription-instead-of-path.stderr b/tests/ui/suggestions/type-ascription-instead-of-path.stderr index 849630218daed..566b036e53e4d 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-path.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-path.stderr @@ -6,5 +6,5 @@ LL | std:io::stdin(); | = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.stderr b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr index 11d0f5f527e21..6fea7f940523c 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-variant.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr @@ -6,5 +6,5 @@ LL | let _ = Option:Some(""); | = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr index 12466868f0028..fb3573ee2a4ee 100644 --- a/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr +++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr @@ -24,7 +24,12 @@ error[E0560]: struct `RGB` has no field named `c` --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25 | LL | let _ = RGB { r, g, c }; - | ^ help: a field with a similar name exists: `b` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = RGB { r, g, b }; + | ~ error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/undeclared-module-alloc.stderr b/tests/ui/suggestions/undeclared-module-alloc.stderr index 39169dfa9f777..a439546492b5f 100644 --- a/tests/ui/suggestions/undeclared-module-alloc.stderr +++ b/tests/ui/suggestions/undeclared-module-alloc.stderr @@ -6,6 +6,6 @@ LL | use alloc::rc::Rc; | = help: add `extern crate alloc` to use the `alloc` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/use-placement-resolve.stderr b/tests/ui/suggestions/use-placement-resolve.stderr index 77724e7e2a479..562e0bc3fbc1f 100644 --- a/tests/ui/suggestions/use-placement-resolve.stderr +++ b/tests/ui/suggestions/use-placement-resolve.stderr @@ -9,6 +9,6 @@ help: consider importing this trait instead LL + use std::fmt::Debug; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/suggestions/use-placement-typeck.stderr b/tests/ui/suggestions/use-placement-typeck.stderr index e900e12b7df0f..d8f2d58a24878 100644 --- a/tests/ui/suggestions/use-placement-typeck.stderr +++ b/tests/ui/suggestions/use-placement-typeck.stderr @@ -16,6 +16,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use m::Foo; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/super-at-top-level.stderr b/tests/ui/super-at-top-level.stderr index 23613df6752fb..4dce81fbef43f 100644 --- a/tests/ui/super-at-top-level.stderr +++ b/tests/ui/super-at-top-level.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: there are too many leading `super` keywords LL | use super::f; | ^^^^^ there are too many leading `super` keywords -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/svh/changing-crates.stderr b/tests/ui/svh/changing-crates.stderr index caefdfc96f038..130042e34ec70 100644 --- a/tests/ui/svh/changing-crates.stderr +++ b/tests/ui/svh/changing-crates.stderr @@ -9,6 +9,6 @@ LL | extern crate b; crate `a`: $PATH_a crate `b`: $PATH_b -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-lit.stderr b/tests/ui/svh/svh-change-lit.stderr index 5e890c6aa5795..b4d64a78e96b6 100644 --- a/tests/ui/svh/svh-change-lit.stderr +++ b/tests/ui/svh/svh-change-lit.stderr @@ -9,6 +9,6 @@ LL | extern crate b; crate `a`: $PATH_a crate `b`: $PATH_b -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-significant-cfg.stderr b/tests/ui/svh/svh-change-significant-cfg.stderr index dcc250d5216b0..7cbbcca993d06 100644 --- a/tests/ui/svh/svh-change-significant-cfg.stderr +++ b/tests/ui/svh/svh-change-significant-cfg.stderr @@ -9,6 +9,6 @@ LL | extern crate b; crate `a`: $PATH_a crate `b`: $PATH_b -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-trait-bound.stderr b/tests/ui/svh/svh-change-trait-bound.stderr index 2035993d218ec..b06b4a9617b54 100644 --- a/tests/ui/svh/svh-change-trait-bound.stderr +++ b/tests/ui/svh/svh-change-trait-bound.stderr @@ -9,6 +9,6 @@ LL | extern crate b; crate `a`: $PATH_a crate `b`: $PATH_b -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-type-arg.stderr b/tests/ui/svh/svh-change-type-arg.stderr index eef85aa954611..c3e2b436fe1fc 100644 --- a/tests/ui/svh/svh-change-type-arg.stderr +++ b/tests/ui/svh/svh-change-type-arg.stderr @@ -9,6 +9,6 @@ LL | extern crate b; crate `a`: $PATH_a crate `b`: $PATH_b -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-type-ret.stderr b/tests/ui/svh/svh-change-type-ret.stderr index 247f74e50df60..34602405dd101 100644 --- a/tests/ui/svh/svh-change-type-ret.stderr +++ b/tests/ui/svh/svh-change-type-ret.stderr @@ -9,6 +9,6 @@ LL | extern crate b; crate `a`: $PATH_a crate `b`: $PATH_b -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-type-static.stderr b/tests/ui/svh/svh-change-type-static.stderr index 78b54f227f0f0..94c2d9f15c5d6 100644 --- a/tests/ui/svh/svh-change-type-static.stderr +++ b/tests/ui/svh/svh-change-type-static.stderr @@ -9,6 +9,6 @@ LL | extern crate b; crate `a`: $PATH_a crate `b`: $PATH_b -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-use-trait.stderr b/tests/ui/svh/svh-use-trait.stderr index d8a81864dcaa8..31c16973b30ec 100644 --- a/tests/ui/svh/svh-use-trait.stderr +++ b/tests/ui/svh/svh-use-trait.stderr @@ -9,6 +9,6 @@ LL | extern crate utb; crate `uta`: $PATH_uta crate `utb`: $PATH_utb -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/switched-expectations.stderr b/tests/ui/switched-expectations.stderr index 6e1bbf701d77f..cc57674740020 100644 --- a/tests/ui/switched-expectations.stderr +++ b/tests/ui/switched-expectations.stderr @@ -6,6 +6,6 @@ LL | let ref string: String = var; | | | expected `String`, found `i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/symbol-names/foreign-types.stderr b/tests/ui/symbol-names/foreign-types.stderr index 9c8633742b249..6304499148526 100644 --- a/tests/ui/symbol-names/foreign-types.stderr +++ b/tests/ui/symbol-names/foreign-types.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_RMCsCRATE_HASH_13foreign_typesINtB_5CheckNvB_11ForeignTypeE) +error: symbol-name(_RMCsCRATE_HASH_13foreign_typesINtB_5CheckNtB_11ForeignTypeE) --> $DIR/foreign-types.rs:13:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/impl2.stderr b/tests/ui/symbol-names/impl2.stderr index 0c3205e0108e6..36f080b608366 100644 --- a/tests/ui/symbol-names/impl2.stderr +++ b/tests/ui/symbol-names/impl2.stderr @@ -4,5 +4,5 @@ error: def-path(<[u8; 1 + 2] as Foo>::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/sync/mutexguard-sync.stderr b/tests/ui/sync/mutexguard-sync.stderr index 4dc5571196c14..1501a793d5e8b 100644 --- a/tests/ui/sync/mutexguard-sync.stderr +++ b/tests/ui/sync/mutexguard-sync.stderr @@ -15,6 +15,6 @@ note: required by a bound in `test_sync` LL | fn test_sync(_t: T) {} | ^^^^ required by this bound in `test_sync` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/sync/suggest-once-cell.stderr b/tests/ui/sync/suggest-once-cell.stderr index 20242f4b61c71..8a9446a09b9ef 100644 --- a/tests/ui/sync/suggest-once-cell.stderr +++ b/tests/ui/sync/suggest-once-cell.stderr @@ -12,6 +12,6 @@ note: required by a bound in `require_sync` LL | fn require_sync() {} | ^^^^ required by this bound in `require_sync` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/sync/suggest-ref-cell.stderr b/tests/ui/sync/suggest-ref-cell.stderr index ca3ae77b1a052..9ef8ddc18cda5 100644 --- a/tests/ui/sync/suggest-ref-cell.stderr +++ b/tests/ui/sync/suggest-ref-cell.stderr @@ -12,6 +12,6 @@ note: required by a bound in `require_sync` LL | fn require_sync() {} | ^^^^ required by this bound in `require_sync` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/tag-type-args.stderr b/tests/ui/tag-type-args.stderr index 5b54880a68552..49ecf65b7e62f 100644 --- a/tests/ui/tag-type-args.stderr +++ b/tests/ui/tag-type-args.stderr @@ -14,6 +14,6 @@ help: add missing generic argument LL | fn foo(c: Quux) { assert!((false)); } | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/tag-variant-cast-non-nullary.stderr b/tests/ui/tag-variant-cast-non-nullary.stderr index ae2f5a7aead55..560dd7e8164f1 100644 --- a/tests/ui/tag-variant-cast-non-nullary.stderr +++ b/tests/ui/tag-variant-cast-non-nullary.stderr @@ -6,6 +6,6 @@ LL | let val = v as isize; | = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/tail-typeck.stderr b/tests/ui/tail-typeck.stderr index 10dfd2de744fc..0e470a7b4057f 100644 --- a/tests/ui/tail-typeck.stderr +++ b/tests/ui/tail-typeck.stderr @@ -11,6 +11,6 @@ help: you can convert a `usize` to an `isize` and panic if the converted value d LL | fn f() -> isize { return g().try_into().unwrap(); } | ++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 0ec7427c3c456..b3bd12600f8dc 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -7,6 +7,6 @@ LL | #[target_feature(enable = "avx512bw")] = note: see issue #44839 for more information = help: add `#![feature(avx512_target_feature)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/target-feature/similar-feature-suggestion.stderr b/tests/ui/target-feature/similar-feature-suggestion.stderr index 2f376065fdfb0..f39dfd401e07c 100644 --- a/tests/ui/target-feature/similar-feature-suggestion.stderr +++ b/tests/ui/target-feature/similar-feature-suggestion.stderr @@ -1,6 +1,6 @@ -warning: unknown feature specified for `-Ctarget-feature`: `rdrnd` +warning: unknown and unstable feature specified for `-Ctarget-feature`: `rdrnd` | - = note: it is still passed through to the codegen backend + = note: it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future = help: you might have meant: `rdrand` warning: 1 warning emitted diff --git a/tests/ui/target-feature/tied-features-cli.one.stderr b/tests/ui/target-feature/tied-features-cli.one.stderr index b4b50d98192b1..bf211fbee2f3a 100644 --- a/tests/ui/target-feature/tied-features-cli.one.stderr +++ b/tests/ui/target-feature/tied-features-cli.one.stderr @@ -1,4 +1,4 @@ error: the target features paca, pacg must all be either enabled or disabled together -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/target-feature/tied-features-cli.three.stderr b/tests/ui/target-feature/tied-features-cli.three.stderr index b4b50d98192b1..bf211fbee2f3a 100644 --- a/tests/ui/target-feature/tied-features-cli.three.stderr +++ b/tests/ui/target-feature/tied-features-cli.three.stderr @@ -1,4 +1,4 @@ error: the target features paca, pacg must all be either enabled or disabled together -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/target-feature/tied-features-cli.two.stderr b/tests/ui/target-feature/tied-features-cli.two.stderr index b4b50d98192b1..bf211fbee2f3a 100644 --- a/tests/ui/target-feature/tied-features-cli.two.stderr +++ b/tests/ui/target-feature/tied-features-cli.two.stderr @@ -1,4 +1,4 @@ error: the target features paca, pacg must all be either enabled or disabled together -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/target-feature/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs new file mode 100644 index 0000000000000..bd0d72938f4da --- /dev/null +++ b/tests/ui/target-feature/unstable-feature.rs @@ -0,0 +1,6 @@ +// compile-flags: -Ctarget-feature=+vaes --crate-type=rlib --target=x86_64-unknown-linux-gnu +// build-pass +// needs-llvm-components: x86 + +#![feature(no_core)] +#![no_core] diff --git a/tests/ui/target-feature/unstable-feature.stderr b/tests/ui/target-feature/unstable-feature.stderr new file mode 100644 index 0000000000000..d34544c5c2773 --- /dev/null +++ b/tests/ui/target-feature/unstable-feature.stderr @@ -0,0 +1,6 @@ +warning: unstable feature specified for `-Ctarget-feature`: `vaes` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: 1 warning emitted + diff --git a/tests/ui/test-attrs/custom-test-frameworks/issue-107454.stderr b/tests/ui/test-attrs/custom-test-frameworks/issue-107454.stderr index bd604afb79f8e..6ac79924d8057 100644 --- a/tests/ui/test-attrs/custom-test-frameworks/issue-107454.stderr +++ b/tests/ui/test-attrs/custom-test-frameworks/issue-107454.stderr @@ -11,5 +11,5 @@ LL | #![deny(unnameable_test_items)] | ^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `test_case` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/test-attrs/issue-109816.stderr b/tests/ui/test-attrs/issue-109816.stderr index e699328755556..6f5e3ae6b63f6 100644 --- a/tests/ui/test-attrs/issue-109816.stderr +++ b/tests/ui/test-attrs/issue-109816.stderr @@ -12,5 +12,5 @@ help: replace with conditional compilation to make the item only exist when test LL | #[cfg(test)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/test-attrs/issue-12997-2.stderr b/tests/ui/test-attrs/issue-12997-2.stderr index 2a3d0e3457b03..bc84ff413dfeb 100644 --- a/tests/ui/test-attrs/issue-12997-2.stderr +++ b/tests/ui/test-attrs/issue-12997-2.stderr @@ -16,6 +16,6 @@ LL | fn bar(x: isize) { } | ^^^ -------- = note: this error originates in the attribute macro `bench` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/test-attrs/test-panic-abort-disabled.stderr b/tests/ui/test-attrs/test-panic-abort-disabled.stderr index 9c65c7360c108..c6aeb41f5accc 100644 --- a/tests/ui/test-attrs/test-panic-abort-disabled.stderr +++ b/tests/ui/test-attrs/test-panic-abort-disabled.stderr @@ -1,4 +1,4 @@ error: building tests with panic=abort is not supported without `-Zpanic_abort_tests` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/test-attrs/test-warns-dead-code.stderr b/tests/ui/test-attrs/test-warns-dead-code.stderr index 6c0f288412846..1c58e3885a05c 100644 --- a/tests/ui/test-attrs/test-warns-dead-code.stderr +++ b/tests/ui/test-attrs/test-warns-dead-code.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/thread-local/thread-local-mutation.stderr b/tests/ui/thread-local/thread-local-mutation.stderr index e5dc0e72edfc7..9001de34adfb5 100644 --- a/tests/ui/thread-local/thread-local-mutation.stderr +++ b/tests/ui/thread-local/thread-local-mutation.stderr @@ -4,6 +4,6 @@ error[E0594]: cannot assign to immutable static item `S` LL | S = "after"; | ^^^^^^^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.mir.stderr similarity index 88% rename from tests/ui/thread-local/thread-local-static.stderr rename to tests/ui/thread-local/thread-local-static.mir.stderr index 712050a25fcfe..607d7ee902cb6 100644 --- a/tests/ui/thread-local/thread-local-static.stderr +++ b/tests/ui/thread-local/thread-local-static.mir.stderr @@ -1,5 +1,5 @@ error[E0658]: mutable references are not allowed in constant functions - --> $DIR/thread-local-static.rs:7:12 + --> $DIR/thread-local-static.rs:10:12 | LL | const fn g(x: &mut [u32; 8]) { | ^ @@ -8,13 +8,13 @@ LL | const fn g(x: &mut [u32; 8]) { = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0625]: thread-local statics cannot be accessed at compile-time - --> $DIR/thread-local-static.rs:9:28 + --> $DIR/thread-local-static.rs:12:28 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ error[E0013]: constant functions cannot refer to statics - --> $DIR/thread-local-static.rs:9:28 + --> $DIR/thread-local-static.rs:12:28 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) = help: consider extracting the value of the `static` to a `const`, and referring to that error[E0658]: mutable references are not allowed in constant functions - --> $DIR/thread-local-static.rs:9:23 + --> $DIR/thread-local-static.rs:12:23 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0133]: use of mutable static is unsafe and requires unsafe function or block - --> $DIR/thread-local-static.rs:9:23 + --> $DIR/thread-local-static.rs:12:23 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^^^^^^ use of mutable static diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs index c7fee9e6b4c5a..afaffbb7e9bbf 100644 --- a/tests/ui/thread-local/thread-local-static.rs +++ b/tests/ui/thread-local/thread-local-static.rs @@ -1,7 +1,10 @@ // edition:2018 +// revisions: mir thir +//thir: -Zthir-unsafeck #![feature(thread_local)] #![feature(const_swap)] + #[thread_local] static mut STATIC_VAR_2: [u32; 8] = [4; 8]; const fn g(x: &mut [u32; 8]) { diff --git a/tests/ui/thread-local/thread-local-static.thir.stderr b/tests/ui/thread-local/thread-local-static.thir.stderr new file mode 100644 index 0000000000000..607d7ee902cb6 --- /dev/null +++ b/tests/ui/thread-local/thread-local-static.thir.stderr @@ -0,0 +1,44 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:10:12 + | +LL | const fn g(x: &mut [u32; 8]) { + | ^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-static.rs:12:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + +error[E0013]: constant functions cannot refer to statics + --> $DIR/thread-local-static.rs:12:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:12:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/thread-local-static.rs:12:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0013, E0133, E0625, E0658. +For more information about an error, try `rustc --explain E0013`. diff --git a/tests/ui/tool-attributes/diagnostic_item.stderr b/tests/ui/tool-attributes/diagnostic_item.stderr index 743e4b658c6b7..a181aee6b5819 100644 --- a/tests/ui/tool-attributes/diagnostic_item.stderr +++ b/tests/ui/tool-attributes/diagnostic_item.stderr @@ -6,6 +6,6 @@ LL | #[rustc_diagnostic_item = "foomp"] | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/tool-attributes/tool-attributes-shadowing.stderr b/tests/ui/tool-attributes/tool-attributes-shadowing.stderr index 98ad109a07e8a..f2da617272288 100644 --- a/tests/ui/tool-attributes/tool-attributes-shadowing.stderr +++ b/tests/ui/tool-attributes/tool-attributes-shadowing.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: could not find `skip` in `rustfmt` LL | #[rustfmt::skip] | ^^^^ could not find `skip` in `rustfmt` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/tool_lints-fail.stderr b/tests/ui/tool_lints-fail.stderr index 16f678144a37d..7d80e0728f78c 100644 --- a/tests/ui/tool_lints-fail.stderr +++ b/tests/ui/tool_lints-fail.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unknown_lints)] | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/track-diagnostics/track2.stderr b/tests/ui/track-diagnostics/track2.stderr index fe13e5ef3f546..dffa0b0c91c1e 100644 --- a/tests/ui/track-diagnostics/track2.stderr +++ b/tests/ui/track-diagnostics/track2.stderr @@ -13,6 +13,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref _moved @ ref _from = String::from("foo"); | +++ +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/track-diagnostics/track4.stderr b/tests/ui/track-diagnostics/track4.stderr index 9ebf222ee342f..d9eaea93638d1 100644 --- a/tests/ui/track-diagnostics/track4.stderr +++ b/tests/ui/track-diagnostics/track4.stderr @@ -10,5 +10,5 @@ help: add `struct` here to parse `onion` as a public struct LL | pub struct onion { | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/track-diagnostics/track5.stderr b/tests/ui/track-diagnostics/track5.stderr index aa54f92b6c022..ecc7d81b3c36f 100644 --- a/tests/ui/track-diagnostics/track5.stderr +++ b/tests/ui/track-diagnostics/track5.stderr @@ -5,5 +5,5 @@ LL | } | ^ unexpected closing delimiter -Ztrack-diagnostics: created at compiler/rustc_parse/src/lexer/tokentrees.rs:LL:CC -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr index 583b02555b453..8ca56d6db2162 100644 --- a/tests/ui/track-diagnostics/track6.stderr +++ b/tests/ui/track-diagnostics/track6.stderr @@ -8,6 +8,6 @@ LL | default fn bar() {} = note: see issue #31844 for more information = help: add `#![feature(specialization)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr index 32f6b00b20c41..9a3bcaa0c4aa4 100644 --- a/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr +++ b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr @@ -8,6 +8,6 @@ LL | let _ = Option::<[u8]>::None; note: required by a bound in `None` --> $SRC_DIR/core/src/option.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr index 543ceac8e9178..84c2ab68da958 100644 --- a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr +++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr @@ -26,6 +26,6 @@ help: consider restricting the type parameter to satisfy the trait bound LL | struct Victim<'a, T: Perpetrator + ?Sized> where Self: Sized { | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr index f08d685836ec1..c597ad0b572ee 100644 --- a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr +++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr @@ -26,6 +26,6 @@ help: consider restricting the type parameter to satisfy the trait bound LL | Self: Sized, Self: Sized | +++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/trait-bounds/issue-82038.stderr b/tests/ui/trait-bounds/issue-82038.stderr index 30bb4a0a8509d..a97daece3b345 100644 --- a/tests/ui/trait-bounds/issue-82038.stderr +++ b/tests/ui/trait-bounds/issue-82038.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/trait-bounds/restrict-assoc-type-of-generic-bound.stderr b/tests/ui/trait-bounds/restrict-assoc-type-of-generic-bound.stderr index 61132efc414d8..5024ad21892a6 100644 --- a/tests/ui/trait-bounds/restrict-assoc-type-of-generic-bound.stderr +++ b/tests/ui/trait-bounds/restrict-assoc-type-of-generic-bound.stderr @@ -15,6 +15,6 @@ help: consider further restricting this bound LL | pub fn foo, B>(a: A) -> B { | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr index 4547e1c984c05..e2a72697501f2 100644 --- a/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr +++ b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr @@ -14,6 +14,6 @@ LL - pub struct A(pub H); LL + pub struct A(pub H); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/trait-impl-bound-suggestions.stderr b/tests/ui/trait-impl-bound-suggestions.stderr index 38679679cf935..c1f31e2b32e27 100644 --- a/tests/ui/trait-impl-bound-suggestions.stderr +++ b/tests/ui/trait-impl-bound-suggestions.stderr @@ -14,6 +14,6 @@ help: consider further restricting type parameter `X` LL | trait InsufficientlyConstrainedGeneric where X: std::marker::Copy { | ++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/trait-method-number-parameters.stderr b/tests/ui/trait-method-number-parameters.stderr index e47fe1a8026d5..cf9b4f2ae7913 100644 --- a/tests/ui/trait-method-number-parameters.stderr +++ b/tests/ui/trait-method-number-parameters.stderr @@ -8,6 +8,6 @@ LL | / &mut self, LL | | x: i32, | |______________^ expected 3 parameters, found 2 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0050`. diff --git a/tests/ui/traits/alias/ambiguous.stderr b/tests/ui/traits/alias/ambiguous.stderr index 203bdc526f6dd..034e8a3fb7b99 100644 --- a/tests/ui/traits/alias/ambiguous.stderr +++ b/tests/ui/traits/alias/ambiguous.stderr @@ -23,6 +23,6 @@ help: disambiguate the method for candidate #2 LL | B::foo(&t); | ~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/traits/alias/dont-elaborate-non-self.stderr b/tests/ui/traits/alias/dont-elaborate-non-self.stderr index 247a4f8128073..4e2edb474c06a 100644 --- a/tests/ui/traits/alias/dont-elaborate-non-self.stderr +++ b/tests/ui/traits/alias/dont-elaborate-non-self.stderr @@ -15,6 +15,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn f(a: &dyn F) {} | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/impl.stderr b/tests/ui/traits/alias/impl.stderr index cedcd10213da7..ff463f4793791 100644 --- a/tests/ui/traits/alias/impl.stderr +++ b/tests/ui/traits/alias/impl.stderr @@ -4,6 +4,6 @@ error[E0404]: expected trait, found trait alias `DefaultAlias` LL | impl DefaultAlias for () {} | ^^^^^^^^^^^^ not a trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr index 39f974f962c2b..968ad2667a210 100644 --- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr @@ -14,6 +14,6 @@ note: required by a bound in `f` LL | fn f(_: impl IteratorAlias) {} | ^^^^^^^^^^^^^ required by this bound in `f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr index f1b259d5a652d..74526b4dbc182 100644 --- a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr +++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr @@ -20,6 +20,6 @@ LL | impl Foo { | | | unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr index a78294da6c140..847fda417766a 100644 --- a/tests/ui/traits/alias/issue-83613.stderr +++ b/tests/ui/traits/alias/issue-83613.stderr @@ -6,6 +6,6 @@ LL | impl AnotherTrait for T {} LL | impl AnotherTrait for OpaqueType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/alias/self-in-const-generics.stderr b/tests/ui/traits/alias/self-in-const-generics.stderr index 61cc217cfbce6..3de31b64c8bf9 100644 --- a/tests/ui/traits/alias/self-in-const-generics.stderr +++ b/tests/ui/traits/alias/self-in-const-generics.stderr @@ -6,6 +6,6 @@ LL | fn foo(x: &dyn BB) {} | = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr index 80af4e5aae336..ffc0a00ad7d9b 100644 --- a/tests/ui/traits/alias/self-in-generics.stderr +++ b/tests/ui/traits/alias/self-in-generics.stderr @@ -6,6 +6,6 @@ LL | pub fn f(_f: &dyn SelfInput) {} | = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr index 6e03eeada499c..afe34a125b202 100644 --- a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr +++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr @@ -9,6 +9,6 @@ help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` LL | trait Strings = Iterator; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/alias/wf.stderr b/tests/ui/traits/alias/wf.stderr index 7172008d3eeae..3be6e8a49d692 100644 --- a/tests/ui/traits/alias/wf.stderr +++ b/tests/ui/traits/alias/wf.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | trait B = A; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/as-struct-constructor.stderr b/tests/ui/traits/as-struct-constructor.stderr index d06e85f3a2038..42353d210b44f 100644 --- a/tests/ui/traits/as-struct-constructor.stderr +++ b/tests/ui/traits/as-struct-constructor.stderr @@ -4,6 +4,6 @@ error[E0574]: expected struct, variant or union type, found trait `TraitNotAStru LL | TraitNotAStruct{ value: 0 }; | ^^^^^^^^^^^^^^^ not a struct, variant or union type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/traits/assoc-type-in-superbad.stderr b/tests/ui/traits/assoc-type-in-superbad.stderr index 7fa1d2c2eed67..2f07a32aa223d 100644 --- a/tests/ui/traits/assoc-type-in-superbad.stderr +++ b/tests/ui/traits/assoc-type-in-superbad.stderr @@ -10,6 +10,6 @@ note: required by a bound in `Foo` LL | pub trait Foo: Iterator::Key> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr index fa7a8a2a09335..e7e55d0beeeb4 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr @@ -11,6 +11,6 @@ note: required by a bound in `f` LL | fn f() { | ^ required by this bound in `f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr index 68b9319d65c76..b7a7784755ec0 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr @@ -11,6 +11,6 @@ note: required by a bound in `f` LL | fn f X<'r> + ?Sized>() { | ^^^^^^^^^^^^^ required by this bound in `f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr index c7af71a421438..77072656c3366 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr @@ -12,6 +12,6 @@ LL | LL | } | - `s` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr index 4891ee9c29f7e..5cc38e4371d1c 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr @@ -11,6 +11,6 @@ note: required by a bound in `f` LL | fn f() { | ^ required by this bound in `f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr index 00fdb37534613..3e9e6dcac91ae 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr @@ -17,6 +17,6 @@ note: required by a bound in `is_obj` LL | fn is_obj(_: &T) {} | ^^^ required by this bound in `is_obj` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr index 9b0975e5ed3c3..0e2a32735e96f 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr @@ -17,6 +17,6 @@ note: required by a bound in `is_obj` LL | fn is_obj(_: &T) {} | ^^^ required by this bound in `is_obj` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/bad-method-typaram-kind.stderr b/tests/ui/traits/bad-method-typaram-kind.stderr index 4c2d8e9f050a4..376a83e58a7d3 100644 --- a/tests/ui/traits/bad-method-typaram-kind.stderr +++ b/tests/ui/traits/bad-method-typaram-kind.stderr @@ -16,6 +16,6 @@ help: consider further restricting this bound LL | fn foo() { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr index f30fe12b216d6..c8631ed3677e8 100644 --- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -15,6 +15,6 @@ LL | s.strip_suffix(b'\n').unwrap_or(s) &'b str = note: required for `u8` to implement `Pattern<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index 36b08a7d30931..1d97bf3d8f957 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -29,6 +29,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn foo(_x: &Foo + Send) { | + -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr index 372bbabbd8621..48c3688a0446c 100644 --- a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr +++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr @@ -15,6 +15,6 @@ note: required by a bound in `Foo` LL | struct Foo { | ^^^^^ required by this bound in `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/sugar.stderr b/tests/ui/traits/bound/sugar.stderr index b67648c7b04da..3b3ab1e995c3b 100644 --- a/tests/ui/traits/bound/sugar.stderr +++ b/tests/ui/traits/bound/sugar.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn a(_x: Box) { | ^ ----------------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/cache-reached-depth-ice.stderr b/tests/ui/traits/cache-reached-depth-ice.stderr index 7cd75819277df..e84ebc91ae169 100644 --- a/tests/ui/traits/cache-reached-depth-ice.stderr +++ b/tests/ui/traits/cache-reached-depth-ice.stderr @@ -7,5 +7,5 @@ LL | fn test() {} LL | test::(); | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr index 30a3c40db95b3..26136c6f72c8b 100644 --- a/tests/ui/traits/coercion-generic-bad.stderr +++ b/tests/ui/traits/coercion-generic-bad.stderr @@ -8,6 +8,6 @@ LL | let s: Box> = Box::new(Struct { person: "Fred" }); = help: for that trait implementation, expected `&'static str`, found `isize` = note: required for the cast from `Box` to `Box>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/coercion-generic-regions.stderr b/tests/ui/traits/coercion-generic-regions.stderr index ae70202ab7ccd..576035f8c13e4 100644 --- a/tests/ui/traits/coercion-generic-regions.stderr +++ b/tests/ui/traits/coercion-generic-regions.stderr @@ -12,6 +12,6 @@ LL | let s: Box> = Box::new(Struct { person: person LL | } | - `person` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr index 7e676c9da011f..750140c017c25 100644 --- a/tests/ui/traits/copy-guessing.stderr +++ b/tests/ui/traits/copy-guessing.stderr @@ -9,6 +9,6 @@ help: consider giving `n` an explicit type, where the type for type parameter `T LL | let n: Option = None; | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr index 86c511c089567..3bdb8b70172c4 100644 --- a/tests/ui/traits/copy-impl-cannot-normalize.stderr +++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr @@ -19,6 +19,6 @@ help: consider restricting type parameter `T` LL | impl Copy for Foo {} | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr index 1304252118413..56544dd4def0a 100644 --- a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr +++ b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr @@ -17,6 +17,6 @@ help: consider restricting type parameter `'any` LL | impl<'any: 'static> Copy for Bar<'any> {} | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr index aee41c43aefeb..4f9615104cbf4 100644 --- a/tests/ui/traits/cycle-cache-err-60010.stderr +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -37,6 +37,6 @@ LL | where LL | DB: SourceDatabase, | -------------- unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr index 5a4dd1388b2e0..7ad10cfce984f 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr @@ -10,6 +10,6 @@ note: required because of this annotation LL | #[rustc_must_implement_one_of(eq, neq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr index 228bc3e35c21d..cb7eb1567c815 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr @@ -6,6 +6,6 @@ LL | #[rustc_must_implement_one_of(eq, neq)] | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/deny-builtin-object-impl.current.stderr b/tests/ui/traits/deny-builtin-object-impl.current.stderr index 8ca3d3a057fa3..0dbf8f0e668e8 100644 --- a/tests/ui/traits/deny-builtin-object-impl.current.stderr +++ b/tests/ui/traits/deny-builtin-object-impl.current.stderr @@ -15,6 +15,6 @@ note: required by a bound in `test_not_object` LL | fn test_not_object() {} | ^^^^^^^^^ required by this bound in `test_not_object` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/deny-builtin-object-impl.next.stderr b/tests/ui/traits/deny-builtin-object-impl.next.stderr index 8ca3d3a057fa3..0dbf8f0e668e8 100644 --- a/tests/ui/traits/deny-builtin-object-impl.next.stderr +++ b/tests/ui/traits/deny-builtin-object-impl.next.stderr @@ -15,6 +15,6 @@ note: required by a bound in `test_not_object` LL | fn test_not_object() {} | ^^^^^^^^^ required by this bound in `test_not_object` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr index 2185c51e59d87..460595dd961e0 100644 --- a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr +++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr @@ -17,6 +17,6 @@ help: try using a fully qualified path to specify the expected types LL | as Method>::method(thing, 42); | +++++++++++++++++++++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/duplicate-methods.stderr b/tests/ui/traits/duplicate-methods.stderr index 6aa88d0dff4fa..06232772678a9 100644 --- a/tests/ui/traits/duplicate-methods.stderr +++ b/tests/ui/traits/duplicate-methods.stderr @@ -8,6 +8,6 @@ LL | fn orange(&self); | = note: `orange` must be defined only once in the value namespace of this trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/ice-with-dyn-pointee-errors.stderr b/tests/ui/traits/ice-with-dyn-pointee-errors.stderr index 8ad11c3344a14..8bfda71bac1fb 100644 --- a/tests/ui/traits/ice-with-dyn-pointee-errors.stderr +++ b/tests/ui/traits/ice-with-dyn-pointee-errors.stderr @@ -14,6 +14,6 @@ note: required by a bound in `unknown_sized_object_ptr_in` LL | fn unknown_sized_object_ptr_in(_: &(impl Pointee + ?Sized)) {} | ^^^^^^^^^^^^^ required by this bound in `unknown_sized_object_ptr_in` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/ignore-err-impls.stderr b/tests/ui/traits/ignore-err-impls.stderr index 45bd533b5c6f0..955e2d7804981 100644 --- a/tests/ui/traits/ignore-err-impls.stderr +++ b/tests/ui/traits/ignore-err-impls.stderr @@ -9,6 +9,6 @@ help: you might be missing a type parameter LL | impl Generic for S {} | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/impl-1.stderr b/tests/ui/traits/impl-1.stderr index 7694e3f5cfae6..8c290addc7b68 100644 --- a/tests/ui/traits/impl-1.stderr +++ b/tests/ui/traits/impl-1.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `foo` found for reference `&i32` in the current sc LL | x.foo(); | ^^^ method not found in `&i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/impl-bounds-checking.stderr b/tests/ui/traits/impl-bounds-checking.stderr index bfa8213abe76f..61302bfa08882 100644 --- a/tests/ui/traits/impl-bounds-checking.stderr +++ b/tests/ui/traits/impl-bounds-checking.stderr @@ -15,6 +15,6 @@ note: required by a bound in `Getter` LL | trait Getter { | ^^^^^^ required by this bound in `Getter` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/impl-different-num-params.stderr b/tests/ui/traits/impl-different-num-params.stderr index 910ba35106410..0f73f5ca7dee5 100644 --- a/tests/ui/traits/impl-different-num-params.stderr +++ b/tests/ui/traits/impl-different-num-params.stderr @@ -7,6 +7,6 @@ LL | fn bar(&self, x: usize) -> Self; LL | fn bar(&self) -> isize { | ^^^^^ expected 2 parameters, found 1 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0050`. diff --git a/tests/ui/traits/impl-for-module.stderr b/tests/ui/traits/impl-for-module.stderr index 6ec4083b513db..b715c699e89f1 100644 --- a/tests/ui/traits/impl-for-module.stderr +++ b/tests/ui/traits/impl-for-module.stderr @@ -7,6 +7,6 @@ LL | trait A { LL | impl A for a { | ^ help: a trait with a similar name exists: `A` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/traits/impl-method-mismatch.stderr b/tests/ui/traits/impl-method-mismatch.stderr index 252b5aff96a01..2655d465f2363 100644 --- a/tests/ui/traits/impl-method-mismatch.stderr +++ b/tests/ui/traits/impl-method-mismatch.stderr @@ -12,6 +12,6 @@ LL | fn jumbo(&self, x: &usize) -> usize; = note: expected signature `fn(&usize, &usize) -> usize` found signature `unsafe fn(&usize, &usize)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr index 1bace8ab2864b..092776edea77d 100644 --- a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr +++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -22,6 +22,6 @@ LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { = note: expected `T1<'a>` found `T1<'_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/traits/inductive-overflow/lifetime.stderr b/tests/ui/traits/inductive-overflow/lifetime.stderr index 7ab2864a8cfdc..b34bb0361f1e4 100644 --- a/tests/ui/traits/inductive-overflow/lifetime.stderr +++ b/tests/ui/traits/inductive-overflow/lifetime.stderr @@ -15,6 +15,6 @@ note: required by a bound in `is_send` LL | fn is_send() {} | ^^^^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/inductive-overflow/simultaneous.stderr b/tests/ui/traits/inductive-overflow/simultaneous.stderr index e3b4ec07d2369..b9a746e44ba01 100644 --- a/tests/ui/traits/inductive-overflow/simultaneous.stderr +++ b/tests/ui/traits/inductive-overflow/simultaneous.stderr @@ -17,6 +17,6 @@ note: required by a bound in `is_ee` LL | fn is_ee(t: T) { | ^^^^^ required by this bound in `is_ee` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/inductive-overflow/supertrait.stderr b/tests/ui/traits/inductive-overflow/supertrait.stderr index b537ecf17213f..f2dccbbbb2cb6 100644 --- a/tests/ui/traits/inductive-overflow/supertrait.stderr +++ b/tests/ui/traits/inductive-overflow/supertrait.stderr @@ -17,6 +17,6 @@ note: required by a bound in `copy` LL | fn copy(x: T) -> (T, T) { (x, x) } | ^^^^^ required by this bound in `copy` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/invalid_operator_trait.stderr b/tests/ui/traits/invalid_operator_trait.stderr index 8c6e3695905ee..f2e5e9080b16e 100644 --- a/tests/ui/traits/invalid_operator_trait.stderr +++ b/tests/ui/traits/invalid_operator_trait.stderr @@ -4,5 +4,5 @@ error: `add` must not have any generic parameters LL | fn add(self, _: RHS) -> Self::Output; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/issue-18400.stderr b/tests/ui/traits/issue-18400.stderr index edaf08f490f13..146ba16397a20 100644 --- a/tests/ui/traits/issue-18400.stderr +++ b/tests/ui/traits/issue-18400.stderr @@ -15,6 +15,6 @@ LL | impl<'a, T, S> Set<&'a [T]> for S where = note: 128 redundant requirements hidden = note: required for `{integer}` to implement `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/issue-22384.stderr b/tests/ui/traits/issue-22384.stderr index 1f767a443d0f0..f53c95c2b677e 100644 --- a/tests/ui/traits/issue-22384.stderr +++ b/tests/ui/traits/issue-22384.stderr @@ -4,6 +4,6 @@ error[E0576]: cannot find associated type `foobar` in trait `Copy` LL | <::foobar as Trait>::foo(); | ^^^^^^ not found in `Copy` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0576`. diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index 203cd0630ebd0..9fe508646423e 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -15,6 +15,6 @@ LL | pub trait Bar: Foo { | | ...because it uses `Self` as a type parameter | this trait cannot be made into an object... -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr index 6b5b721384cbb..2bf365745a6bd 100644 --- a/tests/ui/traits/issue-43784-supertrait.stderr +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -19,6 +19,6 @@ help: consider restricting type parameter `T` LL | impl Complete for T {} | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr index c57921a08aabb..c37dde90e336f 100644 --- a/tests/ui/traits/issue-52893.stderr +++ b/tests/ui/traits/issue-52893.stderr @@ -24,6 +24,6 @@ note: method defined here LL | fn push(self, other: T) -> Self::PushRes; | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr index ae33e61d83b7a..22b5af43ba9fa 100644 --- a/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr +++ b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr @@ -12,6 +12,6 @@ help: the following trait defines an item `foo`, perhaps you need to restrict ty LL | fn do_stuff(t : T) { | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/issue-65673.stderr b/tests/ui/traits/issue-65673.stderr index 8f01d7c53e771..3c327f9edd51a 100644 --- a/tests/ui/traits/issue-65673.stderr +++ b/tests/ui/traits/issue-65673.stderr @@ -7,6 +7,6 @@ LL | trait Alias = where T: Trait; LL | type Ctx = dyn Alias; | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/issue-68295.stderr b/tests/ui/traits/issue-68295.stderr index 671a97666fdaa..8bc315302417b 100644 --- a/tests/ui/traits/issue-68295.stderr +++ b/tests/ui/traits/issue-68295.stderr @@ -12,6 +12,6 @@ LL | input.into_owned() = help: consider constraining the associated type `<() as Allocator>::Buffer` to `u32` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr index 1c0e8bcf18512..1749366317286 100644 --- a/tests/ui/traits/issue-7013.stderr +++ b/tests/ui/traits/issue-7013.stderr @@ -14,6 +14,6 @@ LL | struct B { | ^ = note: required for the cast from `Box` to `Box` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-71036.stderr b/tests/ui/traits/issue-71036.stderr index 79eb7a2ae8bd3..2452731f19f16 100644 --- a/tests/ui/traits/issue-71036.stderr +++ b/tests/ui/traits/issue-71036.stderr @@ -7,6 +7,6 @@ LL | impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-71136.stderr b/tests/ui/traits/issue-71136.stderr index ef55796187ee7..2c03c6bf08ed8 100644 --- a/tests/ui/traits/issue-71136.stderr +++ b/tests/ui/traits/issue-71136.stderr @@ -15,6 +15,6 @@ LL + #[derive(Clone)] LL | struct Foo(u8); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-72410.stderr b/tests/ui/traits/issue-72410.stderr index c7beb834b57f3..58266e1842e28 100644 --- a/tests/ui/traits/issue-72410.stderr +++ b/tests/ui/traits/issue-72410.stderr @@ -20,6 +20,6 @@ help: alternatively, consider constraining `map` so it does not apply to trait o LL | where for<'a> &'a mut [dyn Bar]:, Self: Sized ; | +++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-75627.stderr b/tests/ui/traits/issue-75627.stderr index 1675edc9ff0b9..137985ee04641 100644 --- a/tests/ui/traits/issue-75627.stderr +++ b/tests/ui/traits/issue-75627.stderr @@ -9,6 +9,6 @@ help: you might be missing a type parameter LL | unsafe impl Send for Foo {} | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/issue-79458.stderr b/tests/ui/traits/issue-79458.stderr index 08f7bbbf0eafe..c80efbe928729 100644 --- a/tests/ui/traits/issue-79458.stderr +++ b/tests/ui/traits/issue-79458.stderr @@ -11,6 +11,6 @@ LL | bar: &'a mut T = note: `Clone` is implemented for `&T`, but not for `&mut T` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-8153.stderr b/tests/ui/traits/issue-8153.stderr index ae214bb9e9b4f..8882097af3390 100644 --- a/tests/ui/traits/issue-8153.stderr +++ b/tests/ui/traits/issue-8153.stderr @@ -9,6 +9,6 @@ LL | fn bar(&self) -> isize {1} LL | fn bar(&self) -> isize {2} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0201`. diff --git a/tests/ui/traits/issue-85735.stderr b/tests/ui/traits/issue-85735.stderr index 9e80497ca6e92..0980c5c33bdb4 100644 --- a/tests/ui/traits/issue-85735.stderr +++ b/tests/ui/traits/issue-85735.stderr @@ -1,10 +1,10 @@ -error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>` +error[E0283]: type annotations needed: cannot satisfy `T: FnMut(&'a ())` --> $DIR/issue-85735.rs:7:8 | LL | T: FnMut(&'a ()), | ^^^^^^^^^^^^^ | -note: multiple `impl`s or `where` clauses satisfying `T: FnMut<(&'a (),)>` found +note: multiple `impl`s or `where` clauses satisfying `T: FnMut(&'a ())` found --> $DIR/issue-85735.rs:7:8 | LL | T: FnMut(&'a ()), @@ -13,6 +13,6 @@ LL | LL | T: FnMut(&'b ()), | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr index 85d903fadd120..13568179e81f4 100644 --- a/tests/ui/traits/issue-91594.stderr +++ b/tests/ui/traits/issue-91594.stderr @@ -13,6 +13,6 @@ LL | impl> Component for Foo { | | | unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr index 4593fa2c48570..c4324f0f0a872 100644 --- a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr +++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -25,6 +25,6 @@ LL | impl> Iterator for IteratorOfWrapped { = note: 256 redundant requirements hidden = note: required for `IteratorOfWrapped<(), Map>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48}>>` to implement `Iterator` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/issue-95898.stderr b/tests/ui/traits/issue-95898.stderr index ca7bacdbf41ba..0bb0b2840e5a9 100644 --- a/tests/ui/traits/issue-95898.stderr +++ b/tests/ui/traits/issue-95898.stderr @@ -12,6 +12,6 @@ help: the following trait defines an item `clone`, perhaps you need to restrict LL | fn foo(t: T) { | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/issue-97576.stderr b/tests/ui/traits/issue-97576.stderr index 9062a0fab630a..2c6cfd83b9571 100644 --- a/tests/ui/traits/issue-97576.stderr +++ b/tests/ui/traits/issue-97576.stderr @@ -6,6 +6,6 @@ LL | bar: bar.into(), | = note: required for `impl ToString` to implement `Into` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/map-types.stderr b/tests/ui/traits/map-types.stderr index 4315056f2065f..b19b5d2e1dd32 100644 --- a/tests/ui/traits/map-types.stderr +++ b/tests/ui/traits/map-types.stderr @@ -7,6 +7,6 @@ LL | let y: Box> = Box::new(x); = help: the trait `Map` is implemented for `HashMap` = note: required for the cast from `Box>>` to `Box>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/method-private.stderr b/tests/ui/traits/method-private.stderr index e11799308c5c7..d19f0bc086b28 100644 --- a/tests/ui/traits/method-private.stderr +++ b/tests/ui/traits/method-private.stderr @@ -13,6 +13,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use inner::Bar; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/traits/multidispatch-bad.stderr b/tests/ui/traits/multidispatch-bad.stderr index d58f1e2d9e59c..0bb095fb0e13f 100644 --- a/tests/ui/traits/multidispatch-bad.stderr +++ b/tests/ui/traits/multidispatch-bad.stderr @@ -16,6 +16,6 @@ help: change the type of the numeric literal from `i32` to `u32` LL | test(22i32, 44u32); | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr index e3bfc78bb08d5..17c3db9ad33ee 100644 --- a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr @@ -26,6 +26,6 @@ help: consider specifying the generic arguments LL | test::(22, std::default::Default::default()); | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr index 23e182738f700..420ed2dcd2f09 100644 --- a/tests/ui/traits/mutual-recursion-issue-75860.stderr +++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr @@ -8,6 +8,6 @@ LL | iso(left, right) note: required by a bound in `Option` --> $SRC_DIR/core/src/option.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr index b253fbd0da7f9..a232e6d8619b2 100644 --- a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr @@ -7,6 +7,6 @@ LL | impl !MyTrait for u32 {} = note: see issue #68318 for more information = help: add `#![feature(negative_impls)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/negative-impls/negative-default-impls.stderr b/tests/ui/traits/negative-impls/negative-default-impls.stderr index 7b54cf542220f..328e744a1e39b 100644 --- a/tests/ui/traits/negative-impls/negative-default-impls.stderr +++ b/tests/ui/traits/negative-impls/negative-default-impls.stderr @@ -14,6 +14,6 @@ error[E0750]: negative impls cannot be default impls LL | default impl !MyTrait for u32 {} | ^^^^^^^ ^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0750`. diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr index 1cfa49b20f35b..97727da76f26a 100644 --- a/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr +++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr @@ -17,6 +17,6 @@ LL | impl MyTrait for T { LL | impl !MyTrait for u32 {} | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr index 9f9e28678abcb..100f97aba93c5 100644 --- a/tests/ui/traits/negative-impls/negative-specializes-positive.stderr +++ b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr @@ -16,6 +16,6 @@ LL | impl MyTrait for T {} LL | impl !MyTrait for u32 {} | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/no-items.stderr b/tests/ui/traits/negative-impls/no-items.stderr index 040d9d14503f0..36436dfba9dfc 100644 --- a/tests/ui/traits/negative-impls/no-items.stderr +++ b/tests/ui/traits/negative-impls/no-items.stderr @@ -4,6 +4,6 @@ error[E0749]: negative impls cannot have any items LL | type Foo = i32; | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0749`. diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr index a87acb1fb0976..4778f31ff3a04 100644 --- a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr @@ -6,6 +6,6 @@ LL | impl<'a> Clone for &'a mut MyType<'a> { | = note: negative implementation in crate `core` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr index 9185e8f8430bf..95d7f6ba912de 100644 --- a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr @@ -6,6 +6,6 @@ LL | impl<'a> DerefMut for &'a MyType<'a> { | = note: negative implementation in crate `core` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.stderr b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr index 545f94143adde..1655cb05019cc 100644 --- a/tests/ui/traits/negative-impls/positive-specializes-negative.stderr +++ b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr @@ -16,6 +16,6 @@ LL | impl !MyTrait for T {} LL | impl MyTrait for u32 {} | ^^^^^^^^^^^^^^^^^^^^ positive implementation here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs index 825e874d71bcb..907a30103551c 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs @@ -23,7 +23,7 @@ fn main() { let x = String::from("hello, world"); drop(<() as Foo>::copy_me(&x)); //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized` - //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` + //~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr index ca4b5c90ff280..29d4d983c03ec 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr @@ -19,7 +19,7 @@ LL | drop(<() as Foo>::copy_me(&x)); | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` --> $DIR/alias-bound-unsound.rs:24:10 | LL | drop(<() as Foo>::copy_me(&x)); diff --git a/tests/ui/traits/new-solver/alias-relate/deeply-nested-no-hang.rs b/tests/ui/traits/new-solver/alias-relate/deeply-nested-no-hang.rs new file mode 100644 index 0000000000000..4abce7b57d50d --- /dev/null +++ b/tests/ui/traits/new-solver/alias-relate/deeply-nested-no-hang.rs @@ -0,0 +1,22 @@ +// check-pass +// compile-flags: -Ztrait-solver=next +// regression test for trait-system-refactor-initiative#68 +trait Identity { + type Assoc: ?Sized; +} + +impl Identity for T { + type Assoc = T; +} + +type Id = ::Assoc; + +type Five = Id>>>>; +type Ty = Five>>>>; + +trait Trait {} + +impl Trait for Ty {} +impl Trait for Ty {} + +fn main() {} diff --git a/tests/ui/traits/new-solver/alias-relate/opaque-hidden-ty-is-rigid-alias.rs b/tests/ui/traits/new-solver/alias-relate/opaque-hidden-ty-is-rigid-alias.rs new file mode 100644 index 0000000000000..29a73e1a96799 --- /dev/null +++ b/tests/ui/traits/new-solver/alias-relate/opaque-hidden-ty-is-rigid-alias.rs @@ -0,0 +1,8 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +fn test(x: T::Item) -> impl Sized { + x +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr index 46677a583160d..8c6840f72a7ff 100644 --- a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr +++ b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr @@ -8,6 +8,6 @@ LL | impl Overlaps for ::Assoc {} | = note: downstream crates may implement trait `TraitB` for type `std::boxed::Box<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr index 414deb47727e3..4bd55ee80c6bb 100644 --- a/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr +++ b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr @@ -11,6 +11,6 @@ note: required by a bound in `iter` LL | fn iter() -> ::Item { | ^^^^^^^^ required by this bound in `iter` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/async.fail.stderr b/tests/ui/traits/new-solver/async.fail.stderr index 44097b556fc11..ebd0ada2604c6 100644 --- a/tests/ui/traits/new-solver/async.fail.stderr +++ b/tests/ui/traits/new-solver/async.fail.stderr @@ -12,6 +12,6 @@ note: required by a bound in `needs_async` LL | fn needs_async(_: impl Future) {} | ^^^^^^^^^^^^ required by this bound in `needs_async` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr index 4aefdd6bb0735..ac05dfb2d46f2 100644 --- a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr +++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr @@ -13,6 +13,6 @@ note: required by a bound in `is_send` LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/borrowck-error.stderr b/tests/ui/traits/new-solver/borrowck-error.stderr index a7d8201747a12..4cb41e7d59784 100644 --- a/tests/ui/traits/new-solver/borrowck-error.stderr +++ b/tests/ui/traits/new-solver/borrowck-error.stderr @@ -7,6 +7,6 @@ LL | &HashMap::new() | |temporary value created here | returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr index 4eaa259617bac..08047852f203a 100644 --- a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr +++ b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr @@ -11,6 +11,6 @@ note: required by a bound in `foo` LL | fn foo, T: Tuple>(f: Option, t: T) { | ^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/coherence/issue-102048.stderr b/tests/ui/traits/new-solver/coherence/issue-102048.stderr index 41bf68a1d9f39..4e93ae2849695 100644 --- a/tests/ui/traits/new-solver/coherence/issue-102048.stderr +++ b/tests/ui/traits/new-solver/coherence/issue-102048.stderr @@ -11,6 +11,6 @@ LL | / impl Trait fn(>::Assoc, u32)> for (T, U LL | | U: for<'a> WithAssoc1<'a> | |_____________________________^ conflicting implementation for `(_, _)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index 73d46c4df9602..e3c0dabf549e8 100644 --- a/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -1,7 +1,3 @@ -WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <::Assoc as std::marker::Sized> -WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <::Assoc as std::marker::Sized> -WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <::Assoc as std::marker::Sized> -WARN rustc_trait_selection::traits::coherence expected an unknowable trait ref: <::Assoc as std::marker::Sized> error[E0119]: conflicting implementations of trait `Trait` for type `::Assoc` --> $DIR/trait_ref_is_knowable-norm-overflow.rs:17:1 | @@ -10,9 +6,7 @@ LL | impl Trait for T {} LL | struct LocalTy; LL | impl Trait for ::Assoc {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `::Assoc` - | - = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `::Assoc` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr b/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr index 4db6e22e57ffa..163710706b04d 100644 --- a/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr +++ b/tests/ui/traits/new-solver/const-param-placeholder.fail.stderr @@ -11,6 +11,6 @@ note: required by a bound in `needs_foo` LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr index 1ac0e297729ce..05aaf6108f1da 100644 --- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr +++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr @@ -11,6 +11,6 @@ note: required by a bound in `impls` LL | fn impls() {} | ^^^^^ required by this bound in `impls` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr index f1871ff0564a1..d4932191791fd 100644 --- a/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr +++ b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr @@ -11,6 +11,6 @@ note: required by a bound in `impls_trait` LL | fn impls_trait, U: ?Sized, V: ?Sized, D: ?Sized>() {} | ^^^^^^^^^^^^^^ required by this bound in `impls_trait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr index 4cbd0898148a5..7b3075f4ff35a 100644 --- a/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr +++ b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr @@ -6,5 +6,5 @@ LL | fn check<'a, T: ?Sized>() { LL | impls_trait::<'a, 'static, A>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr index 57227321a6dbc..acacaf6a331d9 100644 --- a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr @@ -11,6 +11,6 @@ note: required by a bound in `impls_trait` LL | fn impls_trait() {} | ^^^^^ required by this bound in `impls_trait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr index 5a7459ec1fdee..576ede52aff2d 100644 --- a/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr +++ b/tests/ui/traits/new-solver/dont-normalize-proj-with-error.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `TypeError` in this scope LL | fn type_error() -> TypeError { todo!() } | ^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr index a31bfd9589b3b..076dab29d890b 100644 --- a/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr +++ b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr @@ -11,6 +11,6 @@ note: required by a bound in `needs_send` LL | fn needs_send() {} | ^^^^ required by this bound in `needs_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/equating-projection-cyclically.rs b/tests/ui/traits/new-solver/equating-projection-cyclically.rs index 2668da1b745df..845597e9ce198 100644 --- a/tests/ui/traits/new-solver/equating-projection-cyclically.rs +++ b/tests/ui/traits/new-solver/equating-projection-cyclically.rs @@ -1,3 +1,4 @@ +// check-pass // compile-flags: -Ztrait-solver=next trait Test { @@ -22,7 +23,9 @@ fn main() { let mut x: Inv<_> = Inv(None); // This ends up equating `Inv` with `Inv<::Assoc>` // which fails the occurs check when generalizing `?x`. + // + // We end up emitting a delayed obligation, causing this to still + // succeed. x = transform(x); - //~^ ERROR mismatched types x = Inv::(None); } diff --git a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr b/tests/ui/traits/new-solver/equating-projection-cyclically.stderr deleted file mode 100644 index 6031d4f08ee9a..0000000000000 --- a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/equating-projection-cyclically.rs:25:9 - | -LL | x = transform(x); - | ^^^^^^^^^^^^ cyclic type of infinite size - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs index 94d645a98592c..7fe242f4714e0 100644 --- a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs +++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs @@ -1,5 +1,7 @@ // compile-flags: -Ztrait-solver=next // known-bug: trait-system-refactor-initiative#60 +// dont-check-failure-status +// dont-check-compiler-stderr // Generalizing a projection containing an inference variable // which cannot be named by the `root_vid` can result in ambiguity. diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr index 9aa4f4531f95d..b2a523ba62052 100644 --- a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr +++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr @@ -13,6 +13,6 @@ LL | where LL | T: WithAssoc, | ^^^^^^^^^ required by this bound in `bound` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr new file mode 100644 index 0000000000000..ad8b24a39c701 --- /dev/null +++ b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr @@ -0,0 +1,11 @@ +error[E0275]: overflow evaluating the requirement `<>::Id as Unnormalizable>::Assoc == _` + --> $DIR/occurs-check-nested-alias.rs:36:9 + | +LL | x = y; + | ^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`occurs_check_nested_alias`) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs new file mode 100644 index 0000000000000..02ac091c0a8a4 --- /dev/null +++ b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs @@ -0,0 +1,38 @@ +// revisions: old next +//[old] check-pass + +// Currently always fails to generalize the outer alias, even if it +// is treated as rigid by `alias-relate`. +//[next] compile-flags: -Ztrait-solver=next +//[next] known-bug: trait-system-refactor-initiative#8 +#![crate_type = "lib"] +#![allow(unused)] +trait Unnormalizable { + type Assoc; +} + +trait Id { + type Id; +} +impl Id for U { + type Id = U; +} + +struct Inv(*mut T); + +fn unconstrained() -> T { + todo!() +} + +fn create( + x: &U, +) -> (Inv, Inv<<>::Id as Unnormalizable>::Assoc>) { + todo!() +} + +fn foo() { + let q = unconstrained(); + let (mut x, y) = create::<_, _>(&q); + x = y; + drop::(q); +} diff --git a/tests/ui/traits/new-solver/more-object-bound.stderr b/tests/ui/traits/new-solver/more-object-bound.stderr index 54965dee184ab..e3be2931e1232 100644 --- a/tests/ui/traits/new-solver/more-object-bound.stderr +++ b/tests/ui/traits/new-solver/more-object-bound.stderr @@ -17,6 +17,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn transmute(x: A) -> B where dyn Trait: Trait { | ++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/normalize-unsize-rhs.rs b/tests/ui/traits/new-solver/normalize-unsize-rhs.rs index a398ab4f2f2cd..1bb5c9b4111a7 100644 --- a/tests/ui/traits/new-solver/normalize-unsize-rhs.rs +++ b/tests/ui/traits/new-solver/normalize-unsize-rhs.rs @@ -1,8 +1,6 @@ // compile-flags: -Ztrait-solver=next // check-pass -#![feature(trait_upcasting)] - trait A {} trait B: A {} diff --git a/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr index f482e8cfaf966..c1a8b74df0824 100644 --- a/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr +++ b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr @@ -17,6 +17,6 @@ help: consider specifying the generic argument LL | foo::(unconstrained()) | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr index 023efc41aeb38..90b54b1e78980 100644 --- a/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr +++ b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr @@ -11,6 +11,6 @@ note: required by a bound in `impls` LL | fn impls() {} | ^^^^^ required by this bound in `impls` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/overflow/global-cache.stderr b/tests/ui/traits/new-solver/overflow/global-cache.stderr index ebb03d84b8710..67616619384c6 100644 --- a/tests/ui/traits/new-solver/overflow/global-cache.stderr +++ b/tests/ui/traits/new-solver/overflow/global-cache.stderr @@ -11,6 +11,6 @@ note: required by a bound in `impls_trait` LL | fn impls_trait() {} | ^^^^^ required by this bound in `impls_trait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/pointer-like.stderr b/tests/ui/traits/new-solver/pointer-like.stderr index 215a81cc26573..4b624fd0d3545 100644 --- a/tests/ui/traits/new-solver/pointer-like.stderr +++ b/tests/ui/traits/new-solver/pointer-like.stderr @@ -19,6 +19,6 @@ LL | require_(&1u16); LL | require_(&mut 1u16); | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/projection-discr-kind.stderr b/tests/ui/traits/new-solver/projection-discr-kind.stderr index e14953f19ff37..69999c755228f 100644 --- a/tests/ui/traits/new-solver/projection-discr-kind.stderr +++ b/tests/ui/traits/new-solver/projection-discr-kind.stderr @@ -17,6 +17,6 @@ note: required by a bound in `needs_bar` LL | fn needs_bar(_: impl Bar) {} | ^^^ required by this bound in `needs_bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs new file mode 100644 index 0000000000000..e36d574efe264 --- /dev/null +++ b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs @@ -0,0 +1,14 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1 +// a minimization of a pattern in core. +fn next, U>(t: &mut T) -> Option { + t.next() +} + +fn foo(t: &mut T) { + let _: Option = next(t); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs new file mode 100644 index 0000000000000..c8050997a1d2a --- /dev/null +++ b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs @@ -0,0 +1,29 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1, +// a minimization of a pattern in core. + +trait Iterator { + type Item; +} + +struct Flatten(I); + +impl Iterator for Flatten +where + I: Iterator, +{ + type Item = U; +} + +fn needs_iterator() {} + +fn environment() +where + J: Iterator, +{ + needs_iterator::>(); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs index f6b19e7adf512..fac7d76f8cf5f 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.rs +++ b/tests/ui/traits/new-solver/specialization-transmute.rs @@ -10,7 +10,7 @@ trait Default { } impl Default for T { - default type Id = T; + default type Id = T; //~ ERROR type annotations needed // This will be fixed by #111994 fn intu(&self) -> &Self::Id { //~ ERROR type annotations needed self diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr index 09b1405fefbf3..eaf32a475ac95 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.stderr +++ b/tests/ui/traits/new-solver/specialization-transmute.stderr @@ -8,14 +8,19 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error[E0284]: type annotations needed +error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to _` --> $DIR/specialization-transmute.rs:15:23 | LL | fn intu(&self) -> &Self::Id { - | ^^^^^^^^^ cannot infer type + | ^^^^^^^^^ cannot satisfy `::Id normalizes-to _` + +error[E0282]: type annotations needed + --> $DIR/specialization-transmute.rs:13:23 | - = note: cannot satisfy `::Id == _` +LL | default type Id = T; + | ^ cannot infer type for associated type `::Id` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.rs b/tests/ui/traits/new-solver/specialization-unconstrained.rs index 02150689ee5c3..7fd753109be2d 100644 --- a/tests/ui/traits/new-solver/specialization-unconstrained.rs +++ b/tests/ui/traits/new-solver/specialization-unconstrained.rs @@ -11,7 +11,7 @@ trait Default { } impl Default for T { - default type Id = T; + default type Id = T; //~ ERROR type annotations needed } fn test, U>() {} diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr index 910925cbaeb0d..ed4dafa1484c2 100644 --- a/tests/ui/traits/new-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/new-solver/specialization-unconstrained.stderr @@ -20,6 +20,13 @@ note: required by a bound in `test` LL | fn test, U>() {} | ^^^^^^ required by this bound in `test` -error: aborting due to previous error; 1 warning emitted +error[E0282]: type annotations needed + --> $DIR/specialization-unconstrained.rs:14:22 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `::Id` + +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr b/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr index a3ab7836c193b..2e3c22c8d384f 100644 --- a/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr +++ b/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr @@ -12,6 +12,6 @@ note: required by a bound in `needs_foo` LL | fn needs_foo(x: impl Foo) {} | ^^^ required by this bound in `needs_foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs b/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs index 43cd773bf3ce6..79114b93b78df 100644 --- a/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs +++ b/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs @@ -1,8 +1,6 @@ // check-pass // compile-flags: -Ztrait-solver=next -#![feature(trait_upcasting)] - pub trait A {} pub trait B: A {} diff --git a/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.stderr index b311ac6b5a615..dfff9f11b8756 100644 --- a/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.stderr +++ b/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.stderr @@ -12,6 +12,6 @@ note: required by a bound in `needs_bar` LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/unevaluated-const-impl-trait-ref.fails.stderr b/tests/ui/traits/new-solver/unevaluated-const-impl-trait-ref.fails.stderr index 072ac32a5de97..4be90c702a035 100644 --- a/tests/ui/traits/new-solver/unevaluated-const-impl-trait-ref.fails.stderr +++ b/tests/ui/traits/new-solver/unevaluated-const-impl-trait-ref.fails.stderr @@ -13,6 +13,6 @@ note: required by a bound in `needs` LL | fn needs() where (): Trait {} | ^^^^^^^^ required by this bound in `needs` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/upcast-right-substs.rs b/tests/ui/traits/new-solver/upcast-right-substs.rs index c19c82acf24ff..97eb189d5c730 100644 --- a/tests/ui/traits/new-solver/upcast-right-substs.rs +++ b/tests/ui/traits/new-solver/upcast-right-substs.rs @@ -1,8 +1,6 @@ // compile-flags: -Ztrait-solver=next // check-pass -#![feature(trait_upcasting)] - trait Foo: Bar + Bar {} trait Bar {} diff --git a/tests/ui/traits/new-solver/upcast-wrong-substs.rs b/tests/ui/traits/new-solver/upcast-wrong-substs.rs index f2d04d932bbcb..3376f9787d36c 100644 --- a/tests/ui/traits/new-solver/upcast-wrong-substs.rs +++ b/tests/ui/traits/new-solver/upcast-wrong-substs.rs @@ -1,7 +1,5 @@ // compile-flags: -Ztrait-solver=next -#![feature(trait_upcasting)] - trait Foo: Bar + Bar {} trait Bar {} diff --git a/tests/ui/traits/new-solver/upcast-wrong-substs.stderr b/tests/ui/traits/new-solver/upcast-wrong-substs.stderr index 8623f395f5978..00ba1ef678f46 100644 --- a/tests/ui/traits/new-solver/upcast-wrong-substs.stderr +++ b/tests/ui/traits/new-solver/upcast-wrong-substs.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/upcast-wrong-substs.rs:11:30 + --> $DIR/upcast-wrong-substs.rs:9:30 | LL | let y: &dyn Bar = x; | --------------- ^ expected trait `Bar`, found trait `Foo` @@ -9,6 +9,6 @@ LL | let y: &dyn Bar = x; = note: expected reference `&dyn Bar` found reference `&dyn Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/no-fallback-multiple-impls.stderr b/tests/ui/traits/no-fallback-multiple-impls.stderr index 61c9e5aaabdb4..e38c432ca98c8 100644 --- a/tests/ui/traits/no-fallback-multiple-impls.stderr +++ b/tests/ui/traits/no-fallback-multiple-impls.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `missing` in this scope LL | missing(); | ^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/traits/no_send-struct.stderr b/tests/ui/traits/no_send-struct.stderr index ee7bdf282b740..fb7f26bb76669 100644 --- a/tests/ui/traits/no_send-struct.stderr +++ b/tests/ui/traits/no_send-struct.stderr @@ -13,6 +13,6 @@ note: required by a bound in `bar` LL | fn bar(_: T) {} | ^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr new file mode 100644 index 0000000000000..9f373cc50f0ac --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr new file mode 100644 index 0000000000000..9f373cc50f0ac --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.rs b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs new file mode 100644 index 0000000000000..9a8a5ced2e250 --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs @@ -0,0 +1,16 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete and may not be safe + +fn trivial() +where + for dyn Fn(A, *const B): Fn(A, *const B), +{ +} + +fn main() { + trivial::(); +} diff --git a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr index 07e02d47f27f6..d5f2bfef19260 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr @@ -19,6 +19,6 @@ note: required by a bound in `foo` LL | fn foo() where for T: Copy {} | ^^^^ required by this bound in `foo` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr index d65892ec6dffb..4e0441c1c7d02 100644 --- a/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr +++ b/tests/ui/traits/non_lifetime_binders/capture-late-ct-in-anon.stderr @@ -15,5 +15,5 @@ LL | for [(); C]: Copy, | | | parameter defined here -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs new file mode 100644 index 0000000000000..b999f251d333e --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs @@ -0,0 +1,19 @@ +// check-pass + +trait Foo { + type Bar + where + dyn Send + 'static: Send; +} + +impl Foo for () { + type Bar = i32; + // We take `<() as Foo>::Bar: Sized` and normalize it under the where clause + // of `for <() as Foo>::Bar = i32`. This gives us back `i32: Send` with + // the nested obligation `(dyn Send + 'static): Send`. However, during candidate + // assembly for object types, we disqualify any obligations that has non-region + // late-bound vars in the param env(!), rather than just the predicate. This causes + // the where clause to not hold even though it trivially should. +} + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr index a985b1a6e12f6..1f13207e33ca3 100644 --- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr +++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr @@ -19,6 +19,6 @@ note: the implementor must specify the same requirement LL | struct Bar(T) where T: Foo; | ^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr index da09343fb276b..8cf32c89416a7 100644 --- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr @@ -23,6 +23,6 @@ LL | where LL | for T: PartialEq + PartialOrd, | ^^^^^^^^^^ required by this bound in `auto_trait` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr index dc54e1acc392c..cc482887c8144 100644 --- a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr +++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr @@ -23,5 +23,5 @@ LL | for [i32; { let _: T = todo!(); 0 }]:, | | | parameter defined here -error: aborting due to previous error; 2 warnings emitted +error: aborting due to 1 previous error; 2 warnings emitted diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr index d985386423d29..eecf8e88fb64d 100644 --- a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr +++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr @@ -18,6 +18,6 @@ help: if there were a trait named `Example` with associated type `Item` implemen LL | for ::Item: Send, | ~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr index 1124076c23c9c..8304469150911 100644 --- a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr +++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr @@ -13,5 +13,5 @@ error: `impl Trait` can only mention type parameters from an fn or impl LL | fn uwu(_: impl for Trait<(), Assoc = impl Trait>) {} | - type parameter declared here ^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr index 95656f99976ff..2d330f6b14334 100644 --- a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr @@ -13,5 +13,5 @@ error: late-bound type parameter not allowed on trait object types LL | fn foo() -> &'static dyn for Test { | ^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr index 3b17f7697b2be..fbd723a1ba6bf 100644 --- a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr @@ -13,5 +13,5 @@ error: late-bound type parameter not allowed on function pointer types LL | fn foo() -> for fn(T) { | ^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr new file mode 100644 index 0000000000000..7dd383b1e7a55 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr @@ -0,0 +1,26 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/placeholders-dont-outlive-static.rs:6:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0310]: the placeholder type `!1_"T"` may not live long enough + --> $DIR/placeholders-dont-outlive-static.rs:13:5 + | +LL | foo(); + | ^^^^^ + | | + | the placeholder type `!1_"T"` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn bad() where !1_"T": 'static { + | +++++++++++++++++++++ + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr new file mode 100644 index 0000000000000..b4f00978ada87 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr @@ -0,0 +1,26 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/placeholders-dont-outlive-static.rs:6:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0310]: the placeholder type `!1_"T"` may not live long enough + --> $DIR/placeholders-dont-outlive-static.rs:19:5 + | +LL | foo(); + | ^^^^^ + | | + | the placeholder type `!1_"T"` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn good() where for T: 'static, !1_"T": 'static { + | +++++++++++++++++ + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs new file mode 100644 index 0000000000000..ae6866511e277 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs @@ -0,0 +1,22 @@ +// revisions: good bad + +//[good] known-bug: unknown +// `for T: 'static` doesn't imply itself when processing outlives obligations + +#![feature(non_lifetime_binders)] +//[bad]~^ WARN the feature `non_lifetime_binders` is incomplete + +fn foo() where for T: 'static {} + +#[cfg(bad)] +fn bad() { + foo(); + //[bad]~^ ERROR the placeholder type `!1_"T"` may not live long enough +} + +#[cfg(good)] +fn good() where for T: 'static { + foo(); +} + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs index 5ff7089b993a8..53957914e3ab2 100644 --- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs +++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs @@ -1,10 +1,9 @@ // edition:2021 -// check-pass +// known-bug: unknown // Checks that test_type_match code doesn't ICE when predicates have late-bound types #![feature(non_lifetime_binders)] -//~^ WARN is incomplete and may not be safe to use async fn walk2<'a, T: 'a>(_: T) where diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr index 3609bed28dffb..3a4415ed23aca 100644 --- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr +++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr @@ -7,5 +7,20 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error[E0309]: the placeholder type `!1_"F"` may not live long enough + --> $DIR/type-match-with-late-bound.rs:11:1 + | +LL | async fn walk2<'a, T: 'a>(_: T) + | -- the placeholder type `!1_"F"` must be valid for the lifetime `'a` as defined here... +... +LL | {} + | ^^ ...so that the type `F` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | for F: 'a, !1_"F": 'a + | ~~~~~~~~~~~~ + +error: aborting due to 1 previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr index bfcad72e35278..ecc97e283beea 100644 --- a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr +++ b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr @@ -22,6 +22,6 @@ LL | where LL | for T: Other {} | ^^^^^^^^ required by this bound in `foo` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr index 86ae49b32fcf0..1d5489845efe6 100644 --- a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr @@ -24,6 +24,6 @@ help: try using a fully qualified path to specify the expected types LL | as V>::method(a); | +++++++++++++++++++++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/object-does-not-impl-trait.stderr b/tests/ui/traits/object-does-not-impl-trait.stderr index 81d67255a0bdb..1ae055851746d 100644 --- a/tests/ui/traits/object-does-not-impl-trait.stderr +++ b/tests/ui/traits/object-does-not-impl-trait.stderr @@ -17,6 +17,6 @@ note: required by a bound in `take_foo` LL | fn take_foo(f: F) {} | ^^^ required by this bound in `take_foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/object/auto-dedup-in-impl.stderr b/tests/ui/traits/object/auto-dedup-in-impl.stderr index 5f13c781341c4..075f3c33808eb 100644 --- a/tests/ui/traits/object/auto-dedup-in-impl.stderr +++ b/tests/ui/traits/object/auto-dedup-in-impl.stderr @@ -7,6 +7,6 @@ LL | fn test(&self) { println!("one"); } LL | fn test(&self) { println!("two"); } | -------------- other definition for `test` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/traits/object/enforce-supertrait-projection.stderr b/tests/ui/traits/object/enforce-supertrait-projection.stderr index 2fb94d348966a..198a185dd4840 100644 --- a/tests/ui/traits/object/enforce-supertrait-projection.stderr +++ b/tests/ui/traits/object/enforce-supertrait-projection.stderr @@ -21,6 +21,6 @@ LL | where LL | T: Trait, | ^^^^^^^^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/object/issue-44454-1.stderr b/tests/ui/traits/object/issue-44454-1.stderr index 859487f50ac1e..e85b467693143 100644 --- a/tests/ui/traits/object/issue-44454-1.stderr +++ b/tests/ui/traits/object/issue-44454-1.stderr @@ -6,5 +6,5 @@ LL | fn bar<'a>(_arg: &'a i32) { LL | foo::, &'a i32>() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/object/issue-44454-2.stderr b/tests/ui/traits/object/issue-44454-2.stderr index 7f574769b7f60..366b519aeb579 100644 --- a/tests/ui/traits/object/issue-44454-2.stderr +++ b/tests/ui/traits/object/issue-44454-2.stderr @@ -12,6 +12,6 @@ LL | hr::(x) | `x` escapes the function body here | argument requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/traits/object/issue-44454-3.stderr b/tests/ui/traits/object/issue-44454-3.stderr index 294684d26bdfc..5b1ebf2d1a997 100644 --- a/tests/ui/traits/object/issue-44454-3.stderr +++ b/tests/ui/traits/object/issue-44454-3.stderr @@ -7,5 +7,5 @@ LL | let x: as Projector>::Foo = t; LL | let any = generic::, &'a T>(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr b/tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr index fcaa583e2bd45..196e74d396000 100644 --- a/tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr +++ b/tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr @@ -13,6 +13,6 @@ LL | type Bar; | ^^^ ...because it contains the generic associated type `Bar` = help: consider moving `Bar` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/print_vtable_sizes.stdout b/tests/ui/traits/object/print_vtable_sizes.stdout index ce90c76217b95..b43e168df3f38 100644 --- a/tests/ui/traits/object/print_vtable_sizes.stdout +++ b/tests/ui/traits/object/print_vtable_sizes.stdout @@ -1,11 +1,11 @@ -print-vtable-sizes { "crate_name": "", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } -print-vtable-sizes { "crate_name": "", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } -print-vtable-sizes { "crate_name": "", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } -print-vtable-sizes { "crate_name": "", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } diff --git a/tests/ui/traits/object/supertrait-lifetime-bound.stderr b/tests/ui/traits/object/supertrait-lifetime-bound.stderr index ed2f8624357bb..4fd7d2f0ec726 100644 --- a/tests/ui/traits/object/supertrait-lifetime-bound.stderr +++ b/tests/ui/traits/object/supertrait-lifetime-bound.stderr @@ -7,5 +7,5 @@ LL | fn test2<'a>() { LL | test1::, _>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/object/vs-lifetime-2.stderr b/tests/ui/traits/object/vs-lifetime-2.stderr index 9b8e793dfd2ff..9a2bb7d1c985e 100644 --- a/tests/ui/traits/object/vs-lifetime-2.stderr +++ b/tests/ui/traits/object/vs-lifetime-2.stderr @@ -4,6 +4,6 @@ error[E0224]: at least one trait is required for an object type LL | dyn 'static +: 'static + Copy, | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr index e24ed695dc55c..d63362a7a601d 100644 --- a/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr +++ b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr @@ -6,6 +6,6 @@ LL | impl !Send for MyStruct {} LL | impl !Send for MyStruct {} | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/param-without-lifetime-constraint.stderr b/tests/ui/traits/param-without-lifetime-constraint.stderr index b128b6518ce4b..b8ec1fa5654a1 100644 --- a/tests/ui/traits/param-without-lifetime-constraint.stderr +++ b/tests/ui/traits/param-without-lifetime-constraint.stderr @@ -15,5 +15,5 @@ help: the lifetime requirements from the `impl` do not correspond to the require LL | fn get_relation(&self) -> To; | ^^ consider borrowing this type parameter in the trait -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/project-modulo-regions.with_clause.stderr b/tests/ui/traits/project-modulo-regions.with_clause.stderr index dcc98e855d1b4..0e3081ddfdfeb 100644 --- a/tests/ui/traits/project-modulo-regions.with_clause.stderr +++ b/tests/ui/traits/project-modulo-regions.with_clause.stderr @@ -7,5 +7,5 @@ LL | fn test(val: MyStruct) where Helper: HelperTrait { LL | test(val); | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/project-modulo-regions.without_clause.stderr b/tests/ui/traits/project-modulo-regions.without_clause.stderr index e9959567e06af..830a07c4f5f79 100644 --- a/tests/ui/traits/project-modulo-regions.without_clause.stderr +++ b/tests/ui/traits/project-modulo-regions.without_clause.stderr @@ -7,5 +7,5 @@ LL | fn test(val: MyStruct) where Helper: HelperTrait { LL | test(val); | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/question-mark-result-err-mismatch.rs b/tests/ui/traits/question-mark-result-err-mismatch.rs new file mode 100644 index 0000000000000..0ca18b5b0ddce --- /dev/null +++ b/tests/ui/traits/question-mark-result-err-mismatch.rs @@ -0,0 +1,59 @@ +fn foo() -> Result { //~ NOTE expected `String` because of this + let test = String::from("one,two"); + let x = test + .split_whitespace() + .next() + .ok_or_else(|| { + "Couldn't split the test string" + }); + let one = x + .map(|s| ()) + .map_err(|e| { //~ NOTE this can't be annotated with `?` because it has type `Result<_, ()>` + e; //~ HELP remove this semicolon + }) + .map(|()| "")?; //~ ERROR `?` couldn't convert the error to `String` + //~^ NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE the trait `From<()>` is not implemented for `String` + //~| NOTE the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + //~| NOTE required for `Result` to implement `FromResidual>` + Ok(one.to_string()) +} + +fn bar() -> Result<(), String> { //~ NOTE expected `String` because of this + let x = foo(); //~ NOTE this has type `Result<_, String>` + let one = x + .map(|s| ()) + .map_err(|_| ())?; //~ ERROR `?` couldn't convert the error to `String` + //~^ NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE this can't be annotated with `?` because it has type `Result<_, ()>` + //~| NOTE the trait `From<()>` is not implemented for `String` + //~| NOTE the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + //~| NOTE required for `Result<(), String>` to implement `FromResidual>` + //~| HELP the following other types implement trait `From`: + Ok(one) +} + +fn baz() -> Result { //~ NOTE expected `String` because of this + let test = String::from("one,two"); + let one = test + .split_whitespace() + .next() + .ok_or_else(|| { //~ NOTE this can't be annotated with `?` because it has type `Result<_, ()>` + "Couldn't split the test string"; //~ HELP remove this semicolon + })?; + //~^ ERROR `?` couldn't convert the error to `String` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE the trait `From<()>` is not implemented for `String` + //~| NOTE the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + //~| NOTE required for `Result` to implement `FromResidual>` + Ok(one.to_string()) +} + +fn main() {} diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr new file mode 100644 index 0000000000000..3059e0beca3e4 --- /dev/null +++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr @@ -0,0 +1,62 @@ +error[E0277]: `?` couldn't convert the error to `String` + --> $DIR/question-mark-result-err-mismatch.rs:14:22 + | +LL | fn foo() -> Result { + | ---------------------- expected `String` because of this +... +LL | .map_err(|e| { + | __________- +LL | | e; + | | - help: remove this semicolon +LL | | }) + | |__________- this can't be annotated with `?` because it has type `Result<_, ()>` +LL | .map(|()| "")?; + | ^ the trait `From<()>` is not implemented for `String` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = note: required for `Result` to implement `FromResidual>` + +error[E0277]: `?` couldn't convert the error to `String` + --> $DIR/question-mark-result-err-mismatch.rs:28:25 + | +LL | fn bar() -> Result<(), String> { + | ------------------ expected `String` because of this +LL | let x = foo(); + | ----- this has type `Result<_, String>` +... +LL | .map_err(|_| ())?; + | ---------------^ the trait `From<()>` is not implemented for `String` + | | + | this can't be annotated with `?` because it has type `Result<_, ()>` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the following other types implement trait `From`: + > + >> + >> + > + > + > + = note: required for `Result<(), String>` to implement `FromResidual>` + +error[E0277]: `?` couldn't convert the error to `String` + --> $DIR/question-mark-result-err-mismatch.rs:48:11 + | +LL | fn baz() -> Result { + | ---------------------- expected `String` because of this +... +LL | .ok_or_else(|| { + | __________- +LL | | "Couldn't split the test string"; + | | - help: remove this semicolon +LL | | })?; + | | -^ the trait `From<()>` is not implemented for `String` + | |__________| + | this can't be annotated with `?` because it has type `Result<_, ()>` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = note: required for `Result` to implement `FromResidual>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/reservation-impl/coherence-conflict.next.stderr b/tests/ui/traits/reservation-impl/coherence-conflict.next.stderr index e5a3c3f5cc4b7..2b5277f933289 100644 --- a/tests/ui/traits/reservation-impl/coherence-conflict.next.stderr +++ b/tests/ui/traits/reservation-impl/coherence-conflict.next.stderr @@ -5,7 +5,9 @@ LL | impl OtherTrait for () {} | ---------------------- first implementation here LL | impl OtherTrait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: this impl is reserved -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/reservation-impl/coherence-conflict.old.stderr b/tests/ui/traits/reservation-impl/coherence-conflict.old.stderr index 393350ea3f12a..2b5277f933289 100644 --- a/tests/ui/traits/reservation-impl/coherence-conflict.old.stderr +++ b/tests/ui/traits/reservation-impl/coherence-conflict.old.stderr @@ -8,6 +8,6 @@ LL | impl OtherTrait for T {} | = note: this impl is reserved -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/reservation-impl/no-use.next.stderr b/tests/ui/traits/reservation-impl/no-use.next.stderr index 632f0f81624cd..aa7b51dc5df4e 100644 --- a/tests/ui/traits/reservation-impl/no-use.next.stderr +++ b/tests/ui/traits/reservation-impl/no-use.next.stderr @@ -6,6 +6,6 @@ LL | <() as MyTrait>::foo(&()); | = help: the trait `MyTrait` is implemented for `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/reservation-impl/no-use.old.stderr b/tests/ui/traits/reservation-impl/no-use.old.stderr index 632f0f81624cd..aa7b51dc5df4e 100644 --- a/tests/ui/traits/reservation-impl/no-use.old.stderr +++ b/tests/ui/traits/reservation-impl/no-use.old.stderr @@ -6,6 +6,6 @@ LL | <() as MyTrait>::foo(&()); | = help: the trait `MyTrait` is implemented for `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/resolution-in-overloaded-op.stderr b/tests/ui/traits/resolution-in-overloaded-op.stderr index fe5e1d6d2854d..2f5408beb966a 100644 --- a/tests/ui/traits/resolution-in-overloaded-op.stderr +++ b/tests/ui/traits/resolution-in-overloaded-op.stderr @@ -11,6 +11,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn foo>(a: &T, b: f64) -> f64 where &T: Mul { | ++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/traits/safety-fn-body.mir.stderr b/tests/ui/traits/safety-fn-body.mir.stderr index ea7b2048e836f..9a04f3e7d6216 100644 --- a/tests/ui/traits/safety-fn-body.mir.stderr +++ b/tests/ui/traits/safety-fn-body.mir.stderr @@ -6,6 +6,6 @@ LL | *self += 1; | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/traits/safety-fn-body.thir.stderr b/tests/ui/traits/safety-fn-body.thir.stderr index 23696c32bef57..5d4626c161ea9 100644 --- a/tests/ui/traits/safety-fn-body.thir.stderr +++ b/tests/ui/traits/safety-fn-body.thir.stderr @@ -6,6 +6,6 @@ LL | *self += 1; | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/traits/safety-inherent-impl.stderr b/tests/ui/traits/safety-inherent-impl.stderr index 1c8f43feca431..2513fef909ef1 100644 --- a/tests/ui/traits/safety-inherent-impl.stderr +++ b/tests/ui/traits/safety-inherent-impl.stderr @@ -6,6 +6,6 @@ LL | unsafe impl SomeStruct { | | | unsafe because of this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0197`. diff --git a/tests/ui/traits/safety-trait-impl-cc.stderr b/tests/ui/traits/safety-trait-impl-cc.stderr index 0ca565787f6b6..f530e5a769ecd 100644 --- a/tests/ui/traits/safety-trait-impl-cc.stderr +++ b/tests/ui/traits/safety-trait-impl-cc.stderr @@ -10,6 +10,6 @@ help: add `unsafe` to this trait implementation LL | unsafe impl lib::Foo for Bar { | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0200`. diff --git a/tests/ui/traits/self-without-lifetime-constraint.stderr b/tests/ui/traits/self-without-lifetime-constraint.stderr index 05a49820a822d..0a5ae8a027e48 100644 --- a/tests/ui/traits/self-without-lifetime-constraint.stderr +++ b/tests/ui/traits/self-without-lifetime-constraint.stderr @@ -15,5 +15,5 @@ help: the lifetime requirements from the `impl` do not correspond to the require LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; | ^^^^ consider borrowing this type parameter in the trait -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr index 8f9ce3ef1e99c..2ab150fc0f627 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr @@ -19,6 +19,6 @@ note: required because it appears within the type `Runtime` LL | struct Runtime { | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/static-method-generic-inference.stderr b/tests/ui/traits/static-method-generic-inference.stderr index 575ace2374ee6..44c7c099832b5 100644 --- a/tests/ui/traits/static-method-generic-inference.stderr +++ b/tests/ui/traits/static-method-generic-inference.stderr @@ -12,6 +12,6 @@ help: use the fully-qualified path to the only available implementation LL | let _f: base::Foo = ::new(); | +++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/traits/staticness-mismatch.stderr b/tests/ui/traits/staticness-mismatch.stderr index b67ac5adbe14b..3546cb7055545 100644 --- a/tests/ui/traits/staticness-mismatch.stderr +++ b/tests/ui/traits/staticness-mismatch.stderr @@ -7,6 +7,6 @@ LL | fn bar(); LL | fn bar(&self) {} | ^^^^^^^^^^^^^ `&self` used in impl -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0185`. diff --git a/tests/ui/traits/subtype-recursion-limit.rs b/tests/ui/traits/subtype-recursion-limit.rs new file mode 100644 index 0000000000000..5804748844e5a --- /dev/null +++ b/tests/ui/traits/subtype-recursion-limit.rs @@ -0,0 +1,17 @@ +// Variant of #117151 when the overflow comes entirely from subtype predicates. + +#![allow(unreachable_code)] + +use std::ptr; + +fn main() { + // Give x and y completely unconstrained types. Using a function call + // or `as` cast would create a well-formed predicate. + let x = return; + let y = return; + let mut w = (x, y); + //~^ ERROR overflow evaluating the requirement + // Avoid creating lifetimes, `Sized` bounds or function calls. + let a = (ptr::addr_of!(y), ptr::addr_of!(x)); + w = a; +} diff --git a/tests/ui/traits/subtype-recursion-limit.stderr b/tests/ui/traits/subtype-recursion-limit.stderr new file mode 100644 index 0000000000000..5310f822cc338 --- /dev/null +++ b/tests/ui/traits/subtype-recursion-limit.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `_ <: *const _` + --> $DIR/subtype-recursion-limit.rs:12:17 + | +LL | let mut w = (x, y); + | ^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr index bd0e7ca2c02e5..8024ad28d5ae6 100644 --- a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr +++ b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr @@ -17,6 +17,6 @@ LL | where LL | I: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `use_iterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-dereferences/issue-39029.stderr b/tests/ui/traits/suggest-dereferences/issue-39029.stderr index 49105de3d691d..fd45fa3cf74d0 100644 --- a/tests/ui/traits/suggest-dereferences/issue-39029.stderr +++ b/tests/ui/traits/suggest-dereferences/issue-39029.stderr @@ -14,6 +14,6 @@ help: consider dereferencing here LL | let _errors = TcpListener::bind(&*bad); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-dereferences/issue-62530.stderr b/tests/ui/traits/suggest-dereferences/issue-62530.stderr index e47ae0b65af0e..22b001c800177 100644 --- a/tests/ui/traits/suggest-dereferences/issue-62530.stderr +++ b/tests/ui/traits/suggest-dereferences/issue-62530.stderr @@ -16,6 +16,6 @@ help: consider dereferencing here LL | takes_type_parameter(&*string); // Error | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-dereferences/multiple-0.stderr b/tests/ui/traits/suggest-dereferences/multiple-0.stderr index 6a4d4b8d5212f..691b4ddc8e1c5 100644 --- a/tests/ui/traits/suggest-dereferences/multiple-0.stderr +++ b/tests/ui/traits/suggest-dereferences/multiple-0.stderr @@ -16,6 +16,6 @@ help: consider dereferencing here LL | foo(&***baz); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-dereferences/multiple-1.stderr b/tests/ui/traits/suggest-dereferences/multiple-1.stderr index 6e12321c2333b..2517cc6a02cb0 100644 --- a/tests/ui/traits/suggest-dereferences/multiple-1.stderr +++ b/tests/ui/traits/suggest-dereferences/multiple-1.stderr @@ -13,6 +13,6 @@ note: required by a bound in `foo` LL | fn foo(_: T) where T: Happy {} | ^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr index a19708e46bb1a..62500866c49b9 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr +++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr @@ -16,6 +16,6 @@ help: consider dereferencing here LL | .filter(|c| "aeiou".contains(*c)) | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr index ede31a2c7bcf1..d6033bc6baa0f 100644 --- a/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr +++ b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr @@ -10,6 +10,6 @@ help: consider dereferencing here LL | let _b: TargetStruct = (*a).into(); | ++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-fully-qualified-closure.stderr b/tests/ui/traits/suggest-fully-qualified-closure.stderr index 43cef7027a2c6..e077bd7ac2a6e 100644 --- a/tests/ui/traits/suggest-fully-qualified-closure.stderr +++ b/tests/ui/traits/suggest-fully-qualified-closure.stderr @@ -17,6 +17,6 @@ help: try using a fully qualified path to specify the expected types LL | >::lol::<{closure@}>(&q, ||()); | +++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/test.stderr b/tests/ui/traits/test.stderr index 668228abe0936..af005db58809a 100644 --- a/tests/ui/traits/test.stderr +++ b/tests/ui/traits/test.stderr @@ -4,6 +4,6 @@ error[E0404]: expected trait, found builtin type `isize` LL | impl isize for usize { fn foo(&self) {} } | ^^^^^ not a trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/trait-object-lifetime-default-note.rs b/tests/ui/traits/trait-object-lifetime-default-note.rs new file mode 100644 index 0000000000000..31e3eb4ba4155 --- /dev/null +++ b/tests/ui/traits/trait-object-lifetime-default-note.rs @@ -0,0 +1,16 @@ +trait A {} + +impl A for T {} + +fn main() { + let local = 0; //~ NOTE binding `local` declared here + let r = &local; //~ ERROR `local` does not live long enough + //~| NOTE borrowed value does not live long enough + //~| NOTE due to object lifetime defaults, `Box` actually means `Box<(dyn A + 'static)>` + require_box(Box::new(r)); + //~^ NOTE cast requires that `local` is borrowed for `'static` + + let _ = 0; +} //~ NOTE `local` dropped here while still borrowed + +fn require_box(_a: Box) {} diff --git a/tests/ui/traits/trait-object-lifetime-default-note.stderr b/tests/ui/traits/trait-object-lifetime-default-note.stderr new file mode 100644 index 0000000000000..4244e34873ad1 --- /dev/null +++ b/tests/ui/traits/trait-object-lifetime-default-note.stderr @@ -0,0 +1,19 @@ +error[E0597]: `local` does not live long enough + --> $DIR/trait-object-lifetime-default-note.rs:7:13 + | +LL | let local = 0; + | ----- binding `local` declared here +LL | let r = &local; + | ^^^^^^ borrowed value does not live long enough +... +LL | require_box(Box::new(r)); + | ----------- cast requires that `local` is borrowed for `'static` +... +LL | } + | - `local` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box` actually means `Box<(dyn A + 'static)>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/traits/trait-or-new-type-instead.stderr b/tests/ui/traits/trait-or-new-type-instead.stderr index 6fd8a03fd8fed..17ee939887864 100644 --- a/tests/ui/traits/trait-or-new-type-instead.stderr +++ b/tests/ui/traits/trait-or-new-type-instead.stderr @@ -6,6 +6,6 @@ LL | impl Option { | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0116`. diff --git a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs index 4a5e445d1efbe..927a9d6b94f8a 100644 --- a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs +++ b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs @@ -1,4 +1,3 @@ -#![feature(trait_upcasting)] #![feature(trait_alias)] // Although we *elaborate* `T: Alias` to `i32: B`, we should diff --git a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr index 5574a0320895e..1a410519a4edc 100644 --- a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr +++ b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/alias-where-clause-isnt-supertrait.rs:27:5 + --> $DIR/alias-where-clause-isnt-supertrait.rs:26:5 | LL | fn test(x: &dyn C) -> &dyn B { | ------ expected `&dyn B` because of return type @@ -9,6 +9,6 @@ LL | x = note: expected reference `&dyn B` found reference `&dyn C` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/basic.rs b/tests/ui/traits/trait-upcasting/basic.rs index 570ec5160bfe9..538cd8329cc64 100644 --- a/tests/ui/traits/trait-upcasting/basic.rs +++ b/tests/ui/traits/trait-upcasting/basic.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(trait_upcasting)] - trait Foo: PartialEq + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { 10 diff --git a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs index eae5cf8d58d01..4a379d9f875b8 100644 --- a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs +++ b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(trait_upcasting)] trait Foo: Bar + Bar {} trait Bar { diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr index 62c732fb1d958..85c05bd05db1f 100644 --- a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr +++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr @@ -12,6 +12,6 @@ LL | trait A: B + A {} | ^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/trait-upcasting/deref-lint-regions.rs b/tests/ui/traits/trait-upcasting/deref-lint-regions.rs new file mode 100644 index 0000000000000..946305cbb2b4b --- /dev/null +++ b/tests/ui/traits/trait-upcasting/deref-lint-regions.rs @@ -0,0 +1,17 @@ +// check-pass + +use std::ops::Deref; + +trait Bar<'a> {} +trait Foo<'a>: Bar<'a> {} + +impl<'a> Deref for dyn Foo<'a> { + //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion + type Target = dyn Bar<'a>; + + fn deref(&self) -> &Self::Target { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr b/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr new file mode 100644 index 0000000000000..557a4420a3dbf --- /dev/null +++ b/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr @@ -0,0 +1,14 @@ +warning: this `Deref` implementation is covered by an implicit supertrait coercion + --> $DIR/deref-lint-regions.rs:8:1 + | +LL | impl<'a> Deref for dyn Foo<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref>` which conflicts with supertrait `Bar<'_>` +LL | +LL | type Target = dyn Bar<'a>; + | -------------------------- target type is a supertrait of `dyn Foo<'_>` + | + = help: consider removing this implementation or replacing it with a method instead + = note: `#[warn(deref_into_dyn_supertrait)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs b/tests/ui/traits/trait-upcasting/deref-lint.rs similarity index 50% rename from tests/ui/traits/trait-upcasting/migrate-lint-deny.rs rename to tests/ui/traits/trait-upcasting/deref-lint.rs index d624187561ed7..68838d2ae20dd 100644 --- a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs +++ b/tests/ui/traits/trait-upcasting/deref-lint.rs @@ -1,16 +1,13 @@ -#![deny(deref_into_dyn_supertrait)] +// check-pass -extern crate core; - -use core::ops::Deref; +use std::ops::Deref; // issue 89190 trait A {} trait B: A {} impl<'a> Deref for dyn 'a + B { - //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target - //~| WARN this was previously accepted by the compiler but is being phased out; + //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion type Target = dyn A; fn deref(&self) -> &Self::Target { diff --git a/tests/ui/traits/trait-upcasting/deref-lint.stderr b/tests/ui/traits/trait-upcasting/deref-lint.stderr new file mode 100644 index 0000000000000..5a13659edf568 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/deref-lint.stderr @@ -0,0 +1,14 @@ +warning: this `Deref` implementation is covered by an implicit supertrait coercion + --> $DIR/deref-lint.rs:9:1 + | +LL | impl<'a> Deref for dyn 'a + B { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref` which conflicts with supertrait `A` +... +LL | type Target = dyn A; + | -------------------- target type is a supertrait of `dyn B` + | + = help: consider removing this implementation or replacing it with a method instead + = note: `#[warn(deref_into_dyn_supertrait)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs new file mode 100644 index 0000000000000..366eae1a58a34 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs @@ -0,0 +1,34 @@ +#![deny(deref_into_dyn_supertrait)] +use std::ops::Deref; + +trait Bar {} +impl Bar for T {} + +trait Foo: Bar { + fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar + 'a); +} + +impl Foo for () { + fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar + 'a) { + self + } +} + +impl<'a> Deref for dyn Foo + 'a { + type Target = dyn Bar + 'a; + + fn deref(&self) -> &Self::Target { + self.as_dyn_bar_u32() + } +} + +fn take_dyn(x: &dyn Bar) -> T { + todo!() +} + +fn main() { + let x: &dyn Foo = &(); + let y = take_dyn(x); + let z: u32 = y; + //~^ ERROR mismatched types +} diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr new file mode 100644 index 0000000000000..193d09e350111 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/deref-upcast-behavioral-change.rs:32:18 + | +LL | let z: u32 = y; + | --- ^ expected `u32`, found `i32` + | | + | expected due to this + | +help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit + | +LL | let z: u32 = y.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/diamond.rs b/tests/ui/traits/trait-upcasting/diamond.rs index a4f81c464b402..9a78339a4ec84 100644 --- a/tests/ui/traits/trait-upcasting/diamond.rs +++ b/tests/ui/traits/trait-upcasting/diamond.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(trait_upcasting)] - trait Foo: PartialEq + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { 10 diff --git a/tests/ui/traits/trait-upcasting/fewer-associated.rs b/tests/ui/traits/trait-upcasting/fewer-associated.rs index 8228eea2681aa..937818aac58e8 100644 --- a/tests/ui/traits/trait-upcasting/fewer-associated.rs +++ b/tests/ui/traits/trait-upcasting/fewer-associated.rs @@ -3,8 +3,6 @@ // revisions: current next //[next] compile-flags: -Ztrait-solver=next -#![feature(trait_upcasting)] - trait A: B { type Assoc; } diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr index 59c9d5737056a..119b3109c6323 100644 --- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr +++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/illegal-upcast-from-impl.rs:16:66 + --> $DIR/illegal-upcast-from-impl.rs:14:66 | LL | fn illegal(x: &dyn Sub) -> &dyn Super { x } | ----------------------- ^ expected trait `Super`, found trait `Sub` @@ -9,6 +9,6 @@ LL | fn illegal(x: &dyn Sub) -> &dyn Super { x } = note: expected reference `&dyn Super` found reference `&dyn Sub` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr index 59c9d5737056a..119b3109c6323 100644 --- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr +++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/illegal-upcast-from-impl.rs:16:66 + --> $DIR/illegal-upcast-from-impl.rs:14:66 | LL | fn illegal(x: &dyn Sub) -> &dyn Super { x } | ----------------------- ^ expected trait `Super`, found trait `Sub` @@ -9,6 +9,6 @@ LL | fn illegal(x: &dyn Sub) -> &dyn Super { x } = note: expected reference `&dyn Super` found reference `&dyn Sub` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs index 774474281eab9..4b730dab7ccaf 100644 --- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs +++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs @@ -1,8 +1,6 @@ // revisions: current next //[next] compile-flags: -Ztrait-solver=next -#![feature(trait_upcasting)] - trait Super { type Assoc; } diff --git a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs new file mode 100644 index 0000000000000..999f3b16f50d8 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs @@ -0,0 +1,35 @@ +#![deny(deref_into_dyn_supertrait)] + +use std::ops::Deref; + +trait Bar {} +impl Bar for T {} + +trait Foo: Bar { + fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar + 'a); +} + +impl Foo for () { + fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar + 'a) { + self + } +} + +impl<'a> Deref for dyn Foo + 'a { + type Target = dyn Bar + 'a; + + fn deref(&self) -> &Self::Target { + self.as_dyn_bar_u32() + } +} + +fn take_dyn(x: &dyn Bar) -> T { + todo!() +} + +fn main() { + let x: &dyn Foo = &(); + let y = take_dyn(x); + let z: u32 = y; + //~^ ERROR mismatched types +} diff --git a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr new file mode 100644 index 0000000000000..fcc80c6148f7d --- /dev/null +++ b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/inference-behavior-change-deref.rs:33:18 + | +LL | let z: u32 = y; + | --- ^ expected `u32`, found `i32` + | | + | expected due to this + | +help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit + | +LL | let z: u32 = y.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.rs b/tests/ui/traits/trait-upcasting/invalid-upcast.rs index e634bbd5ac6f5..9269a5e3e9ff6 100644 --- a/tests/ui/traits/trait-upcasting/invalid-upcast.rs +++ b/tests/ui/traits/trait-upcasting/invalid-upcast.rs @@ -1,5 +1,3 @@ -#![feature(trait_upcasting)] - trait Foo { fn a(&self) -> i32 { 10 diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr index 3aa21ee3dddfb..e70b99d28c7e4 100644 --- a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr +++ b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:53:35 + --> $DIR/invalid-upcast.rs:51:35 | LL | let _: &dyn std::fmt::Debug = baz; | -------------------- ^^^ expected trait `Debug`, found trait `Baz` @@ -10,7 +10,7 @@ LL | let _: &dyn std::fmt::Debug = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:55:24 + --> $DIR/invalid-upcast.rs:53:24 | LL | let _: &dyn Send = baz; | --------- ^^^ expected trait `Send`, found trait `Baz` @@ -21,7 +21,7 @@ LL | let _: &dyn Send = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:57:24 + --> $DIR/invalid-upcast.rs:55:24 | LL | let _: &dyn Sync = baz; | --------- ^^^ expected trait `Sync`, found trait `Baz` @@ -32,7 +32,7 @@ LL | let _: &dyn Sync = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:60:25 + --> $DIR/invalid-upcast.rs:58:25 | LL | let bar: &dyn Bar = baz; | -------- ^^^ expected trait `Bar`, found trait `Baz` @@ -43,7 +43,7 @@ LL | let bar: &dyn Bar = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:62:35 + --> $DIR/invalid-upcast.rs:60:35 | LL | let _: &dyn std::fmt::Debug = bar; | -------------------- ^^^ expected trait `Debug`, found trait `Bar` @@ -54,7 +54,7 @@ LL | let _: &dyn std::fmt::Debug = bar; found reference `&dyn Bar` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:64:24 + --> $DIR/invalid-upcast.rs:62:24 | LL | let _: &dyn Send = bar; | --------- ^^^ expected trait `Send`, found trait `Bar` @@ -65,7 +65,7 @@ LL | let _: &dyn Send = bar; found reference `&dyn Bar` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:66:24 + --> $DIR/invalid-upcast.rs:64:24 | LL | let _: &dyn Sync = bar; | --------- ^^^ expected trait `Sync`, found trait `Bar` @@ -76,7 +76,7 @@ LL | let _: &dyn Sync = bar; found reference `&dyn Bar` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:69:25 + --> $DIR/invalid-upcast.rs:67:25 | LL | let foo: &dyn Foo = baz; | -------- ^^^ expected trait `Foo`, found trait `Baz` @@ -87,7 +87,7 @@ LL | let foo: &dyn Foo = baz; found reference `&dyn Baz` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:71:35 + --> $DIR/invalid-upcast.rs:69:35 | LL | let _: &dyn std::fmt::Debug = foo; | -------------------- ^^^ expected trait `Debug`, found trait `Foo` @@ -98,7 +98,7 @@ LL | let _: &dyn std::fmt::Debug = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:73:24 + --> $DIR/invalid-upcast.rs:71:24 | LL | let _: &dyn Send = foo; | --------- ^^^ expected trait `Send`, found trait `Foo` @@ -109,7 +109,7 @@ LL | let _: &dyn Send = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:75:24 + --> $DIR/invalid-upcast.rs:73:24 | LL | let _: &dyn Sync = foo; | --------- ^^^ expected trait `Sync`, found trait `Foo` @@ -120,7 +120,7 @@ LL | let _: &dyn Sync = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:78:25 + --> $DIR/invalid-upcast.rs:76:25 | LL | let foo: &dyn Foo = bar; | -------- ^^^ expected trait `Foo`, found trait `Bar` @@ -131,7 +131,7 @@ LL | let foo: &dyn Foo = bar; found reference `&dyn Bar` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:80:35 + --> $DIR/invalid-upcast.rs:78:35 | LL | let _: &dyn std::fmt::Debug = foo; | -------------------- ^^^ expected trait `Debug`, found trait `Foo` @@ -142,7 +142,7 @@ LL | let _: &dyn std::fmt::Debug = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:82:24 + --> $DIR/invalid-upcast.rs:80:24 | LL | let _: &dyn Send = foo; | --------- ^^^ expected trait `Send`, found trait `Foo` @@ -153,7 +153,7 @@ LL | let _: &dyn Send = foo; found reference `&dyn Foo` error[E0308]: mismatched types - --> $DIR/invalid-upcast.rs:84:24 + --> $DIR/invalid-upcast.rs:82:24 | LL | let _: &dyn Sync = foo; | --------- ^^^ expected trait `Sync`, found trait `Foo` diff --git a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs index b672963ae9887..77ce627078f90 100644 --- a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs +++ b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(trait_upcasting)] struct Test { func: Box, diff --git a/tests/ui/traits/trait-upcasting/issue-11515.current.stderr b/tests/ui/traits/trait-upcasting/issue-11515.current.stderr deleted file mode 100644 index 97d66cccb25be..0000000000000 --- a/tests/ui/traits/trait-upcasting/issue-11515.current.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental - --> $DIR/issue-11515.rs:10:38 - | -LL | let test = Box::new(Test { func: closure }); - | ^^^^^^^ - | - = note: see issue #65991 for more information - = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable - = note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/trait-upcasting/issue-11515.next.stderr b/tests/ui/traits/trait-upcasting/issue-11515.next.stderr deleted file mode 100644 index 97d66cccb25be..0000000000000 --- a/tests/ui/traits/trait-upcasting/issue-11515.next.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental - --> $DIR/issue-11515.rs:10:38 - | -LL | let test = Box::new(Test { func: closure }); - | ^^^^^^^ - | - = note: see issue #65991 for more information - = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable - = note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/trait-upcasting/issue-11515.rs b/tests/ui/traits/trait-upcasting/issue-11515.rs index 723f3a24fd4e2..66ab1ce260a45 100644 --- a/tests/ui/traits/trait-upcasting/issue-11515.rs +++ b/tests/ui/traits/trait-upcasting/issue-11515.rs @@ -1,3 +1,4 @@ +// check-pass // revisions: current next //[next] compile-flags: -Ztrait-solver=next @@ -7,5 +8,5 @@ struct Test { fn main() { let closure: Box = Box::new(|| ()); - let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658] + let test = Box::new(Test { func: closure }); } diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs index 9825158c2dd38..6c65c38870f24 100644 --- a/tests/ui/traits/trait-upcasting/lifetime.rs +++ b/tests/ui/traits/trait-upcasting/lifetime.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(trait_upcasting)] - trait Foo: PartialEq + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { 10 diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr deleted file mode 100644 index 4533b1163425c..0000000000000 --- a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target - --> $DIR/migrate-lint-deny.rs:11:1 - | -LL | impl<'a> Deref for dyn 'a + B { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | type Target = dyn A; - | -------------------- target type is set here - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #89460 -note: the lint level is defined here - --> $DIR/migrate-lint-deny.rs:1:9 - | -LL | #![deny(deref_into_dyn_supertrait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs new file mode 100644 index 0000000000000..2c9126c863d52 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs @@ -0,0 +1,20 @@ +// check-pass + +use std::ops::Deref; + +trait Bar {} + +trait Foo: Bar { + fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar + 'a); +} + +impl<'a> Deref for dyn Foo + 'a { + //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion + type Target = dyn Bar + 'a; + + fn deref(&self) -> &Self::Target { + self.as_dyn_bar_u32() + } +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr new file mode 100644 index 0000000000000..a447f9cf83b7a --- /dev/null +++ b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr @@ -0,0 +1,14 @@ +warning: this `Deref` implementation is covered by an implicit supertrait coercion + --> $DIR/migrate-lint-different-substs.rs:11:1 + | +LL | impl<'a> Deref for dyn Foo + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref>` which conflicts with supertrait `Bar` +LL | +LL | type Target = dyn Bar + 'a; + | -------------------------------- target type is a supertrait of `dyn Foo` + | + = help: consider removing this implementation or replacing it with a method instead + = note: `#[warn(deref_into_dyn_supertrait)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs index 2e53a00a90e9c..0e17c27671770 100644 --- a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs +++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs @@ -1,5 +1,4 @@ // check-fail -#![feature(trait_upcasting)] trait Bar { fn bar(&self, _: T) {} diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr index 0ad18be03cdf9..c888ccc1ebb0d 100644 --- a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr +++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/multiple-occurrence-ambiguousity.rs:20:26 + --> $DIR/multiple-occurrence-ambiguousity.rs:19:26 | LL | let t: &dyn Bar<_> = s; | ----------- ^ expected trait `Bar`, found trait `Foo` @@ -9,6 +9,6 @@ LL | let t: &dyn Bar<_> = s; = note: expected reference `&dyn Bar<_>` found reference `&dyn Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr b/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr index ad80a009ece80..d075102b2e85a 100644 --- a/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr +++ b/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(multiple_supertrait_upcastable)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/trait-upcasting/normalization.rs b/tests/ui/traits/trait-upcasting/normalization.rs index c78338b0da93e..c57640e7e3467 100644 --- a/tests/ui/traits/trait-upcasting/normalization.rs +++ b/tests/ui/traits/trait-upcasting/normalization.rs @@ -3,8 +3,6 @@ // revisions: current next //[next] compile-flags: -Ztrait-solver=next -#![feature(trait_upcasting)] - trait Mirror { type Assoc; } diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs index 9ccfc9306ac0c..4a7304ec2d716 100644 --- a/tests/ui/traits/trait-upcasting/replace-vptr.rs +++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(trait_upcasting)] - trait A { fn foo_a(&self); } diff --git a/tests/ui/traits/trait-upcasting/struct.rs b/tests/ui/traits/trait-upcasting/struct.rs index a3e41696956cb..64fa9ca1b5fa5 100644 --- a/tests/ui/traits/trait-upcasting/struct.rs +++ b/tests/ui/traits/trait-upcasting/struct.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(trait_upcasting)] - use std::rc::Rc; use std::sync::Arc; diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs index 136d15af0e8b2..20277280440c5 100644 --- a/tests/ui/traits/trait-upcasting/subtrait-method.rs +++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs @@ -1,5 +1,3 @@ -#![feature(trait_upcasting)] - trait Foo: PartialEq + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { 10 diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr index 918159e845b9e..3fdf3f4816160 100644 --- a/tests/ui/traits/trait-upcasting/subtrait-method.stderr +++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr @@ -1,64 +1,64 @@ error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope - --> $DIR/subtrait-method.rs:55:9 + --> $DIR/subtrait-method.rs:53:9 | LL | bar.c(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:27:1 + --> $DIR/subtrait-method.rs:25:1 | LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope - --> $DIR/subtrait-method.rs:59:9 + --> $DIR/subtrait-method.rs:57:9 | LL | foo.b(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `b`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:17:1 + --> $DIR/subtrait-method.rs:15:1 | LL | trait Bar: Foo { | ^^^^^^^^^^^^^^ error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope - --> $DIR/subtrait-method.rs:61:9 + --> $DIR/subtrait-method.rs:59:9 | LL | foo.c(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:27:1 + --> $DIR/subtrait-method.rs:25:1 | LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope - --> $DIR/subtrait-method.rs:65:9 + --> $DIR/subtrait-method.rs:63:9 | LL | foo.b(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `b`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:17:1 + --> $DIR/subtrait-method.rs:15:1 | LL | trait Bar: Foo { | ^^^^^^^^^^^^^^ error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope - --> $DIR/subtrait-method.rs:67:9 + --> $DIR/subtrait-method.rs:65:9 | LL | foo.c(); | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it - --> $DIR/subtrait-method.rs:27:1 + --> $DIR/subtrait-method.rs:25:1 | LL | trait Baz: Bar { | ^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr index b612005fcb051..47ffa68b8ff88 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr @@ -1,9 +1,9 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` - --> $DIR/type-checking-test-1.rs:19:13 + --> $DIR/type-checking-test-1.rs:17:13 | LL | let _ = x as &dyn Bar<_>; // Ambiguous | ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr index b612005fcb051..47ffa68b8ff88 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr @@ -1,9 +1,9 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` - --> $DIR/type-checking-test-1.rs:19:13 + --> $DIR/type-checking-test-1.rs:17:13 | LL | let _ = x as &dyn Bar<_>; // Ambiguous | ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs index afea8521e87d4..3b6ec3b65e75a 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs @@ -1,8 +1,6 @@ // revisions: current next //[next] compile-flags: -Ztrait-solver=next -#![feature(trait_upcasting)] - trait Foo: Bar + Bar {} trait Bar { fn bar(&self) -> Option { diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs index b024b27750bc6..b4df0f5a90258 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs @@ -1,5 +1,3 @@ -#![feature(trait_upcasting)] - trait Foo: Bar + Bar {} trait Bar { fn bar(&self) -> Option { diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr index 3e59b9d33634a..f84ea93dc6792 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr @@ -1,11 +1,11 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar` - --> $DIR/type-checking-test-2.rs:19:13 + --> $DIR/type-checking-test-2.rs:17:13 | LL | let _ = x as &dyn Bar; // Error | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` - --> $DIR/type-checking-test-2.rs:24:13 + --> $DIR/type-checking-test-2.rs:22:13 | LL | let a = x as &dyn Bar<_>; // Ambiguous | ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs index b2db3a127974c..3685569d98d1a 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs @@ -1,5 +1,3 @@ -#![feature(trait_upcasting)] - trait Foo<'a>: Bar<'a> {} trait Bar<'a> {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr index e6cb6a753998f..640a6066268de 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:11:13 + --> $DIR/type-checking-test-3.rs:9:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'a>; // Error | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:16:13 + --> $DIR/type-checking-test-3.rs:14:13 | LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { | -- lifetime `'a` defined here diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs index f40c48f0d125f..65391502386de 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs @@ -1,5 +1,3 @@ -#![feature(trait_upcasting)] - trait Foo<'a>: Bar<'a, 'a> {} trait Bar<'a, 'b> { fn get_b(&self) -> Option<&'a u32> { diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr index 8d506e5807ece..7e7548955d39d 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:15:13 + --> $DIR/type-checking-test-4.rs:13:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'static, 'a>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:20:13 + --> $DIR/type-checking-test-4.rs:18:13 | LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -15,7 +15,7 @@ LL | let _ = x as &dyn Bar<'a, 'static>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:26:5 + --> $DIR/type-checking-test-4.rs:24:5 | LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -24,7 +24,7 @@ LL | y.get_b() // ERROR | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:31:5 + --> $DIR/type-checking-test-4.rs:29:5 | LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -32,7 +32,7 @@ LL | <_ as Bar>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:36:5 + --> $DIR/type-checking-test-4.rs:34:5 | LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -40,7 +40,7 @@ LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:44:5 + --> $DIR/type-checking-test-4.rs:42:5 | LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr deleted file mode 100644 index 9f0993d65a710..0000000000000 --- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental - --> $DIR/upcast-through-struct-tail.rs:10:5 - | -LL | x - | ^ - | - = note: see issue #65991 for more information - = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable - = note: required when coercing `Box>` into `Box>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr deleted file mode 100644 index 9f0993d65a710..0000000000000 --- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental - --> $DIR/upcast-through-struct-tail.rs:10:5 - | -LL | x - | ^ - | - = note: see issue #65991 for more information - = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable - = note: required when coercing `Box>` into `Box>` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs index 42495f45f8a65..9981d43606293 100644 --- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs +++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs @@ -1,3 +1,4 @@ +// check-pass // revisions: current next //[next] compile-flags: -Ztrait-solver=next @@ -8,7 +9,6 @@ trait B {} fn test<'a>(x: Box>) -> Box> { x - //~^ ERROR cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental } fn main() {} diff --git a/tests/ui/traits/trivial_impl.stderr b/tests/ui/traits/trivial_impl.stderr index 4b29b55bea13d..68dbf5dd4e8ea 100644 --- a/tests/ui/traits/trivial_impl.stderr +++ b/tests/ui/traits/trivial_impl.stderr @@ -9,6 +9,6 @@ LL | | Self: Foo<()>; LL | impl Foo for () {} | ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/trivial_impl2.stderr b/tests/ui/traits/trivial_impl2.stderr index 04c05df0616d1..9a220d24f3d65 100644 --- a/tests/ui/traits/trivial_impl2.stderr +++ b/tests/ui/traits/trivial_impl2.stderr @@ -9,6 +9,6 @@ LL | | Self: Foo<()>; LL | impl Foo for () {} | ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/trivial_impl3.stderr b/tests/ui/traits/trivial_impl3.stderr index dfb39d6ce159c..5aa1a4a3c3205 100644 --- a/tests/ui/traits/trivial_impl3.stderr +++ b/tests/ui/traits/trivial_impl3.stderr @@ -9,6 +9,6 @@ LL | | Self: trivial3::Trait; LL | impl Foo for u8 {} | ^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/trivial_impl4.stderr b/tests/ui/traits/trivial_impl4.stderr index 04b29ed77340d..2e86be730cc11 100644 --- a/tests/ui/traits/trivial_impl4.stderr +++ b/tests/ui/traits/trivial_impl4.stderr @@ -9,6 +9,6 @@ LL | | Self: trivial4::Trait; LL | impl Foo for u8 {} | ^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/unsend-future.stderr b/tests/ui/traits/unsend-future.stderr index 01829021b4a79..25df34197947b 100644 --- a/tests/ui/traits/unsend-future.stderr +++ b/tests/ui/traits/unsend-future.stderr @@ -18,5 +18,5 @@ note: required by a bound in `require_handler` LL | fn require_handler(h: H) {} | ^^^^^^^ required by this bound in `require_handler` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/vtable-res-trait-param.stderr b/tests/ui/traits/vtable-res-trait-param.stderr index 4cfceefb24cd0..fff602b8d2bed 100644 --- a/tests/ui/traits/vtable-res-trait-param.stderr +++ b/tests/ui/traits/vtable-res-trait-param.stderr @@ -17,6 +17,6 @@ note: required by a bound in `TraitB::gimme_an_a` LL | fn gimme_an_a(&self, a: A) -> isize; | ^^^^^^ required by this bound in `TraitB::gimme_an_a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/vtable/issue-97381.stderr b/tests/ui/traits/vtable/issue-97381.stderr index 89360c44e78b4..503d0f125218d 100644 --- a/tests/ui/traits/vtable/issue-97381.stderr +++ b/tests/ui/traits/vtable/issue-97381.stderr @@ -13,6 +13,6 @@ LL | LL | println!("{}", ***el > 0); | ---- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.stderr b/tests/ui/traits/vtable/vtable-non-object-safe.stderr index 9345c2711978a..53eef5d0b13ca 100644 --- a/tests/ui/traits/vtable/vtable-non-object-safe.stderr +++ b/tests/ui/traits/vtable/vtable-non-object-safe.stderr @@ -12,5 +12,5 @@ error: vtable entries for ` as A>`: [ LL | trait A: Iterator {} | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/vtable/vtable-vacant.stderr b/tests/ui/traits/vtable/vtable-vacant.stderr index 5346a70271635..9ce1d0b763289 100644 --- a/tests/ui/traits/vtable/vtable-vacant.stderr +++ b/tests/ui/traits/vtable/vtable-vacant.stderr @@ -12,5 +12,5 @@ error: vtable entries for ``: [ LL | trait B: A { | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/traits/well-formed-recursion-limit.rs b/tests/ui/traits/well-formed-recursion-limit.rs new file mode 100644 index 0000000000000..056cf947d4b55 --- /dev/null +++ b/tests/ui/traits/well-formed-recursion-limit.rs @@ -0,0 +1,27 @@ +// Regression test for #117151, this used to hang the compiler + +pub type ISO = (Box B>, Box A>); +pub fn iso(a: F1, b: F2) -> ISO +where + F1: 'static + Fn(A) -> B, + F2: 'static + Fn(B) -> A, +{ + (Box::new(a), Box::new(b)) +} +pub fn iso_un_option(i: ISO, Option>) -> ISO { + let (ab, ba) = (i.ab, i.ba); + //~^ ERROR no field `ab` on type + //~| ERROR no field `ba` on type + let left = move |o_a| match o_a { + //~^ ERROR overflow evaluating the requirement + None => panic!("absured"), + Some(a) => a, + }; + let right = move |o_b| match o_b { + None => panic!("absurd"), + Some(b) => b, + }; + iso(left, right) +} + +fn main() {} diff --git a/tests/ui/traits/well-formed-recursion-limit.stderr b/tests/ui/traits/well-formed-recursion-limit.stderr new file mode 100644 index 0000000000000..6f5fda02315c0 --- /dev/null +++ b/tests/ui/traits/well-formed-recursion-limit.stderr @@ -0,0 +1,22 @@ +error[E0609]: no field `ab` on type `(Box<(dyn Fn(Option) -> Option + 'static)>, Box<(dyn Fn(Option) -> Option + 'static)>)` + --> $DIR/well-formed-recursion-limit.rs:12:23 + | +LL | let (ab, ba) = (i.ab, i.ba); + | ^^ unknown field + +error[E0609]: no field `ba` on type `(Box<(dyn Fn(Option) -> Option + 'static)>, Box<(dyn Fn(Option) -> Option + 'static)>)` + --> $DIR/well-formed-recursion-limit.rs:12:29 + | +LL | let (ab, ba) = (i.ab, i.ba); + | ^^ unknown field + +error[E0275]: overflow evaluating the requirement `_ <: Option<_>` + --> $DIR/well-formed-recursion-limit.rs:15:33 + | +LL | let left = move |o_a| match o_a { + | ^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0275, E0609. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr index 59246fb1b0371..c68c1481f4d21 100644 --- a/tests/ui/transmutability/alignment/align-fail.stderr +++ b/tests/ui/transmutability/alignment/align-fail.stderr @@ -25,6 +25,6 @@ LL - assert::is_maybe_transmutable::<&'static [u8; 0], &'static [u16; 0]>(); LL + assert::is_maybe_transmutable::<&'static [u8; 0], [u16; 0]>(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/arrays/issue-103783-array-length.stderr b/tests/ui/transmutability/arrays/issue-103783-array-length.stderr index 37774c59e6cbb..2c581664f3952 100644 --- a/tests/ui/transmutability/arrays/issue-103783-array-length.stderr +++ b/tests/ui/transmutability/arrays/issue-103783-array-length.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | type NaughtyLenArray = [u32; 3.14159]; | ^^^^^^^ expected `usize`, found floating-point number -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/enums/should_pad_variants.stderr b/tests/ui/transmutability/enums/should_pad_variants.stderr index bfbef8b25fcf4..fd98e355fb915 100644 --- a/tests/ui/transmutability/enums/should_pad_variants.stderr +++ b/tests/ui/transmutability/enums/should_pad_variants.stderr @@ -19,6 +19,6 @@ LL | | .and(Assume::VALIDITY) LL | | }> | |__________^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/should_respect_endianness.stderr b/tests/ui/transmutability/enums/should_respect_endianness.stderr index e59301a8ce9e2..8823f40e53496 100644 --- a/tests/ui/transmutability/enums/should_respect_endianness.stderr +++ b/tests/ui/transmutability/enums/should_respect_endianness.stderr @@ -19,6 +19,6 @@ LL | | .and(Assume::VALIDITY) LL | | }> | |__________^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr index 420a9f3300838..d5ed205d14b41 100644 --- a/tests/ui/transmutability/issue-101739-2.stderr +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -9,6 +9,6 @@ LL | | ASSUME_VALIDITY, LL | | ASSUME_VISIBILITY, | |_____________________________- help: remove these generic arguments -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr index b4591778f8e7b..10e057ec104b8 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr @@ -9,6 +9,6 @@ help: you might be missing a type parameter LL | fn should_gracefully_handle_unknown_dst() { | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr index a55d71d806824..a84d2726fa989 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr @@ -9,6 +9,6 @@ help: you might be missing a type parameter LL | fn should_gracefully_handle_unknown_src() { | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/primitives/bool-mut.stderr b/tests/ui/transmutability/primitives/bool-mut.stderr index b36991e1c01c6..62a7a2b86224c 100644 --- a/tests/ui/transmutability/primitives/bool-mut.stderr +++ b/tests/ui/transmutability/primitives/bool-mut.stderr @@ -13,6 +13,6 @@ LL | where LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/primitives/bool.current.stderr b/tests/ui/transmutability/primitives/bool.current.stderr index 4b3eb6c517d91..6dfd83dd51444 100644 --- a/tests/ui/transmutability/primitives/bool.current.stderr +++ b/tests/ui/transmutability/primitives/bool.current.stderr @@ -13,6 +13,6 @@ LL | where LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/primitives/bool.next.stderr b/tests/ui/transmutability/primitives/bool.next.stderr index 4b3eb6c517d91..6dfd83dd51444 100644 --- a/tests/ui/transmutability/primitives/bool.next.stderr +++ b/tests/ui/transmutability/primitives/bool.next.stderr @@ -13,6 +13,6 @@ LL | where LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/primitives/unit.current.stderr b/tests/ui/transmutability/primitives/unit.current.stderr index c49eb6097bd0c..e5d8466c32364 100644 --- a/tests/ui/transmutability/primitives/unit.current.stderr +++ b/tests/ui/transmutability/primitives/unit.current.stderr @@ -19,6 +19,6 @@ LL | | .and(Assume::VALIDITY) LL | | }> | |__________^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/primitives/unit.next.stderr b/tests/ui/transmutability/primitives/unit.next.stderr index c49eb6097bd0c..e5d8466c32364 100644 --- a/tests/ui/transmutability/primitives/unit.next.stderr +++ b/tests/ui/transmutability/primitives/unit.next.stderr @@ -19,6 +19,6 @@ LL | | .and(Assume::VALIDITY) LL | | }> | |__________^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr index 4b4d6ad0298ee..8b22f89c7efda 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr @@ -20,6 +20,6 @@ LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr index ecfe4865962f7..982af825918e3 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr @@ -20,6 +20,6 @@ LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/references/unit-to-u8.stderr b/tests/ui/transmutability/references/unit-to-u8.stderr index f2b72357f792b..a0891dfd01eb5 100644 --- a/tests/ui/transmutability/references/unit-to-u8.stderr +++ b/tests/ui/transmutability/references/unit-to-u8.stderr @@ -20,6 +20,6 @@ LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/region-infer.stderr b/tests/ui/transmutability/region-infer.stderr index 307d0dfe50d22..50d060cd47431 100644 --- a/tests/ui/transmutability/region-infer.stderr +++ b/tests/ui/transmutability/region-infer.stderr @@ -18,6 +18,6 @@ LL | | { Assume { alignment: true, lifetimes: true, safety: true, va LL | | >, | |_________^ required by this bound in `test` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_pad_variants.stderr b/tests/ui/transmutability/unions/should_pad_variants.stderr index bfbef8b25fcf4..fd98e355fb915 100644 --- a/tests/ui/transmutability/unions/should_pad_variants.stderr +++ b/tests/ui/transmutability/unions/should_pad_variants.stderr @@ -19,6 +19,6 @@ LL | | .and(Assume::VALIDITY) LL | | }> | |__________^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_reject_contraction.stderr b/tests/ui/transmutability/unions/should_reject_contraction.stderr index 553f655a10ac0..e3493e184893c 100644 --- a/tests/ui/transmutability/unions/should_reject_contraction.stderr +++ b/tests/ui/transmutability/unions/should_reject_contraction.stderr @@ -13,6 +13,6 @@ LL | where LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr index 827df05decb8f..cf94d72b883dc 100644 --- a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr @@ -10,6 +10,6 @@ note: the struct `Dst` is defined here LL | #[repr(C)] pub(self) struct Dst { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr index 76dc7f3407555..57ceac61f16de 100644 --- a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr @@ -10,6 +10,6 @@ note: the struct `Src` is defined here LL | #[repr(C)] pub(self) struct Src { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr index 863ada3c2c44c..cb2e7ec29a5b5 100644 --- a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr @@ -13,6 +13,6 @@ LL | where LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr index 7b0f1b4d56ec6..434c3fcd278e7 100644 --- a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr @@ -13,6 +13,6 @@ LL | where LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr index df19477ef2697..e987aa595b96f 100644 --- a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr @@ -13,6 +13,6 @@ LL | where LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmute/transmute-impl.stderr b/tests/ui/transmute/transmute-impl.stderr index dd19bcd54e328..6ed1cd6cec455 100644 --- a/tests/ui/transmute/transmute-impl.stderr +++ b/tests/ui/transmute/transmute-impl.stderr @@ -7,6 +7,6 @@ LL | unsafe { transmute(x) } = note: source type: `&T` (pointer to `T`) = note: target type: `&isize` (N bits) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/transmute/transmute-imut-to-mut.stderr b/tests/ui/transmute/transmute-imut-to-mut.stderr index 1e9dff3ce89b2..d37050fa58af6 100644 --- a/tests/ui/transmute/transmute-imut-to-mut.stderr +++ b/tests/ui/transmute/transmute-imut-to-mut.stderr @@ -6,5 +6,5 @@ LL | let _a: &mut u8 = unsafe { transmute(&1u8) }; | = note: `#[deny(mutable_transmutes)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/transmute/transmute-padding-ice.stderr b/tests/ui/transmute/transmute-padding-ice.stderr index f5480e0b9fb82..ff5c5c3a5dd8b 100644 --- a/tests/ui/transmute/transmute-padding-ice.stderr +++ b/tests/ui/transmute/transmute-padding-ice.stderr @@ -18,6 +18,6 @@ LL | | { Assume { alignment: true, lifetimes: true, safety: true, va LL | | >, | |_________^ required by this bound in `is_maybe_transmutable` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/treat-err-as-bug/delay_span_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs similarity index 66% rename from tests/ui/treat-err-as-bug/delay_span_bug.rs rename to tests/ui/treat-err-as-bug/span_delayed_bug.rs index 533c8d1ec8f51..dda35b9b92a6d 100644 --- a/tests/ui/treat-err-as-bug/delay_span_bug.rs +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs @@ -1,12 +1,12 @@ // compile-flags: -Ztreat-err-as-bug // failure-status: 101 // error-pattern: aborting due to `-Z treat-err-as-bug=1` -// error-pattern: [trigger_delay_span_bug] triggering a delay span bug +// error-pattern: [trigger_span_delayed_bug] triggering a span delayed bug for testing incremental // normalize-stderr-test "note: .*\n\n" -> "" // normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> "" // rustc-env:RUST_BACKTRACE=0 #![feature(rustc_attrs)] -#[rustc_error(delay_span_bug_from_inside_query)] +#[rustc_error(span_delayed_bug_from_inside_query)] fn main() {} diff --git a/tests/ui/treat-err-as-bug/delay_span_bug.stderr b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr similarity index 55% rename from tests/ui/treat-err-as-bug/delay_span_bug.stderr rename to tests/ui/treat-err-as-bug/span_delayed_bug.stderr index 22c6175048a63..a61ffaea8c242 100644 --- a/tests/ui/treat-err-as-bug/delay_span_bug.stderr +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr @@ -1,5 +1,5 @@ -error: internal compiler error: delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)] - --> $DIR/delay_span_bug.rs:12:1 +error: internal compiler error: delayed span bug triggered by #[rustc_error(span_delayed_bug_from_inside_query)] + --> $DIR/span_delayed_bug.rs:12:1 | LL | fn main() {} | ^^^^^^^^^ @@ -7,5 +7,5 @@ LL | fn main() {} error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [trigger_delay_span_bug] triggering a delay span bug +#0 [trigger_span_delayed_bug] triggering a span delayed bug for testing incremental end of query stack diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr index 26679e713803e..554b3a64cc29d 100644 --- a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr @@ -12,6 +12,6 @@ help: you can convert an `i32` to a `u8` and panic if the converted value doesn' LL | B::get_x().try_into().unwrap() | ++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr b/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr index b3ec3cd8d9d09..e48d48a7271d1 100644 --- a/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr +++ b/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr @@ -4,6 +4,6 @@ error[E0507]: cannot move out of `*t` which is behind a shared reference LL | *t | ^^ move occurs because `*t` has type `String`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr index b41bf86d3d911..d58a011ff5501 100644 --- a/tests/ui/try-block/try-block-bad-type.stderr +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -2,7 +2,9 @@ error[E0277]: `?` couldn't convert the error to `TryFromSliceError` --> $DIR/try-block-bad-type.rs:7:16 | LL | Err("")?; - | ^ the trait `From<&str>` is not implemented for `TryFromSliceError` + | -------^ the trait `From<&str>` is not implemented for `TryFromSliceError` + | | + | this can't be annotated with `?` because it has type `Result<_, &str>` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the trait `From` is implemented for `TryFromSliceError` diff --git a/tests/ui/try-block/try-block-catch.stderr b/tests/ui/try-block/try-block-catch.stderr index 39cf943f4d8ab..185bcb4071be3 100644 --- a/tests/ui/try-block/try-block-catch.stderr +++ b/tests/ui/try-block/try-block-catch.stderr @@ -6,5 +6,5 @@ LL | } catch { }; | = help: try using `match` on the result of the `try` block instead -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/try-block/try-block-in-while.stderr b/tests/ui/try-block/try-block-in-while.stderr index 62cc26dd4010d..2760e930102b4 100644 --- a/tests/ui/try-block/try-block-in-while.stderr +++ b/tests/ui/try-block/try-block-in-while.stderr @@ -6,6 +6,6 @@ LL | while try { false } {} | = help: the trait `Try` is not implemented for `bool` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/try-block/try-block-opt-init.stderr b/tests/ui/try-block/try-block-opt-init.stderr index c397385017ff4..1679fc2ac18c5 100644 --- a/tests/ui/try-block/try-block-opt-init.stderr +++ b/tests/ui/try-block/try-block-opt-init.stderr @@ -12,6 +12,6 @@ LL | assert_eq!(cfg_res, 5); | = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index d8b9431becc6b..97fbbdbf8f8a8 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -4,7 +4,9 @@ error[E0277]: `?` couldn't convert the error to `u8` LL | fn result_to_result() -> Result { | --------------- expected `u8` because of this LL | Ok(Err(123_i32)?) - | ^ the trait `From` is not implemented for `u8` + | ------------^ the trait `From` is not implemented for `u8` + | | + | this can't be annotated with `?` because it has type `Result<_, i32>` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following other types implement trait `From`: diff --git a/tests/ui/try-trait/issue-32709.stderr b/tests/ui/try-trait/issue-32709.stderr index 94e8f9295fdd5..b155b3ff66313 100644 --- a/tests/ui/try-trait/issue-32709.stderr +++ b/tests/ui/try-trait/issue-32709.stderr @@ -4,7 +4,9 @@ error[E0277]: `?` couldn't convert the error to `()` LL | fn a() -> Result { | --------------- expected `()` because of this LL | Err(5)?; - | ^ the trait `From<{integer}>` is not implemented for `()` + | ------^ the trait `From<{integer}>` is not implemented for `()` + | | + | this can't be annotated with `?` because it has type `Result<_, {integer}>` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following other types implement trait `From`: @@ -19,6 +21,6 @@ LL | Err(5)?; and 4 others = note: required for `Result` to implement `FromResidual>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/tuple/array-diagnostics.stderr b/tests/ui/tuple/array-diagnostics.stderr index a10d7af470c7c..629ca2b37fa5a 100644 --- a/tests/ui/tuple/array-diagnostics.stderr +++ b/tests/ui/tuple/array-diagnostics.stderr @@ -4,6 +4,6 @@ error[E0618]: expected function, found `(&'static str, {integer})` LL | ("C200B40A83", 4) | ^^^^^^^^^^^^^^^^^- help: consider separating array elements with a comma: `,` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/tuple/index-invalid.stderr b/tests/ui/tuple/index-invalid.stderr index 8d22f458a6c6e..ae2c275f52cd9 100644 --- a/tests/ui/tuple/index-invalid.stderr +++ b/tests/ui/tuple/index-invalid.stderr @@ -2,19 +2,19 @@ error[E0609]: no field `1` on type `(((),),)` --> $DIR/index-invalid.rs:2:22 | LL | let _ = (((),),).1.0; - | ^ + | ^ unknown field error[E0609]: no field `1` on type `((),)` --> $DIR/index-invalid.rs:4:24 | LL | let _ = (((),),).0.1; - | ^ + | ^ unknown field error[E0609]: no field `000` on type `(((),),)` --> $DIR/index-invalid.rs:6:22 | LL | let _ = (((),),).000.000; - | ^^^ + | ^^^ unknown field error: aborting due to 3 previous errors diff --git a/tests/ui/tuple/tuple-index-not-tuple.stderr b/tests/ui/tuple/tuple-index-not-tuple.stderr index a1bcdfaedbc60..a267e41b1bc32 100644 --- a/tests/ui/tuple/tuple-index-not-tuple.stderr +++ b/tests/ui/tuple/tuple-index-not-tuple.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `0` on type `Point` --> $DIR/tuple-index-not-tuple.rs:6:12 | LL | origin.0; - | ^ help: a field with a similar name exists: `x` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | origin.x; + | ~ error[E0609]: no field `0` on type `Empty` --> $DIR/tuple-index-not-tuple.rs:8:11 diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.stderr b/tests/ui/tuple/tuple-index-out-of-bounds.stderr index 7d7c5cd7892ea..96090435d06be 100644 --- a/tests/ui/tuple/tuple-index-out-of-bounds.stderr +++ b/tests/ui/tuple/tuple-index-out-of-bounds.stderr @@ -2,13 +2,18 @@ error[E0609]: no field `2` on type `Point` --> $DIR/tuple-index-out-of-bounds.rs:7:12 | LL | origin.2; - | ^ help: a field with a similar name exists: `0` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | origin.0; + | ~ error[E0609]: no field `2` on type `({integer}, {integer})` --> $DIR/tuple-index-out-of-bounds.rs:12:11 | LL | tuple.2; - | ^ + | ^ unknown field error: aborting due to 2 previous errors diff --git a/tests/ui/tuple/wrong_argument_ice-2.stderr b/tests/ui/tuple/wrong_argument_ice-2.stderr index 41244209214e7..a868adf411b00 100644 --- a/tests/ui/tuple/wrong_argument_ice-2.stderr +++ b/tests/ui/tuple/wrong_argument_ice-2.stderr @@ -14,6 +14,6 @@ help: wrap these arguments in parentheses to construct a tuple LL | test((x.qux(), x.qux())); | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/tuple/wrong_argument_ice-3.stderr b/tests/ui/tuple/wrong_argument_ice-3.stderr index 8b9dac6e291e2..ce21751f39d20 100644 --- a/tests/ui/tuple/wrong_argument_ice-3.stderr +++ b/tests/ui/tuple/wrong_argument_ice-3.stderr @@ -19,6 +19,6 @@ LL - groups.push(new_group, vec![process]); LL + groups.push(/* (Vec, Vec) */); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/tuple/wrong_argument_ice-4.stderr b/tests/ui/tuple/wrong_argument_ice-4.stderr index 1fbf180c673f0..3c7d6699be2b5 100644 --- a/tests/ui/tuple/wrong_argument_ice-4.stderr +++ b/tests/ui/tuple/wrong_argument_ice-4.stderr @@ -17,6 +17,6 @@ note: closure defined here LL | (|| {})(|| { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/tuple/wrong_argument_ice.stderr b/tests/ui/tuple/wrong_argument_ice.stderr index 213ca8f885cf2..6d0558d2876f7 100644 --- a/tests/ui/tuple/wrong_argument_ice.stderr +++ b/tests/ui/tuple/wrong_argument_ice.stderr @@ -11,6 +11,6 @@ help: wrap these arguments in parentheses to construct a tuple LL | self.acc.push_back((self.current_provides, self.current_requires)); | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr index 6870b9d7d09f4..2e6136eb9599e 100644 --- a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr +++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr @@ -4,6 +4,6 @@ error[E0533]: expected unit struct, unit variant or constant, found tuple varian LL | Self::A => (), | ^^^^^^^ not a unit struct, unit variant or constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0533`. diff --git a/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr b/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr index 51b1c8a1068a9..3c143f342161a 100644 --- a/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr +++ b/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr @@ -6,6 +6,6 @@ LL | let _ = Alias::None::; | | | not allowed on this type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr b/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr index f190bfb69839e..7ddcc318f88bc 100644 --- a/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr +++ b/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr @@ -4,5 +4,5 @@ error: expected type, found variant `V` LL | fn check() -> ::V {} | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr index aa79b1a57c4c8..404e376e364e0 100644 --- a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr +++ b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -69,6 +69,6 @@ LL | | fn main() {} | |____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/assoc-type-const.rs b/tests/ui/type-alias-impl-trait/assoc-type-const.rs index 62f66914ee330..6632a3450e5d6 100644 --- a/tests/ui/type-alias-impl-trait/assoc-type-const.rs +++ b/tests/ui/type-alias-impl-trait/assoc-type-const.rs @@ -1,7 +1,9 @@ // Tests that we properly detect defining usages when using // const generics in an associated opaque type -// check-pass +// check-pass +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next #![feature(impl_trait_in_assoc_type)] trait UnwrapItemsExt<'a, const C: usize> { diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr index e594dc577b1cd..089c3e4fd8ab2 100644 --- a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, I> UnwrapItemsExt for I { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr index d7247302dd1e0..2ed918eca1714 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -21,6 +21,6 @@ note: required by a bound in `is_send` LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index d47b1fe3678c6..f6f754557991f 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -22,5 +22,5 @@ note: required by a bound in `is_send` LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr index 8678e9b33b5ea..20e478160c61b 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `T` LL | type X = impl Clone; | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr index 962dedde09a52..ad1b9f19d8ef9 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -7,6 +7,6 @@ LL | type X<'a> = impl Into<&'static str> + From<&'a str>; LL | t | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr index a845cba771637..bca88b5fae10f 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr @@ -15,6 +15,6 @@ help: consider further restricting this bound LL | type Foo = (impl Debug, Struct); | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.stderr index 36bbb985ef028..4462b70f782ba 100644 --- a/tests/ui/type-alias-impl-trait/coherence.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.stderr @@ -9,6 +9,6 @@ LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr b/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr index 63a3ce29cc77b..893a27faced67 100644 --- a/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr +++ b/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr @@ -8,6 +8,6 @@ LL | impl OtherTrait for i32 {} | = note: upstream crates may add a new impl of trait `coherence_cross_crate_trait_decl::SomeTrait` for type `i32` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.stderr b/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.stderr index f2aee798608a6..ef170101b4455 100644 --- a/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.stderr +++ b/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.stderr @@ -7,6 +7,6 @@ LL | LL | impl Trait for (u32, i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(TAIT, TAIT)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr index d5fc46cb1f596..948bd6deacd0d 100644 --- a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr +++ b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr @@ -4,6 +4,6 @@ error[E0582]: binding for associated type `Output` references lifetime `'a`, whi LL | type MalformedTy = dyn for<'a> Callable, Output = &'a str>; | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr index 60bc24320a301..772f487d96aae 100644 --- a/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr +++ b/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr @@ -6,5 +6,5 @@ LL | type Bar = impl std::fmt::Debug; | = note: `Bar` must be used in combination with a concrete type within the same module -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr index a8b4cd7afe8a9..9e6169b2af73f 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr @@ -10,5 +10,5 @@ note: previous use here LL | "" | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr index b138f9d5c45ab..e5cee49cf2961 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr @@ -10,5 +10,5 @@ note: previous use here LL | if { return } { | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr index 8fc2e22848c70..0fdcb81f66726 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr @@ -10,5 +10,5 @@ note: previous use here LL | let x: Tait = (); | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr index 09dadb0afcef5..2a77eb4c4ac33 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr @@ -10,5 +10,5 @@ note: previous use here LL | "" | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr index 146a57cbb7e05..abf4a0d241b2c 100644 --- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr @@ -10,5 +10,5 @@ note: previous use here LL | fn one() -> Tait { One } | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr index 0c50a84e89436..07ba17ad27b8f 100644 --- a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr +++ b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr @@ -10,5 +10,5 @@ note: previous use here LL | a | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr index 8205a60ccdd7b..7dce067d39c68 100644 --- a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr +++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr @@ -4,5 +4,5 @@ error: cannot capture late-bound lifetime in type alias impl trait LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; | -- lifetime defined here ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/fallback.stderr b/tests/ui/type-alias-impl-trait/fallback.stderr index e767bfdb08b6b..5250252a0da44 100644 --- a/tests/ui/type-alias-impl-trait/fallback.stderr +++ b/tests/ui/type-alias-impl-trait/fallback.stderr @@ -12,6 +12,6 @@ help: consider specifying the generic argument LL | Wrapper::::Second | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/future.stderr b/tests/ui/type-alias-impl-trait/future.stderr index 7e76c120a2566..b20073fcdfcde 100644 --- a/tests/ui/type-alias-impl-trait/future.stderr +++ b/tests/ui/type-alias-impl-trait/future.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `B` LL | type FooFuture = impl Future; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr index 47ac3346259e9..72271d158a1a9 100644 --- a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr +++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr @@ -10,5 +10,5 @@ note: previous use here LL | std::iter::once(t) | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index 3dbfff7453fd0..d2d6380b65a34 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `T` LL | type Two = impl Debug; | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index 21a5369d9fff9..2338dbd522b73 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `U` LL | type Two = impl Debug; | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr index 648efd1cbfe7c..00aedfae46375 100644 --- a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr @@ -15,6 +15,6 @@ note: this item must have the opaque type in its signature in order to be able t LL | fn foo() -> Foo { | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr index 85e8a600ce37f..5a6998f41658e 100644 --- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr @@ -10,5 +10,5 @@ note: previous use here LL | pub type Tait = impl Copy + From> + Into>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr index 39f584dd49ca3..e037dede2e0f6 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr @@ -11,5 +11,5 @@ note: this item must mention the opaque type in its signature in order to be abl LL | fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr index 8cf8fb1d16c4d..137a4db81b563 100644 --- a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr @@ -4,6 +4,6 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl X for () { | ^ unconstrained type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr index c312ee7dece8d..a13e9eaab3add 100644 --- a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr +++ b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr @@ -6,6 +6,6 @@ LL | impl Trait for Alias {} | = note: a trait object implements `Trait` if and only if `Trait` is one of the trait object's trait bounds -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0321`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr index 1c83105a18aff..9840bcef7d14b 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr @@ -11,6 +11,6 @@ note: required by a bound in `is_yay` LL | fn is_yay() { } | ^^^ required by this bound in `is_yay` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr index a6440f02c27d8..2259aa7bb1508 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr @@ -11,6 +11,6 @@ note: required by a bound in `is_yay` LL | fn is_yay() { } | ^^^ required by this bound in `is_yay` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/implied_bounds.stderr b/tests/ui/type-alias-impl-trait/implied_bounds.stderr index 6f11b66634b29..64a203fe4658e 100644 --- a/tests/ui/type-alias-impl-trait/implied_bounds.stderr +++ b/tests/ui/type-alias-impl-trait/implied_bounds.stderr @@ -12,5 +12,5 @@ LL | x | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr index 151564c3b45a1..f3f9962f10682 100644 --- a/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr +++ b/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr @@ -7,5 +7,5 @@ LL | let t = into_impl(x); LL | helper(|_| t) | ^ returning this value requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr index cbc5e60731815..5967a9468302c 100644 --- a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr +++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr @@ -12,5 +12,5 @@ LL | x | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index 81bc64bc32c63..ff11aee40261b 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | type Ty = impl Sized + 'static; | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr index 66e4783157b7c..9bffa94fda165 100644 --- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr @@ -13,6 +13,6 @@ help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr index b93ea955c89f5..f0cf681d8bb72 100644 --- a/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr +++ b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr @@ -7,6 +7,6 @@ LL | impl FnOnce<()> for &F { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/type-alias-impl-trait/incomplete-inference.stderr b/tests/ui/type-alias-impl-trait/incomplete-inference.stderr index 9a0e71b4eed90..3976a43a89c53 100644 --- a/tests/ui/type-alias-impl-trait/incomplete-inference.stderr +++ b/tests/ui/type-alias-impl-trait/incomplete-inference.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | None:: | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs index f6cbbf04d8264..6a2ee761e1915 100644 --- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs @@ -1,6 +1,5 @@ // edition: 2021 // build-fail -//~^^ ERROR cycle detected when computing layout of #![feature(impl_trait_in_assoc_type)] @@ -21,6 +20,7 @@ impl Recur for () { fn recur(self) -> Self::Recur { async move { recur(self).await; } + //~^ ERROR cycle detected when computing layout of } } diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr index 2063becdb0838..11d9cd0af0817 100644 --- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr @@ -1,19 +1,27 @@ -error[E0391]: cycle detected when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}` +error[E0391]: cycle detected when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}` + --> $DIR/indirect-recursion-issue-112047.rs:22:22 | - = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}>`... - = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}>`... - = note: ...which requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}`... +LL | async move { recur(self).await; } + | ^^^^^^^^^^^^^^^^^ + | + = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:14:31: 16:2}>`... + = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:14:31: 16:2}>`... +note: ...which requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:14:31: 16:2}`... + --> $DIR/indirect-recursion-issue-112047.rs:15:5 + | +LL | t.recur().await; + | ^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<<() as Recur>::Recur>`... - = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}>`... - = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}>`... - = note: ...which again requires computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}`, completing the cycle -note: cycle used when elaborating drops for `::recur` - --> $DIR/indirect-recursion-issue-112047.rs:22:5 + = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}>`... + = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}>`... + = note: ...which again requires computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}`, completing the cycle +note: cycle used when elaborating drops for `::recur` + --> $DIR/indirect-recursion-issue-112047.rs:21:5 | LL | fn recur(self) -> Self::Recur { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr index ef7abe588644f..fd7488fa2601e 100644 --- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -22,5 +22,5 @@ note: required by a bound in `is_send` LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr index 50ae6f3864112..d820df472f95b 100644 --- a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr +++ b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr @@ -4,6 +4,6 @@ error[E0720]: cannot resolve opaque type LL | type T = impl Copy; | ^^^^^^^^^ cannot resolve opaque type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr index 6ec5d13f812a7..169d8e41d20d7 100644 --- a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr +++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr @@ -17,6 +17,6 @@ note: this item must have the opaque type in its signature in order to be able t LL | fn bar() { | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr index 47bae8bd12b6b..41c5206d9e88a 100644 --- a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr +++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr @@ -6,6 +6,6 @@ LL | impl AnotherTrait for T {} LL | impl AnotherTrait for OpaqueType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-109054.stderr b/tests/ui/type-alias-impl-trait/issue-109054.stderr index a611b9fe448e1..a099b7d8b8a63 100644 --- a/tests/ui/type-alias-impl-trait/issue-109054.stderr +++ b/tests/ui/type-alias-impl-trait/issue-109054.stderr @@ -7,6 +7,6 @@ LL | type ReturnType<'a> = impl std::future::Future + 'a; LL | &inner | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr index 4c5fd22556aae..4570ce8e41da0 100644 --- a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr +++ b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr @@ -10,5 +10,5 @@ note: previous use here LL | fn _unused() -> Opaque { String::new() } | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr index acd40f9804ea0..ea4c5297ad5e3 100644 --- a/tests/ui/type-alias-impl-trait/issue-52843.stderr +++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `T` LL | type Foo = impl Default; | +++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr index 2109cf8a784dc..8605a0981933c 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `U` LL | type Bug> = impl Fn(T) -> U + Copy; | +++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53096.stderr b/tests/ui/type-alias-impl-trait/issue-53096.stderr index 0af3a75f8532e..fba1802efd202 100644 --- a/tests/ui/type-alias-impl-trait/issue-53096.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53096.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-53598.stderr b/tests/ui/type-alias-impl-trait/issue-53598.stderr index f8b8201e2ebed..a31aabedba542 100644 --- a/tests/ui/type-alias-impl-trait/issue-53598.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53598.stderr @@ -4,5 +4,5 @@ error: type parameter `T` is part of concrete type but not used in parameter lis LL | S::(Default::default()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-57700.stderr b/tests/ui/type-alias-impl-trait/issue-57700.stderr index 31b6df5d4c318..7efb05f40b079 100644 --- a/tests/ui/type-alias-impl-trait/issue-57700.stderr +++ b/tests/ui/type-alias-impl-trait/issue-57700.stderr @@ -4,5 +4,5 @@ error: type parameter `impl Deref` is part of concrete type but n LL | self | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-57961.stderr b/tests/ui/type-alias-impl-trait/issue-57961.stderr index 8d11b48888947..314296b5bb317 100644 --- a/tests/ui/type-alias-impl-trait/issue-57961.stderr +++ b/tests/ui/type-alias-impl-trait/issue-57961.stderr @@ -15,6 +15,6 @@ note: required by a bound in `Foo::Bar` LL | type Bar: Iterator; | ^^^^^^^^ required by this bound in `Foo::Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-60407.stderr b/tests/ui/type-alias-impl-trait/issue-60407.stderr index fecee27797a54..583156b9f7cb6 100644 --- a/tests/ui/type-alias-impl-trait/issue-60407.stderr +++ b/tests/ui/type-alias-impl-trait/issue-60407.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-65384.stderr b/tests/ui/type-alias-impl-trait/issue-65384.stderr index f6692ae320733..6accd45bad657 100644 --- a/tests/ui/type-alias-impl-trait/issue-65384.stderr +++ b/tests/ui/type-alias-impl-trait/issue-65384.stderr @@ -7,6 +7,6 @@ LL | impl MyTrait for () {} LL | impl MyTrait for Bar {} | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr index b7af3f06d0d9a..aa7bcbf6a02d6 100644 --- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr @@ -14,6 +14,6 @@ help: consider introducing lifetime `'a` here LL | type Return<'a, A> = impl WithAssoc; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/type-alias-impl-trait/issue-70121.stderr b/tests/ui/type-alias-impl-trait/issue-70121.stderr index 30c3ddd8659d1..d6ab26e30daf6 100644 --- a/tests/ui/type-alias-impl-trait/issue-70121.stderr +++ b/tests/ui/type-alias-impl-trait/issue-70121.stderr @@ -11,5 +11,5 @@ note: this item must mention the opaque type in its signature in order to be abl LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item { | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-74244.stderr b/tests/ui/type-alias-impl-trait/issue-74244.stderr index ff6bacd277e1e..f5ca56bacccf6 100644 --- a/tests/ui/type-alias-impl-trait/issue-74244.stderr +++ b/tests/ui/type-alias-impl-trait/issue-74244.stderr @@ -4,6 +4,6 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl Allocator for DefaultAllocator { | ^ unconstrained type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74280.stderr b/tests/ui/type-alias-impl-trait/issue-74280.stderr index 66886db6eb946..c09efbe4e1333 100644 --- a/tests/ui/type-alias-impl-trait/issue-74280.stderr +++ b/tests/ui/type-alias-impl-trait/issue-74280.stderr @@ -7,6 +7,6 @@ LL | let y = || -> Test { () }; LL | 7 | ^ expected `()`, found integer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index 053546e4b9285..68dd6570d00c0 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -7,6 +7,6 @@ LL | fn test() -> Pointer<_> { | | not allowed in type signatures | help: replace with the correct return type: `Pointer` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/type-alias-impl-trait/issue-78450.rs b/tests/ui/type-alias-impl-trait/issue-78450.rs index 2a984c1ed7133..236e9f4e88cec 100644 --- a/tests/ui/type-alias-impl-trait/issue-78450.rs +++ b/tests/ui/type-alias-impl-trait/issue-78450.rs @@ -1,4 +1,6 @@ // check-pass +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr index 6a75e1bd2c0fa..461da20f37b67 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr @@ -7,6 +7,6 @@ LL | impl Trait for Out { LL | impl Trait<(), In> for Out { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-89686.stderr b/tests/ui/type-alias-impl-trait/issue-89686.stderr index b636ada8b75b1..91d71339a0848 100644 --- a/tests/ui/type-alias-impl-trait/issue-89686.stderr +++ b/tests/ui/type-alias-impl-trait/issue-89686.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `T` LL | type G<'a, T: Trait> = impl Future; | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr index ead28769f0660..bc233a5321437 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `B` LL | type FooFn = impl FnOnce(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr index 0c45046f5f516..37abb3fe021bb 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -16,6 +16,6 @@ help: consider restricting type parameter `B` LL | type FooFn = impl Baz; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-94429.stderr b/tests/ui/type-alias-impl-trait/issue-94429.stderr index 360ecfa61bfa7..5d081e6b1eff5 100644 --- a/tests/ui/type-alias-impl-trait/issue-94429.stderr +++ b/tests/ui/type-alias-impl-trait/issue-94429.stderr @@ -4,6 +4,6 @@ error[E0271]: type mismatch resolving `<{coroutine@$DIR/issue-94429.rs:17:9: 17: LL | fn run(&mut self) -> Self::Coro { | ^^^^^^^^^^ expected integer, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr index 728244a1844db..4f4ca1041d768 100644 --- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr @@ -10,6 +10,6 @@ LL | Some((a, b, c)) => (), = note: expected tuple `(u32, u32)` found tuple `(_, _, _)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-98604.stderr b/tests/ui/type-alias-impl-trait/issue-98604.stderr index af758d8099f88..2390b72535625 100644 --- a/tests/ui/type-alias-impl-trait/issue-98604.stderr +++ b/tests/ui/type-alias-impl-trait/issue-98604.stderr @@ -6,6 +6,6 @@ LL | Box::new(test) as AsyncFnPtr; | = note: required for the cast from `Box impl Future {test}>` to `Box<(dyn Fn() -> Pin + 'static)>> + 'static)>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-98608.stderr b/tests/ui/type-alias-impl-trait/issue-98608.stderr index 9b651008371f2..d5c56636f66e4 100644 --- a/tests/ui/type-alias-impl-trait/issue-98608.stderr +++ b/tests/ui/type-alias-impl-trait/issue-98608.stderr @@ -11,6 +11,6 @@ LL | let b: Box Box> = Box::new(hi); found opaque type `impl Sized` = note: required for the cast from `Box impl Sized {hi}>` to `Box Box>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 6bcae6e531648..03cc943d50995 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -9,6 +9,6 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } | | | hidden type `&'a i32` captures the lifetime `'a` as defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/type-alias-impl-trait/multi-error.stderr b/tests/ui/type-alias-impl-trait/multi-error.stderr index b2de2effea662..b0e6d13b0e1f0 100644 --- a/tests/ui/type-alias-impl-trait/multi-error.stderr +++ b/tests/ui/type-alias-impl-trait/multi-error.stderr @@ -10,6 +10,6 @@ note: for this opaque type LL | type Bar = impl Sized; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr index 2781170091245..b050b08a8e2e4 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr @@ -7,5 +7,5 @@ LL | (42_i64, 60) | expected `i64`, got `i32` | this expression supplies two conflicting concrete types for the same opaque type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr index 81e603e2355df..552cf3fda3000 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr @@ -7,5 +7,5 @@ LL | (i, i) | expected `&'a i32`, got `&'b i32` | this expression supplies two conflicting concrete types for the same opaque type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr index 66a6b0bbf7431..b5f38074632ee 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -10,6 +10,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn f(a: &'static A, b: B) -> (X, X) where &'static B: From<&A> { | ++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr index 0f752212ac9c6..c7a4b2115bf23 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr @@ -7,5 +7,5 @@ LL | (a.clone(), a) | expected `A`, got `B` | this expression supplies two conflicting concrete types for the same opaque type -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr index bbe709dccab4e..c3128ea6f5e9e 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -13,6 +13,6 @@ LL | (a, b) = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.stderr b/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.stderr index 49c59f7eb37a1..cf6e42bc722ff 100644 --- a/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.stderr +++ b/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `<() as B>::Assoc == _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr index 62db019ed6a91..172ecded7a2f9 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -9,6 +9,6 @@ LL | () | = help: the trait `Foo<()>` is implemented for `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr index dccf84362f0f8..c549ca5b2ce11 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -11,6 +11,6 @@ LL | () <() as Foo> <() as Foo<()>> -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr index b1d947a9ccf4e..ce5d303705347 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -6,5 +6,5 @@ LL | type FooX = impl Debug; | = note: `FooX` must be used in combination with a concrete type within the same module -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/nested.stderr b/tests/ui/type-alias-impl-trait/nested.stderr index 732af5c0b561f..a19d4c4eb7164 100644 --- a/tests/ui/type-alias-impl-trait/nested.stderr +++ b/tests/ui/type-alias-impl-trait/nested.stderr @@ -7,6 +7,6 @@ LL | println!("{:?}", bar()); = help: the trait `Debug` is not implemented for `Bar` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr index fa6ecf68d28f3..3e67a162f0f0f 100644 --- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr +++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr @@ -15,5 +15,5 @@ note: opaque type being used as hidden type LL | pub type Foo = impl Debug; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr index f3e8ae9c7dbae..fabc80c0a4f24 100644 --- a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr +++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr @@ -6,5 +6,5 @@ LL | pub type Foo = impl Copy; | = note: `Foo` must be used in combination with a concrete type within the same module -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.stderr b/tests/ui/type-alias-impl-trait/non-defining-method.stderr index ed5590f9d7174..2ba4c90a1c431 100644 --- a/tests/ui/type-alias-impl-trait/non-defining-method.stderr +++ b/tests/ui/type-alias-impl-trait/non-defining-method.stderr @@ -10,6 +10,6 @@ note: for this opaque type LL | type Bar = impl Sized; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr index a621bb519cdf3..d4528fb76fed9 100644 --- a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr +++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr @@ -17,6 +17,6 @@ note: this item must have the opaque type in its signature in order to be able t LL | fn test() -> <() as Foo>::Assoc { | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.stderr b/tests/ui/type-alias-impl-trait/not_well_formed.stderr index b267e6a754492..dbd80ffa4f6c3 100644 --- a/tests/ui/type-alias-impl-trait/not_well_formed.stderr +++ b/tests/ui/type-alias-impl-trait/not_well_formed.stderr @@ -9,6 +9,6 @@ help: consider restricting type parameter `V` LL | type Foo = impl Trait; | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr index b2898a21190ad..e8925b9b489fa 100644 --- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr @@ -10,5 +10,5 @@ note: previous use here LL | |_: usize |loop {} | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr index 7481557fcbade..eec35548c5504 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr @@ -10,5 +10,5 @@ note: previous use here LL | fn foo() -> Op { &"hello world" } | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr index e4209643b7a3d..05825e6862591 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr @@ -10,5 +10,5 @@ note: previous use here LL | A | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr index 844103d77a8ce..d4e2f95353381 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: no errors encountered even though `delay_span_bug` issued +error: internal compiler error: no errors encountered even though `span_delayed_bug` issued error: internal compiler error: {OpaqueTypeKey { def_id: DefId(get_rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }) } }} | diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.stderr index c2cf70687fd20..ab57812ba9bb7 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-2.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-2.stderr @@ -9,6 +9,6 @@ LL | 42_i32 = help: the trait `PartialEq` is not implemented for `i32` = help: the trait `PartialEq` is implemented for `i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr index 4155a114b4f98..15ebcdafca6fb 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr @@ -10,6 +10,6 @@ LL | i = help: the trait `PartialEq>` is not implemented for `&i32` = help: the trait `PartialEq` is implemented for `i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr index dbc183f54f46b..b1ccd5cc402d7 100644 --- a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr +++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr @@ -4,5 +4,5 @@ error: `Bar` cannot be used in patterns LL | LEAK_FREE => (), | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/structural-match.stderr b/tests/ui/type-alias-impl-trait/structural-match.stderr index 61287f268066e..b0415db0e55c4 100644 --- a/tests/ui/type-alias-impl-trait/structural-match.stderr +++ b/tests/ui/type-alias-impl-trait/structural-match.stderr @@ -4,5 +4,5 @@ error: `Foo` cannot be used in patterns LL | VALUE => (), | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr index e57c59d616578..5641ff301649f 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr @@ -4,6 +4,6 @@ error[E0562]: `impl Trait` only allowed in function and inherent method argument LL | type Foo = fn() -> impl Send; | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr index 8cdce2f8e81ca..cff2695304ae2 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a, I: Iterator> Trait for (i32, I) { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr index a770eeac39b7d..3d43fbe0dbccb 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr @@ -6,5 +6,5 @@ LL | type Foo = impl Fn() -> Foo; | = note: `Foo` must be used in combination with a concrete type within the same module -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr index 3f3699ce5324a..e2dc887989b29 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr @@ -6,5 +6,5 @@ LL | type Foo = impl Bar; | = note: `Foo` must be used in combination with a concrete type within the same module -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr b/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr index 6cc5b7a8a0a88..6d9c8eabfad59 100644 --- a/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr +++ b/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr @@ -12,6 +12,6 @@ LL + _ => todo!(), LL + } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr index 65139307f8e01..6206f169c5b9e 100644 --- a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr +++ b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr @@ -4,6 +4,6 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, LL | impl<'a> Trait for Opaque<&'a str> { | ^^ unconstrained lifetime parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/under-binder.stderr b/tests/ui/type-alias-impl-trait/under-binder.stderr index 82c4ec97335f1..f4a121ce440d7 100644 --- a/tests/ui/type-alias-impl-trait/under-binder.stderr +++ b/tests/ui/type-alias-impl-trait/under-binder.stderr @@ -7,6 +7,6 @@ LL | type Opaque<'a> = impl Sized + 'a; LL | f | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr index 103636b6cdde2..e4de9245951cf 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -16,6 +16,6 @@ help: consider restricting type parameter `T` LL | type Converter = impl ProofForConversion; | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr index 12d85a49d01c8..34b50fb1f05e4 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr @@ -15,6 +15,6 @@ note: but the referenced data is only valid for the lifetime `'a` as defined her LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr index e0005489d1e7c..47bea7bbe608c 100644 --- a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `B` LL | type FooFn = impl FnOnce(B); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr index 7d72c9f811af4..c4ad8434ed147 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/wf-in-associated-type.rs:36:23 + --> $DIR/wf-in-associated-type.rs:38:23 | LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... @@ -12,7 +12,7 @@ LL | impl<'a, T: 'a> Trait<'a, T> for () { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/wf-in-associated-type.rs:36:23 + --> $DIR/wf-in-associated-type.rs:38:23 | LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs index 31fbef9f78f83..b966ca4bff0e7 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs @@ -1,14 +1,16 @@ // WF check for impl Trait in associated type position. // -// revisions: pass fail +// revisions: pass pass_next fail // [pass] check-pass +// [pass_next] compile-flags: -Ztrait-solver=next +// [pass_next] check-pass // [fail] check-fail #![feature(impl_trait_in_assoc_type)] // The hidden type here (`&'a T`) requires proving `T: 'a`. // We know it holds because of implied bounds from the impl header. -#[cfg(pass)] +#[cfg(any(pass, pass_next))] mod pass { trait Trait { type Opaque1; diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr index 2858afcd46f04..dcc4b8021eac6 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr @@ -17,6 +17,6 @@ help: consider adding an explicit lifetime bound LL | type InnerOpaque = impl Sized; | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr index 285e4f18ca30c..121664bd95693 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr +++ b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | fn test() { | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr index 58ae8617b9bd9..09a42f73490a0 100644 --- a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr +++ b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `B` LL | type FooFn = impl FnOnce(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias/issue-62263-self-in-atb.stderr b/tests/ui/type-alias/issue-62263-self-in-atb.stderr index c20074dc27ce7..18c8bc1a1b361 100644 --- a/tests/ui/type-alias/issue-62263-self-in-atb.stderr +++ b/tests/ui/type-alias/issue-62263-self-in-atb.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: `Self` is only available in impls, traits, and LL | pub type Alias = dyn Trait; | ^^^^ `Self` is only available in impls, traits, and type definitions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/type-alias/issue-62305-self-assoc-ty.stderr b/tests/ui/type-alias/issue-62305-self-assoc-ty.stderr index f3da50df9269b..a35e644d3aa89 100644 --- a/tests/ui/type-alias/issue-62305-self-assoc-ty.stderr +++ b/tests/ui/type-alias/issue-62305-self-assoc-ty.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: `Self` is only available in impls, traits, and LL | type Alias = Self::Target; | ^^^^ `Self` is only available in impls, traits, and type definitions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/type-alias/issue-62364-self-ty-arg.stderr b/tests/ui/type-alias/issue-62364-self-ty-arg.stderr index 7e15e42e3ccd9..26d93dcc27276 100644 --- a/tests/ui/type-alias/issue-62364-self-ty-arg.stderr +++ b/tests/ui/type-alias/issue-62364-self-ty-arg.stderr @@ -6,6 +6,6 @@ LL | type Alias<'a> = Struct<&'a Self>; | | | `Self` not allowed in a type alias -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0411`. diff --git a/tests/ui/type-inference/generalize-subtyped-variables.rs b/tests/ui/type-inference/generalize-subtyped-variables.rs new file mode 100644 index 0000000000000..f93408a43db5e --- /dev/null +++ b/tests/ui/type-inference/generalize-subtyped-variables.rs @@ -0,0 +1,25 @@ +// Test for specific details of how we handle higher-ranked subtyping to make +// sure that any changes are made deliberately. +// +// - `let y = x` creates a `Subtype` obligation that is deferred for later. +// - `w = a` sets the type of `x` to `Option fn(&'a ())>` and generalizes +// `z` first to `Option<_>` and then to `Option`. +// - The various subtyping obligations are then processed. +// +// This requires that +// 1. the `Subtype` obligation from `y = x` isn't processed while the types of +// `w` and `a` are being unified. +// 2. the pending subtype obligation isn't considered when determining the type +// to generalize `z` to first (when related to the type of `y`). +// +// Found when considering fixes to #117151 +// check-pass + +fn main() { + let mut x = None; + let y = x; + let z = Default::default(); + let mut w = (&mut x, z, z); + let a = (&mut None::, y, None::); + w = a; +} diff --git a/tests/ui/type-inference/issue-30225.stderr b/tests/ui/type-inference/issue-30225.stderr index 72c33d16cabe0..cd2d9e2bea853 100644 --- a/tests/ui/type-inference/issue-30225.stderr +++ b/tests/ui/type-inference/issue-30225.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | u = v; // mark $0 and $1 in a subtype relationship | ^ expected `A`, found `B` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-inference/or_else-multiple-type-params.stderr b/tests/ui/type-inference/or_else-multiple-type-params.stderr index 6ac63a91ee9ac..d1bbe308ed3dd 100644 --- a/tests/ui/type-inference/or_else-multiple-type-params.stderr +++ b/tests/ui/type-inference/or_else-multiple-type-params.stderr @@ -9,6 +9,6 @@ help: try giving this closure an explicit return type LL | .or_else(|err| -> Result { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-inference/sort_by_key.stderr b/tests/ui/type-inference/sort_by_key.stderr index 81af024b3fb94..3d2e0250dd21c 100644 --- a/tests/ui/type-inference/sort_by_key.stderr +++ b/tests/ui/type-inference/sort_by_key.stderr @@ -14,6 +14,6 @@ help: consider specifying the generic argument LL | lst.sort_by_key(|&(v, _)| v.iter().sum::()); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-inference/unbounded-associated-type.stderr b/tests/ui/type-inference/unbounded-associated-type.stderr index e0fecc72f3092..c9dfa0bf587f7 100644 --- a/tests/ui/type-inference/unbounded-associated-type.stderr +++ b/tests/ui/type-inference/unbounded-associated-type.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | S(std::marker::PhantomData::).foo(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr index 209abfe5cba49..dc0bea58a70e8 100644 --- a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr +++ b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic arguments LL | foo::(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn.stderr b/tests/ui/type-inference/unbounded-type-param-in-fn.stderr index d92892eeb84ed..31e6e805e6c9d 100644 --- a/tests/ui/type-inference/unbounded-type-param-in-fn.stderr +++ b/tests/ui/type-inference/unbounded-type-param-in-fn.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | foo::(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/ascription/issue-34255-1.stderr b/tests/ui/type/ascription/issue-34255-1.stderr index 254d36cb9479c..6cb42fad614a9 100644 --- a/tests/ui/type/ascription/issue-34255-1.stderr +++ b/tests/ui/type/ascription/issue-34255-1.stderr @@ -14,5 +14,5 @@ LL | input_cells: Vec::new() LL ~ } } | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/ascription/issue-47666.stderr b/tests/ui/type/ascription/issue-47666.stderr index 74d85a75c85c6..562ce53052bd1 100644 --- a/tests/ui/type/ascription/issue-47666.stderr +++ b/tests/ui/type/ascription/issue-47666.stderr @@ -6,5 +6,5 @@ LL | let _ = Option:Some(vec![0, 1]); | = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/ascription/issue-54516.stderr b/tests/ui/type/ascription/issue-54516.stderr index a1371432f5ad6..2c567a1a0ff61 100644 --- a/tests/ui/type/ascription/issue-54516.stderr +++ b/tests/ui/type/ascription/issue-54516.stderr @@ -6,5 +6,5 @@ LL | println!("{}", std::mem:size_of::>()); | = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/ascription/issue-60933.stderr b/tests/ui/type/ascription/issue-60933.stderr index 0ec527ff5a958..cd184ceba3313 100644 --- a/tests/ui/type/ascription/issue-60933.stderr +++ b/tests/ui/type/ascription/issue-60933.stderr @@ -6,5 +6,5 @@ LL | let _: usize = std::mem:size_of::(); | = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/closure-with-wrong-borrows.stderr b/tests/ui/type/closure-with-wrong-borrows.stderr index 7370bc7646765..65e11ec52fc07 100644 --- a/tests/ui/type/closure-with-wrong-borrows.stderr +++ b/tests/ui/type/closure-with-wrong-borrows.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn f(inner: fn(&str, &S)) { | ^ ------------------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/issue-101866.stderr b/tests/ui/type/issue-101866.stderr index fe99821198e20..6f4b380b4e746 100644 --- a/tests/ui/type/issue-101866.stderr +++ b/tests/ui/type/issue-101866.stderr @@ -13,6 +13,6 @@ LL - TraitA::::func(); LL + >::func(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/type/issue-58355.stderr b/tests/ui/type/issue-58355.stderr index 67078bcfe89ad..b6056f0fd65ad 100644 --- a/tests/ui/type/issue-58355.stderr +++ b/tests/ui/type/issue-58355.stderr @@ -8,6 +8,6 @@ LL | x = Some(Box::new(callback)); = note: required because it appears within the type `fn() -> dyn ToString` = note: required for the cast from `Box dyn ToString>` to `Box (dyn ToString + 'static)>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type/issue-91268.stderr b/tests/ui/type/issue-91268.stderr index a3619d863e259..395559442d1c4 100644 --- a/tests/ui/type/issue-91268.stderr +++ b/tests/ui/type/issue-91268.stderr @@ -8,5 +8,5 @@ LL | 0: u8(ţ | | | unclosed delimiter -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/missing-let-in-binding-2.stderr b/tests/ui/type/missing-let-in-binding-2.stderr index 2e10125943e75..abf24763abc71 100644 --- a/tests/ui/type/missing-let-in-binding-2.stderr +++ b/tests/ui/type/missing-let-in-binding-2.stderr @@ -9,5 +9,5 @@ help: you might have meant to introduce a new binding LL | let _v: Vec = vec![1, 2, 3]; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/missing-let-in-binding-3.stderr b/tests/ui/type/missing-let-in-binding-3.stderr index ca828ce37eb7a..b01323b4e666e 100644 --- a/tests/ui/type/missing-let-in-binding-3.stderr +++ b/tests/ui/type/missing-let-in-binding-3.stderr @@ -6,5 +6,5 @@ LL | struct A { LL | : :u8, | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/missing-let-in-binding-4.stderr b/tests/ui/type/missing-let-in-binding-4.stderr index e6f173a665870..258eab5b91fcf 100644 --- a/tests/ui/type/missing-let-in-binding-4.stderr +++ b/tests/ui/type/missing-let-in-binding-4.stderr @@ -6,5 +6,5 @@ LL | struct A { LL | : u8 =, | ^ expected identifier -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/missing-let-in-binding.stderr b/tests/ui/type/missing-let-in-binding.stderr index fc094e8cbad71..a9d766e4c3cf5 100644 --- a/tests/ui/type/missing-let-in-binding.stderr +++ b/tests/ui/type/missing-let-in-binding.stderr @@ -10,5 +10,5 @@ help: you might have meant to introduce a new binding LL | let _foo: i32 = 4; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/type-annotation-needed.stderr b/tests/ui/type/type-annotation-needed.stderr index 87bba3166be6a..521d25537f3b9 100644 --- a/tests/ui/type/type-annotation-needed.stderr +++ b/tests/ui/type/type-annotation-needed.stderr @@ -15,6 +15,6 @@ help: consider specifying the generic argument LL | foo::(42); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type/type-ascription-with-fn-call.stderr b/tests/ui/type/type-ascription-with-fn-call.stderr index e3afa497ac201..2ae5873c82421 100644 --- a/tests/ui/type/type-ascription-with-fn-call.stderr +++ b/tests/ui/type/type-ascription-with-fn-call.stderr @@ -6,5 +6,5 @@ LL | f() : | = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/type-check/cannot_infer_local_or_array.stderr b/tests/ui/type/type-check/cannot_infer_local_or_array.stderr index e823bad2668ae..dafbab8278d1b 100644 --- a/tests/ui/type/type-check/cannot_infer_local_or_array.stderr +++ b/tests/ui/type/type-check/cannot_infer_local_or_array.stderr @@ -9,6 +9,6 @@ help: consider giving `x` an explicit type, where the placeholders `_` are speci LL | let x: [_; 0] = []; | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr index 7be00341d101e..fa90240d34e4c 100644 --- a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr +++ b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr @@ -9,6 +9,6 @@ help: consider giving `x` an explicit type, where the placeholders `_` are speci LL | let x: Vec<_> = vec![]; | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr index 1fa253052e649..5f389bee71074 100644 --- a/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -9,6 +9,6 @@ help: consider giving this pattern a type, where the placeholders `_` are specif LL | let (x, ): (Vec<_>,) = (vec![], ); | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.stderr b/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.stderr index 447b22a152d7e..3a8d9c71968d7 100644 --- a/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.stderr +++ b/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.stderr @@ -10,6 +10,6 @@ LL | out = note: expected enum `Result` found enum `Result<(), _>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/issue-22897.stderr b/tests/ui/type/type-check/issue-22897.stderr index fae7b79269bec..e3e8deb304640 100644 --- a/tests/ui/type/type-check/issue-22897.stderr +++ b/tests/ui/type/type-check/issue-22897.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | []; | ^^ cannot infer type for array `[_; 0]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/issue-40294.stderr b/tests/ui/type/type-check/issue-40294.stderr index d15fd23418bb0..c6c1d6893243e 100644 --- a/tests/ui/type/type-check/issue-40294.stderr +++ b/tests/ui/type/type-check/issue-40294.stderr @@ -12,6 +12,6 @@ LL | where &'a T : Foo, LL | &'b T : Foo | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type/type-check/issue-41314.stderr b/tests/ui/type/type-check/issue-41314.stderr index 4a9bf610647a7..2a089029b0a51 100644 --- a/tests/ui/type/type-check/issue-41314.stderr +++ b/tests/ui/type/type-check/issue-41314.stderr @@ -9,6 +9,6 @@ help: use the tuple variant pattern syntax instead LL | X::Y(number) => {} | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0769`. diff --git a/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr b/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr index a431fe89c237c..229729a9ba68d 100644 --- a/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr +++ b/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr @@ -17,6 +17,6 @@ LL | | _ => (), LL | | } | |_____- `match` arms have incompatible types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr b/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr index 847bc517ea3d3..1ef02321e15c8 100644 --- a/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr +++ b/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr @@ -9,5 +9,5 @@ LL | many_args!{[_]########## ######} | = note: this error originates in the macro `many_args` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type/type-check/point-at-inference-3.stderr b/tests/ui/type/type-check/point-at-inference-3.stderr index 238764812364c..663799e9f86b4 100644 --- a/tests/ui/type/type-check/point-at-inference-3.stderr +++ b/tests/ui/type/type-check/point-at-inference-3.stderr @@ -18,6 +18,6 @@ help: change the type of the numeric literal from `u32` to `i32` LL | v.push(1i32); | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/point-at-inference-issue-116155.stderr b/tests/ui/type/type-check/point-at-inference-issue-116155.stderr index c8c01603cb848..703694abe594d 100644 --- a/tests/ui/type/type-check/point-at-inference-issue-116155.stderr +++ b/tests/ui/type/type-check/point-at-inference-issue-116155.stderr @@ -13,6 +13,6 @@ LL | let _: S = s; = note: expected struct `S` found struct `S` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/point-at-inference.stderr b/tests/ui/type/type-check/point-at-inference.stderr index 5fc94d4d1b6ba..b5b0353eb18af 100644 --- a/tests/ui/type/type-check/point-at-inference.stderr +++ b/tests/ui/type/type-check/point-at-inference.stderr @@ -23,6 +23,6 @@ help: consider dereferencing the borrow LL | foo.push(*i); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-dependent-def-issue-49241.stderr b/tests/ui/type/type-dependent-def-issue-49241.stderr index 64c7687f7a882..15d47cca3d202 100644 --- a/tests/ui/type/type-dependent-def-issue-49241.stderr +++ b/tests/ui/type/type-dependent-def-issue-49241.stderr @@ -6,6 +6,6 @@ LL | const l: usize = v.count(); | | | help: consider using `let` instead of `const`: `let l` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/type/type-error-break-tail.stderr b/tests/ui/type/type-error-break-tail.stderr index 9a02bc28752ae..5ef522fee2a88 100644 --- a/tests/ui/type/type-error-break-tail.stderr +++ b/tests/ui/type/type-error-break-tail.stderr @@ -13,6 +13,6 @@ help: give it a value of the expected type LL | if false { break 42; } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr index 67a4745b399d6..16d08b2672267 100644 --- a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr +++ b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr @@ -9,6 +9,6 @@ LL | fn foo(x: &dyn Foo) { } | = note: because of the default `Self` reference, type parameters must be specified on object types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/type/type-parameter-names.stderr b/tests/ui/type/type-parameter-names.stderr index f0ca8afca4e74..8e3e2388c6cba 100644 --- a/tests/ui/type/type-parameter-names.stderr +++ b/tests/ui/type/type-parameter-names.stderr @@ -14,6 +14,6 @@ LL | x = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-params-in-different-spaces-1.stderr b/tests/ui/type/type-params-in-different-spaces-1.stderr index 7529f25bd8e4b..1d0e097fdc323 100644 --- a/tests/ui/type/type-params-in-different-spaces-1.stderr +++ b/tests/ui/type/type-params-in-different-spaces-1.stderr @@ -15,6 +15,6 @@ LL | *self + rhs = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-params-in-different-spaces-3.stderr b/tests/ui/type/type-params-in-different-spaces-3.stderr index c538d67316c6a..58783fe1ff008 100644 --- a/tests/ui/type/type-params-in-different-spaces-3.stderr +++ b/tests/ui/type/type-params-in-different-spaces-3.stderr @@ -15,6 +15,6 @@ LL | u = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-recursive-box-shadowed.stderr b/tests/ui/type/type-recursive-box-shadowed.stderr index cb0e982877cf7..8cc4eb36d82c7 100644 --- a/tests/ui/type/type-recursive-box-shadowed.stderr +++ b/tests/ui/type/type-recursive-box-shadowed.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | inner: Box, | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/type/type-shadow.stderr b/tests/ui/type/type-shadow.stderr index 25b4bff4d9aaa..999ba4b5fc53e 100644 --- a/tests/ui/type/type-shadow.stderr +++ b/tests/ui/type/type-shadow.stderr @@ -6,6 +6,6 @@ LL | let y: Y = "hello"; | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-unsatisfiable.usage.stderr b/tests/ui/type/type-unsatisfiable.usage.stderr index 0b76ba8eb7e83..b7c828b747933 100644 --- a/tests/ui/type/type-unsatisfiable.usage.stderr +++ b/tests/ui/type/type-unsatisfiable.usage.stderr @@ -6,6 +6,6 @@ LL | let bar = *hey - *word; | | | dyn Vector2 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/type_length_limit.polonius.stderr b/tests/ui/type_length_limit.polonius.stderr index 82d066b2a2fef..bc09f15918328 100644 --- a/tests/ui/type_length_limit.polonius.stderr +++ b/tests/ui/type_length_limit.polonius.stderr @@ -7,5 +7,5 @@ LL | pub fn drop(_x: T) {} = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit.polonius/type_length_limit.long-type.txt' = help: consider adding a `#![type_length_limit="8"]` attribute to your crate -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/type_length_limit.stderr b/tests/ui/type_length_limit.stderr index 5b00d387aba5d..32290a2f5bfc7 100644 --- a/tests/ui/type_length_limit.stderr +++ b/tests/ui/type_length_limit.stderr @@ -4,5 +4,5 @@ error: reached the type-length limit while instantiating `std::mem::drop::() | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs new file mode 100644 index 0000000000000..c8f6db7aef3e5 --- /dev/null +++ b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs @@ -0,0 +1,29 @@ +// Test against ICE in #118111 + +use std::ops::Index; + +struct Map { + f: F, + inner: T, +} + +impl Index for Map +where + T: Index, + F: FnOnce(&T, Idx) -> Idx, +{ + type Output = T::Output; + + fn index(&self, index: Idx) -> &Self::Output { + todo!() + } +} + +fn main() { + Map { inner: [0_usize], f: |_, i: usize| 1_usize }[0]; + //~^ ERROR cannot index into a value of type + // Problem here is that + // `f: |_, i: usize| ...` + // should be + // `f: |_: &_, i: usize| ...` +} diff --git a/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr new file mode 100644 index 0000000000000..93c370fd893e3 --- /dev/null +++ b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr @@ -0,0 +1,9 @@ +error[E0608]: cannot index into a value of type `Map<[usize; 1], {closure@$DIR/bad-index-modulo-higher-ranked-regions.rs:23:32: 23:45}>` + --> $DIR/bad-index-modulo-higher-ranked-regions.rs:23:55 + | +LL | Map { inner: [0_usize], f: |_, i: usize| 1_usize }[0]; + | ^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/typeck/bad-type-in-vec-contains.stderr b/tests/ui/typeck/bad-type-in-vec-contains.stderr index b9b3a5fe5ec8f..de9bd33eb1c2f 100644 --- a/tests/ui/typeck/bad-type-in-vec-contains.stderr +++ b/tests/ui/typeck/bad-type-in-vec-contains.stderr @@ -15,6 +15,6 @@ help: consider borrowing here LL | primes.contains(&3); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/call-block.stderr b/tests/ui/typeck/call-block.stderr index 68984bc1c453f..3c67cdd0fbc5e 100644 --- a/tests/ui/typeck/call-block.stderr +++ b/tests/ui/typeck/call-block.stderr @@ -6,6 +6,6 @@ LL | let _ = {42}(); | | | call expression requires function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/typeck/check-args-on-fn-err.stderr b/tests/ui/typeck/check-args-on-fn-err.stderr index 864d33e0e93bb..be0798ab107c0 100644 --- a/tests/ui/typeck/check-args-on-fn-err.stderr +++ b/tests/ui/typeck/check-args-on-fn-err.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `unknown` in this scope LL | unknown(1, |glyf| { | ^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/typeck/derive-sugg-arg-arity.stderr b/tests/ui/typeck/derive-sugg-arg-arity.stderr index 5b4c481719830..41b16a772ca95 100644 --- a/tests/ui/typeck/derive-sugg-arg-arity.stderr +++ b/tests/ui/typeck/derive-sugg-arg-arity.stderr @@ -26,6 +26,6 @@ LL + #[derive(PartialEq, PartialOrd)] LL | pub struct A; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr index 02e87d701b687..b651d80292d7d 100644 --- a/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr +++ b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr @@ -12,6 +12,6 @@ note: method defined here LL | fn setFrame_display_(self, display: ()) {} | ^^^^^^^^^^^^^^^^^ ----------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/escaping_bound_vars.stderr b/tests/ui/typeck/escaping_bound_vars.stderr index f7077e52a707f..3ea409435779e 100644 --- a/tests/ui/typeck/escaping_bound_vars.stderr +++ b/tests/ui/typeck/escaping_bound_vars.stderr @@ -6,5 +6,5 @@ LL | (): Test<{ 1 + (<() as Elide(&())>::call) }>, | | | lifetime defined here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-100246.stderr b/tests/ui/typeck/issue-100246.stderr index 428a0792091e6..86eb163b4713a 100644 --- a/tests/ui/typeck/issue-100246.stderr +++ b/tests/ui/typeck/issue-100246.stderr @@ -8,6 +8,6 @@ LL | let other: Other = downcast()?; = note: expected struct `Other` found reference `&_` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-100285.rs b/tests/ui/typeck/issue-100285.rs index e206469b85f55..460e0457105f5 100644 --- a/tests/ui/typeck/issue-100285.rs +++ b/tests/ui/typeck/issue-100285.rs @@ -1,6 +1,5 @@ -fn foo(n: i32) -> i32 { - for i in 0..0 { - //~^ ERROR: mismatched types [E0308] +fn foo(n: i32) -> i32 { //~ HELP otherwise consider changing the return type to account for that possibility + for i in 0..0 { //~ ERROR mismatched types [E0308] if n < 0 { return i; } else if n < 10 { @@ -15,8 +14,7 @@ fn foo(n: i32) -> i32 { return 5; } - } - //~| help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility + } //~ HELP return a value for the case when the loop has zero elements to iterate on } fn main() {} diff --git a/tests/ui/typeck/issue-100285.stderr b/tests/ui/typeck/issue-100285.stderr index 42c64b03918c5..9c8685a77127b 100644 --- a/tests/ui/typeck/issue-100285.stderr +++ b/tests/ui/typeck/issue-100285.stderr @@ -4,9 +4,9 @@ error[E0308]: mismatched types LL | fn foo(n: i32) -> i32 { | --- expected `i32` because of return type LL | / for i in 0..0 { -LL | | LL | | if n < 0 { LL | | return i; +LL | | } else if n < 10 { ... | LL | | LL | | } @@ -17,7 +17,7 @@ note: the function expects a value to always be returned, but loops might run ze | LL | for i in 0..0 { | ^^^^^^^^^^^^^ this might have zero elements to iterate on -... +LL | if n < 0 { LL | return i; | -------- if the loop doesn't execute, this value would never get returned LL | } else if n < 10 { @@ -27,8 +27,33 @@ LL | } else if n < 20 { LL | return 2; | -------- if the loop doesn't execute, this value would never get returned = note: if the loop doesn't execute, 3 other values would never get returned - = help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility +help: return a value for the case when the loop has zero elements to iterate on + | +LL ~ } +LL ~ /* `i32` value */ + | +help: otherwise consider changing the return type to account for that possibility + | +LL ~ fn foo(n: i32) -> Option { +LL | for i in 0..0 { +LL | if n < 0 { +LL ~ return Some(i); +LL | } else if n < 10 { +LL ~ return Some(1); +LL | } else if n < 20 { +LL ~ return Some(2); +LL | } else if n < 30 { +LL ~ return Some(3); +LL | } else if n < 40 { +LL ~ return Some(4); +LL | } else { +LL ~ return Some(5); +LL | } +LL | +LL ~ } +LL ~ None + | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-10401.stderr b/tests/ui/typeck/issue-10401.stderr index 1f68abcfb4371..1b7daa9c2b9ba 100644 --- a/tests/ui/typeck/issue-10401.stderr +++ b/tests/ui/typeck/issue-10401.stderr @@ -6,6 +6,6 @@ LL | a += { "b" }; | | | cannot use `+=` on type `&str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0368`. diff --git a/tests/ui/typeck/issue-104510-ice.stderr b/tests/ui/typeck/issue-104510-ice.stderr index ddb510ef04772..143139b2c089c 100644 --- a/tests/ui/typeck/issue-104510-ice.stderr +++ b/tests/ui/typeck/issue-104510-ice.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Oops` in this scope LL | struct W(Oops); | ^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/issue-105946.stderr b/tests/ui/typeck/issue-105946.stderr index 26c3b7fbc841d..2220271e58122 100644 --- a/tests/ui/typeck/issue-105946.stderr +++ b/tests/ui/typeck/issue-105946.stderr @@ -3,6 +3,11 @@ error[E0425]: cannot find value `_y` in this scope | LL | let [_y..] = [Box::new(1), Box::new(2)]; | ^^ not found in this scope + | +help: if you meant to collect the rest of the slice in `_y`, use the at operator + | +LL | let [_y @ ..] = [Box::new(1), Box::new(2)]; + | + error[E0658]: `X..` patterns in slices are experimental --> $DIR/issue-105946.rs:6:10 diff --git a/tests/ui/typeck/issue-106929.stderr b/tests/ui/typeck/issue-106929.stderr index f744e5a41f0cd..375c9372ec288 100644 --- a/tests/ui/typeck/issue-106929.stderr +++ b/tests/ui/typeck/issue-106929.stderr @@ -10,6 +10,6 @@ LL - post(c, ()); LL + c.post(()); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/typeck/issue-107087.stderr b/tests/ui/typeck/issue-107087.stderr index 8921e3f7694d4..289c8d161ae86 100644 --- a/tests/ui/typeck/issue-107087.stderr +++ b/tests/ui/typeck/issue-107087.stderr @@ -4,6 +4,6 @@ error[E0223]: ambiguous associated type LL | A::B::<>::C | ^^^^^^^^ help: use fully-qualified syntax: ` as Foo>::B` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/typeck/issue-107775.stderr b/tests/ui/typeck/issue-107775.stderr index b97e74b7e53fa..180b0183a3f2d 100644 --- a/tests/ui/typeck/issue-107775.stderr +++ b/tests/ui/typeck/issue-107775.stderr @@ -11,6 +11,6 @@ LL | Self { map } = note: expected struct `HashMap Pin + Send + 'static)>>>` found struct `HashMap<{integer}, fn(_) -> Pin + Send>> {::do_something::<'_>}>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr index 75374fa6121e6..b25b6c0c0b78c 100644 --- a/tests/ui/typeck/issue-110052.stderr +++ b/tests/ui/typeck/issue-110052.stderr @@ -4,6 +4,6 @@ error[E0223]: ambiguous associated type LL | for<'iter> dyn Validator<<&'iter I>::Item>:, | ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'iter I as IntoIterator>::Item` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.stderr b/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.stderr index cf2648d084079..c7d853428dd2e 100644 --- a/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.stderr +++ b/tests/ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.stderr @@ -9,6 +9,6 @@ help: consider adding `let` LL | while let Some(foo) = None {} | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-114529-illegal-break-with-value.rs b/tests/ui/typeck/issue-114529-illegal-break-with-value.rs index 613d1b6343a34..353a935e37313 100644 --- a/tests/ui/typeck/issue-114529-illegal-break-with-value.rs +++ b/tests/ui/typeck/issue-114529-illegal-break-with-value.rs @@ -17,4 +17,10 @@ fn main() { }; 51 }]; + + while true { + break (|| { //~ ERROR `break` with value from a `while` loop + let local = 9; + }); + } } diff --git a/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr b/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr index 4d6c27bbbd03b..731f234c162ad 100644 --- a/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr +++ b/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr @@ -24,6 +24,21 @@ help: use `break` on its own without a value inside this `while` loop LL | break; | ~~~~~ -error: aborting due to 2 previous errors +error[E0571]: `break` with value from a `while` loop + --> $DIR/issue-114529-illegal-break-with-value.rs:22:9 + | +LL | while true { + | ---------- you can't `break` with a value in a `while` loop +LL | / break (|| { +LL | | let local = 9; +LL | | }); + | |__________^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ~~~~~ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0571`. diff --git a/tests/ui/typeck/issue-114918/const-in-fn-return-type.stderr b/tests/ui/typeck/issue-114918/const-in-fn-return-type.stderr index 88ed96e148cc2..02c212e2492fe 100644 --- a/tests/ui/typeck/issue-114918/const-in-fn-return-type.stderr +++ b/tests/ui/typeck/issue-114918/const-in-fn-return-type.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | fn func() -> [u8; { () } ] { | ^^ expected `usize`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-114918/const-in-struct-type-arg.stderr b/tests/ui/typeck/issue-114918/const-in-struct-type-arg.stderr index 3307e76d95755..5941ea188b534 100644 --- a/tests/ui/typeck/issue-114918/const-in-struct-type-arg.stderr +++ b/tests/ui/typeck/issue-114918/const-in-struct-type-arg.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | let s = S::<{ () }> { arr: [5, 6, 7]}; | ^^ expected `usize`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-114918/const-in-trait-fn-return-type.stderr b/tests/ui/typeck/issue-114918/const-in-trait-fn-return-type.stderr index 6bc0de77a6267..063e21f402355 100644 --- a/tests/ui/typeck/issue-114918/const-in-trait-fn-return-type.stderr +++ b/tests/ui/typeck/issue-114918/const-in-trait-fn-return-type.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | fn func() -> [ (); { () }] { | ^^ expected `usize`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-13853-2.stderr b/tests/ui/typeck/issue-13853-2.stderr index 92068df6c0570..af50e8da7f0c9 100644 --- a/tests/ui/typeck/issue-13853-2.stderr +++ b/tests/ui/typeck/issue-13853-2.stderr @@ -9,6 +9,6 @@ help: use parentheses to call the method LL | fn foo(res : Box) { res.get() } | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/typeck/issue-13853-5.stderr b/tests/ui/typeck/issue-13853-5.stderr index 3d8f824ec94cb..1eead9563286c 100644 --- a/tests/ui/typeck/issue-13853-5.stderr +++ b/tests/ui/typeck/issue-13853-5.stderr @@ -4,6 +4,6 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl<'a, T: Deserializable> Deserializable for &'a str { | ^ unconstrained type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/typeck/issue-1871.stderr b/tests/ui/typeck/issue-1871.stderr index b774ca22dd72a..808226015b50c 100644 --- a/tests/ui/typeck/issue-1871.stderr +++ b/tests/ui/typeck/issue-1871.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `honk` found for type `{integer}` in the current s LL | f.honk() | ^^^^ method not found in `{integer}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-18937.stderr b/tests/ui/typeck/issue-18937.stderr index 5e2ba0ef4fc5a..0575751a89624 100644 --- a/tests/ui/typeck/issue-18937.stderr +++ b/tests/ui/typeck/issue-18937.stderr @@ -9,6 +9,6 @@ LL | | Self: Sized; LL | where F: fmt::Debug + 'static, | ^^^^^^^ impl has extra requirement `F: 'static` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/typeck/issue-33575.stderr b/tests/ui/typeck/issue-33575.stderr index bbd8042d1cd6b..dc723952ff10d 100644 --- a/tests/ui/typeck/issue-33575.stderr +++ b/tests/ui/typeck/issue-33575.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `foo` found for unit type `()` in the current scop LL | let baz = ().foo(); | ^^^ method not found in `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-36708.stderr b/tests/ui/typeck/issue-36708.stderr index f1e0f4719281c..3589796b6aac6 100644 --- a/tests/ui/typeck/issue-36708.stderr +++ b/tests/ui/typeck/issue-36708.stderr @@ -9,6 +9,6 @@ LL | fn foo() {} LL | fn foo(); | --------- expected 0 type parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/typeck/issue-43189.stderr b/tests/ui/typeck/issue-43189.stderr index c072e6a08ba0b..2e12651699d45 100644 --- a/tests/ui/typeck/issue-43189.stderr +++ b/tests/ui/typeck/issue-43189.stderr @@ -15,6 +15,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use xcrate_issue_43189_b::xcrate_issue_43189_a::A; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-46112.stderr b/tests/ui/typeck/issue-46112.stderr index 26fc21dda06ae..16beaea75db7f 100644 --- a/tests/ui/typeck/issue-46112.stderr +++ b/tests/ui/typeck/issue-46112.stderr @@ -22,6 +22,6 @@ help: try wrapping the expression in `Some` LL | fn main() { test(Ok(Some(()))); } | +++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-50687-ice-on-borrow.stderr b/tests/ui/typeck/issue-50687-ice-on-borrow.stderr index 9e48ccefd86b9..24dce4697929d 100644 --- a/tests/ui/typeck/issue-50687-ice-on-borrow.stderr +++ b/tests/ui/typeck/issue-50687-ice-on-borrow.stderr @@ -13,6 +13,6 @@ help: consider dereferencing the borrow LL | let _: () = *Borrow::borrow(&owned); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr b/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr index 4be4c91dfc2c3..e1091c8f5ca00 100644 --- a/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr +++ b/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr @@ -5,7 +5,7 @@ LL | fn equals_ref(a: &Point, b: &Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `x` on type `&Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:18 @@ -14,7 +14,7 @@ LL | fn equals_ref(a: &Point, b: &Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `y` on type `&Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:25 @@ -23,7 +23,7 @@ LL | fn equals_ref(a: &Point, b: &Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `y` on type `&Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:32 @@ -32,7 +32,7 @@ LL | fn equals_ref(a: &Point, b: &Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `x` on type `Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:11 @@ -41,7 +41,7 @@ LL | fn equals_val(a: Point, b: Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `x` on type `Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:18 @@ -50,7 +50,7 @@ LL | fn equals_val(a: Point, b: Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `y` on type `Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:25 @@ -59,7 +59,7 @@ LL | fn equals_val(a: Point, b: Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `y` on type `Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:32 @@ -68,7 +68,7 @@ LL | fn equals_val(a: Point, b: Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error: aborting due to 8 previous errors diff --git a/tests/ui/typeck/issue-53712.stderr b/tests/ui/typeck/issue-53712.stderr index db85919afcb55..ec31766324b26 100644 --- a/tests/ui/typeck/issue-53712.stderr +++ b/tests/ui/typeck/issue-53712.stderr @@ -3,9 +3,10 @@ error[E0609]: no field `0` on type `[{integer}; 5]` | LL | arr.0; | ----^ - | | + | | | + | | unknown field | help: instead of using tuple indexing, use array indexing: `arr[0]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/typeck/issue-57404.stderr b/tests/ui/typeck/issue-57404.stderr index a631dbb39fb8f..4c1bfc0cbf773 100644 --- a/tests/ui/typeck/issue-57404.stderr +++ b/tests/ui/typeck/issue-57404.stderr @@ -14,6 +14,6 @@ LL - handlers.unwrap().as_mut().call_mut(&mut ()); LL + handlers.unwrap().as_mut().call_mut(()); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr index 6c3302f29c2dc..3018388806294 100644 --- a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr +++ b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr @@ -9,6 +9,6 @@ LL | *x = note: expected unit type `()` found trait object `(dyn Iterator + 'static)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-65611.stderr b/tests/ui/typeck/issue-65611.stderr index 003c630790d2c..2278450a6d8eb 100644 --- a/tests/ui/typeck/issue-65611.stderr +++ b/tests/ui/typeck/issue-65611.stderr @@ -8,7 +8,7 @@ error[E0609]: no field `0` on type `&_` --> $DIR/issue-65611.rs:59:36 | LL | let x = buffer.last().unwrap().0.clone(); - | ^ + | ^ unknown field error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr b/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr index fc7c23a225240..1b70c6f9d02ad 100644 --- a/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr +++ b/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr @@ -6,5 +6,5 @@ LL | struct Foo { 0: u8 } | | | while parsing this struct -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-7813.stderr b/tests/ui/typeck/issue-7813.stderr index 2a747f679a84d..953cbd206dc77 100644 --- a/tests/ui/typeck/issue-7813.stderr +++ b/tests/ui/typeck/issue-7813.stderr @@ -9,6 +9,6 @@ help: consider giving `v` an explicit type, where the placeholders `_` are speci LL | let v: &[_; 0] = &[]; | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/typeck/issue-83621-placeholder-static-in-extern.stderr b/tests/ui/typeck/issue-83621-placeholder-static-in-extern.stderr index 9376e8bcf80bc..a4cb53025e3be 100644 --- a/tests/ui/typeck/issue-83621-placeholder-static-in-extern.stderr +++ b/tests/ui/typeck/issue-83621-placeholder-static-in-extern.stderr @@ -4,6 +4,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | static x: _; | ^ not allowed in type signatures -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-84160.stderr b/tests/ui/typeck/issue-84160.stderr index 4d456ae842f62..1dc798b5e229d 100644 --- a/tests/ui/typeck/issue-84160.stderr +++ b/tests/ui/typeck/issue-84160.stderr @@ -10,6 +10,6 @@ LL | return "test"; = note: expected reference `&u32` found reference `&'static str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-86721-return-expr-ice.rev1.stderr b/tests/ui/typeck/issue-86721-return-expr-ice.rev1.stderr index b1111fcf1484c..36ae7d5de1bf1 100644 --- a/tests/ui/typeck/issue-86721-return-expr-ice.rev1.stderr +++ b/tests/ui/typeck/issue-86721-return-expr-ice.rev1.stderr @@ -4,6 +4,6 @@ error[E0572]: return statement outside of function body LL | const U: usize = return; | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/typeck/issue-86721-return-expr-ice.rev2.stderr b/tests/ui/typeck/issue-86721-return-expr-ice.rev2.stderr index f489ae2002a13..ff781a68dc69a 100644 --- a/tests/ui/typeck/issue-86721-return-expr-ice.rev2.stderr +++ b/tests/ui/typeck/issue-86721-return-expr-ice.rev2.stderr @@ -4,6 +4,6 @@ error[E0572]: return statement outside of function body LL | fn foo(a: [(); return]); | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/typeck/issue-87181/empty-tuple-method.stderr b/tests/ui/typeck/issue-87181/empty-tuple-method.stderr index f0ca49e6d1e3e..a34ed08376a21 100644 --- a/tests/ui/typeck/issue-87181/empty-tuple-method.stderr +++ b/tests/ui/typeck/issue-87181/empty-tuple-method.stderr @@ -9,6 +9,6 @@ help: use parentheses to construct this tuple struct LL | (thing.bar)().foo(); | + +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-87181/enum-variant.stderr b/tests/ui/typeck/issue-87181/enum-variant.stderr index d313a887abd98..800369b517655 100644 --- a/tests/ui/typeck/issue-87181/enum-variant.stderr +++ b/tests/ui/typeck/issue-87181/enum-variant.stderr @@ -9,6 +9,6 @@ help: use parentheses to construct this tuple variant LL | (thing.bar)().foo(); | + +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-87181/tuple-field.stderr b/tests/ui/typeck/issue-87181/tuple-field.stderr index 0a7d30b615a63..e4b5a155e49f9 100644 --- a/tests/ui/typeck/issue-87181/tuple-field.stderr +++ b/tests/ui/typeck/issue-87181/tuple-field.stderr @@ -2,13 +2,13 @@ error[E0609]: no field `0` on type `fn(char, u16) -> Foo {Foo}` --> $DIR/tuple-field.rs:12:15 | LL | thing.bar.0; - | ^ + | ^ unknown field | help: use parentheses to construct this tuple struct | LL | (thing.bar)(/* char */, /* u16 */).0; | + ++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/typeck/issue-87181/tuple-method.stderr b/tests/ui/typeck/issue-87181/tuple-method.stderr index de3dc15a54b12..87145d9bbd634 100644 --- a/tests/ui/typeck/issue-87181/tuple-method.stderr +++ b/tests/ui/typeck/issue-87181/tuple-method.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `foo` found for struct constructor `fn(u8, i32) -> LL | thing.bar.foo(); | ^^^ method not found in `fn(u8, i32) -> Foo {Foo}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr b/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr index 56817ee2ca9f8..93c52f3c5b371 100644 --- a/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr +++ b/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr @@ -6,6 +6,6 @@ LL | let mut a; LL | a = a = true; | ^^^^^^^^ expected `bool`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr b/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr index f0bd3e0ddf768..899dd02583a71 100644 --- a/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr +++ b/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr @@ -4,7 +4,7 @@ error: cannot construct `Foo` with struct literal syntax due to private fields LL | foo::Foo {}; | ^^^^^^^^ | - = note: ... and other private field `you_cant_use_this_field` that was not provided + = note: private field `you_cant_use_this_field` that was not provided -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr index dc30975103ccc..96ac481438f7a 100644 --- a/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr +++ b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr @@ -13,6 +13,6 @@ help: if you don't care about this missing field, you can explicitly ignore it LL | let foo::Foo { .. } = foo::Foo::default(); | ~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/typeck/issue-88803-call-expr-method.stderr b/tests/ui/typeck/issue-88803-call-expr-method.stderr index 645c04b87a1fd..ebae93cee2b34 100644 --- a/tests/ui/typeck/issue-88803-call-expr-method.stderr +++ b/tests/ui/typeck/issue-88803-call-expr-method.stderr @@ -10,6 +10,6 @@ LL - (a.unwrap)() LL + a.unwrap() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/typeck/issue-88844.stderr b/tests/ui/typeck/issue-88844.stderr index 90bba90be346c..68473f65dcf53 100644 --- a/tests/ui/typeck/issue-88844.stderr +++ b/tests/ui/typeck/issue-88844.stderr @@ -7,6 +7,6 @@ LL | struct Struct { value: i32 } LL | impl Stuct { | ^^^^^ help: a struct with a similar name exists: `Struct` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/issue-89044-wrapped-expr-method.stderr b/tests/ui/typeck/issue-89044-wrapped-expr-method.stderr index 6fa0915dcaf9a..bb407fdb8a9c6 100644 --- a/tests/ui/typeck/issue-89044-wrapped-expr-method.stderr +++ b/tests/ui/typeck/issue-89044-wrapped-expr-method.stderr @@ -9,6 +9,6 @@ help: use parentheses to call the method LL | (a.unwrap()) | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/typeck/issue-89275.stderr b/tests/ui/typeck/issue-89275.stderr index d73e647d21f6b..6686d5f977e6b 100644 --- a/tests/ui/typeck/issue-89275.stderr +++ b/tests/ui/typeck/issue-89275.stderr @@ -9,6 +9,6 @@ LL | let other: &mut Other = downcast(); = note: expected mutable reference `&mut Other` found reference `&_` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-89806.stderr b/tests/ui/typeck/issue-89806.stderr index c36b4967ee996..554a06cb6afd1 100644 --- a/tests/ui/typeck/issue-89806.stderr +++ b/tests/ui/typeck/issue-89806.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `as_ref` found for type `u8` in the current scope LL | 0u8.as_ref(); | ^^^^^^ method not found in `u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-90101.stderr b/tests/ui/typeck/issue-90101.stderr index 484089f9e87e3..a24f9cb540fc8 100644 --- a/tests/ui/typeck/issue-90101.stderr +++ b/tests/ui/typeck/issue-90101.stderr @@ -19,6 +19,6 @@ note: required by a bound in `func` LL | fn func(path: impl Into, code: impl Into) {} | ^^^^^^^^^^^^^ required by this bound in `func` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-90164.stderr b/tests/ui/typeck/issue-90164.stderr index 8586f522291b7..43e96e1adc6bd 100644 --- a/tests/ui/typeck/issue-90164.stderr +++ b/tests/ui/typeck/issue-90164.stderr @@ -18,6 +18,6 @@ help: consider restricting type parameter `T` LL | fn f(r: T) { | ++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-90319.stderr b/tests/ui/typeck/issue-90319.stderr index 61549dd701e74..fa18056e802d4 100644 --- a/tests/ui/typeck/issue-90319.stderr +++ b/tests/ui/typeck/issue-90319.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Thing` in this scope LL | let thing = get::(); | ^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr b/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr index 02cdc102c15ba..fff9f5da16ff4 100644 --- a/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr +++ b/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr @@ -9,6 +9,6 @@ help: a method `foo` also exists, call it with parentheses LL | || s.foo() + s.foo(); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr b/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr index a75024aa24818..2d4069f502968 100644 --- a/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr +++ b/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr @@ -10,6 +10,6 @@ note: required by a bound in `check` LL | pub fn check>(_: T) {} | ^^^^^^^^^^^ required by this bound in `check` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-91210-ptr-method.stderr b/tests/ui/typeck/issue-91210-ptr-method.stderr index 7a0cfb2cf51a7..f2f996c7b304e 100644 --- a/tests/ui/typeck/issue-91210-ptr-method.stderr +++ b/tests/ui/typeck/issue-91210-ptr-method.stderr @@ -9,6 +9,6 @@ help: to access the field, dereference first LL | (*x).read = 4; | ++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/typeck/issue-92481.stderr b/tests/ui/typeck/issue-92481.stderr index d87d3277d563a..a1fdd8359a632 100644 --- a/tests/ui/typeck/issue-92481.stderr +++ b/tests/ui/typeck/issue-92481.stderr @@ -7,5 +7,5 @@ LL | fn r({) { | |unclosed delimiter | closing delimiter possibly meant for this -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-93486.stderr b/tests/ui/typeck/issue-93486.stderr index 167edc8942aec..c1489d9bcaa14 100644 --- a/tests/ui/typeck/issue-93486.stderr +++ b/tests/ui/typeck/issue-93486.stderr @@ -11,6 +11,6 @@ help: consider dereferencing here to assign to the mutably borrowed value LL | *vec![].last_mut().unwrap() = 3_u8; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/typeck/issue-96530.stderr b/tests/ui/typeck/issue-96530.stderr index 3a67ef0260b41..d2fb8169ffca0 100644 --- a/tests/ui/typeck/issue-96530.stderr +++ b/tests/ui/typeck/issue-96530.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | ..man.clone() | ^^^^^^^^^^^ expected `Person`, found `&Person` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-96738.stderr b/tests/ui/typeck/issue-96738.stderr index 547cffffa2ee3..2bc8453dda74d 100644 --- a/tests/ui/typeck/issue-96738.stderr +++ b/tests/ui/typeck/issue-96738.stderr @@ -8,7 +8,7 @@ error[E0609]: no field `nonexistent_field` on type `fn(_) -> Option<_> {Option:: --> $DIR/issue-96738.rs:3:10 | LL | Some.nonexistent_field; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ unknown field error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-98260.stderr b/tests/ui/typeck/issue-98260.stderr index 08a1d17e244a8..b7debd335b0fb 100644 --- a/tests/ui/typeck/issue-98260.stderr +++ b/tests/ui/typeck/issue-98260.stderr @@ -7,6 +7,6 @@ LL | fn a(aa: B) -> Result<_, B> { | | not allowed in type signatures | help: replace with the correct return type: `Result<(), B>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-98982.rs b/tests/ui/typeck/issue-98982.rs index 2553824bbfebb..f875d20fa4c53 100644 --- a/tests/ui/typeck/issue-98982.rs +++ b/tests/ui/typeck/issue-98982.rs @@ -1,9 +1,7 @@ -fn foo() -> i32 { - for i in 0..0 { - //~^ ERROR: mismatched types [E0308] +fn foo() -> i32 { //~ HELP otherwise consider changing the return type to account for that possibility + for i in 0..0 { //~ ERROR mismatched types [E0308] return i; - } - //~| help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility + } //~ HELP return a value for the case when the loop has zero elements to iterate on } fn main() {} diff --git a/tests/ui/typeck/issue-98982.stderr b/tests/ui/typeck/issue-98982.stderr index 3c9806ac965fb..d8d5a86b157f2 100644 --- a/tests/ui/typeck/issue-98982.stderr +++ b/tests/ui/typeck/issue-98982.stderr @@ -4,7 +4,6 @@ error[E0308]: mismatched types LL | fn foo() -> i32 { | --- expected `i32` because of return type LL | / for i in 0..0 { -LL | | LL | | return i; LL | | } | |_____^ expected `i32`, found `()` @@ -14,11 +13,22 @@ note: the function expects a value to always be returned, but loops might run ze | LL | for i in 0..0 { | ^^^^^^^^^^^^^ this might have zero elements to iterate on -LL | LL | return i; | -------- if the loop doesn't execute, this value would never get returned - = help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility +help: return a value for the case when the loop has zero elements to iterate on + | +LL ~ } +LL ~ /* `i32` value */ + | +help: otherwise consider changing the return type to account for that possibility + | +LL ~ fn foo() -> Option { +LL | for i in 0..0 { +LL ~ return Some(i); +LL ~ } +LL ~ None + | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/mismatched-map-under-self.stderr b/tests/ui/typeck/mismatched-map-under-self.stderr index 51491407c4938..41391720a28c5 100644 --- a/tests/ui/typeck/mismatched-map-under-self.stderr +++ b/tests/ui/typeck/mismatched-map-under-self.stderr @@ -30,6 +30,10 @@ LL | self.map(Insertable::values).unwrap_or_default() found function signature `for<'a> fn(&'a _) -> _` note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL +help: consider wrapping the function in a closure + | +LL | self.map(|arg0: T| Insertable::values(&arg0)).unwrap_or_default() + | +++++++++ +++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/missing-private-fields-in-struct-literal.stderr b/tests/ui/typeck/missing-private-fields-in-struct-literal.stderr index 234110f31f79c..003eaa405924a 100644 --- a/tests/ui/typeck/missing-private-fields-in-struct-literal.stderr +++ b/tests/ui/typeck/missing-private-fields-in-struct-literal.stderr @@ -9,7 +9,7 @@ LL | a: (), LL | b: (), | ----- private field | - = note: ... and other private fields `c`, `d` and `e` that were not provided + = note: ...and other private fields `c`, `d` and `e` that were not provided -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/typeck/no-type-for-node-ice.stderr b/tests/ui/typeck/no-type-for-node-ice.stderr index b50241fb1a059..a79d6b600ebe5 100644 --- a/tests/ui/typeck/no-type-for-node-ice.stderr +++ b/tests/ui/typeck/no-type-for-node-ice.stderr @@ -2,8 +2,8 @@ error[E0609]: no field `homura` on type `&'static str` --> $DIR/no-type-for-node-ice.rs:4:8 | LL | "".homura[""]; - | ^^^^^^ + | ^^^^^^ unknown field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/typeck/nonexistent-field-not-ambiguous.stderr b/tests/ui/typeck/nonexistent-field-not-ambiguous.stderr index 76a2a5f99f2b6..82207a731b962 100644 --- a/tests/ui/typeck/nonexistent-field-not-ambiguous.stderr +++ b/tests/ui/typeck/nonexistent-field-not-ambiguous.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `MissingType` in this scope LL | val: MissingType, | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/output-type-mismatch.stderr b/tests/ui/typeck/output-type-mismatch.stderr index 4507a4df621e1..c6df6650654a6 100644 --- a/tests/ui/typeck/output-type-mismatch.stderr +++ b/tests/ui/typeck/output-type-mismatch.stderr @@ -6,6 +6,6 @@ LL | fn main() { let i: isize; i = f(); } | | | expected due to this type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr index b01e30be54de0..3e03c17f3b1c3 100644 --- a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr +++ b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `page_size` LL | let page_size = page_size::get(); | ^^^^^^^^^ use of undeclared crate or module `page_size` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/typeck/point-at-type-param-in-path-expr.stderr b/tests/ui/typeck/point-at-type-param-in-path-expr.stderr index 1feaa0508bfa7..14642b25c9943 100644 --- a/tests/ui/typeck/point-at-type-param-in-path-expr.stderr +++ b/tests/ui/typeck/point-at-type-param-in-path-expr.stderr @@ -12,6 +12,6 @@ note: required by a bound in `foo` LL | fn foo() {} | ^^^^^^^^^^^^^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/point-at-type-parameter-definition.stderr b/tests/ui/typeck/point-at-type-parameter-definition.stderr index 8a6ab61100d24..bfe01f3614e0c 100644 --- a/tests/ui/typeck/point-at-type-parameter-definition.stderr +++ b/tests/ui/typeck/point-at-type-parameter-definition.stderr @@ -7,6 +7,6 @@ LL | fn do_stuff(&self) { LL | self[0].method(); | ^^^^^^ method not found in `Hello` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/ptr-null-mutability-suggestions.stderr b/tests/ui/typeck/ptr-null-mutability-suggestions.stderr index 705b029bdeab5..b615d9fb45cbe 100644 --- a/tests/ui/typeck/ptr-null-mutability-suggestions.stderr +++ b/tests/ui/typeck/ptr-null-mutability-suggestions.stderr @@ -16,6 +16,6 @@ note: function defined here LL | fn expecting_null_mut(_: *mut u8) {} | ^^^^^^^^^^^^^^^^^^ ---------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/quiet-type-err-let-binding.stderr b/tests/ui/typeck/quiet-type-err-let-binding.stderr index ad7f85e01ec06..f27ca1dd58206 100644 --- a/tests/ui/typeck/quiet-type-err-let-binding.stderr +++ b/tests/ui/typeck/quiet-type-err-let-binding.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `foo` in this scope LL | let x = foo(); | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/typeck/remove-extra-argument.stderr b/tests/ui/typeck/remove-extra-argument.stderr index 72ddebab486ce..9557c41457dcd 100644 --- a/tests/ui/typeck/remove-extra-argument.stderr +++ b/tests/ui/typeck/remove-extra-argument.stderr @@ -13,6 +13,6 @@ note: function defined here LL | fn l(_a: Vec) {} | ^ ----------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/typeck/repeat-expr-checks-wf.stderr b/tests/ui/typeck/repeat-expr-checks-wf.stderr index a821088a4b30e..8d5b57ead03a4 100644 --- a/tests/ui/typeck/repeat-expr-checks-wf.stderr +++ b/tests/ui/typeck/repeat-expr-checks-wf.stderr @@ -7,6 +7,6 @@ LL | let a = [T::ASSOC; 2]; = help: the trait `Sized` is not implemented for `[u8]` = note: slice and array elements must have `Sized` type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/return-dyn-type-mismatch-2.stderr b/tests/ui/typeck/return-dyn-type-mismatch-2.stderr index 9c368e83834b1..77299621ab91e 100644 --- a/tests/ui/typeck/return-dyn-type-mismatch-2.stderr +++ b/tests/ui/typeck/return-dyn-type-mismatch-2.stderr @@ -10,6 +10,6 @@ LL | 42 = note: expected trait object `(dyn Trait + 'static)` found type `{integer}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/return-dyn-type-mismatch.stderr b/tests/ui/typeck/return-dyn-type-mismatch.stderr index 9d0a609d87f81..064d0d64e0789 100644 --- a/tests/ui/typeck/return-dyn-type-mismatch.stderr +++ b/tests/ui/typeck/return-dyn-type-mismatch.stderr @@ -10,6 +10,6 @@ LL | None => None, = note: expected trait object `(dyn TestTrait + 'static)` found enum `Option<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/return_type_containing_closure.stderr b/tests/ui/typeck/return_type_containing_closure.stderr index 7be46ac073ea8..ea9c74be36238 100644 --- a/tests/ui/typeck/return_type_containing_closure.stderr +++ b/tests/ui/typeck/return_type_containing_closure.stderr @@ -15,6 +15,6 @@ help: a return type might be missing here LL | fn foo() -> _ { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/suppressed-error.stderr b/tests/ui/typeck/suppressed-error.stderr index 11d70f8a43369..0b68fc97e7888 100644 --- a/tests/ui/typeck/suppressed-error.stderr +++ b/tests/ui/typeck/suppressed-error.stderr @@ -9,6 +9,6 @@ LL | let (x, y) = (); = note: expected unit type `()` found tuple `(_, _)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr b/tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr index c4f1642956343..3a7e2068ca63f 100644 --- a/tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr +++ b/tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr @@ -13,6 +13,6 @@ help: consider using `Option::expect` to unwrap the `Option<_>` value, panicking LL | let x : char = last(y).expect("REASON"); | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/terr-in-field.stderr b/tests/ui/typeck/terr-in-field.stderr index 09df4b34bb52d..adc336db50164 100644 --- a/tests/ui/typeck/terr-in-field.stderr +++ b/tests/ui/typeck/terr-in-field.stderr @@ -12,6 +12,6 @@ note: function defined here LL | fn want_foo(f: Foo) {} | ^^^^^^^^ ------ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/terr-sorts.stderr b/tests/ui/typeck/terr-sorts.stderr index 8f1975374a576..59d9392c236ec 100644 --- a/tests/ui/typeck/terr-sorts.stderr +++ b/tests/ui/typeck/terr-sorts.stderr @@ -18,6 +18,6 @@ help: consider unboxing the value LL | want_foo(*b); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/typeck-cast-pointer-to-float.stderr b/tests/ui/typeck/typeck-cast-pointer-to-float.stderr index 81d968454be7b..670ff73e28b20 100644 --- a/tests/ui/typeck/typeck-cast-pointer-to-float.stderr +++ b/tests/ui/typeck/typeck-cast-pointer-to-float.stderr @@ -4,6 +4,6 @@ error[E0606]: casting `*const i16` as `f32` is invalid LL | ((&x) as *const i16) as f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/tests/ui/typeck/typeck-default-trait-impl-assoc-type.stderr index 468a14762c0d7..cedb1b13b1e51 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-assoc-type.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-assoc-type.stderr @@ -15,6 +15,6 @@ help: consider further restricting the associated type LL | fn bar() where ::AssocType: Send { | +++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-send.stderr b/tests/ui/typeck/typeck-default-trait-impl-negation-send.stderr index 2ce32990e55db..771272ad10b24 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-negation-send.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-send.stderr @@ -11,6 +11,6 @@ note: required by a bound in `is_send` LL | fn is_send() {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr index 887a1ddbb6924..537ae6b2b5f66 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | fn foo() { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr index c4e4aed20673e..e4b1c02c20149 100644 --- a/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr @@ -12,6 +12,6 @@ note: struct defined here, with 1 generic parameter: `T` LL | struct Foo<'a, T:'a> { | ^^^ - -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr index 302231777bdfc..fcb5ecc4042b0 100644 --- a/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr @@ -12,6 +12,6 @@ note: struct defined here, with 1 generic parameter: `T` LL | struct Foo<'a, T:'a> { | ^^^ - -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/while-loop-block-cond.stderr b/tests/ui/typeck/while-loop-block-cond.stderr index 598273af9cfc4..7f67650fd4ce2 100644 --- a/tests/ui/typeck/while-loop-block-cond.stderr +++ b/tests/ui/typeck/while-loop-block-cond.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | while {} {} | ^^ expected `bool`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/while-type-error.stderr b/tests/ui/typeck/while-type-error.stderr index 529cbff0563bd..b67ec561531fe 100644 --- a/tests/ui/typeck/while-type-error.stderr +++ b/tests/ui/typeck/while-type-error.stderr @@ -7,6 +7,6 @@ LL | fn main() { while main { } } = note: expected type `bool` found fn item `fn() {main}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/wrong-ret-type.stderr b/tests/ui/typeck/wrong-ret-type.stderr index c686a0b2f5aea..33a094ce95d30 100644 --- a/tests/ui/typeck/wrong-ret-type.stderr +++ b/tests/ui/typeck/wrong-ret-type.stderr @@ -11,6 +11,6 @@ help: you can convert an `isize` to a `usize` and panic if the converted value d LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); } | ++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeof/issue-100183.stderr b/tests/ui/typeof/issue-100183.stderr index 01d3079b246d1..7be923d938357 100644 --- a/tests/ui/typeof/issue-100183.stderr +++ b/tests/ui/typeof/issue-100183.stderr @@ -9,6 +9,6 @@ help: consider replacing `typeof(...)` with an actual type LL | y: (&'static str,), | ~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0516`. diff --git a/tests/ui/typeof/issue-29184.stderr b/tests/ui/typeof/issue-29184.stderr index 75b6c64f2ced3..f07c850e55669 100644 --- a/tests/ui/typeof/issue-29184.stderr +++ b/tests/ui/typeof/issue-29184.stderr @@ -9,6 +9,6 @@ help: consider replacing `typeof(...)` with an actual type LL | let x: i32 = 92; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0516`. diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr index 147a20974732d..0815ae1fb5a2b 100644 --- a/tests/ui/unboxed-closures/issue-30906.stderr +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -7,5 +7,5 @@ LL | test(Compose(f, |_| {})); = note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr index cfbe1c6f2cbbc..66d393c67c543 100644 --- a/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr +++ b/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr @@ -7,6 +7,6 @@ LL | fn a>(f: F) {} note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0059`. diff --git a/tests/ui/unboxed-closures/non-tupled-call.stderr b/tests/ui/unboxed-closures/non-tupled-call.stderr index 35ac9ebe29103..207438bc9d8bc 100644 --- a/tests/ui/unboxed-closures/non-tupled-call.stderr +++ b/tests/ui/unboxed-closures/non-tupled-call.stderr @@ -4,6 +4,6 @@ error[E0059]: cannot use call notation; the first type parameter for the functio LL | func(x); | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0059`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-feature-gate.stderr b/tests/ui/unboxed-closures/unboxed-closure-feature-gate.stderr index b824d160d7160..d06fa3007dfb4 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-feature-gate.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-feature-gate.stderr @@ -7,6 +7,6 @@ LL | let x: Box; = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr index 9d3c1902cf30b..563167f3c0b06 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr @@ -14,6 +14,6 @@ note: required by a bound in `g` LL | fn g(_: F) where F: FnOnce(Option) {} | ^^^^^^^^^^^^^^^^^ required by this bound in `g` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0644`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-region.stderr b/tests/ui/unboxed-closures/unboxed-closure-region.stderr index 43e9af24a7c2b..70407628f1df9 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-region.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-region.stderr @@ -16,6 +16,6 @@ help: to force the closure to take ownership of `x` (and any other referenced va LL | move || x | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-default.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-default.stderr index a3b32d2c1c8ce..b5cef0b3a27bb 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-default.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-default.stderr @@ -10,6 +10,6 @@ note: required by a bound in `eq` LL | fn eq() where A : Eq { } | ^^^^^ required by this bound in `eq` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr index bccbf307ae157..923f1a345136f 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr @@ -10,6 +10,6 @@ note: required by a bound in `eq` LL | fn eq>() { } | ^^^^^ required by this bound in `eq` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr index 2b8fec86c8a18..b7e9e1baa7bb4 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -19,6 +19,6 @@ LL | LL ~ let _: dyn Foo(&'a isize, &'a usize) -> &'a usize; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr index 8814617814c90..0465c20dffa27 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr @@ -10,6 +10,6 @@ note: trait defined here, with 1 lifetime parameter: `'a` LL | trait Foo<'a,T> { | ^^^ -- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr index 4df404e8198fa..ce2c90f97da6a 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr @@ -9,6 +9,6 @@ help: use angle brackets instead LL | let b = Bar::::new(); // OK too (for the parser) | ~ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr index e4772478bd910..b8fb0702a08e3 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr @@ -4,6 +4,6 @@ error[E0220]: associated type `Output` not found for `One` LL | fn foo(_: &dyn One()) | ^^^^^ associated type `Output` not found -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr b/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr index 98fe97c5c1814..4adf24162a071 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr @@ -10,6 +10,6 @@ LL | let _y = x; LL | f; | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr index ff2a597bed065..5a76ef3e87587 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr @@ -12,6 +12,6 @@ help: consider giving `closure0` an explicit type, where the placeholders `_` ar LL | let mut closure0: Option = None; | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr index ce4d0fe25f51d..795bd0a0d180f 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr @@ -14,6 +14,6 @@ note: required by a bound in `call_it` LL | fn call_itisize>(f: &F, x: isize) -> isize { | ^^^^^^^^^^^^^^^^ required by this bound in `call_it` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr index e97157b83980c..40d3414024553 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr @@ -8,5 +8,5 @@ LL | doit(0, &|x, y| { LL | x.set(y); | ^^^^^^^^ argument requires that `'1` must outlive `'2` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr index 846a44ce4d7a9..cc81ce9bc3609 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr @@ -18,6 +18,6 @@ LL | fn foo(f: F) LL | where F: Fn() | ^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr index 3f539c42d9b31..b18f67a998389 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr @@ -11,6 +11,6 @@ help: consider changing this to be mutable LL | let mut tick = || counter += 1; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr index e3b19297b9c18..1c465f409474c 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr @@ -11,6 +11,6 @@ help: consider changing this to be mutable LL | let mut tick = move || counter += 1; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr index ab6f06518467c..7013529a85720 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr @@ -17,6 +17,6 @@ note: this value implements `FnOnce`, which causes it to be moved when called LL | tick(); | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr index 8d70a2b17602b..2884dbfd29dab 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr @@ -17,6 +17,6 @@ note: this value implements `FnOnce`, which causes it to be moved when called LL | tick(); | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr index 7d15cd0c882a5..cbe42861d5ee2 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr @@ -11,6 +11,6 @@ LL | call(|| { LL | counter += 1; | ^^^^^^^^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr b/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr index 830f6bc993dfe..178cabd424dd5 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr @@ -7,6 +7,6 @@ LL | (self.func)(self, arg) | first mutable borrow occurs here | first borrow later used by call -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr index e2d867ff266a4..4d5e6f4796500 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `call` found for closure `{closure@$DIR/unboxed-cl LL | mut_.call((0, )); | ^^^^ method not found in `{closure@unboxed-closures-static-call-wrong-trait.rs:6:26}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-unique-type-id.rs b/tests/ui/unboxed-closures/unboxed-closures-unique-type-id.rs index 4b7016def9d60..94bb44d2cf50c 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-unique-type-id.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-unique-type-id.rs @@ -10,7 +10,6 @@ // This is a regression test for issue #17021. // // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet use std::ptr; diff --git a/tests/ui/unconstrained-none.stderr b/tests/ui/unconstrained-none.stderr index 19ac74fdf5831..4af6f412e5b22 100644 --- a/tests/ui/unconstrained-none.stderr +++ b/tests/ui/unconstrained-none.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | None::; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/unconstrained-ref.stderr b/tests/ui/unconstrained-ref.stderr index 1df6d8b446d5c..72fd0202f4e53 100644 --- a/tests/ui/unconstrained-ref.stderr +++ b/tests/ui/unconstrained-ref.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | S:: { o: &None }; | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/underscore-ident-matcher.stderr b/tests/ui/underscore-ident-matcher.stderr index b0e4d88f67186..a663f34cde1b1 100644 --- a/tests/ui/underscore-ident-matcher.stderr +++ b/tests/ui/underscore-ident-matcher.stderr @@ -13,5 +13,5 @@ note: while trying to match meta-variable `$i:ident` LL | ($i: ident) => ( | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/underscore-imports/shadow.stderr b/tests/ui/underscore-imports/shadow.stderr index f2c19405bbb8b..da26316389289 100644 --- a/tests/ui/underscore-imports/shadow.stderr +++ b/tests/ui/underscore-imports/shadow.stderr @@ -10,6 +10,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use std::ops::Deref; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr index fd08600280393..e2bd9192d57da 100644 --- a/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr +++ b/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr @@ -10,6 +10,6 @@ LL ~ struct Foo<'a> { LL ~ x: Box, | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/underscore-lifetime/dyn-trait-underscore.stderr b/tests/ui/underscore-lifetime/dyn-trait-underscore.stderr index 60b0b3ee7ba2a..c3bda45e929a9 100644 --- a/tests/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/tests/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -12,5 +12,5 @@ help: to declare that the trait object captures data from argument `items`, you LL | fn a(items: &[T]) -> Box + '_> { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/underscore-lifetime/in-fn-return-illegal.stderr b/tests/ui/underscore-lifetime/in-fn-return-illegal.stderr index 6a104e8f94b32..fb036c695b41c 100644 --- a/tests/ui/underscore-lifetime/in-fn-return-illegal.stderr +++ b/tests/ui/underscore-lifetime/in-fn-return-illegal.stderr @@ -10,6 +10,6 @@ help: consider introducing a named lifetime parameter LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } } | ++++ ++ ++ ~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr index 2b34f0c555a20..ed9d22d255839 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr +++ b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr @@ -12,5 +12,5 @@ help: consider introducing a named lifetime parameter LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } | ++++ ~~ ~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/underscore-lifetime/underscore-outlives-bounds.stderr b/tests/ui/underscore-lifetime/underscore-outlives-bounds.stderr index 4b38a26f957f9..4d23abf83dae2 100644 --- a/tests/ui/underscore-lifetime/underscore-outlives-bounds.stderr +++ b/tests/ui/underscore-lifetime/underscore-outlives-bounds.stderr @@ -4,6 +4,6 @@ error[E0637]: `'_` cannot be used here LL | impl<'b: '_> Foo<'b> for i32 {} | ^^ `'_` is a reserved lifetime name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr index 3e197dc9a9d12..54e62f34fbaa3 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr @@ -9,6 +9,6 @@ help: consider introducing a higher-ranked lifetime here LL | T: for<'a> WithType<&'a u32> | +++++++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr index 08b4268e5d237..36f3e9ef14527 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr @@ -9,6 +9,6 @@ help: consider introducing a higher-ranked lifetime here LL | T: for<'a> WithType<&'a u32> | +++++++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr index 95939fd6b7e03..d65c6042e16f2 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr @@ -4,6 +4,6 @@ error[E0637]: `'_` cannot be used here LL | T: WithRegion<'_> | ^^ `'_` is a reserved lifetime name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr index 95939fd6b7e03..d65c6042e16f2 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr @@ -4,6 +4,6 @@ error[E0637]: `'_` cannot be used here LL | T: WithRegion<'_> | ^^ `'_` is a reserved lifetime name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr index 8c5bbb631b4c7..92b7a9c2af893 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr @@ -9,6 +9,6 @@ help: consider introducing a higher-ranked lifetime here LL | T: for<'a> WithType<&'a u32> | +++++++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr index 0268c59fa4af8..63d8b99ed18fb 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr @@ -9,6 +9,6 @@ help: consider introducing a higher-ranked lifetime here LL | T: for<'a> WithType<&'a u32> | +++++++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr index 92caff0dcde99..dae9523975d1a 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr @@ -4,6 +4,6 @@ error[E0637]: `'_` cannot be used here LL | T: WithRegion<'_> | ^^ `'_` is a reserved lifetime name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr index 92caff0dcde99..dae9523975d1a 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr @@ -4,6 +4,6 @@ error[E0637]: `'_` cannot be used here LL | T: WithRegion<'_> | ^^ `'_` is a reserved lifetime name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/unevaluated_fixed_size_array_len.stderr b/tests/ui/unevaluated_fixed_size_array_len.stderr index b04a7b7f2f1d4..43cc377006e0e 100644 --- a/tests/ui/unevaluated_fixed_size_array_len.stderr +++ b/tests/ui/unevaluated_fixed_size_array_len.stderr @@ -6,6 +6,6 @@ LL | <[(); 0] as Foo>::foo() | = help: the trait `Foo` is implemented for `[(); 1]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr b/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr index 0dfd22a30acc7..5f2f02c99fb79 100644 --- a/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr +++ b/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr @@ -12,6 +12,6 @@ help: consider assigning a value LL | let y: &mut u32 = todo!(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.stderr index daf75f51b5a11..304e738ed2561 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/tests/ui/uninhabited/uninhabited-irrefutable.stderr @@ -21,6 +21,6 @@ help: you might want to use `let else` to handle the variant that isn't matched LL | let Foo::D(_y, _z) = x else { todo!() }; | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/union/issue-41073.stderr b/tests/ui/union/issue-41073.stderr index ae1c4dfed9a23..c9b6903b1bfba 100644 --- a/tests/ui/union/issue-41073.stderr +++ b/tests/ui/union/issue-41073.stderr @@ -10,6 +10,6 @@ help: wrap the field type in `ManuallyDrop<...>` LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0740`. diff --git a/tests/ui/union/projection-as-union-type-error-2.stderr b/tests/ui/union/projection-as-union-type-error-2.stderr index 21f4ea103ada3..3b073ca1fb4e0 100644 --- a/tests/ui/union/projection-as-union-type-error-2.stderr +++ b/tests/ui/union/projection-as-union-type-error-2.stderr @@ -17,6 +17,6 @@ LL | impl Identity for T { | | | unsatisfied trait bound introduced here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/projection-as-union-type-error.stderr b/tests/ui/union/projection-as-union-type-error.stderr index 2b0241caf98ca..f43fb2fe9e518 100644 --- a/tests/ui/union/projection-as-union-type-error.stderr +++ b/tests/ui/union/projection-as-union-type-error.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | pub trait Identity { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-const-pat.stderr b/tests/ui/union/union-const-pat.stderr index dc87f4de5219f..e9dbb275944ae 100644 --- a/tests/ui/union/union-const-pat.stderr +++ b/tests/ui/union/union-const-pat.stderr @@ -4,5 +4,5 @@ error: cannot use unions in constant patterns LL | C => {} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/union/union-copy.stderr b/tests/ui/union/union-copy.stderr index ff6fa48db90fd..bd63908b49a2c 100644 --- a/tests/ui/union/union-copy.stderr +++ b/tests/ui/union/union-copy.stderr @@ -13,6 +13,6 @@ note: the `Copy` impl for `ManuallyDrop` requires that `String: Copy` LL | a: std::mem::ManuallyDrop | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/union/union-derive-eq.mirunsafeck.stderr b/tests/ui/union/union-derive-eq.mirunsafeck.stderr index 136cd883e26ce..86e7c955d2eea 100644 --- a/tests/ui/union/union-derive-eq.mirunsafeck.stderr +++ b/tests/ui/union/union-derive-eq.mirunsafeck.stderr @@ -16,6 +16,6 @@ LL + #[derive(Eq)] LL | struct PartialEqNotEq; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-derive-eq.thirunsafeck.stderr b/tests/ui/union/union-derive-eq.thirunsafeck.stderr index 136cd883e26ce..86e7c955d2eea 100644 --- a/tests/ui/union/union-derive-eq.thirunsafeck.stderr +++ b/tests/ui/union/union-derive-eq.thirunsafeck.stderr @@ -16,6 +16,6 @@ LL + #[derive(Eq)] LL | struct PartialEqNotEq; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-empty.stderr b/tests/ui/union/union-empty.stderr index a80b27e6eb563..03a939769c78b 100644 --- a/tests/ui/union/union-empty.stderr +++ b/tests/ui/union/union-empty.stderr @@ -4,5 +4,5 @@ error: unions cannot have zero fields LL | union U {} | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/union/union-lint-dead-code.mirunsafeck.stderr b/tests/ui/union/union-lint-dead-code.mirunsafeck.stderr index 6e21584c37c06..8a3677d525d66 100644 --- a/tests/ui/union/union-lint-dead-code.mirunsafeck.stderr +++ b/tests/ui/union/union-lint-dead-code.mirunsafeck.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/union/union-lint-dead-code.thirunsafeck.stderr b/tests/ui/union/union-lint-dead-code.thirunsafeck.stderr index 6e21584c37c06..8a3677d525d66 100644 --- a/tests/ui/union/union-lint-dead-code.thirunsafeck.stderr +++ b/tests/ui/union/union-lint-dead-code.thirunsafeck.stderr @@ -13,5 +13,5 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/union/union-nonrepresentable.stderr b/tests/ui/union/union-nonrepresentable.stderr index c266d2e9e138b..90d38727f2279 100644 --- a/tests/ui/union/union-nonrepresentable.stderr +++ b/tests/ui/union/union-nonrepresentable.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | b: std::mem::ManuallyDrop>, | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/union/union-repr-c.stderr b/tests/ui/union/union-repr-c.stderr index 49124eee5ee5a..0beb7c376f3ad 100644 --- a/tests/ui/union/union-repr-c.stderr +++ b/tests/ui/union/union-repr-c.stderr @@ -17,5 +17,5 @@ note: the lint level is defined here LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/union/union-suggest-field.mirunsafeck.stderr b/tests/ui/union/union-suggest-field.mirunsafeck.stderr index 58b1f5cb0786a..efe4987bd0252 100644 --- a/tests/ui/union/union-suggest-field.mirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.mirunsafeck.stderr @@ -2,13 +2,23 @@ error[E0560]: union `U` has no field named `principle` --> $DIR/union-suggest-field.rs:13:17 | LL | let u = U { principle: 0 }; - | ^^^^^^^^^ help: a field with a similar name exists: `principal` + | ^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let u = U { principal: 0 }; + | ~~~~~~~~~ error[E0609]: no field `principial` on type `U` --> $DIR/union-suggest-field.rs:17:15 | LL | let w = u.principial; - | ^^^^^^^^^^ help: a field with a similar name exists: `principal` + | ^^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let w = u.principal; + | ~~~~~~~~~ error[E0615]: attempted to take value of method `calculate` on type `U` --> $DIR/union-suggest-field.rs:21:15 diff --git a/tests/ui/union/union-suggest-field.thirunsafeck.stderr b/tests/ui/union/union-suggest-field.thirunsafeck.stderr index 58b1f5cb0786a..efe4987bd0252 100644 --- a/tests/ui/union/union-suggest-field.thirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.thirunsafeck.stderr @@ -2,13 +2,23 @@ error[E0560]: union `U` has no field named `principle` --> $DIR/union-suggest-field.rs:13:17 | LL | let u = U { principle: 0 }; - | ^^^^^^^^^ help: a field with a similar name exists: `principal` + | ^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let u = U { principal: 0 }; + | ~~~~~~~~~ error[E0609]: no field `principial` on type `U` --> $DIR/union-suggest-field.rs:17:15 | LL | let w = u.principial; - | ^^^^^^^^^^ help: a field with a similar name exists: `principal` + | ^^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let w = u.principal; + | ~~~~~~~~~ error[E0615]: attempted to take value of method `calculate` on type `U` --> $DIR/union-suggest-field.rs:21:15 diff --git a/tests/ui/union/union-unsafe.mir.stderr b/tests/ui/union/union-unsafe.mir.stderr index 544213dbc5543..15f059ffa4875 100644 --- a/tests/ui/union/union-unsafe.mir.stderr +++ b/tests/ui/union/union-unsafe.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:33:5 + --> $DIR/union-unsafe.rs:34:5 | LL | *(u.p) = 13; | ^^^^^^^^^^^ access to union field @@ -7,7 +7,7 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:46:6 + --> $DIR/union-unsafe.rs:47:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -15,7 +15,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:52:6 + --> $DIR/union-unsafe.rs:53:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -23,7 +23,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:60:13 + --> $DIR/union-unsafe.rs:61:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -31,7 +31,7 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:63:14 + --> $DIR/union-unsafe.rs:64:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -39,7 +39,7 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:64:12 + --> $DIR/union-unsafe.rs:65:12 | LL | if let U1 { a: 12 } = u1 {} | ^^^^^^^^^^^^ access to union field @@ -47,7 +47,15 @@ LL | if let U1 { a: 12 } = u1 {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:69:6 + --> $DIR/union-unsafe.rs:66:12 + | +LL | if let Some(U1 { a: 13 }) = Some(u1) {} + | ^^^^^^^^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:71:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -55,7 +63,7 @@ LL | *u2.a = String::from("new"); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:73:6 + --> $DIR/union-unsafe.rs:75:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -63,13 +71,13 @@ LL | *u3.a = 1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:77:6 + --> $DIR/union-unsafe.rs:79:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/union/union-unsafe.rs b/tests/ui/union/union-unsafe.rs index 5e1837a901d46..d1465486f7784 100644 --- a/tests/ui/union/union-unsafe.rs +++ b/tests/ui/union/union-unsafe.rs @@ -1,30 +1,31 @@ // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck -use std::mem::ManuallyDrop; use std::cell::RefCell; +use std::mem::ManuallyDrop; union U1 { - a: u8 + a: u8, } union U2 { - a: ManuallyDrop + a: ManuallyDrop, } union U3 { - a: ManuallyDrop + a: ManuallyDrop, } union U4 { - a: T + a: T, } union URef { p: &'static mut i32, } -union URefCell { // field that does not drop but is not `Copy`, either +union URefCell { + // field that does not drop but is not `Copy`, either a: (ManuallyDrop>, i32), } @@ -62,6 +63,7 @@ fn main() { let U1 { a } = u1; //~ ERROR access to union field is unsafe if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe + if let Some(U1 { a: 13 }) = Some(u1) {} //~ ERROR access to union field is unsafe // let U1 { .. } = u1; // OK let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK diff --git a/tests/ui/union/union-unsafe.thir.stderr b/tests/ui/union/union-unsafe.thir.stderr index f959fe5bdb5c5..9ce835497c519 100644 --- a/tests/ui/union/union-unsafe.thir.stderr +++ b/tests/ui/union/union-unsafe.thir.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:33:6 + --> $DIR/union-unsafe.rs:34:6 | LL | *(u.p) = 13; | ^^^^^ access to union field @@ -7,7 +7,7 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:46:6 + --> $DIR/union-unsafe.rs:47:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -15,7 +15,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:52:6 + --> $DIR/union-unsafe.rs:53:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -23,7 +23,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:60:13 + --> $DIR/union-unsafe.rs:61:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -31,7 +31,7 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:63:14 + --> $DIR/union-unsafe.rs:64:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -39,15 +39,23 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:64:8 + --> $DIR/union-unsafe.rs:65:20 | LL | if let U1 { a: 12 } = u1 {} - | ^^^^^^^^^^^^^^^^^^^^^ access to union field + | ^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:69:6 + --> $DIR/union-unsafe.rs:66:25 + | +LL | if let Some(U1 { a: 13 }) = Some(u1) {} + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:71:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -55,7 +63,7 @@ LL | *u2.a = String::from("new"); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:73:6 + --> $DIR/union-unsafe.rs:75:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -63,13 +71,13 @@ LL | *u3.a = 1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:77:6 + --> $DIR/union-unsafe.rs:79:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/union/unresolved-field-isnt-copy.stderr b/tests/ui/union/unresolved-field-isnt-copy.stderr index 22301582eefc7..ee5d1e37b141c 100644 --- a/tests/ui/union/unresolved-field-isnt-copy.stderr +++ b/tests/ui/union/unresolved-field-isnt-copy.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Missing` in this scope LL | x: *const Missing, | ^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/unknown-language-item.stderr b/tests/ui/unknown-language-item.stderr index c5fe9b8ad0e8b..1e0256867c562 100644 --- a/tests/ui/unknown-language-item.stderr +++ b/tests/ui/unknown-language-item.stderr @@ -4,6 +4,6 @@ error[E0522]: definition of an unknown language item: `foo` LL | #[lang = "foo"] | ^^^^^^^^^^^^^^^ definition of unknown language item `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0522`. diff --git a/tests/ui/unknown-tool-name.stderr b/tests/ui/unknown-tool-name.stderr index 4a1370ba80a50..361d359a10e47 100644 --- a/tests/ui/unknown-tool-name.stderr +++ b/tests/ui/unknown-tool-name.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` LL | #[foo::bar] | ^^^ use of undeclared crate or module `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/unop-neg-bool.stderr b/tests/ui/unop-neg-bool.stderr index 9913747b88ee9..9bc5e7dcf2268 100644 --- a/tests/ui/unop-neg-bool.stderr +++ b/tests/ui/unop-neg-bool.stderr @@ -4,6 +4,6 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | -true; | ^^^^^ cannot apply unary operator `-` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/unpretty/avoid-crash.stderr b/tests/ui/unpretty/avoid-crash.stderr index 15bcc277e6491..6fa3e8ca630a4 100644 --- a/tests/ui/unpretty/avoid-crash.stderr +++ b/tests/ui/unpretty/avoid-crash.stderr @@ -1,4 +1,4 @@ error: failed to write `/tmp/` due to $ERROR_MESSAGE -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/unpretty/bad-literal.stderr b/tests/ui/unpretty/bad-literal.stderr index f3fcb4a4e921d..b6259484f67d5 100644 --- a/tests/ui/unpretty/bad-literal.stderr +++ b/tests/ui/unpretty/bad-literal.stderr @@ -6,5 +6,5 @@ LL | 1u; | = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/unpretty/mir-unpretty.stderr b/tests/ui/unpretty/mir-unpretty.stderr index 3808f8583b836..a9e40884bfb11 100644 --- a/tests/ui/unpretty/mir-unpretty.stderr +++ b/tests/ui/unpretty/mir-unpretty.stderr @@ -6,6 +6,6 @@ LL | let x: () = 0; | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unresolved/unresolved-asterisk-imports.stderr b/tests/ui/unresolved/unresolved-asterisk-imports.stderr index 8df8eab34a715..24ac2f8e6213a 100644 --- a/tests/ui/unresolved/unresolved-asterisk-imports.stderr +++ b/tests/ui/unresolved/unresolved-asterisk-imports.stderr @@ -6,6 +6,6 @@ LL | use not_existing_crate::*; | = help: consider adding `extern crate not_existing_crate` to use the `not_existing_crate` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/unresolved/unresolved-extern-mod-suggestion.stderr b/tests/ui/unresolved/unresolved-extern-mod-suggestion.stderr index 28333228a29ba..b493d0fa3fe28 100644 --- a/tests/ui/unresolved/unresolved-extern-mod-suggestion.stderr +++ b/tests/ui/unresolved/unresolved-extern-mod-suggestion.stderr @@ -8,6 +8,6 @@ LL | use core; | = note: `core` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/unresolved/unresolved-import-recovery.stderr b/tests/ui/unresolved/unresolved-import-recovery.stderr index 5e371b70bfa50..1c006049756e9 100644 --- a/tests/ui/unresolved/unresolved-import-recovery.stderr +++ b/tests/ui/unresolved/unresolved-import-recovery.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `unresolved` LL | pub use unresolved; | ^^^^^^^^^^ no `unresolved` in the root -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/unresolved/unresolved-import-suggest-disambiguated-crate-name.stderr b/tests/ui/unresolved/unresolved-import-suggest-disambiguated-crate-name.stderr index f139c0f3cf1e8..c6812dbb19639 100644 --- a/tests/ui/unresolved/unresolved-import-suggest-disambiguated-crate-name.stderr +++ b/tests/ui/unresolved/unresolved-import-suggest-disambiguated-crate-name.stderr @@ -9,6 +9,6 @@ help: consider importing this struct instead LL | pub use ::library::SomeUsefulType; | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr similarity index 80% rename from tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr rename to tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr index fbc621f4d0e37..ea53bf59d3101 100644 --- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr @@ -1,12 +1,12 @@ warning: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:5 + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13:5 | LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:11:1 + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1 | LL | unsafe fn foo() { | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs index a192f3445f73e..1b429955cb035 100644 --- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs @@ -1,17 +1,21 @@ // edition: 2024 // compile-flags: -Zunstable-options // check-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![crate_type = "lib"] - #![deny(unused_unsafe)] unsafe fn unsf() {} unsafe fn foo() { unsf(); - //~^ WARN call to unsafe function is unsafe and requires unsafe block + //[mir]~^ WARN call to unsafe function is unsafe and requires unsafe block + //[thir]~^^ WARN call to unsafe function `unsf` is unsafe and requires unsafe block // no unused_unsafe - unsafe { unsf(); } + unsafe { + unsf(); + } } diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr new file mode 100644 index 0000000000000..d63843ed2b361 --- /dev/null +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr @@ -0,0 +1,16 @@ +warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1 + | +LL | unsafe fn foo() { + | ^^^^^^^^^^^^^^^ + = note: `#[warn(unsafe_op_in_unsafe_fn)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/unsafe/foreign-unsafe-fn-called.mir.stderr b/tests/ui/unsafe/foreign-unsafe-fn-called.mir.stderr index d3cf5d84fdd98..5157dbb514bad 100644 --- a/tests/ui/unsafe/foreign-unsafe-fn-called.mir.stderr +++ b/tests/ui/unsafe/foreign-unsafe-fn-called.mir.stderr @@ -6,6 +6,6 @@ LL | test::free(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/foreign-unsafe-fn-called.thir.stderr b/tests/ui/unsafe/foreign-unsafe-fn-called.thir.stderr index 00ba0f7a6a3e0..8c221314cd7cf 100644 --- a/tests/ui/unsafe/foreign-unsafe-fn-called.thir.stderr +++ b/tests/ui/unsafe/foreign-unsafe-fn-called.thir.stderr @@ -6,6 +6,6 @@ LL | test::free(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/initializing-ranged-via-ctor.stderr b/tests/ui/unsafe/initializing-ranged-via-ctor.stderr index 13438fd31d0a9..56b112867cf04 100644 --- a/tests/ui/unsafe/initializing-ranged-via-ctor.stderr +++ b/tests/ui/unsafe/initializing-ranged-via-ctor.stderr @@ -11,6 +11,6 @@ LL | println!("{:?}", Some(1).map(NonZeroAndOneU8).unwrap()); note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsafe/inline_asm.mir.stderr b/tests/ui/unsafe/inline_asm.mir.stderr index 633f1edb26cef..e38a9388a786e 100644 --- a/tests/ui/unsafe/inline_asm.mir.stderr +++ b/tests/ui/unsafe/inline_asm.mir.stderr @@ -6,6 +6,6 @@ LL | asm!("nop"); | = note: inline assembly is entirely unchecked and can cause undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/inline_asm.thir.stderr b/tests/ui/unsafe/inline_asm.thir.stderr index 633f1edb26cef..e38a9388a786e 100644 --- a/tests/ui/unsafe/inline_asm.thir.stderr +++ b/tests/ui/unsafe/inline_asm.thir.stderr @@ -6,6 +6,6 @@ LL | asm!("nop"); | = note: inline assembly is entirely unchecked and can cause undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-115348-false-positive-warning-of-unnecessary-unsafe.stderr b/tests/ui/unsafe/issue-115348-false-positive-warning-of-unnecessary-unsafe.stderr index 7384899b978ff..9dd68d2a63441 100644 --- a/tests/ui/unsafe/issue-115348-false-positive-warning-of-unnecessary-unsafe.stderr +++ b/tests/ui/unsafe/issue-115348-false-positive-warning-of-unnecessary-unsafe.stderr @@ -16,6 +16,6 @@ LL ~ Some(_) => unsafe { uwu() }, LL ~ None => todo!(), | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/unsafe/issue-3080.mir.stderr b/tests/ui/unsafe/issue-3080.mir.stderr index f395c30b8155a..a1ad98d205eb0 100644 --- a/tests/ui/unsafe/issue-3080.mir.stderr +++ b/tests/ui/unsafe/issue-3080.mir.stderr @@ -6,6 +6,6 @@ LL | X(()).with(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-3080.thir.stderr b/tests/ui/unsafe/issue-3080.thir.stderr index 4d8acac61d9ed..1018218b1b061 100644 --- a/tests/ui/unsafe/issue-3080.thir.stderr +++ b/tests/ui/unsafe/issue-3080.thir.stderr @@ -6,6 +6,6 @@ LL | X(()).with(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr b/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr index 660c4070451a8..23bfe3c9c2eed 100644 --- a/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr +++ b/tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr @@ -10,6 +10,6 @@ LL | let x: fn(u8) -> NonZeroAndOneU8 = NonZeroAndOneU8; found struct constructor `unsafe fn(_) -> NonZeroAndOneU8 {NonZeroAndOneU8}` = note: unsafe functions cannot be coerced into safe function pointers -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unsafe/ranged_ints.mir.stderr b/tests/ui/unsafe/ranged_ints.mir.stderr index f9ef7834e1e50..ef00edae05d9f 100644 --- a/tests/ui/unsafe/ranged_ints.mir.stderr +++ b/tests/ui/unsafe/ranged_ints.mir.stderr @@ -6,6 +6,6 @@ LL | let _x = NonZero(0); | = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints.thir.stderr b/tests/ui/unsafe/ranged_ints.thir.stderr index f9ef7834e1e50..ef00edae05d9f 100644 --- a/tests/ui/unsafe/ranged_ints.thir.stderr +++ b/tests/ui/unsafe/ranged_ints.thir.stderr @@ -6,6 +6,6 @@ LL | let _x = NonZero(0); | = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr index 427843f8d45ce..dc6bd72f56c57 100644 --- a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr @@ -6,6 +6,14 @@ LL | let y = &mut x.0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:12:25 + | +LL | if let Some(NonZero(ref mut y)) = Some(x) {} + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2.rs b/tests/ui/unsafe/ranged_ints2.rs index 9a6bb18f92664..ad9d598aba2a4 100644 --- a/tests/ui/unsafe/ranged_ints2.rs +++ b/tests/ui/unsafe/ranged_ints2.rs @@ -9,4 +9,5 @@ pub(crate) struct NonZero(pub(crate) T); fn main() { let mut x = unsafe { NonZero(1) }; let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe + if let Some(NonZero(ref mut y)) = Some(x) {} //~ ERROR mutation of layout constrained field is unsafe } diff --git a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr index 427843f8d45ce..dc6bd72f56c57 100644 --- a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr @@ -6,6 +6,14 @@ LL | let y = &mut x.0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:12:25 + | +LL | if let Some(NonZero(ref mut y)) = Some(x) {} + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr index 9eec0b09e9b18..72bce5de0aed9 100644 --- a/tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr @@ -6,6 +6,6 @@ LL | let y = &x.0; | = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr index 9eec0b09e9b18..72bce5de0aed9 100644 --- a/tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr @@ -6,6 +6,6 @@ LL | let y = &x.0; | = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr index 493483d2c4540..4f2f1e42e7653 100644 --- a/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr @@ -6,6 +6,6 @@ LL | x.0 = 0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr index 493483d2c4540..4f2f1e42e7653 100644 --- a/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr @@ -6,6 +6,6 @@ LL | x.0 = 0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr index a06c6f479b8da..a2a3ae668a2c4 100644 --- a/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr @@ -6,6 +6,6 @@ LL | x.0 = 0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr index a06c6f479b8da..a2a3ae668a2c4 100644 --- a/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr @@ -6,6 +6,6 @@ LL | x.0 = 0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints_const.mir.stderr b/tests/ui/unsafe/ranged_ints_const.mir.stderr index 33d134c7ce59e..563b9be267210 100644 --- a/tests/ui/unsafe/ranged_ints_const.mir.stderr +++ b/tests/ui/unsafe/ranged_ints_const.mir.stderr @@ -6,6 +6,6 @@ LL | const fn foo() -> NonZero { NonZero(0) } | = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints_const.thir.stderr b/tests/ui/unsafe/ranged_ints_const.thir.stderr index 33d134c7ce59e..563b9be267210 100644 --- a/tests/ui/unsafe/ranged_ints_const.thir.stderr +++ b/tests/ui/unsafe/ranged_ints_const.thir.stderr @@ -6,6 +6,6 @@ LL | const fn foo() -> NonZero { NonZero(0) } | = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr index 4cdd97e5e06aa..ad0621a1d0435 100644 --- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr @@ -5,6 +5,11 @@ LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:1 + | +LL | unsafe fn deny_level() { + | ^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9 | @@ -46,6 +51,11 @@ LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:27:1 + | +LL | unsafe fn warning_level() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8 | diff --git a/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr b/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr index 9abc51424abaf..f8b55e0668d47 100644 --- a/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr +++ b/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr @@ -6,6 +6,6 @@ LL | foo.0.0 = 0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr b/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr index 9abc51424abaf..f8b55e0668d47 100644 --- a/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr +++ b/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr @@ -6,6 +6,6 @@ LL | foo.0.0 = 0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-block-without-braces.stderr b/tests/ui/unsafe/unsafe-block-without-braces.stderr index 44f77b99c561c..d29e49d73a661 100644 --- a/tests/ui/unsafe/unsafe-block-without-braces.stderr +++ b/tests/ui/unsafe/unsafe-block-without-braces.stderr @@ -11,5 +11,5 @@ help: try placing this code inside a block LL | { std::mem::transmute::(1.0); } | + + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/unsafe/unsafe-const-fn.mir.stderr b/tests/ui/unsafe/unsafe-const-fn.mir.stderr index 3031be720f02e..2450f08664c98 100644 --- a/tests/ui/unsafe/unsafe-const-fn.mir.stderr +++ b/tests/ui/unsafe/unsafe-const-fn.mir.stderr @@ -6,6 +6,6 @@ LL | const VAL: u32 = dummy(0xFFFF); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-const-fn.thir.stderr b/tests/ui/unsafe/unsafe-const-fn.thir.stderr index 1a77adf4459d0..199dca9237e15 100644 --- a/tests/ui/unsafe/unsafe-const-fn.thir.stderr +++ b/tests/ui/unsafe/unsafe-const-fn.thir.stderr @@ -6,6 +6,6 @@ LL | const VAL: u32 = dummy(0xFFFF); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr index fee645e4118de..da3d5f3bd291d 100644 --- a/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr +++ b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr @@ -6,6 +6,6 @@ LL | *p = 0; | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr index bbe4a415b5e55..aa5644782a41c 100644 --- a/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr +++ b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr @@ -6,6 +6,6 @@ LL | *p = 0; | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-autoderef.stderr b/tests/ui/unsafe/unsafe-fn-autoderef.stderr index 20a88c356108d..c3ab802022267 100644 --- a/tests/ui/unsafe/unsafe-fn-autoderef.stderr +++ b/tests/ui/unsafe/unsafe-fn-autoderef.stderr @@ -3,9 +3,10 @@ error[E0609]: no field `f` on type `*const Rec` | LL | return p.f; | --^ - | | + | | | + | | unknown field | help: `p` is a raw pointer; try dereferencing it: `(*p).f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr b/tests/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr index 1d6fa4cbf407d..d334743707550 100644 --- a/tests/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr +++ b/tests/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr @@ -6,6 +6,6 @@ LL | f(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr b/tests/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr index 206dbd90a7521..75431666186ea 100644 --- a/tests/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr +++ b/tests/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr @@ -6,6 +6,6 @@ LL | f(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr b/tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr index b08a7109dda57..01e8e49ecfafd 100644 --- a/tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr +++ b/tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr @@ -6,6 +6,6 @@ LL | x(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-used-as-value.thir.stderr b/tests/ui/unsafe/unsafe-fn-used-as-value.thir.stderr index e81dd3b2b4186..c38da7226f615 100644 --- a/tests/ui/unsafe/unsafe-fn-used-as-value.thir.stderr +++ b/tests/ui/unsafe/unsafe-fn-used-as-value.thir.stderr @@ -6,6 +6,6 @@ LL | x(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-subtyping.stderr b/tests/ui/unsafe/unsafe-subtyping.stderr index 2db7cc31280a3..1cc949cf757b5 100644 --- a/tests/ui/unsafe/unsafe-subtyping.stderr +++ b/tests/ui/unsafe/unsafe-subtyping.stderr @@ -9,6 +9,6 @@ LL | x = note: expected enum `Option` found enum `Option` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unsafe/unsafe-trait-impl.stderr b/tests/ui/unsafe/unsafe-trait-impl.stderr index 18ba79404b77e..db5200e1c2030 100644 --- a/tests/ui/unsafe/unsafe-trait-impl.stderr +++ b/tests/ui/unsafe/unsafe-trait-impl.stderr @@ -12,6 +12,6 @@ LL | unsafe fn len(&self) -> u32; = note: expected signature `unsafe fn(&u32) -> _` found signature `fn(&u32) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/unsafe/unsafe-unstable-const-fn.mir.stderr b/tests/ui/unsafe/unsafe-unstable-const-fn.mir.stderr index dcb84a80cb034..79133ab39a0c0 100644 --- a/tests/ui/unsafe/unsafe-unstable-const-fn.mir.stderr +++ b/tests/ui/unsafe/unsafe-unstable-const-fn.mir.stderr @@ -6,6 +6,6 @@ LL | *a == b | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-unstable-const-fn.thir.stderr b/tests/ui/unsafe/unsafe-unstable-const-fn.thir.stderr index dcb84a80cb034..79133ab39a0c0 100644 --- a/tests/ui/unsafe/unsafe-unstable-const-fn.thir.stderr +++ b/tests/ui/unsafe/unsafe-unstable-const-fn.thir.stderr @@ -6,6 +6,6 @@ LL | *a == b | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed similarity index 73% rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed index db1c102210e3b..b59029df6429b 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed @@ -1,7 +1,10 @@ // run-rustfix // aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] extern crate external_unsafe_macro; @@ -9,11 +12,13 @@ unsafe fn unsf() {} pub unsafe fn foo() { unsafe { //~^ NOTE an unsafe function restricts its caller, but its body is safe by default - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE }} @@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { unsafe { }} macro_rules! unsafe_macro { () => (unsf()) } -//~^ ERROR call to unsafe function is unsafe +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE -//~| ERROR call to unsafe function is unsafe +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr similarity index 86% rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr index 43f619c27d274..7a1b83c7367da 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr @@ -1,23 +1,23 @@ error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:12:5 + --> $DIR/wrapping-unsafe-block-sugg.rs:15:5 | LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:10:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:13:1 | LL | pub unsafe fn foo() { | ^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/wrapping-unsafe-block-sugg.rs:4:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:6:9 | LL | #![deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:15:5 + --> $DIR/wrapping-unsafe-block-sugg.rs:19:5 | LL | unsf(); | ^^^^^^ call to unsafe function @@ -25,20 +25,20 @@ LL | unsf(); = note: consult the function's documentation for information on how to avoid undefined behavior error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:22:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:27:13 | LL | let y = *x; | ^^ dereference of raw pointer | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:20:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:25:1 | LL | pub unsafe fn bar(x: *const i32) -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:25:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:30:9 | LL | y + *x | ^^ dereference of raw pointer @@ -46,20 +46,20 @@ LL | y + *x = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error: use of mutable static is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:33:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:38:13 | LL | let y = BAZ; | ^^^ use of mutable static | = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:31:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:36:1 | LL | pub unsafe fn baz() -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of mutable static is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:36:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:41:9 | LL | y + BAZ | ^^^ use of mutable static @@ -67,7 +67,7 @@ LL | y + BAZ = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:41:36 + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 | LL | macro_rules! unsafe_macro { () => (unsf()) } | ^^^^^^ call to unsafe function @@ -77,14 +77,14 @@ LL | unsafe_macro!(); | = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:49:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:56:1 | LL | pub unsafe fn unsafe_in_macro() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:41:36 + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 | LL | macro_rules! unsafe_macro { () => (unsf()) } | ^^^^^^ call to unsafe function diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs index 9c6be45896e25..3629b8a1beb5f 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs @@ -1,7 +1,10 @@ // run-rustfix // aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] extern crate external_unsafe_macro; @@ -9,11 +12,13 @@ unsafe fn unsf() {} pub unsafe fn foo() { //~^ NOTE an unsafe function restricts its caller, but its body is safe by default - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE } @@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { } macro_rules! unsafe_macro { () => (unsf()) } -//~^ ERROR call to unsafe function is unsafe +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE -//~| ERROR call to unsafe function is unsafe +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed new file mode 100644 index 0000000000000..b59029df6429b --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed @@ -0,0 +1,73 @@ +// run-rustfix +// aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] + +extern crate external_unsafe_macro; + +unsafe fn unsf() {} + +pub unsafe fn foo() { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE + //~| NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE + //~| NOTE +}} + +pub unsafe fn bar(x: *const i32) -> i32 { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE + y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE +}} + +static mut BAZ: i32 = 0; +pub unsafe fn baz() -> i32 { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE + y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE +}} + +macro_rules! unsafe_macro { () => (unsf()) } +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe +//~| NOTE +//~| NOTE +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe +//~| NOTE +//~| NOTE + +pub unsafe fn unsafe_in_macro() { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + unsafe_macro!(); + //~^ NOTE + //~| NOTE + unsafe_macro!(); + //~^ NOTE + //~| NOTE +}} + +pub unsafe fn unsafe_in_external_macro() { + // FIXME: https://github.com/rust-lang/rust/issues/112504 + // FIXME: ~^ NOTE an unsafe function restricts its caller, but its body is safe by default + external_unsafe_macro::unsafe_macro!(); + external_unsafe_macro::unsafe_macro!(); +} + +fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr new file mode 100644 index 0000000000000..b1fb35f85a606 --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr @@ -0,0 +1,99 @@ +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:15:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:13:1 + | +LL | pub unsafe fn foo() { + | ^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/wrapping-unsafe-block-sugg.rs:6:9 + | +LL | #![deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:19:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:27:13 + | +LL | let y = *x; + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:25:1 + | +LL | pub unsafe fn bar(x: *const i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:30:9 + | +LL | y + *x + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:38:13 + | +LL | let y = BAZ; + | ^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:36:1 + | +LL | pub unsafe fn baz() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:41:9 + | +LL | y + BAZ + | ^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 + | +LL | macro_rules! unsafe_macro { () => (unsf()) } + | ^^^^^^ call to unsafe function +... +LL | unsafe_macro!(); + | --------------- in this macro invocation + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:56:1 + | +LL | pub unsafe fn unsafe_in_macro() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 + | +LL | macro_rules! unsafe_macro { () => (unsf()) } + | ^^^^^^ call to unsafe function +... +LL | unsafe_macro!(); + | --------------- in this macro invocation + | + = note: consult the function's documentation for information on how to avoid undefined behavior + = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety.stderr b/tests/ui/unsized-locals/by-value-trait-object-safety.stderr index 4f13ec7ac08ef..6a93464febb10 100644 --- a/tests/ui/unsized-locals/by-value-trait-object-safety.stderr +++ b/tests/ui/unsized-locals/by-value-trait-object-safety.stderr @@ -16,5 +16,5 @@ LL | Self: Sized; LL | x.foo(); | ^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr b/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr index b6002cf895f0e..ee8e4f3eee26b 100644 --- a/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr +++ b/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr @@ -17,6 +17,6 @@ LL | let _x: fn(_) -> Test = Test; = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-30276.stderr b/tests/ui/unsized-locals/issue-30276.stderr index 8cccbd792da5c..15f70b18b3245 100644 --- a/tests/ui/unsized-locals/issue-30276.stderr +++ b/tests/ui/unsized-locals/issue-30276.stderr @@ -8,6 +8,6 @@ LL | let _x: fn(_) -> Test = Test; = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr index 8bbe317ec74ec..b39eb2e70bbae 100644 --- a/tests/ui/unsized-locals/issue-50940-with-feature.stderr +++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr @@ -21,6 +21,6 @@ LL | struct A(X); | ^ = note: the return type of a function must have a statically known size -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-50940.stderr b/tests/ui/unsized-locals/issue-50940.stderr index 8f09b460e004b..160e14794d514 100644 --- a/tests/ui/unsized-locals/issue-50940.stderr +++ b/tests/ui/unsized-locals/issue-50940.stderr @@ -8,6 +8,6 @@ LL | A as fn(str) -> A; = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-67981.stderr b/tests/ui/unsized-locals/issue-67981.stderr index 13fdc037ac569..e1fa41de2a80a 100644 --- a/tests/ui/unsized-locals/issue-67981.stderr +++ b/tests/ui/unsized-locals/issue-67981.stderr @@ -7,6 +7,6 @@ LL | let f: fn([u8]) = |_| {}; = help: the trait `Sized` is not implemented for `[u8]` = note: all function arguments must have a statically known size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/rust-call.stderr b/tests/ui/unsized-locals/rust-call.stderr index fff7ef75b3322..9eb0f3dabcca1 100644 --- a/tests/ui/unsized-locals/rust-call.stderr +++ b/tests/ui/unsized-locals/rust-call.stderr @@ -8,6 +8,6 @@ LL | f(*slice); = note: required because it appears within the type `([u8],)` = note: argument required to be sized due to `extern "rust-call"` ABI -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/unsized-exprs2.stderr b/tests/ui/unsized-locals/unsized-exprs2.stderr index 88269f237afb7..47b6d72acc7f1 100644 --- a/tests/ui/unsized-locals/unsized-exprs2.stderr +++ b/tests/ui/unsized-locals/unsized-exprs2.stderr @@ -7,6 +7,6 @@ LL | udrop::<[u8]>(foo()[..]); | cannot move out of here | move occurs because value has type `[u8]`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/unsized-locals/unsized-exprs3.stderr b/tests/ui/unsized-locals/unsized-exprs3.stderr index 57d9978225a2d..9dfedfd8ada78 100644 --- a/tests/ui/unsized-locals/unsized-exprs3.stderr +++ b/tests/ui/unsized-locals/unsized-exprs3.stderr @@ -8,6 +8,6 @@ LL | udrop as fn([u8]); = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.stderr b/tests/ui/unsized/box-instead-of-dyn-fn.stderr index 6087f5c546526..f2828b384b254 100644 --- a/tests/ui/unsized/box-instead-of-dyn-fn.stderr +++ b/tests/ui/unsized/box-instead-of-dyn-fn.stderr @@ -16,6 +16,6 @@ LL | if a % 2 == 0 { LL ~ Box::new(move || println!("{a}")) | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/unsized/issue-30355.stderr b/tests/ui/unsized/issue-30355.stderr index 71bbdf5dec769..cfbcd0aea901d 100644 --- a/tests/ui/unsized/issue-30355.stderr +++ b/tests/ui/unsized/issue-30355.stderr @@ -8,6 +8,6 @@ LL | &X(*Y) = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/issue-71659.current.stderr b/tests/ui/unsized/issue-71659.current.stderr index 6b982a73952bd..df0b998fd883e 100644 --- a/tests/ui/unsized/issue-71659.current.stderr +++ b/tests/ui/unsized/issue-71659.current.stderr @@ -13,6 +13,6 @@ LL | where LL | Self: CastTo, | ^^^^^^^^^ required by this bound in `Cast::cast` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/issue-71659.next.stderr b/tests/ui/unsized/issue-71659.next.stderr index 6b982a73952bd..df0b998fd883e 100644 --- a/tests/ui/unsized/issue-71659.next.stderr +++ b/tests/ui/unsized/issue-71659.next.stderr @@ -13,6 +13,6 @@ LL | where LL | Self: CastTo, | ^^^^^^^^^ required by this bound in `Cast::cast` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/issue-75707.stderr b/tests/ui/unsized/issue-75707.stderr index aa7f9c78fa84e..f5f2f7192aab4 100644 --- a/tests/ui/unsized/issue-75707.stderr +++ b/tests/ui/unsized/issue-75707.stderr @@ -15,6 +15,6 @@ note: required by a bound in `f` LL | fn f() { | ^^^^^^^^^^ required by this bound in `f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/issue-91801.stderr b/tests/ui/unsized/issue-91801.stderr index da5c432240348..d1d652d1860f9 100644 --- a/tests/ui/unsized/issue-91801.stderr +++ b/tests/ui/unsized/issue-91801.stderr @@ -9,6 +9,6 @@ help: box the return type, and wrap all of the returned values in `Box::new` LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Box> { | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/unsized/issue-91803.stderr b/tests/ui/unsized/issue-91803.stderr index a43b8d0741f2c..632af02b4b6ce 100644 --- a/tests/ui/unsized/issue-91803.stderr +++ b/tests/ui/unsized/issue-91803.stderr @@ -13,6 +13,6 @@ help: box the return type, and wrap all of the returned values in `Box::new` LL | fn or<'a>(first: &'static dyn Foo<'a>) -> Box> { | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/unsized/param-mentioned-by-different-field.stderr b/tests/ui/unsized/param-mentioned-by-different-field.stderr index b1ad0cb5b88ea..0d8b59aa9227f 100644 --- a/tests/ui/unsized/param-mentioned-by-different-field.stderr +++ b/tests/ui/unsized/param-mentioned-by-different-field.stderr @@ -9,6 +9,6 @@ LL | let y: &Foo<[u8]> = &x; = note: expected reference `&Foo<[u8]>` found reference `&Foo<[u8; 1]>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unsized/return-unsized-from-trait-method.stderr b/tests/ui/unsized/return-unsized-from-trait-method.stderr index 671d409937cac..82446151a7e9f 100644 --- a/tests/ui/unsized/return-unsized-from-trait-method.stderr +++ b/tests/ui/unsized/return-unsized-from-trait-method.stderr @@ -4,6 +4,6 @@ error[E0161]: cannot move a value of type `[u8]` LL | let _ = f.foo(); | ^^^^^^^ the size of `[u8]` cannot be statically determined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0161`. diff --git a/tests/ui/unsized/unsized-bare-typaram.stderr b/tests/ui/unsized/unsized-bare-typaram.stderr index daef984404a79..aa3f8fae72a17 100644 --- a/tests/ui/unsized/unsized-bare-typaram.stderr +++ b/tests/ui/unsized/unsized-bare-typaram.stderr @@ -17,6 +17,6 @@ LL - fn foo() { bar::() } LL + fn foo() { bar::() } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-enum.stderr b/tests/ui/unsized/unsized-enum.stderr index 9e6408e814367..8c56a83a5122e 100644 --- a/tests/ui/unsized/unsized-enum.stderr +++ b/tests/ui/unsized/unsized-enum.stderr @@ -24,6 +24,6 @@ LL - fn foo2() { not_sized::>() } LL + fn foo2() { not_sized::>() } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-fn-arg.stderr b/tests/ui/unsized/unsized-fn-arg.stderr index 0f6fadde19a05..c8a6622b80929 100644 --- a/tests/ui/unsized/unsized-fn-arg.stderr +++ b/tests/ui/unsized/unsized-fn-arg.stderr @@ -17,6 +17,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn f(t: &T) {} | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr index 9e5ad92eb04cd..3e16a20d726dc 100644 --- a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -24,6 +24,6 @@ LL - impl S5 { LL + impl S5 { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unused-crate-deps/deny-attr.stderr b/tests/ui/unused-crate-deps/deny-attr.stderr index 93694f6827f9c..89e87c9d5ac28 100644 --- a/tests/ui/unused-crate-deps/deny-attr.stderr +++ b/tests/ui/unused-crate-deps/deny-attr.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unused_crate_dependencies)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/unused-crate-deps/deny-cmdline-json-silent.stderr b/tests/ui/unused-crate-deps/deny-cmdline-json-silent.stderr index 595619f3a8a4e..f6594fdaa911e 100644 --- a/tests/ui/unused-crate-deps/deny-cmdline-json-silent.stderr +++ b/tests/ui/unused-crate-deps/deny-cmdline-json-silent.stderr @@ -1 +1 @@ -{"lint_level":"deny","unused_extern_names":["bar"]} +{"$message_type":"unused_extern","lint_level":"deny","unused_extern_names":["bar"]} diff --git a/tests/ui/unused-crate-deps/deny-cmdline-json.stderr b/tests/ui/unused-crate-deps/deny-cmdline-json.stderr index 595619f3a8a4e..f6594fdaa911e 100644 --- a/tests/ui/unused-crate-deps/deny-cmdline-json.stderr +++ b/tests/ui/unused-crate-deps/deny-cmdline-json.stderr @@ -1 +1 @@ -{"lint_level":"deny","unused_extern_names":["bar"]} +{"$message_type":"unused_extern","lint_level":"deny","unused_extern_names":["bar"]} diff --git a/tests/ui/unused-crate-deps/deny-cmdline.stderr b/tests/ui/unused-crate-deps/deny-cmdline.stderr index 0951dc670fe9e..fc526878ef052 100644 --- a/tests/ui/unused-crate-deps/deny-cmdline.stderr +++ b/tests/ui/unused-crate-deps/deny-cmdline.stderr @@ -6,5 +6,5 @@ LL | fn main() {} | = note: requested on the command line with `-D unused-crate-dependencies` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/unused-crate-deps/warn-cmdline-json.stderr b/tests/ui/unused-crate-deps/warn-cmdline-json.stderr index 98dbd763927e6..ef99f986eb1d7 100644 --- a/tests/ui/unused-crate-deps/warn-cmdline-json.stderr +++ b/tests/ui/unused-crate-deps/warn-cmdline-json.stderr @@ -1 +1 @@ -{"lint_level":"warn","unused_extern_names":["bar"]} +{"$message_type":"unused_extern","lint_level":"warn","unused_extern_names":["bar"]} diff --git a/tests/ui/use/issue-18986.stderr b/tests/ui/use/issue-18986.stderr index 6c23178c70011..350cb18f95272 100644 --- a/tests/ui/use/issue-18986.stderr +++ b/tests/ui/use/issue-18986.stderr @@ -4,6 +4,6 @@ error[E0574]: expected struct, variant or union type, found trait `Trait` LL | Trait { x: 42 } => () | ^^^^^ not a struct, variant or union type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/use/use-after-move-based-on-type.stderr b/tests/ui/use/use-after-move-based-on-type.stderr index 7b4d2454994d7..02a6ed599a920 100644 --- a/tests/ui/use/use-after-move-based-on-type.stderr +++ b/tests/ui/use/use-after-move-based-on-type.stderr @@ -14,6 +14,6 @@ help: consider cloning the value if the performance cost is acceptable LL | let _y = x.clone(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/use/use-after-move-implicity-coerced-object.stderr b/tests/ui/use/use-after-move-implicity-coerced-object.stderr index 84487a8d0dcdf..35ede21717ef8 100644 --- a/tests/ui/use/use-after-move-implicity-coerced-object.stderr +++ b/tests/ui/use/use-after-move-implicity-coerced-object.stderr @@ -18,6 +18,6 @@ LL | fn push(&mut self, n: Box) { | | | in this method -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/use/use-after-move-self-based-on-type.stderr b/tests/ui/use/use-after-move-self-based-on-type.stderr index 1bdf49801f975..17827becccecc 100644 --- a/tests/ui/use/use-after-move-self-based-on-type.stderr +++ b/tests/ui/use/use-after-move-self-based-on-type.stderr @@ -14,6 +14,6 @@ note: `S::bar` takes ownership of the receiver `self`, which moves `self` LL | pub fn bar(self) {} | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/use/use-after-move-self.stderr b/tests/ui/use/use-after-move-self.stderr index 59cc22eadb015..ebd6cef58b431 100644 --- a/tests/ui/use/use-after-move-self.stderr +++ b/tests/ui/use/use-after-move-self.stderr @@ -14,6 +14,6 @@ note: `S::bar` takes ownership of the receiver `self`, which moves `self` LL | pub fn bar(self) {} | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/use/use-associated-const.stderr b/tests/ui/use/use-associated-const.stderr index 4bc0d7e61cb2c..f0de7a7466c34 100644 --- a/tests/ui/use/use-associated-const.stderr +++ b/tests/ui/use/use-associated-const.stderr @@ -4,6 +4,6 @@ error[E0432]: unresolved import `foo::Foo` LL | use foo::Foo::BAR; | ^^^ `Foo` is a struct, not a module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/use/use-crate-self.stderr b/tests/ui/use/use-crate-self.stderr index dd4036bfff475..a8f65b128fe16 100644 --- a/tests/ui/use/use-crate-self.stderr +++ b/tests/ui/use/use-crate-self.stderr @@ -4,5 +4,5 @@ error: crate root imports need to be explicitly named: `use crate as name;` LL | use crate::{self}; | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/use/use-meta-mismatch.stderr b/tests/ui/use/use-meta-mismatch.stderr index 62b71fe8e12f4..b793229e5fddc 100644 --- a/tests/ui/use/use-meta-mismatch.stderr +++ b/tests/ui/use/use-meta-mismatch.stderr @@ -4,6 +4,6 @@ error[E0463]: can't find crate for `fake_crate` LL | extern crate fake_crate as extra; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/use/use-mod/use-mod-5.stderr b/tests/ui/use/use-mod/use-mod-5.stderr index 62859e261a36a..22201361c584f 100644 --- a/tests/ui/use/use-mod/use-mod-5.stderr +++ b/tests/ui/use/use-mod/use-mod-5.stderr @@ -14,6 +14,6 @@ help: alternatively, use the multi-path `use` syntax to import `self` LL | use foo::bar::{self}; | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0429`. diff --git a/tests/ui/use/use-mod/use-mod-6.stderr b/tests/ui/use/use-mod/use-mod-6.stderr index 2d2c90067aa61..f9ab346f8c36e 100644 --- a/tests/ui/use/use-mod/use-mod-6.stderr +++ b/tests/ui/use/use-mod/use-mod-6.stderr @@ -14,6 +14,6 @@ help: alternatively, use the multi-path `use` syntax to import `self` LL | use foo::bar::{self as abc}; | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0429`. diff --git a/tests/ui/use/use-nested-groups-error.stderr b/tests/ui/use/use-nested-groups-error.stderr index 7234c8ec621cd..d73754c6baa2d 100644 --- a/tests/ui/use/use-nested-groups-error.stderr +++ b/tests/ui/use/use-nested-groups-error.stderr @@ -7,6 +7,6 @@ LL | use a::{b1::{C1, C2}, B2}; | no `C1` in `a::b1` | help: a similar name exists in the module: `C2` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/use/use-paths-as-items.stderr b/tests/ui/use/use-paths-as-items.stderr index b09001a9bcd45..c54f40dafbcb4 100644 --- a/tests/ui/use/use-paths-as-items.stderr +++ b/tests/ui/use/use-paths-as-items.stderr @@ -8,6 +8,6 @@ LL | use std::mem; | = note: `mem` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/usize-generic-argument-parent.stderr b/tests/ui/usize-generic-argument-parent.stderr index 131c476aa55c0..9c081a287ed75 100644 --- a/tests/ui/usize-generic-argument-parent.stderr +++ b/tests/ui/usize-generic-argument-parent.stderr @@ -12,6 +12,6 @@ LL - let x: usize; LL + let x: usize; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr index 4df2d8da3d680..e25f0879add0a 100644 --- a/tests/ui/variance/variance-associated-consts.stderr +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -4,5 +4,5 @@ error: [o] LL | struct Foo { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/variance/variance-associated-types2.stderr b/tests/ui/variance/variance-associated-types2.stderr index 35871c1236fae..158b09b0630ca 100644 --- a/tests/ui/variance/variance-associated-types2.stderr +++ b/tests/ui/variance/variance-associated-types2.stderr @@ -6,5 +6,5 @@ LL | fn take<'a>(_: &'a u32) { LL | let _: Box> = make(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/variance/variance-cell-is-invariant.stderr b/tests/ui/variance/variance-cell-is-invariant.stderr index ab5435d1656d2..18e2de9f5024a 100644 --- a/tests/ui/variance/variance-cell-is-invariant.stderr +++ b/tests/ui/variance/variance-cell-is-invariant.stderr @@ -14,5 +14,5 @@ LL | let _: Foo<'long> = c; = note: the struct `Foo<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/variance/variance-object-types.stderr b/tests/ui/variance/variance-object-types.stderr index 55a760425ee59..963f3454e1baf 100644 --- a/tests/ui/variance/variance-object-types.stderr +++ b/tests/ui/variance/variance-object-types.stderr @@ -4,5 +4,5 @@ error: [o] LL | struct Foo<'a> { | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/variance/variance-trait-matching.stderr b/tests/ui/variance/variance-trait-matching.stderr index 3308cc6d25016..9c72fe239dde9 100644 --- a/tests/ui/variance/variance-trait-matching.stderr +++ b/tests/ui/variance/variance-trait-matching.stderr @@ -7,6 +7,6 @@ LL | fn get<'a, G>(get: &G) -> i32 LL | pick(get, &22) | ^^^^^^^^^^^^^^ lifetime `'a` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/variance/variance-trait-object-bound.stderr b/tests/ui/variance/variance-trait-object-bound.stderr index bfcc8d4a1d11b..f0471a3461925 100644 --- a/tests/ui/variance/variance-trait-object-bound.stderr +++ b/tests/ui/variance/variance-trait-object-bound.stderr @@ -4,5 +4,5 @@ error: [+] LL | struct TOption<'a> { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/variance/variance-use-contravariant-struct-1.stderr b/tests/ui/variance/variance-use-contravariant-struct-1.stderr index 50de7c90f1354..5000787b8f99d 100644 --- a/tests/ui/variance/variance-use-contravariant-struct-1.stderr +++ b/tests/ui/variance/variance-use-contravariant-struct-1.stderr @@ -11,5 +11,5 @@ LL | v | = help: consider adding the following bound: `'min: 'max` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/variance/variance-use-covariant-struct-1.stderr b/tests/ui/variance/variance-use-covariant-struct-1.stderr index bab858c5acb37..bd8458cd85dbe 100644 --- a/tests/ui/variance/variance-use-covariant-struct-1.stderr +++ b/tests/ui/variance/variance-use-covariant-struct-1.stderr @@ -11,5 +11,5 @@ LL | v | = help: consider adding the following bound: `'min: 'max` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/variants/variant-size-differences.stderr b/tests/ui/variants/variant-size-differences.stderr index 241a757d44523..cbc3eabd1d1ac 100644 --- a/tests/ui/variants/variant-size-differences.stderr +++ b/tests/ui/variants/variant-size-differences.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(variant_size_differences)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/walk-struct-literal-with.stderr b/tests/ui/walk-struct-literal-with.stderr index 2b85fa9bed480..34b501f8ec881 100644 --- a/tests/ui/walk-struct-literal-with.stderr +++ b/tests/ui/walk-struct-literal-with.stderr @@ -15,6 +15,6 @@ LL | fn make_string_bar(mut self) -> Mine{ | ^^^^ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/wf/issue-103573.stderr b/tests/ui/wf/issue-103573.stderr index 5227badb77dde..3129f2a8c3415 100644 --- a/tests/ui/wf/issue-103573.stderr +++ b/tests/ui/wf/issue-103573.stderr @@ -9,6 +9,6 @@ help: consider further restricting the associated type LL | fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA) where <>::TypeC<'a> as TraitB>::TypeB: TraitA; | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/issue-87495.stderr b/tests/ui/wf/issue-87495.stderr index c924cd87997e1..3ccfd7f8d7929 100644 --- a/tests/ui/wf/issue-87495.stderr +++ b/tests/ui/wf/issue-87495.stderr @@ -13,6 +13,6 @@ LL | const CONST: (bool, dyn T); | ^^^^^ ...because it contains this associated `const` = help: consider moving `CONST` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/issue-95665.stderr b/tests/ui/wf/issue-95665.stderr index f80cd41a4c2d3..1b14045d558d0 100644 --- a/tests/ui/wf/issue-95665.stderr +++ b/tests/ui/wf/issue-95665.stderr @@ -15,6 +15,6 @@ note: required by a bound in `Struct` LL | pub struct Struct { | ^^^^^ required by this bound in `Struct` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/issue-96810.stderr b/tests/ui/wf/issue-96810.stderr index 1407e62b1e139..622d72f791e2e 100644 --- a/tests/ui/wf/issue-96810.stderr +++ b/tests/ui/wf/issue-96810.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `K` LL | struct Hoge { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-array-elem-sized.stderr b/tests/ui/wf/wf-array-elem-sized.stderr index 7f3c58d6bba27..6bca8d036d525 100644 --- a/tests/ui/wf/wf-array-elem-sized.stderr +++ b/tests/ui/wf/wf-array-elem-sized.stderr @@ -7,6 +7,6 @@ LL | foo: [[u8]], = help: the trait `Sized` is not implemented for `[u8]` = note: slice and array elements must have `Sized` type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-complex-assoc-type.stderr b/tests/ui/wf/wf-complex-assoc-type.stderr index 6a623bec815e4..161ee9d7059cf 100644 --- a/tests/ui/wf/wf-complex-assoc-type.stderr +++ b/tests/ui/wf/wf-complex-assoc-type.stderr @@ -15,6 +15,6 @@ note: required by a bound in `AssertMyTrait` LL | struct AssertMyTrait(T); | ^^^^^^^ required by this bound in `AssertMyTrait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-enum-bound.stderr b/tests/ui/wf/wf-enum-bound.stderr index d39fc0c6a459e..78b5c6ec20eb4 100644 --- a/tests/ui/wf/wf-enum-bound.stderr +++ b/tests/ui/wf/wf-enum-bound.stderr @@ -14,6 +14,6 @@ help: consider further restricting type parameter `U` LL | where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-enum-fields-struct-variant.stderr b/tests/ui/wf/wf-enum-fields-struct-variant.stderr index c12d62521f77b..2f2c1c2d2665c 100644 --- a/tests/ui/wf/wf-enum-fields-struct-variant.stderr +++ b/tests/ui/wf/wf-enum-fields-struct-variant.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `A` LL | enum AnotherEnum { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-enum-fields.stderr b/tests/ui/wf/wf-enum-fields.stderr index ac3301a965ac7..a5feaadfc7587 100644 --- a/tests/ui/wf/wf-enum-fields.stderr +++ b/tests/ui/wf/wf-enum-fields.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `A` LL | enum SomeEnum { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-impl-associated-type-region.stderr b/tests/ui/wf/wf-impl-associated-type-region.stderr index e6fb81247ad66..f17d33474f40a 100644 --- a/tests/ui/wf/wf-impl-associated-type-region.stderr +++ b/tests/ui/wf/wf-impl-associated-type-region.stderr @@ -11,6 +11,6 @@ help: consider adding an explicit lifetime bound LL | impl<'a, T: 'a> Foo<'a> for T { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/wf/wf-impl-associated-type-trait.stderr b/tests/ui/wf/wf-impl-associated-type-trait.stderr index bdf8bba5ee026..09e255bead025 100644 --- a/tests/ui/wf/wf-impl-associated-type-trait.stderr +++ b/tests/ui/wf/wf-impl-associated-type-trait.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | impl Foo for T { | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-impl-self-type.stderr b/tests/ui/wf/wf-impl-self-type.stderr index 1ca368729fe6f..86fe6df32bf21 100644 --- a/tests/ui/wf/wf-impl-self-type.stderr +++ b/tests/ui/wf/wf-impl-self-type.stderr @@ -8,6 +8,6 @@ LL | impl Foo for Option<[u8]> {} note: required by a bound in `Option` --> $SRC_DIR/core/src/option.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-arg.stderr b/tests/ui/wf/wf-in-fn-arg.stderr index 83a4a592ad315..8f22edd17a100 100644 --- a/tests/ui/wf/wf-in-fn-arg.stderr +++ b/tests/ui/wf/wf-in-fn-arg.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | fn bar(_: &MustBeCopy) | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-ret.stderr b/tests/ui/wf/wf-in-fn-ret.stderr index 7eeb974728322..85cf78c598790 100644 --- a/tests/ui/wf/wf-in-fn-ret.stderr +++ b/tests/ui/wf/wf-in-fn-ret.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | fn bar() -> MustBeCopy | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-type-arg.stderr b/tests/ui/wf/wf-in-fn-type-arg.stderr index be5e9d4182bed..17594c813daa7 100644 --- a/tests/ui/wf/wf-in-fn-type-arg.stderr +++ b/tests/ui/wf/wf-in-fn-type-arg.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | struct Bar { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-type-ret.stderr b/tests/ui/wf/wf-in-fn-type-ret.stderr index 8fcfcb0b21af3..fac535a112659 100644 --- a/tests/ui/wf/wf-in-fn-type-ret.stderr +++ b/tests/ui/wf/wf-in-fn-type-ret.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | struct Foo { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-where-clause.stderr b/tests/ui/wf/wf-in-fn-where-clause.stderr index 160a738409bf5..4c556d3d77de3 100644 --- a/tests/ui/wf/wf-in-fn-where-clause.stderr +++ b/tests/ui/wf/wf-in-fn-where-clause.stderr @@ -14,6 +14,6 @@ help: consider further restricting type parameter `U` LL | where T: MustBeCopy, U: std::marker::Copy | ++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr index b10856571a61c..0af4ab022e1eb 100644 --- a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr +++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr @@ -9,6 +9,6 @@ help: indicate the anonymous lifetime LL | impl Trait for Ref<'_> {} | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/wf/wf-in-obj-type-static.stderr b/tests/ui/wf/wf-in-obj-type-static.stderr index 4b9b189164c6d..9e837b10e284d 100644 --- a/tests/ui/wf/wf-in-obj-type-static.stderr +++ b/tests/ui/wf/wf-in-obj-type-static.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | struct Foo { | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/wf/wf-in-obj-type-trait.stderr b/tests/ui/wf/wf-in-obj-type-trait.stderr index f556b678e0e38..b96f56a12a54c 100644 --- a/tests/ui/wf/wf-in-obj-type-trait.stderr +++ b/tests/ui/wf/wf-in-obj-type-trait.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | struct Bar { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr index e723d1ba76bcc..4cfbec12b6e41 100644 --- a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr +++ b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `U` LL | impl Foo { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-inherent-impl-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-where-clause.stderr index 39e0d348ea5ed..bdc1ee3e0e21c 100644 --- a/tests/ui/wf/wf-inherent-impl-where-clause.stderr +++ b/tests/ui/wf/wf-inherent-impl-where-clause.stderr @@ -14,6 +14,6 @@ help: consider further restricting type parameter `U` LL | impl Foo where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-object-safe.stderr b/tests/ui/wf/wf-object-safe.stderr index 64969fbe3203e..cc5351346b35a 100644 --- a/tests/ui/wf/wf-object-safe.stderr +++ b/tests/ui/wf/wf-object-safe.stderr @@ -13,6 +13,6 @@ LL | fn foo(&self, _x: &Self); | ^^^^^ ...because method `foo` references the `Self` type in this parameter = help: consider moving `foo` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr index 52f46562c3716..8e3088c6f4a0f 100644 --- a/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr +++ b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | pub trait Allocator { type Buffer; } | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-struct-bound.stderr b/tests/ui/wf/wf-struct-bound.stderr index 6248e3e4e43b6..4ac7f4634e462 100644 --- a/tests/ui/wf/wf-struct-bound.stderr +++ b/tests/ui/wf/wf-struct-bound.stderr @@ -14,6 +14,6 @@ help: consider further restricting type parameter `U` LL | where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-struct-field.stderr b/tests/ui/wf/wf-struct-field.stderr index 78a8da8602a43..241ced3c2dbd8 100644 --- a/tests/ui/wf/wf-struct-field.stderr +++ b/tests/ui/wf/wf-struct-field.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `A` LL | struct SomeStruct { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-associated-type-bound.stderr b/tests/ui/wf/wf-trait-associated-type-bound.stderr index 8297700171fd7..4ea895a9b0396 100644 --- a/tests/ui/wf/wf-trait-associated-type-bound.stderr +++ b/tests/ui/wf/wf-trait-associated-type-bound.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | trait SomeTrait { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-associated-type-region.stderr b/tests/ui/wf/wf-trait-associated-type-region.stderr index ca7aeb55b250c..d6647b2cb96e0 100644 --- a/tests/ui/wf/wf-trait-associated-type-region.stderr +++ b/tests/ui/wf/wf-trait-associated-type-region.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | type Type2 = &'a Self::Type1 where >::Type1: 'a; | ++++++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/wf/wf-trait-associated-type-trait.stderr b/tests/ui/wf/wf-trait-associated-type-trait.stderr index a73c3a2aed608..1dc8e2d87a214 100644 --- a/tests/ui/wf/wf-trait-associated-type-trait.stderr +++ b/tests/ui/wf/wf-trait-associated-type-trait.stderr @@ -14,6 +14,6 @@ help: consider further restricting the associated type LL | trait SomeTrait where ::Type1: Copy { | ++++++++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-bound.stderr b/tests/ui/wf/wf-trait-bound.stderr index bace3e3ef0081..5845d05b38e67 100644 --- a/tests/ui/wf/wf-trait-bound.stderr +++ b/tests/ui/wf/wf-trait-bound.stderr @@ -14,6 +14,6 @@ help: consider further restricting type parameter `U` LL | where T: ExtraCopy, U: std::marker::Copy | ++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-arg.stderr b/tests/ui/wf/wf-trait-default-fn-arg.stderr index 8c3d0568fdf1d..a885f8988627f 100644 --- a/tests/ui/wf/wf-trait-default-fn-arg.stderr +++ b/tests/ui/wf/wf-trait-default-fn-arg.stderr @@ -14,6 +14,6 @@ help: consider further restricting `Self` LL | fn bar(&self, x: &Bar) where Self: Eq { | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-ret.stderr b/tests/ui/wf/wf-trait-default-fn-ret.stderr index 6422e862d287d..f749ac7b1b3e6 100644 --- a/tests/ui/wf/wf-trait-default-fn-ret.stderr +++ b/tests/ui/wf/wf-trait-default-fn-ret.stderr @@ -14,6 +14,6 @@ help: consider further restricting `Self` LL | fn bar(&self) -> Bar where Self: Eq { | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-where-clause.stderr b/tests/ui/wf/wf-trait-default-fn-where-clause.stderr index f260d5750c566..e44a96fa5894d 100644 --- a/tests/ui/wf/wf-trait-default-fn-where-clause.stderr +++ b/tests/ui/wf/wf-trait-default-fn-where-clause.stderr @@ -14,6 +14,6 @@ help: consider further restricting `Self` LL | fn bar(&self) where A: Bar, Self: Eq { | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-arg.stderr b/tests/ui/wf/wf-trait-fn-arg.stderr index 3bd1f48928d71..8b35f36fa68a8 100644 --- a/tests/ui/wf/wf-trait-fn-arg.stderr +++ b/tests/ui/wf/wf-trait-fn-arg.stderr @@ -14,6 +14,6 @@ help: consider further restricting `Self` LL | fn bar(&self, x: &Bar) where Self: Eq; | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-ret.stderr b/tests/ui/wf/wf-trait-fn-ret.stderr index 9bd3cc7711b84..3d70f04def2e0 100644 --- a/tests/ui/wf/wf-trait-fn-ret.stderr +++ b/tests/ui/wf/wf-trait-fn-ret.stderr @@ -14,6 +14,6 @@ help: consider further restricting `Self` LL | fn bar(&self) -> &Bar where Self: Eq; | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-where-clause.stderr b/tests/ui/wf/wf-trait-fn-where-clause.stderr index d064f7fc56e5c..0ad3b58e7c76a 100644 --- a/tests/ui/wf/wf-trait-fn-where-clause.stderr +++ b/tests/ui/wf/wf-trait-fn-where-clause.stderr @@ -14,6 +14,6 @@ help: consider further restricting `Self` LL | fn bar(&self) where Self: Sized, Bar: Copy, Self: Eq; | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-superbound.stderr b/tests/ui/wf/wf-trait-superbound.stderr index cd49243a4bf0b..3c05065e57f91 100644 --- a/tests/ui/wf/wf-trait-superbound.stderr +++ b/tests/ui/wf/wf-trait-superbound.stderr @@ -14,6 +14,6 @@ help: consider restricting type parameter `T` LL | trait SomeTrait: ExtraCopy { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr index 29b36f44a4d12..4c15497d5308e 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr @@ -18,6 +18,6 @@ LL | where LL | for<'b> fn(&'b ()): Foo, | ^^^ required by this bound in `called` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr index 54afeaa7edabc..3318c70f1bb38 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `for fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ()): Foo` is not satisfied +error[E0277]: the trait bound `for fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ()): Foo` is not satisfied --> $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` + | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` | help: this trait has no implementations, consider adding one --> $DIR/higher-ranked-fn-type.rs:6:1 @@ -18,6 +18,6 @@ LL | where LL | for<'b> fn(&'b ()): Foo, | ^^^ required by this bound in `called` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/ignore-err-clauses.stderr b/tests/ui/where-clauses/ignore-err-clauses.stderr index cfddc3e10b64a..4cf553da4c5fc 100644 --- a/tests/ui/where-clauses/ignore-err-clauses.stderr +++ b/tests/ui/where-clauses/ignore-err-clauses.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `UUU` in this scope LL | UUU: Copy, | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr index ea51f5084f875..7f92ac102f012 100644 --- a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr +++ b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr @@ -10,6 +10,6 @@ note: required by a bound in `Trait::autotrait_bound` LL | fn autotrait_bound(&self) where Self: AutoTrait {} | ^^^^^^^^^ required by this bound in `Trait::autotrait_bound` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr index 43fbc0a9061cf..2612cefef28c1 100644 --- a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -16,6 +16,6 @@ help: consider restricting type parameter `T` LL | impl Foo { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr index f2db8fcc4a3f5..090df26a39e10 100644 --- a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -16,6 +16,6 @@ help: consider restricting type parameter `T` LL | impl Foo for Bar { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clause-method-substituion.stderr b/tests/ui/where-clauses/where-clause-method-substituion.stderr index 2f3b615a13bdf..1a1d9c13ab899 100644 --- a/tests/ui/where-clauses/where-clause-method-substituion.stderr +++ b/tests/ui/where-clauses/where-clause-method-substituion.stderr @@ -15,6 +15,6 @@ note: required by a bound in `Bar::method` LL | fn method(&self) where A: Foo; | ^^^^^^ required by this bound in `Bar::method` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr index 6cf717295141b..840df342ef9a9 100644 --- a/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr @@ -15,6 +15,6 @@ LL + #[derive(Eq)] LL | struct Bar; // does not implement Eq | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clauses-unsatisfied.stderr b/tests/ui/where-clauses/where-clauses-unsatisfied.stderr index 4d239bf43079f..205b82d49bfeb 100644 --- a/tests/ui/where-clauses/where-clauses-unsatisfied.stderr +++ b/tests/ui/where-clauses/where-clauses-unsatisfied.stderr @@ -15,6 +15,6 @@ LL + #[derive(Eq)] LL | struct Struct; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-for-self-2.stderr b/tests/ui/where-clauses/where-for-self-2.stderr index f65db78fc8993..f479210772194 100644 --- a/tests/ui/where-clauses/where-for-self-2.stderr +++ b/tests/ui/where-clauses/where-for-self-2.stderr @@ -7,5 +7,5 @@ LL | foo(&X); = note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... = note: ...but `Bar` is actually implemented for the type `&'static u32` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/where-clauses/where-for-self.stderr b/tests/ui/where-clauses/where-for-self.stderr index d06afc1e42376..8936e45c19cbc 100644 --- a/tests/ui/where-clauses/where-for-self.stderr +++ b/tests/ui/where-clauses/where-for-self.stderr @@ -4,6 +4,6 @@ error[E0316]: nested quantification of lifetimes LL | where for<'a> &'a T: for<'b> Bar<'b> | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0316`. diff --git a/tests/ui/while/while-else-err.stderr b/tests/ui/while/while-else-err.stderr index 88f715d566609..b937956108f00 100644 --- a/tests/ui/while/while-else-err.stderr +++ b/tests/ui/while/while-else-err.stderr @@ -13,5 +13,5 @@ LL | | }; | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/while/while-else-let-else-err.stderr b/tests/ui/while/while-else-let-else-err.stderr index 431d37c007c6d..27d68ffdb24ed 100644 --- a/tests/ui/while/while-else-let-else-err.stderr +++ b/tests/ui/while/while-else-let-else-err.stderr @@ -13,5 +13,5 @@ LL | | }; | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/windows-subsystem-invalid.stderr b/tests/ui/windows-subsystem-invalid.stderr index 0cb843cf0f14e..703f35c969c38 100644 --- a/tests/ui/windows-subsystem-invalid.stderr +++ b/tests/ui/windows-subsystem-invalid.stderr @@ -1,4 +1,4 @@ error: invalid windows subsystem `wrong`, only `windows` and `console` are allowed -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/writing-to-immutable-vec.stderr b/tests/ui/writing-to-immutable-vec.stderr index 286267c3834ab..06e1684dffed5 100644 --- a/tests/ui/writing-to-immutable-vec.stderr +++ b/tests/ui/writing-to-immutable-vec.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut v: Vec = vec![1, 2, 3]; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs b/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs index 69ed498e7e1cd..4f8b3508398f2 100644 --- a/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs +++ b/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs @@ -18,6 +18,11 @@ pub struct TupleStruct(pub usize, pub &'static str); #[derive(Copy, Clone)] pub struct StructWithFields { + pub foo: isize, +} + +#[derive(Copy, Clone)] +pub struct StructWithPrivFields { foo: isize, } diff --git a/tests/ui/xcrate/xcrate-unit-struct.rs b/tests/ui/xcrate/xcrate-unit-struct.rs index c99cf77ce7a4a..bc14cd8d4c01c 100644 --- a/tests/ui/xcrate/xcrate-unit-struct.rs +++ b/tests/ui/xcrate/xcrate-unit-struct.rs @@ -8,5 +8,7 @@ extern crate xcrate_unit_struct; fn main() { let _ = xcrate_unit_struct::StructWithFields; //~^ ERROR expected value, found struct `xcrate_unit_struct::StructWithFields` + let _ = xcrate_unit_struct::StructWithPrivFields; + //~^ ERROR expected value, found struct `xcrate_unit_struct::StructWithPrivFields` let _ = xcrate_unit_struct::Struct; } diff --git a/tests/ui/xcrate/xcrate-unit-struct.stderr b/tests/ui/xcrate/xcrate-unit-struct.stderr index cee314568887c..7365170b69ea2 100644 --- a/tests/ui/xcrate/xcrate-unit-struct.stderr +++ b/tests/ui/xcrate/xcrate-unit-struct.stderr @@ -9,6 +9,17 @@ LL | let _ = xcrate_unit_struct::StructWithFields; LL | pub struct StructWithFields { | --------------------------- `xcrate_unit_struct::StructWithFields` defined here -error: aborting due to previous error +error[E0423]: expected value, found struct `xcrate_unit_struct::StructWithPrivFields` + --> $DIR/xcrate-unit-struct.rs:11:13 + | +LL | let _ = xcrate_unit_struct::StructWithPrivFields; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + ::: $DIR/auxiliary/xcrate_unit_struct.rs:25:1 + | +LL | pub struct StructWithPrivFields { + | ------------------------------- `xcrate_unit_struct::StructWithPrivFields` defined here + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0423`. diff --git a/triagebot.toml b/triagebot.toml index b419727bcfdd6..775d9714c6062 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -18,6 +18,7 @@ allow-unauthenticated = [ "relnotes", "requires-*", "regression-*", + "rla-*", "perf-*", "AsyncAwait-OnDeck", "needs-triage", @@ -415,7 +416,7 @@ Issue #{number} "{title}" has been added. """ [no-merges] -exclude_titles = ["Rollup of", "subtree update"] +exclude_titles = ["Rollup of", "subtree update", "Subtree update"] labels = ["has-merge-commits", "S-waiting-on-author"] [github-releases] @@ -430,7 +431,7 @@ changelog-branch = "master" cc = ["@bjorn3"] [mentions."compiler/rustc_codegen_gcc"] -cc = ["@antoyo"] +cc = ["@antoyo", "@GuillaumeGomez"] [mentions."compiler/rustc_const_eval/src/interpret"] message = "Some changes occurred to the CTFE / Miri engine" @@ -533,6 +534,12 @@ message = "The Miri subtree was changed" cc = ["@rust-lang/miri"] [mentions."src/tools/rust-analyzer"] +message = """ +rust-analyzer is developed in its own repository. If possible, consider making \ +this change to [rust-lang/rust-analyzer] instead. + +[rust-lang/rust-analyzer]: https://github.com/rust-lang/rust-analyzer +""" cc = ["@rust-lang/rust-analyzer"] [mentions."src/tools/rustfmt"] @@ -579,15 +586,27 @@ Otherwise, you can ignore this comment. message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x` so tidy will suggest installing the new version." [mentions."src/tools/tidy/src/deps.rs"] -message = "Third-party dependency whitelist may have been modified! You must ensure that any new dependencies have compatible licenses before merging." +message = "The list of allowed third-party dependencies may have been modified! You must ensure that any new dependencies have compatible licenses before merging." cc = ["@davidtwco", "@wesleywiser"] [mentions."src/bootstrap/src/core/config"] -message = "This PR modifies `src/bootstrap/src/core/config`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`." +message = """ +This PR modifies `src/bootstrap/src/core/config`. + +If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs` and `change-id` in `config.example.toml`. +""" [mentions."src/bootstrap/defaults"] -message = "This PR modifies `src/bootstrap/defaults`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`." +message = """ +This PR modifies `src/bootstrap/defaults`. + +If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs` and `change-id` in `config.example.toml`. +""" [mentions."config.example.toml"] -message = "This PR changes `config.example.toml`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`." +message = """ +This PR modifies `config.example.toml`. + +If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs` and `change-id` in `config.example.toml`. +""" [mentions."src/bootstrap/defaults/config.compiler.toml"] message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appropriate, please also update `config.codegen.toml` so the defaults are in sync." @@ -608,19 +627,18 @@ cc = ["@nnethercote"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "jackh726", "WaffleLapkin", "oli-obk"] +users_on_vacation = ["jyn514", "oli-obk", "wesleywiser"] [assign.adhoc_groups] compiler-team = [ "@cjgillot", + "@compiler-errors", "@petrochenkov", "@davidtwco", "@oli-obk", "@wesleywiser", ] compiler-team-contributors = [ - "@compiler-errors", - "@jackh726", "@TaKO8Ki", "@WaffleLapkin", "@b-naber", @@ -714,6 +732,13 @@ style-team = [ "@yaahc", ] +project-stable-mir = [ + "@celinval", + "@oli-obk", + "@spastorino", + "@ouz-a", +] + [assign.owners] "/.github/workflows" = ["infra-ci"] "/Cargo.lock" = ["@Mark-Simulacrum"] @@ -730,6 +755,7 @@ style-team = [ "/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"] "/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"] "/compiler/rustc_mir_build/src/build" = ["compiler", "mir"] +"/compiler/rustc_smir" = ["project-stable-mir"] "/compiler/rustc_parse" = ["compiler", "parser"] "/compiler/rustc_parse/src/lexer" = ["compiler", "lexer"] "/compiler/rustc_query_impl" = ["compiler", "query-system"] @@ -737,6 +763,7 @@ style-team = [ "/compiler/rustc_trait_selection" = ["compiler", "types"] "/compiler/rustc_traits" = ["compiler", "types"] "/compiler/rustc_type_ir" = ["compiler", "types"] +"/compiler/stable_mir" = ["project-stable-mir"] "/library/alloc" = ["libs"] "/library/core" = ["libs"] "/library/panic_abort" = ["libs"]

    {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #13231 for more information + = help: add `#![feature(auto_traits)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0567, E0658. +For more information about an error, try `rustc --explain E0567`. diff --git a/tests/ui/auto-traits/issue-23080-2.current.stderr b/tests/ui/auto-traits/issue-23080-2.current.stderr index a57c6d9b0cbf9..178bfff97d22c 100644 --- a/tests/ui/auto-traits/issue-23080-2.current.stderr +++ b/tests/ui/auto-traits/issue-23080-2.current.stderr @@ -6,6 +6,6 @@ LL | unsafe auto trait Trait { LL | type Output; | -----^^^^^^- help: remove these associated items -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0380`. diff --git a/tests/ui/auto-traits/issue-23080-2.next.stderr b/tests/ui/auto-traits/issue-23080-2.next.stderr index a57c6d9b0cbf9..178bfff97d22c 100644 --- a/tests/ui/auto-traits/issue-23080-2.next.stderr +++ b/tests/ui/auto-traits/issue-23080-2.next.stderr @@ -6,6 +6,6 @@ LL | unsafe auto trait Trait { LL | type Output; | -----^^^^^^- help: remove these associated items -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0380`. diff --git a/tests/ui/auto-traits/issue-23080.stderr b/tests/ui/auto-traits/issue-23080.stderr index f5d607298b797..5cea45060c824 100644 --- a/tests/ui/auto-traits/issue-23080.stderr +++ b/tests/ui/auto-traits/issue-23080.stderr @@ -9,6 +9,6 @@ LL | | println!("Hello"); LL | | } | |_____- help: remove these associated items -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0380`. diff --git a/tests/ui/auto-traits/issue-83857-ub.stderr b/tests/ui/auto-traits/issue-83857-ub.stderr index 23a2f62d9057f..80f9330eb8180 100644 --- a/tests/ui/auto-traits/issue-83857-ub.stderr +++ b/tests/ui/auto-traits/issue-83857-ub.stderr @@ -17,6 +17,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) where Foo: Send { | +++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/issue-84075.stderr b/tests/ui/auto-traits/issue-84075.stderr index 6fbdc669b6ffb..943d521ce9e27 100644 --- a/tests/ui/auto-traits/issue-84075.stderr +++ b/tests/ui/auto-traits/issue-84075.stderr @@ -6,6 +6,6 @@ LL | auto trait Magic where Self: Copy {} | | | auto traits cannot have super traits or lifetime bounds -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0568`. diff --git a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr index 1cf16cebddd15..e1dae35be006d 100644 --- a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr +++ b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr @@ -11,6 +11,6 @@ note: required by a bound in `needs_auto_trait` LL | fn needs_auto_trait() {} | ^^^^^^^^^ required by this bound in `needs_auto_trait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr index 80f0741038127..23aae13639c77 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr @@ -6,6 +6,6 @@ LL | auto trait Magic: Copy {} | | | auto traits cannot have super traits or lifetime bounds -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0568`. diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr index 0c4970a72591f..aa5585a5371f6 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr @@ -11,6 +11,6 @@ note: required by a bound in `is_mytrait` LL | fn is_mytrait() {} | ^^^^^^^ required by this bound in `is_mytrait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr index c575c485a85f7..668cbc8aeb43e 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr @@ -10,6 +10,6 @@ note: required by a bound in `is_mytrait` LL | fn is_mytrait() {} | ^^^^^^^ required by this bound in `is_mytrait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index bd7aaf6fb6dfc..2498af996eabd 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -22,6 +22,6 @@ LL - is_defaulted::<&'static u32>(); LL + is_defaulted::(); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr index 06a7e90858ce7..19c3c64181985 100644 --- a/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr +++ b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr @@ -12,6 +12,6 @@ help: consider giving `var_fn` an explicit type, where the placeholders `_` are LL | let var_fn: Value> = Value::wrap(); | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/binding/const-param.stderr b/tests/ui/binding/const-param.stderr index adda80810ead2..e68893a59e499 100644 --- a/tests/ui/binding/const-param.stderr +++ b/tests/ui/binding/const-param.stderr @@ -4,6 +4,6 @@ error[E0158]: const parameters cannot be referenced in patterns LL | N => {} | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0158`. diff --git a/tests/ui/binding/match-arm-statics.rs b/tests/ui/binding/match-arm-statics.rs index e6d17def1477e..5f7e357eeb2a9 100644 --- a/tests/ui/binding/match-arm-statics.rs +++ b/tests/ui/binding/match-arm-statics.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet #[derive(PartialEq, Eq)] struct NewBool(bool); diff --git a/tests/ui/binop/binary-op-on-double-ref.stderr b/tests/ui/binop/binary-op-on-double-ref.stderr index 2e8aeebc681d6..d1d1d770765e7 100644 --- a/tests/ui/binop/binary-op-on-double-ref.stderr +++ b/tests/ui/binop/binary-op-on-double-ref.stderr @@ -11,6 +11,6 @@ help: `%` can be used on `&{integer}` if you dereference the left-hand side LL | *x % 2 == 0 | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/binary-op-suggest-deref.fixed b/tests/ui/binop/binary-op-suggest-deref.fixed new file mode 100644 index 0000000000000..1ff3599137b16 --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.fixed @@ -0,0 +1,8 @@ +// Issue #52544 +// run-rustfix + +fn main() { + let i: &i64 = &1; + if *i < 0 {} + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/binop/binary-op-suggest-deref.rs b/tests/ui/binop/binary-op-suggest-deref.rs new file mode 100644 index 0000000000000..12505a9ac27e8 --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.rs @@ -0,0 +1,8 @@ +// Issue #52544 +// run-rustfix + +fn main() { + let i: &i64 = &1; + if i < 0 {} + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr new file mode 100644 index 0000000000000..d1d0089ece795 --- /dev/null +++ b/tests/ui/binop/binary-op-suggest-deref.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/binary-op-suggest-deref.rs:6:12 + | +LL | if i < 0 {} + | ^ expected `&i64`, found integer + | +help: consider dereferencing the borrow + | +LL | if *i < 0 {} + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/binop/binop-bitxor-str.stderr b/tests/ui/binop/binop-bitxor-str.stderr index f236cd61efe59..20b1ecc5a939e 100644 --- a/tests/ui/binop/binop-bitxor-str.stderr +++ b/tests/ui/binop/binop-bitxor-str.stderr @@ -6,6 +6,6 @@ LL | fn main() { let x = "a".to_string() ^ "b".to_string(); } | | | String -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/binop-mul-bool.stderr b/tests/ui/binop/binop-mul-bool.stderr index 8b5cde63c9991..82d066f45a4e2 100644 --- a/tests/ui/binop/binop-mul-bool.stderr +++ b/tests/ui/binop/binop-mul-bool.stderr @@ -6,6 +6,6 @@ LL | fn main() { let x = true * false; } | | | bool -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/binop-mul-i32-f32.stderr b/tests/ui/binop/binop-mul-i32-f32.stderr index 115e700061981..6ed3e7b44476a 100644 --- a/tests/ui/binop/binop-mul-i32-f32.stderr +++ b/tests/ui/binop/binop-mul-i32-f32.stderr @@ -11,6 +11,6 @@ LL | x * y <&'a i32 as Mul> <&i32 as Mul<&i32>> -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/binop/binop-typeck.stderr b/tests/ui/binop/binop-typeck.stderr index 42d910819995a..da7f318282648 100644 --- a/tests/ui/binop/binop-typeck.stderr +++ b/tests/ui/binop/binop-typeck.stderr @@ -6,6 +6,6 @@ LL | let z = x + y; | | | bool -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/eq-arr.stderr b/tests/ui/binop/eq-arr.stderr index a22f8e3ab0c79..afcfb7b288b8d 100644 --- a/tests/ui/binop/eq-arr.stderr +++ b/tests/ui/binop/eq-arr.stderr @@ -17,6 +17,6 @@ LL + #[derive(PartialEq)] LL | struct X; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/eq-vec.stderr b/tests/ui/binop/eq-vec.stderr index 0a98cddfe05a9..14739752877ce 100644 --- a/tests/ui/binop/eq-vec.stderr +++ b/tests/ui/binop/eq-vec.stderr @@ -19,6 +19,6 @@ LL + #[derive(PartialEq)] LL | enum Foo { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.fixed b/tests/ui/binop/false-binop-caused-by-missing-semi.fixed new file mode 100644 index 0000000000000..b47372c906486 --- /dev/null +++ b/tests/ui/binop/false-binop-caused-by-missing-semi.fixed @@ -0,0 +1,10 @@ +// run-rustfix +fn foo() {} +fn main() { + let mut y = 42; + let x = &mut y; + foo(); + *x = 0; //~ ERROR invalid left-hand side of assignment + let _ = x; + println!("{y}"); +} diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.rs b/tests/ui/binop/false-binop-caused-by-missing-semi.rs new file mode 100644 index 0000000000000..14671de7e5111 --- /dev/null +++ b/tests/ui/binop/false-binop-caused-by-missing-semi.rs @@ -0,0 +1,10 @@ +// run-rustfix +fn foo() {} +fn main() { + let mut y = 42; + let x = &mut y; + foo() + *x = 0; //~ ERROR invalid left-hand side of assignment + let _ = x; + println!("{y}"); +} diff --git a/tests/ui/binop/false-binop-caused-by-missing-semi.stderr b/tests/ui/binop/false-binop-caused-by-missing-semi.stderr new file mode 100644 index 0000000000000..eeb6b028a9a37 --- /dev/null +++ b/tests/ui/binop/false-binop-caused-by-missing-semi.stderr @@ -0,0 +1,17 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/false-binop-caused-by-missing-semi.rs:7:8 + | +LL | / foo() +LL | | *x = 0; + | | - ^ + | |______| + | cannot assign to this expression + | +help: you might have meant to write a semicolon here + | +LL | foo(); + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/binop/issue-3820.stderr b/tests/ui/binop/issue-3820.stderr index cfa78a41dbf08..7cce93dca090f 100644 --- a/tests/ui/binop/issue-3820.stderr +++ b/tests/ui/binop/issue-3820.stderr @@ -14,6 +14,6 @@ LL | struct Thing { note: the trait `Mul` must be implemented --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr index b3856b6ae1681..e58ae0fad9b4d 100644 --- a/tests/ui/binop/issue-77910-2.stderr +++ b/tests/ui/binop/issue-77910-2.stderr @@ -11,6 +11,6 @@ help: use parentheses to call this function LL | if foo(/* &i32 */) == y {} | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/issue-93927.stderr b/tests/ui/binop/issue-93927.stderr index 75558b502f9dc..9bcf2b17357eb 100644 --- a/tests/ui/binop/issue-93927.stderr +++ b/tests/ui/binop/issue-93927.stderr @@ -11,6 +11,6 @@ help: consider further restricting this bound LL | fn cond(val: MyType) -> bool { | ++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/placement-syntax.stderr b/tests/ui/binop/placement-syntax.stderr index 3fdaf4cd0f55d..b20a2ee63538b 100644 --- a/tests/ui/binop/placement-syntax.stderr +++ b/tests/ui/binop/placement-syntax.stderr @@ -9,5 +9,5 @@ help: if you meant to write a comparison against a negative value, add a space i LL | if x< -1 { | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/blind/blind-item-block-item-shadow.stderr b/tests/ui/blind/blind-item-block-item-shadow.stderr index 68b3f4c1ae2fc..2e24ef453c2e4 100644 --- a/tests/ui/blind/blind-item-block-item-shadow.stderr +++ b/tests/ui/blind/blind-item-block-item-shadow.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use foo::Bar as OtherBar; | ~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/blind/blind-item-block-middle.stderr b/tests/ui/blind/blind-item-block-middle.stderr index 63e6d76843d18..b2ae169013a62 100644 --- a/tests/ui/blind/blind-item-block-middle.stderr +++ b/tests/ui/blind/blind-item-block-middle.stderr @@ -11,6 +11,6 @@ LL | let bar = 5; | `bar` is interpreted as a unit struct, not a new binding | help: introduce a new binding instead: `other_bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/blind/blind-item-item-shadow.stderr b/tests/ui/blind/blind-item-item-shadow.stderr index 7f9e800892918..84b273c7338b1 100644 --- a/tests/ui/blind/blind-item-item-shadow.stderr +++ b/tests/ui/blind/blind-item-item-shadow.stderr @@ -13,6 +13,6 @@ help: you can use `as` to change the binding name of the import LL | use foo::foo as other_foo; | ~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/block-result/block-must-not-have-result-do.stderr b/tests/ui/block-result/block-must-not-have-result-do.stderr index 914886f81b4ae..2a94f0a87e181 100644 --- a/tests/ui/block-result/block-must-not-have-result-do.stderr +++ b/tests/ui/block-result/block-must-not-have-result-do.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | true | ^^^^ expected `()`, found `bool` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/block-must-not-have-result-res.stderr b/tests/ui/block-result/block-must-not-have-result-res.stderr index b7427462bcbd5..e075dc230d0da 100644 --- a/tests/ui/block-result/block-must-not-have-result-res.stderr +++ b/tests/ui/block-result/block-must-not-have-result-res.stderr @@ -6,6 +6,6 @@ LL | fn drop(&mut self) { LL | true | ^^^^ expected `()`, found `bool` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/block-must-not-have-result-while.stderr b/tests/ui/block-result/block-must-not-have-result-while.stderr index 7f96aa289d0ab..94a4b33da5dda 100644 --- a/tests/ui/block-result/block-must-not-have-result-while.stderr +++ b/tests/ui/block-result/block-must-not-have-result-while.stderr @@ -16,6 +16,6 @@ LL | | LL | | } | |_____- expected this to be `()` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/issue-11714.stderr b/tests/ui/block-result/issue-11714.stderr index 42fb3d3d43d4b..25651328e9dcc 100644 --- a/tests/ui/block-result/issue-11714.stderr +++ b/tests/ui/block-result/issue-11714.stderr @@ -9,6 +9,6 @@ LL | fn blah() -> i32 { LL | ; | - help: remove this semicolon to return this value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/issue-3563.stderr b/tests/ui/block-result/issue-3563.stderr index be551f6e889fc..c473a84413eb7 100644 --- a/tests/ui/block-result/issue-3563.stderr +++ b/tests/ui/block-result/issue-3563.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `b` found for reference `&Self` in the current sco LL | || self.b() | ^ help: there is a method with a similar name: `a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/block-result/issue-5500.stderr b/tests/ui/block-result/issue-5500.stderr index 417991e9e0bbd..71ca8ffe2a8e3 100644 --- a/tests/ui/block-result/issue-5500.stderr +++ b/tests/ui/block-result/issue-5500.stderr @@ -14,6 +14,6 @@ LL - &panic!() LL + panic!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/unexpected-return-on-unit.stderr b/tests/ui/block-result/unexpected-return-on-unit.stderr index 4acb955a8e7a4..0b79cf0da2a69 100644 --- a/tests/ui/block-result/unexpected-return-on-unit.stderr +++ b/tests/ui/block-result/unexpected-return-on-unit.stderr @@ -13,6 +13,6 @@ help: try adding a return type LL | fn bar() -> usize { | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/bogus-tag.stderr b/tests/ui/bogus-tag.stderr index 899ff4261ba3b..d94bd489ec609 100644 --- a/tests/ui/bogus-tag.stderr +++ b/tests/ui/bogus-tag.stderr @@ -7,6 +7,6 @@ LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } LL | Color::Hsl(h, s, l) => { println!("hsl"); } | ^^^ variant or associated item not found in `Color` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/borrowck/access-mode-in-closures.stderr b/tests/ui/borrowck/access-mode-in-closures.stderr index abee72ba8cf97..b9a45edb330c3 100644 --- a/tests/ui/borrowck/access-mode-in-closures.stderr +++ b/tests/ui/borrowck/access-mode-in-closures.stderr @@ -13,6 +13,6 @@ LL - match *s { S(v) => v } LL + match s { S(v) => v } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/accidentally-cloning-ref-borrow-error.rs b/tests/ui/borrowck/accidentally-cloning-ref-borrow-error.rs new file mode 100644 index 0000000000000..2b25a5b2348a4 --- /dev/null +++ b/tests/ui/borrowck/accidentally-cloning-ref-borrow-error.rs @@ -0,0 +1,38 @@ +#[derive(Debug)] +struct X(T); + +impl Clone for X { + fn clone(&self) -> X { + X(self.0.clone()) + } +} + +#[derive(Debug)] +struct Y; + +#[derive(Debug)] +struct Str { + x: Option, +} + +fn foo(s: &mut Option) { + if s.is_none() { + *s = Some(0); + } + println!("{:?}", s); +} + +fn bar(s: &mut X) { + println!("{:?}", s); +} +fn main() { + let s = Str { x: None }; + let sr = &s; + let mut sm = sr.clone(); + foo(&mut sm.x); //~ ERROR cannot borrow `sm.x` as mutable, as it is behind a `&` reference + + let x = X(Y); + let xr = &x; + let mut xm = xr.clone(); + bar(&mut xm); //~ ERROR cannot borrow data in a `&` reference as mutable +} diff --git a/tests/ui/borrowck/accidentally-cloning-ref-borrow-error.stderr b/tests/ui/borrowck/accidentally-cloning-ref-borrow-error.stderr new file mode 100644 index 0000000000000..7e51a4819eef6 --- /dev/null +++ b/tests/ui/borrowck/accidentally-cloning-ref-borrow-error.stderr @@ -0,0 +1,30 @@ +error[E0596]: cannot borrow `sm.x` as mutable, as it is behind a `&` reference + --> $DIR/accidentally-cloning-ref-borrow-error.rs:32:9 + | +LL | foo(&mut sm.x); + | ^^^^^^^^^ `sm` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: `Str` doesn't implement `Clone`, so this call clones the reference `&Str` + --> $DIR/accidentally-cloning-ref-borrow-error.rs:31:21 + | +LL | let mut sm = sr.clone(); + | ^^^^^^^ +help: consider annotating `Str` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Str { + | +help: consider specifying this binding's type + | +LL | let mut sm: &mut Str = sr.clone(); + | ++++++++++ + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/accidentally-cloning-ref-borrow-error.rs:37:9 + | +LL | bar(&mut xm); + | ^^^^^^^ cannot borrow as mutable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr b/tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr index 7fd0cb9bb028d..0cd6dfe77626b 100644 --- a/tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr +++ b/tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr @@ -14,6 +14,6 @@ LL ~ let binding = String::new(); LL ~ let func = get_func::(&binding); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/alias-liveness/higher-ranked-outlives-for-capture.stderr b/tests/ui/borrowck/alias-liveness/higher-ranked-outlives-for-capture.stderr index 58a42d8afe4d7..b5c2b662f3159 100644 --- a/tests/ui/borrowck/alias-liveness/higher-ranked-outlives-for-capture.stderr +++ b/tests/ui/borrowck/alias-liveness/higher-ranked-outlives-for-capture.stderr @@ -11,6 +11,6 @@ LL | } | = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/alias-liveness/opaque-type-param.stderr b/tests/ui/borrowck/alias-liveness/opaque-type-param.stderr index e1fbbc14f44ee..73de58649536a 100644 --- a/tests/ui/borrowck/alias-liveness/opaque-type-param.stderr +++ b/tests/ui/borrowck/alias-liveness/opaque-type-param.stderr @@ -8,6 +8,6 @@ LL | fn foo<'a>(s: &'a str) -> impl Trait + 'static { LL | bar(s) | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/borrowck/anonymous-region-in-apit.stderr b/tests/ui/borrowck/anonymous-region-in-apit.stderr index 9e100f8ac3c50..72dfbb797ebc7 100644 --- a/tests/ui/borrowck/anonymous-region-in-apit.stderr +++ b/tests/ui/borrowck/anonymous-region-in-apit.stderr @@ -11,6 +11,6 @@ LL | |baz: &str| foo.bar(baz); | | let's call the lifetime of this reference `'1` | `baz` is a reference that is only valid in the closure body -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr b/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr index 6235e0db0da18..2b16206cd7742 100644 --- a/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr +++ b/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr @@ -9,6 +9,6 @@ LL | move || { LL | x += 1; | ^^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/borrowck-and-init.stderr b/tests/ui/borrowck/borrowck-and-init.stderr index 5abf07a3118d8..37386f1c46516 100644 --- a/tests/ui/borrowck/borrowck-and-init.stderr +++ b/tests/ui/borrowck/borrowck-and-init.stderr @@ -11,6 +11,6 @@ LL | println!("{}", i); | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-anon-fields-struct.stderr b/tests/ui/borrowck/borrowck-anon-fields-struct.stderr index 7a959fb6ec62f..37e98732f1f4a 100644 --- a/tests/ui/borrowck/borrowck-anon-fields-struct.stderr +++ b/tests/ui/borrowck/borrowck-anon-fields-struct.stderr @@ -10,6 +10,6 @@ LL | Y(ref mut b, _) => b LL | *a += 1; | ------- first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-anon-fields-tuple.stderr b/tests/ui/borrowck/borrowck-anon-fields-tuple.stderr index 88a8867f5ee08..b749779b94825 100644 --- a/tests/ui/borrowck/borrowck-anon-fields-tuple.stderr +++ b/tests/ui/borrowck/borrowck-anon-fields-tuple.stderr @@ -10,6 +10,6 @@ LL | (ref mut b, _) => b LL | *a += 1; | ------- first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-assign-to-constants.stderr b/tests/ui/borrowck/borrowck-assign-to-constants.stderr index 864d933da127f..82972b573c6f7 100644 --- a/tests/ui/borrowck/borrowck-assign-to-constants.stderr +++ b/tests/ui/borrowck/borrowck-assign-to-constants.stderr @@ -4,6 +4,6 @@ error[E0594]: cannot assign to immutable static item `foo` LL | foo = 6; | ^^^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr b/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr index 25d642c30dd9e..d14fbd76153b8 100644 --- a/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr +++ b/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut x = Foo { x: 3 }; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-autoref-3261.stderr b/tests/ui/borrowck/borrowck-autoref-3261.stderr index c2dfb687e8ee9..0e462256c5a92 100644 --- a/tests/ui/borrowck/borrowck-autoref-3261.stderr +++ b/tests/ui/borrowck/borrowck-autoref-3261.stderr @@ -11,6 +11,6 @@ LL | |opt| { LL | x = X(Either::Left((0, 0))); | - second borrow occurs due to use of `x` in closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-block-uninit.stderr b/tests/ui/borrowck/borrowck-block-uninit.stderr index 1a5969586f239..07c09f1f443c5 100644 --- a/tests/ui/borrowck/borrowck-block-uninit.stderr +++ b/tests/ui/borrowck/borrowck-block-uninit.stderr @@ -13,6 +13,6 @@ help: consider assigning a value LL | let x: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-borrow-from-temporary.stderr b/tests/ui/borrowck/borrowck-borrow-from-temporary.stderr index 71bf052c93d61..dabb5e21fd096 100644 --- a/tests/ui/borrowck/borrowck-borrow-from-temporary.stderr +++ b/tests/ui/borrowck/borrowck-borrow-from-temporary.stderr @@ -6,6 +6,6 @@ LL | let &Foo(ref x) = &id(Foo(3)); LL | x | ^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr b/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr index a61fdbf6c8f84..199f7c120d8a6 100644 --- a/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr +++ b/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut a: Box<_> = Box::new(A); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-borrow-mut-object-twice.stderr b/tests/ui/borrowck/borrowck-borrow-mut-object-twice.stderr index fa0ae318e72cd..0bcf63d6af553 100644 --- a/tests/ui/borrowck/borrowck-borrow-mut-object-twice.stderr +++ b/tests/ui/borrowck/borrowck-borrow-mut-object-twice.stderr @@ -8,6 +8,6 @@ LL | x.f2(); LL | y.use_ref(); | - first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr index 6e112e2703003..7f0ecf7b35965 100644 --- a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr +++ b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr @@ -15,6 +15,6 @@ LL ~ let binding = vec!["Goodbye", "world!"]; LL ~ let x = defer(&binding); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr index 7ee840b34c52a..5d6fc8fa7a339 100644 --- a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr +++ b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr @@ -15,6 +15,6 @@ LL ~ let binding = Box::new(1); LL ~ buggy_map.insert(42, &*binding); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/borrowck-break-uninit-2.stderr b/tests/ui/borrowck/borrowck-break-uninit-2.stderr index ea93a8f409ce4..7c0cda31c9734 100644 --- a/tests/ui/borrowck/borrowck-break-uninit-2.stderr +++ b/tests/ui/borrowck/borrowck-break-uninit-2.stderr @@ -13,6 +13,6 @@ help: consider assigning a value LL | let x: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-break-uninit.stderr b/tests/ui/borrowck/borrowck-break-uninit.stderr index a7a8fc2ff8378..0d879c6fb7df2 100644 --- a/tests/ui/borrowck/borrowck-break-uninit.stderr +++ b/tests/ui/borrowck/borrowck-break-uninit.stderr @@ -13,6 +13,6 @@ help: consider assigning a value LL | let x: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-closures-mut-of-mut.stderr b/tests/ui/borrowck/borrowck-closures-mut-of-mut.stderr index e5ee5a401050a..105a0b05189ed 100644 --- a/tests/ui/borrowck/borrowck-closures-mut-of-mut.stderr +++ b/tests/ui/borrowck/borrowck-closures-mut-of-mut.stderr @@ -13,6 +13,6 @@ LL | LL | c2(); c1(); | -- first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0524`. diff --git a/tests/ui/borrowck/borrowck-closures-unique-imm.stderr b/tests/ui/borrowck/borrowck-closures-unique-imm.stderr index b8bbb31a3550f..669dd614f52d1 100644 --- a/tests/ui/borrowck/borrowck-closures-unique-imm.stderr +++ b/tests/ui/borrowck/borrowck-closures-unique-imm.stderr @@ -8,6 +8,6 @@ LL | &mut this.x; LL | p.use_ref(); | - immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-closures-use-after-free.stderr b/tests/ui/borrowck/borrowck-closures-use-after-free.stderr index 30900a3b6d96e..bc840577e9b6f 100644 --- a/tests/ui/borrowck/borrowck-closures-use-after-free.stderr +++ b/tests/ui/borrowck/borrowck-closures-use-after-free.stderr @@ -11,6 +11,6 @@ LL | test(&*ptr); | | | mutable borrow later used by call -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-consume-unsize-vec.stderr b/tests/ui/borrowck/borrowck-consume-unsize-vec.stderr index d2e9497d0795c..abd7f19fc9553 100644 --- a/tests/ui/borrowck/borrowck-consume-unsize-vec.stderr +++ b/tests/ui/borrowck/borrowck-consume-unsize-vec.stderr @@ -20,6 +20,6 @@ help: consider cloning the value if the performance cost is acceptable LL | consume(b.clone()); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-consume-upcast-box.stderr b/tests/ui/borrowck/borrowck-consume-upcast-box.stderr index ed7e883ca6392..4c3861cfe7ab5 100644 --- a/tests/ui/borrowck/borrowck-consume-upcast-box.stderr +++ b/tests/ui/borrowck/borrowck-consume-upcast-box.stderr @@ -16,6 +16,6 @@ LL | fn consume(_: Box) { | | | in this function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-escaping-closure-error-1.stderr b/tests/ui/borrowck/borrowck-escaping-closure-error-1.stderr index acf6b37b77396..6dcd451736df9 100644 --- a/tests/ui/borrowck/borrowck-escaping-closure-error-1.stderr +++ b/tests/ui/borrowck/borrowck-escaping-closure-error-1.stderr @@ -16,6 +16,6 @@ help: to force the closure to take ownership of `books` (and any other reference LL | spawn(move || books.push(4)); | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/borrowck/borrowck-escaping-closure-error-2.stderr b/tests/ui/borrowck/borrowck-escaping-closure-error-2.stderr index 814042539a22f..7a1c1510b6a6a 100644 --- a/tests/ui/borrowck/borrowck-escaping-closure-error-2.stderr +++ b/tests/ui/borrowck/borrowck-escaping-closure-error-2.stderr @@ -16,6 +16,6 @@ help: to force the closure to take ownership of `books` (and any other reference LL | Box::new(move || books.push(4)) | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/borrowck/borrowck-fn-in-const-a.stderr b/tests/ui/borrowck/borrowck-fn-in-const-a.stderr index e7491afdad120..e05696864fdf8 100644 --- a/tests/ui/borrowck/borrowck-fn-in-const-a.stderr +++ b/tests/ui/borrowck/borrowck-fn-in-const-a.stderr @@ -4,6 +4,6 @@ error[E0507]: cannot move out of `*x` which is behind a shared reference LL | return *x | ^^ move occurs because `*x` has type `String`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-fn-in-const-c.stderr b/tests/ui/borrowck/borrowck-fn-in-const-c.stderr index d48866dce0423..ee1bb2a48816e 100644 --- a/tests/ui/borrowck/borrowck-fn-in-const-c.stderr +++ b/tests/ui/borrowck/borrowck-fn-in-const-c.stderr @@ -6,6 +6,6 @@ LL | return &local.inner; LL | } | - here, drop of `local` needs exclusive access to `local.inner`, because the type `DropString` implements the `Drop` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr b/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr index fc1a44c3ca04e..79519e885d017 100644 --- a/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr +++ b/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr @@ -8,6 +8,6 @@ LL | for _ in 0..0 { x = 10; } LL | return x; | ^ `x` used here but it is possibly-uninitialized -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-if-no-else.stderr b/tests/ui/borrowck/borrowck-if-no-else.stderr index 9eafc2c2a86e6..f1fad2d36dc5e 100644 --- a/tests/ui/borrowck/borrowck-if-no-else.stderr +++ b/tests/ui/borrowck/borrowck-if-no-else.stderr @@ -9,6 +9,6 @@ LL | let x: isize; if 1 > 2 { x = 10; } LL | foo(x); | ^ `x` used here but it is possibly-uninitialized -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-if-with-else.stderr b/tests/ui/borrowck/borrowck-if-with-else.stderr index 3f0fe291ca250..c246e41487fc3 100644 --- a/tests/ui/borrowck/borrowck-if-with-else.stderr +++ b/tests/ui/borrowck/borrowck-if-with-else.stderr @@ -9,6 +9,6 @@ LL | if 1 > 2 { LL | foo(x); | ^ `x` used here but it is possibly-uninitialized -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr b/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr index 1a20ec85fc00f..3f052f8fe3bd7 100644 --- a/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr +++ b/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr @@ -10,6 +10,6 @@ LL | _a = 4; LL | drop(b); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-in-static.stderr b/tests/ui/borrowck/borrowck-in-static.stderr index 2033e4a573014..8171e6950ace5 100644 --- a/tests/ui/borrowck/borrowck-in-static.stderr +++ b/tests/ui/borrowck/borrowck-in-static.stderr @@ -8,6 +8,6 @@ LL | Box::new(|| x) | | | captured by this `Fn` closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr index 1a22b5f0975c0..a27b6956b305b 100644 --- a/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr +++ b/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let i: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr b/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr index f1b9b9aa7090a..16f4c40f529c9 100644 --- a/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr +++ b/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let i: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-init-in-fru.stderr b/tests/ui/borrowck/borrowck-init-in-fru.stderr index 39b28811a0c27..f27993e10b44e 100644 --- a/tests/ui/borrowck/borrowck-init-in-fru.stderr +++ b/tests/ui/borrowck/borrowck-init-in-fru.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let mut origin: Point = todo!(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-init-op-equal.stderr b/tests/ui/borrowck/borrowck-init-op-equal.stderr index ef0fa6df4fb7e..241d24341cb69 100644 --- a/tests/ui/borrowck/borrowck-init-op-equal.stderr +++ b/tests/ui/borrowck/borrowck-init-op-equal.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let v: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-init-plus-equal.stderr b/tests/ui/borrowck/borrowck-init-plus-equal.stderr index cec0533183647..65de6e8bf5d3a 100644 --- a/tests/ui/borrowck/borrowck-init-plus-equal.stderr +++ b/tests/ui/borrowck/borrowck-init-plus-equal.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let mut v: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-issue-2657-1.stderr b/tests/ui/borrowck/borrowck-issue-2657-1.stderr index 4ea4eb8f00759..194403fc17eb9 100644 --- a/tests/ui/borrowck/borrowck-issue-2657-1.stderr +++ b/tests/ui/borrowck/borrowck-issue-2657-1.stderr @@ -8,6 +8,6 @@ LL | let _a = x; LL | _y.use_ref(); | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-issue-2657-2.stderr b/tests/ui/borrowck/borrowck-issue-2657-2.stderr index 850bb9ae3930c..6fab19000fcb7 100644 --- a/tests/ui/borrowck/borrowck-issue-2657-2.stderr +++ b/tests/ui/borrowck/borrowck-issue-2657-2.stderr @@ -10,6 +10,6 @@ LL - let _b = *y; LL + let _b = y; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-lend-flow-if.stderr b/tests/ui/borrowck/borrowck-lend-flow-if.stderr index 68a82bdb57c55..abcd14f9a567d 100644 --- a/tests/ui/borrowck/borrowck-lend-flow-if.stderr +++ b/tests/ui/borrowck/borrowck-lend-flow-if.stderr @@ -9,6 +9,6 @@ LL | borrow_mut(&mut *v); LL | _w.use_ref(); | -- immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-lend-flow-match.stderr b/tests/ui/borrowck/borrowck-lend-flow-match.stderr index 6cdce7bee8897..3e9124bdc27bb 100644 --- a/tests/ui/borrowck/borrowck-lend-flow-match.stderr +++ b/tests/ui/borrowck/borrowck-lend-flow-match.stderr @@ -8,6 +8,6 @@ LL | x = Some(1); LL | drop(r); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-lend-flow.stderr b/tests/ui/borrowck/borrowck-lend-flow.stderr index 07b11b3e72828..0c60b094834a0 100644 --- a/tests/ui/borrowck/borrowck-lend-flow.stderr +++ b/tests/ui/borrowck/borrowck-lend-flow.stderr @@ -8,6 +8,6 @@ LL | borrow_mut(&mut *v); LL | _w.use_ref(); | -- immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr index de8da490c2e41..d1fbc5b47db14 100644 --- a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr +++ b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr @@ -10,6 +10,6 @@ LL | take(v); LL | w.use_ref(); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr b/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr index fa5308c290390..3285c7f0ca14a 100644 --- a/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr +++ b/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr @@ -10,6 +10,6 @@ LL | |w| { LL | v = Box::new(4); | - second borrow occurs due to use of `v` in closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-loan-in-overloaded-op.stderr b/tests/ui/borrowck/borrowck-loan-in-overloaded-op.stderr index 93622a0c5f650..5f1e3994af207 100644 --- a/tests/ui/borrowck/borrowck-loan-in-overloaded-op.stderr +++ b/tests/ui/borrowck/borrowck-loan-in-overloaded-op.stderr @@ -13,6 +13,6 @@ help: consider cloning the value if the performance cost is acceptable LL | let _y = {x.clone()} + x.clone(); // the `{x}` forces a move to occur | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr b/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr index 311369a260d76..838568fd32ca6 100644 --- a/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr +++ b/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr @@ -9,6 +9,6 @@ LL | let alias: &'static mut String = s; LL | *s = String::new(); | ^^ `*s` is assigned to here but it was already borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-loan-vec-content.stderr b/tests/ui/borrowck/borrowck-loan-vec-content.stderr index 6691a2396a1da..eb11dfa38b8d3 100644 --- a/tests/ui/borrowck/borrowck-loan-vec-content.stderr +++ b/tests/ui/borrowck/borrowck-loan-vec-content.stderr @@ -10,6 +10,6 @@ LL | || { LL | v[1] = 4; | - second borrow occurs due to use of `v` in closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.stderr b/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.stderr index 9d19de211a5e0..9c26bc353ab7d 100644 --- a/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.stderr +++ b/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.stderr @@ -4,6 +4,6 @@ error[E0515]: cannot return reference to function parameter `x` LL | &x | ^^ returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr b/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr index 0fdb1dabbc50c..bac9c2790c54b 100644 --- a/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr +++ b/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr @@ -12,6 +12,6 @@ LL | *x = Some(&mut z.1); LL | } | - `z.1` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/borrowck/borrowck-move-by-capture.stderr b/tests/ui/borrowck/borrowck-move-by-capture.stderr index 6eaa1fa316932..01647011207f4 100644 --- a/tests/ui/borrowck/borrowck-move-by-capture.stderr +++ b/tests/ui/borrowck/borrowck-move-by-capture.stderr @@ -12,6 +12,6 @@ LL | let _h = to_fn_once(move || -> isize { *bar }); | | move occurs because `bar` has type `Box`, which does not implement the `Copy` trait | `bar` is moved here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr index 4f0202f38324a..a41c4af98e7cd 100644 --- a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr +++ b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr @@ -11,6 +11,6 @@ LL | let z = *a; LL | b.use_ref(); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr b/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr index 43fc102bd6256..7213f85ad98fc 100644 --- a/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr +++ b/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr @@ -10,6 +10,6 @@ LL - let y = *x; LL + let y = x; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-moved-value-into-closure.stderr b/tests/ui/borrowck/borrowck-move-moved-value-into-closure.stderr index 9509ebb7cde9a..6a77d86f250a1 100644 --- a/tests/ui/borrowck/borrowck-move-moved-value-into-closure.stderr +++ b/tests/ui/borrowck/borrowck-move-moved-value-into-closure.stderr @@ -13,6 +13,6 @@ LL | call_f(move|| { *t + 1 }); | | | value used here after move -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr index e1e3c7f8aaa56..88eb6c8ceeee6 100644 --- a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr +++ b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr @@ -11,6 +11,6 @@ LL | *t1 = 22; LL | p.use_ref(); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.fixed b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.fixed new file mode 100644 index 0000000000000..0b7551b97af94 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.fixed @@ -0,0 +1,7 @@ +// run-rustfix +use std::rc::Rc; + +pub fn main() { + let _x = as Clone>::clone(&Rc::new(vec![1, 2])).into_iter(); + //~^ ERROR [E0507] +} diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs index 0b9e7102cd54f..5cb8ceaca0866 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs +++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs @@ -1,3 +1,4 @@ +// run-rustfix use std::rc::Rc; pub fn main() { diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr index 934dd8df1d2d7..076f0ce3440a0 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of an `Rc` - --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:4:14 + --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:5:14 | LL | let _x = Rc::new(vec![1, 2]).into_iter(); | ^^^^^^^^^^^^^^^^^^^ ----------- value moved due to this method call @@ -10,9 +10,9 @@ note: `into_iter` takes ownership of the receiver `self`, which moves value --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL help: you can `clone` the value and consume it, but this might not be your desired behavior | -LL | let _x = Rc::new(vec![1, 2]).clone().into_iter(); - | ++++++++ +LL | let _x = as Clone>::clone(&Rc::new(vec![1, 2])).into_iter(); + | ++++++++++++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr b/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr index 599fa1e88dfec..dce1f4d0775e6 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr @@ -10,6 +10,6 @@ LL - let _x = *Rc::new("hi".to_string()); LL + let _x = Rc::new("hi".to_string()); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr index edf8c954f816b..07dcaf875e701 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -4,6 +4,6 @@ error[E0507]: cannot move out of static item `BAR` LL | test(BAR); | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-vec-tail.stderr b/tests/ui/borrowck/borrowck-move-out-of-vec-tail.stderr index 9ff20a1f46a12..4fa23f16bfdb2 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-vec-tail.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-vec-tail.stderr @@ -16,6 +16,6 @@ LL - &[Foo { string: a }, LL + [Foo { string: a }, | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr index 341146bd18fd9..8408d99156a30 100644 --- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -10,6 +10,6 @@ LL | let S { x: ax } = a; LL | f(pb); | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr b/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr index 20528e3f0ee08..84f35dc2249ec 100644 --- a/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr +++ b/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut x: isize = 3; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr b/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr index 8ab472e64c7a9..823f470ce8efb 100644 --- a/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr +++ b/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut v = vec![1, 2, 3]; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr b/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr index 3462b7610d38b..bde43a90850ba 100644 --- a/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr +++ b/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr @@ -8,6 +8,6 @@ LL | y.a = x; | | | borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-or-init.stderr b/tests/ui/borrowck/borrowck-or-init.stderr index 16d66bf40d109..7b43f2aee30e7 100644 --- a/tests/ui/borrowck/borrowck-or-init.stderr +++ b/tests/ui/borrowck/borrowck-or-init.stderr @@ -11,6 +11,6 @@ LL | println!("{}", i); | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr b/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr index 7f42becd21c2a..7b2cac9879605 100644 --- a/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr @@ -9,6 +9,6 @@ LL | LL | read(*i); | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr b/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr index f5f4817e9bf32..b4106702cd1a8 100644 --- a/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr @@ -9,6 +9,6 @@ help: consider borrowing here LL | let bad = &v[0]; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-partial-reinit-2.stderr b/tests/ui/borrowck/borrowck-partial-reinit-2.stderr index 36a871fbb12a1..e25ca082b7b55 100644 --- a/tests/ui/borrowck/borrowck-partial-reinit-2.stderr +++ b/tests/ui/borrowck/borrowck-partial-reinit-2.stderr @@ -8,6 +8,6 @@ LL | let mut u = Test { a: 2, b: Some(Box::new(t))}; LL | t.b = Some(Box::new(u)); | ^^^ value assigned here after move -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-partial-reinit-3.stderr b/tests/ui/borrowck/borrowck-partial-reinit-3.stderr index 05f5411eed68c..291737952388d 100644 --- a/tests/ui/borrowck/borrowck-partial-reinit-3.stderr +++ b/tests/ui/borrowck/borrowck-partial-reinit-3.stderr @@ -8,6 +8,6 @@ LL | x.0.f = 3; | = note: move occurs because `x.0` has type `Test`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-partial-reinit-4.stderr b/tests/ui/borrowck/borrowck-partial-reinit-4.stderr index d12a482cb69a9..4833e689c19b3 100644 --- a/tests/ui/borrowck/borrowck-partial-reinit-4.stderr +++ b/tests/ui/borrowck/borrowck-partial-reinit-4.stderr @@ -8,6 +8,6 @@ LL | (x.0).0 = Some(Test); | = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr b/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr index b86a8693881a9..387c681fddfa8 100644 --- a/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr +++ b/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr @@ -9,6 +9,6 @@ LL | x = Some(*i+1); LL | drop(i); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr b/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr index f28c42ce2d58f..65748d844fa1d 100644 --- a/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr +++ b/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr @@ -10,5 +10,5 @@ LL | S { pointer: &mut *p.pointer } | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr b/tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr index 5cfd81bd00428..5f319112b86e0 100644 --- a/tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr +++ b/tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | fn destructure(mut x: Option) -> isize { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-reinit.stderr b/tests/ui/borrowck/borrowck-reinit.stderr index f785900d53fc0..16047efa32bfa 100644 --- a/tests/ui/borrowck/borrowck-reinit.stderr +++ b/tests/ui/borrowck/borrowck-reinit.stderr @@ -14,6 +14,6 @@ help: consider cloning the value if the performance cost is acceptable LL | drop(x.clone()); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr b/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr index d54449ac4ad46..eade7d1ea95ce 100644 --- a/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr +++ b/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr @@ -7,6 +7,6 @@ LL | (&x).clone() | returns a value referencing data owned by the current function | `x` is borrowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-return.stderr b/tests/ui/borrowck/borrowck-return.stderr index 9799357c9ca19..a1bc3008ea8cc 100644 --- a/tests/ui/borrowck/borrowck-return.stderr +++ b/tests/ui/borrowck/borrowck-return.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let x: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-storage-dead.stderr b/tests/ui/borrowck/borrowck-storage-dead.stderr index 3a413153acd19..a08e2a7b5352e 100644 --- a/tests/ui/borrowck/borrowck-storage-dead.stderr +++ b/tests/ui/borrowck/borrowck-storage-dead.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let x: i32 = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-swap-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-swap-mut-base-ptr.stderr index 1c55953c91fb7..225a983bab44f 100644 --- a/tests/ui/borrowck/borrowck-swap-mut-base-ptr.stderr +++ b/tests/ui/borrowck/borrowck-swap-mut-base-ptr.stderr @@ -9,6 +9,6 @@ LL | *t1 = 22; LL | p.use_ref(); | - immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr index 2f397f6b58532..11ee8f7bb91a5 100644 --- a/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr +++ b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr @@ -6,6 +6,6 @@ LL | assert_static(&FOO); LL | } | - end of enclosing function is here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0712`. diff --git a/tests/ui/borrowck/borrowck-unary-move.stderr b/tests/ui/borrowck/borrowck-unary-move.stderr index f3b962059f5b4..e6c3869f67ae4 100644 --- a/tests/ui/borrowck/borrowck-unary-move.stderr +++ b/tests/ui/borrowck/borrowck-unary-move.stderr @@ -10,6 +10,6 @@ LL | free(x); LL | *y | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-uninit-after-item.stderr b/tests/ui/borrowck/borrowck-uninit-after-item.stderr index 071598b42eecd..06bb419aa3b38 100644 --- a/tests/ui/borrowck/borrowck-uninit-after-item.stderr +++ b/tests/ui/borrowck/borrowck-uninit-after-item.stderr @@ -12,6 +12,6 @@ help: consider assigning a value LL | let bar = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-uninit.stderr b/tests/ui/borrowck/borrowck-uninit.stderr index eeafc4ce191c6..213b541b8a920 100644 --- a/tests/ui/borrowck/borrowck-uninit.stderr +++ b/tests/ui/borrowck/borrowck-uninit.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let x: isize = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-union-borrow-nested.stderr b/tests/ui/borrowck/borrowck-union-borrow-nested.stderr index f2e549cd88c92..68a950dfdaaf3 100644 --- a/tests/ui/borrowck/borrowck-union-borrow-nested.stderr +++ b/tests/ui/borrowck/borrowck-union-borrow-nested.stderr @@ -8,6 +8,6 @@ LL | let b = u.c; LL | ra.use_mut(); | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/borrowck/borrowck-union-move-assign.stderr b/tests/ui/borrowck/borrowck-union-move-assign.stderr index af6f6fac40870..8c0239a3ae91f 100644 --- a/tests/ui/borrowck/borrowck-union-move-assign.stderr +++ b/tests/ui/borrowck/borrowck-union-move-assign.stderr @@ -8,6 +8,6 @@ LL | let a = u.a; LL | let a = u.a; | ^^^ value used here after move -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr index 55f3ff553c13c..dcbaa75333e01 100644 --- a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let x: &i32 = todo!(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr index ea3d0d3ef51cb..7ccf6a4c3fc8a 100644 --- a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let x: &i32 = todo!(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr b/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr index 5141fcc1bb261..d5964d28b083e 100644 --- a/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr +++ b/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr @@ -9,6 +9,6 @@ LL | v.push(tail[0] + tail[1]); | | | second mutable borrow occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr b/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr index 494d8c351a152..03a7efacb332e 100644 --- a/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr +++ b/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr @@ -9,6 +9,6 @@ LL | a[2] = 0; LL | println!("t[0]: {}", t[0]); | ---- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr b/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr index 7e21c55f21b5f..2187437a1cd2f 100644 --- a/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr +++ b/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr @@ -7,6 +7,6 @@ LL | let vec: &[isize] = &vec; LL | tail | ^^^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-while-break.stderr b/tests/ui/borrowck/borrowck-while-break.stderr index 13143d436df8e..e91af728b649e 100644 --- a/tests/ui/borrowck/borrowck-while-break.stderr +++ b/tests/ui/borrowck/borrowck-while-break.stderr @@ -11,6 +11,6 @@ LL | println!("{}", v); | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-while-cond.stderr b/tests/ui/borrowck/borrowck-while-cond.stderr index 5d01949895639..2d92b45e02a6e 100644 --- a/tests/ui/borrowck/borrowck-while-cond.stderr +++ b/tests/ui/borrowck/borrowck-while-cond.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let x: bool = false; | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-while.stderr b/tests/ui/borrowck/borrowck-while.stderr index c45235990c383..d560b9c02fb68 100644 --- a/tests/ui/borrowck/borrowck-while.stderr +++ b/tests/ui/borrowck/borrowck-while.stderr @@ -8,6 +8,6 @@ LL | while 1 == 1 { x = 10; } LL | return x; | ^ `x` used here but it is possibly-uninitialized -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/clone-span-on-try-operator.fixed b/tests/ui/borrowck/clone-span-on-try-operator.fixed index 52f66e43a930a..4fad75b9a3d61 100644 --- a/tests/ui/borrowck/clone-span-on-try-operator.fixed +++ b/tests/ui/borrowck/clone-span-on-try-operator.fixed @@ -7,5 +7,5 @@ impl Foo { } fn main() { let foo = &Foo; - (*foo).clone().foo(); //~ ERROR cannot move out + ::clone(&(*foo)).foo(); //~ ERROR cannot move out } diff --git a/tests/ui/borrowck/clone-span-on-try-operator.stderr b/tests/ui/borrowck/clone-span-on-try-operator.stderr index 85785e670729d..adf84e49a9f8d 100644 --- a/tests/ui/borrowck/clone-span-on-try-operator.stderr +++ b/tests/ui/borrowck/clone-span-on-try-operator.stderr @@ -13,9 +13,9 @@ LL | fn foo(self) {} | ^^^^ help: you can `clone` the value and consume it, but this might not be your desired behavior | -LL | (*foo).clone().foo(); - | ++++++++ +LL | ::clone(&(*foo)).foo(); + | +++++++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/copy-suggestion-region-vid.stderr b/tests/ui/borrowck/copy-suggestion-region-vid.stderr index b344aa6640517..3a801a22ea2b0 100644 --- a/tests/ui/borrowck/copy-suggestion-region-vid.stderr +++ b/tests/ui/borrowck/copy-suggestion-region-vid.stderr @@ -14,6 +14,6 @@ help: consider cloning the value if the performance cost is acceptable LL | HelperStruct { helpers: helpers.clone(), is_empty: helpers[0].is_empty() } | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr b/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr index 78ca090feb722..879ff8be0e882 100644 --- a/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr +++ b/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr @@ -14,5 +14,5 @@ LL | move || { iter.next() } = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/drop-in-loop.stderr b/tests/ui/borrowck/drop-in-loop.stderr index d5734e7ec9770..98dae19a7d442 100644 --- a/tests/ui/borrowck/drop-in-loop.stderr +++ b/tests/ui/borrowck/drop-in-loop.stderr @@ -9,6 +9,6 @@ LL | base = false; LL | wrapper = WrapperWithDrop(&mut base); | ------- borrow might be used here, when `wrapper` is dropped and runs the `Drop` code for type `WrapperWithDrop` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/generic_const_early_param.rs b/tests/ui/borrowck/generic_const_early_param.rs new file mode 100644 index 0000000000000..f601e45d21fee --- /dev/null +++ b/tests/ui/borrowck/generic_const_early_param.rs @@ -0,0 +1,16 @@ +#![feature(generic_const_exprs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +struct DataWrapper<'static> { + //~^ ERROR invalid lifetime parameter name: `'static` + data: &'a [u8; Self::SIZE], + //~^ ERROR use of undeclared lifetime name `'a` + //~^^ ERROR lifetime may not live long enough +} + +impl DataWrapper<'a> { + //~^ ERROR undeclared lifetime + const SIZE: usize = 14; +} + +fn main(){} diff --git a/tests/ui/borrowck/generic_const_early_param.stderr b/tests/ui/borrowck/generic_const_early_param.stderr new file mode 100644 index 0000000000000..a71ab09396e73 --- /dev/null +++ b/tests/ui/borrowck/generic_const_early_param.stderr @@ -0,0 +1,42 @@ +error[E0262]: invalid lifetime parameter name: `'static` + --> $DIR/generic_const_early_param.rs:4:20 + | +LL | struct DataWrapper<'static> { + | ^^^^^^^ 'static is a reserved lifetime name + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/generic_const_early_param.rs:6:12 + | +LL | struct DataWrapper<'static> { + | - help: consider introducing lifetime `'a` here: `'a,` +LL | +LL | data: &'a [u8; Self::SIZE], + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/generic_const_early_param.rs:11:18 + | +LL | impl DataWrapper<'a> { + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/generic_const_early_param.rs:1:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: lifetime may not live long enough + --> $DIR/generic_const_early_param.rs:6:20 + | +LL | data: &'a [u8; Self::SIZE], + | ^^^^^^^^^^ requires that `'_` must outlive `'static` + +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0261, E0262. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/borrowck/immutable-arg.stderr b/tests/ui/borrowck/immutable-arg.stderr index bddb0633a0b86..84a480f641071 100644 --- a/tests/ui/borrowck/immutable-arg.stderr +++ b/tests/ui/borrowck/immutable-arg.stderr @@ -6,6 +6,6 @@ LL | fn foo(_x: u32) { LL | _x = 4; | ^^^^^^ cannot assign to immutable argument -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/borrowck/index-mut-help-with-impl.stderr b/tests/ui/borrowck/index-mut-help-with-impl.stderr index 89391f4099a21..a97f2bdd4c9b7 100644 --- a/tests/ui/borrowck/index-mut-help-with-impl.stderr +++ b/tests/ui/borrowck/index-mut-help-with-impl.stderr @@ -4,6 +4,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | Index::index(&v, 1..2).make_ascii_uppercase(); | ^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-101119.stderr b/tests/ui/borrowck/issue-101119.stderr index a22afdc67648f..1f32ece3d3d29 100644 --- a/tests/ui/borrowck/issue-101119.stderr +++ b/tests/ui/borrowck/issue-101119.stderr @@ -10,6 +10,6 @@ LL | LL | fill_segment(state); | ----- use occurs due to use in closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-103250.stderr b/tests/ui/borrowck/issue-103250.stderr index 4a237835222f5..b7ece5d971d89 100644 --- a/tests/ui/borrowck/issue-103250.stderr +++ b/tests/ui/borrowck/issue-103250.stderr @@ -12,6 +12,6 @@ help: consider assigning a value LL | let mut last_error: Box = todo!(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr b/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr index 8221505b100e9..3ee89d9734a0f 100644 --- a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr +++ b/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr @@ -9,7 +9,7 @@ LL | let x = format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3); LL | bar(x); | - borrow later used here | - = note: the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used + = note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used = note: to learn more, visit = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -24,7 +24,7 @@ LL | LL | bar(foo); | --- borrow later used here | - = note: the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used + = note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used = note: to learn more, visit = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/borrowck/issue-11493.stderr b/tests/ui/borrowck/issue-11493.stderr index 2720b09b0fc5f..211d4cb3e4bd1 100644 --- a/tests/ui/borrowck/issue-11493.stderr +++ b/tests/ui/borrowck/issue-11493.stderr @@ -14,6 +14,6 @@ LL ~ let binding = id(5); LL ~ let y = x.as_ref().unwrap_or(&binding); | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr b/tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr index 7e0fc2cf298b0..40ab2e61d6a42 100644 --- a/tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr +++ b/tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr @@ -11,6 +11,6 @@ help: you may want to use `iter_mut` here LL | self.layers.iter_mut().fold(0, |result, mut layer| result + layer.process()) | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-17545.stderr b/tests/ui/borrowck/issue-17545.stderr index 3ae7e64d202b6..45e977e39477e 100644 --- a/tests/ui/borrowck/issue-17545.stderr +++ b/tests/ui/borrowck/issue-17545.stderr @@ -11,6 +11,6 @@ LL | | )); | |______| | argument requires that borrow lasts for `'a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr index 65aea5b1834b0..5ca0a7fb8853e 100644 --- a/tests/ui/borrowck/issue-17718-static-move.stderr +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -9,6 +9,6 @@ help: consider borrowing here LL | let _a = &FOO; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-25793.stderr b/tests/ui/borrowck/issue-25793.stderr index 27dab53e48fd5..e2efc405faba4 100644 --- a/tests/ui/borrowck/issue-25793.stderr +++ b/tests/ui/borrowck/issue-25793.stderr @@ -13,6 +13,6 @@ LL | r.get_size(width!(self)) | = note: this error originates in the macro `width` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/borrowck/issue-33819.stderr b/tests/ui/borrowck/issue-33819.stderr index f77fdbf2b6bfe..41c9d6aac760b 100644 --- a/tests/ui/borrowck/issue-33819.stderr +++ b/tests/ui/borrowck/issue-33819.stderr @@ -7,6 +7,6 @@ LL | Some(ref v) => { let a = &mut v; }, | cannot borrow as mutable | help: try removing `&mut` here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-36082.stderr b/tests/ui/borrowck/issue-36082.stderr index a6357f8182fc2..47c78d6863b50 100644 --- a/tests/ui/borrowck/issue-36082.stderr +++ b/tests/ui/borrowck/issue-36082.stderr @@ -15,6 +15,6 @@ LL ~ let binding = x.borrow(); LL ~ let val: &_ = binding.0; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/issue-41962.stderr b/tests/ui/borrowck/issue-41962.stderr index 716cc9d0c8ba2..8585376b92dd7 100644 --- a/tests/ui/borrowck/issue-41962.stderr +++ b/tests/ui/borrowck/issue-41962.stderr @@ -10,6 +10,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | if let Some(ref thing) = maybe { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-42344.stderr b/tests/ui/borrowck/issue-42344.stderr index 5cffa1b51219f..bf82d462b51bc 100644 --- a/tests/ui/borrowck/issue-42344.stderr +++ b/tests/ui/borrowck/issue-42344.stderr @@ -4,6 +4,6 @@ error[E0596]: cannot borrow `*TAB[_]` as mutable, as `TAB` is an immutable stati LL | TAB[0].iter_mut(); | ^^^^^^ cannot borrow as mutable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-45983.stderr b/tests/ui/borrowck/issue-45983.stderr index feb098c598588..19a4a98bb1f49 100644 --- a/tests/ui/borrowck/issue-45983.stderr +++ b/tests/ui/borrowck/issue-45983.stderr @@ -8,6 +8,6 @@ LL | give_any(|y| x = Some(y)); | | | `y` is a reference that is only valid in the closure body -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/issue-46471.stderr b/tests/ui/borrowck/issue-46471.stderr index 935414c1f3f9d..17e4b5e8dcfb2 100644 --- a/tests/ui/borrowck/issue-46471.stderr +++ b/tests/ui/borrowck/issue-46471.stderr @@ -4,6 +4,6 @@ error[E0515]: cannot return reference to local variable `x` LL | &x | ^^ returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/issue-47215-ice-from-drop-elab.stderr b/tests/ui/borrowck/issue-47215-ice-from-drop-elab.stderr index 8d4918867f75e..d6aeb410ec4de 100644 --- a/tests/ui/borrowck/issue-47215-ice-from-drop-elab.stderr +++ b/tests/ui/borrowck/issue-47215-ice-from-drop-elab.stderr @@ -9,6 +9,6 @@ help: consider borrowing here LL | let mut x = &X; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-47646.stderr b/tests/ui/borrowck/issue-47646.stderr index d82e1f908cb8d..85adfc03d1070 100644 --- a/tests/ui/borrowck/issue-47646.stderr +++ b/tests/ui/borrowck/issue-47646.stderr @@ -15,6 +15,6 @@ LL | }; | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/issue-51117.stderr b/tests/ui/borrowck/issue-51117.stderr index f8a9608ad373a..d19fa18dfb63a 100644 --- a/tests/ui/borrowck/issue-51117.stderr +++ b/tests/ui/borrowck/issue-51117.stderr @@ -8,6 +8,6 @@ LL | bar.take(); LL | drop(baz); | --- first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/issue-51301.stderr b/tests/ui/borrowck/issue-51301.stderr index 6ec920cb81f39..c0b06437093a6 100644 --- a/tests/ui/borrowck/issue-51301.stderr +++ b/tests/ui/borrowck/issue-51301.stderr @@ -12,6 +12,6 @@ help: consider borrowing the pattern binding LL | .find(|(&ref event_type, _)| event == event_type) | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-51415.stderr b/tests/ui/borrowck/issue-51415.stderr index 0d486b45592b5..e51e0b33ebd30 100644 --- a/tests/ui/borrowck/issue-51415.stderr +++ b/tests/ui/borrowck/issue-51415.stderr @@ -12,6 +12,6 @@ help: consider borrowing the pattern binding LL | let opt = a.iter().enumerate().find(|(_, &ref s)| { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-52713-bug.stderr b/tests/ui/borrowck/issue-52713-bug.stderr index 3f7715645e60c..ac4936bac4bc0 100644 --- a/tests/ui/borrowck/issue-52713-bug.stderr +++ b/tests/ui/borrowck/issue-52713-bug.stderr @@ -9,6 +9,6 @@ LL | x += 1; LL | println!("{}", y); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr b/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr index 3debfb62c3f9c..5887752800b55 100644 --- a/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr +++ b/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr @@ -15,5 +15,5 @@ help: consider adding 'move' keyword before the nested closure LL | move || f() // The `nested` closure | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr b/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr index 99c63e4db50d3..121c2e870e7ac 100644 --- a/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr +++ b/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr @@ -10,6 +10,6 @@ LL - *array LL + array | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr b/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr index 967451c68bea1..630d07d652b30 100644 --- a/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr +++ b/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr @@ -12,6 +12,6 @@ LL | greeting = "DEALLOCATED".to_string(); LL | println!("thread result: {:?}", res); | --- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr b/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr index 8fe8fa710643b..e19f37538c16e 100644 --- a/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr +++ b/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr @@ -12,6 +12,6 @@ help: consider assigning a value LL | let e: i32 = 0; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr b/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr index 19f194100a199..466f19eb0ab95 100644 --- a/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr +++ b/tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr @@ -11,6 +11,6 @@ help: you may want to use `iter_mut` here LL | vec.iter_mut().flat_map(|container| container.things()).cloned().collect::>(); | ~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr b/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr index 369a8c61d2c99..87b8e05913528 100644 --- a/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr +++ b/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr @@ -7,6 +7,6 @@ LL | LL | *item = (); | ^^^^^^^^^^ `item` is a `&` reference, so the data it refers to cannot be written -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-7573.stderr b/tests/ui/borrowck/issue-7573.stderr index 9d86286b8676c..07a67474c8310 100644 --- a/tests/ui/borrowck/issue-7573.stderr +++ b/tests/ui/borrowck/issue-7573.stderr @@ -10,6 +10,6 @@ LL | LL | lines_to_use.push(installed_id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/issue-81365-1.stderr b/tests/ui/borrowck/issue-81365-1.stderr index 0d803b0427ace..94566ae195167 100644 --- a/tests/ui/borrowck/issue-81365-1.stderr +++ b/tests/ui/borrowck/issue-81365-1.stderr @@ -15,6 +15,6 @@ note: deref defined here LL | type Target = DerefTarget; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-10.stderr b/tests/ui/borrowck/issue-81365-10.stderr index 2bbde82fafdf4..7681ee68c0f2c 100644 --- a/tests/ui/borrowck/issue-81365-10.stderr +++ b/tests/ui/borrowck/issue-81365-10.stderr @@ -8,6 +8,6 @@ LL | self.container_field = true; LL | first; | ----- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-11.stderr b/tests/ui/borrowck/issue-81365-11.stderr index 5f7e86f11dcd1..f1f28dcceb033 100644 --- a/tests/ui/borrowck/issue-81365-11.stderr +++ b/tests/ui/borrowck/issue-81365-11.stderr @@ -8,6 +8,6 @@ LL | self.container_field = true; LL | first; | ----- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-2.stderr b/tests/ui/borrowck/issue-81365-2.stderr index d9aeaf15f2002..f55da67a85bca 100644 --- a/tests/ui/borrowck/issue-81365-2.stderr +++ b/tests/ui/borrowck/issue-81365-2.stderr @@ -15,6 +15,6 @@ note: deref defined here LL | type Target = DerefTarget; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-3.stderr b/tests/ui/borrowck/issue-81365-3.stderr index 0c0d1994baff2..f1c24640c132f 100644 --- a/tests/ui/borrowck/issue-81365-3.stderr +++ b/tests/ui/borrowck/issue-81365-3.stderr @@ -15,6 +15,6 @@ note: deref defined here LL | type Target = Container; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-4.stderr b/tests/ui/borrowck/issue-81365-4.stderr index 98093daa94520..c0dae0de32819 100644 --- a/tests/ui/borrowck/issue-81365-4.stderr +++ b/tests/ui/borrowck/issue-81365-4.stderr @@ -15,6 +15,6 @@ note: deref defined here LL | type Target = Container; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-5.stderr b/tests/ui/borrowck/issue-81365-5.stderr index 094cec021e469..06c2ea5ab720e 100644 --- a/tests/ui/borrowck/issue-81365-5.stderr +++ b/tests/ui/borrowck/issue-81365-5.stderr @@ -15,6 +15,6 @@ note: deref defined here LL | type Target = DerefTarget; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-6.stderr b/tests/ui/borrowck/issue-81365-6.stderr index e61dc95ecc8fa..e52ebf9382c97 100644 --- a/tests/ui/borrowck/issue-81365-6.stderr +++ b/tests/ui/borrowck/issue-81365-6.stderr @@ -15,6 +15,6 @@ note: deref defined here LL | type Target = [()]; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-7.stderr b/tests/ui/borrowck/issue-81365-7.stderr index 0565127e3875b..1933f5bd8d278 100644 --- a/tests/ui/borrowck/issue-81365-7.stderr +++ b/tests/ui/borrowck/issue-81365-7.stderr @@ -15,6 +15,6 @@ note: deref defined here LL | type Target = DerefTarget; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-8.stderr b/tests/ui/borrowck/issue-81365-8.stderr index 0ca732ff2ae43..ab9f71cc00ce7 100644 --- a/tests/ui/borrowck/issue-81365-8.stderr +++ b/tests/ui/borrowck/issue-81365-8.stderr @@ -15,6 +15,6 @@ note: deref defined here LL | type Target = DerefTarget; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-9.stderr b/tests/ui/borrowck/issue-81365-9.stderr index 4d305268a0b33..f0aefd7ba877e 100644 --- a/tests/ui/borrowck/issue-81365-9.stderr +++ b/tests/ui/borrowck/issue-81365-9.stderr @@ -8,6 +8,6 @@ LL | self.container_field = true; LL | first; | ----- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81899.stderr b/tests/ui/borrowck/issue-81899.stderr index 5ff33933cf095..1da573ea97c19 100644 --- a/tests/ui/borrowck/issue-81899.stderr +++ b/tests/ui/borrowck/issue-81899.stderr @@ -22,6 +22,6 @@ note: erroneous constant encountered LL | const _CONST: &[u8] = &f(&[], |_| {}); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/borrowck/issue-82032.stderr b/tests/ui/borrowck/issue-82032.stderr index f272477a9f5b3..2ac785cd1e3bd 100644 --- a/tests/ui/borrowck/issue-82032.stderr +++ b/tests/ui/borrowck/issue-82032.stderr @@ -9,6 +9,6 @@ LL | for v in self.0.values() { LL | v.flush(); | ^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-82462.stderr b/tests/ui/borrowck/issue-82462.stderr index a2c291f779792..8cb4583eba940 100644 --- a/tests/ui/borrowck/issue-82462.stderr +++ b/tests/ui/borrowck/issue-82462.stderr @@ -17,6 +17,6 @@ help: consider adding semicolon after the expression so its temporaries are drop LL | }; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr b/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr index 26ce007dd346a..4e7a9b695e179 100644 --- a/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr +++ b/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr @@ -7,6 +7,6 @@ LL | LL | *v -= 1; | ^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-83760.fixed b/tests/ui/borrowck/issue-83760.fixed new file mode 100644 index 0000000000000..4544eeb6e1966 --- /dev/null +++ b/tests/ui/borrowck/issue-83760.fixed @@ -0,0 +1,47 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] +#[derive(Clone)] +struct Struct; +#[derive(Clone)] +struct Struct2; +// We use a second one here because otherwise when applying suggestions we'd end up with two +// `#[derive(Clone)]` annotations. + +fn test1() { + let mut val = Some(Struct); + while let Some(ref foo) = val { //~ ERROR use of moved value + if true { + val = None; + } else { + + } + } +} + +fn test2() { + let mut foo = Some(Struct); + let _x = foo.clone().unwrap(); + if true { + foo = Some(Struct); + } else { + } + let _y = foo; //~ ERROR use of moved value: `foo` +} + +fn test3() { + let mut foo = Some(Struct2); + let _x = foo.clone().unwrap(); + if true { + foo = Some(Struct2); + } else if true { + foo = Some(Struct2); + } else if true { + foo = Some(Struct2); + } else if true { + foo = Some(Struct2); + } else { + } + let _y = foo; //~ ERROR use of moved value: `foo` +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-83760.rs b/tests/ui/borrowck/issue-83760.rs index e25b4f727856e..81bfdf0fcc769 100644 --- a/tests/ui/borrowck/issue-83760.rs +++ b/tests/ui/borrowck/issue-83760.rs @@ -1,4 +1,9 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] struct Struct; +struct Struct2; +// We use a second one here because otherwise when applying suggestions we'd end up with two +// `#[derive(Clone)]` annotations. fn test1() { let mut val = Some(Struct); @@ -22,16 +27,16 @@ fn test2() { } fn test3() { - let mut foo = Some(Struct); + let mut foo = Some(Struct2); let _x = foo.unwrap(); if true { - foo = Some(Struct); + foo = Some(Struct2); } else if true { - foo = Some(Struct); + foo = Some(Struct2); } else if true { - foo = Some(Struct); + foo = Some(Struct2); } else if true { - foo = Some(Struct); + foo = Some(Struct2); } else { } let _y = foo; //~ ERROR use of moved value: `foo` diff --git a/tests/ui/borrowck/issue-83760.stderr b/tests/ui/borrowck/issue-83760.stderr index a585bff0c6543..d120adbc03bb3 100644 --- a/tests/ui/borrowck/issue-83760.stderr +++ b/tests/ui/borrowck/issue-83760.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value - --> $DIR/issue-83760.rs:5:20 + --> $DIR/issue-83760.rs:10:20 | LL | while let Some(foo) = val { | ^^^ value moved here, in previous iteration of loop @@ -14,7 +14,7 @@ LL | while let Some(ref foo) = val { | +++ error[E0382]: use of moved value: `foo` - --> $DIR/issue-83760.rs:21:14 + --> $DIR/issue-83760.rs:26:14 | LL | let mut foo = Some(Struct); | ------- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait @@ -29,12 +29,21 @@ LL | let _y = foo; | note: `Option::::unwrap` takes ownership of the receiver `self`, which moves `foo` --> $SRC_DIR/core/src/option.rs:LL:COL +help: you could `clone` the value and consume it, if the `Struct: Clone` trait bound could be satisfied + | +LL | let _x = foo.clone().unwrap(); + | ++++++++ +help: consider annotating `Struct` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Struct; + | error[E0382]: use of moved value: `foo` - --> $DIR/issue-83760.rs:37:14 + --> $DIR/issue-83760.rs:42:14 | -LL | let mut foo = Some(Struct); - | ------- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait +LL | let mut foo = Some(Struct2); + | ------- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait LL | let _x = foo.unwrap(); | -------- `foo` moved due to this method call ... @@ -42,18 +51,27 @@ LL | let _y = foo; | ^^^ value used here after move | note: these 3 reinitializations and 1 other might get skipped - --> $DIR/issue-83760.rs:30:9 + --> $DIR/issue-83760.rs:35:9 | -LL | foo = Some(Struct); - | ^^^^^^^^^^^^^^^^^^ +LL | foo = Some(Struct2); + | ^^^^^^^^^^^^^^^^^^^ LL | } else if true { -LL | foo = Some(Struct); - | ^^^^^^^^^^^^^^^^^^ +LL | foo = Some(Struct2); + | ^^^^^^^^^^^^^^^^^^^ LL | } else if true { -LL | foo = Some(Struct); - | ^^^^^^^^^^^^^^^^^^ +LL | foo = Some(Struct2); + | ^^^^^^^^^^^^^^^^^^^ note: `Option::::unwrap` takes ownership of the receiver `self`, which moves `foo` --> $SRC_DIR/core/src/option.rs:LL:COL +help: you could `clone` the value and consume it, if the `Struct2: Clone` trait bound could be satisfied + | +LL | let _x = foo.clone().unwrap(); + | ++++++++ +help: consider annotating `Struct2` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Struct2; + | error: aborting due to 3 previous errors diff --git a/tests/ui/borrowck/issue-83924.stderr b/tests/ui/borrowck/issue-83924.stderr index 572414df2bf9d..c37de178f2499 100644 --- a/tests/ui/borrowck/issue-83924.stderr +++ b/tests/ui/borrowck/issue-83924.stderr @@ -17,6 +17,6 @@ help: consider creating a fresh reborrow of `v` here LL | for n in &mut *v { | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-85581.stderr b/tests/ui/borrowck/issue-85581.stderr index 29c0429f2a046..80f1f4cb50919 100644 --- a/tests/ui/borrowck/issue-85581.stderr +++ b/tests/ui/borrowck/issue-85581.stderr @@ -12,6 +12,6 @@ LL | Some(_) => { heap.pop(); }, LL | } | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/issue-85765-closure.rs b/tests/ui/borrowck/issue-85765-closure.rs index f2d1dd0fbc3fb..edc9eeaffb5ac 100644 --- a/tests/ui/borrowck/issue-85765-closure.rs +++ b/tests/ui/borrowck/issue-85765-closure.rs @@ -3,6 +3,7 @@ fn main() { let mut test = Vec::new(); let rofl: &Vec> = &mut test; //~^ HELP consider changing this binding's type + //~| HELP you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-85765-closure.stderr b/tests/ui/borrowck/issue-85765-closure.stderr index 936ddd67bcd81..4a6a0e94becd9 100644 --- a/tests/ui/borrowck/issue-85765-closure.stderr +++ b/tests/ui/borrowck/issue-85765-closure.stderr @@ -1,16 +1,21 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference - --> $DIR/issue-85765-closure.rs:6:9 + --> $DIR/issue-85765-closure.rs:7:9 | LL | rofl.push(Vec::new()); | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable | +help: you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior + --> $DIR/issue-85765-closure.rs:4:36 + | +LL | let rofl: &Vec> = &mut test; + | ^^^^^^^^^ help: consider changing this binding's type | LL | let rofl: &mut Vec> = &mut test; | ~~~~~~~~~~~~~~~~~~ error[E0594]: cannot assign to `*r`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:13:9 + --> $DIR/issue-85765-closure.rs:14:9 | LL | *r = 0; | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written @@ -21,7 +26,7 @@ LL | let r = &mut mutvar; | +++ error[E0594]: cannot assign to `*x`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:20:9 + --> $DIR/issue-85765-closure.rs:21:9 | LL | *x = 1; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written @@ -32,7 +37,7 @@ LL | let x: &mut usize = &mut{0}; | ~~~~~~~~~~ error[E0594]: cannot assign to `*y`, which is behind a `&` reference - --> $DIR/issue-85765-closure.rs:27:9 + --> $DIR/issue-85765-closure.rs:28:9 | LL | *y = 1; | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-85765.rs b/tests/ui/borrowck/issue-85765.rs index 76e0b51735416..ce5740bc0e7c1 100644 --- a/tests/ui/borrowck/issue-85765.rs +++ b/tests/ui/borrowck/issue-85765.rs @@ -2,6 +2,7 @@ fn main() { let mut test = Vec::new(); let rofl: &Vec> = &mut test; //~^ HELP consider changing this binding's type + //~| HELP you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-85765.stderr b/tests/ui/borrowck/issue-85765.stderr index 57900bfb612e1..4889f774afa8e 100644 --- a/tests/ui/borrowck/issue-85765.stderr +++ b/tests/ui/borrowck/issue-85765.stderr @@ -1,16 +1,21 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference - --> $DIR/issue-85765.rs:5:5 + --> $DIR/issue-85765.rs:6:5 | LL | rofl.push(Vec::new()); | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable | +help: you can `clone` the `Vec>` value and consume it, but this might not be your desired behavior + --> $DIR/issue-85765.rs:3:32 + | +LL | let rofl: &Vec> = &mut test; + | ^^^^^^^^^ help: consider changing this binding's type | LL | let rofl: &mut Vec> = &mut test; | ~~~~~~~~~~~~~~~~~~ error[E0594]: cannot assign to `*r`, which is behind a `&` reference - --> $DIR/issue-85765.rs:12:5 + --> $DIR/issue-85765.rs:13:5 | LL | *r = 0; | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written @@ -21,7 +26,7 @@ LL | let r = &mut mutvar; | +++ error[E0594]: cannot assign to `*x`, which is behind a `&` reference - --> $DIR/issue-85765.rs:19:5 + --> $DIR/issue-85765.rs:20:5 | LL | *x = 1; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written @@ -32,7 +37,7 @@ LL | let x: &mut usize = &mut{0}; | ~~~~~~~~~~ error[E0594]: cannot assign to `*y`, which is behind a `&` reference - --> $DIR/issue-85765.rs:26:5 + --> $DIR/issue-85765.rs:27:5 | LL | *y = 1; | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-87456-point-to-closure.stderr b/tests/ui/borrowck/issue-87456-point-to-closure.stderr index afd141125ac7c..a15909df07bf7 100644 --- a/tests/ui/borrowck/issue-87456-point-to-closure.stderr +++ b/tests/ui/borrowck/issue-87456-point-to-closure.stderr @@ -15,6 +15,6 @@ help: consider borrowing here LL | let _foo: String = &val; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-88434-minimal-example.stderr b/tests/ui/borrowck/issue-88434-minimal-example.stderr index 7b785b25bd054..b32331ce448e6 100644 --- a/tests/ui/borrowck/issue-88434-minimal-example.stderr +++ b/tests/ui/borrowck/issue-88434-minimal-example.stderr @@ -22,6 +22,6 @@ note: erroneous constant encountered LL | const _CONST: &() = &f(&|_| {}); | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index 9732b8cfa4dad..e3c881dd46503 100644 --- a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -22,6 +22,6 @@ note: erroneous constant encountered LL | const _CONST: &[u8] = &f(&[], |_| {}); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/borrowck/issue-91206.rs b/tests/ui/borrowck/issue-91206.rs index e062a253767de..c60ac62fa3477 100644 --- a/tests/ui/borrowck/issue-91206.rs +++ b/tests/ui/borrowck/issue-91206.rs @@ -10,6 +10,7 @@ fn main() { let client = TestClient; let inner = client.get_inner_ref(); //~^ HELP consider specifying this binding's type + //~| HELP you can `clone` the `Vec` value and consume it, but this might not be your desired behavior inner.clear(); //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] //~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-91206.stderr b/tests/ui/borrowck/issue-91206.stderr index 30f83656518dc..e3dd65b64197a 100644 --- a/tests/ui/borrowck/issue-91206.stderr +++ b/tests/ui/borrowck/issue-91206.stderr @@ -1,14 +1,19 @@ error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference - --> $DIR/issue-91206.rs:13:5 + --> $DIR/issue-91206.rs:14:5 | LL | inner.clear(); | ^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable | +help: you can `clone` the `Vec` value and consume it, but this might not be your desired behavior + --> $DIR/issue-91206.rs:11:17 + | +LL | let inner = client.get_inner_ref(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider specifying this binding's type | LL | let inner: &mut Vec = client.get_inner_ref(); | +++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-92015.stderr b/tests/ui/borrowck/issue-92015.stderr index ea4f9abb87d9a..167a5cf5863c6 100644 --- a/tests/ui/borrowck/issue-92015.stderr +++ b/tests/ui/borrowck/issue-92015.stderr @@ -9,6 +9,6 @@ help: consider specifying this binding's type LL | let foo: &mut i32 = Some(&0).unwrap(); | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-92157.stderr b/tests/ui/borrowck/issue-92157.stderr index a46b1288911dc..0ffedccd6906d 100644 --- a/tests/ui/borrowck/issue-92157.stderr +++ b/tests/ui/borrowck/issue-92157.stderr @@ -7,6 +7,6 @@ LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isi = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _` found signature `fn(fn() -> T, isize, *const *const u8) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/borrowck/issue-93078.stderr b/tests/ui/borrowck/issue-93078.stderr index bcbcbe724127f..446b4582bfb9d 100644 --- a/tests/ui/borrowck/issue-93078.stderr +++ b/tests/ui/borrowck/issue-93078.stderr @@ -7,6 +7,6 @@ LL | self.modify(); = note: as `Self` may be unsized, this call attempts to take `&mut &mut self` = note: however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-93093.stderr b/tests/ui/borrowck/issue-93093.stderr index afa76594f0b5e..b6a2768b61da3 100644 --- a/tests/ui/borrowck/issue-93093.stderr +++ b/tests/ui/borrowck/issue-93093.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | async fn bar(&mut self) { | ~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/many-mutable-borrows.stderr b/tests/ui/borrowck/many-mutable-borrows.stderr index 0f808ac92761b..bc2ba987c9dc8 100644 --- a/tests/ui/borrowck/many-mutable-borrows.stderr +++ b/tests/ui/borrowck/many-mutable-borrows.stderr @@ -28,6 +28,6 @@ help: consider changing this to be mutable LL | let mut v = Vec::new(); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr index 38dba94bdd41b..0d5edadcb4641 100644 --- a/tests/ui/borrowck/move-error-in-promoted-2.stderr +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -7,6 +7,6 @@ LL | &([S][0],); | cannot move out of here | move occurs because value has type `S`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/borrowck/move-error-in-promoted.stderr b/tests/ui/borrowck/move-error-in-promoted.stderr index a4432e38da0e4..03c0297c5a980 100644 --- a/tests/ui/borrowck/move-error-in-promoted.stderr +++ b/tests/ui/borrowck/move-error-in-promoted.stderr @@ -7,6 +7,6 @@ LL | let _ = S1(C[0]).clone(); | cannot move out of here | move occurs because value has type `S2`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 8ac711e9e59db..83f9e19aa0d5c 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -15,6 +15,6 @@ help: consider borrowing here LL | let a = &$c; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr b/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr index 55948afca733b..bfbae5be050a8 100644 --- a/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr +++ b/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr @@ -10,6 +10,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | if let Some(ref mut _x) = opt {} | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr index 74e7067c9afaa..7b9a946f3ca3e 100644 --- a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr +++ b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr @@ -20,6 +20,6 @@ help: consider creating a fresh reborrow of `value` here LL | Other::handle(&mut *value); | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr index ecd916a59fcbd..8590dd9ca3d07 100644 --- a/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr +++ b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr @@ -16,6 +16,6 @@ help: consider creating a fresh reborrow of `state` here LL | for _ in &mut *state {} | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/regions-escape-bound-fn-2.stderr b/tests/ui/borrowck/regions-escape-bound-fn-2.stderr index 14393bc8eeede..9c070de445710 100644 --- a/tests/ui/borrowck/regions-escape-bound-fn-2.stderr +++ b/tests/ui/borrowck/regions-escape-bound-fn-2.stderr @@ -8,6 +8,6 @@ LL | with_int(|y| x = Some(y)); | | | `y` is a reference that is only valid in the closure body -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/regions-escape-bound-fn.stderr b/tests/ui/borrowck/regions-escape-bound-fn.stderr index a23fdacdee641..868ba9c89be2f 100644 --- a/tests/ui/borrowck/regions-escape-bound-fn.stderr +++ b/tests/ui/borrowck/regions-escape-bound-fn.stderr @@ -8,6 +8,6 @@ LL | with_int(|y| x = Some(y)); | | | `y` is a reference that is only valid in the closure body -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/regions-escape-unboxed-closure.stderr b/tests/ui/borrowck/regions-escape-unboxed-closure.stderr index 153f77c8913ac..c861f772be0d3 100644 --- a/tests/ui/borrowck/regions-escape-unboxed-closure.stderr +++ b/tests/ui/borrowck/regions-escape-unboxed-closure.stderr @@ -8,6 +8,6 @@ LL | with_int(&mut |y| x = Some(y)); | | | `y` is a reference that is only valid in the closure body -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/return-local-binding-from-desugaring.stderr b/tests/ui/borrowck/return-local-binding-from-desugaring.stderr index 9f952542e18b0..1f4a548a4cb05 100644 --- a/tests/ui/borrowck/return-local-binding-from-desugaring.stderr +++ b/tests/ui/borrowck/return-local-binding-from-desugaring.stderr @@ -7,6 +7,6 @@ LL | for ref x in xs { LL | result | ^^^^^^ returns a value referencing data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr b/tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr index bada08368fc6b..1e98006a9a71e 100644 --- a/tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr +++ b/tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr @@ -9,6 +9,10 @@ LL | cb.map(|cb| cb()); | note: `Option::::map` takes ownership of the receiver `self`, which moves `*cb` --> $SRC_DIR/core/src/option.rs:LL:COL +help: you could `clone` the value and consume it, if the `&mut dyn FnMut(): Clone` trait bound could be satisfied + | +LL | as Clone>::clone(&cb).map(|cb| cb()); + | ++++++++++++++++++++++++++++++++++++++++++++ + error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference --> $DIR/suggest-as-ref-on-mut-closure.rs:12:26 diff --git a/tests/ui/borrowck/suggest-local-var-for-vector.stderr b/tests/ui/borrowck/suggest-local-var-for-vector.stderr index c8d00f7b2227d..d88e8b09687db 100644 --- a/tests/ui/borrowck/suggest-local-var-for-vector.stderr +++ b/tests/ui/borrowck/suggest-local-var-for-vector.stderr @@ -19,6 +19,6 @@ help: ...and then using that local here LL | vec[vec.len() - 1] = 123; | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/suggest-mut-iterator.stderr b/tests/ui/borrowck/suggest-mut-iterator.stderr index 77f991a9a61c6..b396bb7b5ec4c 100644 --- a/tests/ui/borrowck/suggest-mut-iterator.stderr +++ b/tests/ui/borrowck/suggest-mut-iterator.stderr @@ -11,6 +11,6 @@ help: use a mutable iterator instead LL | for test in &mut tests { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/suggest-storing-local-var-for-vector.stderr b/tests/ui/borrowck/suggest-storing-local-var-for-vector.stderr index 368d728101c27..a69a025cbcbc0 100644 --- a/tests/ui/borrowck/suggest-storing-local-var-for-vector.stderr +++ b/tests/ui/borrowck/suggest-storing-local-var-for-vector.stderr @@ -19,6 +19,6 @@ help: ...and then using that local here LL | vec[vec.len() - 1] = 123; | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/tainted-promoteds.stderr b/tests/ui/borrowck/tainted-promoteds.stderr index b276ea9acebe9..a5c448fdcdbef 100644 --- a/tests/ui/borrowck/tainted-promoteds.stderr +++ b/tests/ui/borrowck/tainted-promoteds.stderr @@ -9,6 +9,6 @@ LL | let a = 0; LL | a = &0 * &1 * &2 * &3; | ^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/borrowck/two-phase-across-loop.stderr b/tests/ui/borrowck/two-phase-across-loop.stderr index d7c0210cc77fa..bd63fc9612644 100644 --- a/tests/ui/borrowck/two-phase-across-loop.stderr +++ b/tests/ui/borrowck/two-phase-across-loop.stderr @@ -6,6 +6,6 @@ LL | strings.push(foo.get_string()); | | | first borrow used here, in later iteration of loop -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr b/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr index 2c3f1c18a0847..6a3e0db4be630 100644 --- a/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr +++ b/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr @@ -9,6 +9,6 @@ LL | LL | vec.push(2); | ^^^^^^^^^^^ mutable borrow occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr b/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr index e3e4057d6a789..b1e4392989fee 100644 --- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr +++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr @@ -10,6 +10,6 @@ LL | delay = &mut vec; LL | shared[0]; | ------ immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/two-phase-sneaky.stderr b/tests/ui/borrowck/two-phase-sneaky.stderr index 4db970c1da06a..4f1712ccc0094 100644 --- a/tests/ui/borrowck/two-phase-sneaky.stderr +++ b/tests/ui/borrowck/two-phase-sneaky.stderr @@ -9,6 +9,6 @@ LL | LL | v.push(format!("foo")); | ^ second mutable borrow occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr index 9f9d4bd8d6c05..b3bf2f924fc3e 100644 --- a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr +++ b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr @@ -77,6 +77,8 @@ LL | reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); | | | immutable borrow occurs here | | cast requires that `reg.sess_mut` is borrowed for `'a` | mutable borrow occurs here + | + = note: due to object lifetime defaults, `Box LateLintPass<'b>>` actually means `Box<(dyn for<'b> LateLintPass<'b> + 'static)>` error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable --> $DIR/two-phase-surprise-no-conflict.rs:144:5 @@ -119,6 +121,8 @@ LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); | | | first mutable borrow occurs here | | cast requires that `reg.sess_mut` is borrowed for `'a` | second mutable borrow occurs here + | + = note: due to object lifetime defaults, `Box LateLintPass<'b>>` actually means `Box<(dyn for<'b> LateLintPass<'b> + 'static)>` error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:158:53 diff --git a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed index b0c5376105b28..85acafd88f671 100644 --- a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed +++ b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed @@ -9,7 +9,7 @@ fn call(f: F) where F : Fn() { fn main() { let y = vec![format!("World")]; call(|| { - y.clone().into_iter(); + as Clone>::clone(&y).into_iter(); //~^ ERROR cannot move out of `y`, a captured variable in an `Fn` closure }); } diff --git a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index a2f6365b74e60..a2ff70255f575 100644 --- a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -14,9 +14,9 @@ note: `into_iter` takes ownership of the receiver `self`, which moves `y` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL help: you can `clone` the value and consume it, but this might not be your desired behavior | -LL | y.clone().into_iter(); - | ++++++++ +LL | as Clone>::clone(&y).into_iter(); + | +++++++++++++++++++++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/box/alloc-unstable-fail.stderr b/tests/ui/box/alloc-unstable-fail.stderr index 03ae36e889016..352efce318f3f 100644 --- a/tests/ui/box/alloc-unstable-fail.stderr +++ b/tests/ui/box/alloc-unstable-fail.stderr @@ -7,6 +7,6 @@ LL | let _boxed: Box = Box::new(10); = note: see issue #32838 for more information = help: add `#![feature(allocator_api)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/box/issue-82446.stderr b/tests/ui/box/issue-82446.stderr index c03f35884b8a4..568d23c2cb791 100644 --- a/tests/ui/box/issue-82446.stderr +++ b/tests/ui/box/issue-82446.stderr @@ -7,6 +7,6 @@ LL | val = note: expected struct `Box<(dyn MyTrait + 'static)>` found reference `&Box<(dyn MyTrait + 'static)>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr index feda8841fc8d1..8b8cea3fe8491 100644 --- a/tests/ui/box/leak-alloc.stderr +++ b/tests/ui/box/leak-alloc.stderr @@ -12,6 +12,6 @@ LL | LL | use_value(*theref) | ------- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/box/unit/unique-object-noncopyable.stderr b/tests/ui/box/unit/unique-object-noncopyable.stderr index db42ed9baf1ed..1b98d09ccddb0 100644 --- a/tests/ui/box/unit/unique-object-noncopyable.stderr +++ b/tests/ui/box/unit/unique-object-noncopyable.stderr @@ -20,6 +20,6 @@ LL | let _z = y.clone(); `dyn Foo: Clone` which is required by `Box: Clone` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/box/unit/unique-pinned-nocopy.stderr b/tests/ui/box/unit/unique-pinned-nocopy.stderr index 2fd5b0d82e8fa..d662a2d6d0512 100644 --- a/tests/ui/box/unit/unique-pinned-nocopy.stderr +++ b/tests/ui/box/unit/unique-pinned-nocopy.stderr @@ -23,6 +23,6 @@ LL + #[derive(Clone)] LL | struct R { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/btreemap/btreemap-index-mut-2.stderr b/tests/ui/btreemap/btreemap-index-mut-2.stderr index c8d4fd59550f0..0b8c77cb9e104 100644 --- a/tests/ui/btreemap/btreemap-index-mut-2.stderr +++ b/tests/ui/btreemap/btreemap-index-mut-2.stderr @@ -14,6 +14,6 @@ LL | map.get_mut(&0).map(|val| { *val = 1; }); LL | let val = map.entry(&0).or_insert(1); | +++++++++ ~~~~~~~ ~~~~~~~~~~~~ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/btreemap/btreemap-index-mut.stderr b/tests/ui/btreemap/btreemap-index-mut.stderr index 26f2a4c4b2914..cc465fbf3def8 100644 --- a/tests/ui/btreemap/btreemap-index-mut.stderr +++ b/tests/ui/btreemap/btreemap-index-mut.stderr @@ -14,6 +14,6 @@ LL | map.get_mut(&0).map(|val| { *val = 1; }); LL | let val = map.entry(&0).or_insert(1); | +++++++++ ~~~~~~~ ~~~~~~~~~~~~ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/btreemap/btreemap_dropck.stderr b/tests/ui/btreemap/btreemap_dropck.stderr index d405e465aaeea..805c2112bdc10 100644 --- a/tests/ui/btreemap/btreemap_dropck.stderr +++ b/tests/ui/btreemap/btreemap_dropck.stderr @@ -10,6 +10,6 @@ LL | drop(s); LL | } | - borrow might be used here, when `_map` is dropped and runs the `Drop` code for type `BTreeMap` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index f9d548bb8fbe9..251651df4f908 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -19,6 +19,6 @@ help: consider further restricting this bound LL | impl RequiresRequiresShareAndSend for X { } | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr index 0e2c6c60b6e3a..d0102635315f1 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr @@ -17,6 +17,6 @@ help: consider adding an explicit lifetime bound LL | impl Foo for T { } | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr index 8b19170b0f100..7579bffc72d7b 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr @@ -11,6 +11,6 @@ note: required by a bound in `Foo` LL | trait Foo : Send { } | ^^^^ required by this bound in `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr index 0cfea72d5f184..4a25c42b5835d 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr @@ -14,6 +14,6 @@ help: consider further restricting this bound LL | impl Foo for T { } | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/c-variadic/issue-32201.stderr b/tests/ui/c-variadic/issue-32201.stderr index cedb58784662e..352db9f62f6d8 100644 --- a/tests/ui/c-variadic/issue-32201.stderr +++ b/tests/ui/c-variadic/issue-32201.stderr @@ -4,6 +4,6 @@ error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function LL | foo(0, bar); | ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0617`. diff --git a/tests/ui/c-variadic/issue-86053-2.stderr b/tests/ui/c-variadic/issue-86053-2.stderr index 815b06e770890..2c4be2522f614 100644 --- a/tests/ui/c-variadic/issue-86053-2.stderr +++ b/tests/ui/c-variadic/issue-86053-2.stderr @@ -11,6 +11,6 @@ note: but the referenced data is only valid for the lifetime `'a` as defined her LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr index 8884fc6fb2af7..d0ca7034ba1c1 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.stderr +++ b/tests/ui/c-variadic/variadic-ffi-2.stderr @@ -4,6 +4,6 @@ error[E0045]: C-variadic function must have a compatible calling convention, lik LL | fn baz(f: extern "stdcall" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0045`. diff --git a/tests/ui/c-variadic/variadic-ffi-6.stderr b/tests/ui/c-variadic/variadic-ffi-6.stderr index 4c7792d965019..1ceff5704786d 100644 --- a/tests/ui/c-variadic/variadic-ffi-6.stderr +++ b/tests/ui/c-variadic/variadic-ffi-6.stderr @@ -10,6 +10,6 @@ help: consider using the `'static` lifetime LL | ) -> &'static usize { | +++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/tests/ui/c-variadic/variadic-ffi-no-fixed-args.stderr index e11ba43ca2a9a..e268ef3fa6814 100644 --- a/tests/ui/c-variadic/variadic-ffi-no-fixed-args.stderr +++ b/tests/ui/c-variadic/variadic-ffi-no-fixed-args.stderr @@ -4,5 +4,5 @@ error: C-variadic function must be declared with at least one named argument LL | fn foo(...); | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/capture1.stderr b/tests/ui/capture1.stderr index ad8434709d5eb..067b85ba61913 100644 --- a/tests/ui/capture1.stderr +++ b/tests/ui/capture1.stderr @@ -6,6 +6,6 @@ LL | fn foo() -> isize { return bar; } | = help: use the `|| { ... }` closure form instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/cast/cast-errors-issue-43825.stderr b/tests/ui/cast/cast-errors-issue-43825.stderr index 1e77f5dbdc643..658d5ddbb611c 100644 --- a/tests/ui/cast/cast-errors-issue-43825.stderr +++ b/tests/ui/cast/cast-errors-issue-43825.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `error` in this scope LL | let error = error; | ^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/cast/cast-from-nil.stderr b/tests/ui/cast/cast-from-nil.stderr index dab133cfb4b67..991ff93a8bd0d 100644 --- a/tests/ui/cast/cast-from-nil.stderr +++ b/tests/ui/cast/cast-from-nil.stderr @@ -4,6 +4,6 @@ error[E0605]: non-primitive cast: `()` as `u32` LL | fn main() { let u = (assert!(true) as u32); } | ^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/cast-macro-lhs.stderr b/tests/ui/cast/cast-macro-lhs.stderr index db7ce57e15062..83c6cf31faae2 100644 --- a/tests/ui/cast/cast-macro-lhs.stderr +++ b/tests/ui/cast/cast-macro-lhs.stderr @@ -6,6 +6,6 @@ LL | let x = foo!() as *const [u8]; | | | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/cast-rfc0401-2.stderr b/tests/ui/cast/cast-rfc0401-2.stderr index dd90c3a97231a..b7fb420533e65 100644 --- a/tests/ui/cast/cast-rfc0401-2.stderr +++ b/tests/ui/cast/cast-rfc0401-2.stderr @@ -9,6 +9,6 @@ help: compare with zero instead LL | let _ = 3 != 0; | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0054`. diff --git a/tests/ui/cast/cast-to-nil.stderr b/tests/ui/cast/cast-to-nil.stderr index 29a9baffd71d7..14c75983b94c2 100644 --- a/tests/ui/cast/cast-to-nil.stderr +++ b/tests/ui/cast/cast-to-nil.stderr @@ -4,6 +4,6 @@ error[E0605]: non-primitive cast: `u32` as `()` LL | fn main() { let u = 0u32 as (); } | ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/casts-differing-anon.stderr b/tests/ui/cast/casts-differing-anon.stderr index f9abfb5225f91..8ddd97137c30d 100644 --- a/tests/ui/cast/casts-differing-anon.stderr +++ b/tests/ui/cast/casts-differing-anon.stderr @@ -6,6 +6,6 @@ LL | b_raw = f_raw as *mut _; | = note: vtable kinds may not match -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/casts-issue-46365.stderr b/tests/ui/cast/casts-issue-46365.stderr index 84175473696df..84bc73a9b7862 100644 --- a/tests/ui/cast/casts-issue-46365.stderr +++ b/tests/ui/cast/casts-issue-46365.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Ipsum` in this scope LL | ipsum: Ipsum | ^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/cast/issue-10991.stderr b/tests/ui/cast/issue-10991.stderr index 5b8a182338693..52afc8343e1eb 100644 --- a/tests/ui/cast/issue-10991.stderr +++ b/tests/ui/cast/issue-10991.stderr @@ -4,6 +4,6 @@ error[E0605]: non-primitive cast: `()` as `usize` LL | let _t = nil as usize; | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/issue-17444.stderr b/tests/ui/cast/issue-17444.stderr index 1097079dfc1d1..0d4f6f194318e 100644 --- a/tests/ui/cast/issue-17444.stderr +++ b/tests/ui/cast/issue-17444.stderr @@ -4,6 +4,6 @@ error[E0606]: casting `Test` as `*const isize` is invalid LL | let _x = Test::Foo as *const isize; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/issue-85586.stderr b/tests/ui/cast/issue-85586.stderr index ed8a6fc62e9dd..847a5527dda1d 100644 --- a/tests/ui/cast/issue-85586.stderr +++ b/tests/ui/cast/issue-85586.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | let b = (a + 1) as usize; | ^^^^^^^ cannot infer type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/cast/issue-88621.stderr b/tests/ui/cast/issue-88621.stderr index 886145c1bafee..0459ce5eabde5 100644 --- a/tests/ui/cast/issue-88621.stderr +++ b/tests/ui/cast/issue-88621.stderr @@ -4,6 +4,6 @@ error[E0605]: non-primitive cast: `Kind2` as `u8` LL | let _ = Kind2::Foo() as u8; | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/issue-89497.stderr b/tests/ui/cast/issue-89497.stderr index bf3c3537fade1..1208ca45d50ea 100644 --- a/tests/ui/cast/issue-89497.stderr +++ b/tests/ui/cast/issue-89497.stderr @@ -10,6 +10,6 @@ LL - let _reference: &'static i32 = unsafe { pointer as *const i32 as &'stat LL + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) }; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/unsized-struct-cast.stderr b/tests/ui/cast/unsized-struct-cast.stderr index 79b3d973c32fd..47a51d8465255 100644 --- a/tests/ui/cast/unsized-struct-cast.stderr +++ b/tests/ui/cast/unsized-struct-cast.stderr @@ -4,6 +4,6 @@ error[E0606]: casting `&[_; 0]` as `*const Data` is invalid LL | const _: *const Data = &[] as *const Data; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/unsupported-cast.stderr b/tests/ui/cast/unsupported-cast.stderr index 56a375a1d942a..2c4951ec7b186 100644 --- a/tests/ui/cast/unsupported-cast.stderr +++ b/tests/ui/cast/unsupported-cast.stderr @@ -4,6 +4,6 @@ error[E0606]: casting `f64` as `*const A` is invalid LL | println!("{:?}", 1.0 as *const A); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cenum_impl_drop_cast.stderr b/tests/ui/cenum_impl_drop_cast.stderr index b3f921c14edbc..541d15d021d3f 100644 --- a/tests/ui/cenum_impl_drop_cast.stderr +++ b/tests/ui/cenum_impl_drop_cast.stderr @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![deny(cenum_impl_drop_cast)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: error: cannot cast enum `E` into integer `u32` because it implements `Drop` diff --git a/tests/ui/cfg/conditional-compile-arch.rs b/tests/ui/cfg/conditional-compile-arch.rs index e59e06f801b78..c6ecf4807364d 100644 --- a/tests/ui/cfg/conditional-compile-arch.rs +++ b/tests/ui/cfg/conditional-compile-arch.rs @@ -28,9 +28,6 @@ pub fn main() { } #[cfg(target_arch = "s390x")] pub fn main() { } -#[cfg(target_arch = "asmjs")] -pub fn main() { } - #[cfg(target_arch = "wasm32")] pub fn main() { } diff --git a/tests/ui/cfg/diagnostics-not-a-def.stderr b/tests/ui/cfg/diagnostics-not-a-def.stderr index af0e1a1727579..6941f850e5f70 100644 --- a/tests/ui/cfg/diagnostics-not-a-def.stderr +++ b/tests/ui/cfg/diagnostics-not-a-def.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `i_am_not` in module `inner` LL | inner::i_am_not(); | ^^^^^^^^ not found in `inner` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr index b0c459fabf8eb..19d9443d477a4 100644 --- a/tests/ui/check-cfg/allow-same-level.stderr +++ b/tests/ui/check-cfg/allow-same-level.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE` LL | #[cfg(FALSE)] | ^^^^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs new file mode 100644 index 0000000000000..ea48c6ea20154 --- /dev/null +++ b/tests/ui/check-cfg/cargo-feature.rs @@ -0,0 +1,14 @@ +// This test checks that when no features are passed by Cargo we +// suggest adding some in the Cargo.toml instead of vomitting a +// list of all the expected names +// +// check-pass +// rustc-env:CARGO=/usr/bin/cargo +// compile-flags: --check-cfg=cfg() -Z unstable-options +// error-pattern:Cargo.toml + +#[cfg(feature = "serde")] +//~^ WARNING unexpected `cfg` condition name +fn ser() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cargo-feature.stderr b/tests/ui/check-cfg/cargo-feature.stderr new file mode 100644 index 0000000000000..619410a28f370 --- /dev/null +++ b/tests/ui/check-cfg/cargo-feature.stderr @@ -0,0 +1,11 @@ +warning: unexpected `cfg` condition name: `feature` + --> $DIR/cargo-feature.rs:10:7 + | +LL | #[cfg(feature = "serde")] + | ^^^^^^^^^^^^^^^^^ + | + = help: consider defining some features in `Cargo.toml` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr index b0228774b751b..ffde972a25ef8 100644 --- a/tests/ui/check-cfg/compact-names.stderr +++ b/tests/ui/check-cfg/compact-names.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `target_architecture` LL | #[cfg(target(os = "linux", architecture = "arm"))] | ^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index 53ccc0f4d317e..9efc77fb43f1b 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -1,14 +1,14 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names-values.rs:12:7 + --> $DIR/exhaustive-names-values.rs:10:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-names-values.rs:16:7 + --> $DIR/exhaustive-names-values.rs:14:7 | LL | #[cfg(test = "value")] | ^^^^---------- @@ -17,9 +17,17 @@ LL | #[cfg(test = "value")] | = note: no expected value for `test` -warning: unexpected `empty_cfg` as condition name +warning: unexpected `cfg` condition name: `feature` + --> $DIR/exhaustive-names-values.rs:18:7 | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected names +LL | #[cfg(feature = "unk")] + | ^^^^^^^^^^^^^^^ -warning: 3 warnings emitted +warning: unexpected `cfg` condition name: `feature` + --> $DIR/exhaustive-names-values.rs:25:7 + | +LL | #[cfg(feature = "std")] + | ^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr index 5e8b74054ceb6..971abb1a21a41 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr @@ -1,14 +1,14 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names-values.rs:12:7 + --> $DIR/exhaustive-names-values.rs:11:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-names-values.rs:16:7 + --> $DIR/exhaustive-names-values.rs:15:7 | LL | #[cfg(test = "value")] | ^^^^---------- @@ -17,9 +17,17 @@ LL | #[cfg(test = "value")] | = note: no expected value for `test` -warning: unexpected `empty_names_values` as condition name +warning: unexpected `cfg` condition name: `feature` + --> $DIR/exhaustive-names-values.rs:19:7 | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected names +LL | #[cfg(feature = "unk")] + | ^^^^^^^^^^^^^^^ -warning: 3 warnings emitted +warning: unexpected `cfg` condition name: `feature` + --> $DIR/exhaustive-names-values.rs:26:7 + | +LL | #[cfg(feature = "std")] + | ^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index 7705a665eb77e..4549482abcb91 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names-values.rs:12:7 + --> $DIR/exhaustive-names-values.rs:10:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #[cfg(unknown_key = "value")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-names-values.rs:16:7 + --> $DIR/exhaustive-names-values.rs:14:7 | LL | #[cfg(test = "value")] | ^^^^---------- @@ -18,16 +18,12 @@ LL | #[cfg(test = "value")] = note: no expected value for `test` warning: unexpected `cfg` condition value: `unk` - --> $DIR/exhaustive-names-values.rs:20:7 + --> $DIR/exhaustive-names-values.rs:18:7 | LL | #[cfg(feature = "unk")] | ^^^^^^^^^^^^^^^ | = note: expected values for `feature` are: `std` -warning: unexpected condition value `` for condition name `feature` - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected values - -warning: 4 warnings emitted +warning: 3 warnings emitted diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index f0224a2e33c75..4549482abcb91 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names-values.rs:12:7 + --> $DIR/exhaustive-names-values.rs:10:7 | LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #[cfg(unknown_key = "value")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-names-values.rs:16:7 + --> $DIR/exhaustive-names-values.rs:14:7 | LL | #[cfg(test = "value")] | ^^^^---------- @@ -18,16 +18,12 @@ LL | #[cfg(test = "value")] = note: no expected value for `test` warning: unexpected `cfg` condition value: `unk` - --> $DIR/exhaustive-names-values.rs:20:7 + --> $DIR/exhaustive-names-values.rs:18:7 | LL | #[cfg(feature = "unk")] | ^^^^^^^^^^^^^^^ | = note: expected values for `feature` are: `std` -warning: unexpected `full` as condition name - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected names - -warning: 4 warnings emitted +warning: 3 warnings emitted diff --git a/tests/ui/check-cfg/exhaustive-names-values.rs b/tests/ui/check-cfg/exhaustive-names-values.rs index f553d93cae2a3..956992a1e777d 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.rs +++ b/tests/ui/check-cfg/exhaustive-names-values.rs @@ -1,10 +1,8 @@ -// Check warning for unexpected cfg in the code and in the CLI -// arguments (here the revision cfg). +// Check warning for unexpected cfg in the code. // // check-pass -// revisions: empty_names_values empty_cfg feature full +// revisions: empty_cfg feature full // compile-flags: -Z unstable-options -// [empty_names_values]compile-flags: --check-cfg=names() --check-cfg=values() // [empty_cfg]compile-flags: --check-cfg=cfg() // [feature]compile-flags: --check-cfg=cfg(feature,values("std")) // [full]compile-flags: --check-cfg=cfg(feature,values("std")) --check-cfg=cfg() @@ -18,11 +16,15 @@ pub fn f() {} pub fn f() {} #[cfg(feature = "unk")] -//[feature]~^ WARNING unexpected `cfg` condition value -//[full]~^^ WARNING unexpected `cfg` condition value +//[empty_names_values]~^ WARNING unexpected `cfg` condition name +//[empty_cfg]~^^ WARNING unexpected `cfg` condition name +//[feature]~^^^ WARNING unexpected `cfg` condition value +//[full]~^^^^ WARNING unexpected `cfg` condition value pub fn feat() {} #[cfg(feature = "std")] +//[empty_names_values]~^ WARNING unexpected `cfg` condition name +//[empty_cfg]~^^ WARNING unexpected `cfg` condition name pub fn feat() {} #[cfg(windows)] diff --git a/tests/ui/check-cfg/exhaustive-names.empty_names.stderr b/tests/ui/check-cfg/exhaustive-names.empty_names.stderr deleted file mode 100644 index 6190ff71464c5..0000000000000 --- a/tests/ui/check-cfg/exhaustive-names.empty_names.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: unexpected `cfg` condition name: `unknown_key` - --> $DIR/exhaustive-names.rs:8:7 - | -LL | #[cfg(unknown_key = "value")] - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` - = note: `#[warn(unexpected_cfgs)]` on by default - -warning: unexpected `empty_names` as condition name - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected names - -warning: 2 warnings emitted - diff --git a/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr index f338434cd299d..7d01c73cc09b5 100644 --- a/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr +++ b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr @@ -4,12 +4,8 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = note: `#[warn(unexpected_cfgs)]` on by default -warning: unexpected `exhaustive_names` as condition name - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected names - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/check-cfg/exhaustive-names.rs b/tests/ui/check-cfg/exhaustive-names.rs index b86a7f84eb4b3..8066802069957 100644 --- a/tests/ui/check-cfg/exhaustive-names.rs +++ b/tests/ui/check-cfg/exhaustive-names.rs @@ -1,9 +1,7 @@ // Check warning for unexpected cfg // // check-pass -// revisions: empty_names exhaustive_names -// [empty_names]compile-flags: --check-cfg=names() -Z unstable-options -// [exhaustive_names]compile-flags: --check-cfg=cfg() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[cfg(unknown_key = "value")] //~^ WARNING unexpected `cfg` condition name diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr new file mode 100644 index 0000000000000..866595b1213cb --- /dev/null +++ b/tests/ui/check-cfg/exhaustive-names.stderr @@ -0,0 +1,11 @@ +warning: unexpected `cfg` condition name: `unknown_key` + --> $DIR/exhaustive-names.rs:6:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr index 999b270284979..745646bda1c9f 100644 --- a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-values.rs:9:7 + --> $DIR/exhaustive-values.rs:8:7 | LL | #[cfg(test = "value")] | ^^^^---------- @@ -9,9 +9,5 @@ LL | #[cfg(test = "value")] = note: no expected value for `test` = note: `#[warn(unexpected_cfgs)]` on by default -warning: unexpected `empty_cfg` as condition name - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected names - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/check-cfg/exhaustive-values.empty_values.stderr b/tests/ui/check-cfg/exhaustive-values.empty_values.stderr deleted file mode 100644 index 77ddc35100ae3..0000000000000 --- a/tests/ui/check-cfg/exhaustive-values.empty_values.stderr +++ /dev/null @@ -1,13 +0,0 @@ -warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-values.rs:9:7 - | -LL | #[cfg(test = "value")] - | ^^^^---------- - | | - | help: remove the value - | - = note: no expected value for `test` - = note: `#[warn(unexpected_cfgs)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/check-cfg/exhaustive-values.rs b/tests/ui/check-cfg/exhaustive-values.rs index 8a1689ba86b5f..430d3b89e7abd 100644 --- a/tests/ui/check-cfg/exhaustive-values.rs +++ b/tests/ui/check-cfg/exhaustive-values.rs @@ -1,8 +1,7 @@ // Check warning for unexpected cfg value // // check-pass -// revisions: empty_values empty_cfg without_names -// [empty_values]compile-flags: --check-cfg=values() -Z unstable-options +// revisions: empty_cfg without_names // [empty_cfg]compile-flags: --check-cfg=cfg() -Z unstable-options // [without_names]compile-flags: --check-cfg=cfg(any()) -Z unstable-options diff --git a/tests/ui/check-cfg/exhaustive-values.without_names.stderr b/tests/ui/check-cfg/exhaustive-values.without_names.stderr index 77ddc35100ae3..745646bda1c9f 100644 --- a/tests/ui/check-cfg/exhaustive-values.without_names.stderr +++ b/tests/ui/check-cfg/exhaustive-values.without_names.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `value` - --> $DIR/exhaustive-values.rs:9:7 + --> $DIR/exhaustive-values.rs:8:7 | LL | #[cfg(test = "value")] | ^^^^---------- diff --git a/tests/ui/check-cfg/invalid-arguments.names_simple_ident.stderr b/tests/ui/check-cfg/invalid-arguments.names_simple_ident.stderr deleted file mode 100644 index 8fadcc1f9f06c..0000000000000 --- a/tests/ui/check-cfg/invalid-arguments.names_simple_ident.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: invalid `--check-cfg` argument: `names("NOT_IDENT")` (`names()` arguments must be simple identifiers) - diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index a56f48e0af93d..90c62fa38070d 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -1,7 +1,7 @@ // Check that invalid --check-cfg are rejected // // check-fail -// revisions: anything_else names_simple_ident values_simple_ident values_string_literals +// revisions: anything_else // revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values // revisions: multiple_values_any not_empty_any not_empty_values_any // revisions: values_any_missing_values values_any_before_ident ident_in_values_1 @@ -10,9 +10,6 @@ // // compile-flags: -Z unstable-options // [anything_else]compile-flags: --check-cfg=anything_else(...) -// [names_simple_ident]compile-flags: --check-cfg=names("NOT_IDENT") -// [values_simple_ident]compile-flags: --check-cfg=values("NOT_IDENT") -// [values_string_literals]compile-flags: --check-cfg=values(test,12) // [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT") // [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar) // [multiple_any]compile-flags: --check-cfg=cfg(any(),any()) diff --git a/tests/ui/check-cfg/invalid-arguments.values_simple_ident.stderr b/tests/ui/check-cfg/invalid-arguments.values_simple_ident.stderr deleted file mode 100644 index 061d3f0e971c3..0000000000000 --- a/tests/ui/check-cfg/invalid-arguments.values_simple_ident.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: invalid `--check-cfg` argument: `values("NOT_IDENT")` (`values()` first argument must be a simple identifier) - diff --git a/tests/ui/check-cfg/invalid-arguments.values_string_literals.stderr b/tests/ui/check-cfg/invalid-arguments.values_string_literals.stderr deleted file mode 100644 index 5853b4741a642..0000000000000 --- a/tests/ui/check-cfg/invalid-arguments.values_string_literals.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: invalid `--check-cfg` argument: `values(test,12)` (`values()` arguments must be string literals) - diff --git a/tests/ui/check-cfg/mix.cfg.stderr b/tests/ui/check-cfg/mix.cfg.stderr index daa200440cc94..21c0c7da1dd3d 100644 --- a/tests/ui/check-cfg/mix.cfg.stderr +++ b/tests/ui/check-cfg/mix.cfg.stderr @@ -38,14 +38,6 @@ LL | #[cfg_attr(uu, test)] | = help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` -warning: unexpected condition value `bar` for condition name `feature` - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected values - -warning: unexpected `unknown_name` as condition name - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected names - warning: unexpected `cfg` condition name: `widnows` --> $DIR/mix.rs:43:10 | @@ -188,5 +180,5 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | = note: expected values for `feature` are: `foo` -warning: 28 warnings emitted +warning: 26 warnings emitted diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index d7b3b4953b7a4..a6c3efee61167 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -1,13 +1,10 @@ -// This test checks the combination of well known names, their activation via names(), -// the usage of values(), and that no implicit is done with --cfg while also testing that +// This test checks the combination of well known names, the usage of cfg(), +// and that no implicit cfgs is added from --cfg while also testing that // we correctly lint on the `cfg!` macro and `cfg_attr` attribute. // // check-pass -// revisions: names_values cfg // compile-flags: --cfg feature="bar" --cfg unknown_name -Z unstable-options -// compile-flags: --check-cfg=cfg(names_values,cfg) -// [names_values]compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") -// [cfg]compile-flags: --check-cfg=cfg(feature,values("foo")) +// compile-flags: --check-cfg=cfg(feature,values("foo")) #[cfg(windows)] fn do_windows_stuff() {} diff --git a/tests/ui/check-cfg/mix.names_values.stderr b/tests/ui/check-cfg/mix.stderr similarity index 76% rename from tests/ui/check-cfg/mix.names_values.stderr rename to tests/ui/check-cfg/mix.stderr index daa200440cc94..eefdbd6af30ed 100644 --- a/tests/ui/check-cfg/mix.names_values.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `widnows` - --> $DIR/mix.rs:15:7 + --> $DIR/mix.rs:12:7 | LL | #[cfg(widnows)] | ^^^^^^^ help: there is a config with a similar name: `windows` @@ -7,7 +7,7 @@ LL | #[cfg(widnows)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/mix.rs:19:7 + --> $DIR/mix.rs:16:7 | LL | #[cfg(feature)] | ^^^^^^^- help: specify a config value: `= "foo"` @@ -15,7 +15,7 @@ LL | #[cfg(feature)] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `bar` - --> $DIR/mix.rs:26:7 + --> $DIR/mix.rs:23:7 | LL | #[cfg(feature = "bar")] | ^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | #[cfg(feature = "bar")] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:30:7 + --> $DIR/mix.rs:27:7 | LL | #[cfg(feature = "zebra")] | ^^^^^^^^^^^^^^^^^ @@ -31,29 +31,21 @@ LL | #[cfg(feature = "zebra")] = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `uu` - --> $DIR/mix.rs:34:12 + --> $DIR/mix.rs:31:12 | LL | #[cfg_attr(uu, test)] | ^^ | - = help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` - -warning: unexpected condition value `bar` for condition name `feature` - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected values - -warning: unexpected `unknown_name` as condition name - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` warning: unexpected `cfg` condition name: `widnows` - --> $DIR/mix.rs:43:10 + --> $DIR/mix.rs:40:10 | LL | cfg!(widnows); | ^^^^^^^ help: there is a config with a similar name: `windows` warning: unexpected `cfg` condition value: `bar` - --> $DIR/mix.rs:46:10 + --> $DIR/mix.rs:43:10 | LL | cfg!(feature = "bar"); | ^^^^^^^^^^^^^^^ @@ -61,7 +53,7 @@ LL | cfg!(feature = "bar"); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:48:10 + --> $DIR/mix.rs:45:10 | LL | cfg!(feature = "zebra"); | ^^^^^^^^^^^^^^^^^ @@ -69,25 +61,25 @@ LL | cfg!(feature = "zebra"); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:50:10 + --> $DIR/mix.rs:47:10 | LL | cfg!(xxx = "foo"); | ^^^^^^^^^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:52:10 + --> $DIR/mix.rs:49:10 | LL | cfg!(xxx); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:54:14 + --> $DIR/mix.rs:51:14 | LL | cfg!(any(xxx, windows)); | ^^^ warning: unexpected `cfg` condition value: `bad` - --> $DIR/mix.rs:56:14 + --> $DIR/mix.rs:53:14 | LL | cfg!(any(feature = "bad", windows)); | ^^^^^^^^^^^^^^^ @@ -95,43 +87,43 @@ LL | cfg!(any(feature = "bad", windows)); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:58:23 + --> $DIR/mix.rs:55:23 | LL | cfg!(any(windows, xxx)); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:60:20 + --> $DIR/mix.rs:57:20 | LL | cfg!(all(unix, xxx)); | ^^^ warning: unexpected `cfg` condition name: `aa` - --> $DIR/mix.rs:62:14 + --> $DIR/mix.rs:59:14 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `bb` - --> $DIR/mix.rs:62:18 + --> $DIR/mix.rs:59:18 | LL | cfg!(all(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `aa` - --> $DIR/mix.rs:65:14 + --> $DIR/mix.rs:62:14 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition name: `bb` - --> $DIR/mix.rs:65:18 + --> $DIR/mix.rs:62:18 | LL | cfg!(any(aa, bb)); | ^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:68:20 + --> $DIR/mix.rs:65:20 | LL | cfg!(any(unix, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -139,13 +131,13 @@ LL | cfg!(any(unix, feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:70:14 + --> $DIR/mix.rs:67:14 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:70:19 + --> $DIR/mix.rs:67:19 | LL | cfg!(any(xxx, feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -153,19 +145,19 @@ LL | cfg!(any(xxx, feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:73:14 + --> $DIR/mix.rs:70:14 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition name: `xxx` - --> $DIR/mix.rs:73:25 + --> $DIR/mix.rs:70:25 | LL | cfg!(any(xxx, unix, xxx)); | ^^^ warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:76:14 + --> $DIR/mix.rs:73:14 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -173,7 +165,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:76:33 + --> $DIR/mix.rs:73:33 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ @@ -181,12 +173,12 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = note: expected values for `feature` are: `foo` warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:76:52 + --> $DIR/mix.rs:73:52 | LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); | ^^^^^^^^^^^^^^^^^ | = note: expected values for `feature` are: `foo` -warning: 28 warnings emitted +warning: 26 warnings emitted diff --git a/tests/ui/check-cfg/no-expected-values.empty.stderr b/tests/ui/check-cfg/no-expected-values.empty.stderr index 5d261b2a5e63e..0969d61dd40e9 100644 --- a/tests/ui/check-cfg/no-expected-values.empty.stderr +++ b/tests/ui/check-cfg/no-expected-values.empty.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:12:7 + --> $DIR/no-expected-values.rs:11:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^-------- @@ -10,7 +10,7 @@ LL | #[cfg(feature = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:16:7 + --> $DIR/no-expected-values.rs:15:7 | LL | #[cfg(test = "foo")] | ^^^^-------- diff --git a/tests/ui/check-cfg/no-expected-values.mixed.stderr b/tests/ui/check-cfg/no-expected-values.mixed.stderr index 5d261b2a5e63e..0969d61dd40e9 100644 --- a/tests/ui/check-cfg/no-expected-values.mixed.stderr +++ b/tests/ui/check-cfg/no-expected-values.mixed.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:12:7 + --> $DIR/no-expected-values.rs:11:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^-------- @@ -10,7 +10,7 @@ LL | #[cfg(feature = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:16:7 + --> $DIR/no-expected-values.rs:15:7 | LL | #[cfg(test = "foo")] | ^^^^-------- diff --git a/tests/ui/check-cfg/no-expected-values.rs b/tests/ui/check-cfg/no-expected-values.rs index 9e2a9f09aedcd..9f34c019ea534 100644 --- a/tests/ui/check-cfg/no-expected-values.rs +++ b/tests/ui/check-cfg/no-expected-values.rs @@ -1,10 +1,9 @@ // Check that we detect unexpected value when none are allowed // // check-pass -// revisions: values simple mixed empty +// revisions: simple mixed empty // compile-flags: -Z unstable-options // compile-flags: --check-cfg=cfg(values,simple,mixed,empty) -// [values]compile-flags: --check-cfg=values(test) --check-cfg=values(feature) // [simple]compile-flags: --check-cfg=cfg(test) --check-cfg=cfg(feature) // [mixed]compile-flags: --check-cfg=cfg(test,feature) // [empty]compile-flags: --check-cfg=cfg(test,feature,values()) diff --git a/tests/ui/check-cfg/no-expected-values.simple.stderr b/tests/ui/check-cfg/no-expected-values.simple.stderr index 5d261b2a5e63e..0969d61dd40e9 100644 --- a/tests/ui/check-cfg/no-expected-values.simple.stderr +++ b/tests/ui/check-cfg/no-expected-values.simple.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:12:7 + --> $DIR/no-expected-values.rs:11:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^-------- @@ -10,7 +10,7 @@ LL | #[cfg(feature = "foo")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:16:7 + --> $DIR/no-expected-values.rs:15:7 | LL | #[cfg(test = "foo")] | ^^^^-------- diff --git a/tests/ui/check-cfg/no-expected-values.values.stderr b/tests/ui/check-cfg/no-expected-values.values.stderr deleted file mode 100644 index 5d261b2a5e63e..0000000000000 --- a/tests/ui/check-cfg/no-expected-values.values.stderr +++ /dev/null @@ -1,23 +0,0 @@ -warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:12:7 - | -LL | #[cfg(feature = "foo")] - | ^^^^^^^-------- - | | - | help: remove the value - | - = note: no expected value for `feature` - = note: `#[warn(unexpected_cfgs)]` on by default - -warning: unexpected `cfg` condition value: `foo` - --> $DIR/no-expected-values.rs:16:7 - | -LL | #[cfg(test = "foo")] - | ^^^^-------- - | | - | help: remove the value - | - = note: no expected value for `test` - -warning: 2 warnings emitted - diff --git a/tests/ui/check-cfg/order-independant.names_after.stderr b/tests/ui/check-cfg/order-independant.names_after.stderr deleted file mode 100644 index a308358e48587..0000000000000 --- a/tests/ui/check-cfg/order-independant.names_after.stderr +++ /dev/null @@ -1,19 +0,0 @@ -warning: unexpected `cfg` condition value: (none) - --> $DIR/order-independant.rs:8:7 - | -LL | #[cfg(a)] - | ^- help: specify a config value: `= "b"` - | - = note: expected values for `a` are: `b` - = note: `#[warn(unexpected_cfgs)]` on by default - -warning: unexpected `cfg` condition value: `unk` - --> $DIR/order-independant.rs:12:7 - | -LL | #[cfg(a = "unk")] - | ^^^^^^^^^ - | - = note: expected values for `a` are: `b` - -warning: 2 warnings emitted - diff --git a/tests/ui/check-cfg/order-independant.names_before.stderr b/tests/ui/check-cfg/order-independant.names_before.stderr deleted file mode 100644 index a308358e48587..0000000000000 --- a/tests/ui/check-cfg/order-independant.names_before.stderr +++ /dev/null @@ -1,19 +0,0 @@ -warning: unexpected `cfg` condition value: (none) - --> $DIR/order-independant.rs:8:7 - | -LL | #[cfg(a)] - | ^- help: specify a config value: `= "b"` - | - = note: expected values for `a` are: `b` - = note: `#[warn(unexpected_cfgs)]` on by default - -warning: unexpected `cfg` condition value: `unk` - --> $DIR/order-independant.rs:12:7 - | -LL | #[cfg(a = "unk")] - | ^^^^^^^^^ - | - = note: expected values for `a` are: `b` - -warning: 2 warnings emitted - diff --git a/tests/ui/check-cfg/order-independant.rs b/tests/ui/check-cfg/order-independant.rs index ce056b8dcd6f8..86e3cfa1d9bfd 100644 --- a/tests/ui/check-cfg/order-independant.rs +++ b/tests/ui/check-cfg/order-independant.rs @@ -1,12 +1,13 @@ // check-pass -// revisions: names_before names_after +// +// revisions: values_before values_after // compile-flags: -Z unstable-options -// compile-flags: --check-cfg=names(names_before,names_after) -// [names_before]compile-flags: --check-cfg=names(a) --check-cfg=values(a,"b") -// [names_after]compile-flags: --check-cfg=values(a,"b") --check-cfg=names(a) +// compile-flags: --check-cfg=cfg(values_before,values_after) +// +// [values_before]compile-flags: --check-cfg=cfg(a,values("b")) --check-cfg=cfg(a) +// [values_after]compile-flags: --check-cfg=cfg(a) --check-cfg=cfg(a,values("b")) #[cfg(a)] -//~^ WARNING unexpected `cfg` condition value fn my_cfg() {} #[cfg(a = "unk")] diff --git a/tests/ui/check-cfg/order-independant.values_after.stderr b/tests/ui/check-cfg/order-independant.values_after.stderr new file mode 100644 index 0000000000000..ed162fb5489d4 --- /dev/null +++ b/tests/ui/check-cfg/order-independant.values_after.stderr @@ -0,0 +1,11 @@ +warning: unexpected `cfg` condition value: `unk` + --> $DIR/order-independant.rs:13:7 + | +LL | #[cfg(a = "unk")] + | ^^^^^^^^^ + | + = note: expected values for `a` are: (none), `b` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/order-independant.values_before.stderr b/tests/ui/check-cfg/order-independant.values_before.stderr new file mode 100644 index 0000000000000..ed162fb5489d4 --- /dev/null +++ b/tests/ui/check-cfg/order-independant.values_before.stderr @@ -0,0 +1,11 @@ +warning: unexpected `cfg` condition value: `unk` + --> $DIR/order-independant.rs:13:7 + | +LL | #[cfg(a = "unk")] + | ^^^^^^^^^ + | + = note: expected values for `a` are: (none), `b` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr index 900ea4e4da06c..3fb3ae27ec487 100644 --- a/tests/ui/check-cfg/stmt-no-ice.stderr +++ b/tests/ui/check-cfg/stmt-no-ice.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `crossbeam_loom` LL | #[cfg(crossbeam_loom)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr b/tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr deleted file mode 100644 index 513f7ac7fd18e..0000000000000 --- a/tests/ui/check-cfg/unexpected-cfg-name.exhaustive.stderr +++ /dev/null @@ -1,10 +0,0 @@ -warning: unexpected `cfg` condition name: `widnows` - --> $DIR/unexpected-cfg-name.rs:9:7 - | -LL | #[cfg(widnows)] - | ^^^^^^^ help: there is a config with a similar name: `windows` - | - = note: `#[warn(unexpected_cfgs)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/check-cfg/unexpected-cfg-name.rs b/tests/ui/check-cfg/unexpected-cfg-name.rs index 15c3aa6e08122..9fc0e28a8fec0 100644 --- a/tests/ui/check-cfg/unexpected-cfg-name.rs +++ b/tests/ui/check-cfg/unexpected-cfg-name.rs @@ -1,10 +1,7 @@ // Check warning for unexpected configuration name // // check-pass -// revisions: names exhaustive -// compile-flags: --check-cfg=cfg(names,exhaustive) -// [names]compile-flags: --check-cfg=names() -Z unstable-options -// [exhaustive]compile-flags: --check-cfg=cfg() -Z unstable-options +// compile-flags: --check-cfg=cfg() -Z unstable-options #[cfg(widnows)] //~^ WARNING unexpected `cfg` condition name diff --git a/tests/ui/check-cfg/unexpected-cfg-name.names.stderr b/tests/ui/check-cfg/unexpected-cfg-name.stderr similarity index 86% rename from tests/ui/check-cfg/unexpected-cfg-name.names.stderr rename to tests/ui/check-cfg/unexpected-cfg-name.stderr index 513f7ac7fd18e..0874ccfc4617a 100644 --- a/tests/ui/check-cfg/unexpected-cfg-name.names.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-name.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `widnows` - --> $DIR/unexpected-cfg-name.rs:9:7 + --> $DIR/unexpected-cfg-name.rs:6:7 | LL | #[cfg(widnows)] | ^^^^^^^ help: there is a config with a similar name: `windows` diff --git a/tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr b/tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr index 2ed7f9005573f..2855aa75966bc 100644 --- a/tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-value.cfg.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `sedre` - --> $DIR/unexpected-cfg-value.rs:11:7 + --> $DIR/unexpected-cfg-value.rs:9:7 | LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^------- @@ -10,16 +10,12 @@ LL | #[cfg(feature = "sedre")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `rand` - --> $DIR/unexpected-cfg-value.rs:18:7 + --> $DIR/unexpected-cfg-value.rs:16:7 | LL | #[cfg(feature = "rand")] | ^^^^^^^^^^^^^^^^ | = note: expected values for `feature` are: `full`, `serde` -warning: unexpected condition value `rand` for condition name `feature` - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected values - -warning: 3 warnings emitted +warning: 2 warnings emitted diff --git a/tests/ui/check-cfg/unexpected-cfg-value.rs b/tests/ui/check-cfg/unexpected-cfg-value.rs index a84458071de84..54dce0f0de407 100644 --- a/tests/ui/check-cfg/unexpected-cfg-value.rs +++ b/tests/ui/check-cfg/unexpected-cfg-value.rs @@ -1,12 +1,8 @@ -// Check warning for invalid configuration value in the code and -// in the cli +// Check for unexpected configuration value in the code. // // check-pass -// revisions: values cfg // compile-flags: --cfg=feature="rand" -Z unstable-options -// compile-flags: --check-cfg=cfg(values,cfg) -// [values]compile-flags: --check-cfg=values(feature,"serde","full") -// [cfg]compile-flags: --check-cfg=cfg(feature,values("serde","full")) +// compile-flags: --check-cfg=cfg(feature,values("serde","full")) #[cfg(feature = "sedre")] //~^ WARNING unexpected `cfg` condition value diff --git a/tests/ui/check-cfg/unexpected-cfg-value.values.stderr b/tests/ui/check-cfg/unexpected-cfg-value.stderr similarity index 66% rename from tests/ui/check-cfg/unexpected-cfg-value.values.stderr rename to tests/ui/check-cfg/unexpected-cfg-value.stderr index 2ed7f9005573f..31c473a08cb2b 100644 --- a/tests/ui/check-cfg/unexpected-cfg-value.values.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-value.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `sedre` - --> $DIR/unexpected-cfg-value.rs:11:7 + --> $DIR/unexpected-cfg-value.rs:7:7 | LL | #[cfg(feature = "sedre")] | ^^^^^^^^^^------- @@ -10,16 +10,12 @@ LL | #[cfg(feature = "sedre")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `rand` - --> $DIR/unexpected-cfg-value.rs:18:7 + --> $DIR/unexpected-cfg-value.rs:14:7 | LL | #[cfg(feature = "rand")] | ^^^^^^^^^^^^^^^^ | = note: expected values for `feature` are: `full`, `serde` -warning: unexpected condition value `rand` for condition name `feature` - | - = help: was set with `--cfg` but isn't in the `--check-cfg` expected values - -warning: 3 warnings emitted +warning: 2 warnings emitted diff --git a/tests/ui/check-cfg/values-target-json.rs b/tests/ui/check-cfg/values-target-json.rs index 2ef5a44592b81..e4c1b54ccccfd 100644 --- a/tests/ui/check-cfg/values-target-json.rs +++ b/tests/ui/check-cfg/values-target-json.rs @@ -2,7 +2,7 @@ // // check-pass // needs-llvm-components: x86 -// compile-flags: --crate-type=lib --check-cfg=values() --target={{src-base}}/check-cfg/my-awesome-platform.json -Z unstable-options +// compile-flags: --crate-type=lib --check-cfg=cfg() --target={{src-base}}/check-cfg/my-awesome-platform.json -Z unstable-options #![feature(lang_items, no_core, auto_traits)] #![no_core] diff --git a/tests/ui/check-cfg/well-known-names.rs b/tests/ui/check-cfg/well-known-names.rs index 1dcb419b4a73b..32c14703d25b5 100644 --- a/tests/ui/check-cfg/well-known-names.rs +++ b/tests/ui/check-cfg/well-known-names.rs @@ -15,6 +15,7 @@ fn target_os() {} fn feature_misspell() {} #[cfg(feature = "foo")] +//~^ WARNING unexpected `cfg` condition name fn feature() {} #[cfg(uniw)] diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index 3001289b7e06f..a986e61bcdc30 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -14,15 +14,21 @@ warning: unexpected `cfg` condition name: `features` --> $DIR/well-known-names.rs:13:7 | LL | #[cfg(features = "foo")] - | --------^^^^^^^^ - | | - | help: there is a config with a similar name: `feature` + | ^^^^^^^^^^^^^^^^ + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + +warning: unexpected `cfg` condition name: `feature` + --> $DIR/well-known-names.rs:17:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^^^^^^^^^ warning: unexpected `cfg` condition name: `uniw` - --> $DIR/well-known-names.rs:20:7 + --> $DIR/well-known-names.rs:21:7 | LL | #[cfg(uniw)] | ^^^^ help: there is a config with a similar name: `unix` -warning: 3 warnings emitted +warning: 4 warnings emitted diff --git a/tests/ui/check-static-immutable-mut-slices.stderr b/tests/ui/check-static-immutable-mut-slices.stderr index a32a94c1315ab..402f9032b640d 100644 --- a/tests/ui/check-static-immutable-mut-slices.stderr +++ b/tests/ui/check-static-immutable-mut-slices.stderr @@ -4,6 +4,6 @@ error[E0764]: mutable references are not allowed in the final value of statics LL | static TEST: &'static mut [isize] = &mut []; | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0764`. diff --git a/tests/ui/class-cast-to-trait.stderr b/tests/ui/class-cast-to-trait.stderr index 56d10d88d8b25..4ea0f41c3ed93 100644 --- a/tests/ui/class-cast-to-trait.stderr +++ b/tests/ui/class-cast-to-trait.stderr @@ -4,6 +4,6 @@ error[E0599]: no method named `eat` found for struct `Box` in the cur LL | nyan.eat(); | ^^^ method not found in `Box` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/class-method-missing.stderr b/tests/ui/class-method-missing.stderr index 3b4ac3a9adc56..42bd22e18a198 100644 --- a/tests/ui/class-method-missing.stderr +++ b/tests/ui/class-method-missing.stderr @@ -7,6 +7,6 @@ LL | fn eat(&self); LL | impl Animal for Cat { | ^^^^^^^^^^^^^^^^^^^ missing `eat` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr index c5089295063dd..d3cd8185f924b 100644 --- a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr +++ b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr @@ -16,6 +16,6 @@ LL | fn with_closure(_: F) LL | where F: FnOnce(A, A) | ^^^^^^^^^^^^ required by this bound in `with_closure` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr index 7a04ed7381e66..8799a2a0772f2 100644 --- a/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr +++ b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr @@ -9,6 +9,6 @@ help: consider giving this closure parameter an explicit type LL | with_closure(|x: u32, y: /* Type */| {}); | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/closure_context/issue-26046-fn-mut.stderr b/tests/ui/closure_context/issue-26046-fn-mut.stderr index eeb4094524243..0b58180bcca77 100644 --- a/tests/ui/closure_context/issue-26046-fn-mut.stderr +++ b/tests/ui/closure_context/issue-26046-fn-mut.stderr @@ -11,6 +11,6 @@ LL | Box::new(closure) | = note: required for the cast from `Box<{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}>` to `Box<(dyn Fn() + 'static)>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closure_context/issue-26046-fn-once.stderr b/tests/ui/closure_context/issue-26046-fn-once.stderr index 24773a1d7e351..66fb1856cbbbf 100644 --- a/tests/ui/closure_context/issue-26046-fn-once.stderr +++ b/tests/ui/closure_context/issue-26046-fn-once.stderr @@ -11,6 +11,6 @@ LL | Box::new(closure) | = note: required for the cast from `Box<{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}>` to `Box<(dyn Fn() -> Vec + 'static)>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closure_context/issue-42065.stderr b/tests/ui/closure_context/issue-42065.stderr index 896bb6dc6bee8..9ae89047d128c 100644 --- a/tests/ui/closure_context/issue-42065.stderr +++ b/tests/ui/closure_context/issue-42065.stderr @@ -17,6 +17,6 @@ note: this value implements `FnOnce`, which causes it to be moved when called LL | debug_dump_dict(); | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr index 341d2bc65634b..f59a2625cd2c1 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr @@ -14,6 +14,6 @@ LL | println!("{:?}", p); LL | *y+=1; | ----- first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr index 584bb862b2c0a..64d5ff8e2e0c1 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr @@ -14,6 +14,6 @@ LL | let x = &mut p.x; LL | println!("{}", y); | - immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr index ee92380478685..979527e9f793b 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr @@ -17,6 +17,6 @@ help: to force the closure to take ownership of `p` (and any other referenced va LL | move || { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr index 46379a3815a4d..d47f0539b84b2 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr @@ -17,6 +17,6 @@ help: to force the closure to take ownership of `p` (and any other referenced va LL | let mut c = move || { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr index 5f1dae2972f9e..57234fffec64c 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr @@ -16,6 +16,6 @@ LL | }; LL | drop(c2); | -- immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr index 38c530b809a62..d224f21bc8492 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr @@ -7,6 +7,6 @@ LL | LL | z.0.0.0 = format!("X1"); | ------- mutable borrow occurs due to use of `*z.0.0` in closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr index 309c63e52932b..1172f54c15088 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr @@ -17,6 +17,6 @@ note: required by a bound in `expect_fn` LL | fn expect_fn(_f: F) {} | ^^^^ required by this bound in `expect_fn` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr index 83d282aadb915..347fa3fa8920d 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr @@ -16,6 +16,6 @@ help: consider mutably borrowing `c` LL | let a = &mut c; | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr index 46323b75210cb..c9b27e7687959 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr @@ -16,6 +16,6 @@ help: consider mutably borrowing `c` LL | let b = &mut c; | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr index 25029cc7bd8b8..079a9abedf976 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr @@ -16,6 +16,6 @@ help: consider mutably borrowing `hello` LL | let b = &mut hello; | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr index 06ef7baf9c068..0bf717404ceb7 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr @@ -16,6 +16,6 @@ help: consider mutably borrowing `hello` LL | let b = &mut hello; | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr index 3e77635f9e0c8..4abe5eda22d76 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr @@ -17,6 +17,6 @@ note: required by a bound in `expect_fn` LL | fn expect_fn(_f: F) {} | ^^^^ required by this bound in `expect_fn` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr index ac4c9c93769ce..5a054ef5fdcd2 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr @@ -12,6 +12,6 @@ LL | LL | c(); | - first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr index 8c44229bcebe1..c9972c8e7e349 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr @@ -9,6 +9,6 @@ LL | println!("{}", foo.x); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0793`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr index 06157b2af7a07..68fdb3ce131f7 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr @@ -16,6 +16,6 @@ LL | c(); | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr index 17834e6123628..63fb3e5d97536 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr @@ -13,6 +13,6 @@ LL | a.y = 1; LL | c(); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/closures/2229_closure_analysis/issue-90465.stderr b/tests/ui/closures/2229_closure_analysis/issue-90465.stderr index c1679c6b637e5..ccca24764e42a 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-90465.stderr +++ b/tests/ui/closures/2229_closure_analysis/issue-90465.stderr @@ -22,5 +22,5 @@ LL ~ let c0 = move || { LL + let _ = &f0; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs index 914ebbe26a57d..106485e04eea6 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs @@ -26,7 +26,8 @@ pub fn edge_case_str(event: String) { pub fn edge_case_raw_ptr(event: *const i32) { let _ = || { match event { - NUMBER_POINTER => (), + NUMBER_POINTER => (), //~WARN behave unpredictably + //~| previously accepted _ => (), }; }; diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr new file mode 100644 index 0000000000000..c83ba41976bcd --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr @@ -0,0 +1,12 @@ +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/match-edge-cases_1.rs:29:13 + | +LL | NUMBER_POINTER => (), + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr index 1e42d73c62bd9..d82db0481a06f 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr @@ -12,6 +12,6 @@ LL | LL | _b(); | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/closures/2229_closure_analysis/migrations/macro.stderr b/tests/ui/closures/2229_closure_analysis/migrations/macro.stderr index c17edce72f987..7ea5136d11910 100644 --- a/tests/ui/closures/2229_closure_analysis/migrations/macro.stderr +++ b/tests/ui/closures/2229_closure_analysis/migrations/macro.stderr @@ -18,5 +18,5 @@ help: add a dummy let to cause `a` to be fully captured LL | let _ = || { let _ = &a; dbg!(a.0) }; | +++++++++++++ + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index e10898f984499..2b76deca37708 100644 --- a/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -22,5 +22,5 @@ LL ~ let result = panic::catch_unwind(move || { LL + let _ = &f; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.stderr b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.stderr index 730823281abc9..e4b5d39c0b1ff 100644 --- a/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.stderr +++ b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-1.stderr @@ -10,5 +10,5 @@ LL | let mut closure = |input| x.0 = input; | = help: consider adding the following bound: `'b: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.stderr b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.stderr index 66ba0fe3547a6..c18649b9ee9db 100644 --- a/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.stderr +++ b/tests/ui/closures/2229_closure_analysis/unique-borrows-are-invariant-2.stderr @@ -11,5 +11,5 @@ LL | self.borrowed = borrow; | = help: consider adding the following bound: `'a: 'b` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/closures/add_semicolon_non_block_closure.stderr b/tests/ui/closures/add_semicolon_non_block_closure.stderr index 6f9c309edda2e..d095e59c7ebb0 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.stderr +++ b/tests/ui/closures/add_semicolon_non_block_closure.stderr @@ -11,6 +11,6 @@ help: consider using a semicolon here LL | foo(|| { bar(); }) | + +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/binder/const-bound.stderr b/tests/ui/closures/binder/const-bound.stderr index c016465c101ce..9c4fd95ed76ed 100644 --- a/tests/ui/closures/binder/const-bound.stderr +++ b/tests/ui/closures/binder/const-bound.stderr @@ -13,5 +13,5 @@ error: late-bound const parameter not allowed on closures LL | for || -> () {}; | ^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr index 59f299315f856..d38b233d99a8a 100644 --- a/tests/ui/closures/binder/disallow-const.stderr +++ b/tests/ui/closures/binder/disallow-const.stderr @@ -7,6 +7,6 @@ LL | for || -> () {}; = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr index 3370e21bd711a..bc6696ad36b41 100644 --- a/tests/ui/closures/binder/disallow-ty.stderr +++ b/tests/ui/closures/binder/disallow-ty.stderr @@ -7,6 +7,6 @@ LL | for || -> () {}; = note: see issue #108185 for more information = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/binder/implicit-return.stderr b/tests/ui/closures/binder/implicit-return.stderr index 35db34ce21d1c..ff39e8841ee71 100644 --- a/tests/ui/closures/binder/implicit-return.stderr +++ b/tests/ui/closures/binder/implicit-return.stderr @@ -6,5 +6,5 @@ LL | let _f = for<'a> |_: &'a ()| {}; | | | `for<...>` is here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/closures/binder/type-bound-2.stderr b/tests/ui/closures/binder/type-bound-2.stderr index 14b2dbf03957f..6609b326f19a5 100644 --- a/tests/ui/closures/binder/type-bound-2.stderr +++ b/tests/ui/closures/binder/type-bound-2.stderr @@ -13,5 +13,5 @@ error: late-bound type parameter not allowed on closures LL | for || -> () {}; | ^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/closures/binder/type-bound.stderr b/tests/ui/closures/binder/type-bound.stderr index ef00a2dffceae..22431130a5d4a 100644 --- a/tests/ui/closures/binder/type-bound.stderr +++ b/tests/ui/closures/binder/type-bound.stderr @@ -13,5 +13,5 @@ error: late-bound type parameter not allowed on closures LL | for || -> T {}; | ^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr.stderr b/tests/ui/closures/cannot-call-unsized-via-ptr.stderr index 9ecc66d5ce897..7c73372e33c9c 100644 --- a/tests/ui/closures/cannot-call-unsized-via-ptr.stderr +++ b/tests/ui/closures/cannot-call-unsized-via-ptr.stderr @@ -7,6 +7,6 @@ LL | let f: fn([u8]) = |_result| {}; = help: the trait `Sized` is not implemented for `[u8]` = note: all function arguments must have a statically known size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/capture-unsized-by-move.stderr b/tests/ui/closures/capture-unsized-by-move.stderr index d7fafc8cadd7b..686bbab883951 100644 --- a/tests/ui/closures/capture-unsized-by-move.stderr +++ b/tests/ui/closures/capture-unsized-by-move.stderr @@ -9,6 +9,6 @@ LL | k.to_string(); = help: the trait `Sized` is not implemented for `(dyn std::fmt::Display + 'static)` = note: all values captured by value by a closure must have a statically known size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr index bf6ec5c36e480..e98f05b470e77 100644 --- a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr +++ b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr @@ -14,6 +14,6 @@ help: consider further restricting this bound LL | fn foo(blk: F) -> X where F: FnOnce() + 'static + std::marker::Send { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-bounds-subtype.stderr b/tests/ui/closures/closure-bounds-subtype.stderr index 8ad8273fc2b9b..42588668e8a03 100644 --- a/tests/ui/closures/closure-bounds-subtype.stderr +++ b/tests/ui/closures/closure-bounds-subtype.stderr @@ -20,6 +20,6 @@ help: consider further restricting this bound LL | fn give_owned(f: F) where F: FnOnce() + Send + std::marker::Sync { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-expected.stderr b/tests/ui/closures/closure-expected.stderr index 565038f5144e1..6b309d70bdf16 100644 --- a/tests/ui/closures/closure-expected.stderr +++ b/tests/ui/closures/closure-expected.stderr @@ -11,6 +11,6 @@ LL | let y = x.or_else(4); note: required by a bound in `Option::::or_else` --> $SRC_DIR/core/src/option.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-immutable-outer-variable.stderr b/tests/ui/closures/closure-immutable-outer-variable.stderr index 799097889cd30..23bd0020db6b3 100644 --- a/tests/ui/closures/closure-immutable-outer-variable.stderr +++ b/tests/ui/closures/closure-immutable-outer-variable.stderr @@ -6,6 +6,6 @@ LL | let y = true; LL | foo(Box::new(move || y = !y) as Box<_>); | ^^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/closures/closure-move-sync.stderr b/tests/ui/closures/closure-move-sync.stderr index aee903ac9504a..2bb26b0c0b7d4 100644 --- a/tests/ui/closures/closure-move-sync.stderr +++ b/tests/ui/closures/closure-move-sync.stderr @@ -20,6 +20,6 @@ LL | let t = thread::spawn(|| { note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-no-fn-1.stderr b/tests/ui/closures/closure-no-fn-1.stderr index 87e670bb0b393..8fab92e9b151d 100644 --- a/tests/ui/closures/closure-no-fn-1.stderr +++ b/tests/ui/closures/closure-no-fn-1.stderr @@ -14,6 +14,6 @@ note: closures can only be coerced to `fn` types if they do not capture any vari LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | ^ `a` captured here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-no-fn-2.stderr b/tests/ui/closures/closure-no-fn-2.stderr index 7c7e9d0ce125b..06682fcc244a3 100644 --- a/tests/ui/closures/closure-no-fn-2.stderr +++ b/tests/ui/closures/closure-no-fn-2.stderr @@ -14,6 +14,6 @@ note: closures can only be coerced to `fn` types if they do not capture any vari LL | let bar: fn() -> u8 = || { b }; | ^ `b` captured here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-no-fn-3.stderr b/tests/ui/closures/closure-no-fn-3.stderr index 276e766e8065b..bbf3677fb7235 100644 --- a/tests/ui/closures/closure-no-fn-3.stderr +++ b/tests/ui/closures/closure-no-fn-3.stderr @@ -4,6 +4,6 @@ error[E0605]: non-primitive cast: `{closure@$DIR/closure-no-fn-3.rs:6:28: 6:30}` LL | let baz: fn() -> u8 = (|| { b }) as fn() -> u8; | ^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/closures/closure-no-fn-4.stderr b/tests/ui/closures/closure-no-fn-4.stderr index 0bec11ab61fc3..c86731b127d3c 100644 --- a/tests/ui/closures/closure-no-fn-4.stderr +++ b/tests/ui/closures/closure-no-fn-4.stderr @@ -19,6 +19,6 @@ note: closures can only be coerced to `fn` types if they do not capture any vari LL | false => |a| a - b, | ^ `b` captured here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-no-fn-5.stderr b/tests/ui/closures/closure-no-fn-5.stderr index 13d19495d23d9..ffe01fac4966d 100644 --- a/tests/ui/closures/closure-no-fn-5.stderr +++ b/tests/ui/closures/closure-no-fn-5.stderr @@ -18,6 +18,6 @@ LL | let bar: fn() -> u8 = || { a; b; c; d; e }; | | `b` captured here | `a` captured here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-referencing-itself-issue-25954.stderr b/tests/ui/closures/closure-referencing-itself-issue-25954.stderr index 8ca43cd1cffb1..6fe6840b35b3b 100644 --- a/tests/ui/closures/closure-referencing-itself-issue-25954.stderr +++ b/tests/ui/closures/closure-referencing-itself-issue-25954.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | let q = || p.b.set(5i32); | ^^^^^^^^^^^^^^^^ cyclic type of infinite size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-reform-bad.stderr b/tests/ui/closures/closure-reform-bad.stderr index 6bb59813157b2..426930666065d 100644 --- a/tests/ui/closures/closure-reform-bad.stderr +++ b/tests/ui/closures/closure-reform-bad.stderr @@ -21,6 +21,6 @@ note: function defined here LL | fn call_bare(f: fn(&str)) { | ^^^^^^^^^ ----------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-wrong-kind.stderr b/tests/ui/closures/closure-wrong-kind.stderr index 9ea55d764f345..705cc948668fc 100644 --- a/tests/ui/closures/closure-wrong-kind.stderr +++ b/tests/ui/closures/closure-wrong-kind.stderr @@ -16,6 +16,6 @@ note: required by a bound in `bar` LL | fn bar(_: T) {} | ^^^^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr index a60100ddaeaeb..579227703103a 100644 --- a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr +++ b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr @@ -6,6 +6,6 @@ LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); }; | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr index 8c516e8900c27..fb237231d65a7 100644 --- a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr +++ b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr @@ -6,6 +6,6 @@ LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); }; | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr index bd4ab13a205f2..4841ff32e7011 100644 --- a/tests/ui/closures/coerce-unsafe-to-closure.stderr +++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr @@ -11,6 +11,6 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/infer-signature-from-impl.next.stderr b/tests/ui/closures/infer-signature-from-impl.next.stderr index 97351706699a6..0866265cf048b 100644 --- a/tests/ui/closures/infer-signature-from-impl.next.stderr +++ b/tests/ui/closures/infer-signature-from-impl.next.stderr @@ -11,6 +11,6 @@ help: consider giving this closure parameter an explicit type LL | needs_foo(|x: /* Type */| { | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/closures/issue-10398.stderr b/tests/ui/closures/issue-10398.stderr index 423b79dafcc97..bcbcd6d4c2d83 100644 --- a/tests/ui/closures/issue-10398.stderr +++ b/tests/ui/closures/issue-10398.stderr @@ -8,6 +8,6 @@ LL | drop(x); | = note: move occurs because `x` has type `Box`, which does not implement the `Copy` trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/issue-112547.stderr b/tests/ui/closures/issue-112547.stderr index d86b05dc6a7bf..f47ea60729763 100644 --- a/tests/ui/closures/issue-112547.stderr +++ b/tests/ui/closures/issue-112547.stderr @@ -18,6 +18,6 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/closures/issue-113087.stderr b/tests/ui/closures/issue-113087.stderr index 8ccef4a54f5d6..c51d13f4ad0f2 100644 --- a/tests/ui/closures/issue-113087.stderr +++ b/tests/ui/closures/issue-113087.stderr @@ -11,6 +11,6 @@ LL | }); LL | } | - `a` dropped here while still borrowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/closures/issue-11873.stderr b/tests/ui/closures/issue-11873.stderr index c814eedd22614..04921b9227e0f 100644 --- a/tests/ui/closures/issue-11873.stderr +++ b/tests/ui/closures/issue-11873.stderr @@ -11,6 +11,6 @@ LL | LL | f(); | - borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/closures/issue-25439.stderr b/tests/ui/closures/issue-25439.stderr index 5e889e6c18442..19a26396a5d94 100644 --- a/tests/ui/closures/issue-25439.stderr +++ b/tests/ui/closures/issue-25439.stderr @@ -14,6 +14,6 @@ note: required by a bound in `fix` LL | fn fix(f: F) -> i32 where F: Fn(Helper, i32) -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fix` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0644`. diff --git a/tests/ui/closures/issue-67123.stderr b/tests/ui/closures/issue-67123.stderr index 7877c7334d79b..bdafeaef15fd5 100644 --- a/tests/ui/closures/issue-67123.stderr +++ b/tests/ui/closures/issue-67123.stderr @@ -12,6 +12,6 @@ help: consider restricting type parameter `T` LL | fn foo(t: T) { | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/issue-6801.stderr b/tests/ui/closures/issue-6801.stderr index 6a40db0d51d4b..aed673fe1ab5d 100644 --- a/tests/ui/closures/issue-6801.stderr +++ b/tests/ui/closures/issue-6801.stderr @@ -11,6 +11,6 @@ LL | twice(x); LL | invoke(sq); | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/closures/issue-80313-mutable-borrow-in-closure.stderr b/tests/ui/closures/issue-80313-mutable-borrow-in-closure.stderr index 239f071ca92b3..1266c603e5d87 100644 --- a/tests/ui/closures/issue-80313-mutable-borrow-in-closure.stderr +++ b/tests/ui/closures/issue-80313-mutable-borrow-in-closure.stderr @@ -12,6 +12,6 @@ help: consider changing this to be mutable LL | let mut callback = || { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr b/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr index 1ec279f03eff5..57320b58d0159 100644 --- a/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr +++ b/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr @@ -12,6 +12,6 @@ help: consider changing this to be mutable LL | let mut callback = move || { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-80313-mutation-in-closure.stderr b/tests/ui/closures/issue-80313-mutation-in-closure.stderr index 22a62ce735053..b605cd2f9e51b 100644 --- a/tests/ui/closures/issue-80313-mutation-in-closure.stderr +++ b/tests/ui/closures/issue-80313-mutation-in-closure.stderr @@ -12,6 +12,6 @@ help: consider changing this to be mutable LL | let mut callback = || { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-80313-mutation-in-move-closure.stderr b/tests/ui/closures/issue-80313-mutation-in-move-closure.stderr index a2222f8cc9570..b0210ac7cb723 100644 --- a/tests/ui/closures/issue-80313-mutation-in-move-closure.stderr +++ b/tests/ui/closures/issue-80313-mutation-in-move-closure.stderr @@ -12,6 +12,6 @@ help: consider changing this to be mutable LL | let mut callback = move || { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-81700-mut-borrow.stderr b/tests/ui/closures/issue-81700-mut-borrow.stderr index 03b18c3f70c63..d050fb60c3db2 100644 --- a/tests/ui/closures/issue-81700-mut-borrow.stderr +++ b/tests/ui/closures/issue-81700-mut-borrow.stderr @@ -11,6 +11,6 @@ help: consider changing this to be mutable LL | let mut bar = || { foo(x); }; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-82438-mut-without-upvar.stderr b/tests/ui/closures/issue-82438-mut-without-upvar.stderr index f0951b7d10873..c6ed7097c5d48 100644 --- a/tests/ui/closures/issue-82438-mut-without-upvar.stderr +++ b/tests/ui/closures/issue-82438-mut-without-upvar.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut c = |a, b, c, d| {}; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-84044-drop-non-mut.stderr b/tests/ui/closures/issue-84044-drop-non-mut.stderr index 5335a056cd89f..ada0e337324eb 100644 --- a/tests/ui/closures/issue-84044-drop-non-mut.stderr +++ b/tests/ui/closures/issue-84044-drop-non-mut.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut f = || {}; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-84128.stderr b/tests/ui/closures/issue-84128.stderr index 1cd8949b8c4b7..9d4c7f715811a 100644 --- a/tests/ui/closures/issue-84128.stderr +++ b/tests/ui/closures/issue-84128.stderr @@ -19,6 +19,6 @@ note: tuple struct defined here LL | struct Foo(T); | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/issue-868.rs b/tests/ui/closures/issue-868.rs index ce0a3c7ca526c..df03b191a99e9 100644 --- a/tests/ui/closures/issue-868.rs +++ b/tests/ui/closures/issue-868.rs @@ -1,5 +1,6 @@ // run-pass #![allow(unused_parens)] +#![allow(unit_bindings)] // pretty-expanded FIXME #23616 fn f(g: F) -> T where F: FnOnce() -> T { g() } diff --git a/tests/ui/closures/issue-99565.stderr b/tests/ui/closures/issue-99565.stderr index 0d940aa9a2f5f..e48f5106165b0 100644 --- a/tests/ui/closures/issue-99565.stderr +++ b/tests/ui/closures/issue-99565.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic arguments LL | foo::(|| {}); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr index d94c902f7214d..d510fc585f651 100644 --- a/tests/ui/closures/multiple-fn-bounds.stderr +++ b/tests/ui/closures/multiple-fn-bounds.stderr @@ -23,6 +23,6 @@ help: consider adjusting the signature so it does not borrow its argument LL | foo(move |char| v); | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/closures/old-closure-expression-remove-semicolon.stderr b/tests/ui/closures/old-closure-expression-remove-semicolon.stderr index bc54ab4d511a5..c6ce1c62d93ec 100644 --- a/tests/ui/closures/old-closure-expression-remove-semicolon.stderr +++ b/tests/ui/closures/old-closure-expression-remove-semicolon.stderr @@ -9,6 +9,6 @@ LL | | foo(); LL | | }; | |_____^ expected `i32`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/print/closure-print-generic-1.stderr b/tests/ui/closures/print/closure-print-generic-1.stderr index 2697f93b14c2b..41cad279f7b9f 100644 --- a/tests/ui/closures/print/closure-print-generic-1.stderr +++ b/tests/ui/closures/print/closure-print-generic-1.stderr @@ -15,6 +15,6 @@ note: this value implements `FnOnce`, which causes it to be moved when called LL | c(); | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/print/closure-print-generic-2.stderr b/tests/ui/closures/print/closure-print-generic-2.stderr index ced0be9458b8e..0a604a7d6cf02 100644 --- a/tests/ui/closures/print/closure-print-generic-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-2.stderr @@ -15,6 +15,6 @@ help: use parentheses to call this closure LL | let c1: () = c(); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index 6e3659b95ea8d..1a13255429f00 100644 --- a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -15,6 +15,6 @@ help: use parentheses to call this closure LL | let c1 : () = c(); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/print/closure-print-generic-verbose-1.stderr b/tests/ui/closures/print/closure-print-generic-verbose-1.stderr index 5e8a6b1a73aa7..75aa3c9347993 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-1.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-1.stderr @@ -15,6 +15,6 @@ note: this value implements `FnOnce`, which causes it to be moved when called LL | c(); | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr index f1fc35e755cca..8553817247d54 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -15,6 +15,6 @@ help: use parentheses to call this closure LL | let c1 : () = c(); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/print/closure-print-verbose.stderr b/tests/ui/closures/print/closure-print-verbose.stderr index 3f9160fe5fa97..3d0af5eb171c8 100644 --- a/tests/ui/closures/print/closure-print-verbose.stderr +++ b/tests/ui/closures/print/closure-print-verbose.stderr @@ -14,6 +14,6 @@ note: closures can only be coerced to `fn` types if they do not capture any vari LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | ^ `a` captured here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr index ed8e16899a161..0a5884d38f78a 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr @@ -7,6 +7,6 @@ LL | core::mem::transmute:: for more information = help: add `#![feature(abi_c_cmse_nonsecure_call)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr index 37230078781ed..a8aced2483e8f 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr @@ -1,4 +1,4 @@ error: :0:0: in function test i32 (i32, i32, i32, i32, i32): call to non-secure function would require passing arguments on stack -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr index 08b763b260822..8d1b10eaeb5b6 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr @@ -4,6 +4,6 @@ error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function poin LL | pub extern "C-cmse-nonsecure-call" fn test() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0781`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr index 3ade9891e48a5..917098e21d82c 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr @@ -6,6 +6,6 @@ LL | | fn test(); LL | | } | |_^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0781`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr index 426d82d8d0753..26d3bfe78375b 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr @@ -7,5 +7,5 @@ LL | LL | struct XEmpty2; | --------------- not a function definition -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr index 1054c26651270..cfbdda509e580 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr @@ -1,4 +1,4 @@ error: :0:0: in function entry_function i32 (i32, i32, i32, i32, i32): secure entry function requires arguments on stack -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr index 7e8862f9ab7f2..3e6954394f445 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr @@ -4,6 +4,6 @@ error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the Trust LL | #[cmse_nonsecure_entry] | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0775`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr index 36d76c9674adf..4d34f0d75099d 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr @@ -4,6 +4,6 @@ error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI LL | #[cmse_nonsecure_entry] | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0776`. diff --git a/tests/ui/codegen/issue-99551.rs b/tests/ui/codegen/issue-99551.rs index b223aff4e9492..9e203fba113c9 100644 --- a/tests/ui/codegen/issue-99551.rs +++ b/tests/ui/codegen/issue-99551.rs @@ -1,5 +1,4 @@ // build-pass -#![feature(trait_upcasting)] pub trait A {} pub trait B {} diff --git a/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr index 2c1c3c2dc967d..917ea7330a185 100644 --- a/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr +++ b/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr @@ -6,6 +6,6 @@ LL | impl dyn C { fn f() {} } LL | impl dyn C { fn f() {} } | ------ other definition for `f` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/codemap_tests/empty_span.stderr b/tests/ui/codemap_tests/empty_span.stderr index e36f59ee5463b..32f51c95d4408 100644 --- a/tests/ui/codemap_tests/empty_span.stderr +++ b/tests/ui/codemap_tests/empty_span.stderr @@ -4,6 +4,6 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i LL | unsafe impl Send for &'static Foo { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0321`. diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.stderr b/tests/ui/codemap_tests/huge_multispan_highlight.stderr index 9f8ce3b6183f2..d2923875c94cf 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/tests/ui/codemap_tests/huge_multispan_highlight.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut x = "foo"; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/codemap_tests/issue-11715.stderr b/tests/ui/codemap_tests/issue-11715.stderr index d0c29c768eb61..5d0cf718761c4 100644 --- a/tests/ui/codemap_tests/issue-11715.stderr +++ b/tests/ui/codemap_tests/issue-11715.stderr @@ -9,6 +9,6 @@ LL | z.use_mut(); LL | y.use_mut(); | - first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/codemap_tests/issue-28308.stderr b/tests/ui/codemap_tests/issue-28308.stderr index 7daa0510cfa1c..efd8fa22fa5ce 100644 --- a/tests/ui/codemap_tests/issue-28308.stderr +++ b/tests/ui/codemap_tests/issue-28308.stderr @@ -6,6 +6,6 @@ LL | assert!("foo"); | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/codemap_tests/one_line.stderr b/tests/ui/codemap_tests/one_line.stderr index 75fbbada72ce3..90762b87b5cde 100644 --- a/tests/ui/codemap_tests/one_line.stderr +++ b/tests/ui/codemap_tests/one_line.stderr @@ -18,6 +18,6 @@ help: ...and then using that local as the argument to this call LL | v.push(v.pop().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/codemap_tests/tab_2.stderr b/tests/ui/codemap_tests/tab_2.stderr index 0bfdc3ac2651d..4f9a937155dde 100644 --- a/tests/ui/codemap_tests/tab_2.stderr +++ b/tests/ui/codemap_tests/tab_2.stderr @@ -6,6 +6,6 @@ LL | """; LL | | } | |__^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0765`. diff --git a/tests/ui/codemap_tests/tab_3.stderr b/tests/ui/codemap_tests/tab_3.stderr index b17159be6e065..7ae21a57052fe 100644 --- a/tests/ui/codemap_tests/tab_3.stderr +++ b/tests/ui/codemap_tests/tab_3.stderr @@ -17,6 +17,6 @@ help: you can `clone` the value and consume it, but this might not be your desir LL | some_vec.clone().into_iter(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/codemap_tests/two_files.stderr b/tests/ui/codemap_tests/two_files.stderr index 2eb3fd5678314..d833d4944bfe9 100644 --- a/tests/ui/codemap_tests/two_files.stderr +++ b/tests/ui/codemap_tests/two_files.stderr @@ -10,6 +10,6 @@ help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` LL | trait Bar = dyn Foo; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/codemap_tests/unicode.normal.stderr b/tests/ui/codemap_tests/unicode.normal.stderr index 05ceb6910dadd..a6e22e1c38f9c 100644 --- a/tests/ui/codemap_tests/unicode.normal.stderr +++ b/tests/ui/codemap_tests/unicode.normal.stderr @@ -6,6 +6,6 @@ LL | extern "路濫狼á́́" fn foo() {} | = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/coercion/coerce-block-tail-26978.stderr b/tests/ui/coercion/coerce-block-tail-26978.stderr index 90eb75f2bdfd1..89682e103aa54 100644 --- a/tests/ui/coercion/coerce-block-tail-26978.stderr +++ b/tests/ui/coercion/coerce-block-tail-26978.stderr @@ -11,6 +11,6 @@ help: consider unboxing the value LL | f(&{*x}); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-block-tail-57749.stderr b/tests/ui/coercion/coerce-block-tail-57749.stderr index 7e14f42eaafce..6a6f5ec11b9fa 100644 --- a/tests/ui/coercion/coerce-block-tail-57749.stderr +++ b/tests/ui/coercion/coerce-block-tail-57749.stderr @@ -9,6 +9,6 @@ help: consider dereferencing the type LL | reset(&{ *Homura }); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-block-tail-83783.stderr b/tests/ui/coercion/coerce-block-tail-83783.stderr index da3c387773f9a..bf2c3899925f1 100644 --- a/tests/ui/coercion/coerce-block-tail-83783.stderr +++ b/tests/ui/coercion/coerce-block-tail-83783.stderr @@ -11,6 +11,6 @@ help: consider unboxing the value LL | _consume_reference::(&*async { Box::new(7_i32) }.await); | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-block-tail-83850.stderr b/tests/ui/coercion/coerce-block-tail-83850.stderr index 3cfebb8a54372..e98b3e610a8b5 100644 --- a/tests/ui/coercion/coerce-block-tail-83850.stderr +++ b/tests/ui/coercion/coerce-block-tail-83850.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn f(_: &[i32]) {} | ^ --------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-block-tail.stderr b/tests/ui/coercion/coerce-block-tail.stderr index 7044fc3cefc4c..1301f3b7813ed 100644 --- a/tests/ui/coercion/coerce-block-tail.stderr +++ b/tests/ui/coercion/coerce-block-tail.stderr @@ -11,6 +11,6 @@ help: consider unboxing the value LL | let _: &i32 = & { *Box::new(1i32) }; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-mut.stderr b/tests/ui/coercion/coerce-mut.stderr index 11a4f310154c5..9bbfcc29e61ab 100644 --- a/tests/ui/coercion/coerce-mut.stderr +++ b/tests/ui/coercion/coerce-mut.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn f(x: &mut i32) {} | ^ ----------- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr index 5cbdef2183114..498ef33d52ecc 100644 --- a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr +++ b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr @@ -14,6 +14,6 @@ note: function defined here LL | fn test(_a: T, _b: T) {} | ^^^^ ----- -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coercion-slice.stderr b/tests/ui/coercion/coercion-slice.stderr index 17bbca7a0bdb6..26a7a5c1cdd85 100644 --- a/tests/ui/coercion/coercion-slice.stderr +++ b/tests/ui/coercion/coercion-slice.stderr @@ -11,6 +11,6 @@ help: consider borrowing here LL | let _: &[i32] = &[0]; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/issue-53475.stderr b/tests/ui/coercion/issue-53475.stderr index 4778611bf1b53..af114519add6c 100644 --- a/tests/ui/coercion/issue-53475.stderr +++ b/tests/ui/coercion/issue-53475.stderr @@ -12,6 +12,6 @@ help: consider adding an explicit lifetime bound LL | impl CoerceUnsized> for Foo {} | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/coercion/retslot-cast.stderr b/tests/ui/coercion/retslot-cast.stderr index 798ce1199a9dc..dac21a7f25b2b 100644 --- a/tests/ui/coercion/retslot-cast.stderr +++ b/tests/ui/coercion/retslot-cast.stderr @@ -10,6 +10,6 @@ LL | inner(x) = note: expected enum `Option<&dyn Iterator>` found enum `Option<&dyn Iterator + Send>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coherence/coherence-all-remote.stderr b/tests/ui/coherence/coherence-all-remote.stderr index 7eca417533954..0cf9f87b40ac7 100644 --- a/tests/ui/coherence/coherence-all-remote.stderr +++ b/tests/ui/coherence/coherence-all-remote.stderr @@ -7,6 +7,6 @@ LL | impl Remote1 for isize { } = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/coherence-bigint-param.stderr b/tests/ui/coherence/coherence-bigint-param.stderr index e8d74c917e465..e6c77624a8e8d 100644 --- a/tests/ui/coherence/coherence-bigint-param.stderr +++ b/tests/ui/coherence/coherence-bigint-param.stderr @@ -7,6 +7,6 @@ LL | impl Remote1 for T { } = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr index 9156972a1df99..3618fe841b13e 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr @@ -7,6 +7,6 @@ LL | impl MyTrait for T { LL | impl MyTrait for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr index 8400968e1227d..510480f6a045f 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr @@ -7,6 +7,6 @@ LL | impl MyTrait for T { LL | impl MyTrait for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr index 4d7872598b1e7..4b86cffbe479f 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr @@ -8,6 +8,6 @@ LL | impl GoMut for MyThingy { - impl GoMut for G where G: Go; -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr index c2a925213da2d..ddb7474c2899a 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr @@ -7,6 +7,6 @@ LL | impl MyTrait for T { LL | impl MyTrait for MyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr index e1a5dffebdaad..b681285341bf4 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr @@ -7,6 +7,6 @@ LL | impl MyTrait for T { LL | impl MyTrait for MyType { | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific.stderr index ba60a2ea92947..164edff4a7b6e 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific.stderr @@ -7,6 +7,6 @@ LL | impl MyTrait for T { LL | impl MyTrait for MyType { | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-cow.re_a.stderr b/tests/ui/coherence/coherence-cow.re_a.stderr index fe4b5b4107895..0bc017817b67d 100644 --- a/tests/ui/coherence/coherence-cow.re_a.stderr +++ b/tests/ui/coherence/coherence-cow.re_a.stderr @@ -9,6 +9,6 @@ LL | impl Remote for Pair> { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-cow.re_b.stderr b/tests/ui/coherence/coherence-cow.re_b.stderr index da4ede3251ed8..9bdb49dcc04ff 100644 --- a/tests/ui/coherence/coherence-cow.re_b.stderr +++ b/tests/ui/coherence/coherence-cow.re_b.stderr @@ -9,6 +9,6 @@ LL | impl Remote for Pair,T> { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-cow.re_c.stderr b/tests/ui/coherence/coherence-cow.re_c.stderr index d1a20c0ca101b..dfff2667ebbcc 100644 --- a/tests/ui/coherence/coherence-cow.re_c.stderr +++ b/tests/ui/coherence/coherence-cow.re_c.stderr @@ -9,6 +9,6 @@ LL | impl Remote for Pair,U> { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-cross-crate-conflict.stderr b/tests/ui/coherence/coherence-cross-crate-conflict.stderr index 3d253d56a4565..812ce97721ccf 100644 --- a/tests/ui/coherence/coherence-cross-crate-conflict.stderr +++ b/tests/ui/coherence/coherence-cross-crate-conflict.stderr @@ -7,6 +7,6 @@ LL | impl Foo for A { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/coherence-error-suppression.stderr b/tests/ui/coherence/coherence-error-suppression.stderr index aadc80cb1c3ea..fcaa510c632a8 100644 --- a/tests/ui/coherence/coherence-error-suppression.stderr +++ b/tests/ui/coherence/coherence-error-suppression.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `DoesNotExist` in this scope LL | impl Foo for DoesNotExist {} | ^^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr index 7dabd97b94e82..316da26b54d4a 100644 --- a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr +++ b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -8,6 +8,6 @@ LL | impl<'a> Trait for fn(fn(&'a ())) {} | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-fn-implied-bounds.stderr b/tests/ui/coherence/coherence-fn-implied-bounds.stderr index 2018712043e23..b0dea74670925 100644 --- a/tests/ui/coherence/coherence-fn-implied-bounds.stderr +++ b/tests/ui/coherence/coherence-fn-implied-bounds.stderr @@ -16,5 +16,5 @@ note: the lint level is defined here LL | #![deny(coherence_leak_check)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-fn-inputs.stderr b/tests/ui/coherence/coherence-fn-inputs.stderr index 82bd8a35f4575..246ec5947b3e4 100644 --- a/tests/ui/coherence/coherence-fn-inputs.stderr +++ b/tests/ui/coherence/coherence-fn-inputs.stderr @@ -8,6 +8,6 @@ LL | impl Trait for for<'c> fn(&'c u32, &'c u32) { | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-free-vs-bound-region.stderr b/tests/ui/coherence/coherence-free-vs-bound-region.stderr index e2d84b833200c..c97b32e429d37 100644 --- a/tests/ui/coherence/coherence-free-vs-bound-region.stderr +++ b/tests/ui/coherence/coherence-free-vs-bound-region.stderr @@ -16,5 +16,5 @@ note: the lint level is defined here LL | #![deny(coherence_leak_check)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr index a35a95ef4bfab..db6a94748042d 100644 --- a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr +++ b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr @@ -9,6 +9,6 @@ LL | impl Misc for dyn Fundamental {} | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr index 684e528220f87..9f813d6d5716a 100644 --- a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr +++ b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr @@ -22,6 +22,6 @@ LL | trait Trait { type Assoc; } | ^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/coherence/coherence-inherited-subtyping.stderr b/tests/ui/coherence/coherence-inherited-subtyping.stderr index f60b2aa2735d5..5c5753939049e 100644 --- a/tests/ui/coherence/coherence-inherited-subtyping.stderr +++ b/tests/ui/coherence/coherence-inherited-subtyping.stderr @@ -9,6 +9,6 @@ LL | fn method1(&self) {} | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-lone-type-parameter.stderr b/tests/ui/coherence/coherence-lone-type-parameter.stderr index ef5b088365381..48d25bba8d714 100644 --- a/tests/ui/coherence/coherence-lone-type-parameter.stderr +++ b/tests/ui/coherence/coherence-lone-type-parameter.stderr @@ -7,6 +7,6 @@ LL | impl Remote for T { } = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/coherence-negative-impls-safe.stderr b/tests/ui/coherence/coherence-negative-impls-safe.stderr index 1bd37f395902a..759e50c3bea48 100644 --- a/tests/ui/coherence/coherence-negative-impls-safe.stderr +++ b/tests/ui/coherence/coherence-negative-impls-safe.stderr @@ -7,6 +7,6 @@ LL | unsafe impl !Send for TestType {} | | negative because of this | unsafe because of this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0198`. diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs b/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs index 0e16d12a18114..531977d6dac24 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs @@ -1,5 +1,9 @@ // revisions: stock with_negative_coherence + //[with_negative_coherence] known-bug: unknown +// Ideally this would work, but we don't use `&'a T` to imply that `T: 'a` +// which is required for `&'a T: !MyPredicate` to hold. This is similar to the +// test `negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr` #![feature(negative_impls)] #![cfg_attr(with_negative_coherence, feature(with_negative_coherence))] diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr index 097cc4e0fe3e6..dbb22d8937d54 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr @@ -1,11 +1,11 @@ error[E0119]: conflicting implementations of trait `MyTrait<'_>` for type `&_` - --> $DIR/coherence-negative-outlives-lifetimes.rs:14:1 + --> $DIR/coherence-negative-outlives-lifetimes.rs:18:1 | LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here LL | impl<'a, T> MyTrait<'a> for &'a T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr index 097cc4e0fe3e6..dbb22d8937d54 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr @@ -1,11 +1,11 @@ error[E0119]: conflicting implementations of trait `MyTrait<'_>` for type `&_` - --> $DIR/coherence-negative-outlives-lifetimes.rs:14:1 + --> $DIR/coherence-negative-outlives-lifetimes.rs:18:1 | LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here LL | impl<'a, T> MyTrait<'a> for &'a T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr b/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr index 8a43ad7b7f0e8..ca8d7a5c4c3b2 100644 --- a/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr +++ b/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr @@ -6,6 +6,6 @@ LL | impl MyTrait for T {} LL | impl MyTrait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-all-t-and-tuple.stderr b/tests/ui/coherence/coherence-overlap-all-t-and-tuple.stderr index 6a0880334b6e0..a6e47d9f92e79 100644 --- a/tests/ui/coherence/coherence-overlap-all-t-and-tuple.stderr +++ b/tests/ui/coherence/coherence-overlap-all-t-and-tuple.stderr @@ -7,6 +7,6 @@ LL | impl From for T { LL | impl From<(U11,)> for (T11,) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr index c02a679c149cf..2f3ad6278088f 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr @@ -9,6 +9,6 @@ LL | impl Cake> { fn dummy(&self) { } } | = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr index c02a679c149cf..2f3ad6278088f 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr @@ -9,6 +9,6 @@ LL | impl Cake> { fn dummy(&self) { } } | = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr index a4e87af8ac40e..b949477402549 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr @@ -8,6 +8,6 @@ LL | impl Sweet for Box { } | = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr index a4e87af8ac40e..b949477402549 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr @@ -8,6 +8,6 @@ LL | impl Sweet for Box { } | = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr index 4b55001ecc0e1..21c82eedd5df5 100644 --- a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr +++ b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr @@ -6,6 +6,6 @@ LL | impl Foo for T {} LL | impl Foo for &U {} | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-trait-alias.stderr b/tests/ui/coherence/coherence-overlap-trait-alias.stderr index 687f3af004032..4f277ad68a67d 100644 --- a/tests/ui/coherence/coherence-overlap-trait-alias.stderr +++ b/tests/ui/coherence/coherence-overlap-trait-alias.stderr @@ -6,6 +6,6 @@ LL | impl C for T {} LL | impl C for u32 {} | ^^^^^^^^^^^^^^ conflicting implementation for `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-upstream-inherent.stderr b/tests/ui/coherence/coherence-overlap-upstream-inherent.stderr index f355c6e855ce1..65885ecac41e0 100644 --- a/tests/ui/coherence/coherence-overlap-upstream-inherent.stderr +++ b/tests/ui/coherence/coherence-overlap-upstream-inherent.stderr @@ -9,6 +9,6 @@ LL | impl A { fn dummy(&self) { } } | = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-upstream.stderr b/tests/ui/coherence/coherence-overlap-upstream.stderr index 8272c88758607..212ef484afc43 100644 --- a/tests/ui/coherence/coherence-overlap-upstream.stderr +++ b/tests/ui/coherence/coherence-overlap-upstream.stderr @@ -8,6 +8,6 @@ LL | impl Foo for i16 {} | = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-with-regions.rs b/tests/ui/coherence/coherence-overlap-with-regions.rs index 9945c8e6cfd7b..32f01f4180103 100644 --- a/tests/ui/coherence/coherence-overlap-with-regions.rs +++ b/tests/ui/coherence/coherence-overlap-with-regions.rs @@ -1,10 +1,4 @@ -// known-bug: unknown - -// This fails because we currently perform negative coherence in coherence mode. -// This means that when looking for a negative predicate, we also assemble a -// coherence-unknowable predicate. Since confirming the negative impl has region -// obligations, we don't prefer the impl over the unknowable predicate -// unconditionally and instead flounder. +// check-pass #![feature(negative_impls)] #![feature(rustc_attrs)] diff --git a/tests/ui/coherence/coherence-overlap-with-regions.stderr b/tests/ui/coherence/coherence-overlap-with-regions.stderr deleted file mode 100644 index fd25f0978bad2..0000000000000 --- a/tests/ui/coherence/coherence-overlap-with-regions.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0119]: conflicting implementations of trait `Bar` for type `&_` - --> $DIR/coherence-overlap-with-regions.rs:20:1 - | -LL | impl Bar for T {} - | ---------------------- first implementation here -LL | impl Bar for &T where T: 'static {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlapping-pairs.stderr b/tests/ui/coherence/coherence-overlapping-pairs.stderr index 15c92dfeb07d7..4d0a9c6ee1400 100644 --- a/tests/ui/coherence/coherence-overlapping-pairs.stderr +++ b/tests/ui/coherence/coherence-overlapping-pairs.stderr @@ -9,6 +9,6 @@ LL | impl Remote for lib::Pair { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr index 03d7871238128..15cd66e9d09d0 100644 --- a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr +++ b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr @@ -10,6 +10,6 @@ LL | impl Remote1>> for i32 { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr index 73dfe2f572ae3..359dbe8509d80 100644 --- a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr +++ b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr @@ -9,6 +9,6 @@ LL | impl Remote for Pair> { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-projection-conflict-orphan.stderr b/tests/ui/coherence/coherence-projection-conflict-orphan.stderr index b1ee0795b2eb3..9760189930552 100644 --- a/tests/ui/coherence/coherence-projection-conflict-orphan.stderr +++ b/tests/ui/coherence/coherence-projection-conflict-orphan.stderr @@ -9,6 +9,6 @@ LL | impl Foo for A { } | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-projection-conflict-ty-param.stderr b/tests/ui/coherence/coherence-projection-conflict-ty-param.stderr index 94d242eaac431..f074467bbaa75 100644 --- a/tests/ui/coherence/coherence-projection-conflict-ty-param.stderr +++ b/tests/ui/coherence/coherence-projection-conflict-ty-param.stderr @@ -7,6 +7,6 @@ LL | LL | impl Foo for Option { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Option<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-projection-conflict.stderr b/tests/ui/coherence/coherence-projection-conflict.stderr index 7d2c584c37067..c916091e62db2 100644 --- a/tests/ui/coherence/coherence-projection-conflict.stderr +++ b/tests/ui/coherence/coherence-projection-conflict.stderr @@ -7,6 +7,6 @@ LL | LL | impl Foo for A { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-tuple-conflict.stderr b/tests/ui/coherence/coherence-tuple-conflict.stderr index 09ad5e5b22435..4e02c0eb43c7c 100644 --- a/tests/ui/coherence/coherence-tuple-conflict.stderr +++ b/tests/ui/coherence/coherence-tuple-conflict.stderr @@ -7,6 +7,6 @@ LL | impl MyTrait for (T,T) { LL | impl MyTrait for (A,B) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_, _)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr index a3a37fd277578..4f898ec127b9f 100644 --- a/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr +++ b/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr @@ -17,6 +17,6 @@ note: required by a bound in `takes_t` LL | fn takes_t(s: S) { | ^^^^^ required by this bound in `takes_t` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coherence/coherence-vec-local-2.stderr b/tests/ui/coherence/coherence-vec-local-2.stderr index 95fdf172ec255..e4249710d0028 100644 --- a/tests/ui/coherence/coherence-vec-local-2.stderr +++ b/tests/ui/coherence/coherence-vec-local-2.stderr @@ -9,6 +9,6 @@ LL | impl Remote for Vec> { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-vec-local.stderr b/tests/ui/coherence/coherence-vec-local.stderr index 4835e771abd3b..c465fb1966eb8 100644 --- a/tests/ui/coherence/coherence-vec-local.stderr +++ b/tests/ui/coherence/coherence-vec-local.stderr @@ -9,6 +9,6 @@ LL | impl Remote for Vec { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-wasm-bindgen.stderr b/tests/ui/coherence/coherence-wasm-bindgen.stderr index 600cd42d8c69d..b3c3dac612dbd 100644 --- a/tests/ui/coherence/coherence-wasm-bindgen.stderr +++ b/tests/ui/coherence/coherence-wasm-bindgen.stderr @@ -23,5 +23,5 @@ note: the lint level is defined here LL | #![deny(coherence_leak_check)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-with-closure.stderr b/tests/ui/coherence/coherence-with-closure.stderr index 431108e14d7d8..501279ffe6a72 100644 --- a/tests/ui/coherence/coherence-with-closure.stderr +++ b/tests/ui/coherence/coherence-with-closure.stderr @@ -6,6 +6,6 @@ LL | impl Trait for Wrapper {} LL | impl Trait for Wrapper {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-with-coroutine.stock.stderr b/tests/ui/coherence/coherence-with-coroutine.stock.stderr index b2a9135c542f8..9cf20ea493649 100644 --- a/tests/ui/coherence/coherence-with-coroutine.stock.stderr +++ b/tests/ui/coherence/coherence-with-coroutine.stock.stderr @@ -6,6 +6,6 @@ LL | impl Trait for Wrapper {} LL | impl Trait for Wrapper {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr index 93486fa5f3605..50bbe12bc20ab 100644 --- a/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr +++ b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr @@ -9,6 +9,6 @@ LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { } | = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence_copy_like_err_struct.stderr b/tests/ui/coherence/coherence_copy_like_err_struct.stderr index 7432733b932a4..715a825ceb075 100644 --- a/tests/ui/coherence/coherence_copy_like_err_struct.stderr +++ b/tests/ui/coherence/coherence_copy_like_err_struct.stderr @@ -9,6 +9,6 @@ LL | impl MyTrait for lib::MyStruct { } | = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyStruct` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence_copy_like_err_tuple.stderr b/tests/ui/coherence/coherence_copy_like_err_tuple.stderr index 090497ec18977..fbd293dba9aef 100644 --- a/tests/ui/coherence/coherence_copy_like_err_tuple.stderr +++ b/tests/ui/coherence/coherence_copy_like_err_tuple.stderr @@ -9,6 +9,6 @@ LL | impl MyTrait for (MyType,) { } | = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence_inherent.stderr b/tests/ui/coherence/coherence_inherent.stderr index b381b0680734f..da8c03847eda1 100644 --- a/tests/ui/coherence/coherence_inherent.stderr +++ b/tests/ui/coherence/coherence_inherent.stderr @@ -10,6 +10,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use Lib::TheTrait; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/coherence/coherence_inherent_cc.stderr b/tests/ui/coherence/coherence_inherent_cc.stderr index 7b6cb7d4390b4..d34f6fa213bec 100644 --- a/tests/ui/coherence/coherence_inherent_cc.stderr +++ b/tests/ui/coherence/coherence_inherent_cc.stderr @@ -10,6 +10,6 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f LL + use coherence_inherent_cc_lib::TheTrait; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/coherence/coherence_local_err_struct.stderr b/tests/ui/coherence/coherence_local_err_struct.stderr index afc6fc45d0e03..96572b5a71648 100644 --- a/tests/ui/coherence/coherence_local_err_struct.stderr +++ b/tests/ui/coherence/coherence_local_err_struct.stderr @@ -9,6 +9,6 @@ LL | impl lib::MyCopy for lib::MyStruct { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence_local_err_tuple.stderr b/tests/ui/coherence/coherence_local_err_tuple.stderr index a4953859f77fd..85a063bb34ae2 100644 --- a/tests/ui/coherence/coherence_local_err_tuple.stderr +++ b/tests/ui/coherence/coherence_local_err_tuple.stderr @@ -9,6 +9,6 @@ LL | impl lib::MyCopy for (MyType,) { } | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr index 7b6dd4b380f6f..e79abe35597d4 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.stderr +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -13,6 +13,6 @@ note: the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListCo LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/coherence/illegal-copy-bad-projection.stderr b/tests/ui/coherence/illegal-copy-bad-projection.stderr index 8fed9ba23b24b..2a74cb5a9b8b1 100644 --- a/tests/ui/coherence/illegal-copy-bad-projection.stderr +++ b/tests/ui/coherence/illegal-copy-bad-projection.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `void` in this scope LL | type Ptr = *const void; | ^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/coherence/impl-foreign-for-foreign.stderr b/tests/ui/coherence/impl-foreign-for-foreign.stderr index 93f7a6fdc25d3..6c74b47a1c48e 100644 --- a/tests/ui/coherence/impl-foreign-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign-for-foreign.stderr @@ -9,6 +9,6 @@ LL | impl Remote for i32 { | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr index 65b3aa394a85f..fe8a34b78cfd0 100644 --- a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr +++ b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr @@ -10,6 +10,6 @@ LL | impl Remote1 for f64 { | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr b/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr index 249a5c44c79cd..12d9a807f492d 100644 --- a/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr +++ b/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr @@ -7,6 +7,6 @@ LL | impl Remote for Box { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr b/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr index aed184767a0bd..6ca3ccd05febc 100644 --- a/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr +++ b/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr @@ -7,6 +7,6 @@ LL | impl Remote1 for T { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-t.stderr b/tests/ui/coherence/impl[t]-foreign[local]-for-t.stderr index d97e85dcb3c3e..1f3463e88371b 100644 --- a/tests/ui/coherence/impl[t]-foreign[local]-for-t.stderr +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-t.stderr @@ -7,6 +7,6 @@ LL | impl Remote1 for T { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr b/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr index 44e3b7eedb40c..a1f3936497e65 100644 --- a/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr @@ -7,6 +7,6 @@ LL | impl Remote1 for u32 { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr b/tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr index ff72969dc52ae..acd84f7115f57 100644 --- a/tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr @@ -7,6 +7,6 @@ LL | impl Remote1 for T { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr index 9b2dbc66ca7fd..74be598c44c76 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr @@ -12,6 +12,6 @@ LL | | I: Iterator, | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr index 9b2dbc66ca7fd..74be598c44c76 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr @@ -12,6 +12,6 @@ LL | | I: Iterator, | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.rs b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.rs new file mode 100644 index 0000000000000..5d8beb4513280 --- /dev/null +++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.rs @@ -0,0 +1,14 @@ +#![feature(negative_impls)] +#![feature(with_negative_coherence)] + +struct Wrap(T); + +trait Foo {} +impl !Foo for Box {} + +trait Bar {} +impl Bar for T where T: Foo {} +impl Bar for Box {} +//~^ ERROR conflicting implementations of trait `Bar` for type `Box<_>` + +fn main() {} diff --git a/tests/ui/coherence/negative-coherence-considering-regions.static_lt.stderr b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr similarity index 51% rename from tests/ui/coherence/negative-coherence-considering-regions.static_lt.stderr rename to tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr index 87e7be2aa44a9..f515c39ea8d10 100644 --- a/tests/ui/coherence/negative-coherence-considering-regions.static_lt.stderr +++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr @@ -1,12 +1,11 @@ -error[E0119]: conflicting implementations of trait `Bar` for type `&'static _` - --> $DIR/negative-coherence-considering-regions.rs:26:1 +error[E0119]: conflicting implementations of trait `Bar` for type `Box<_>` + --> $DIR/negative-coherence-check-placeholder-outlives.rs:11:1 | LL | impl Bar for T where T: Foo {} | ------------------------------ first implementation here -... -LL | impl Bar for &'static T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&'static _` +LL | impl Bar for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr index 4cf50b4f208e3..f24de10f6ac48 100644 --- a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr +++ b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Bar` for type `&_` - --> $DIR/negative-coherence-considering-regions.rs:22:1 + --> $DIR/negative-coherence-considering-regions.rs:16:1 | LL | impl Bar for T where T: Foo {} | ------------------------------ first implementation here @@ -7,6 +7,6 @@ LL | impl Bar for T where T: Foo {} LL | impl Bar for &T {} | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/negative-coherence-considering-regions.rs b/tests/ui/coherence/negative-coherence-considering-regions.rs index 597a597262846..a43ad19eca7c0 100644 --- a/tests/ui/coherence/negative-coherence-considering-regions.rs +++ b/tests/ui/coherence/negative-coherence-considering-regions.rs @@ -1,11 +1,5 @@ // revisions: any_lt static_lt -//[static_lt] known-bug: unknown - -// This fails because we currently perform negative coherence in coherence mode. -// This means that when looking for a negative predicate, we also assemble a -// coherence-unknowable predicate. Since confirming the negative impl has region -// obligations, we don't prefer the impl over the unknowable predicate -// unconditionally and instead flounder. +//[static_lt] check-pass #![feature(negative_impls)] #![feature(with_negative_coherence)] diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr new file mode 100644 index 0000000000000..5368db293383c --- /dev/null +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr @@ -0,0 +1,19 @@ +error: conflicting implementations of trait `FnMarker` for type `fn(&_)` + --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:21:1 + | +LL | impl FnMarker for fn(T) {} + | ------------------------------------------- first implementation here +LL | impl FnMarker for fn(&T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&_)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details +note: the lint level is defined here + --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11 + | +LL | #![forbid(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs new file mode 100644 index 0000000000000..26d9d84d8f0c9 --- /dev/null +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs @@ -0,0 +1,25 @@ +// revisions: explicit implicit +//[implicit] check-pass + +#![forbid(coherence_leak_check)] +#![feature(negative_impls, with_negative_coherence)] + +pub trait Marker {} + +#[cfg(implicit)] +impl !Marker for &T {} + +#[cfg(explicit)] +impl<'a, T: ?Sized + 'a> !Marker for &'a T {} + +trait FnMarker {} + +// Unifying these two impls below results in a `T: '!0` obligation +// that we shouldn't need to care about. Ideally, we'd treat that +// as an assumption when proving `&'!0 T: Marker`... +impl FnMarker for fn(T) {} +impl FnMarker for fn(&T) {} +//[explicit]~^ ERROR conflicting implementations of trait `FnMarker` for type `fn(&_)` +//[explicit]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +fn main() {} diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr new file mode 100644 index 0000000000000..0e48aaed87991 --- /dev/null +++ b/tests/ui/coherence/normalize-for-errors.current.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)` + --> $DIR/normalize-for-errors.rs:16:1 + | +LL | impl MyTrait for (T, S::Item) {} + | ------------------------------------------------------ first implementation here +LL | +LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)` + | + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr new file mode 100644 index 0000000000000..a8a7d437b32d3 --- /dev/null +++ b/tests/ui/coherence/normalize-for-errors.next.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` + --> $DIR/normalize-for-errors.rs:16:1 + | +LL | impl MyTrait for (T, S::Item) {} + | ------------------------------------------------------ first implementation here +LL | +LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` + | + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs new file mode 100644 index 0000000000000..367d34251ae30 --- /dev/null +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -0,0 +1,21 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next + +struct MyType; +trait MyTrait {} + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +impl MyTrait for (T, S::Item) {} +//~^ NOTE first implementation here +impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} +//~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, +//~| NOTE conflicting implementation for `(Box<(MyType,)>, +//~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions + +fn main() {} diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr new file mode 100644 index 0000000000000..69f541cba050a --- /dev/null +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -0,0 +1,25 @@ +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` + --> $DIR/associated-type.rs:31:1 + | +LL | impl Overlap for T { + | ------------------------ first implementation here +... +LL | / impl Overlap fn(&'a (), Assoc<'a, T>)> for T +LL | | +LL | | where +LL | | for<'a> *const T: ToUnit<'a>, + | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr new file mode 100644 index 0000000000000..c2c951af0dbb4 --- /dev/null +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -0,0 +1,25 @@ +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) }) +error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` + --> $DIR/associated-type.rs:31:1 + | +LL | impl Overlap for T { + | ------------------------ first implementation here +... +LL | / impl Overlap fn(&'a (), Assoc<'a, T>)> for T +LL | | +LL | | where +LL | | for<'a> *const T: ToUnit<'a>, + | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs new file mode 100644 index 0000000000000..909551f65be49 --- /dev/null +++ b/tests/ui/coherence/occurs-check/associated-type.rs @@ -0,0 +1,45 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next + +// A regression test for #105787 + +// Using the higher ranked projection hack to prevent us from replacing the projection +// with an inference variable. +trait ToUnit<'a> { + type Unit; +} + +struct LocalTy; +impl<'a> ToUnit<'a> for *const LocalTy { + type Unit = (); +} + +impl<'a, T: Copy + ?Sized> ToUnit<'a> for *const T { + type Unit = (); +} + +trait Overlap { + type Assoc; +} + +type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; + +impl Overlap for T { + type Assoc = usize; +} + +impl Overlap fn(&'a (), Assoc<'a, T>)> for T +//~^ ERROR conflicting implementations of trait +where + for<'a> *const T: ToUnit<'a>, +{ + type Assoc = Box; +} + +fn foo, U>(x: T::Assoc) -> T::Assoc { + x +} + +fn main() { + foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); +} diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr new file mode 100644 index 0000000000000..428ee902ea528 --- /dev/null +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait>` for type `Alias<_>` + --> $DIR/opaques.rs:29:1 + | +LL | impl Trait for T { + | ---------------------- first implementation here +... +LL | impl Trait for defining_scope::Alias { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias<_>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs new file mode 100644 index 0000000000000..9d31a3dc82da9 --- /dev/null +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -0,0 +1,37 @@ +//revisions: old next +//[next] compile-flags: -Ztrait-solver=next + +// A regression test for #105787 + +//[old] known-bug: #105787 +//[old] check-pass +#![feature(type_alias_impl_trait)] +mod defining_scope { + use super::*; + pub type Alias = impl Sized; + + pub fn cast(x: Container, T>) -> Container { + x + } +} + +struct Container, U> { + x: >::Assoc, +} + +trait Trait { + type Assoc; +} + +impl Trait for T { + type Assoc = Box; +} +impl Trait for defining_scope::Alias { + //[next]~^ ERROR conflicting implementations of trait + type Assoc = usize; +} + +fn main() { + let x: Box = defining_scope::cast::<()>(Container { x: 0 }).x; + println!("{}", *x); +} diff --git a/tests/ui/coherence/strict-coherence-needs-negative-coherence.stderr b/tests/ui/coherence/strict-coherence-needs-negative-coherence.stderr index b5472928778eb..82804e8baac48 100644 --- a/tests/ui/coherence/strict-coherence-needs-negative-coherence.stderr +++ b/tests/ui/coherence/strict-coherence-needs-negative-coherence.stderr @@ -6,5 +6,5 @@ LL | #[rustc_strict_coherence] LL | trait Foo {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr index 4f32639a63107..4535b6f681152 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr @@ -22,7 +22,7 @@ note: the lint level is defined here LL | #![deny(coinductive_overlap_in_coherence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: error: implementations of `PartialEq>` for `Interval<_>` will conflict in the future diff --git a/tests/ui/command-line-diagnostics.stderr b/tests/ui/command-line-diagnostics.stderr index 6223ad880d695..b719a00ad5ddd 100644 --- a/tests/ui/command-line-diagnostics.stderr +++ b/tests/ui/command-line-diagnostics.stderr @@ -9,6 +9,6 @@ LL | let x = 42; LL | x = 43; | ^^^^^^ cannot assign twice to immutable variable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr b/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr index 305f76694f71a..89f7210c048e1 100644 --- a/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr +++ b/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr @@ -2,5 +2,5 @@ error: invalid character `'.'` in crate name: `need_crate_arg_ignore_tidy.x` | = help: you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/compare-method/proj-outlives-region.stderr b/tests/ui/compare-method/proj-outlives-region.stderr index 797a8167931f8..b349e24f589b4 100644 --- a/tests/ui/compare-method/proj-outlives-region.stderr +++ b/tests/ui/compare-method/proj-outlives-region.stderr @@ -7,6 +7,6 @@ LL | fn foo() where T: 'a; LL | fn foo() where U: 'a { } | ^^ impl has extra requirement `U: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/region-extra-2.stderr b/tests/ui/compare-method/region-extra-2.stderr index eb19d57ab05ac..3f55f67311763 100644 --- a/tests/ui/compare-method/region-extra-2.stderr +++ b/tests/ui/compare-method/region-extra-2.stderr @@ -12,6 +12,6 @@ help: copy the `where` clause predicates from the trait LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'b: 'a { | ~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/region-extra.stderr b/tests/ui/compare-method/region-extra.stderr index 1a471e18d9dc1..065b3c152edca 100644 --- a/tests/ui/compare-method/region-extra.stderr +++ b/tests/ui/compare-method/region-extra.stderr @@ -13,6 +13,6 @@ LL - fn foo() where 'a: 'b { } LL + fn foo() { } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/region-unrelated.stderr b/tests/ui/compare-method/region-unrelated.stderr index f7ae6f94438e2..75a4d51ce8fb1 100644 --- a/tests/ui/compare-method/region-unrelated.stderr +++ b/tests/ui/compare-method/region-unrelated.stderr @@ -7,6 +7,6 @@ LL | fn foo() where T: 'a; LL | fn foo() where V: 'a { } | ^^ impl has extra requirement `V: 'a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/reordered-type-param.stderr b/tests/ui/compare-method/reordered-type-param.stderr index 1552d542d15de..8a439acee13de 100644 --- a/tests/ui/compare-method/reordered-type-param.stderr +++ b/tests/ui/compare-method/reordered-type-param.stderr @@ -19,6 +19,6 @@ LL | fn b(&self, x: C) -> C; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/compare-method/trait-bound-on-type-parameter.stderr b/tests/ui/compare-method/trait-bound-on-type-parameter.stderr index ce6885c1541f7..0899d5406f996 100644 --- a/tests/ui/compare-method/trait-bound-on-type-parameter.stderr +++ b/tests/ui/compare-method/trait-bound-on-type-parameter.stderr @@ -7,6 +7,6 @@ LL | fn b(&self, x: C) -> C; LL | fn b(&self, _x: F) -> F { panic!() } | ^^^^ impl has extra requirement `F: Sync` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/traits-misc-mismatch-2.stderr b/tests/ui/compare-method/traits-misc-mismatch-2.stderr index 36bb764d40eb4..b8d3fd02ab5a7 100644 --- a/tests/ui/compare-method/traits-misc-mismatch-2.stderr +++ b/tests/ui/compare-method/traits-misc-mismatch-2.stderr @@ -7,6 +7,6 @@ LL | fn zip>(self, other: U) -> ZipIterator; LL | fn zip>(self, other: U) -> ZipIterator { | ^^^^^^^^^^^ impl has extra requirement `U: Iterator` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compile_error_macro.stderr b/tests/ui/compile_error_macro.stderr index 91ebcaa6e9de6..92d5564e8a7c7 100644 --- a/tests/ui/compile_error_macro.stderr +++ b/tests/ui/compile_error_macro.stderr @@ -4,5 +4,5 @@ error: a very descriptive error message LL | compile_error!("a very descriptive error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr index d61872c48ea96..5f7fea0965f65 100644 --- a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -4,6 +4,6 @@ error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` LL | fn main() { } | ^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/conditional-compilation/cfg-attr-crate-2.stderr b/tests/ui/conditional-compilation/cfg-attr-crate-2.stderr index 4997ca4db27cd..82dc436199909 100644 --- a/tests/ui/conditional-compilation/cfg-attr-crate-2.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-crate-2.stderr @@ -7,6 +7,6 @@ LL | #![cfg_attr(broken, no_core)] = note: see issue #29639 for more information = help: add `#![feature(no_core)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr index 96c571ebebdb4..2033894b3b4f6 100644 --- a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr @@ -4,6 +4,6 @@ error[E0537]: invalid predicate `foo` LL | #[cfg(foo(bar))] | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0537`. diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr index c8762d15d942a..daba4eb1a63df 100644 --- a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr @@ -7,6 +7,6 @@ LL | #![cfg_attr(broken, no_core, no_std)] = note: see issue #29639 for more information = help: add `#![feature(no_core)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr index e75b1c5b4c87c..675792d2e3219 100644 --- a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr @@ -7,6 +7,6 @@ LL | #![cfg_attr(broken, no_std, no_core)] = note: see issue #29639 for more information = help: add `#![feature(no_core)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr index fc8df6552c3e1..c91ad128d6e57 100644 --- a/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr @@ -9,5 +9,5 @@ LL | foo!(); | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr index ff72c43efbd08..98be6d01f1bbf 100644 --- a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -4,6 +4,6 @@ error[E0601]: `main` function not found in crate `cfg_in_crate_1` LL | #![cfg(bar)] | ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/conditional-compilation/cfg_accessible-stuck.stderr b/tests/ui/conditional-compilation/cfg_accessible-stuck.stderr index 33af7d62548ec..22ed1c5a39ec1 100644 --- a/tests/ui/conditional-compilation/cfg_accessible-stuck.stderr +++ b/tests/ui/conditional-compilation/cfg_accessible-stuck.stderr @@ -4,5 +4,5 @@ error: cannot determine whether the path is accessible or not LL | #[cfg_accessible(S)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr b/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr index 2f55b9559c78f..f034419097679 100644 --- a/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr +++ b/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr @@ -7,6 +7,6 @@ LL | #[cfg_accessible(std)] = note: see issue #64797 for more information = help: add `#![feature(cfg_accessible)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/test-cfg.stderr b/tests/ui/conditional-compilation/test-cfg.stderr index c35fe2f9458d4..9715f16acc20c 100644 --- a/tests/ui/conditional-compilation/test-cfg.stderr +++ b/tests/ui/conditional-compilation/test-cfg.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `foo` in this scope LL | foo(); | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/confuse-field-and-method/issue-18343.stderr b/tests/ui/confuse-field-and-method/issue-18343.stderr index 1c9a6847ceb4f..a51fd4f02aabf 100644 --- a/tests/ui/confuse-field-and-method/issue-18343.stderr +++ b/tests/ui/confuse-field-and-method/issue-18343.stderr @@ -12,6 +12,6 @@ help: to call the function stored in `closure`, surround the field access with p LL | (o.closure)(); | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/confuse-field-and-method/issue-32128.stderr b/tests/ui/confuse-field-and-method/issue-32128.stderr index 4b96bce8d2e82..3d860d8c85a12 100644 --- a/tests/ui/confuse-field-and-method/issue-32128.stderr +++ b/tests/ui/confuse-field-and-method/issue-32128.stderr @@ -12,6 +12,6 @@ help: to call the function stored in `example`, surround the field access with p LL | (demo.example)(1); | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/confuse-field-and-method/private-field.stderr b/tests/ui/confuse-field-and-method/private-field.stderr index 783378f8db58d..142c84504276a 100644 --- a/tests/ui/confuse-field-and-method/private-field.stderr +++ b/tests/ui/confuse-field-and-method/private-field.stderr @@ -7,6 +7,6 @@ LL | pub struct Dog { LL | let dog_age = dog.dog_age(); | ^^^^^^^ private field, not a method -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/conservative_impl_trait.stderr b/tests/ui/conservative_impl_trait.stderr index 63a4df242f85f..eecdb6f92667c 100644 --- a/tests/ui/conservative_impl_trait.stderr +++ b/tests/ui/conservative_impl_trait.stderr @@ -6,6 +6,6 @@ LL | fn will_ice(something: &u32) -> impl Iterator { | = help: the trait `Iterator` is not implemented for `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr index ef55242df8742..1177965d0d2c2 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr @@ -11,6 +11,6 @@ note: required by a bound in `check` LL | fn check() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs index bf8202ac15267..d51696f9ebde9 100644 --- a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs @@ -9,9 +9,9 @@ pub trait Parse { } pub trait CoolStuff: Parse {} -//~^ ERROR expected associated constant bound -//~| ERROR expected associated constant bound -//~| ERROR expected type +//~^ ERROR expected type, found variant +//~| ERROR expected constant, found type +//~| ERROR expected constant, found type fn no_help() -> Mode::Cool {} //~^ ERROR expected type, found variant diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr index 6d5cd45479ec7..3d724bb164247 100644 --- a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr @@ -16,30 +16,42 @@ LL | fn no_help() -> Mode::Cool {} | not a type | help: try using the variant's enum: `Mode` -error: expected associated constant bound, found type - --> $DIR/assoc_const_eq_diagnostic.rs:11:28 +error: expected constant, found type + --> $DIR/assoc_const_eq_diagnostic.rs:11:35 | LL | pub trait CoolStuff: Parse {} - | ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }` + | ---- ^^^^^^^^^^ unexpected type + | | + | expected a constant because of this associated constant | -note: associated constant defined here +note: the associated constant is defined here --> $DIR/assoc_const_eq_diagnostic.rs:8:5 | LL | const MODE: Mode; | ^^^^^^^^^^^^^^^^ +help: consider adding braces here + | +LL | pub trait CoolStuff: Parse {} + | + + -error: expected associated constant bound, found type - --> $DIR/assoc_const_eq_diagnostic.rs:11:28 +error: expected constant, found type + --> $DIR/assoc_const_eq_diagnostic.rs:11:35 | LL | pub trait CoolStuff: Parse {} - | ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }` + | ---- ^^^^^^^^^^ unexpected type + | | + | expected a constant because of this associated constant | -note: associated constant defined here +note: the associated constant is defined here --> $DIR/assoc_const_eq_diagnostic.rs:8:5 | LL | const MODE: Mode; | ^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding braces here + | +LL | pub trait CoolStuff: Parse {} + | + + error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/associated-type-bound-fail.stderr b/tests/ui/const-generics/associated-type-bound-fail.stderr index e5e7ee26e44bc..602a8927a8530 100644 --- a/tests/ui/const-generics/associated-type-bound-fail.stderr +++ b/tests/ui/const-generics/associated-type-bound-fail.stderr @@ -11,6 +11,6 @@ note: required by a bound in `Foo::Assoc` LL | type Assoc: Bar; | ^^^^^^ required by this bound in `Foo::Assoc` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/bad-generic-in-copy-impl.stderr b/tests/ui/const-generics/bad-generic-in-copy-impl.stderr index 25701ce68ccc8..d60d8ec0e90d3 100644 --- a/tests/ui/const-generics/bad-generic-in-copy-impl.stderr +++ b/tests/ui/const-generics/bad-generic-in-copy-impl.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | x: [u8; SIZE], | ^^^^ expected `usize`, found `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr index bd24f9140e4ea..6f5bc567c378b 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.stderr +++ b/tests/ui/const-generics/bad-subst-const-kind.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | impl Q for [u8; N] { | ^ expected `usize`, found `u64` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr index f1f22e2342d4d..ce7fce2599360 100644 --- a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr +++ b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -5,7 +5,7 @@ LL | let _: [u8; foo::()]; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:16:23 @@ -14,7 +14,7 @@ LL | let _: [u8; bar::()]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:18:23 @@ -23,7 +23,7 @@ LL | let _: [u8; faz::<'a>(&())]; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:20:23 @@ -32,7 +32,7 @@ LL | let _: [u8; baz::<'a>(&())]; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:21:23 @@ -41,7 +41,7 @@ LL | let _: [u8; faz::<'b>(&())]; | ^^ cannot perform const operation using `'b` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:23:23 @@ -50,7 +50,7 @@ LL | let _: [u8; baz::<'b>(&())]; | ^^ cannot perform const operation using `'b` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:26:23 @@ -59,7 +59,7 @@ LL | let _ = [0; bar::()]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:28:23 @@ -68,7 +68,7 @@ LL | let _ = [0; faz::<'a>(&())]; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:30:23 @@ -77,7 +77,7 @@ LL | let _ = [0; baz::<'a>(&())]; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:31:23 @@ -86,7 +86,7 @@ LL | let _ = [0; faz::<'b>(&())]; | ^^ cannot perform const operation using `'b` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:33:23 @@ -95,7 +95,7 @@ LL | let _ = [0; baz::<'b>(&())]; | ^^ cannot perform const operation using `'b` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:34:24 @@ -104,7 +104,7 @@ LL | let _: Foo<{ foo::() }>; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:35:24 @@ -113,7 +113,7 @@ LL | let _: Foo<{ bar::() }>; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:37:24 @@ -122,7 +122,7 @@ LL | let _: Foo<{ faz::<'a>(&()) }>; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:39:24 @@ -131,7 +131,7 @@ LL | let _: Foo<{ baz::<'a>(&()) }>; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:40:24 @@ -140,7 +140,7 @@ LL | let _: Foo<{ faz::<'b>(&()) }>; | ^^ cannot perform const operation using `'b` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:42:24 @@ -149,7 +149,7 @@ LL | let _: Foo<{ baz::<'b>(&()) }>; | ^^ cannot perform const operation using `'b` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:43:27 @@ -158,7 +158,7 @@ LL | let _ = Foo::<{ foo::() }>; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:44:27 @@ -167,7 +167,7 @@ LL | let _ = Foo::<{ bar::() }>; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:46:27 @@ -176,7 +176,7 @@ LL | let _ = Foo::<{ faz::<'a>(&()) }>; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:48:27 @@ -185,7 +185,7 @@ LL | let _ = Foo::<{ baz::<'a>(&()) }>; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:49:27 @@ -194,7 +194,7 @@ LL | let _ = Foo::<{ faz::<'b>(&()) }>; | ^^ cannot perform const operation using `'b` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:51:27 @@ -203,7 +203,7 @@ LL | let _ = Foo::<{ baz::<'b>(&()) }>; | ^^ cannot perform const operation using `'b` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0747]: unresolved item provided when a constant was expected --> $DIR/const-arg-in-const-arg.rs:16:23 diff --git a/tests/ui/const-generics/const-arg-type-arg-misordered.stderr b/tests/ui/const-generics/const-arg-type-arg-misordered.stderr index 4e12f7a8c6e69..e91b885803ee5 100644 --- a/tests/ui/const-generics/const-arg-type-arg-misordered.stderr +++ b/tests/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -4,6 +4,6 @@ error[E0747]: constant provided when a type was expected LL | fn foo() -> Array { | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/const-argument-if-length.min.stderr b/tests/ui/const-generics/const-argument-if-length.min.stderr index 3ba9ffebd4de6..b9d9bcc927069 100644 --- a/tests/ui/const-generics/const-argument-if-length.min.stderr +++ b/tests/ui/const-generics/const-argument-if-length.min.stderr @@ -5,7 +5,7 @@ LL | pad: [u8; is_zst::()], | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/const-argument-if-length.rs:15:12 diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr index 310ca75fdc90c..a1254672c9dc9 100644 --- a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr +++ b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr @@ -5,7 +5,7 @@ LL | let _: &'a (); | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr b/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr index a345c48b088cc..4cea35f1c8eb9 100644 --- a/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr +++ b/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr @@ -11,6 +11,6 @@ help: consider assigning a value LL | let s: &'static str = todo!(); s.len() | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/const-generics/const-param-before-other-params.stderr b/tests/ui/const-generics/const-param-before-other-params.stderr index 2c7a47bbc78cd..8f8c87afe8514 100644 --- a/tests/ui/const-generics/const-param-before-other-params.stderr +++ b/tests/ui/const-generics/const-param-before-other-params.stderr @@ -4,5 +4,5 @@ error: lifetime parameters must be declared prior to type and const parameters LL | fn bar(_: &'a ()) { | --------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const X: u8>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr index c5160d1c3848d..55bced29aff10 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -6,6 +6,6 @@ LL | struct B(PhantomData<[T; N]>); | = note: type parameters may not be used in the type of const parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr index e508890dd7c8b..2bfa604fc5673 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr @@ -6,6 +6,6 @@ LL | pub struct Dependent([(); X]); | = note: type parameters may not be used in the type of const parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr index e508890dd7c8b..2bfa604fc5673 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr @@ -6,6 +6,6 @@ LL | pub struct Dependent([(); X]); | = note: type parameters may not be used in the type of const parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-with-additional-obligations.stderr b/tests/ui/const-generics/const-param-with-additional-obligations.stderr index f7ec4d57401c1..a05554d7a3670 100644 --- a/tests/ui/const-generics/const-param-with-additional-obligations.stderr +++ b/tests/ui/const-generics/const-param-with-additional-obligations.stderr @@ -6,6 +6,6 @@ LL | fn foo>() {} | = note: `u8` must implement `Other`, but it does not -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/const-parameter-uppercase-lint.stderr b/tests/ui/const-generics/const-parameter-uppercase-lint.stderr index efaa182852aca..2a5ca5d39ceae 100644 --- a/tests/ui/const-generics/const-parameter-uppercase-lint.stderr +++ b/tests/ui/const-generics/const-parameter-uppercase-lint.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(non_upper_case_globals)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr index b836cfeaedbb7..199546c0883f3 100644 --- a/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr +++ b/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -5,7 +5,7 @@ LL | struct Foo; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-generic-default-expr.rs:9:62 @@ -14,7 +14,7 @@ LL | struct Bar() }>(T); | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/defaults/default-on-impl.stderr b/tests/ui/const-generics/defaults/default-on-impl.stderr index 4b2b05742538b..691e0354eddc2 100644 --- a/tests/ui/const-generics/defaults/default-on-impl.stderr +++ b/tests/ui/const-generics/defaults/default-on-impl.stderr @@ -4,5 +4,5 @@ error: defaults for const parameters are only allowed in `struct`, `enum`, `type LL | impl Foo {} | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr index 4259ce2b626fe..35aae46244379 100644 --- a/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | struct Foo; | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr index 4259ce2b626fe..35aae46244379 100644 --- a/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | struct Foo; | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr index a61411d6eb6e7..65ee0ecfdc5a4 100644 --- a/tests/ui/const-generics/defaults/doesnt_infer.stderr +++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr @@ -9,6 +9,6 @@ help: consider giving `foo` an explicit type, where the value of const parameter LL | let foo: Foo = Foo::foo(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr b/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr index 61b3551182c90..fbf1adfb7a520 100644 --- a/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr +++ b/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr @@ -7,6 +7,6 @@ LL | Foo::<10, 12> = note: expected constant `11` found constant `12` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr index e83f89a60333f..25b3fed0daffd 100644 --- a/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr +++ b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr @@ -7,6 +7,6 @@ LL | Foo:: = note: expected constant `{ N + 1 }` found constant `{ N + 2 }` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr index ba08b4646d0f4..bf2b21c012d42 100644 --- a/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr +++ b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr @@ -4,5 +4,5 @@ error: lifetime parameters must be declared prior to type and const parameters LL | struct Foo(&'a u32); | ----------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const M: usize = 10>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/defaults/self-referential.stderr b/tests/ui/const-generics/defaults/self-referential.stderr index 170c1f7f7b2ae..be67ea3f5039b 100644 --- a/tests/ui/const-generics/defaults/self-referential.stderr +++ b/tests/ui/const-generics/defaults/self-referential.stderr @@ -6,6 +6,6 @@ LL | trait Foo {} | | | first use of `M` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/const-generics/different_generic_args.full.stderr b/tests/ui/const-generics/different_generic_args.full.stderr index eba1768f7dda3..8a72b5aff6de0 100644 --- a/tests/ui/const-generics/different_generic_args.full.stderr +++ b/tests/ui/const-generics/different_generic_args.full.stderr @@ -7,6 +7,6 @@ LL | u = ConstUsize::<4> {}; = note: expected struct `ConstUsize<3>` found struct `ConstUsize<4>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/different_generic_args.min.stderr b/tests/ui/const-generics/different_generic_args.min.stderr index eba1768f7dda3..8a72b5aff6de0 100644 --- a/tests/ui/const-generics/different_generic_args.min.stderr +++ b/tests/ui/const-generics/different_generic_args.min.stderr @@ -7,6 +7,6 @@ LL | u = ConstUsize::<4> {}; = note: expected struct `ConstUsize<3>` found struct `ConstUsize<4>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/different_generic_args_array.stderr b/tests/ui/const-generics/different_generic_args_array.stderr index 4c5b5ada4f132..e185474f5bd8f 100644 --- a/tests/ui/const-generics/different_generic_args_array.stderr +++ b/tests/ui/const-generics/different_generic_args_array.stderr @@ -7,6 +7,6 @@ LL | x = Const::<{ [4] }> {}; = note: expected struct `Const<[3]>` found struct `Const<[4]>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr index b3a2756602603..4e9e001f2c1a4 100644 --- a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr +++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/early/const-expression-parameter.stderr b/tests/ui/const-generics/early/const-expression-parameter.stderr index 4ce1be25edb93..ca4db8e28dad3 100644 --- a/tests/ui/const-generics/early/const-expression-parameter.stderr +++ b/tests/ui/const-generics/early/const-expression-parameter.stderr @@ -9,5 +9,5 @@ help: enclose the `const` expression in braces LL | i32_identity::<{ 1 + 2 }>(); | + + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr index 826f2657905d3..faba4ce10a1b4 100644 --- a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr +++ b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr @@ -8,6 +8,6 @@ LL | fn bar() -> u32 { LL | X | ^ use of generic parameter from outer item -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/const-generics/early/const-param-shadowing.stderr b/tests/ui/const-generics/early/const-param-shadowing.stderr index 625338bd9b4a6..3ae2c9c8e60b1 100644 --- a/tests/ui/const-generics/early/const-param-shadowing.stderr +++ b/tests/ui/const-generics/early/const-param-shadowing.stderr @@ -9,6 +9,6 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | fn test() -> Foo<{ N }> { | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/early/macro_rules-braces.stderr b/tests/ui/const-generics/early/macro_rules-braces.stderr index 49382dbf0bd50..3269506680109 100644 --- a/tests/ui/const-generics/early/macro_rules-braces.stderr +++ b/tests/ui/const-generics/early/macro_rules-braces.stderr @@ -27,7 +27,7 @@ LL | let _: foo!({{ N }}); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:36:19 @@ -36,7 +36,7 @@ LL | let _: bar!({ N }); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:41:20 @@ -45,7 +45,7 @@ LL | let _: baz!({{ N }}); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:46:19 @@ -54,7 +54,7 @@ LL | let _: biz!({ N }); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/ensure_is_evaluatable.stderr b/tests/ui/const-generics/ensure_is_evaluatable.stderr index ab2871ff28127..a6f362308200a 100644 --- a/tests/ui/const-generics/ensure_is_evaluatable.stderr +++ b/tests/ui/const-generics/ensure_is_evaluatable.stderr @@ -14,5 +14,5 @@ LL | where LL | [(); N + 1]:, | ^^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/exhaustive-value.stderr b/tests/ui/const-generics/exhaustive-value.stderr index deb65ddba708c..42814c1fb7056 100644 --- a/tests/ui/const-generics/exhaustive-value.stderr +++ b/tests/ui/const-generics/exhaustive-value.stderr @@ -15,6 +15,6 @@ LL | <() as Foo>::test() <() as Foo<7>> and 248 others -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/float-generic.adt_const_params.stderr b/tests/ui/const-generics/float-generic.adt_const_params.stderr index 6fe5390471ddc..cae4806368a90 100644 --- a/tests/ui/const-generics/float-generic.adt_const_params.stderr +++ b/tests/ui/const-generics/float-generic.adt_const_params.stderr @@ -4,6 +4,6 @@ error[E0741]: `f32` is forbidden as the type of a const generic parameter LL | fn foo() {} | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/float-generic.simple.stderr b/tests/ui/const-generics/float-generic.simple.stderr index aeb19dc75322d..eccf9059ee335 100644 --- a/tests/ui/const-generics/float-generic.simple.stderr +++ b/tests/ui/const-generics/float-generic.simple.stderr @@ -6,5 +6,5 @@ LL | fn foo() {} | = note: the only supported types are integers, `bool` and `char` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/fn-const-param-infer.full.stderr b/tests/ui/const-generics/fn-const-param-infer.full.stderr index 2d66a19233269..48d4a45345af8 100644 --- a/tests/ui/const-generics/fn-const-param-infer.full.stderr +++ b/tests/ui/const-generics/fn-const-param-infer.full.stderr @@ -4,6 +4,6 @@ error[E0741]: using function pointers as const generic parameters is forbidden LL | struct Checked bool>; | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/fn-const-param-infer.min.stderr b/tests/ui/const-generics/fn-const-param-infer.min.stderr index a7afa48427594..f6d41809d67da 100644 --- a/tests/ui/const-generics/fn-const-param-infer.min.stderr +++ b/tests/ui/const-generics/fn-const-param-infer.min.stderr @@ -6,5 +6,5 @@ LL | struct Checked bool>; | = note: the only supported types are integers, `bool` and `char` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/fn_with_two_const_inputs.stderr b/tests/ui/const-generics/fn_with_two_const_inputs.stderr index c124010aab05b..ad32a688c03f7 100644 --- a/tests/ui/const-generics/fn_with_two_const_inputs.stderr +++ b/tests/ui/const-generics/fn_with_two_const_inputs.stderr @@ -14,5 +14,5 @@ LL | where LL | [(); N + 1]:, | ^^^^^ required by this bound in `bar` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/forbid-non-structural_match-types.stderr b/tests/ui/const-generics/forbid-non-structural_match-types.stderr index 0efb9e9d3c287..94afded9469e8 100644 --- a/tests/ui/const-generics/forbid-non-structural_match-types.stderr +++ b/tests/ui/const-generics/forbid-non-structural_match-types.stderr @@ -10,6 +10,6 @@ LL + #[derive(ConstParamTy, PartialEq, Eq)] LL | struct C; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/generic-param-mismatch.stderr b/tests/ui/const-generics/generic-param-mismatch.stderr index d0776d49d71ba..be6b3b90ec72a 100644 --- a/tests/ui/const-generics/generic-param-mismatch.stderr +++ b/tests/ui/const-generics/generic-param-mismatch.stderr @@ -9,6 +9,6 @@ LL | [0; N] = note: expected array `[u8; M]` found array `[u8; N]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr index 0096d4ee23d11..f2cc17bc517cd 100644 --- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed for `Mask<_, LANES>` +error[E0283]: type annotations needed for `Mask<_, N>` --> $DIR/issue-91614.rs:6:9 | LL | let y = Mask::<_, _>::splat(false); @@ -11,13 +11,13 @@ LL | let y = Mask::<_, _>::splat(false); i16 i32 i64 -note: required by a bound in `Mask::::splat` +note: required by a bound in `Mask::::splat` --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL help: consider giving `y` an explicit type, where the type for type parameter `T` is specified | -LL | let y: Mask<_, LANES> = Mask::<_, _>::splat(false); - | ++++++++++++++++ +LL | let y: Mask<_, N> = Mask::<_, _>::splat(false); + | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr index d48b639dbdee3..4b76ae6cfd56d 100644 --- a/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr +++ b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr @@ -6,5 +6,5 @@ LL | bar::<{ N as usize as usize }>(); | = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr index 64d1e0bcff4e0..1f4b892e20f97 100644 --- a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr @@ -5,7 +5,7 @@ LL | struct ArithArrayLen([u32; 0 + N]); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/array-size-in-generic-struct-param.rs:23:15 @@ -14,7 +14,7 @@ LL | arr: [u8; CFG.arr_size], | ^^^ cannot perform const operation using `CFG` | = help: const parameters may only be used as standalone arguments, i.e. `CFG` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: `Config` is forbidden as the type of a const generic parameter --> $DIR/array-size-in-generic-struct-param.rs:21:21 diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr index e4a0cabe57284..a8657bf5263a8 100644 --- a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr @@ -6,5 +6,5 @@ LL | bar::<{ T::ASSOC }>(); | = help: try adding a `where` bound using this expression: `where [(); { T::ASSOC }]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/closures.stderr b/tests/ui/const-generics/generic_const_exprs/closures.stderr index 45d7922bd0b80..e245a6dab25fa 100644 --- a/tests/ui/const-generics/generic_const_exprs/closures.stderr +++ b/tests/ui/const-generics/generic_const_exprs/closures.stderr @@ -22,6 +22,6 @@ LL | fn test() -> [u8; N + (|| 42)()] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr index f262599084015..a85e0cbcf7e99 100644 --- a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr @@ -16,5 +16,5 @@ LL | let _ = [0u8; const { std::mem::size_of::() }]; = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr index d674e3acdffde..f454ff4e6c036 100644 --- a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr @@ -5,7 +5,7 @@ LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/dependence_lint.rs:21:37 @@ -14,7 +14,7 @@ LL | let _: [u8; if true { size_of::() } else { 3 }]; // error on stable, | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions warning: cannot use constants which depend on generic parameters in types --> $DIR/dependence_lint.rs:10:9 diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr index 2d9de8805bb55..043fa34d605ab 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -7,6 +7,6 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr index 2d60ebaa83a1c..9c4e3d8583c04 100644 --- a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr +++ b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr @@ -5,7 +5,7 @@ LL | type Arr = [u8; N - 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr index bd71b49ee238b..080e920258dc7 100644 --- a/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr +++ b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of `test::<0>::{constant#0}` failed LL | fn test() -> [u8; N - 1] { | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr index 827dd59d9ad33..09b618fb3f050 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | Combination::<0>.and::<_>().and::<_>(); | ~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr index ea6f5f6927659..2454b3119213a 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -5,7 +5,7 @@ LL | Condition<{ LHS <= RHS }>: True | ^^^ cannot perform const operation using `LHS` | = help: const parameters may only be used as standalone arguments, i.e. `LHS` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:11:24 @@ -14,7 +14,7 @@ LL | Condition<{ LHS <= RHS }>: True | ^^^ cannot perform const operation using `RHS` | = help: const parameters may only be used as standalone arguments, i.e. `RHS` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:23:25 @@ -23,7 +23,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ cannot perform const operation using `I` | = help: const parameters may only be used as standalone arguments, i.e. `I` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:23:36 @@ -32,7 +32,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | ^ cannot perform const operation using `J` | = help: const parameters may only be used as standalone arguments, i.e. `J` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr index 42671412fa77f..c504464127aff 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr @@ -5,7 +5,7 @@ LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr index f0e0a4b971106..78717028f6565 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr @@ -5,7 +5,7 @@ LL | let _: &'a (); | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0308]: mismatched types --> $DIR/issue-74713.rs:3:10 diff --git a/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr index 302da59651ccb..2cec51cce2280 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr @@ -16,6 +16,6 @@ help: add missing generic argument LL | test::<2, P>(); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr index 511ae58a1dcdd..08ecb2e486641 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr @@ -11,6 +11,6 @@ LL | Self::AssocInstance == [(); std::mem::size_of::()]; = help: consider constraining the associated type `::Assoc` to `[(); std::mem::size_of::()]` or calling a method that returns `::Assoc` = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr index 9b66fc502b726..8d59235e2f448 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -6,5 +6,5 @@ query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `::{constant#0}` #1 [eval_to_valtree] evaluating type-level constant end of query stack -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr index dc7d0c54fcc9a..b57779739a55b 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr @@ -11,5 +11,5 @@ help: consider enabling this feature LL + #![feature(generic_const_exprs)] | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.stderr b/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.stderr index 8b6eb5b75940f..1036b7261f26a 100644 --- a/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.stderr +++ b/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.stderr @@ -13,6 +13,6 @@ error[E0747]: constant provided when a type was expected LL | fn f = ()>>() {} | ^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr index 7b41e39b7d742..395088bf2f29c 100644 --- a/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr +++ b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr @@ -6,5 +6,5 @@ LL | b: [f32; complex_maths::(N)], | = help: try adding a `where` bound using this expression: `where [(); complex_maths::(N)]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr index 3e5c2f5cad1df..100cf3f8b6299 100644 --- a/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr +++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr @@ -6,5 +6,5 @@ LL | b: [f32; complex_maths(N)], | = help: try adding a `where` bound using this expression: `where [(); complex_maths(N)]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr index 3926c830adb7a..7d84d7bcae7b3 100644 --- a/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr +++ b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr @@ -7,6 +7,6 @@ LL | let _: anon_const_non_local::Foo<2> = anon_const_non_local::foo::(); = note: expected constant `2` found constant `anon_const_non_local::::foo::{constant#0}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr index b7ec657120c6d..6f0a6b04333e3 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr @@ -14,9 +14,8 @@ LL | fn test(&self) -> [u8; bar::()]; | | | ...because method `test` references the `Self` type in its `where` clause = help: consider moving `test` to another trait - = help: consider moving `test` to another trait = help: only type `()` implements the trait, consider using it directly instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr index 440cf457e196c..9e480ce9b856a 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr @@ -20,5 +20,5 @@ note: the lint level is defined here LL | #![deny(where_clauses_object_safety)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr index 59e9fee1eaf41..e800c5d059f43 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr @@ -14,6 +14,6 @@ help: consider specifying the generic argument LL | use_dyn::(&()); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr index 63e6fcc8e119b..eba8b9b6257e5 100644 --- a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr +++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr @@ -15,6 +15,6 @@ LL | fn g() LL | Is<{ std::mem::size_of::() == 0 }>: True, | ^^^^ required by this bound in `g` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr index 0314d7ed23d3f..c73d1022ed312 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -7,6 +7,6 @@ LL | const ASSOC: usize; LL | impl Q for [u8; N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr index 8cbd12654480a..3bae93ccb83fb 100644 --- a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr +++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr @@ -7,5 +7,5 @@ LL | WHAT_A_TYPE => 0, = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/unresolved_lifetimes_error.stderr b/tests/ui/const-generics/generic_const_exprs/unresolved_lifetimes_error.stderr index 976f037062dd9..67eed46eaddc3 100644 --- a/tests/ui/const-generics/generic_const_exprs/unresolved_lifetimes_error.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unresolved_lifetimes_error.stderr @@ -6,6 +6,6 @@ LL | fn foo() -> [(); { LL | let a: &'a (); | ^^ undeclared lifetime -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/const-generics/ice-118285-fn-ptr-value.rs b/tests/ui/const-generics/ice-118285-fn-ptr-value.rs new file mode 100644 index 0000000000000..b68afb0bc8346 --- /dev/null +++ b/tests/ui/const-generics/ice-118285-fn-ptr-value.rs @@ -0,0 +1,5 @@ +struct Checked bool>; +//~^ ERROR function pointers as const generic parameters is forbidden +fn not_one(val: usize) -> bool { val != 1 } +const _: Checked = Checked::; +fn main() {} diff --git a/tests/ui/const-generics/ice-118285-fn-ptr-value.stderr b/tests/ui/const-generics/ice-118285-fn-ptr-value.stderr new file mode 100644 index 0000000000000..46a8a975d50d7 --- /dev/null +++ b/tests/ui/const-generics/ice-118285-fn-ptr-value.stderr @@ -0,0 +1,10 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/ice-118285-fn-ptr-value.rs:1:25 + | +LL | struct Checked bool>; + | ^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/ice-68875.stderr b/tests/ui/const-generics/ice-68875.stderr index 1db62c57fd438..5a39a57242110 100644 --- a/tests/ui/const-generics/ice-68875.stderr +++ b/tests/ui/const-generics/ice-68875.stderr @@ -4,5 +4,5 @@ error: generic `Self` types are currently not permitted in anonymous constants LL | data: &'a [u8; Self::SIZE], | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr b/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr index a72f5800a07c3..5d3ef008b16ea 100644 --- a/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr +++ b/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr @@ -4,5 +4,5 @@ error: expected one of `(`, `::`, `<`, or `>`, found `;` LL | fn return_ty() -> impl Into<<() as Reexported; | ^ expected one of `(`, `::`, `<`, or `>` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/infer/cannot-infer-const-args.stderr b/tests/ui/const-generics/infer/cannot-infer-const-args.stderr index 93e45a88a6c20..e3caefef10f81 100644 --- a/tests/ui/const-generics/infer/cannot-infer-const-args.stderr +++ b/tests/ui/const-generics/infer/cannot-infer-const-args.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | foo::(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/issue-77092.stderr b/tests/ui/const-generics/infer/issue-77092.stderr index 1682b26ac8777..5b411269862a2 100644 --- a/tests/ui/const-generics/infer/issue-77092.stderr +++ b/tests/ui/const-generics/infer/issue-77092.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic arguments LL | println!("{:?}", take_array_from_mut::(&mut arr, i)); | ++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/method-chain.stderr b/tests/ui/const-generics/infer/method-chain.stderr index f527ee6e4f556..2def9e85ab75a 100644 --- a/tests/ui/const-generics/infer/method-chain.stderr +++ b/tests/ui/const-generics/infer/method-chain.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic argument LL | Foo.bar().bar().bar().bar().baz::(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/one-param-uninferred.stderr b/tests/ui/const-generics/infer/one-param-uninferred.stderr index cf70c21813950..3e33fec9cefe5 100644 --- a/tests/ui/const-generics/infer/one-param-uninferred.stderr +++ b/tests/ui/const-generics/infer/one-param-uninferred.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic arguments LL | let _: [u8; 17] = foo::<17, M>(); | +++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/uninferred-consts.stderr b/tests/ui/const-generics/infer/uninferred-consts.stderr index 20daf45706bf8..0ec6ac9c22e53 100644 --- a/tests/ui/const-generics/infer/uninferred-consts.stderr +++ b/tests/ui/const-generics/infer/uninferred-consts.stderr @@ -9,6 +9,6 @@ help: consider specifying the generic arguments LL | Foo.foo::(); | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr index 4c45339b93b37..95f75c32186a0 100644 --- a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -5,7 +5,7 @@ LL | T: Trait<{std::intrinsics::type_name::()}> | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/intrinsics-type_name-as-const-argument.rs:10:22 diff --git a/tests/ui/const-generics/invalid-constant-in-args.stderr b/tests/ui/const-generics/invalid-constant-in-args.stderr index 2545cc6f39644..158b9722ee61b 100644 --- a/tests/ui/const-generics/invalid-constant-in-args.stderr +++ b/tests/ui/const-generics/invalid-constant-in-args.stderr @@ -6,6 +6,6 @@ LL | let _: Cell<&str, "a"> = Cell::new(""); | | | expected 1 generic argument -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/invariant.stderr b/tests/ui/const-generics/invariant.stderr index aabe4c93b3624..f631e1311460f 100644 --- a/tests/ui/const-generics/invariant.stderr +++ b/tests/ui/const-generics/invariant.stderr @@ -21,6 +21,6 @@ LL | v = note: expected reference `&Foo` found reference `&Foo fn(&'a ())>` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issue-112505-overflow.stderr b/tests/ui/const-generics/issue-112505-overflow.stderr index bd8a4feeff5e7..0bd3f6eddd459 100644 --- a/tests/ui/const-generics/issue-112505-overflow.stderr +++ b/tests/ui/const-generics/issue-112505-overflow.stderr @@ -7,6 +7,6 @@ LL | unsafe { std::mem::transmute(v) } = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/const-generics/issue-46511.stderr b/tests/ui/const-generics/issue-46511.stderr index 58c93a1fab49c..d57295fa2fae1 100644 --- a/tests/ui/const-generics/issue-46511.stderr +++ b/tests/ui/const-generics/issue-46511.stderr @@ -5,7 +5,7 @@ LL | _a: [u8; std::mem::size_of::<&'a mut u8>()] | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0392]: parameter `'a` is never used --> $DIR/issue-46511.rs:3:12 diff --git a/tests/ui/const-generics/issue-66451.stderr b/tests/ui/const-generics/issue-66451.stderr index 946d5148667ec..404e3839bca90 100644 --- a/tests/ui/const-generics/issue-66451.stderr +++ b/tests/ui/const-generics/issue-66451.stderr @@ -15,6 +15,6 @@ LL | | }> = x; = note: expected struct `Test(5) }>` found struct `Test(4) }>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issue-80471.stderr b/tests/ui/const-generics/issue-80471.stderr index 3b7143de543d7..b21ad3aec7950 100644 --- a/tests/ui/const-generics/issue-80471.stderr +++ b/tests/ui/const-generics/issue-80471.stderr @@ -19,6 +19,6 @@ LL + #[derive(ConstParamTy)] LL | enum Nat { | -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issue-93647.stderr b/tests/ui/const-generics/issue-93647.stderr index 18370eea57149..a87b59940cb8c 100644 --- a/tests/ui/const-generics/issue-93647.stderr +++ b/tests/ui/const-generics/issue-93647.stderr @@ -8,6 +8,6 @@ LL | (||1usize)() = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/issues/issue-56445-1.full.stderr b/tests/ui/const-generics/issues/issue-56445-1.full.stderr index 5fc0ec260474c..86eb57355bd61 100644 --- a/tests/ui/const-generics/issues/issue-56445-1.full.stderr +++ b/tests/ui/const-generics/issues/issue-56445-1.full.stderr @@ -6,6 +6,6 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | = note: lifetime parameters may not be used in the type of const parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-56445-2.stderr b/tests/ui/const-generics/issues/issue-56445-2.stderr index 770c80cbbd305..351dcb1a15579 100644 --- a/tests/ui/const-generics/issues/issue-56445-2.stderr +++ b/tests/ui/const-generics/issues/issue-56445-2.stderr @@ -10,5 +10,5 @@ note: not a concrete type LL | impl<'a> OnDiskDirEntry<'a> { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-56445-3.stderr b/tests/ui/const-generics/issues/issue-56445-3.stderr index f1c49eecfb547..96b68ca22f4fc 100644 --- a/tests/ui/const-generics/issues/issue-56445-3.stderr +++ b/tests/ui/const-generics/issues/issue-56445-3.stderr @@ -4,5 +4,5 @@ error: generic `Self` types are currently not permitted in anonymous constants LL | ram: [u8; Self::SIZE], | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-61336-2.stderr b/tests/ui/const-generics/issues/issue-61336-2.stderr index 5bb3566962367..0af6f87a68df8 100644 --- a/tests/ui/const-generics/issues/issue-61336-2.stderr +++ b/tests/ui/const-generics/issues/issue-61336-2.stderr @@ -10,6 +10,6 @@ help: consider restricting type parameter `T` LL | fn g(x: T) -> [T; N] { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-61336.stderr b/tests/ui/const-generics/issues/issue-61336.stderr index 8d9e545b45689..4132e511240ae 100644 --- a/tests/ui/const-generics/issues/issue-61336.stderr +++ b/tests/ui/const-generics/issues/issue-61336.stderr @@ -10,6 +10,6 @@ help: consider restricting type parameter `T` LL | fn g(x: T) -> [T; N] { | +++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-62878.full.stderr b/tests/ui/const-generics/issues/issue-62878.full.stderr index c658b5a6e6866..615bfeb65a515 100644 --- a/tests/ui/const-generics/issues/issue-62878.full.stderr +++ b/tests/ui/const-generics/issues/issue-62878.full.stderr @@ -6,6 +6,6 @@ LL | fn foo() {} | = note: const parameters may not be used in the type of const parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr index e2d8c5ca0e148..5082705927ee5 100644 --- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr @@ -6,6 +6,6 @@ LL | fn test() { | = note: `(dyn A + 'static)` must implement `ConstParamTy`, but it does not -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr index 9d80f1cd01bc6..b9588e23e55ce 100644 --- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr @@ -7,5 +7,5 @@ LL | fn test() { = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67375.full.stderr b/tests/ui/const-generics/issues/issue-67375.full.stderr index 13cb8d1cd6866..96e0f1b0e1fc1 100644 --- a/tests/ui/const-generics/issues/issue-67375.full.stderr +++ b/tests/ui/const-generics/issues/issue-67375.full.stderr @@ -8,5 +8,5 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], | = help: consider moving this anonymous constant into a `const` function -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67375.min.stderr b/tests/ui/const-generics/issues/issue-67375.min.stderr index 5256d96c87694..7671e3c468876 100644 --- a/tests/ui/const-generics/issues/issue-67375.min.stderr +++ b/tests/ui/const-generics/issues/issue-67375.min.stderr @@ -5,7 +5,7 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0392]: parameter `T` is never used --> $DIR/issue-67375.rs:5:12 diff --git a/tests/ui/const-generics/issues/issue-67739.full.stderr b/tests/ui/const-generics/issues/issue-67739.full.stderr index f1a426c3c5861..bdf05023d5f0b 100644 --- a/tests/ui/const-generics/issues/issue-67739.full.stderr +++ b/tests/ui/const-generics/issues/issue-67739.full.stderr @@ -6,5 +6,5 @@ LL | [0u8; mem::size_of::()]; | = help: try adding a `where` bound using this expression: `where [(); mem::size_of::()]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67739.min.stderr b/tests/ui/const-generics/issues/issue-67739.min.stderr index dcbe5b94a6281..14037b9eea5ac 100644 --- a/tests/ui/const-generics/issues/issue-67739.min.stderr +++ b/tests/ui/const-generics/issues/issue-67739.min.stderr @@ -6,5 +6,5 @@ LL | [0u8; mem::size_of::()]; | = note: this may fail depending on what value the parameter takes -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67945-1.full.stderr b/tests/ui/const-generics/issues/issue-67945-1.full.stderr index ee17ec3c698ba..2ecdc0366d558 100644 --- a/tests/ui/const-generics/issues/issue-67945-1.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-1.full.stderr @@ -12,6 +12,6 @@ LL | let x: S = MaybeUninit::uninit(); = note: expected type parameter `S` found union `MaybeUninit<_>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-67945-1.min.stderr b/tests/ui/const-generics/issues/issue-67945-1.min.stderr index eee04eb75a258..1d071da903fa1 100644 --- a/tests/ui/const-generics/issues/issue-67945-1.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-1.min.stderr @@ -5,7 +5,7 @@ LL | let x: S = MaybeUninit::uninit(); | ^ cannot perform const operation using `S` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-67945-1.rs:13:45 @@ -14,7 +14,7 @@ LL | let b = &*(&x as *const _ as *const S); | ^ cannot perform const operation using `S` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0392]: parameter `S` is never used --> $DIR/issue-67945-1.rs:7:12 diff --git a/tests/ui/const-generics/issues/issue-67945-2.full.stderr b/tests/ui/const-generics/issues/issue-67945-2.full.stderr index 47429b7612f94..837927d588c7e 100644 --- a/tests/ui/const-generics/issues/issue-67945-2.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-2.full.stderr @@ -13,5 +13,5 @@ LL | | }], = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67945-2.min.stderr b/tests/ui/const-generics/issues/issue-67945-2.min.stderr index 6e07af1e672a8..62fbed71aef54 100644 --- a/tests/ui/const-generics/issues/issue-67945-2.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-2.min.stderr @@ -4,5 +4,5 @@ error: generic `Self` types are currently not permitted in anonymous constants LL | let x: Option> = None; | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67945-3.full.stderr b/tests/ui/const-generics/issues/issue-67945-3.full.stderr index 98f9f83976aa7..9683769aa2402 100644 --- a/tests/ui/const-generics/issues/issue-67945-3.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-3.full.stderr @@ -12,5 +12,5 @@ LL | | }], = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67945-3.min.stderr b/tests/ui/const-generics/issues/issue-67945-3.min.stderr index 8e6b4b20409ce..e34869c79386b 100644 --- a/tests/ui/const-generics/issues/issue-67945-3.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-3.min.stderr @@ -5,7 +5,7 @@ LL | let x: Option = None; | ^ cannot perform const operation using `S` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0392]: parameter `S` is never used --> $DIR/issue-67945-3.rs:9:12 diff --git a/tests/ui/const-generics/issues/issue-67945-4.full.stderr b/tests/ui/const-generics/issues/issue-67945-4.full.stderr index c03d40a7bb832..5450cabef6140 100644 --- a/tests/ui/const-generics/issues/issue-67945-4.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-4.full.stderr @@ -12,5 +12,5 @@ LL | | }], = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67945-4.min.stderr b/tests/ui/const-generics/issues/issue-67945-4.min.stderr index f9520872ddd27..280c6f4f2cdfe 100644 --- a/tests/ui/const-generics/issues/issue-67945-4.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-4.min.stderr @@ -5,7 +5,7 @@ LL | let x: Option> = None; | ^ cannot perform const operation using `S` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0392]: parameter `S` is never used --> $DIR/issue-67945-4.rs:8:12 diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr index 3740ced90b1d7..ecf24a356deef 100644 --- a/tests/ui/const-generics/issues/issue-68366.min.stderr +++ b/tests/ui/const-generics/issues/issue-68366.min.stderr @@ -5,7 +5,7 @@ LL | impl Collatz<{Some(N)}> {} | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates --> $DIR/issue-68366.rs:11:7 diff --git a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr index c8b9f17196aca..20962098bfff9 100644 --- a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr +++ b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr @@ -7,5 +7,5 @@ LL | struct Const {} = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-68615-array.min.stderr b/tests/ui/const-generics/issues/issue-68615-array.min.stderr index fc6cef9d44e55..8c76f9b5d65c3 100644 --- a/tests/ui/const-generics/issues/issue-68615-array.min.stderr +++ b/tests/ui/const-generics/issues/issue-68615-array.min.stderr @@ -7,5 +7,5 @@ LL | struct Foo {} = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-71169.full.stderr b/tests/ui/const-generics/issues/issue-71169.full.stderr index ccdfbbd54cfbb..9553be6fc07c7 100644 --- a/tests/ui/const-generics/issues/issue-71169.full.stderr +++ b/tests/ui/const-generics/issues/issue-71169.full.stderr @@ -6,6 +6,6 @@ LL | fn foo() {} | = note: const parameters may not be used in the type of const parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71202.stderr b/tests/ui/const-generics/issues/issue-71202.stderr index 277540610864b..2aa9e344067bf 100644 --- a/tests/ui/const-generics/issues/issue-71202.stderr +++ b/tests/ui/const-generics/issues/issue-71202.stderr @@ -29,5 +29,5 @@ LL | | } as usize] = []; >::VALUE } as usize]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-71382.full.stderr b/tests/ui/const-generics/issues/issue-71382.full.stderr index ab2a4e64a8389..95faa406f859e 100644 --- a/tests/ui/const-generics/issues/issue-71382.full.stderr +++ b/tests/ui/const-generics/issues/issue-71382.full.stderr @@ -4,6 +4,6 @@ error[E0741]: using function pointers as const generic parameters is forbidden LL | fn test(&self) { | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-71382.min.stderr b/tests/ui/const-generics/issues/issue-71382.min.stderr index 217166d847937..0c58b10c0b7c8 100644 --- a/tests/ui/const-generics/issues/issue-71382.min.stderr +++ b/tests/ui/const-generics/issues/issue-71382.min.stderr @@ -6,5 +6,5 @@ LL | fn test(&self) { | = note: the only supported types are integers, `bool` and `char` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-71611.full.stderr b/tests/ui/const-generics/issues/issue-71611.full.stderr index b55f410a02370..6f6a9fc21a699 100644 --- a/tests/ui/const-generics/issues/issue-71611.full.stderr +++ b/tests/ui/const-generics/issues/issue-71611.full.stderr @@ -6,6 +6,6 @@ LL | fn func(outer: A) { | = note: type parameters may not be used in the type of const parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-72352.full.stderr b/tests/ui/const-generics/issues/issue-72352.full.stderr index 92580b33685d1..cc46e7951f0ad 100644 --- a/tests/ui/const-generics/issues/issue-72352.full.stderr +++ b/tests/ui/const-generics/issues/issue-72352.full.stderr @@ -4,6 +4,6 @@ error[E0741]: using function pointers as const generic parameters is forbidden LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const i8) -> usize { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-72352.min.stderr b/tests/ui/const-generics/issues/issue-72352.min.stderr index b010996b89692..cd009c973aeb2 100644 --- a/tests/ui/const-generics/issues/issue-72352.min.stderr +++ b/tests/ui/const-generics/issues/issue-72352.min.stderr @@ -6,5 +6,5 @@ LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const i8 | = note: the only supported types are integers, `bool` and `char` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-72845.stderr b/tests/ui/const-generics/issues/issue-72845.stderr index 631c8605fb4d6..9ab18c3a53de4 100644 --- a/tests/ui/const-generics/issues/issue-72845.stderr +++ b/tests/ui/const-generics/issues/issue-72845.stderr @@ -7,6 +7,6 @@ LL | impl Foo for T { LL | impl Foo for T { | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/issues/issue-73491.min.stderr b/tests/ui/const-generics/issues/issue-73491.min.stderr index fdf057bdbe47d..64df76756ac3a 100644 --- a/tests/ui/const-generics/issues/issue-73491.min.stderr +++ b/tests/ui/const-generics/issues/issue-73491.min.stderr @@ -7,5 +7,5 @@ LL | fn hoge() {} = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr index bed0a02a72673..2b33f35defd0f 100644 --- a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr +++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr @@ -7,5 +7,5 @@ LL | fn a() {} = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-74255.min.stderr b/tests/ui/const-generics/issues/issue-74255.min.stderr index affeca167e970..63d8fc12fa441 100644 --- a/tests/ui/const-generics/issues/issue-74255.min.stderr +++ b/tests/ui/const-generics/issues/issue-74255.min.stderr @@ -7,5 +7,5 @@ LL | fn ice_struct_fn() {} = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-75047.min.stderr b/tests/ui/const-generics/issues/issue-75047.min.stderr index e316b4624a007..1d7ac1b01111b 100644 --- a/tests/ui/const-generics/issues/issue-75047.min.stderr +++ b/tests/ui/const-generics/issues/issue-75047.min.stderr @@ -7,5 +7,5 @@ LL | struct Foo::value()]>; = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr index 3b53e18e6f56c..da2fbc52a6cab 100644 --- a/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr +++ b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr @@ -5,7 +5,7 @@ LL | fn ty_param() -> [u8; std::mem::size_of::()] { | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/issue-76701-ty-param-in-const.rs:6:42 @@ -14,7 +14,7 @@ LL | fn const_param() -> [u8; N + 1] { | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-79674.stderr b/tests/ui/const-generics/issues/issue-79674.stderr index ba7fd2ca3ccf3..1e7878e8da95c 100644 --- a/tests/ui/const-generics/issues/issue-79674.stderr +++ b/tests/ui/const-generics/issues/issue-79674.stderr @@ -15,6 +15,6 @@ LL | A: MiniTypeId, B: MiniTypeId, LL | Lift<{is_same_type::()}>: IsFalse {} | ^^^^^^^ required by this bound in `requires_distinct` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-80062.stderr b/tests/ui/const-generics/issues/issue-80062.stderr index 754f18d5cc420..5da8e45fac805 100644 --- a/tests/ui/const-generics/issues/issue-80062.stderr +++ b/tests/ui/const-generics/issues/issue-80062.stderr @@ -5,7 +5,7 @@ LL | let _: [u8; sof::()]; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-80375.stderr b/tests/ui/const-generics/issues/issue-80375.stderr index 5409002a9fdeb..015196f860533 100644 --- a/tests/ui/const-generics/issues/issue-80375.stderr +++ b/tests/ui/const-generics/issues/issue-80375.stderr @@ -5,7 +5,7 @@ LL | struct MyArray([u8; COUNT + 1]); | ^^^^^ cannot perform const operation using `COUNT` | = help: const parameters may only be used as standalone arguments, i.e. `COUNT` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-82956.stderr b/tests/ui/const-generics/issues/issue-82956.stderr index d70c8d0bfbf34..d0fc7112426a9 100644 --- a/tests/ui/const-generics/issues/issue-82956.stderr +++ b/tests/ui/const-generics/issues/issue-82956.stderr @@ -16,6 +16,6 @@ LL + use std::collections::btree_set::IntoIter; | and 8 other candidates -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/const-generics/issues/issue-83249.stderr b/tests/ui/const-generics/issues/issue-83249.stderr index 5187434ff40e0..f41115ce42769 100644 --- a/tests/ui/const-generics/issues/issue-83249.stderr +++ b/tests/ui/const-generics/issues/issue-83249.stderr @@ -18,6 +18,6 @@ help: consider giving this pattern a type LL | let _: /* Type */ = foo([0; 1]); | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/const-generics/issues/issue-83466.stderr b/tests/ui/const-generics/issues/issue-83466.stderr index bcfd706398966..91451a799b0c2 100644 --- a/tests/ui/const-generics/issues/issue-83466.stderr +++ b/tests/ui/const-generics/issues/issue-83466.stderr @@ -17,6 +17,6 @@ error[E0747]: constant provided when a type was expected LL | S.func::<'a, 10_u32>() | ^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr index df734933c250c..d9956875cf888 100644 --- a/tests/ui/const-generics/issues/issue-83765.stderr +++ b/tests/ui/const-generics/issues/issue-83765.stderr @@ -17,6 +17,6 @@ LL | trait TensorDimension { | ^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/const-generics/issues/issue-84659.stderr b/tests/ui/const-generics/issues/issue-84659.stderr index 2dfc48a34e4b1..796c5515e0458 100644 --- a/tests/ui/const-generics/issues/issue-84659.stderr +++ b/tests/ui/const-generics/issues/issue-84659.stderr @@ -6,5 +6,5 @@ LL | type Baz: Bar<{ Self::N }>; | = help: try adding a `where` bound using this expression: `where [(); { Self::N }]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-86530.stderr b/tests/ui/const-generics/issues/issue-86530.stderr index d02808f7c567b..aa8aa4e10a81e 100644 --- a/tests/ui/const-generics/issues/issue-86530.stderr +++ b/tests/ui/const-generics/issues/issue-86530.stderr @@ -20,6 +20,6 @@ LL | where LL | T: X, | ^ required by this bound in `z` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-86820.stderr b/tests/ui/const-generics/issues/issue-86820.stderr index 3a9cd957f35e7..2928c1923b8b6 100644 --- a/tests/ui/const-generics/issues/issue-86820.stderr +++ b/tests/ui/const-generics/issues/issue-86820.stderr @@ -11,6 +11,6 @@ LL | impl Bits for u8 { LL | fn bit(self) -> bool { | ^^^^^^^^^^^^^^ found const parameter of type `usize` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/const-generics/issues/issue-90364.stderr b/tests/ui/const-generics/issues/issue-90364.stderr index 23424d7b919b6..6c00a654cde78 100644 --- a/tests/ui/const-generics/issues/issue-90364.stderr +++ b/tests/ui/const-generics/issues/issue-90364.stderr @@ -6,6 +6,6 @@ LL | pub struct Foo(T) | = note: type parameters may not be used in the type of const parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-90455.stderr b/tests/ui/const-generics/issues/issue-90455.stderr index 724d7f42e69d1..1db906095727e 100644 --- a/tests/ui/const-generics/issues/issue-90455.stderr +++ b/tests/ui/const-generics/issues/issue-90455.stderr @@ -6,5 +6,5 @@ LL | n: [u64; num_limbs(N)], | = help: try adding a `where` bound using this expression: `where [(); num_limbs(N)]:` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-97278.stderr b/tests/ui/const-generics/issues/issue-97278.stderr index 31e92f840e189..47e6bf1df4d16 100644 --- a/tests/ui/const-generics/issues/issue-97278.stderr +++ b/tests/ui/const-generics/issues/issue-97278.stderr @@ -10,6 +10,6 @@ LL + #[derive(ConstParamTy)] LL | enum Bar { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-98629.stderr b/tests/ui/const-generics/issues/issue-98629.stderr index 4a248be76a9e8..e7582aaae11aa 100644 --- a/tests/ui/const-generics/issues/issue-98629.stderr +++ b/tests/ui/const-generics/issues/issue-98629.stderr @@ -7,6 +7,6 @@ LL | const N: usize; LL | impl const Trait for i32 {} | ^^^^^^^^^^^^^^^^^^^^^^^^ missing `N` in implementation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr b/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr index 21c8fe6865cc1..7bef98b1d5d2f 100644 --- a/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr +++ b/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr @@ -4,5 +4,5 @@ error: cannot capture late-bound lifetime in constant LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { | -- lifetime defined here ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/late-bound-vars/late-bound-in-where-issue-83993.stderr b/tests/ui/const-generics/late-bound-vars/late-bound-in-where-issue-83993.stderr index a66dc8db91442..5edbf7bc04060 100644 --- a/tests/ui/const-generics/late-bound-vars/late-bound-in-where-issue-83993.stderr +++ b/tests/ui/const-generics/late-bound-vars/late-bound-in-where-issue-83993.stderr @@ -6,5 +6,5 @@ LL | for<'b> [(); { LL | let x: &'b (); | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/legacy-const-generics-bad.stderr b/tests/ui/const-generics/legacy-const-generics-bad.stderr index 3c78dd6c78023..83c71e07253b3 100644 --- a/tests/ui/const-generics/legacy-const-generics-bad.stderr +++ b/tests/ui/const-generics/legacy-const-generics-bad.stderr @@ -13,7 +13,7 @@ LL | legacy_const_generics::foo(0, N + 1, 2); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/min_const_generics/complex-expression.stderr b/tests/ui/const-generics/min_const_generics/complex-expression.stderr index deabd05a6d5b0..3affdcf9b03ea 100644 --- a/tests/ui/const-generics/min_const_generics/complex-expression.stderr +++ b/tests/ui/const-generics/min_const_generics/complex-expression.stderr @@ -5,7 +5,7 @@ LL | struct Break0([u8; { N + 1 }]); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:13:40 @@ -14,7 +14,7 @@ LL | struct Break1([u8; { { N } }]); | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:17:17 @@ -23,7 +23,7 @@ LL | let _: [u8; N + 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:22:17 @@ -32,7 +32,7 @@ LL | let _ = [0; N + 1]; | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments, i.e. `N` - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:26:45 @@ -41,7 +41,7 @@ LL | struct BreakTy0(T, [u8; { size_of::<*mut T>() }]); | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:29:47 @@ -50,7 +50,7 @@ LL | struct BreakTy1(T, [u8; { { size_of::<*mut T>() } }]); | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:33:32 @@ -59,7 +59,7 @@ LL | let _: [u8; size_of::<*mut T>() + 1]; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions warning: cannot use constants which depend on generic parameters in types --> $DIR/complex-expression.rs:38:17 diff --git a/tests/ui/const-generics/min_const_generics/const_default_first.stderr b/tests/ui/const-generics/min_const_generics/const_default_first.stderr index 0d5a393cb7bfb..b800c6d77b0a4 100644 --- a/tests/ui/const-generics/min_const_generics/const_default_first.stderr +++ b/tests/ui/const-generics/min_const_generics/const_default_first.stderr @@ -4,5 +4,5 @@ error: generic parameters with a default must be trailing LL | struct Both { | ^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/min_const_generics/default_function_param.stderr b/tests/ui/const-generics/min_const_generics/default_function_param.stderr index dedad2880c9e8..247eea3d98995 100644 --- a/tests/ui/const-generics/min_const_generics/default_function_param.stderr +++ b/tests/ui/const-generics/min_const_generics/default_function_param.stderr @@ -4,5 +4,5 @@ error: defaults for const parameters are only allowed in `struct`, `enum`, `type LL | fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr index 7726016eb835f..909b0476999f3 100644 --- a/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr +++ b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr @@ -5,7 +5,7 @@ LL | test::<{ let _: &'a (); 3 },>(); | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic parameters may not be used in const operations --> $DIR/forbid-non-static-lifetimes.rs:21:16 @@ -14,7 +14,7 @@ LL | [(); (|_: &'a u8| (), 0).1]; | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr index bda8859700680..03c76150010fb 100644 --- a/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr +++ b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr @@ -10,5 +10,5 @@ note: not a concrete type LL | impl BindsParam for ::Assoc { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr index 16a7687c00b54..e9216fc12a22a 100644 --- a/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr @@ -5,7 +5,7 @@ LL | fn t1() -> [u8; std::mem::size_of::()]; | ^^^^ cannot perform const operation using `Self` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error: generic `Self` types are currently not permitted in anonymous constants --> $DIR/self-ty-in-const-1.rs:12:41 diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr index 41546292c47d1..4943f0d70bd03 100644 --- a/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr @@ -10,5 +10,5 @@ note: not a concrete type LL | impl Baz for Bar { | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/nested-type.full.stderr b/tests/ui/const-generics/nested-type.full.stderr index 6d9f4406504ee..04dc84ea3cf5a 100644 --- a/tests/ui/const-generics/nested-type.full.stderr +++ b/tests/ui/const-generics/nested-type.full.stderr @@ -6,6 +6,6 @@ LL | Foo::<17>::value() | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr b/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr index 6b8e688fba8d1..1a251044ec07e 100644 --- a/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr +++ b/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | arr = bind(arr); | ^^^^^^^^^ encountered a self-referencing constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr index 61d055e808473..8c66c4fefb7ed 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -14,6 +14,6 @@ LL | where LL | A: Bar; | ^^^^^^ required by this bound in `A` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-2.stderr b/tests/ui/const-generics/occurs-check/unused-substs-2.stderr index 9532fc21a31b7..4b1b9f20559e8 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-2.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-2.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | t = foo; | ^^^ cyclic type of infinite size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.stderr b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr index fd8f8b2693a4b..bcb59705c6b2f 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-3.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr @@ -6,6 +6,6 @@ LL | t = foo; | | | cyclic type of infinite size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-4.stderr b/tests/ui/const-generics/occurs-check/unused-substs-4.stderr index 5685eedbdeca8..1e33439f6d731 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-4.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-4.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | arr = bind(arr); | ^^^^^^^^^ encountered a self-referencing constant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-5.stderr b/tests/ui/const-generics/occurs-check/unused-substs-5.stderr index be289f44f1b65..1b3a54923284c 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-5.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-5.stderr @@ -6,6 +6,6 @@ LL | x = q::<_, N>(x); | | | cyclic type of infinite size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr index 6b0d18f1989aa..38b25445f611a 100644 --- a/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr +++ b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr @@ -5,7 +5,7 @@ LL | let x: &'a (); | ^^ cannot perform const operation using `'a` | = note: lifetime parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index a5e70f6b9e648..320c9c1c84de0 100644 --- a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -11,7 +11,7 @@ LL | struct Foo()]>(T, U); | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 diff --git a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr index 87ff7babe71c0..07da6ede7251b 100644 --- a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr +++ b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr @@ -10,6 +10,6 @@ note: required by a bound in `foo` LL | pub fn foo(foo: impl Into<[(); N + 1]>) { | ^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr index 1de24bff4692e..be3d4f6d25c14 100644 --- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr @@ -10,5 +10,5 @@ LL - impl Foo for Bar { LL + impl Foo<3> for Bar { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr index f0d0d90c774f8..c46c305e0850e 100644 --- a/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr @@ -4,5 +4,5 @@ error: missing type to the right of `=` LL | impl Foo for Bar { | ^---- expected type, found keyword `type` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/projection-as-arg-const.stderr b/tests/ui/const-generics/projection-as-arg-const.stderr index 9f727231edfbe..88672bce0a7ee 100644 --- a/tests/ui/const-generics/projection-as-arg-const.stderr +++ b/tests/ui/const-generics/projection-as-arg-const.stderr @@ -6,5 +6,5 @@ LL | pub fn foo::Identity>() { | = note: the only supported types are integers, `bool` and `char` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/raw-ptr-const-param.full.stderr b/tests/ui/const-generics/raw-ptr-const-param.full.stderr index 69f1aae5681a4..aef95bdaa8809 100644 --- a/tests/ui/const-generics/raw-ptr-const-param.full.stderr +++ b/tests/ui/const-generics/raw-ptr-const-param.full.stderr @@ -4,6 +4,6 @@ error[E0741]: using raw pointers as const generic parameters is forbidden LL | struct Const; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/raw-ptr-const-param.min.stderr b/tests/ui/const-generics/raw-ptr-const-param.min.stderr index 13fbc34e51a0d..4de98191d5b77 100644 --- a/tests/ui/const-generics/raw-ptr-const-param.min.stderr +++ b/tests/ui/const-generics/raw-ptr-const-param.min.stderr @@ -6,5 +6,5 @@ LL | struct Const; | = note: the only supported types are integers, `bool` and `char` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/struct-with-invalid-const-param.stderr b/tests/ui/const-generics/struct-with-invalid-const-param.stderr index 67f497af50503..734a42fe5266c 100644 --- a/tests/ui/const-generics/struct-with-invalid-const-param.stderr +++ b/tests/ui/const-generics/struct-with-invalid-const-param.stderr @@ -4,6 +4,6 @@ error[E0573]: expected type, found const parameter `C` LL | struct S(C); | ^ not a type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr index f18e149464d3d..25bb7ac803962 100644 --- a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr +++ b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr @@ -7,5 +7,5 @@ LL | struct Const; = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/type-dependent/issue-71382.stderr b/tests/ui/const-generics/type-dependent/issue-71382.stderr index 3f42feea562ab..69fd6f1c7d53e 100644 --- a/tests/ui/const-generics/type-dependent/issue-71382.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71382.stderr @@ -6,5 +6,5 @@ LL | fn test u8>(&self) -> u8 { | = note: the only supported types are integers, `bool` and `char` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr b/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr index 70bc640579899..4fce1aede954f 100644 --- a/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr +++ b/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr @@ -9,6 +9,6 @@ help: change the type of the numeric literal from `u16` to `u8` LL | assert_eq!(R.method::<1u8>(), 1); | ~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr b/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr index 70bc640579899..4fce1aede954f 100644 --- a/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr +++ b/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr @@ -9,6 +9,6 @@ help: change the type of the numeric literal from `u16` to `u8` LL | assert_eq!(R.method::<1u8>(), 1); | ~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/unify_with_nested_expr.stderr b/tests/ui/const-generics/unify_with_nested_expr.stderr index d4d78b5962789..e050254a3e9d2 100644 --- a/tests/ui/const-generics/unify_with_nested_expr.stderr +++ b/tests/ui/const-generics/unify_with_nested_expr.stderr @@ -17,6 +17,6 @@ help: consider specifying the generic argument LL | bar::(); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/unknown_adt.stderr b/tests/ui/const-generics/unknown_adt.stderr index 0f462dd4728f0..2e8210772e94a 100644 --- a/tests/ui/const-generics/unknown_adt.stderr +++ b/tests/ui/const-generics/unknown_adt.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `UnknownStruct` in this scope LL | let _: UnknownStruct<7>; | ^^^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/unused-type-param-suggestion.stderr b/tests/ui/const-generics/unused-type-param-suggestion.stderr index 807065ca109e5..6e985f56666bd 100644 --- a/tests/ui/const-generics/unused-type-param-suggestion.stderr +++ b/tests/ui/const-generics/unused-type-param-suggestion.stderr @@ -7,6 +7,6 @@ LL | struct Example; = help: consider removing `N`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `N` to be a const parameter, use `const N: usize` instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/wrong-normalization.stderr b/tests/ui/const-generics/wrong-normalization.stderr index 658a840660876..2f8dfc895b279 100644 --- a/tests/ui/const-generics/wrong-normalization.stderr +++ b/tests/ui/const-generics/wrong-normalization.stderr @@ -6,6 +6,6 @@ LL | impl as Identity>::Identity { | = note: either implement a trait on it or create a newtype to wrap it instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0118`. diff --git a/tests/ui/const-ptr/forbidden_slices.rs b/tests/ui/const-ptr/forbidden_slices.rs index 0374ac7f714b7..deab67f725a30 100644 --- a/tests/ui/const-ptr/forbidden_slices.rs +++ b/tests/ui/const-ptr/forbidden_slices.rs @@ -1,6 +1,6 @@ // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" #![feature( slice_from_ptr_range, diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr index 105683940cfa7..250366da2a6ad 100644 --- a/tests/ui/const-ptr/forbidden_slices.stderr +++ b/tests/ui/const-ptr/forbidden_slices.stderr @@ -93,7 +93,7 @@ error[E0080]: could not evaluate static initializer | = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance) | -note: inside `ptr::const_ptr::::sub_ptr` +note: inside `std::ptr::const_ptr::::sub_ptr` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `from_ptr_range::<'_, u32>` --> $SRC_DIR/core/src/slice/raw.rs:LL:COL @@ -108,7 +108,7 @@ error[E0080]: could not evaluate static initializer | = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | -note: inside `ptr::const_ptr::::sub_ptr` +note: inside `std::ptr::const_ptr::::sub_ptr` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `from_ptr_range::<'_, ()>` --> $SRC_DIR/core/src/slice/raw.rs:LL:COL @@ -124,7 +124,7 @@ error[E0080]: could not evaluate static initializer | = note: out-of-bounds pointer arithmetic: ALLOC10 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds | -note: inside `ptr::const_ptr::::add` +note: inside `std::ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `R2` --> $DIR/forbidden_slices.rs:52:25 @@ -183,7 +183,7 @@ error[E0080]: could not evaluate static initializer | = note: out-of-bounds pointer arithmetic: ALLOC11 has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds | -note: inside `ptr::const_ptr::::add` +note: inside `std::ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `R8` --> $DIR/forbidden_slices.rs:76:25 @@ -196,7 +196,7 @@ error[E0080]: could not evaluate static initializer | = note: `ptr_offset_from_unsigned` called on pointers into different allocations | -note: inside `ptr::const_ptr::::sub_ptr` +note: inside `std::ptr::const_ptr::::sub_ptr` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `from_ptr_range::<'_, u32>` --> $SRC_DIR/core/src/slice/raw.rs:LL:COL @@ -211,7 +211,7 @@ error[E0080]: could not evaluate static initializer | = note: `ptr_offset_from_unsigned` called on pointers into different allocations | -note: inside `ptr::const_ptr::::sub_ptr` +note: inside `std::ptr::const_ptr::::sub_ptr` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `from_ptr_range::<'_, u32>` --> $SRC_DIR/core/src/slice/raw.rs:LL:COL diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr index be75f76b26f2d..7634ba252100c 100644 --- a/tests/ui/const-ptr/out_of_bounds_read.stderr +++ b/tests/ui/const-ptr/out_of_bounds_read.stderr @@ -18,7 +18,7 @@ error[E0080]: evaluation of constant value failed | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `ptr::const_ptr::::read` +note: inside `std::ptr::const_ptr::::read` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `_CONST_READ` --> $DIR/out_of_bounds_read.rs:11:39 @@ -33,7 +33,7 @@ error[E0080]: evaluation of constant value failed | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `ptr::mut_ptr::::read` +note: inside `std::ptr::mut_ptr::::read` --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL note: inside `_MUT_READ` --> $DIR/out_of_bounds_read.rs:12:37 diff --git a/tests/ui/const_prop/apfloat-f64-roundtrip.rs b/tests/ui/const_prop/apfloat-f64-roundtrip.rs index 9fb2ac96bebdb..5f3ec931c82c6 100644 --- a/tests/ui/const_prop/apfloat-f64-roundtrip.rs +++ b/tests/ui/const_prop/apfloat-f64-roundtrip.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -O -Zmir-opt-level=3 -Cno-prepopulate-passes -// min-llvm-version: 16.0 (requires APFloat fixes in LLVM) // Regression test for a broken MIR optimization (issue #113407). pub fn main() { diff --git a/tests/ui/const_prop/const-prop-ice.stderr b/tests/ui/const_prop/const-prop-ice.stderr index 3bcf2b2de7bd7..8a0f831ba847d 100644 --- a/tests/ui/const_prop/const-prop-ice.stderr +++ b/tests/ui/const_prop/const-prop-ice.stderr @@ -6,5 +6,5 @@ LL | [0; 3][3u64 as usize]; | = note: `#[deny(unconditional_panic)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const_prop/const-prop-ice2.stderr b/tests/ui/const_prop/const-prop-ice2.stderr index 2b65ffc2db760..593b0b94ca2de 100644 --- a/tests/ui/const_prop/const-prop-ice2.stderr +++ b/tests/ui/const_prop/const-prop-ice2.stderr @@ -6,5 +6,5 @@ LL | println!("{}", xs[Enum::One as usize]); | = note: `#[deny(unconditional_panic)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/const_prop/const-prop-read-static-in-const.stderr b/tests/ui/const_prop/const-prop-read-static-in-const.stderr index 793da62858770..9af1f7e3a241c 100644 --- a/tests/ui/const_prop/const-prop-read-static-in-const.stderr +++ b/tests/ui/const_prop/const-prop-read-static-in-const.stderr @@ -12,6 +12,6 @@ help: skipping check that does not even have a feature gate LL | const TEST: u8 = MY_STATIC; | ^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const_prop/overwrite_with_const_with_params.rs b/tests/ui/const_prop/overwrite_with_const_with_params.rs new file mode 100644 index 0000000000000..6f533919a474e --- /dev/null +++ b/tests/ui/const_prop/overwrite_with_const_with_params.rs @@ -0,0 +1,21 @@ +// compile-flags: -O +// run-pass + +// Regression test for https://github.com/rust-lang/rust/issues/118328 + +#![allow(unused_assignments)] + +struct SizeOfConst(std::marker::PhantomData); +impl SizeOfConst { + const SIZE: usize = std::mem::size_of::(); +} + +fn size_of() -> usize { + let mut a = 0; + a = SizeOfConst::::SIZE; + a +} + +fn main() { + assert_eq!(size_of::(), std::mem::size_of::()); +} diff --git a/tests/ui/consts/array-literal-len-mismatch.stderr b/tests/ui/consts/array-literal-len-mismatch.stderr index 22fec638970a7..a11506ecb6d6a 100644 --- a/tests/ui/consts/array-literal-len-mismatch.stderr +++ b/tests/ui/consts/array-literal-len-mismatch.stderr @@ -6,6 +6,6 @@ LL | const NUMBERS: [u8; 3] = [10, 20]; | | | help: consider specifying the actual array length: `2` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/assert-type-intrinsics.rs b/tests/ui/consts/assert-type-intrinsics.rs index b4fd423becd9d..32b5f5c92c52d 100644 --- a/tests/ui/consts/assert-type-intrinsics.rs +++ b/tests/ui/consts/assert-type-intrinsics.rs @@ -1,5 +1,4 @@ #![feature(never_type)] -#![feature(const_assert_type2)] #![feature(core_intrinsics)] use std::intrinsics; diff --git a/tests/ui/consts/assert-type-intrinsics.stderr b/tests/ui/consts/assert-type-intrinsics.stderr index 3c03b03deee35..66c4f0f9cd65f 100644 --- a/tests/ui/consts/assert-type-intrinsics.stderr +++ b/tests/ui/consts/assert-type-intrinsics.stderr @@ -1,20 +1,20 @@ error[E0080]: evaluation of constant value failed - --> $DIR/assert-type-intrinsics.rs:12:9 + --> $DIR/assert-type-intrinsics.rs:11:9 | LL | MaybeUninit::::uninit().assume_init(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:12:36 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:11:36 error[E0080]: evaluation of constant value failed - --> $DIR/assert-type-intrinsics.rs:16:9 + --> $DIR/assert-type-intrinsics.rs:15:9 | LL | intrinsics::assert_mem_uninitialized_valid::<&'static i32>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:16:9 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:15:9 error[E0080]: evaluation of constant value failed - --> $DIR/assert-type-intrinsics.rs:20:9 + --> $DIR/assert-type-intrinsics.rs:19:9 | LL | intrinsics::assert_zero_valid::<&'static i32>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:20:9 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:19:9 error: aborting due to 3 previous errors diff --git a/tests/ui/consts/assoc_const_generic_impl.stderr b/tests/ui/consts/assoc_const_generic_impl.stderr index 854b9ce5b223b..d826972ce9f5a 100644 --- a/tests/ui/consts/assoc_const_generic_impl.stderr +++ b/tests/ui/consts/assoc_const_generic_impl.stderr @@ -10,6 +10,6 @@ note: the above error was encountered while instantiating `fn LL | 42_u32.requires_zero_size(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/async-block.with_feature.stderr b/tests/ui/consts/async-block.with_feature.stderr index 8c6364aeca60d..8228fa29edf17 100644 --- a/tests/ui/consts/async-block.with_feature.stderr +++ b/tests/ui/consts/async-block.with_feature.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-array-oob.stderr b/tests/ui/consts/const-array-oob.stderr index f1c5f58af47d3..d481d7728940b 100644 --- a/tests/ui/consts/const-array-oob.stderr +++ b/tests/ui/consts/const-array-oob.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const BLUB: [u32; FOO[4]] = [5, 6]; | ^^^^^^ index out of bounds: the length is 3 but the index is 4 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-as-fn.stderr b/tests/ui/consts/const-as-fn.stderr index 6c51ed89393a5..8d30321e37345 100644 --- a/tests/ui/consts/const-as-fn.stderr +++ b/tests/ui/consts/const-as-fn.stderr @@ -9,6 +9,6 @@ LL | FOO(); | | | call expression requires function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index b402f0ea91548..81790a62f61da 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -6,6 +6,6 @@ LL | const fn f(x: T) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr index 174103eeba4c4..b13df67b423bb 100644 --- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -6,14 +6,18 @@ LL | let _: [Option; 2] = [no_copy(); 2]; | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)] LL | struct Bar; | +help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Option = no_copy(); +LL ~ let _: [Option; 2] = [ARRAY_REPEAT_VALUE; 2]; + | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 06fa4b0b1f30c..36249bf3f6d4e 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -10,10 +10,14 @@ note: required for `Foo` to implement `Copy` LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Foo = Foo(String::new()); +LL ~ [ARRAY_REPEAT_VALUE; 4]; + | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-call.stderr b/tests/ui/consts/const-call.stderr index e46bcad0e1d0e..4e7098a5c8fa6 100644 --- a/tests/ui/consts/const-call.stderr +++ b/tests/ui/consts/const-call.stderr @@ -6,6 +6,6 @@ LL | let _ = [0; f(2)]; | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-cast-wrong-type.stderr b/tests/ui/consts/const-cast-wrong-type.stderr index ee186636e4ebe..44361f15d8a98 100644 --- a/tests/ui/consts/const-cast-wrong-type.stderr +++ b/tests/ui/consts/const-cast-wrong-type.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | const b: *const i8 = &a as *const i8; | ^^^^^^^^^^^^^^^ expected `u8`, found `i8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-deref-ptr.stderr b/tests/ui/consts/const-deref-ptr.stderr index 16eb6b0162dd2..b102b4d17cca1 100644 --- a/tests/ui/consts/const-deref-ptr.stderr +++ b/tests/ui/consts/const-deref-ptr.stderr @@ -4,6 +4,6 @@ error[E0080]: could not evaluate static initializer LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0xdeadbeef[noalloc] is a dangling pointer (it has no provenance) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err-multi.stderr b/tests/ui/consts/const-err-multi.stderr index 1ad504b3a80d4..2fe0b9bb463a5 100644 --- a/tests/ui/consts/const-err-multi.stderr +++ b/tests/ui/consts/const-err-multi.stderr @@ -22,6 +22,6 @@ note: erroneous constant encountered LL | pub const D: i8 = 50 - A; | ^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err4.32bit.stderr b/tests/ui/consts/const-err4.32bit.stderr index 1cbf78173a7ae..582a848ca603f 100644 --- a/tests/ui/consts/const-err4.32bit.stderr +++ b/tests/ui/consts/const-err4.32bit.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], | ^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err4.64bit.stderr b/tests/ui/consts/const-err4.64bit.stderr index 1cbf78173a7ae..582a848ca603f 100644 --- a/tests/ui/consts/const-err4.64bit.stderr +++ b/tests/ui/consts/const-err4.64bit.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], | ^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/tests/ui/consts/const-eval/assign-to-static-within-other-static.stderr index 4b6784acfcf06..5300111a6b6bd 100644 --- a/tests/ui/consts/const-eval/assign-to-static-within-other-static.stderr +++ b/tests/ui/consts/const-eval/assign-to-static-within-other-static.stderr @@ -4,6 +4,6 @@ error[E0080]: could not evaluate static initializer LL | FOO = 5; | ^^^^^^^ modifying a static's initial value from another static's initializer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/conditional_array_execution.stderr b/tests/ui/consts/const-eval/conditional_array_execution.stderr index c3401fbaefeee..3003437807970 100644 --- a/tests/ui/consts/const-eval/conditional_array_execution.stderr +++ b/tests/ui/consts/const-eval/conditional_array_execution.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; | ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr b/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr index ed6a6ee6e0fd9..d533dcaa6f6b5 100644 --- a/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr +++ b/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr @@ -8,6 +8,6 @@ LL | &std::intrinsics::size_of::(); LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow-3.stderr b/tests/ui/consts/const-eval/const-eval-overflow-3.stderr index 73f421b5b1465..0437cd3adb41b 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-3.stderr +++ b/tests/ui/consts/const-eval/const-eval-overflow-3.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | = [0; (i8::MAX + 1) as usize]; | ^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4.stderr b/tests/ui/consts/const-eval/const-eval-overflow-4.stderr index 94f4193195c20..ce5e59901c133 100644 --- a/tests/ui/consts/const-eval/const-eval-overflow-4.stderr +++ b/tests/ui/consts/const-eval/const-eval-overflow-4.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | : [u32; (i8::MAX as i8 + 1i8) as usize] | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-span.stderr b/tests/ui/consts/const-eval/const-eval-span.stderr index fe33ad4905a5c..ba11759a71061 100644 --- a/tests/ui/consts/const-eval/const-eval-span.stderr +++ b/tests/ui/consts/const-eval/const-eval-span.stderr @@ -4,6 +4,6 @@ error[E0308]: mismatched types LL | V = CONSTANT, | ^^^^^^^^ expected `isize`, found `S` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.stderr b/tests/ui/consts/const-eval/const_fn_target_feature.stderr index 36918b52cd3af..0c7c69b794aa9 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature.stderr +++ b/tests/ui/consts/const-eval/const_fn_target_feature.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const B: () = unsafe { avx2_fn() }; | ^^^^^^^^^ calling a function that requires unavailable target features: avx2 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_panic-normalize-tabs-115498.stderr b/tests/ui/consts/const-eval/const_panic-normalize-tabs-115498.stderr index 82c63dd176d4d..5f4af25611f09 100644 --- a/tests/ui/consts/const-eval/const_panic-normalize-tabs-115498.stderr +++ b/tests/ui/consts/const-eval/const_panic-normalize-tabs-115498.stderr @@ -6,6 +6,6 @@ LL | struct Bug([u8; panic!{"\t"}]); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_panic_stability.e2021.stderr b/tests/ui/consts/const-eval/const_panic_stability.e2021.stderr index 9e8179181fd09..aad36b52b011c 100644 --- a/tests/ui/consts/const-eval/const_panic_stability.e2021.stderr +++ b/tests/ui/consts/const-eval/const_panic_stability.e2021.stderr @@ -9,5 +9,5 @@ help: you might be missing a string literal to format with LL | panic!("{}", { "foo" }); | +++++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/const_panic_track_caller.stderr b/tests/ui/consts/const-eval/const_panic_track_caller.stderr index 846458176d6fd..a7df82705b880 100644 --- a/tests/ui/consts/const-eval/const_panic_track_caller.stderr +++ b/tests/ui/consts/const-eval/const_panic_track_caller.stderr @@ -15,6 +15,6 @@ note: inside `X` LL | const X: u32 = c(); | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/erroneous-const.stderr b/tests/ui/consts/const-eval/erroneous-const.stderr index 0e31520fdbb06..bd25e96c2cf13 100644 --- a/tests/ui/consts/const-eval/erroneous-const.stderr +++ b/tests/ui/consts/const-eval/erroneous-const.stderr @@ -10,6 +10,6 @@ note: erroneous constant encountered LL | PrintName::::VOID; | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/erroneous-const2.stderr b/tests/ui/consts/const-eval/erroneous-const2.stderr index 4ca44694cd787..6a5839e3dfb41 100644 --- a/tests/ui/consts/const-eval/erroneous-const2.stderr +++ b/tests/ui/consts/const-eval/erroneous-const2.stderr @@ -10,6 +10,6 @@ note: erroneous constant encountered LL | PrintName::::VOID; | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr index 23ba2c2f53516..cdde14756e471 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr @@ -15,6 +15,6 @@ note: inside `FOO` LL | const FOO: i32 = foo(); | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr index 2103f842bd58e..dfaecfbcd8f1e 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr @@ -6,5 +6,5 @@ LL | const FOO: *const i32 = foo(); | = note: memory only reachable via raw pointers is not supported -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr index 82de91effe73b..383c167d3c01a 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -6,9 +6,9 @@ LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr index de23aafe05cca..d06792283262d 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -6,9 +6,9 @@ LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr index b6276647350be..3903ccd6ade7b 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -6,5 +6,5 @@ LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 | = note: memory only reachable via raw pointers is not supported -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr index 916344a7b8169..d2d323e5a5156 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | intrinsics::const_deallocate(ptr, 4, 4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has been freed, so this pointer is dangling -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr index 8bcd030059819..4e7ef52f674af 100644 --- a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr +++ b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr @@ -10,6 +10,6 @@ note: the above error was encountered while instantiating `fn f::<()>` LL | f::<()>(); | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/index_out_of_bounds.stderr b/tests/ui/consts/const-eval/index_out_of_bounds.stderr index 8bb3a0c67d65b..d8df74fa01036 100644 --- a/tests/ui/consts/const-eval/index_out_of_bounds.stderr +++ b/tests/ui/consts/const-eval/index_out_of_bounds.stderr @@ -4,6 +4,6 @@ error[E0080]: could not evaluate static initializer LL | static FOO: i32 = [][0]; | ^^^^^ index out of bounds: the length is 0 but the index is 0 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/index_out_of_bounds_propagated.stderr b/tests/ui/consts/const-eval/index_out_of_bounds_propagated.stderr index d247d691dbb1b..64c87af430883 100644 --- a/tests/ui/consts/const-eval/index_out_of_bounds_propagated.stderr +++ b/tests/ui/consts/const-eval/index_out_of_bounds_propagated.stderr @@ -6,5 +6,5 @@ LL | array[1]; | = note: `#[deny(unconditional_panic)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/infinite_loop.stderr b/tests/ui/consts/const-eval/infinite_loop.stderr index f0434a847cea5..e7a0a96a1e605 100644 --- a/tests/ui/consts/const-eval/infinite_loop.stderr +++ b/tests/ui/consts/const-eval/infinite_loop.stderr @@ -23,5 +23,5 @@ LL | | }]; | |_____^ = note: `#[deny(long_running_const_eval)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/issue-44578.stderr b/tests/ui/consts/const-eval/issue-44578.stderr index eea42c8ce451c..6aabe53011c96 100644 --- a/tests/ui/consts/const-eval/issue-44578.stderr +++ b/tests/ui/consts/const-eval/issue-44578.stderr @@ -27,6 +27,6 @@ LL | println!("{}", as Foo>::AMT); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-49296.stderr b/tests/ui/consts/const-eval/issue-49296.stderr index 2022a16e789ef..485a11d1f3c6f 100644 --- a/tests/ui/consts/const-eval/issue-49296.stderr +++ b/tests/ui/consts/const-eval/issue-49296.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const X: u64 = *wat(42); | ^^^^^^^^ memory access failed: ALLOC0 has been freed, so this pointer is dangling -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr b/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr index 6454ce3d1ae12..f3ec3200f9465 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr +++ b/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr @@ -16,6 +16,6 @@ note: erroneous constant encountered LL | & as Foo>::BAR | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-50814-2.normal.stderr b/tests/ui/consts/const-eval/issue-50814-2.normal.stderr index c6b1df6c8f4d9..f552c8fde5bce 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.normal.stderr +++ b/tests/ui/consts/const-eval/issue-50814-2.normal.stderr @@ -16,6 +16,6 @@ note: the above error was encountered while instantiating `fn foo::<()>` LL | println!("{:x}", foo::<()>() as *const usize as usize); | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-50814.stderr b/tests/ui/consts/const-eval/issue-50814.stderr index 48a20d0bbd083..65c49956f1859 100644 --- a/tests/ui/consts/const-eval/issue-50814.stderr +++ b/tests/ui/consts/const-eval/issue-50814.stderr @@ -16,6 +16,6 @@ note: the above error was encountered while instantiating `fn foo::` LL | foo(0); | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-52475.stderr b/tests/ui/consts/const-eval/issue-52475.stderr index ebf9d12a66ad8..daaee03787f4d 100644 --- a/tests/ui/consts/const-eval/issue-52475.stderr +++ b/tests/ui/consts/const-eval/issue-52475.stderr @@ -24,5 +24,5 @@ LL | | }]; | |_____^ = note: `#[deny(long_running_const_eval)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/issue-70723.stderr b/tests/ui/consts/const-eval/issue-70723.stderr index 572a430726fbd..7cece4ed5d6c4 100644 --- a/tests/ui/consts/const-eval/issue-70723.stderr +++ b/tests/ui/consts/const-eval/issue-70723.stderr @@ -13,5 +13,5 @@ LL | static _X: () = loop {}; | ^^^^^^^^^^^^^ = note: `#[deny(long_running_const_eval)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/issue-85155.stderr b/tests/ui/consts/const-eval/issue-85155.stderr index 3d2c76b7ed040..a88e959a8a659 100644 --- a/tests/ui/consts/const-eval/issue-85155.stderr +++ b/tests/ui/consts/const-eval/issue-85155.stderr @@ -10,6 +10,6 @@ note: the above error was encountered while instantiating `fn post_monomorphizat LL | post_monomorphization_error::stdarch_intrinsic::<2>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-85907.stderr b/tests/ui/consts/const-eval/issue-85907.stderr index fd7b40572c1bb..519227bc69379 100644 --- a/tests/ui/consts/const-eval/issue-85907.stderr +++ b/tests/ui/consts/const-eval/issue-85907.stderr @@ -6,5 +6,5 @@ LL | panic!(123); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/livedrop.stderr b/tests/ui/consts/const-eval/livedrop.stderr index d04fdb70ed30b..1add814060370 100644 --- a/tests/ui/consts/const-eval/livedrop.stderr +++ b/tests/ui/consts/const-eval/livedrop.stderr @@ -7,6 +7,6 @@ LL | let mut always_returned = None; LL | always_returned = never_returned; | --------------- value is dropped here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/const-eval/match-test-ptr-null.stderr b/tests/ui/consts/const-eval/match-test-ptr-null.stderr index 05c3951c1284b..1e14c70fcf10b 100644 --- a/tests/ui/consts/const-eval/match-test-ptr-null.stderr +++ b/tests/ui/consts/const-eval/match-test-ptr-null.stderr @@ -7,5 +7,5 @@ LL | match &1 as *const i32 as usize { = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr b/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr index d127d1d455bd4..901ae1922c74e 100644 --- a/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr +++ b/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr @@ -4,6 +4,6 @@ error[E0080]: could not evaluate static initializer LL | *FOO.0.get() = 5; | ^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr b/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr index e34f3f43c64d6..b878c8d1b3761 100644 --- a/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr +++ b/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const _: () = assert!(42 == *unsafe { NON_NULL.as_ref() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x1[noalloc] is a dangling pointer (it has no provenance) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr index 50660664f87f8..eef39255927ab 100644 --- a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr +++ b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr @@ -20,6 +20,6 @@ LL | let _ = PrintName::VOID; | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/panic-never-type.stderr b/tests/ui/consts/const-eval/panic-never-type.stderr index 6bff14a45b1c5..d3ba3eefb1abf 100644 --- a/tests/ui/consts/const-eval/panic-never-type.stderr +++ b/tests/ui/consts/const-eval/panic-never-type.stderr @@ -6,6 +6,6 @@ LL | const VOID: ! = panic!(); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr index b948e07b92dbf..3203ca764bb0c 100644 --- a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr +++ b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr @@ -7,6 +7,6 @@ LL | *(ptr as *mut u8) = 123; = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/promoted_const_fn_fail.stderr b/tests/ui/consts/const-eval/promoted_const_fn_fail.stderr index 2d4e7c83d3e4e..9aec54793977e 100644 --- a/tests/ui/consts/const-eval/promoted_const_fn_fail.stderr +++ b/tests/ui/consts/const-eval/promoted_const_fn_fail.stderr @@ -9,6 +9,6 @@ LL | let x: &'static u8 = &(bar() + 1); LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr index 9ebae3a18a32f..71e10478982c8 100644 --- a/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr +++ b/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr @@ -9,6 +9,6 @@ LL | let x: &'static u8 = &(bar() + 1); LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index 689ebf7522364..57815e6af65c9 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:20:1 + --> $DIR/raw-bytes.rs:22:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x00000001, but expected a valid enum tag @@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:28:1 + --> $DIR/raw-bytes.rs:30:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x00000000, but expected a valid enum tag @@ -21,7 +21,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:42:1 + --> $DIR/raw-bytes.rs:44:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant @@ -32,7 +32,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:44:1 + --> $DIR/raw-bytes.rs:46:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant @@ -43,7 +43,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:50:1 + --> $DIR/raw-bytes.rs:52:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) @@ -54,7 +54,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:54:1 + --> $DIR/raw-bytes.rs:57:1 | LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 @@ -65,7 +65,7 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:57:1 + --> $DIR/raw-bytes.rs:60:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 @@ -76,7 +76,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:59:1 + --> $DIR/raw-bytes.rs:62:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 @@ -87,7 +87,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:65:1 + --> $DIR/raw-bytes.rs:68:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 @@ -98,7 +98,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:71:1 + --> $DIR/raw-bytes.rs:74:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 @@ -109,7 +109,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:74:1 + --> $DIR/raw-bytes.rs:77:1 | LL | const NULL_FAT_PTR: NonNull = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 @@ -120,7 +120,7 @@ LL | const NULL_FAT_PTR: NonNull = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:82:1 + --> $DIR/raw-bytes.rs:85:1 | LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) @@ -131,7 +131,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:86:1 + --> $DIR/raw-bytes.rs:89:1 | LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) @@ -142,7 +142,7 @@ LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:90:1 + --> $DIR/raw-bytes.rs:93:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference @@ -153,7 +153,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:93:1 + --> $DIR/raw-bytes.rs:96:1 | LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box @@ -164,7 +164,7 @@ LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:96:1 + --> $DIR/raw-bytes.rs:99:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance) @@ -175,7 +175,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:99:1 + --> $DIR/raw-bytes.rs:102:1 | LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance) @@ -186,7 +186,7 @@ LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:102:1 + --> $DIR/raw-bytes.rs:105:1 | LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer @@ -197,7 +197,7 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:104:1 + --> $DIR/raw-bytes.rs:107:1 | LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer @@ -208,10 +208,10 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:106:1 + --> $DIR/raw-bytes.rs:109:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -219,7 +219,7 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:112:1 + --> $DIR/raw-bytes.rs:115:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar @@ -230,7 +230,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:137:1 + --> $DIR/raw-bytes.rs:140:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) @@ -241,7 +241,7 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:139:1 + --> $DIR/raw-bytes.rs:142:1 | LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object @@ -252,7 +252,7 @@ LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, us } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:141:1 + --> $DIR/raw-bytes.rs:144:1 | LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object @@ -263,7 +263,7 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize: } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:144:1 + --> $DIR/raw-bytes.rs:147:1 | LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized memory, but expected a string @@ -274,7 +274,7 @@ LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit: } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:146:1 + --> $DIR/raw-bytes.rs:149:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered uninitialized memory, but expected a string @@ -285,7 +285,7 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:148:1 + --> $DIR/raw-bytes.rs:151:1 | LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a pointer, but expected a string @@ -298,7 +298,7 @@ LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _> = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:152:1 + --> $DIR/raw-bytes.rs:155:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) @@ -309,7 +309,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:154:1 + --> $DIR/raw-bytes.rs:157:1 | LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object @@ -320,7 +320,7 @@ LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, is } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:157:1 + --> $DIR/raw-bytes.rs:160:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) @@ -331,7 +331,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:160:1 + --> $DIR/raw-bytes.rs:163:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x03, but expected a boolean @@ -342,13 +342,13 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; } note: erroneous constant encountered - --> $DIR/raw-bytes.rs:160:40 + --> $DIR/raw-bytes.rs:163:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:166:1 + --> $DIR/raw-bytes.rs:169:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered 0x03, but expected a boolean @@ -359,13 +359,13 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 } note: erroneous constant encountered - --> $DIR/raw-bytes.rs:166:42 + --> $DIR/raw-bytes.rs:169:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:170:1 + --> $DIR/raw-bytes.rs:173:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..1[0]: encountered 0x03, but expected a boolean @@ -376,16 +376,16 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran } note: erroneous constant encountered - --> $DIR/raw-bytes.rs:170:42 + --> $DIR/raw-bytes.rs:173:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:175:1 + --> $DIR/raw-bytes.rs:178:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -393,10 +393,10 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:179:1 + --> $DIR/raw-bytes.rs:182:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -404,7 +404,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:183:1 + --> $DIR/raw-bytes.rs:186:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer @@ -415,10 +415,10 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:186:1 + --> $DIR/raw-bytes.rs:189:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -426,7 +426,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:190:1 + --> $DIR/raw-bytes.rs:193:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..: encountered 0x03, but expected a boolean @@ -437,7 +437,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:194:1 + --> $DIR/raw-bytes.rs:197:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer @@ -448,10 +448,10 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:196:1 + --> $DIR/raw-bytes.rs:199:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { @@ -459,29 +459,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:201:1 - | -LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000000, but expected a valid enum tag - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 4) { - 00 00 00 00 00 10 00 00 │ ........ - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:205:1 - | -LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000003, but expected a valid enum tag - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 4) { - 03 00 00 00 09 00 00 00 │ ........ - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:209:1 + --> $DIR/raw-bytes.rs:203:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] @@ -492,7 +470,7 @@ LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:210:1 + --> $DIR/raw-bytes.rs:204:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` @@ -503,7 +481,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:211:1 + --> $DIR/raw-bytes.rs:205:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` @@ -514,7 +492,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:215:1 + --> $DIR/raw-bytes.rs:209:1 | LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized memory, but expected an integer @@ -525,7 +503,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) } } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:218:1 + --> $DIR/raw-bytes.rs:212:1 | LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) }; | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a pointer, but expected an integer @@ -538,7 +516,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem: = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:221:1 + --> $DIR/raw-bytes.rs:215:1 | LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean @@ -549,7 +527,7 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:225:1 + --> $DIR/raw-bytes.rs:219:1 | LL | pub static S7: &[u16] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[1]: encountered uninitialized memory, but expected an integer @@ -560,7 +538,7 @@ LL | pub static S7: &[u16] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:232:1 + --> $DIR/raw-bytes.rs:226:1 | LL | pub static R4: &[u8] = unsafe { | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized memory, but expected an integer @@ -571,7 +549,7 @@ LL | pub static R4: &[u8] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:237:1 + --> $DIR/raw-bytes.rs:231:1 | LL | pub static R5: &[u8] = unsafe { | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a pointer, but expected an integer @@ -584,7 +562,7 @@ LL | pub static R5: &[u8] = unsafe { = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:242:1 + --> $DIR/raw-bytes.rs:236:1 | LL | pub static R6: &[bool] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean @@ -594,6 +572,6 @@ LL | pub static R6: &[bool] = unsafe { ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼.... } -error: aborting due to 52 previous errors +error: aborting due to 50 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index 3447a8ab432c2..c875d91ccb87a 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:20:1 + --> $DIR/raw-bytes.rs:22:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x0000000000000001, but expected a valid enum tag @@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:28:1 + --> $DIR/raw-bytes.rs:30:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x0000000000000000, but expected a valid enum tag @@ -21,7 +21,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:42:1 + --> $DIR/raw-bytes.rs:44:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant @@ -32,7 +32,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:44:1 + --> $DIR/raw-bytes.rs:46:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant @@ -43,7 +43,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:50:1 + --> $DIR/raw-bytes.rs:52:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) @@ -54,7 +54,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:54:1 + --> $DIR/raw-bytes.rs:57:1 | LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 @@ -65,7 +65,7 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:57:1 + --> $DIR/raw-bytes.rs:60:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 @@ -76,7 +76,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:59:1 + --> $DIR/raw-bytes.rs:62:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 @@ -87,7 +87,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:65:1 + --> $DIR/raw-bytes.rs:68:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 @@ -98,7 +98,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:71:1 + --> $DIR/raw-bytes.rs:74:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 @@ -109,7 +109,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:74:1 + --> $DIR/raw-bytes.rs:77:1 | LL | const NULL_FAT_PTR: NonNull = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 @@ -120,7 +120,7 @@ LL | const NULL_FAT_PTR: NonNull = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:82:1 + --> $DIR/raw-bytes.rs:85:1 | LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) @@ -131,7 +131,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:86:1 + --> $DIR/raw-bytes.rs:89:1 | LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) @@ -142,7 +142,7 @@ LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:90:1 + --> $DIR/raw-bytes.rs:93:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference @@ -153,7 +153,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:93:1 + --> $DIR/raw-bytes.rs:96:1 | LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box @@ -164,7 +164,7 @@ LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:96:1 + --> $DIR/raw-bytes.rs:99:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance) @@ -175,7 +175,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:99:1 + --> $DIR/raw-bytes.rs:102:1 | LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance) @@ -186,7 +186,7 @@ LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:102:1 + --> $DIR/raw-bytes.rs:105:1 | LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer @@ -197,7 +197,7 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:104:1 + --> $DIR/raw-bytes.rs:107:1 | LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer @@ -208,10 +208,10 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:106:1 + --> $DIR/raw-bytes.rs:109:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -219,7 +219,7 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:112:1 + --> $DIR/raw-bytes.rs:115:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar @@ -230,7 +230,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:137:1 + --> $DIR/raw-bytes.rs:140:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) @@ -241,7 +241,7 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:139:1 + --> $DIR/raw-bytes.rs:142:1 | LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object @@ -252,7 +252,7 @@ LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, us } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:141:1 + --> $DIR/raw-bytes.rs:144:1 | LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object @@ -263,7 +263,7 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize: } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:144:1 + --> $DIR/raw-bytes.rs:147:1 | LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized memory, but expected a string @@ -274,7 +274,7 @@ LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit: } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:146:1 + --> $DIR/raw-bytes.rs:149:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered uninitialized memory, but expected a string @@ -285,7 +285,7 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:148:1 + --> $DIR/raw-bytes.rs:151:1 | LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a pointer, but expected a string @@ -298,7 +298,7 @@ LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _> = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:152:1 + --> $DIR/raw-bytes.rs:155:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) @@ -309,7 +309,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:154:1 + --> $DIR/raw-bytes.rs:157:1 | LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object @@ -320,7 +320,7 @@ LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, is } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:157:1 + --> $DIR/raw-bytes.rs:160:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) @@ -331,7 +331,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:160:1 + --> $DIR/raw-bytes.rs:163:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x03, but expected a boolean @@ -342,13 +342,13 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; } note: erroneous constant encountered - --> $DIR/raw-bytes.rs:160:40 + --> $DIR/raw-bytes.rs:163:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:166:1 + --> $DIR/raw-bytes.rs:169:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered 0x03, but expected a boolean @@ -359,13 +359,13 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 } note: erroneous constant encountered - --> $DIR/raw-bytes.rs:166:42 + --> $DIR/raw-bytes.rs:169:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:170:1 + --> $DIR/raw-bytes.rs:173:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..1[0]: encountered 0x03, but expected a boolean @@ -376,16 +376,16 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran } note: erroneous constant encountered - --> $DIR/raw-bytes.rs:170:42 + --> $DIR/raw-bytes.rs:173:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:175:1 + --> $DIR/raw-bytes.rs:178:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -393,10 +393,10 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:179:1 + --> $DIR/raw-bytes.rs:182:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -404,7 +404,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:183:1 + --> $DIR/raw-bytes.rs:186:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer @@ -415,10 +415,10 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:186:1 + --> $DIR/raw-bytes.rs:189:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -426,7 +426,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:190:1 + --> $DIR/raw-bytes.rs:193:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..: encountered 0x03, but expected a boolean @@ -437,7 +437,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:194:1 + --> $DIR/raw-bytes.rs:197:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer @@ -448,10 +448,10 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:196:1 + --> $DIR/raw-bytes.rs:199:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -459,29 +459,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:201:1 - | -LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000000, but expected a valid enum tag - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 16, align: 8) { - 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 │ ................ - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:205:1 - | -LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000003, but expected a valid enum tag - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 16, align: 8) { - 03 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00 │ ................ - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:209:1 + --> $DIR/raw-bytes.rs:203:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] @@ -492,7 +470,7 @@ LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:210:1 + --> $DIR/raw-bytes.rs:204:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` @@ -503,7 +481,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:211:1 + --> $DIR/raw-bytes.rs:205:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` @@ -514,7 +492,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:215:1 + --> $DIR/raw-bytes.rs:209:1 | LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized memory, but expected an integer @@ -525,7 +503,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) } } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:218:1 + --> $DIR/raw-bytes.rs:212:1 | LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) }; | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a pointer, but expected an integer @@ -538,7 +516,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem: = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:221:1 + --> $DIR/raw-bytes.rs:215:1 | LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean @@ -549,7 +527,7 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:225:1 + --> $DIR/raw-bytes.rs:219:1 | LL | pub static S7: &[u16] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[1]: encountered uninitialized memory, but expected an integer @@ -560,7 +538,7 @@ LL | pub static S7: &[u16] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:232:1 + --> $DIR/raw-bytes.rs:226:1 | LL | pub static R4: &[u8] = unsafe { | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized memory, but expected an integer @@ -571,7 +549,7 @@ LL | pub static R4: &[u8] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:237:1 + --> $DIR/raw-bytes.rs:231:1 | LL | pub static R5: &[u8] = unsafe { | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a pointer, but expected an integer @@ -584,7 +562,7 @@ LL | pub static R5: &[u8] = unsafe { = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:242:1 + --> $DIR/raw-bytes.rs:236:1 | LL | pub static R6: &[bool] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean @@ -594,6 +572,6 @@ LL | pub static R6: &[bool] = unsafe { ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -error: aborting due to 52 previous errors +error: aborting due to 50 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs index e005922223ad8..ae65a5cb8dfc0 100644 --- a/tests/ui/consts/const-eval/raw-bytes.rs +++ b/tests/ui/consts/const-eval/raw-bytes.rs @@ -1,7 +1,7 @@ // stderr-per-bitwidth // ignore-endian-big // ignore-tidy-linelength -// normalize-stderr-test "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$1╼" +// normalize-stderr-test "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼" -> "╾ALLOC_ID$1╼" #![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)] #![allow(invalid_value)] @@ -12,6 +12,8 @@ use std::ptr::NonNull; use std::num::{NonZeroU8, NonZeroUsize}; use std::slice::{from_ptr_range, from_raw_parts}; +// # Bad enums and chars + #[repr(usize)] #[derive(Copy, Clone)] enum Enum { @@ -50,6 +52,7 @@ const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); //~^ ERROR is undefined behavior +// # Bad pointers and references const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value @@ -196,16 +199,7 @@ const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92 const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; //~^ ERROR it is undefined behavior to use this value - -// not ok, since alignment needs to be non-zero. -const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; -//~^ ERROR it is undefined behavior to use this value - -// not ok, since alignment needs to be a power of two. -const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; -//~^ ERROR it is undefined behavior to use this value - - +// Uninhabited types const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; //~ ERROR undefined behavior diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr index 60fcd461cdecd..cba06fdc639f5 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr +++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr @@ -17,7 +17,7 @@ error[E0080]: evaluation of constant value failed | note: inside `copy_nonoverlapping::` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL -note: inside `ptr::const_ptr::::copy_to_nonoverlapping` +note: inside `std::ptr::const_ptr::::copy_to_nonoverlapping` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `MISALIGNED_COPY` --> $DIR/raw-pointer-ub.rs:22:5 diff --git a/tests/ui/consts/const-eval/shift_overflow.stderr b/tests/ui/consts/const-eval/shift_overflow.stderr index e8d4076a61a24..901bfa10ee85c 100644 --- a/tests/ui/consts/const-eval/shift_overflow.stderr +++ b/tests/ui/consts/const-eval/shift_overflow.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | X = 1 << ((u32::MAX as u64) + 1), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left by `4294967296_u64`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/size-of-t.stderr b/tests/ui/consts/const-eval/size-of-t.stderr index abe6410465e44..418ac6f612ca5 100644 --- a/tests/ui/consts/const-eval/size-of-t.stderr +++ b/tests/ui/consts/const-eval/size-of-t.stderr @@ -5,7 +5,7 @@ LL | let _arr: [u8; size_of::()]; | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions - = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr index a3fd712ca4608..f087c9960c28f 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr @@ -13,5 +13,5 @@ LL | const X: u32 = call_foo(); | ^^^^^^^^^^^^ = note: `#[deny(long_running_const_eval)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr index 5808ee35a6b45..ecb48fc62a3d8 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr @@ -19,5 +19,5 @@ LL | const X: u32 = labelled_loop(19); | ^^^^^^^^^^^^ = note: `#[deny(long_running_const_eval)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr index 524c8e5542666..a05d792c95ca8 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr @@ -13,5 +13,5 @@ LL | const X: u32 = recurse(19); | ^^^^^^^^^^^^ = note: `#[deny(long_running_const_eval)]` on by default -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/transmute-const-promotion.stderr b/tests/ui/consts/const-eval/transmute-const-promotion.stderr index 434a957f64840..3603db03bb204 100644 --- a/tests/ui/consts/const-eval/transmute-const-promotion.stderr +++ b/tests/ui/consts/const-eval/transmute-const-promotion.stderr @@ -9,6 +9,6 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/transmute-const.32bit.stderr b/tests/ui/consts/const-eval/transmute-const.32bit.stderr index 09fd79986958d..35a5cabaa6710 100644 --- a/tests/ui/consts/const-eval/transmute-const.32bit.stderr +++ b/tests/ui/consts/const-eval/transmute-const.32bit.stderr @@ -9,6 +9,6 @@ LL | static FOO: bool = unsafe { mem::transmute(3u8) }; 03 │ . } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/transmute-const.64bit.stderr b/tests/ui/consts/const-eval/transmute-const.64bit.stderr index 09fd79986958d..35a5cabaa6710 100644 --- a/tests/ui/consts/const-eval/transmute-const.64bit.stderr +++ b/tests/ui/consts/const-eval/transmute-const.64bit.stderr @@ -9,6 +9,6 @@ LL | static FOO: bool = unsafe { mem::transmute(3u8) }; 03 │ . } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr index 5750212b44c8f..2a133c057b3e3 100644 --- a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr +++ b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | unsafe { *p } | ^^ using uninitialized data, but this operation requires initialized memory -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr index 7b30233c02569..5c47cbfdf3b1e 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -2,55 +2,55 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:18:1 | LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:23:1 | LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──╼╾──╼ + ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──╼╾──╼ + ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──╼╾──╼ + ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──╼╾──╼ + ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──╼╾──╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index 9330ae3c9a6bb..f400073aca215 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -2,55 +2,55 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:18:1 | LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:23:1 | LL | const INVALID_VTABLE_SIZE: &dyn Trait = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──────╼╾──────╼ + ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ + ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──────╼╾──────╼ + ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──────╼╾──────╼ + ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──────╼╾──────╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr b/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr index 2a4b6f3b76f90..fef6c92af9857 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr @@ -4,6 +4,6 @@ error[E0284]: type annotations needed: cannot satisfy `>::Output == _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs index 08d4dce4d17f8..9e49e3de8bc37 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.rs +++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" #![allow(invalid_value)] use std::mem; diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr index c608bad2a47b0..3bbf2977392c0 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr @@ -141,7 +141,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref-ptr.rs:59:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2, but expected a function pointer + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC2, but expected a function pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -155,7 +155,7 @@ error[E0080]: evaluation of constant value failed | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `ptr::const_ptr::::read` +note: inside `std::ptr::const_ptr::::read` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `UNALIGNED_READ` --> $DIR/ub-ref-ptr.rs:66:5 diff --git a/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr b/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr index 403fb5e09404d..de96821e8b987 100644 --- a/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr +++ b/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr @@ -6,6 +6,6 @@ LL | const B: &[()] = unsafe { A.get_unchecked(3..1) }; | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr index 353a9b782240e..5342fea66bdb4 100644 --- a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -6,9 +6,9 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{ | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr index 097f6b049dc81..a2496dfc287bc 100644 --- a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -6,9 +6,9 @@ LL | const BAD_UPVAR: &dyn FnOnce() = &{ | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr index 39352ca848a80..533db90ce6c9e 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^ cannot infer type for type parameter `U` declared on the function `transmute` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs index dc8d4c640c2f0..3c1baab3e48f6 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.rs +++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs @@ -5,7 +5,7 @@ use std::mem; // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" // normalize-stderr-test "offset \d+" -> "offset N" // normalize-stderr-test "size \d+" -> "size N" diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index b203794858acd..91ce531c9f7c2 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -189,7 +189,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:113:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC12, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC12, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -200,7 +200,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC14, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC14, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -222,7 +222,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:124:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC17, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC17, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -233,7 +233,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:127:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC19, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC19, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -244,7 +244,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:130:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC21, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC21, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -255,7 +255,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:133:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC23, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC23, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -288,7 +288,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:145:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC28, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC28, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -310,7 +310,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:154:1 | LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC31, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC31, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.rs b/tests/ui/consts/const-eval/ub-write-through-immutable.rs new file mode 100644 index 0000000000000..945367f182308 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.rs @@ -0,0 +1,30 @@ +//! Ensure we catch UB due to writing through a shared reference. +#![feature(const_mut_refs, const_refs_to_cell)] +#![deny(writes_through_immutable_pointer)] +#![allow(invalid_reference_casting)] + +use std::mem; +use std::cell::UnsafeCell; + +const WRITE_AFTER_CAST: () = unsafe { + let mut x = 0; + let ptr = &x as *const i32 as *mut i32; + *ptr = 0; //~ERROR: writes_through_immutable_pointer + //~^ previously accepted +}; + +const WRITE_AFTER_TRANSMUTE: () = unsafe { + let mut x = 0; + let ptr: *mut i32 = mem::transmute(&x); + *ptr = 0; //~ERROR: writes_through_immutable_pointer + //~^ previously accepted +}; + +// it's okay when there is interior mutability; +const WRITE_INTERIOR_MUT: () = unsafe { + let x = UnsafeCell::new(0); + let ptr = &x as *const _ as *mut i32; + *ptr = 0; +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.stderr b/tests/ui/consts/const-eval/ub-write-through-immutable.stderr new file mode 100644 index 0000000000000..27eb2d2c0d152 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.stderr @@ -0,0 +1,55 @@ +error: writing through a pointer that was derived from a shared (immutable) reference + --> $DIR/ub-write-through-immutable.rs:12:5 + | +LL | *ptr = 0; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #X +note: the lint level is defined here + --> $DIR/ub-write-through-immutable.rs:3:9 + | +LL | #![deny(writes_through_immutable_pointer)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: writing through a pointer that was derived from a shared (immutable) reference + --> $DIR/ub-write-through-immutable.rs:19:5 + | +LL | *ptr = 0; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #X + +error: aborting due to 2 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: writing through a pointer that was derived from a shared (immutable) reference + --> $DIR/ub-write-through-immutable.rs:12:5 + | +LL | *ptr = 0; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #X +note: the lint level is defined here + --> $DIR/ub-write-through-immutable.rs:3:9 + | +LL | #![deny(writes_through_immutable_pointer)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: writing through a pointer that was derived from a shared (immutable) reference + --> $DIR/ub-write-through-immutable.rs:19:5 + | +LL | *ptr = 0; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #X +note: the lint level is defined here + --> $DIR/ub-write-through-immutable.rs:3:9 + | +LL | #![deny(writes_through_immutable_pointer)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const-eval/union-const-eval-field.stderr b/tests/ui/consts/const-eval/union-const-eval-field.stderr index b299208ae8156..b1de225ec580d 100644 --- a/tests/ui/consts/const-eval/union-const-eval-field.stderr +++ b/tests/ui/consts/const-eval/union-const-eval-field.stderr @@ -18,6 +18,6 @@ LL | FIELD3 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/union_promotion.stderr b/tests/ui/consts/const-eval/union_promotion.stderr index 42f17de200344..49a285f844fd0 100644 --- a/tests/ui/consts/const-eval/union_promotion.stderr +++ b/tests/ui/consts/const-eval/union_promotion.stderr @@ -11,6 +11,6 @@ LL | | }; LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/unused-broken-const-late.stderr b/tests/ui/consts/const-eval/unused-broken-const-late.stderr index cdb70a69dfd8a..c2cf2f3813c5e 100644 --- a/tests/ui/consts/const-eval/unused-broken-const-late.stderr +++ b/tests/ui/consts/const-eval/unused-broken-const-late.stderr @@ -6,6 +6,6 @@ LL | const VOID: () = panic!(); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/unused-broken-const.stderr b/tests/ui/consts/const-eval/unused-broken-const.stderr index fbb10feb76b16..fd0ee316fe248 100644 --- a/tests/ui/consts/const-eval/unused-broken-const.stderr +++ b/tests/ui/consts/const-eval/unused-broken-const.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const FOO: i32 = [][0]; | ^^^^^ index out of bounds: the length is 0 but the index is 0 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/unwind-abort.stderr b/tests/ui/consts/const-eval/unwind-abort.stderr index 759ce15ab1b5d..d7330beca7b54 100644 --- a/tests/ui/consts/const-eval/unwind-abort.stderr +++ b/tests/ui/consts/const-eval/unwind-abort.stderr @@ -16,6 +16,6 @@ LL | const _: () = foo(); | ^^^^^ = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr index 5ec9e2a91f1dc..aaa8dfa8dca5c 100644 --- a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr +++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr @@ -4,5 +4,5 @@ error: expected one of `extern` or `fn`, found `WhereIsFerris` LL | const unsafe WhereIsFerris Now() {} | ^^^^^^^^^^^^^ expected one of `extern` or `fn` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr index ec415ec9d0211..82074867b2690 100644 --- a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr +++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr @@ -4,5 +4,5 @@ error: expected `fn`, found `PUT_ANYTHING_YOU_WANT_HERE` LL | const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `fn` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-external-macro-const-err.stderr b/tests/ui/consts/const-external-macro-const-err.stderr index 81f6c09ffb86a..63f81ea18bc04 100644 --- a/tests/ui/consts/const-external-macro-const-err.stderr +++ b/tests/ui/consts/const-external-macro-const-err.stderr @@ -6,6 +6,6 @@ LL | static_assert!(2 + 2 == 5); | = note: this error originates in the macro `static_assert` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr index a23d81c0ebec4..f0c6c69eac4e6 100644 --- a/tests/ui/consts/const-float-classify.stderr +++ b/tests/ui/consts/const-float-classify.stderr @@ -6,6 +6,6 @@ LL | x.eq(y) | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-fn-in-vec.rs b/tests/ui/consts/const-fn-in-vec.rs index a40290eca0972..0483800efefd1 100644 --- a/tests/ui/consts/const-fn-in-vec.rs +++ b/tests/ui/consts/const-fn-in-vec.rs @@ -1,7 +1,11 @@ +static _MAYBE_STRINGS: [Option; 5] = [None; 5]; +//~^ ERROR the trait bound `String: Copy` is not satisfied + fn main() { // should hint to create an inline `const` block // or to create a new `const` item - let strings: [String; 5] = [String::new(); 5]; + let _strings: [String; 5] = [String::new(); 5]; + //~^ ERROR the trait bound `String: Copy` is not satisfied + let _maybe_strings: [Option; 5] = [None; 5]; //~^ ERROR the trait bound `String: Copy` is not satisfied - println!("{:?}", strings); } diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr index 9eb7524b5044b..4593034bfaea3 100644 --- a/tests/ui/consts/const-fn-in-vec.stderr +++ b/tests/ui/consts/const-fn-in-vec.stderr @@ -1,13 +1,47 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/const-fn-in-vec.rs:4:33 + --> $DIR/const-fn-in-vec.rs:1:47 | -LL | let strings: [String; 5] = [String::new(); 5]; - | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` +LL | static _MAYBE_STRINGS: [Option; 5] = [None; 5]; + | ^^^^ the trait `Copy` is not implemented for `String` | + = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position + | +LL + const ARRAY_REPEAT_VALUE: Option = None; +LL ~ static _MAYBE_STRINGS: [Option; 5] = [ARRAY_REPEAT_VALUE; 5]; + | + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/const-fn-in-vec.rs:7:34 + | +LL | let _strings: [String; 5] = [String::new(); 5]; + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: String = String::new(); +LL ~ let _strings: [String; 5] = [ARRAY_REPEAT_VALUE; 5]; + | + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/const-fn-in-vec.rs:9:48 + | +LL | let _maybe_strings: [Option; 5] = [None; 5]; + | ^^^^ the trait `Copy` is not implemented for `String` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Option = None; +LL ~ let _maybe_strings: [Option; 5] = [ARRAY_REPEAT_VALUE; 5]; + | -error: aborting due to previous error +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-fn-mismatch.stderr b/tests/ui/consts/const-fn-mismatch.stderr index a86a06b3ef19e..beaf52c0cfb36 100644 --- a/tests/ui/consts/const-fn-mismatch.stderr +++ b/tests/ui/consts/const-fn-mismatch.stderr @@ -4,6 +4,6 @@ error[E0379]: functions in traits cannot be declared const LL | const fn f() -> u32 { | ^^^^^ functions in traits cannot be const -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index 2ea377e09f61e..0c24bbad7dd43 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -7,6 +7,6 @@ LL | for _ in 0..5 {} = note: see issue #87575 for more information = help: add `#![feature(const_for)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-int-unchecked.stderr b/tests/ui/consts/const-int-unchecked.stderr index ad880d56d904d..ad14c8f68f8cb 100644 --- a/tests/ui/consts/const-int-unchecked.stderr +++ b/tests/ui/consts/const-int-unchecked.stderr @@ -62,61 +62,61 @@ error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:41:33 | LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:43:35 | LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:45:35 | LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:47:35 | LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:49:37 | LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:55:40 | LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -6 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:57:42 | LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -13 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:59:42 | LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -25 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:61:42 | LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -30 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:63:44 | LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -93 in `unchecked_shl` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:70:29 @@ -182,61 +182,61 @@ error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:96:33 | LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:98:35 | LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:100:35 | LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:102:35 | LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:104:37 | LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:110:40 | LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -6 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:112:42 | LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -13 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:114:42 | LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -25 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:116:42 | LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -30 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:118:44 | LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -93 in `unchecked_shr` error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:123:25 diff --git a/tests/ui/consts/const-len-underflow-separate-spans.next.stderr b/tests/ui/consts/const-len-underflow-separate-spans.next.stderr index b7b5b648c1241..bd2a81f514830 100644 --- a/tests/ui/consts/const-len-underflow-separate-spans.next.stderr +++ b/tests/ui/consts/const-len-underflow-separate-spans.next.stderr @@ -10,6 +10,6 @@ note: erroneous constant encountered LL | let a: [i8; LEN] = unimplemented!(); | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-len-underflow-separate-spans.old.stderr b/tests/ui/consts/const-len-underflow-separate-spans.old.stderr index b7b5b648c1241..bd2a81f514830 100644 --- a/tests/ui/consts/const-len-underflow-separate-spans.old.stderr +++ b/tests/ui/consts/const-len-underflow-separate-spans.old.stderr @@ -10,6 +10,6 @@ note: erroneous constant encountered LL | let a: [i8; LEN] = unimplemented!(); | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-len-underflow-subspans.stderr b/tests/ui/consts/const-len-underflow-subspans.stderr index 68e958b378da7..bfec056cc8aae 100644 --- a/tests/ui/consts/const-len-underflow-subspans.stderr +++ b/tests/ui/consts/const-len-underflow-subspans.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | let a: [i8; ONE - TWO] = unimplemented!(); | ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-match-check.eval1.stderr b/tests/ui/consts/const-match-check.eval1.stderr index 27ff5d4cd5c6b..84890214861b8 100644 --- a/tests/ui/consts/const-match-check.eval1.stderr +++ b/tests/ui/consts/const-match-check.eval1.stderr @@ -16,6 +16,6 @@ help: alternatively, you could prepend the pattern with an underscore to define LL | A = { let _0 = 0; 0 }, | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const-match-check.eval2.stderr b/tests/ui/consts/const-match-check.eval2.stderr index 0c74a7b3dd4d2..0aa12eb86dddc 100644 --- a/tests/ui/consts/const-match-check.eval2.stderr +++ b/tests/ui/consts/const-match-check.eval2.stderr @@ -16,6 +16,6 @@ help: alternatively, you could prepend the pattern with an underscore to define LL | let x: [i32; { let _0 = 0; 0 }] = []; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr b/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr index 3f9bd37053a0e..7d8d062dbbed4 100644 --- a/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr +++ b/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr @@ -7,6 +7,6 @@ LL | const fn foo(x: &mut i32) -> i32 { = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-points-to-static.32bit.stderr b/tests/ui/consts/const-points-to-static.32bit.stderr index 12cc7fbb1fc62..73fbf5e1837e2 100644 --- a/tests/ui/consts/const-points-to-static.32bit.stderr +++ b/tests/ui/consts/const-points-to-static.32bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } warning: skipping const checks @@ -17,6 +17,6 @@ help: skipping check that does not even have a feature gate LL | const TEST: &u8 = &MY_STATIC; | ^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-points-to-static.64bit.stderr b/tests/ui/consts/const-points-to-static.64bit.stderr index 86506e6ca010b..42088bbb2c4a9 100644 --- a/tests/ui/consts/const-points-to-static.64bit.stderr +++ b/tests/ui/consts/const-points-to-static.64bit.stderr @@ -6,7 +6,7 @@ LL | const TEST: &u8 = &MY_STATIC; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } warning: skipping const checks @@ -17,6 +17,6 @@ help: skipping check that does not even have a feature gate LL | const TEST: &u8 = &MY_STATIC; | ^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-ptr-unique.stderr b/tests/ui/consts/const-ptr-unique.stderr index 83448c3e8d876..c3cc69830dfd8 100644 --- a/tests/ui/consts/const-ptr-unique.stderr +++ b/tests/ui/consts/const-ptr-unique.stderr @@ -9,6 +9,6 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-size_of-cycle.stderr b/tests/ui/consts/const-size_of-cycle.stderr index 46b432357aae6..a5679400c2f0e 100644 --- a/tests/ui/consts/const-size_of-cycle.stderr +++ b/tests/ui/consts/const-size_of-cycle.stderr @@ -25,6 +25,6 @@ LL | struct Foo { | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/const-slice-oob.stderr b/tests/ui/consts/const-slice-oob.stderr index 746883a79a65b..30ec340d2a237 100644 --- a/tests/ui/consts/const-slice-oob.stderr +++ b/tests/ui/consts/const-slice-oob.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const BAR: u32 = FOO[5]; | ^^^^^^ index out of bounds: the length is 3 but the index is 5 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-suggest-feature.stderr b/tests/ui/consts/const-suggest-feature.stderr index 3bc1eacf32f96..d4a42a880e328 100644 --- a/tests/ui/consts/const-suggest-feature.stderr +++ b/tests/ui/consts/const-suggest-feature.stderr @@ -7,6 +7,6 @@ LL | *std::ptr::null_mut() = 0; = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr index cd1a063043207..79c6ec108b966 100644 --- a/tests/ui/consts/const-try-feature-gate.stderr +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -7,6 +7,6 @@ LL | Some(())?; = note: see issue #74935 for more information = help: add `#![feature(const_try)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-tup-index-span.stderr b/tests/ui/consts/const-tup-index-span.stderr index d5df0df9525c5..792e18aa8fd4b 100644 --- a/tests/ui/consts/const-tup-index-span.stderr +++ b/tests/ui/consts/const-tup-index-span.stderr @@ -11,6 +11,6 @@ help: use a trailing comma to create a tuple with one element LL | const TUP: (usize,) = (5usize << 64,); | + ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-unwrap.stderr b/tests/ui/consts/const-unwrap.stderr index d2cbe4550f4bb..fee22a1d070b8 100644 --- a/tests/ui/consts/const-unwrap.stderr +++ b/tests/ui/consts/const-unwrap.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const BAR: i32 = Option::::None.unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:7:38 -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr b/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr index ae24f8f65009a..e1b8154a287e0 100644 --- a/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr +++ b/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr index be144a87b8b34..4ecfb3f1c5a48 100644 --- a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr +++ b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr @@ -23,6 +23,6 @@ LL ~ E_SL => {}, LL + &_ => todo!() | -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs new file mode 100644 index 0000000000000..6285427f59cbd --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs @@ -0,0 +1,40 @@ +#![deny(pointer_structural_match)] +#![allow(dead_code)] + +const C: *const u8 = &0; +// Make sure we also find pointers nested in other types. +const C_INNER: (*const u8, u8) = (C, 0); + +fn foo(x: *const u8) { + match x { + C => {} //~ERROR: behave unpredictably + //~| previously accepted + _ => {} + } +} + +fn foo2(x: *const u8) { + match (x, 1) { + C_INNER => {} //~ERROR: behave unpredictably + //~| previously accepted + _ => {} + } +} + +const D: *const [u8; 4] = b"abcd"; + +const STR: *const str = "abcd"; + +fn main() { + match D { + D => {} //~ERROR: behave unpredictably + //~| previously accepted + _ => {} + } + + match STR { + STR => {} //~ERROR: behave unpredictably + //~| previously accepted + _ => {} + } +} diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr new file mode 100644 index 0000000000000..1546f23908c6f --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -0,0 +1,43 @@ +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:10:9 + | +LL | C => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:18:9 + | +LL | C_INNER => {} + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9 + | +LL | D => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9 + | +LL | STR => {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +error: aborting due to 4 previous errors + diff --git a/tests/ui/consts/const_in_pattern/issue-44333.rs b/tests/ui/consts/const_in_pattern/issue-44333.rs index 96e8795e52d56..aaf1edb6fe6e4 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.rs +++ b/tests/ui/consts/const_in_pattern/issue-44333.rs @@ -16,9 +16,9 @@ const BAR: Func = bar; fn main() { match test(std::env::consts::ARCH.len()) { - FOO => println!("foo"), //~ WARN pointers in patterns behave unpredictably + FOO => println!("foo"), //~ WARN behave unpredictably //~^ WARN will become a hard error - BAR => println!("bar"), //~ WARN pointers in patterns behave unpredictably + BAR => println!("bar"), //~ WARN behave unpredictably //~^ WARN will become a hard error _ => unreachable!(), } diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index 731ef509ccad4..441aeecbc6d95 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -1,4 +1,4 @@ -warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-44333.rs:19:9 | LL | FOO => println!("foo"), @@ -12,7 +12,7 @@ note: the lint level is defined here LL | #![warn(pointer_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-44333.rs:21:9 | LL | BAR => println!("bar"), diff --git a/tests/ui/consts/const_in_pattern/issue-78057.stderr b/tests/ui/consts/const_in_pattern/issue-78057.stderr index 5ec68719a9732..719295c96a5bd 100644 --- a/tests/ui/consts/const_in_pattern/issue-78057.stderr +++ b/tests/ui/consts/const_in_pattern/issue-78057.stderr @@ -7,5 +7,5 @@ LL | FOO => {}, = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr index cced6af499f18..1979c297ae44e 100644 --- a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr +++ b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr @@ -7,5 +7,5 @@ LL | BAR_BAZ => panic!(), = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr index 958bf373cf40d..d3628a8decb16 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr @@ -7,5 +7,5 @@ LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_let_refutable.stderr b/tests/ui/consts/const_let_refutable.stderr index d6119028f5b59..5aedfb03f6cbf 100644 --- a/tests/ui/consts/const_let_refutable.stderr +++ b/tests/ui/consts/const_let_refutable.stderr @@ -6,6 +6,6 @@ LL | const fn slice(&[a, b]: &[i32]) -> i32 { | = note: the matched value is of type `&[i32]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const_unsafe_unreachable_ub.stderr b/tests/ui/consts/const_unsafe_unreachable_ub.stderr index 593a51bfe8fea..6394563e2bb87 100644 --- a/tests/ui/consts/const_unsafe_unreachable_ub.stderr +++ b/tests/ui/consts/const_unsafe_unreachable_ub.stderr @@ -16,6 +16,6 @@ note: inside `BAR` LL | const BAR: bool = unsafe { foo(false) }; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/control-flow/assert.stderr b/tests/ui/consts/control-flow/assert.stderr index 8b1ca183de98b..2f863daf760da 100644 --- a/tests/ui/consts/control-flow/assert.stderr +++ b/tests/ui/consts/control-flow/assert.stderr @@ -6,6 +6,6 @@ LL | const _: () = assert!(false); | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/control-flow/issue-46843.stderr b/tests/ui/consts/control-flow/issue-46843.stderr index 66227f61e3563..69bf78839be77 100644 --- a/tests/ui/consts/control-flow/issue-46843.stderr +++ b/tests/ui/consts/control-flow/issue-46843.stderr @@ -6,6 +6,6 @@ LL | pub const Q: i32 = match non_const() { | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/issue-50577.stderr b/tests/ui/consts/control-flow/issue-50577.stderr index a931c89f47e72..1556c6f9c5588 100644 --- a/tests/ui/consts/control-flow/issue-50577.stderr +++ b/tests/ui/consts/control-flow/issue-50577.stderr @@ -8,6 +8,6 @@ LL | Drop = assert_eq!(1, 1), = help: consider adding an `else` block that evaluates to the expected type = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr index 5aeec8fbf8665..7351f5c0a6f96 100644 --- a/tests/ui/consts/control-flow/try.stderr +++ b/tests/ui/consts/control-flow/try.stderr @@ -7,6 +7,6 @@ LL | x?; = note: see issue #74935 for more information = help: add `#![feature(const_try)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr index fa20077da7efe..24572040b9104 100644 --- a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr +++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr @@ -17,6 +17,6 @@ help: consider restricting type parameter `T` LL | impl, const N: usize> Foo { | ++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/dangling-alloc-id-ice.stderr b/tests/ui/consts/dangling-alloc-id-ice.stderr index 0a1cca4ca4d47..e14204c09e54b 100644 --- a/tests/ui/consts/dangling-alloc-id-ice.stderr +++ b/tests/ui/consts/dangling-alloc-id-ice.stderr @@ -4,5 +4,5 @@ error: encountered dangling pointer in final constant LL | const FOO: &() = { | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/dangling_raw_ptr.stderr b/tests/ui/consts/dangling_raw_ptr.stderr index bdfe1e4effe3e..5a428355034aa 100644 --- a/tests/ui/consts/dangling_raw_ptr.stderr +++ b/tests/ui/consts/dangling_raw_ptr.stderr @@ -4,5 +4,5 @@ error: encountered dangling pointer in final constant LL | const FOO: *const u32 = { | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/drop_box.stderr b/tests/ui/consts/drop_box.stderr index 62324939b08af..3f4b6f3482627 100644 --- a/tests/ui/consts/drop_box.stderr +++ b/tests/ui/consts/drop_box.stderr @@ -6,6 +6,6 @@ LL | const fn f(_: Box) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/drop_zst.stderr b/tests/ui/consts/drop_zst.stderr index 37758a4cbda64..e3c6785290d76 100644 --- a/tests/ui/consts/drop_zst.stderr +++ b/tests/ui/consts/drop_zst.stderr @@ -4,6 +4,6 @@ error[E0493]: destructor of `S` cannot be evaluated at compile-time LL | let s = S; | ^ the destructor for this type cannot be evaluated in constant functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/effect_param.rs b/tests/ui/consts/effect_param.rs index f11ec739fce53..bfe0a519037db 100644 --- a/tests/ui/consts/effect_param.rs +++ b/tests/ui/consts/effect_param.rs @@ -3,9 +3,13 @@ fn main() { i8::checked_sub::(42, 43); //~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied + i8::checked_sub::(42, 43); + //~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied } const FOO: () = { i8::checked_sub::(42, 43); //~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied + i8::checked_sub::(42, 43); + //~^ ERROR: method takes 0 generic arguments but 1 generic argument was supplied }; diff --git a/tests/ui/consts/effect_param.stderr b/tests/ui/consts/effect_param.stderr index f8c4bfc02e541..dba5d49b7921e 100644 --- a/tests/ui/consts/effect_param.stderr +++ b/tests/ui/consts/effect_param.stderr @@ -1,11 +1,19 @@ error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/effect_param.rs:9:9 + --> $DIR/effect_param.rs:11:9 | LL | i8::checked_sub::(42, 43); | ^^^^^^^^^^^--------- help: remove these generics | | | expected 0 generic arguments +error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/effect_param.rs:13:9 + | +LL | i8::checked_sub::(42, 43); + | ^^^^^^^^^^^-------- help: remove these generics + | | + | expected 0 generic arguments + error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied --> $DIR/effect_param.rs:4:9 | @@ -14,6 +22,14 @@ LL | i8::checked_sub::(42, 43); | | | expected 0 generic arguments -error: aborting due to 2 previous errors +error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/effect_param.rs:6:9 + | +LL | i8::checked_sub::(42, 43); + | ^^^^^^^^^^^--------- help: remove these generics + | | + | expected 0 generic arguments + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/consts/escaping-bound-var.stderr b/tests/ui/consts/escaping-bound-var.stderr index d26ae2cee1c92..a943c84e3b2ae 100644 --- a/tests/ui/consts/escaping-bound-var.stderr +++ b/tests/ui/consts/escaping-bound-var.stderr @@ -16,5 +16,5 @@ LL | fn test<'a>( LL | let x: &'a (); | ^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/consts/gate-do-not-const-check.stderr b/tests/ui/consts/gate-do-not-const-check.stderr index 3bb1360166a19..27a2c23a6788e 100644 --- a/tests/ui/consts/gate-do-not-const-check.stderr +++ b/tests/ui/consts/gate-do-not-const-check.stderr @@ -6,6 +6,6 @@ LL | #[rustc_do_not_const_check] | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/inline_asm.stderr b/tests/ui/consts/inline_asm.stderr index 65a828d118c0c..0f71ab4b97f04 100644 --- a/tests/ui/consts/inline_asm.stderr +++ b/tests/ui/consts/inline_asm.stderr @@ -4,6 +4,6 @@ error[E0015]: inline assembly is not allowed in constants LL | const _: () = unsafe { asm!("nop") }; | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/intrinsic_without_const_stab.stderr b/tests/ui/consts/intrinsic_without_const_stab.stderr index b32b6398ece62..e3143080c5fcd 100644 --- a/tests/ui/consts/intrinsic_without_const_stab.stderr +++ b/tests/ui/consts/intrinsic_without_const_stab.stderr @@ -6,6 +6,6 @@ LL | unsafe { copy(src, dst, count) } | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/intrinsic_without_const_stab_fail.stderr b/tests/ui/consts/intrinsic_without_const_stab_fail.stderr index fcbb3724567fe..8ade68eb2a971 100644 --- a/tests/ui/consts/intrinsic_without_const_stab_fail.stderr +++ b/tests/ui/consts/intrinsic_without_const_stab_fail.stderr @@ -6,6 +6,6 @@ LL | unsafe { copy(src, dst, count) } | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/invalid-const-in-body.stderr b/tests/ui/consts/invalid-const-in-body.stderr index 3be6583594612..b8944abba266f 100644 --- a/tests/ui/consts/invalid-const-in-body.stderr +++ b/tests/ui/consts/invalid-const-in-body.stderr @@ -4,5 +4,5 @@ error: expected at least one digit in exponent LL | 2.0E | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr index 257ecd7f3cf7f..db7db4b613181 100644 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr @@ -8,6 +8,6 @@ LL | const { (|| {})() } => {} = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/invalid-union.32bit.stderr b/tests/ui/consts/invalid-union.32bit.stderr index 32b67a13061c5..177e4f03e837c 100644 --- a/tests/ui/consts/invalid-union.32bit.stderr +++ b/tests/ui/consts/invalid-union.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-union.rs:41:1 + --> $DIR/invalid-union.rs:35:1 | LL | fn main() { | ^^^^^^^^^ constructing invalid value at ..y..0: encountered `UnsafeCell` in a `const` @@ -10,19 +10,19 @@ LL | fn main() { } note: erroneous constant encountered - --> $DIR/invalid-union.rs:43:25 + --> $DIR/invalid-union.rs:37:25 | LL | let _: &'static _ = &C; | ^^ note: erroneous constant encountered - --> $DIR/invalid-union.rs:43:25 + --> $DIR/invalid-union.rs:37:25 | LL | let _: &'static _ = &C; | ^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr index 45f999eb23c2d..09c648c3cda36 100644 --- a/tests/ui/consts/invalid-union.64bit.stderr +++ b/tests/ui/consts/invalid-union.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-union.rs:41:1 + --> $DIR/invalid-union.rs:35:1 | LL | fn main() { | ^^^^^^^^^ constructing invalid value at ..y..0: encountered `UnsafeCell` in a `const` @@ -10,19 +10,19 @@ LL | fn main() { } note: erroneous constant encountered - --> $DIR/invalid-union.rs:43:25 + --> $DIR/invalid-union.rs:37:25 | LL | let _: &'static _ = &C; | ^^ note: erroneous constant encountered - --> $DIR/invalid-union.rs:43:25 + --> $DIR/invalid-union.rs:37:25 | LL | let _: &'static _ = &C; | ^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/invalid-union.rs b/tests/ui/consts/invalid-union.rs index 28706b4a923e7..4f67ec979029e 100644 --- a/tests/ui/consts/invalid-union.rs +++ b/tests/ui/consts/invalid-union.rs @@ -1,11 +1,6 @@ // Check that constants with interior mutability inside unions are rejected // during validation. // -// Note that this test case relies on undefined behaviour to construct a -// constant with interior mutability that is "invisible" to the static checks. -// If for some reason this approach no longer works, it is should be fine to -// remove the test case. -// // build-fail // stderr-per-bitwidth #![feature(const_mut_refs)] @@ -30,10 +25,9 @@ union U { } const C: S = { - let s = S { x: 0, y: E::A }; - // Go through an &u32 reference which is definitely not allowed to mutate anything. - let p = &s.x as *const u32 as *mut u32; - // Change enum tag to E::B. + let mut s = S { x: 0, y: E::A }; + let p = &mut s.x as *mut u32; + // Change enum tag to E::B. Now there's interior mutability here. unsafe { *p.add(1) = 1 }; s }; diff --git a/tests/ui/consts/issue-104609.stderr b/tests/ui/consts/issue-104609.stderr index 00360c44d610b..8d0526978ed9e 100644 --- a/tests/ui/consts/issue-104609.stderr +++ b/tests/ui/consts/issue-104609.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `oops` in this scope LL | oops; | ^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/consts/issue-104768.stderr b/tests/ui/consts/issue-104768.stderr index 55b2b6f04358f..8a4a41e4d68a8 100644 --- a/tests/ui/consts/issue-104768.stderr +++ b/tests/ui/consts/issue-104768.stderr @@ -7,6 +7,6 @@ LL | const A: &_ = 0_u32; | not allowed in type signatures | help: replace with the correct type: `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/consts/issue-17458.stderr b/tests/ui/consts/issue-17458.stderr index 8936c8d84ecff..766657d12a15a 100644 --- a/tests/ui/consts/issue-17458.stderr +++ b/tests/ui/consts/issue-17458.stderr @@ -7,5 +7,5 @@ LL | static X: usize = unsafe { core::ptr::null::() as usize }; = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-17718-constants-not-static.stderr b/tests/ui/consts/issue-17718-constants-not-static.stderr index 8f3acae71391f..42d2a9acdc7b8 100644 --- a/tests/ui/consts/issue-17718-constants-not-static.stderr +++ b/tests/ui/consts/issue-17718-constants-not-static.stderr @@ -7,6 +7,6 @@ LL | fn foo() -> &'static usize { &id(FOO) } | |temporary value created here | returns a reference to data owned by the current function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/consts/issue-18294.stderr b/tests/ui/consts/issue-18294.stderr index e0cbd2a216dbb..8df40cabaaa8b 100644 --- a/tests/ui/consts/issue-18294.stderr +++ b/tests/ui/consts/issue-18294.stderr @@ -7,5 +7,5 @@ LL | const Y: usize = unsafe { &X as *const u32 as usize }; = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-25826.stderr b/tests/ui/consts/issue-25826.stderr index 780edd2149fe1..7d21020da6477 100644 --- a/tests/ui/consts/issue-25826.stderr +++ b/tests/ui/consts/issue-25826.stderr @@ -6,5 +6,5 @@ LL | const A: bool = unsafe { id:: as *const () < id:: as *const () | = note: see issue #53020 for more information -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-28113.stderr b/tests/ui/consts/issue-28113.stderr index 1294cc99bf736..01bbe4bc9b96c 100644 --- a/tests/ui/consts/issue-28113.stderr +++ b/tests/ui/consts/issue-28113.stderr @@ -8,6 +8,6 @@ LL | || -> u8 { 5 }() = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-32829.stderr b/tests/ui/consts/issue-32829.stderr index cae5163f0df92..8eee87af8e1b1 100644 --- a/tests/ui/consts/issue-32829.stderr +++ b/tests/ui/consts/issue-32829.stderr @@ -6,6 +6,6 @@ LL | static S : u64 = { { panic!("foo"); 0 } }; | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-34784.rs b/tests/ui/consts/issue-34784.rs deleted file mode 100644 index 98d943470a7f9..0000000000000 --- a/tests/ui/consts/issue-34784.rs +++ /dev/null @@ -1,21 +0,0 @@ -// run-pass - -#![warn(pointer_structural_match)] -#![allow(dead_code)] -const C: *const u8 = &0; - -fn foo(x: *const u8) { - match x { - C => {} - _ => {} - } -} - -const D: *const [u8; 4] = b"abcd"; - -fn main() { - match D { - D => {} - _ => {} - } -} diff --git a/tests/ui/consts/issue-3521.stderr b/tests/ui/consts/issue-3521.stderr index aa42772f12d8a..70ce9b2d6a08a 100644 --- a/tests/ui/consts/issue-3521.stderr +++ b/tests/ui/consts/issue-3521.stderr @@ -7,6 +7,6 @@ LL | let foo: isize = 100; LL | Bar = foo | ^^^ non-constant value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 6fcfe3ed28ccc..4f2d92ba3cde0 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -27,6 +27,6 @@ LL | B = A, | ^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/issue-44415.stderr b/tests/ui/consts/issue-44415.stderr index 01d24a6208144..adb5747c42408 100644 --- a/tests/ui/consts/issue-44415.stderr +++ b/tests/ui/consts/issue-44415.stderr @@ -25,6 +25,6 @@ LL | struct Foo { | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/issue-52023-array-size-pointer-cast.stderr b/tests/ui/consts/issue-52023-array-size-pointer-cast.stderr index 9a3d5716e001b..1a47b82a7d3fa 100644 --- a/tests/ui/consts/issue-52023-array-size-pointer-cast.stderr +++ b/tests/ui/consts/issue-52023-array-size-pointer-cast.stderr @@ -7,5 +7,5 @@ LL | let _ = [0; (&0 as *const i32) as usize]; = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-52060.stderr b/tests/ui/consts/issue-52060.stderr index 95e5f2a8282cb..27d00ad044259 100644 --- a/tests/ui/consts/issue-52060.stderr +++ b/tests/ui/consts/issue-52060.stderr @@ -6,6 +6,6 @@ LL | static B: [u32; 1] = [0; A.len()]; | = help: consider extracting the value of the `static` to a `const`, and referring to that -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/consts/issue-63952.32bit.stderr b/tests/ui/consts/issue-63952.32bit.stderr index 5375ec1188a5b..f562f9104e3ed 100644 --- a/tests/ui/consts/issue-63952.32bit.stderr +++ b/tests/ui/consts/issue-63952.32bit.stderr @@ -6,9 +6,9 @@ LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC0╼ ff ff ff ff │ ╾──╼.... + ╾ALLOC0╼ ff ff ff ff │ ╾──╼.... } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-63952.64bit.stderr b/tests/ui/consts/issue-63952.64bit.stderr index a6edbf9321b92..fe66bec13a1b0 100644 --- a/tests/ui/consts/issue-63952.64bit.stderr +++ b/tests/ui/consts/issue-63952.64bit.stderr @@ -6,9 +6,9 @@ LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC0╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + ╾ALLOC0╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-64506.stderr b/tests/ui/consts/issue-64506.stderr index 2fe84245b3ef8..4cc2b71374100 100644 --- a/tests/ui/consts/issue-64506.stderr +++ b/tests/ui/consts/issue-64506.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | let x = unsafe { Foo { b: () }.a }; | ^^^^^^^^^^^^^^^ constructing invalid value at .inner: encountered a value of uninhabited type `AnonPipe` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-68542-closure-in-array-len.stderr b/tests/ui/consts/issue-68542-closure-in-array-len.stderr index d23513ed7ffb9..3c0408cbedf73 100644 --- a/tests/ui/consts/issue-68542-closure-in-array-len.stderr +++ b/tests/ui/consts/issue-68542-closure-in-array-len.stderr @@ -8,6 +8,6 @@ LL | a: [(); (|| { 0 })()] = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.stderr b/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.stderr index 1597120fb5caf..0393316f166ba 100644 --- a/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.stderr +++ b/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.stderr @@ -10,6 +10,6 @@ note: type in trait LL | const VALUE: usize; | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/consts/issue-73976-monomorphic.stderr b/tests/ui/consts/issue-73976-monomorphic.stderr index b23796db4f110..ef754b23ff06e 100644 --- a/tests/ui/consts/issue-73976-monomorphic.stderr +++ b/tests/ui/consts/issue-73976-monomorphic.stderr @@ -8,6 +8,6 @@ note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/any.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-76064.stderr b/tests/ui/consts/issue-76064.stderr index 67b2e90db7508..fabebdb1a7749 100644 --- a/tests/ui/consts/issue-76064.stderr +++ b/tests/ui/consts/issue-76064.stderr @@ -6,6 +6,6 @@ LL | struct Bug([u8; panic!("panic")]); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr index efe4fd22e547c..18bdde45e2c9d 100644 --- a/tests/ui/consts/issue-79137-toogeneric.stderr +++ b/tests/ui/consts/issue-79137-toogeneric.stderr @@ -4,5 +4,5 @@ error: constant pattern depends on a generic parameter LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-79690.64bit.stderr b/tests/ui/consts/issue-79690.64bit.stderr index af59729d438d7..d603a1dc29127 100644 --- a/tests/ui/consts/issue-79690.64bit.stderr +++ b/tests/ui/consts/issue-79690.64bit.stderr @@ -6,9 +6,9 @@ LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ } -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-87046.stderr b/tests/ui/consts/issue-87046.stderr index d0dbb21cee012..0f965e1ac3f1b 100644 --- a/tests/ui/consts/issue-87046.stderr +++ b/tests/ui/consts/issue-87046.stderr @@ -4,5 +4,5 @@ error: cannot use unsized non-slice type `Username` in constant patterns LL | ROOT_USER => true, | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-90878-3.stderr b/tests/ui/consts/issue-90878-3.stderr index 1bcc0eb37877b..46b380d0f74f3 100644 --- a/tests/ui/consts/issue-90878-3.stderr +++ b/tests/ui/consts/issue-90878-3.stderr @@ -6,6 +6,6 @@ LL | |x: usize| [0; x]; | | | this would need to be a `const` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/issue-90878.stderr b/tests/ui/consts/issue-90878.stderr index c038fc622d468..9b7cd97be2241 100644 --- a/tests/ui/consts/issue-90878.stderr +++ b/tests/ui/consts/issue-90878.stderr @@ -6,6 +6,6 @@ LL | |x: usize| [0; x]; | | | this would need to be a `const` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/issue-miri-1910.stderr b/tests/ui/consts/issue-miri-1910.stderr index af0f77c6767b4..32beed5dba095 100644 --- a/tests/ui/consts/issue-miri-1910.stderr +++ b/tests/ui/consts/issue-miri-1910.stderr @@ -5,7 +5,7 @@ error[E0080]: evaluation of constant value failed | note: inside `std::ptr::read::` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `ptr::const_ptr::::read` +note: inside `std::ptr::const_ptr::::read` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `C` --> $DIR/issue-miri-1910.rs:7:5 @@ -15,6 +15,6 @@ LL | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/match_ice.stderr b/tests/ui/consts/match_ice.stderr index 342d94ed31c87..fb5cbe0ed8980 100644 --- a/tests/ui/consts/match_ice.stderr +++ b/tests/ui/consts/match_ice.stderr @@ -7,5 +7,5 @@ LL | C => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr index 3845068d8411c..bfaccf1db1ca4 100644 --- a/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr +++ b/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr @@ -6,5 +6,5 @@ LL | unsafe { x == y } | = note: see issue #53020 for more information -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/mir_check_nonconst.stderr b/tests/ui/consts/mir_check_nonconst.stderr index 1e0652722ff2d..ea6a8b8ee4a59 100644 --- a/tests/ui/consts/mir_check_nonconst.stderr +++ b/tests/ui/consts/mir_check_nonconst.stderr @@ -7,6 +7,6 @@ LL | static foo: Foo = bar(); = note: calls in statics are limited to constant functions, tuple structs and tuple variants = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.stderr b/tests/ui/consts/miri_unleashed/abi-mismatch.stderr index cf3fd88d0342e..51364b01a2d38 100644 --- a/tests/ui/consts/miri_unleashed/abi-mismatch.stderr +++ b/tests/ui/consts/miri_unleashed/abi-mismatch.stderr @@ -23,6 +23,6 @@ help: skipping check that does not even have a feature gate LL | my_fn(); | ^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/assoc_const.stderr b/tests/ui/consts/miri_unleashed/assoc_const.stderr index b129aef3452e4..3303a78426534 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const.stderr +++ b/tests/ui/consts/miri_unleashed/assoc_const.stderr @@ -35,6 +35,6 @@ help: skipping check that does not even have a feature gate LL | const F: u32 = (U::X, 42).1; | ^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr index 46408f6748d98..e923d95b7550c 100644 --- a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr +++ b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr @@ -18,6 +18,6 @@ LL | let y = >::F; | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/box.stderr b/tests/ui/consts/miri_unleashed/box.stderr index 407f5d8cb113d..5229f1e50cd44 100644 --- a/tests/ui/consts/miri_unleashed/box.stderr +++ b/tests/ui/consts/miri_unleashed/box.stderr @@ -22,6 +22,6 @@ help: skipping check that does not even have a feature gate LL | &mut *(Box::new(0)) | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr index 4a3344a5b0455..ab33b0c00c907 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr @@ -24,7 +24,7 @@ LL | const REF_INTERIOR_MUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -35,7 +35,7 @@ LL | const READ_IMMUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC1╼ │ ╾──╼ + ╾ALLOC1╼ │ ╾──╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr index 7573bfa39ec20..f1f58d9ca6d6f 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr @@ -24,7 +24,7 @@ LL | const REF_INTERIOR_MUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -35,7 +35,7 @@ LL | const READ_IMMUT: &usize = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC1╼ │ ╾──────╼ + ╾ALLOC1╼ │ ╾──────╼ } warning: skipping const checks diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index 492d8718a1378..7960648ce3a19 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_MUT: &[u8; 1] = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error: could not evaluate constant pattern @@ -23,7 +23,7 @@ LL | const U8_MUT: &u8 = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + ╾ALLOC0╼ │ ╾──╼ } error: could not evaluate constant pattern diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index f6d82d6c0ba34..6ae0b2d1bfef7 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -6,7 +6,7 @@ LL | const SLICE_MUT: &[u8; 1] = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error: could not evaluate constant pattern @@ -23,7 +23,7 @@ LL | const U8_MUT: &u8 = { | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ + ╾ALLOC0╼ │ ╾──────╼ } error: could not evaluate constant pattern diff --git a/tests/ui/consts/miri_unleashed/drop.stderr b/tests/ui/consts/miri_unleashed/drop.stderr index 4f60b8820691b..5c415b5bac18a 100644 --- a/tests/ui/consts/miri_unleashed/drop.stderr +++ b/tests/ui/consts/miri_unleashed/drop.stderr @@ -19,6 +19,6 @@ help: skipping check that does not even have a feature gate LL | let _v: Vec = Vec::new(); | ^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr index 45ed88b1bb078..833e2745838ff 100644 --- a/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr +++ b/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr @@ -6,6 +6,6 @@ LL | const F: u32 = (U::X, 42).1; | | | the destructor for this type cannot be evaluated in constants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/miri_unleashed/inline_asm.stderr b/tests/ui/consts/miri_unleashed/inline_asm.stderr index 6317cd882678a..e9643f02840c0 100644 --- a/tests/ui/consts/miri_unleashed/inline_asm.stderr +++ b/tests/ui/consts/miri_unleashed/inline_asm.stderr @@ -12,6 +12,6 @@ help: skipping check that does not even have a feature gate LL | unsafe { asm!("nop"); } | ^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr index 3ed96701ab0ad..39298842a33e7 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -32,6 +32,6 @@ help: skipping check that does not even have a feature gate LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/consts/miri_unleashed/mutating_global.stderr b/tests/ui/consts/miri_unleashed/mutating_global.stderr index c8770c8d76ad0..c38e2d44d899e 100644 --- a/tests/ui/consts/miri_unleashed/mutating_global.stderr +++ b/tests/ui/consts/miri_unleashed/mutating_global.stderr @@ -4,6 +4,6 @@ error[E0080]: could not evaluate static initializer LL | GLOBAL = 99 | ^^^^^^^^^^^ modifying a static's initial value from another static's initializer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/non_const_fn.stderr b/tests/ui/consts/miri_unleashed/non_const_fn.stderr index 57836f7966df2..cc893896ecf56 100644 --- a/tests/ui/consts/miri_unleashed/non_const_fn.stderr +++ b/tests/ui/consts/miri_unleashed/non_const_fn.stderr @@ -12,6 +12,6 @@ help: skipping check that does not even have a feature gate LL | static C: () = foo(); | ^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr b/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr index 5acdcdd95e8e3..f4abaecac5e15 100644 --- a/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr +++ b/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr @@ -14,5 +14,5 @@ help: skipping check that does not even have a feature gate LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/consts/missing-larger-array-impl.stderr b/tests/ui/consts/missing-larger-array-impl.stderr index fe9d0f6e6ed24..acf38d00ec64a 100644 --- a/tests/ui/consts/missing-larger-array-impl.stderr +++ b/tests/ui/consts/missing-larger-array-impl.stderr @@ -15,6 +15,6 @@ LL | <[X; 35] as Default>::default(); [T; 7] and 27 others -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index 6860cee4184fc..3e3e8e976be80 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -7,7 +7,7 @@ note: inside `std::ptr::read::>>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `mem::swap_simple::>>` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL -note: inside `ptr::swap_nonoverlapping_simple_untyped::>` +note: inside `std::ptr::swap_nonoverlapping_simple_untyped::>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `swap_nonoverlapping::>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL @@ -23,6 +23,6 @@ note: inside `X` = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/nested_erroneous_ctfe.stderr b/tests/ui/consts/nested_erroneous_ctfe.stderr index b6a1725076bc6..db298246e7cf1 100644 --- a/tests/ui/consts/nested_erroneous_ctfe.stderr +++ b/tests/ui/consts/nested_erroneous_ctfe.stderr @@ -7,6 +7,6 @@ LL | [9; || [9; []]]; = note: expected type `usize` found array `[_; 0]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr index 1ef727e5b0f3a..4fbb2f00100a6 100644 --- a/tests/ui/consts/offset_from_ub.stderr +++ b/tests/ui/consts/offset_from_ub.stderr @@ -9,7 +9,7 @@ error[E0080]: evaluation of constant value failed | = note: `ptr_offset_from` called on pointers into different allocations | -note: inside `ptr::const_ptr::::offset_from` +note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `NOT_PTR` --> $DIR/offset_from_ub.rs:24:14 @@ -88,7 +88,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance) | -note: inside `ptr::const_ptr::::offset_from` +note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OFFSET_VERY_FAR1` --> $DIR/offset_from_ub.rs:115:14 @@ -101,7 +101,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance) | -note: inside `ptr::const_ptr::::offset_from` +note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OFFSET_VERY_FAR2` --> $DIR/offset_from_ub.rs:121:14 diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr index 8bc59d50ee4b3..b398b20393fc4 100644 --- a/tests/ui/consts/offset_ub.stderr +++ b/tests/ui/consts/offset_ub.stderr @@ -3,7 +3,7 @@ error[E0080]: evaluation of constant value failed | = note: overflowing in-bounds pointer arithmetic | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `BEFORE_START` --> $DIR/offset_ub.rs:7:46 @@ -16,7 +16,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds pointer arithmetic: ALLOC0 has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `AFTER_END` --> $DIR/offset_ub.rs:8:43 @@ -29,7 +29,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds pointer arithmetic: ALLOC1 has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `AFTER_ARRAY` --> $DIR/offset_ub.rs:9:45 @@ -42,7 +42,7 @@ error[E0080]: evaluation of constant value failed | = note: overflowing in-bounds pointer arithmetic | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OVERFLOW` --> $DIR/offset_ub.rs:11:43 @@ -55,7 +55,7 @@ error[E0080]: evaluation of constant value failed | = note: overflowing in-bounds pointer arithmetic | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `UNDERFLOW` --> $DIR/offset_ub.rs:12:44 @@ -68,7 +68,7 @@ error[E0080]: evaluation of constant value failed | = note: overflowing in-bounds pointer arithmetic | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OVERFLOW_ADDRESS_SPACE` --> $DIR/offset_ub.rs:13:56 @@ -81,7 +81,7 @@ error[E0080]: evaluation of constant value failed | = note: overflowing in-bounds pointer arithmetic | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `UNDERFLOW_ADDRESS_SPACE` --> $DIR/offset_ub.rs:14:57 @@ -94,7 +94,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds pointer arithmetic: ALLOC2 has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `NEGATIVE_OFFSET` --> $DIR/offset_ub.rs:15:49 @@ -107,7 +107,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds pointer arithmetic: ALLOC3 has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `ZERO_SIZED_ALLOC` --> $DIR/offset_ub.rs:17:50 @@ -120,7 +120,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance) | -note: inside `ptr::mut_ptr::::offset` +note: inside `std::ptr::mut_ptr::::offset` --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL note: inside `DANGLING` --> $DIR/offset_ub.rs:18:42 @@ -133,7 +133,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance) | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `NULL_OFFSET_ZERO` --> $DIR/offset_ub.rs:21:50 @@ -146,7 +146,7 @@ error[E0080]: evaluation of constant value failed | = note: out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance) | -note: inside `ptr::const_ptr::::offset` +note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `UNDERFLOW_ABS` --> $DIR/offset_ub.rs:24:47 diff --git a/tests/ui/consts/partial_qualif.stderr b/tests/ui/consts/partial_qualif.stderr index 32c25be21735b..05e0eeee13329 100644 --- a/tests/ui/consts/partial_qualif.stderr +++ b/tests/ui/consts/partial_qualif.stderr @@ -4,6 +4,6 @@ error[E0492]: constants cannot refer to interior mutable data LL | &{a} | ^^^^ this borrow of an interior mutable value may end up in the final value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/precise-drop-with-promoted.rs b/tests/ui/consts/precise-drop-with-promoted.rs index 0c0514dd9d531..7cbe3c4e41562 100644 --- a/tests/ui/consts/precise-drop-with-promoted.rs +++ b/tests/ui/consts/precise-drop-with-promoted.rs @@ -1,11 +1,6 @@ // Regression test for issue #89938. +// check-pass // compile-flags: --crate-type=lib -// known-bug: #103507 -// failure-status: 101 -// normalize-stderr-test "note: .*\n\n" -> "" -// normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> "" -// normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -// rustc-env:RUST_BACKTRACE=0 #![feature(const_precise_live_drops)] diff --git a/tests/ui/consts/precise-drop-with-promoted.stderr b/tests/ui/consts/precise-drop-with-promoted.stderr deleted file mode 100644 index a56672048eb7a..0000000000000 --- a/tests/ui/consts/precise-drop-with-promoted.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [mir_drops_elaborated_and_const_checked] elaborating drops for `f` -#1 [analysis] running analysis passes on this crate -end of query stack diff --git a/tests/ui/consts/qualif_overwrite.stderr b/tests/ui/consts/qualif_overwrite.stderr index 86a669c433df6..976cf7bd79ebb 100644 --- a/tests/ui/consts/qualif_overwrite.stderr +++ b/tests/ui/consts/qualif_overwrite.stderr @@ -4,6 +4,6 @@ error[E0492]: constants cannot refer to interior mutable data LL | &{a} | ^^^^ this borrow of an interior mutable value may end up in the final value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/qualif_overwrite_2.stderr b/tests/ui/consts/qualif_overwrite_2.stderr index 9eb123d0b01b1..a107c4a5c6dbf 100644 --- a/tests/ui/consts/qualif_overwrite_2.stderr +++ b/tests/ui/consts/qualif_overwrite_2.stderr @@ -4,6 +4,6 @@ error[E0492]: constants cannot refer to interior mutable data LL | &{a.0} | ^^^^^^ this borrow of an interior mutable value may end up in the final value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/raw-ptr-const.rs b/tests/ui/consts/raw-ptr-const.rs index fc774be54dff3..541c5fd1ab134 100644 --- a/tests/ui/consts/raw-ptr-const.rs +++ b/tests/ui/consts/raw-ptr-const.rs @@ -1,4 +1,4 @@ -// This is a regression test for a `delay_span_bug` during interning when a constant +// This is a regression test for a `span_delayed_bug` during interning when a constant // evaluates to a (non-dangling) raw pointer. For now this errors; potentially it // could also be allowed. diff --git a/tests/ui/consts/raw-ptr-const.stderr b/tests/ui/consts/raw-ptr-const.stderr index 82f782fab7f54..9aef78505c087 100644 --- a/tests/ui/consts/raw-ptr-const.stderr +++ b/tests/ui/consts/raw-ptr-const.stderr @@ -6,5 +6,5 @@ LL | const CONST_RAW: *const Vec = &Vec::new() as *const _; | = note: memory only reachable via raw pointers is not supported -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/recursive-zst-static.default.stderr b/tests/ui/consts/recursive-zst-static.default.stderr index d592b5aeef5e5..3bbb685a67819 100644 --- a/tests/ui/consts/recursive-zst-static.default.stderr +++ b/tests/ui/consts/recursive-zst-static.default.stderr @@ -21,6 +21,6 @@ LL | | } | |_^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/recursive-zst-static.unleash.stderr b/tests/ui/consts/recursive-zst-static.unleash.stderr index d592b5aeef5e5..3bbb685a67819 100644 --- a/tests/ui/consts/recursive-zst-static.unleash.stderr +++ b/tests/ui/consts/recursive-zst-static.unleash.stderr @@ -21,6 +21,6 @@ LL | | } | |_^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/recursive.stderr b/tests/ui/consts/recursive.stderr index 60ce64d2a1e0f..0046005c74f09 100644 --- a/tests/ui/consts/recursive.stderr +++ b/tests/ui/consts/recursive.stderr @@ -31,6 +31,6 @@ note: inside `X` LL | const X: () = f(1); | ^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/stable-precise-live-drops-in-libcore.stderr b/tests/ui/consts/stable-precise-live-drops-in-libcore.stderr index 5f70391eec248..323c49b1d1ba0 100644 --- a/tests/ui/consts/stable-precise-live-drops-in-libcore.stderr +++ b/tests/ui/consts/stable-precise-live-drops-in-libcore.stderr @@ -7,6 +7,6 @@ LL | pub const fn unwrap(self) -> T { LL | } | - value is dropped here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr index 8db75dd63cf2a..3d0de233569c9 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr +++ b/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr @@ -4,6 +4,6 @@ error[E0080]: could not evaluate static initializer LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr index 5cdcea2323109..3d5b012d42f37 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr +++ b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr @@ -7,6 +7,6 @@ LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 4 = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/static_mut_containing_mut_ref3.stderr b/tests/ui/consts/static_mut_containing_mut_ref3.stderr index 91f9dbd8d0b9e..be84608acf785 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref3.stderr +++ b/tests/ui/consts/static_mut_containing_mut_ref3.stderr @@ -4,6 +4,6 @@ error[E0080]: could not evaluate static initializer LL | static mut BAR: () = unsafe { FOO.0 = 99; }; | ^^^^^^^^^^ modifying a static's initial value from another static's initializer -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/std/alloc.32bit.stderr b/tests/ui/consts/std/alloc.32bit.stderr deleted file mode 100644 index da805de451c47..0000000000000 --- a/tests/ui/consts/std/alloc.32bit.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:11:1 - | -LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000000, but expected a valid enum tag - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:15:1 - | -LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000003, but expected a valid enum tag - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/std/alloc.64bit.stderr b/tests/ui/consts/std/alloc.64bit.stderr deleted file mode 100644 index 094503e103992..0000000000000 --- a/tests/ui/consts/std/alloc.64bit.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:11:1 - | -LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000000, but expected a valid enum tag - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:15:1 - | -LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000003, but expected a valid enum tag - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - HEX_DUMP - } - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/std/alloc.rs b/tests/ui/consts/std/alloc.rs deleted file mode 100644 index 0a2c2f4dec80f..0000000000000 --- a/tests/ui/consts/std/alloc.rs +++ /dev/null @@ -1,18 +0,0 @@ -// stderr-per-bitwidth -// Strip out raw byte dumps to make comparison platform-independent: -// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" -use std::alloc::Layout; - -// ok -const LAYOUT_VALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x08) }; - -// not ok, since alignment needs to be non-zero. -const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; -//~^ ERROR it is undefined behavior to use this value - -// not ok, since alignment needs to be a power of two. -const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; -//~^ ERROR it is undefined behavior to use this value - -fn main() {} diff --git a/tests/ui/consts/timeout.stderr b/tests/ui/consts/timeout.stderr index 799b5ec8dd9f1..6bfa06d86d11e 100644 --- a/tests/ui/consts/timeout.stderr +++ b/tests/ui/consts/timeout.stderr @@ -11,5 +11,5 @@ LL | static ROOK_ATTACKS_TABLE: () = { = note: `#[deny(long_running_const_eval)]` on by default = note: this error originates in the macro `uint_impl` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr index 4e8470173a101..6bc7e7203aa74 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -7,6 +7,6 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; = note: source type: `usize` (word size) = note: target type: `&[u8]` (2 * word size) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr index f6a651c5e663c..bb8f606edf8e8 100644 --- a/tests/ui/consts/try-operator.stderr +++ b/tests/ui/consts/try-operator.stderr @@ -4,6 +4,6 @@ error[E0635]: unknown feature `const_convert` LL | #![feature(const_convert)] | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0635`. diff --git a/tests/ui/consts/uninhabited-const-issue-61744.stderr b/tests/ui/consts/uninhabited-const-issue-61744.stderr index c92824a0d1a17..c6dd11ee5db92 100644 --- a/tests/ui/consts/uninhabited-const-issue-61744.stderr +++ b/tests/ui/consts/uninhabited-const-issue-61744.stderr @@ -659,6 +659,6 @@ LL | dbg!(i32::CONSTANT); | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index b75f99a720f6e..4b649bf43ed3d 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -4,5 +4,5 @@ error: ~const can only be applied to `#[const_trait]` traits LL | const fn unwrap_or_else T>(self, f: F) -> T { | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/copy-a-resource.stderr b/tests/ui/copy-a-resource.stderr index 128087f1e3755..ff1e28bf9611d 100644 --- a/tests/ui/copy-a-resource.stderr +++ b/tests/ui/copy-a-resource.stderr @@ -11,6 +11,6 @@ LL | let _y = x.clone(); = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `Clone` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/coroutine/async-coroutine-issue-67158.stderr b/tests/ui/coroutine/async-coroutine-issue-67158.stderr index d583d3d5ea0a6..1c4a6b0c35530 100644 --- a/tests/ui/coroutine/async-coroutine-issue-67158.stderr +++ b/tests/ui/coroutine/async-coroutine-issue-67158.stderr @@ -4,6 +4,6 @@ error[E0727]: `async` coroutines are not yet supported LL | async { yield print!(":C") }; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0727`. diff --git a/tests/ui/coroutine/async_gen_fn.rs b/tests/ui/coroutine/async_gen_fn.rs new file mode 100644 index 0000000000000..f8860e07f6cc8 --- /dev/null +++ b/tests/ui/coroutine/async_gen_fn.rs @@ -0,0 +1,11 @@ +// edition: 2024 +// compile-flags: -Zunstable-options +#![feature(gen_blocks)] + +// async generators are not yet supported, so this test makes sure they make some kind of reasonable +// error. + +async gen fn foo() {} +//~^ `async gen` functions are not supported + +fn main() {} diff --git a/tests/ui/coroutine/async_gen_fn.stderr b/tests/ui/coroutine/async_gen_fn.stderr new file mode 100644 index 0000000000000..6857ebe6c7901 --- /dev/null +++ b/tests/ui/coroutine/async_gen_fn.stderr @@ -0,0 +1,8 @@ +error: `async gen` functions are not supported + --> $DIR/async_gen_fn.rs:8:1 + | +LL | async gen fn foo() {} + | ^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/coroutine/auxiliary/unwind-aux.rs b/tests/ui/coroutine/auxiliary/unwind-aux.rs new file mode 100644 index 0000000000000..215d676911633 --- /dev/null +++ b/tests/ui/coroutine/auxiliary/unwind-aux.rs @@ -0,0 +1,11 @@ +// compile-flags: -Cpanic=unwind --crate-type=lib +// no-prefer-dynamic +// edition:2021 + +#![feature(coroutines)] +pub fn run(a: T) { + let _ = move || { + drop(a); + yield; + }; +} diff --git a/tests/ui/coroutine/clone-rpit.rs b/tests/ui/coroutine/clone-rpit.rs new file mode 100644 index 0000000000000..e0061e1c6bb33 --- /dev/null +++ b/tests/ui/coroutine/clone-rpit.rs @@ -0,0 +1,17 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(coroutines, coroutine_trait, coroutine_clone)] + +// This stalls the goal `{coroutine} <: impl Clone`, since that has a nested goal +// of `{coroutine}: Clone`. That is only known if we can compute the generator +// witness types, which we don't know until after borrowck. When we later check +// the goal for correctness, we want to be able to bind the `impl Clone` opaque. +pub fn foo<'a, 'b>() -> impl Clone { + move |_: ()| { + let () = yield (); + } +} + +fn main() {} diff --git a/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr b/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr index 8a96d187f6b1c..cfee8fc44fe09 100644 --- a/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr +++ b/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr @@ -7,6 +7,6 @@ LL | fn dangle(x: &mut i32) -> &'static mut i32 { LL | GeneratorState::Complete(c) => return c, | ^ lifetime `'static` required -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/coroutine/coroutine-region-requirements.stderr b/tests/ui/coroutine/coroutine-region-requirements.stderr index ad3183e7612b3..d31b4eb2b3c8a 100644 --- a/tests/ui/coroutine/coroutine-region-requirements.stderr +++ b/tests/ui/coroutine/coroutine-region-requirements.stderr @@ -7,5 +7,5 @@ LL | fn dangle(x: &mut i32) -> &'static mut i32 { LL | CoroutineState::Complete(c) => return c, | ^ returning this value requires that `'1` must outlive `'static` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/coroutine-with-nll.stderr b/tests/ui/coroutine/coroutine-with-nll.stderr index ed58debe2b4cb..77e8bb1f92ee9 100644 --- a/tests/ui/coroutine/coroutine-with-nll.stderr +++ b/tests/ui/coroutine/coroutine-with-nll.stderr @@ -7,6 +7,6 @@ LL | LL | yield (); | -------- possible yield occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/coroutine/drop-yield-twice.stderr b/tests/ui/coroutine/drop-yield-twice.stderr index fbbedac5775a4..b37c27015fb2e 100644 --- a/tests/ui/coroutine/drop-yield-twice.stderr +++ b/tests/ui/coroutine/drop-yield-twice.stderr @@ -18,5 +18,5 @@ note: required by a bound in `assert_send` LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/dropck-resume.stderr b/tests/ui/coroutine/dropck-resume.stderr index 028523978f9b8..aa6e423c7604c 100644 --- a/tests/ui/coroutine/dropck-resume.stderr +++ b/tests/ui/coroutine/dropck-resume.stderr @@ -10,6 +10,6 @@ LL | LL | } | - mutable borrow might be used here, when `g` is dropped and runs the destructor for coroutine -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/coroutine/gen_block_is_no_future.stderr b/tests/ui/coroutine/gen_block_is_no_future.stderr index db0c3c19b5811..f9e23e45b4435 100644 --- a/tests/ui/coroutine/gen_block_is_no_future.stderr +++ b/tests/ui/coroutine/gen_block_is_no_future.stderr @@ -7,6 +7,6 @@ LL | fn foo() -> impl std::future::Future { = help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` = note: {gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21} must be a future or must implement `IntoFuture` to be awaited -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/gen_block_move.stderr b/tests/ui/coroutine/gen_block_move.stderr index b93ac65f5e7d2..b93f6a9a61045 100644 --- a/tests/ui/coroutine/gen_block_move.stderr +++ b/tests/ui/coroutine/gen_block_move.stderr @@ -25,6 +25,6 @@ help: to force the gen block to take ownership of `x` (and any other referenced LL | gen move { | ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/coroutine/gen_fn.e2024.stderr b/tests/ui/coroutine/gen_fn.e2024.stderr index 388e10fd65e44..9ad890af3e1e7 100644 --- a/tests/ui/coroutine/gen_fn.e2024.stderr +++ b/tests/ui/coroutine/gen_fn.e2024.stderr @@ -1,10 +1,12 @@ -error: `gen` functions are not yet implemented +error[E0658]: gen blocks are experimental --> $DIR/gen_fn.rs:4:1 | LL | gen fn foo() {} | ^^^ | - = help: for now you can use `gen {}` blocks and return `impl Iterator` instead + = note: see issue #117078 for more information + = help: add `#![feature(gen_blocks)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/coroutine/gen_fn.none.stderr b/tests/ui/coroutine/gen_fn.none.stderr index 5e7bd9d8bbfbf..c5342ee22e62f 100644 --- a/tests/ui/coroutine/gen_fn.none.stderr +++ b/tests/ui/coroutine/gen_fn.none.stderr @@ -4,5 +4,5 @@ error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, LL | gen fn foo() {} | ^^^ expected one of 9 possible tokens -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/gen_fn.rs b/tests/ui/coroutine/gen_fn.rs index da515f263b00a..e06629c5dfe54 100644 --- a/tests/ui/coroutine/gen_fn.rs +++ b/tests/ui/coroutine/gen_fn.rs @@ -3,6 +3,6 @@ gen fn foo() {} //[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen` -//[e2024]~^^ ERROR: `gen` functions are not yet implemented +//[e2024]~^^ ERROR: gen blocks are experimental fn main() {} diff --git a/tests/ui/coroutine/gen_fn_iter.rs b/tests/ui/coroutine/gen_fn_iter.rs new file mode 100644 index 0000000000000..da01bc96ef453 --- /dev/null +++ b/tests/ui/coroutine/gen_fn_iter.rs @@ -0,0 +1,20 @@ +// edition: 2024 +// compile-flags: -Zunstable-options +// run-pass +#![feature(gen_blocks)] + +// make sure that a ridiculously simple gen fn works as an iterator. + +gen fn foo() -> i32 { + yield 1; + yield 2; + yield 3; +} + +fn main() { + let mut iter = foo(); + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next(), Some(2)); + assert_eq!(iter.next(), Some(3)); + assert_eq!(iter.next(), None); +} diff --git a/tests/ui/coroutine/gen_fn_lifetime_capture.rs b/tests/ui/coroutine/gen_fn_lifetime_capture.rs new file mode 100644 index 0000000000000..b6a4d71e6cce1 --- /dev/null +++ b/tests/ui/coroutine/gen_fn_lifetime_capture.rs @@ -0,0 +1,19 @@ +// edition: 2024 +// compile-flags: -Zunstable-options +// check-pass +#![feature(gen_blocks)] + +// make sure gen fn captures lifetimes in its signature + +gen fn foo<'a, 'b>(x: &'a i32, y: &'b i32, z: &'b i32) -> &'b i32 { + yield y; + yield z; +} + +fn main() { + let z = 3; + let mut iter = foo(&1, &2, &z); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.next(), None); +} diff --git a/tests/ui/coroutine/issue-102645.stderr b/tests/ui/coroutine/issue-102645.stderr index 3db090346cde1..7a3b7f2b04c34 100644 --- a/tests/ui/coroutine/issue-102645.stderr +++ b/tests/ui/coroutine/issue-102645.stderr @@ -11,6 +11,6 @@ help: provide the argument LL | Pin::new(&mut b).resume(()); | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.mir.stderr b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.mir.stderr index a9a0d6296065b..11dc57bcf4673 100644 --- a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.mir.stderr +++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.mir.stderr @@ -6,6 +6,6 @@ LL | *(1 as *mut u32) = 42; | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.thir.stderr b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.thir.stderr index 22c83e9a3d5a3..a61689a0df51e 100644 --- a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.thir.stderr +++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.thir.stderr @@ -6,6 +6,6 @@ LL | *(1 as *mut u32) = 42; | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/coroutine/issue-48048.stderr b/tests/ui/coroutine/issue-48048.stderr index bb9f189fa7c62..199ecf4ca6aaf 100644 --- a/tests/ui/coroutine/issue-48048.stderr +++ b/tests/ui/coroutine/issue-48048.stderr @@ -6,6 +6,6 @@ LL | x.0({ LL | yield; | ----- possible yield occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/coroutine/issue-57084.rs b/tests/ui/coroutine/issue-57084.rs index 95bed5b151ea3..e0aeae6673503 100644 --- a/tests/ui/coroutine/issue-57084.rs +++ b/tests/ui/coroutine/issue-57084.rs @@ -1,5 +1,5 @@ // This issue reproduces an ICE on compile (E.g. fails on 2018-12-19 nightly). -// "cannot relate bound region: ReLateBound(DebruijnIndex(1), BrAnon(1)) <= '?1" +// "cannot relate bound region: ReBound(DebruijnIndex(1), BrAnon(1)) <= '?1" // run-pass // edition:2018 #![feature(coroutines,coroutine_trait)] diff --git a/tests/ui/coroutine/issue-58888.rs b/tests/ui/coroutine/issue-58888.rs index af8e60ce460cd..9c699c7bb8292 100644 --- a/tests/ui/coroutine/issue-58888.rs +++ b/tests/ui/coroutine/issue-58888.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet #![feature(coroutines, coroutine_trait)] diff --git a/tests/ui/coroutine/issue-64620-yield-array-element.stderr b/tests/ui/coroutine/issue-64620-yield-array-element.stderr index 47632d083ea32..347532fb7193e 100644 --- a/tests/ui/coroutine/issue-64620-yield-array-element.stderr +++ b/tests/ui/coroutine/issue-64620-yield-array-element.stderr @@ -4,6 +4,6 @@ error[E0627]: yield expression outside of coroutine literal LL | yield arr[0]; | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/issue-88653.stderr b/tests/ui/coroutine/issue-88653.stderr index 3ae50b5aff284..8a23ad17b8b37 100644 --- a/tests/ui/coroutine/issue-88653.stderr +++ b/tests/ui/coroutine/issue-88653.stderr @@ -10,6 +10,6 @@ LL | |bar| { = note: expected coroutine signature `fn((bool,)) -> _` found coroutine signature `fn(bool) -> _` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/coroutine/issue-91477.stderr b/tests/ui/coroutine/issue-91477.stderr index 0ab3c1fbabc5f..ca8e43d8a26db 100644 --- a/tests/ui/coroutine/issue-91477.stderr +++ b/tests/ui/coroutine/issue-91477.stderr @@ -4,6 +4,6 @@ error[E0627]: yield expression outside of coroutine literal LL | yield 1; | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/layout-error.stderr b/tests/ui/coroutine/layout-error.stderr index b1a258f4f2ca7..249a99e9b85c6 100644 --- a/tests/ui/coroutine/layout-error.stderr +++ b/tests/ui/coroutine/layout-error.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `Foo` in this scope LL | let a = Foo; | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/coroutine/metadata-sufficient-for-layout.stderr b/tests/ui/coroutine/metadata-sufficient-for-layout.stderr index 3488b04f2267e..c7860fde2a9f7 100644 --- a/tests/ui/coroutine/metadata-sufficient-for-layout.stderr +++ b/tests/ui/coroutine/metadata-sufficient-for-layout.stderr @@ -4,5 +4,5 @@ error: fatal error triggered by #[rustc_error] LL | fn main() {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/pattern-borrow.stderr b/tests/ui/coroutine/pattern-borrow.stderr index ddb3bf66214f8..9e7b330d79de0 100644 --- a/tests/ui/coroutine/pattern-borrow.stderr +++ b/tests/ui/coroutine/pattern-borrow.stderr @@ -6,6 +6,6 @@ LL | if let Test::A(ref _a) = test { LL | yield (); | -------- possible yield occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr index fb80f29d10d81..100993bd33cf6 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr @@ -14,6 +14,6 @@ LL | | }; = note: expected unit type `()` found coroutine `{main::{closure#0} upvar_tys=(unavailable)}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr index 4c8694e67869f..8811faf2fade5 100644 --- a/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr +++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr @@ -10,6 +10,6 @@ LL | a = &b; | | borrow is only valid in the coroutine body | reference to `b` escapes the coroutine body here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr index f1a8a8ed71113..a97cc6190fd91 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.stderr +++ b/tests/ui/coroutine/resume-arg-late-bound.stderr @@ -12,6 +12,6 @@ note: the lifetime requirement is introduced here LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coroutine/retain-resume-ref.stderr b/tests/ui/coroutine/retain-resume-ref.stderr index e33310d12d9ef..eb8b78df6c998 100644 --- a/tests/ui/coroutine/retain-resume-ref.stderr +++ b/tests/ui/coroutine/retain-resume-ref.stderr @@ -8,6 +8,6 @@ LL | gen.as_mut().resume(&mut thing); | | | first borrow later used by call -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/coroutine/self_referential_gen_block.stderr b/tests/ui/coroutine/self_referential_gen_block.stderr index 586f53df8f260..e23d653d0d447 100644 --- a/tests/ui/coroutine/self_referential_gen_block.stderr +++ b/tests/ui/coroutine/self_referential_gen_block.stderr @@ -6,6 +6,6 @@ LL | let z = &y; LL | yield 43; | -------- possible yield occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/coroutine/size-moved-locals.rs b/tests/ui/coroutine/size-moved-locals.rs index cfbbb9c1b318f..10f988cc06665 100644 --- a/tests/ui/coroutine/size-moved-locals.rs +++ b/tests/ui/coroutine/size-moved-locals.rs @@ -11,7 +11,6 @@ // edition:2018 // ignore-wasm32 issue #62807 -// ignore-asmjs issue #62807 // needs-unwind Size of Closures change on panic=abort #![feature(coroutines, coroutine_trait)] diff --git a/tests/ui/coroutine/static-not-unpin.current.stderr b/tests/ui/coroutine/static-not-unpin.current.stderr index cd607904f5a60..8ef54298431f7 100644 --- a/tests/ui/coroutine/static-not-unpin.current.stderr +++ b/tests/ui/coroutine/static-not-unpin.current.stderr @@ -14,6 +14,6 @@ note: required by a bound in `assert_unpin` LL | fn assert_unpin(_: T) { | ^^^^^ required by this bound in `assert_unpin` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/static-not-unpin.next.stderr b/tests/ui/coroutine/static-not-unpin.next.stderr index cd607904f5a60..8ef54298431f7 100644 --- a/tests/ui/coroutine/static-not-unpin.next.stderr +++ b/tests/ui/coroutine/static-not-unpin.next.stderr @@ -14,6 +14,6 @@ note: required by a bound in `assert_unpin` LL | fn assert_unpin(_: T) { | ^^^^^ required by this bound in `assert_unpin` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/too-many-parameters.stderr b/tests/ui/coroutine/too-many-parameters.stderr index 54cf42e78d3b6..c0917c7225ba4 100644 --- a/tests/ui/coroutine/too-many-parameters.stderr +++ b/tests/ui/coroutine/too-many-parameters.stderr @@ -4,6 +4,6 @@ error[E0628]: too many parameters for a coroutine (expected 0 or 1 parameters) LL | |(), ()| { | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0628`. diff --git a/tests/ui/coroutine/type-mismatch-error.stderr b/tests/ui/coroutine/type-mismatch-error.stderr index 8f5949533e2c7..737d9afdd79a9 100644 --- a/tests/ui/coroutine/type-mismatch-error.stderr +++ b/tests/ui/coroutine/type-mismatch-error.stderr @@ -14,6 +14,6 @@ LL | | LL | | } | |_____________- `if` and `else` have incompatible types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coroutine/unresolved-ct-var.stderr b/tests/ui/coroutine/unresolved-ct-var.stderr index 9badc1dc291ee..da2ec272f9fff 100644 --- a/tests/ui/coroutine/unresolved-ct-var.stderr +++ b/tests/ui/coroutine/unresolved-ct-var.stderr @@ -12,6 +12,6 @@ LL | let s = std::array::from_fn(|_| ()).await; = note: [(); _] must be a future or must implement `IntoFuture` to be awaited = note: required for `[(); _]` to implement `IntoFuture` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/unsized-capture-across-yield.stderr b/tests/ui/coroutine/unsized-capture-across-yield.stderr index 8a5b968a56171..436f0901a9776 100644 --- a/tests/ui/coroutine/unsized-capture-across-yield.stderr +++ b/tests/ui/coroutine/unsized-capture-across-yield.stderr @@ -18,6 +18,6 @@ LL | println!("{:?}", &b); = help: the trait `Sized` is not implemented for `[u8]` = note: all values captured by value by a closure must have a statically known size -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/unsized-local-across-yield.stderr b/tests/ui/coroutine/unsized-local-across-yield.stderr index 1942f266e6cc4..c4c3be77ac2bd 100644 --- a/tests/ui/coroutine/unsized-local-across-yield.stderr +++ b/tests/ui/coroutine/unsized-local-across-yield.stderr @@ -16,6 +16,6 @@ LL | let b: [u8] = *(Box::new([]) as Box<[u8]>); = help: the trait `Sized` is not implemented for `[u8]` = note: all values live across `yield` must have a statically known size -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/unwind-abort-mix.rs b/tests/ui/coroutine/unwind-abort-mix.rs new file mode 100644 index 0000000000000..869b3e4f43347 --- /dev/null +++ b/tests/ui/coroutine/unwind-abort-mix.rs @@ -0,0 +1,13 @@ +// Ensure that coroutine drop glue is valid when mixing different panic +// strategies. Regression test for #116953. +// +// no-prefer-dynamic +// build-pass +// aux-build:unwind-aux.rs +// compile-flags: -Cpanic=abort +// needs-unwind +extern crate unwind_aux; + +pub fn main() { + unwind_aux::run(String::new()); +} diff --git a/tests/ui/coroutine/witness-ignore-fake-reads.rs b/tests/ui/coroutine/witness-ignore-fake-reads.rs new file mode 100644 index 0000000000000..ccf9ce8b49e18 --- /dev/null +++ b/tests/ui/coroutine/witness-ignore-fake-reads.rs @@ -0,0 +1,34 @@ +// check-pass +// edition: 2021 + +// regression test for #117059 +struct SendNotSync(*const ()); +unsafe impl Send for SendNotSync {} +// impl !Sync for SendNotSync {} // automatically disabled + +struct Inner { + stream: SendNotSync, + state: bool, +} + +struct SendSync; +impl std::ops::Deref for SendSync { + type Target = Inner; + fn deref(&self) -> &Self::Target { + todo!(); + } +} + +async fn next() { + let inner = SendSync; + match inner.state { + true if false => {} + false => async {}.await, + _ => {} + } +} + +fn is_send(_: T) {} +fn main() { + is_send(next()) +} diff --git a/tests/ui/coroutine/yield-in-args.stderr b/tests/ui/coroutine/yield-in-args.stderr index 4ff97281d7b42..7233f47884b7b 100644 --- a/tests/ui/coroutine/yield-in-args.stderr +++ b/tests/ui/coroutine/yield-in-args.stderr @@ -4,6 +4,6 @@ error[E0626]: borrow may still be in use when coroutine yields LL | foo(&b, yield); | ^^ ----- possible yield occurs here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/coroutine/yield-in-const.stderr b/tests/ui/coroutine/yield-in-const.stderr index 7afcd83403ebc..d5748b0533753 100644 --- a/tests/ui/coroutine/yield-in-const.stderr +++ b/tests/ui/coroutine/yield-in-const.stderr @@ -4,6 +4,6 @@ error[E0627]: yield expression outside of coroutine literal LL | const A: u8 = { yield 3u8; 3u8}; | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/yield-in-function.stderr b/tests/ui/coroutine/yield-in-function.stderr index b2f839a65db08..b9d4708bb8d86 100644 --- a/tests/ui/coroutine/yield-in-function.stderr +++ b/tests/ui/coroutine/yield-in-function.stderr @@ -4,6 +4,6 @@ error[E0627]: yield expression outside of coroutine literal LL | fn main() { yield; } | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/yield-in-static.stderr b/tests/ui/coroutine/yield-in-static.stderr index 17d58325e9868..b56283cab6690 100644 --- a/tests/ui/coroutine/yield-in-static.stderr +++ b/tests/ui/coroutine/yield-in-static.stderr @@ -4,6 +4,6 @@ error[E0627]: yield expression outside of coroutine literal LL | static B: u8 = { yield 3u8; 3u8}; | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/yield-while-ref-reborrowed.stderr b/tests/ui/coroutine/yield-while-ref-reborrowed.stderr index e60a953162289..62ac02653112e 100644 --- a/tests/ui/coroutine/yield-while-ref-reborrowed.stderr +++ b/tests/ui/coroutine/yield-while-ref-reborrowed.stderr @@ -13,6 +13,6 @@ LL | Pin::new(&mut b).resume(()); | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0501`. diff --git a/tests/ui/crate-loading/crateresolve1.stderr b/tests/ui/crate-loading/crateresolve1.stderr index 7b840b52628f1..47131a96bf43b 100644 --- a/tests/ui/crate-loading/crateresolve1.stderr +++ b/tests/ui/crate-loading/crateresolve1.stderr @@ -8,6 +8,6 @@ LL | extern crate crateresolve1; = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-2.somelib = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-3.somelib -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0464`. diff --git a/tests/ui/crate-loading/crateresolve2.stderr b/tests/ui/crate-loading/crateresolve2.stderr index a36f4f02265b7..3dc89dabde6d5 100644 --- a/tests/ui/crate-loading/crateresolve2.stderr +++ b/tests/ui/crate-loading/crateresolve2.stderr @@ -8,6 +8,6 @@ LL | extern crate crateresolve2; = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0464`. diff --git a/tests/ui/crate-name-mismatch.stderr b/tests/ui/crate-name-mismatch.stderr index 96618570d8fb6..511562618d569 100644 --- a/tests/ui/crate-name-mismatch.stderr +++ b/tests/ui/crate-name-mismatch.stderr @@ -4,5 +4,5 @@ error: `--crate-name` and `#[crate_name]` are required to match, but `foo` != `b LL | #![crate_name = "bar"] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/cross/cross-borrow-trait.stderr b/tests/ui/cross/cross-borrow-trait.stderr index 4f5af106613f6..b670de39f6dbf 100644 --- a/tests/ui/cross/cross-borrow-trait.stderr +++ b/tests/ui/cross/cross-borrow-trait.stderr @@ -9,6 +9,6 @@ LL | let _y: &dyn Trait = x; = note: expected reference `&dyn Trait` found struct `Box` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/cross/cross-crate-macro-backtrace/main.stderr b/tests/ui/cross/cross-crate-macro-backtrace/main.stderr index 5bd4ea97e9cd2..d6f20b1f8e9f2 100644 --- a/tests/ui/cross/cross-crate-macro-backtrace/main.stderr +++ b/tests/ui/cross/cross-crate-macro-backtrace/main.stderr @@ -6,5 +6,5 @@ LL | myprintln!("{}"); | = note: this error originates in the macro `concat` which comes from the expansion of the macro `myprintln` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/cross/cross-file-errors/main.stderr b/tests/ui/cross/cross-file-errors/main.stderr index 56eb6ad429af0..c7dea801acfbd 100644 --- a/tests/ui/cross/cross-file-errors/main.stderr +++ b/tests/ui/cross/cross-file-errors/main.stderr @@ -11,5 +11,5 @@ LL | underscore!(); | = note: this error originates in the macro `underscore` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/cross/cross-fn-cache-hole.stderr b/tests/ui/cross/cross-fn-cache-hole.stderr index 79d1713934b3c..ae944387f57a3 100644 --- a/tests/ui/cross/cross-fn-cache-hole.stderr +++ b/tests/ui/cross/cross-fn-cache-hole.stderr @@ -12,6 +12,6 @@ LL | trait Bar { } = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/custom-attribute-multisegment.stderr b/tests/ui/custom-attribute-multisegment.stderr index 57eca211ed10e..90ebe27793911 100644 --- a/tests/ui/custom-attribute-multisegment.stderr +++ b/tests/ui/custom-attribute-multisegment.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: could not find `nonexistent` in `existent` LL | #[existent::nonexistent] | ^^^^^^^^^^^ could not find `nonexistent` in `existent` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/custom_test_frameworks/mismatch.stderr b/tests/ui/custom_test_frameworks/mismatch.stderr index 31b18b2df9844..dad93cfbba4cb 100644 --- a/tests/ui/custom_test_frameworks/mismatch.stderr +++ b/tests/ui/custom_test_frameworks/mismatch.stderr @@ -9,6 +9,6 @@ LL | fn wrong_kind(){} = note: required for the cast from `&TestDescAndFn` to `&dyn Testable` = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr index 3b66704d6131f..e8be9b0b91350 100644 --- a/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr +++ b/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr @@ -16,6 +16,6 @@ LL | | fn main() { } | |_____________^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr index 03cb5015ab0b1..8645b4ebccf51 100644 --- a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr +++ b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr @@ -14,6 +14,6 @@ LL | | } | |_^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr b/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr index c7cc314352044..f2d8f07b04e5a 100644 --- a/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr +++ b/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr @@ -17,6 +17,6 @@ LL | trait A: B { | ^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/cycle-trait/issue-12511.stderr b/tests/ui/cycle-trait/issue-12511.stderr index f5e4f83473dff..bc56b9904f5a7 100644 --- a/tests/ui/cycle-trait/issue-12511.stderr +++ b/tests/ui/cycle-trait/issue-12511.stderr @@ -19,6 +19,6 @@ LL | | } | |_^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr index d5991bcf5693d..06aad9616cb7a 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr @@ -1,4 +1,4 @@ error: values of the type `[u8; usize::MAX]` are too big for the current architecture -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr index d5991bcf5693d..06aad9616cb7a 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr @@ -1,4 +1,4 @@ error: values of the type `[u8; usize::MAX]` are too big for the current architecture -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr index cdc268cff992e..f26b43aa3ec74 100644 --- a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr +++ b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr @@ -4,5 +4,5 @@ error: OK LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.rs index 590475fa03a3e..0331e75b2fe8d 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.rs +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.rs @@ -29,7 +29,7 @@ mod x { mod y { use {Foo, Bar}; - #[rustc_then_this_would_need(typeck)] //~ ERROR OK + #[rustc_then_this_would_need(typeck)] //~ ERROR no path pub fn call_bar() { char::bar('a'); } diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr index 4e10437362c6b..08f382cc024c7 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr @@ -1,4 +1,4 @@ -error: OK +error: no path from `x::` to `typeck` --> $DIR/dep-graph-trait-impl-two-traits.rs:32:5 | LL | #[rustc_then_this_would_need(typeck)] diff --git a/tests/ui/dep-graph/dep-graph-variance-alias.stderr b/tests/ui/dep-graph/dep-graph-variance-alias.stderr index 554ff455a2073..e11de2452899f 100644 --- a/tests/ui/dep-graph/dep-graph-variance-alias.stderr +++ b/tests/ui/dep-graph/dep-graph-variance-alias.stderr @@ -4,5 +4,5 @@ error: OK LL | #[rustc_then_this_would_need(variances_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/deprecation/deprecated_no_stack_check.stderr b/tests/ui/deprecation/deprecated_no_stack_check.stderr index 141664c109228..d78ca20f10b4a 100644 --- a/tests/ui/deprecation/deprecated_no_stack_check.stderr +++ b/tests/ui/deprecation/deprecated_no_stack_check.stderr @@ -4,6 +4,6 @@ error[E0557]: feature has been removed LL | #![feature(no_stack_check)] | ^^^^^^^^^^^^^^ feature has been removed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0557`. diff --git a/tests/ui/deprecation/deprecation-lint-2.stderr b/tests/ui/deprecation/deprecation-lint-2.stderr index a73e5605271be..7d411c00445ce 100644 --- a/tests/ui/deprecation/deprecation-lint-2.stderr +++ b/tests/ui/deprecation/deprecation-lint-2.stderr @@ -11,5 +11,5 @@ LL | #![deny(deprecated)] | ^^^^^^^^^^ = note: this error originates in the macro `macro_test` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/deprecation/deprecation-lint-3.stderr b/tests/ui/deprecation/deprecation-lint-3.stderr index f499ff85e5da8..1723b7bbd0535 100644 --- a/tests/ui/deprecation/deprecation-lint-3.stderr +++ b/tests/ui/deprecation/deprecation-lint-3.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(deprecated)] | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/deprecation/feature-gate-deprecated_suggestion.stderr b/tests/ui/deprecation/feature-gate-deprecated_suggestion.stderr index 438ce3349d252..81cc608b5ebe0 100644 --- a/tests/ui/deprecation/feature-gate-deprecated_suggestion.stderr +++ b/tests/ui/deprecation/feature-gate-deprecated_suggestion.stderr @@ -7,5 +7,5 @@ LL | #[deprecated(suggestion = "foo")] = help: add `#![feature(deprecated_suggestion)]` to the crate root = note: see #94785 for more details -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/deprecation/invalid-literal.stderr b/tests/ui/deprecation/invalid-literal.stderr index b56eedeb80d16..ca827beda0596 100644 --- a/tests/ui/deprecation/invalid-literal.stderr +++ b/tests/ui/deprecation/invalid-literal.stderr @@ -13,5 +13,5 @@ LL | #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] LL | #[deprecated] | ~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr index 24178faf8de78..48c763c50e3b1 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -4,5 +4,5 @@ error: expected unsuffixed literal or identifier, found `test` LL | #[deprecated(note = test)] | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/deref-non-pointer.stderr b/tests/ui/deref-non-pointer.stderr index 1297e496bcb30..2e5e574fb6c7e 100644 --- a/tests/ui/deref-non-pointer.stderr +++ b/tests/ui/deref-non-pointer.stderr @@ -4,6 +4,6 @@ error[E0614]: type `{integer}` cannot be dereferenced LL | match *1 { | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/deref-patterns/gate.stderr b/tests/ui/deref-patterns/gate.stderr index b5b79ed3771c3..e3cbded339d7f 100644 --- a/tests/ui/deref-patterns/gate.stderr +++ b/tests/ui/deref-patterns/gate.stderr @@ -6,6 +6,6 @@ LL | match String::new() { LL | "" | _ => {} | ^^ expected `String`, found `&str` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/derived-errors/issue-30580.stderr b/tests/ui/derived-errors/issue-30580.stderr index 7bd0eaf77a95d..05b5559172994 100644 --- a/tests/ui/derived-errors/issue-30580.stderr +++ b/tests/ui/derived-errors/issue-30580.stderr @@ -2,8 +2,13 @@ error[E0609]: no field `c` on type `&Foo` --> $DIR/issue-30580.rs:12:11 | LL | b.c; - | ^ help: a field with a similar name exists: `a` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | b.a; + | ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/derived-errors/issue-31997-1.stderr b/tests/ui/derived-errors/issue-31997-1.stderr index a0262f4c1e597..40485027a660c 100644 --- a/tests/ui/derived-errors/issue-31997-1.stderr +++ b/tests/ui/derived-errors/issue-31997-1.stderr @@ -9,6 +9,6 @@ help: consider importing this struct LL + use std::collections::HashMap; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/derived-errors/issue-31997.stderr b/tests/ui/derived-errors/issue-31997.stderr index b53c0cda8de4d..7d6415fef83c1 100644 --- a/tests/ui/derived-errors/issue-31997.stderr +++ b/tests/ui/derived-errors/issue-31997.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find function `bar` in this scope LL | try!(closure(|| bar(core::ptr::null_mut()))); | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr index 7f4f78cebc918..e9b757b6bae72 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr @@ -20,5 +20,5 @@ note: the lint level is defined here LL | #![forbid(dead_code)] | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 9f17c76c2ec6d..6cbcb455f87e9 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -27,6 +27,6 @@ LL + #[derive(Clone)] LL | struct NotClone; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/derives/derive-deadlock.stderr b/tests/ui/derives/derive-deadlock.stderr index 8d062491c6a7c..116245aa3cbf1 100644 --- a/tests/ui/derives/derive-deadlock.stderr +++ b/tests/ui/derives/derive-deadlock.stderr @@ -6,5 +6,5 @@ LL | #[derive(Default)] | = note: import resolution is stuck, try simplifying macro imports -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr index 31ab589cf385a..2c8d9431646d6 100644 --- a/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr @@ -14,6 +14,6 @@ LL + #[derive(Clone)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Clone-enum.stderr b/tests/ui/derives/derives-span-Clone-enum.stderr index b5580c02f38f3..b683a8b89441a 100644 --- a/tests/ui/derives/derives-span-Clone-enum.stderr +++ b/tests/ui/derives/derives-span-Clone-enum.stderr @@ -14,6 +14,6 @@ LL + #[derive(Clone)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Clone-struct.stderr b/tests/ui/derives/derives-span-Clone-struct.stderr index fbe7e3f8479da..305a92752716f 100644 --- a/tests/ui/derives/derives-span-Clone-struct.stderr +++ b/tests/ui/derives/derives-span-Clone-struct.stderr @@ -14,6 +14,6 @@ LL + #[derive(Clone)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Clone-tuple-struct.stderr b/tests/ui/derives/derives-span-Clone-tuple-struct.stderr index 639f4d5425478..b636404ad9ed7 100644 --- a/tests/ui/derives/derives-span-Clone-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Clone-tuple-struct.stderr @@ -14,6 +14,6 @@ LL + #[derive(Clone)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr index 7ff6851f6555b..3f6c39bf9396e 100644 --- a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr @@ -16,6 +16,6 @@ LL + #[derive(Debug)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Debug-enum.stderr b/tests/ui/derives/derives-span-Debug-enum.stderr index 346cbec90a940..eaeffaeb84956 100644 --- a/tests/ui/derives/derives-span-Debug-enum.stderr +++ b/tests/ui/derives/derives-span-Debug-enum.stderr @@ -16,6 +16,6 @@ LL + #[derive(Debug)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Debug-struct.stderr b/tests/ui/derives/derives-span-Debug-struct.stderr index 4b39eeb09ee8a..4a725e260deae 100644 --- a/tests/ui/derives/derives-span-Debug-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-struct.stderr @@ -16,6 +16,6 @@ LL + #[derive(Debug)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr index f3043abcadd22..2f816e1c85b25 100644 --- a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr @@ -16,6 +16,6 @@ LL + #[derive(Debug)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Default-struct.stderr b/tests/ui/derives/derives-span-Default-struct.stderr index 4844b63592402..359b61528e183 100644 --- a/tests/ui/derives/derives-span-Default-struct.stderr +++ b/tests/ui/derives/derives-span-Default-struct.stderr @@ -14,6 +14,6 @@ LL + #[derive(Default)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Default-tuple-struct.stderr b/tests/ui/derives/derives-span-Default-tuple-struct.stderr index 9cac7f10780ff..1ddb4ec3f642e 100644 --- a/tests/ui/derives/derives-span-Default-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Default-tuple-struct.stderr @@ -14,6 +14,6 @@ LL + #[derive(Default)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr index 1a9ff9832557d..c9edc89e1bc56 100644 --- a/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr @@ -16,6 +16,6 @@ LL + #[derive(Eq)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Eq-enum.stderr b/tests/ui/derives/derives-span-Eq-enum.stderr index 8205657bb7104..7db13e9711141 100644 --- a/tests/ui/derives/derives-span-Eq-enum.stderr +++ b/tests/ui/derives/derives-span-Eq-enum.stderr @@ -16,6 +16,6 @@ LL + #[derive(Eq)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Eq-struct.stderr b/tests/ui/derives/derives-span-Eq-struct.stderr index af510181df7db..36eeb89bde18e 100644 --- a/tests/ui/derives/derives-span-Eq-struct.stderr +++ b/tests/ui/derives/derives-span-Eq-struct.stderr @@ -16,6 +16,6 @@ LL + #[derive(Eq)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Eq-tuple-struct.stderr b/tests/ui/derives/derives-span-Eq-tuple-struct.stderr index f7c371d7d05ac..126d105354066 100644 --- a/tests/ui/derives/derives-span-Eq-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Eq-tuple-struct.stderr @@ -16,6 +16,6 @@ LL + #[derive(Eq)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr index 311edade0f3d8..ae973228cacbc 100644 --- a/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr @@ -14,6 +14,6 @@ LL + #[derive(Hash)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Hash-enum.stderr b/tests/ui/derives/derives-span-Hash-enum.stderr index 043aa954bfa10..85e26c84fa7a1 100644 --- a/tests/ui/derives/derives-span-Hash-enum.stderr +++ b/tests/ui/derives/derives-span-Hash-enum.stderr @@ -14,6 +14,6 @@ LL + #[derive(Hash)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Hash-struct.stderr b/tests/ui/derives/derives-span-Hash-struct.stderr index 26d31b6613fe7..f9a654b2df798 100644 --- a/tests/ui/derives/derives-span-Hash-struct.stderr +++ b/tests/ui/derives/derives-span-Hash-struct.stderr @@ -14,6 +14,6 @@ LL + #[derive(Hash)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Hash-tuple-struct.stderr b/tests/ui/derives/derives-span-Hash-tuple-struct.stderr index 3155a023ce8a9..0a5fbe286587b 100644 --- a/tests/ui/derives/derives-span-Hash-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Hash-tuple-struct.stderr @@ -14,6 +14,6 @@ LL + #[derive(Hash)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr index 1a06aee5235ad..96ef59ca9631b 100644 --- a/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr @@ -14,6 +14,6 @@ LL + #[derive(Ord)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Ord-enum.stderr b/tests/ui/derives/derives-span-Ord-enum.stderr index 377728e8a7f66..7c75ecb6432e2 100644 --- a/tests/ui/derives/derives-span-Ord-enum.stderr +++ b/tests/ui/derives/derives-span-Ord-enum.stderr @@ -14,6 +14,6 @@ LL + #[derive(Ord)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Ord-struct.stderr b/tests/ui/derives/derives-span-Ord-struct.stderr index e00e990da2a5b..429e7e06f5d9f 100644 --- a/tests/ui/derives/derives-span-Ord-struct.stderr +++ b/tests/ui/derives/derives-span-Ord-struct.stderr @@ -14,6 +14,6 @@ LL + #[derive(Ord)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Ord-tuple-struct.stderr b/tests/ui/derives/derives-span-Ord-tuple-struct.stderr index 959d0b9640408..a46133834c6ad 100644 --- a/tests/ui/derives/derives-span-Ord-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Ord-tuple-struct.stderr @@ -14,6 +14,6 @@ LL + #[derive(Ord)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr index e3b17431f89af..d0b14ef94c17b 100644 --- a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr @@ -19,6 +19,6 @@ LL + #[derive(PartialEq)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-PartialEq-enum.stderr b/tests/ui/derives/derives-span-PartialEq-enum.stderr index d1631732a34f4..f69451ac793ee 100644 --- a/tests/ui/derives/derives-span-PartialEq-enum.stderr +++ b/tests/ui/derives/derives-span-PartialEq-enum.stderr @@ -19,6 +19,6 @@ LL + #[derive(PartialEq)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-PartialEq-struct.stderr b/tests/ui/derives/derives-span-PartialEq-struct.stderr index ab6c6951fc634..d7fc3da46e0ee 100644 --- a/tests/ui/derives/derives-span-PartialEq-struct.stderr +++ b/tests/ui/derives/derives-span-PartialEq-struct.stderr @@ -19,6 +19,6 @@ LL + #[derive(PartialEq)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr index 865ecad0e8e6d..ea3920f406ce8 100644 --- a/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr @@ -19,6 +19,6 @@ LL + #[derive(PartialEq)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr index 746c1d5d21fd4..3f83eb56aaf20 100644 --- a/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr @@ -15,6 +15,6 @@ LL + #[derive(PartialOrd)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-PartialOrd-enum.stderr b/tests/ui/derives/derives-span-PartialOrd-enum.stderr index 8af1776dac87b..cf5915173c5ef 100644 --- a/tests/ui/derives/derives-span-PartialOrd-enum.stderr +++ b/tests/ui/derives/derives-span-PartialOrd-enum.stderr @@ -15,6 +15,6 @@ LL + #[derive(PartialOrd)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-PartialOrd-struct.stderr b/tests/ui/derives/derives-span-PartialOrd-struct.stderr index 11ea7f9dc31be..de21a903b6ca2 100644 --- a/tests/ui/derives/derives-span-PartialOrd-struct.stderr +++ b/tests/ui/derives/derives-span-PartialOrd-struct.stderr @@ -15,6 +15,6 @@ LL + #[derive(PartialOrd)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr index 0a41a3db31eac..3050aeecc0dae 100644 --- a/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr @@ -15,6 +15,6 @@ LL + #[derive(PartialOrd)] LL | struct Error; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index afeca9fec2b84..0eaca7e236098 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -29,6 +29,6 @@ LL + #[derive(Clone, Copy)] LL | struct NonCopy; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs new file mode 100644 index 0000000000000..ffeb02d78b848 --- /dev/null +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs @@ -0,0 +1,96 @@ +// Check that deriving builtin traits for a packed struct with +// non-Copy fields emits move errors along with an additional +// diagnostic note explaining the reason +// See issue #117406 + +use std::fmt::{Debug, Formatter, Result}; +use std::cmp::Ordering; + +// Packed + derives: additional diagnostic should be emitted +// for each of Debug, PartialEq and PartialOrd +#[repr(packed)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] +struct StructA(String); +//~^ ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference + + +// Unrelated impl: additinal diagnostic should NOT be emitted +impl StructA { + fn fmt(&self) -> String { + self.0 //~ ERROR: cannot move out of `self` which is behind a shared reference + } +} + +// Packed + manual impls: additional diagnostic should NOT be emitted +#[repr(packed)] +struct StructB(String); + +impl Debug for StructB { + fn fmt(&self, f: &mut Formatter) -> Result { + let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference + write!(f, "{}", x) + } +} + +impl PartialEq for StructB { + fn eq(&self, other: &StructB) -> bool { + ({ self.0 }) == ({ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +impl PartialOrd for StructB { + fn partial_cmp(&self, other: &StructB) -> Option { + PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +// NOT packed + derives: additinal diagnostic should NOT be emitted +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] +struct StructC(String); + +// NOT packed + manual impls: additinal dignostic should NOT be emitted +struct StructD(String); + +impl Debug for StructD { + fn fmt(&self, f: &mut Formatter) -> Result { + let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference + write!(f, "{}", x) + } +} + +impl PartialEq for StructD { + fn eq(&self, other: &StructD) -> bool { + ({ self.0 }) == ({ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +impl PartialOrd for StructD { + fn partial_cmp(&self, other: &StructD) -> Option { + PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +// Packed + derives but the move is outside of a derive +// expansion: additinal diagnostic should NOT be emitted +fn func(arg: &StructA) -> String { + arg.0 //~ ERROR: cannot move out of `arg` which is behind a shared reference +} + +fn main(){ +} diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr new file mode 100644 index 0000000000000..c538061b365e2 --- /dev/null +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr @@ -0,0 +1,174 @@ +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ----- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | --------- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | --------- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ---------- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ---------- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | --- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | --- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ---- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Hash)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 + | +LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] + | ----- in this derive macro expansion +LL | struct StructA(String); + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + | + = note: `#[derive(Clone)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:28:9 + | +LL | self.0 + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:38:20 + | +LL | let x = &{ self.0 }; + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:45:12 + | +LL | ({ self.0 }) == ({ other.0 }) + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:45:28 + | +LL | ({ self.0 }) == ({ other.0 }) + | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:53:36 + | +LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:53:49 + | +LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:68:20 + | +LL | let x = &{ self.0 }; + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:75:12 + | +LL | ({ self.0 }) == ({ other.0 }) + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:75:28 + | +LL | ({ self.0 }) == ({ other.0 }) + | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:83:36 + | +LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `other` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:83:49 + | +LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `arg` which is behind a shared reference + --> $DIR/deriving-with-repr-packed-move-errors.rs:92:5 + | +LL | arg.0 + | ^^^^^ move occurs because `arg.0` has type `String`, which does not implement the `Copy` trait + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 0cfe03869af1b..151be6901b01c 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -36,9 +36,10 @@ LL | #[repr(packed)] LL | struct X(Y); | ^ move occurs because `self.0` has type `Y`, which does not implement the `Copy` trait | + = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error; 2 warnings emitted +error: aborting due to 1 previous error; 2 warnings emitted For more information about this error, try `rustc --explain E0507`. Future incompatibility report: Future breakage diagnostic: diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr index e83bbb5b60d7e..efb2fb70f5a51 100644 --- a/tests/ui/derives/issue-97343.stderr +++ b/tests/ui/derives/issue-97343.stderr @@ -16,6 +16,6 @@ LL | pub struct Irrelevant { | ^^^^^^^^^^ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout index 3d9f8129d9395..42154c3c3be23 100644 --- a/tests/ui/deriving/deriving-all-codegen.stdout +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -33,6 +33,7 @@ impl ::core::clone::Clone for Empty { impl ::core::marker::Copy for Empty { } #[automatically_derived] impl ::core::fmt::Debug for Empty { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, "Empty") } @@ -97,6 +98,7 @@ impl ::core::clone::Clone for Point { impl ::core::marker::Copy for Point { } #[automatically_derived] impl ::core::fmt::Debug for Point { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", &self.x, "y", &&self.y) @@ -183,6 +185,7 @@ impl ::core::clone::Clone for PackedPoint { impl ::core::marker::Copy for PackedPoint { } #[automatically_derived] impl ::core::fmt::Debug for PackedPoint { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "PackedPoint", "x", &{ self.x }, "y", &&{ self.y }) @@ -276,6 +279,7 @@ impl ::core::clone::Clone for Big { impl ::core::marker::Copy for Big { } #[automatically_derived] impl ::core::fmt::Debug for Big { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let names: &'static _ = &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; @@ -475,6 +479,7 @@ impl Copy for PackedManualCopy {} struct Unsized([u32]); #[automatically_derived] impl ::core::fmt::Debug for Unsized { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unsized", &&self.0) @@ -527,6 +532,7 @@ impl ::core::cmp::Ord for Unsized { struct PackedUnsizedU8([u8]); #[automatically_derived] impl ::core::fmt::Debug for PackedUnsizedU8 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedUnsizedU8", &&self.0) @@ -569,6 +575,7 @@ impl #[automatically_derived] impl ::core::fmt::Debug for Generic where T::A: ::core::fmt::Debug { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field3_finish(f, "Generic", "t", &self.t, "ta", &self.ta, "u", &&self.u) @@ -687,6 +694,7 @@ impl ::core::fmt::Debug for PackedGeneric where T::A: ::core::fmt::Debug + ::core::marker::Copy { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field3_finish(f, "PackedGeneric", &{ self.0 }, &{ self.1 }, &&{ self.2 }) @@ -797,6 +805,7 @@ impl ::core::clone::Clone for Enum0 { impl ::core::marker::Copy for Enum0 { } #[automatically_derived] impl ::core::fmt::Debug for Enum0 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match *self {} } @@ -856,6 +865,7 @@ impl ::core::clone::Clone for Enum1 { } #[automatically_derived] impl ::core::fmt::Debug for Enum1 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Enum1::Single { x: __self_0 } => @@ -932,6 +942,7 @@ impl ::core::clone::Clone for Fieldless1 { } #[automatically_derived] impl ::core::fmt::Debug for Fieldless1 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, "A") } @@ -995,6 +1006,7 @@ impl ::core::clone::Clone for Fieldless { impl ::core::marker::Copy for Fieldless { } #[automatically_derived] impl ::core::fmt::Debug for Fieldless { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, match self { @@ -1083,6 +1095,7 @@ impl ::core::clone::Clone for Mixed { impl ::core::marker::Copy for Mixed { } #[automatically_derived] impl ::core::fmt::Debug for Mixed { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Mixed::P => ::core::fmt::Formatter::write_str(f, "P"), @@ -1217,6 +1230,7 @@ impl ::core::clone::Clone for Fielded { } #[automatically_derived] impl ::core::fmt::Debug for Fielded { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Fielded::X(__self_0) => @@ -1341,6 +1355,7 @@ impl ::core::marker::Copy #[automatically_derived] impl ::core::fmt::Debug for EnumGeneric { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { EnumGeneric::One(__self_0) => diff --git a/tests/ui/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr index 01cce2a397ab3..384899ea43334 100644 --- a/tests/ui/deriving/issue-103157.stderr +++ b/tests/ui/deriving/issue-103157.stderr @@ -22,6 +22,6 @@ note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/deriving/issue-105101.rs b/tests/ui/deriving/issue-105101.rs deleted file mode 100644 index 1a377feb91948..0000000000000 --- a/tests/ui/deriving/issue-105101.rs +++ /dev/null @@ -1,9 +0,0 @@ -// compile-flags: --crate-type=lib - -#[derive(Default)] //~ ERROR multiple declared defaults -enum E { - #[default] - A, - #[default] - A, //~ ERROR defined multiple times -} diff --git a/tests/ui/deriving/issue-105101.stderr b/tests/ui/deriving/issue-105101.stderr deleted file mode 100644 index 0f6f67043f32f..0000000000000 --- a/tests/ui/deriving/issue-105101.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error: multiple declared defaults - --> $DIR/issue-105101.rs:3:10 - | -LL | #[derive(Default)] - | ^^^^^^^ -... -LL | A, - | - first default -LL | #[default] -LL | A, - | - additional default - | - = note: only one variant can be default - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0428]: the name `A` is defined multiple times - --> $DIR/issue-105101.rs:8:5 - | -LL | A, - | - previous definition of the type `A` here -LL | #[default] -LL | A, - | ^ `A` redefined here - | - = note: `A` must be defined only once in the type namespace of this enum - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/deriving/multiple-defaults.rs b/tests/ui/deriving/multiple-defaults.rs new file mode 100644 index 0000000000000..2024a55200bd8 --- /dev/null +++ b/tests/ui/deriving/multiple-defaults.rs @@ -0,0 +1,41 @@ +// compile-flags: --crate-type=lib + +// When we get multiple `#[default]` variants, we emit several tool-only suggestions +// to remove all except one of the `#[default]`s. + +#[derive(Default)] //~ ERROR multiple declared defaults +enum A { + #[default] //~ HELP make `B` default + #[default] //~ HELP make `A` default + A, + #[default] // also "HELP make `A` default", but compiletest can't handle multispans + B, +} + +// Originally, we took each defaulted variant and emitted the suggestion for every variant +// with a different identifier, causing an ICE when multiple variants have the same identifier: +// https://github.com/rust-lang/rust/pull/105106 +#[derive(Default)] //~ ERROR multiple declared defaults +enum E { + #[default] //~ HELP make `A` default + A, + #[default] //~ HELP make `A` default + A, //~ ERROR defined multiple times +} + +// Then, we took each defaulted variant and emitted the suggestion for every variant +// with a different span, causing an ICE when multiple variants have the same span: +// https://github.com/rust-lang/rust/issues/118119 +macro_rules! m { + { $($id:ident)* } => { + #[derive(Default)] //~ ERROR multiple declared defaults + enum F { + $( + #[default] + $id, + )* + } + } +} + +m! { A B } diff --git a/tests/ui/deriving/multiple-defaults.stderr b/tests/ui/deriving/multiple-defaults.stderr new file mode 100644 index 0000000000000..05fb6fecffaec --- /dev/null +++ b/tests/ui/deriving/multiple-defaults.stderr @@ -0,0 +1,62 @@ +error: multiple declared defaults + --> $DIR/multiple-defaults.rs:6:10 + | +LL | #[derive(Default)] + | ^^^^^^^ +... +LL | A, + | - first default +LL | #[default] // also "HELP make `A` default", but compiletest can't handle multispans +LL | B, + | - additional default + | + = note: only one variant can be default + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: multiple declared defaults + --> $DIR/multiple-defaults.rs:18:10 + | +LL | #[derive(Default)] + | ^^^^^^^ +... +LL | A, + | - first default +LL | #[default] +LL | A, + | - additional default + | + = note: only one variant can be default + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0428]: the name `A` is defined multiple times + --> $DIR/multiple-defaults.rs:23:5 + | +LL | A, + | - previous definition of the type `A` here +LL | #[default] +LL | A, + | ^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this enum + +error: multiple declared defaults + --> $DIR/multiple-defaults.rs:31:18 + | +LL | #[derive(Default)] + | ^^^^^^^ +... +LL | $id, + | --- + | | + | first default + | additional default +... +LL | m! { A B } + | ---------- in this macro invocation + | + = note: only one variant can be default + = note: this error originates in the derive macro `Default` which comes from the expansion of the macro `m` (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 E0428`. diff --git a/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr index b285ee1f30482..b0231d91b4312 100644 --- a/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr +++ b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr @@ -9,6 +9,6 @@ LL | (x, y) = &(1, 2); = note: expected reference `&({integer}, {integer})` found tuple `(_, _)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-flags/terminal_urls.stderr b/tests/ui/diagnostic-flags/terminal_urls.stderr index 7f7e69c5d5da7..e5dfcdf6431a6 100644 --- a/tests/ui/diagnostic-flags/terminal_urls.stderr +++ b/tests/ui/diagnostic-flags/terminal_urls.stderr @@ -6,6 +6,6 @@ LL | let () = 4; | | | expected integer, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/E0271.stderr b/tests/ui/diagnostic-width/E0271.stderr index c1b8b32071ce0..31ec3fe366f4b 100644 --- a/tests/ui/diagnostic-width/E0271.stderr +++ b/tests/ui/diagnostic-width/E0271.stderr @@ -17,6 +17,6 @@ LL | type Error = E; | ^ = note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/diagnostic-width/flag-human.stderr b/tests/ui/diagnostic-width/flag-human.stderr index 393dcf2b82845..eaa9684108069 100644 --- a/tests/ui/diagnostic-width/flag-human.stderr +++ b/tests/ui/diagnostic-width/flag-human.stderr @@ -6,6 +6,6 @@ LL | ..._: () = 42; | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/flag-json.stderr b/tests/ui/diagnostic-width/flag-json.stderr index b21391d1640ef..f3bf4f97942c8 100644 --- a/tests/ui/diagnostic-width/flag-json.stderr +++ b/tests/ui/diagnostic-width/flag-json.stderr @@ -1,4 +1,4 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. +{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. Erroneous code examples: @@ -33,8 +33,8 @@ LL | ..._: () = 42; | expected due to this "} -{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error +{"$message_type":"diagnostic","message":"aborting due to 1 previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 1 previous error "} -{"message":"For more information about this error, try `rustc --explain E0308`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0308`. +{"$message_type":"diagnostic","message":"For more information about this error, try `rustc --explain E0308`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0308`. "} diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr index bf277362dbab2..8f200e15c64d8 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr @@ -13,6 +13,6 @@ help: create an owned `String` from a string reference LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; | +++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr index 5dbb9ce45ee9e..a7d5c0bfb9415 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr @@ -6,6 +6,6 @@ LL | ...13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr index 1e5ff9398321f..da3d8d318922e 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr @@ -6,6 +6,6 @@ LL | ...♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄ | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming.stderr index c4ff0e16890b2..872c5ae3b7642 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming.stderr @@ -6,6 +6,6 @@ LL | ... () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = () | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/tab-column-numbers.stderr b/tests/ui/diagnostic-width/tab-column-numbers.stderr index ea4e1ff52a9e9..3093b66fe9d8b 100644 --- a/tests/ui/diagnostic-width/tab-column-numbers.stderr +++ b/tests/ui/diagnostic-width/tab-column-numbers.stderr @@ -9,6 +9,6 @@ LL | s.method(); LL | fn method(&self) {} | ---------------- private method defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/diagnostic-width/tabs-trimming.stderr b/tests/ui/diagnostic-width/tabs-trimming.stderr index 6c8d9afc73b2a..2aa4fc18c3d65 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.stderr +++ b/tests/ui/diagnostic-width/tabs-trimming.stderr @@ -7,6 +7,6 @@ LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Lon | | pattern doesn't bind `v` | variable not in all patterns -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/diagnostic-width/whitespace-trimming-2.stderr b/tests/ui/diagnostic-width/whitespace-trimming-2.stderr index 97a64e603b761..561f9e613fe2c 100644 --- a/tests/ui/diagnostic-width/whitespace-trimming-2.stderr +++ b/tests/ui/diagnostic-width/whitespace-trimming-2.stderr @@ -6,6 +6,6 @@ LL | ...-> usize { LL | ... () | ^^ expected `usize`, found `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/whitespace-trimming.stderr b/tests/ui/diagnostic-width/whitespace-trimming.stderr index e296d48893cda..519ba8a1f5cc2 100644 --- a/tests/ui/diagnostic-width/whitespace-trimming.stderr +++ b/tests/ui/diagnostic-width/whitespace-trimming.stderr @@ -6,6 +6,6 @@ LL | ... let _: () = 42; | | | expected due to this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs new file mode 100644 index 0000000000000..eb985c062f3dd --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs @@ -0,0 +1,67 @@ +#![feature(diagnostic_namespace)] + +#[diagnostic::on_unimplemented( + on(_Self = "&str"), + //~^WARN malformed `on_unimplemented` attribute + //~|WARN malformed `on_unimplemented` attribute + message = "trait has `{Self}` and `{T}` as params", + label = "trait has `{Self}` and `{T}` as params", + note = "trait has `{Self}` and `{T}` as params", + parent_label = "in this scope", + //~^WARN malformed `on_unimplemented` attribute + //~|WARN malformed `on_unimplemented` attribute + append_const_msg + //~^WARN malformed `on_unimplemented` attribute + //~|WARN malformed `on_unimplemented` attribute +)] +trait Foo {} + +#[diagnostic::on_unimplemented = "Message"] +//~^WARN malformed `on_unimplemented` attribute +//~|WARN malformed `on_unimplemented` attribute +trait Bar {} + +#[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] +//~^WARN #[diagnostic::on_unimplemented]` can only be applied to trait definitions +impl Bar for i32 {} + +// cannot use special rustc_on_unimplement symbols +// in the format string +#[diagnostic::on_unimplemented( + message = "{from_desugaring}{direct}{cause}{integral}{integer}", + //~^WARN there is no parameter `from_desugaring` on trait `Baz` + //~|WARN there is no parameter `from_desugaring` on trait `Baz` + //~|WARN there is no parameter `direct` on trait `Baz` + //~|WARN there is no parameter `direct` on trait `Baz` + //~|WARN there is no parameter `cause` on trait `Baz` + //~|WARN there is no parameter `cause` on trait `Baz` + //~|WARN there is no parameter `integral` on trait `Baz` + //~|WARN there is no parameter `integral` on trait `Baz` + //~|WARN there is no parameter `integer` on trait `Baz` + //~|WARN there is no parameter `integer` on trait `Baz` + label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + //~^WARN there is no parameter `float` on trait `Baz` + //~|WARN there is no parameter `float` on trait `Baz` + //~|WARN there is no parameter `_Self` on trait `Baz` + //~|WARN there is no parameter `_Self` on trait `Baz` + //~|WARN there is no parameter `crate_local` on trait `Baz` + //~|WARN there is no parameter `crate_local` on trait `Baz` + //~|WARN there is no parameter `Trait` on trait `Baz` + //~|WARN there is no parameter `Trait` on trait `Baz` + //~|WARN there is no parameter `ItemContext` on trait `Baz` + //~|WARN there is no parameter `ItemContext` on trait `Baz` +)] +trait Baz {} + +fn takes_foo(_: impl Foo) {} +fn takes_bar(_: impl Bar) {} +fn takes_baz(_: impl Baz) {} + +fn main() { + takes_foo(()); + //~^ERROR trait has `()` and `i32` as params + takes_bar(()); + //~^ERROR the trait bound `(): Bar` is not satisfied + takes_baz(()); + //~^ERROR {from_desugaring}{direct}{cause}{integral}{integer} +} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr new file mode 100644 index 0000000000000..75a701f0b5f65 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr @@ -0,0 +1,305 @@ +warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1 + | +LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + | +LL | on(_Self = "&str"), + | ^^^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + | +LL | parent_label = "in this scope", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + | +LL | append_const_msg + | ^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + | +LL | #[diagnostic::on_unimplemented = "Message"] + | ^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + +warning: there is no parameter `from_desugaring` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `direct` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `cause` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `integral` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `integer` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `float` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `_Self` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `crate_local` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `Trait` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: there is no parameter `ItemContext` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + | +LL | on(_Self = "&str"), + | ^^^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + | +LL | parent_label = "in this scope", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + | +LL | append_const_msg + | ^^^^^^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: trait has `()` and `i32` as params + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15 + | +LL | takes_foo(()); + | --------- ^^ trait has `()` and `i32` as params + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is not implemented for `()` + = note: trait has `()` and `i32` as params +help: this trait has no implementations, consider adding one + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1 + | +LL | trait Foo {} + | ^^^^^^^^^^^^ +note: required by a bound in `takes_foo` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22 + | +LL | fn takes_foo(_: impl Foo) {} + | ^^^^^^^^ required by this bound in `takes_foo` + +warning: malformed `on_unimplemented` attribute + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + | +LL | #[diagnostic::on_unimplemented = "Message"] + | ^^^^^^^^^^^ invalid option found here + | + = help: only `message`, `note` and `label` are allowed as options + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 + | +LL | takes_bar(()); + | --------- ^^ the trait `Bar` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the trait `Bar` is implemented for `i32` +note: required by a bound in `takes_bar` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22 + | +LL | fn takes_bar(_: impl Bar) {} + | ^^^ required by this bound in `takes_bar` + +warning: there is no parameter `from_desugaring` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `direct` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `cause` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `integral` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `integer` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + | +LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `float` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `_Self` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `crate_local` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `Trait` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: there is no parameter `ItemContext` on trait `Baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + | +LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer} + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15 + | +LL | takes_baz(()); + | --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext} + | | + | required by a bound introduced by this call + | + = help: the trait `Baz` is not implemented for `()` +help: this trait has no implementations, consider adding one + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1 + | +LL | trait Baz {} + | ^^^^^^^^^ +note: required by a bound in `takes_baz` + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22 + | +LL | fn takes_baz(_: impl Baz) {} + | ^^^ required by this bound in `takes_baz` + +error: aborting due to 3 previous errors; 29 warnings emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs index 346d8373f7398..12fe988170ac1 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs @@ -28,10 +28,16 @@ trait Doom {} //~|WARN missing options for `on_unimplemented` attribute trait Whatever {} +#[diagnostic::on_unimplemented(message = "{DoesNotExist}")] +//~^WARN there is no parameter `DoesNotExist` on trait `Test` +//~|WARN there is no parameter `DoesNotExist` on trait `Test` +trait Test {} + fn take_foo(_: impl Foo) {} fn take_baz(_: impl Baz) {} fn take_boom(_: impl Boom) {} fn take_whatever(_: impl Whatever) {} +fn take_test(_: impl Test) {} fn main() { take_foo(1_i32); @@ -42,4 +48,6 @@ fn main() { //~^ERROR Boom take_whatever(1_i32); //~^ERROR the trait bound `i32: Whatever` is not satisfied + take_test(()); + //~^ERROR {DoesNotExist} } diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr index 162ddd79fbbd9..11263580b15e2 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr @@ -46,6 +46,14 @@ LL | #[diagnostic::on_unimplemented] | = help: at least one of the `message`, `note` and `label` options are expected +warning: there is no parameter `DoesNotExist` on trait `Test` + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + | +LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + warning: malformed `on_unimplemented` attribute --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32 | @@ -56,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 | LL | take_foo(1_i32); | -------- ^^^^^ the trait `Foo` is not implemented for `i32` @@ -69,7 +77,7 @@ help: this trait has no implementations, consider adding one LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `take_foo` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21 | LL | fn take_foo(_: impl Foo) {} | ^^^ required by this bound in `take_foo` @@ -84,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14 | LL | take_baz(1_i32); | -------- ^^^^^ the trait `Baz` is not implemented for `i32` @@ -97,7 +105,7 @@ help: this trait has no implementations, consider adding one LL | trait Baz {} | ^^^^^^^^^ note: required by a bound in `take_baz` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21 | LL | fn take_baz(_: impl Baz) {} | ^^^ required by this bound in `take_baz` @@ -112,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:15 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15 | LL | take_boom(1_i32); | --------- ^^^^^ the trait `Boom` is not implemented for `i32` @@ -125,7 +133,7 @@ help: this trait has no implementations, consider adding one LL | trait Boom {} | ^^^^^^^^^^ note: required by a bound in `take_boom` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:33:22 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 | LL | fn take_boom(_: impl Boom) {} | ^^^^ required by this bound in `take_boom` @@ -140,7 +148,7 @@ LL | #[diagnostic::on_unimplemented] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Whatever` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:19 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19 | LL | take_whatever(1_i32); | ------------- ^^^^^ the trait `Whatever` is not implemented for `i32` @@ -153,11 +161,39 @@ help: this trait has no implementations, consider adding one LL | trait Whatever {} | ^^^^^^^^^^^^^^ note: required by a bound in `take_whatever` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:26 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26 | LL | fn take_whatever(_: impl Whatever) {} | ^^^^^^^^ required by this bound in `take_whatever` -error: aborting due to 4 previous errors; 10 warnings emitted +warning: there is no parameter `DoesNotExist` on trait `Test` + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + | +LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expect either a generic argument name or `{Self}` as format argument + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: {DoesNotExist} + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15 + | +LL | take_test(()); + | --------- ^^ the trait `Test` is not implemented for `()` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1 + | +LL | trait Test {} + | ^^^^^^^^^^ +note: required by a bound in `take_test` + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22 + | +LL | fn take_test(_: impl Test) {} + | ^^^^ required by this bound in `take_test` + +error: aborting due to 5 previous errors; 12 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr index 21f02e3a73ba6..82e3b709f70d7 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr @@ -7,6 +7,6 @@ LL | #[diagnostic::on_unimplemented(message = "Foo")] = note: see issue #111996 for more information = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs index 8410b3eb10513..0893f29c4a3b4 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs @@ -8,6 +8,8 @@ note = "custom note" )] #[diagnostic::on_unimplemented(message = "fallback!!")] +//~^ `message` is ignored due to previous definition of `message` +//~| `message` is ignored due to previous definition of `message` #[diagnostic::on_unimplemented(label = "fallback label")] #[diagnostic::on_unimplemented(note = "fallback note")] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr index 906472beb49df..e00846da77be5 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr @@ -7,6 +7,15 @@ LL | if(Self = "()"), = help: only `message`, `note` and `label` are allowed as options = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default +warning: `message` is ignored due to previous definition of `message` + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32 + | +LL | message = "custom message", + | -------------------------- `message` is first declared here +... +LL | #[diagnostic::on_unimplemented(message = "fallback!!")] + | ^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here + warning: malformed `on_unimplemented` attribute --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5 | @@ -16,8 +25,19 @@ LL | if(Self = "()"), = help: only `message`, `note` and `label` are allowed as options = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +warning: `message` is ignored due to previous definition of `message` + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32 + | +LL | message = "custom message", + | -------------------------- `message` is first declared here +... +LL | #[diagnostic::on_unimplemented(message = "fallback!!")] + | ^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0277]: custom message - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:18:15 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:20:15 | LL | takes_foo(()); | --------- ^^ fallback label @@ -28,16 +48,16 @@ LL | takes_foo(()); = note: custom note = note: fallback note help: this trait has no implementations, consider adding one - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:13:1 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:22 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:17:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` -error: aborting due to previous error; 2 warnings emitted +error: aborting due to 1 previous error; 4 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr index 549c7caa72058..de57f7044bffe 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr @@ -19,6 +19,6 @@ note: required by a bound in `takes_foo` LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs new file mode 100644 index 0000000000000..a7becd2f88f6d --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs @@ -0,0 +1,25 @@ +#![feature(diagnostic_namespace)] + +#[diagnostic::on_unimplemented( + message = "first message", + label = "first label", + note = "custom note" +)] +#[diagnostic::on_unimplemented( + message = "second message", + //~^WARN `message` is ignored due to previous definition of `message` + //~|WARN `message` is ignored due to previous definition of `message` + label = "second label", + //~^WARN `label` is ignored due to previous definition of `label` + //~|WARN `label` is ignored due to previous definition of `label` + note = "second note" +)] +trait Foo {} + + +fn takes_foo(_: impl Foo) {} + +fn main() { + takes_foo(()); + //~^ERROR first message +} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr new file mode 100644 index 0000000000000..d30754dcf10d0 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr @@ -0,0 +1,67 @@ +warning: `message` is ignored due to previous definition of `message` + --> $DIR/report_warning_on_duplicated_options.rs:9:5 + | +LL | message = "first message", + | ------------------------- `message` is first declared here +... +LL | message = "second message", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here + | + = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default + +warning: `label` is ignored due to previous definition of `label` + --> $DIR/report_warning_on_duplicated_options.rs:12:5 + | +LL | label = "first label", + | --------------------- `label` is first declared here +... +LL | label = "second label", + | ^^^^^^^^^^^^^^^^^^^^^^ `label` is already declared here + +warning: `message` is ignored due to previous definition of `message` + --> $DIR/report_warning_on_duplicated_options.rs:9:5 + | +LL | message = "first message", + | ------------------------- `message` is first declared here +... +LL | message = "second message", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: `label` is ignored due to previous definition of `label` + --> $DIR/report_warning_on_duplicated_options.rs:12:5 + | +LL | label = "first label", + | --------------------- `label` is first declared here +... +LL | label = "second label", + | ^^^^^^^^^^^^^^^^^^^^^^ `label` is already declared here + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: first message + --> $DIR/report_warning_on_duplicated_options.rs:23:15 + | +LL | takes_foo(()); + | --------- ^^ first label + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is not implemented for `()` + = note: custom note + = note: second note +help: this trait has no implementations, consider adding one + --> $DIR/report_warning_on_duplicated_options.rs:17:1 + | +LL | trait Foo {} + | ^^^^^^^^^ +note: required by a bound in `takes_foo` + --> $DIR/report_warning_on_duplicated_options.rs:20:22 + | +LL | fn takes_foo(_: impl Foo) {} + | ^^^ required by this bound in `takes_foo` + +error: aborting due to 1 previous error; 4 warnings emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/requires_path.stderr b/tests/ui/diagnostic_namespace/requires_path.stderr index ce867621daaf5..5d07d3a22d50e 100644 --- a/tests/ui/diagnostic_namespace/requires_path.stderr +++ b/tests/ui/diagnostic_namespace/requires_path.stderr @@ -4,5 +4,5 @@ error: cannot find attribute `diagnostic` in this scope LL | #[diagnostic] | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs index 6040f3f30a7b5..ffc37b260a6bc 100644 --- a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs +++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs @@ -29,7 +29,7 @@ fn main() { doc_hidden_fields::B::default().hey; //~^ ERROR no field `hey` on type `B` //~| NOTE unknown field - //~| NOTE available fields are: `bye` + //~| NOTE available field is: `bye` C::default().hey; //~^ ERROR no field `hey` on type `C` diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr index b7fe3b79b475b..55f6d0fa32380 100644 --- a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr +++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr @@ -12,7 +12,7 @@ error[E0609]: no field `hey` on type `B` LL | doc_hidden_fields::B::default().hey; | ^^^ unknown field | - = note: available fields are: `bye` + = note: available field is: `bye` error[E0609]: no field `hey` on type `C` --> $DIR/dont-suggest-doc-hidden-fields.rs:34:18 diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr index 7066d29760e7c..473c9a339fc25 100644 --- a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr @@ -5,9 +5,13 @@ LL | environment!(); | -------------- in this macro invocation ... LL | const CRATE: Crate = Crate { fiel: () }; - | ^^^^ help: a field with a similar name exists: `field` + | ^^^^ unknown field | = note: this error originates in the macro `environment` (in Nightly builds, run with -Z macro-backtrace for more info) +help: a field with a similar name exists + | +LL | const CRATE: Crate = Crate { field: () }; + | ~~~~~ error[E0609]: no field `field` on type `Compound` --> $DIR/dont-suggest-hygienic-fields.rs:24:16 diff --git a/tests/ui/did_you_mean/issue-114112.stderr b/tests/ui/did_you_mean/issue-114112.stderr index d76b5f72e30cf..071c9614f13b6 100644 --- a/tests/ui/did_you_mean/issue-114112.stderr +++ b/tests/ui/did_you_mean/issue-114112.stderr @@ -9,5 +9,5 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | E::::A(v) => { | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr index b69fcd5d32a60..9cbce93c8e009 100644 --- a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr +++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr @@ -10,6 +10,6 @@ LL | f1.foo(1usize); > > -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr index 2d50c09645d7c..6ac0bf21e4aca 100644 --- a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr +++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -14,6 +14,6 @@ LL | f1.foo(1usize); > > -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/did_you_mean/issue-34337.stderr b/tests/ui/did_you_mean/issue-34337.stderr index 1f18ea8923bda..c727a565dbe34 100644 --- a/tests/ui/did_you_mean/issue-34337.stderr +++ b/tests/ui/did_you_mean/issue-34337.stderr @@ -7,6 +7,6 @@ LL | get(&mut key); | cannot borrow as mutable | help: try removing `&mut` here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-36798.stderr b/tests/ui/did_you_mean/issue-36798.stderr index 98876e305ca09..70aa3c32bfbf4 100644 --- a/tests/ui/did_you_mean/issue-36798.stderr +++ b/tests/ui/did_you_mean/issue-36798.stderr @@ -2,8 +2,13 @@ error[E0609]: no field `baz` on type `Foo` --> $DIR/issue-36798.rs:7:7 | LL | f.baz; - | ^^^ help: a field with a similar name exists: `bar` + | ^^^ unknown field + | +help: a field with a similar name exists + | +LL | f.bar; + | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/did_you_mean/issue-36798_unknown_field.stderr b/tests/ui/did_you_mean/issue-36798_unknown_field.stderr index 2ed0a09240062..733af860f58e3 100644 --- a/tests/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/tests/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -4,8 +4,8 @@ error[E0609]: no field `zz` on type `Foo` LL | f.zz; | ^^ unknown field | - = note: available fields are: `bar` + = note: available field is: `bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/did_you_mean/issue-37139.stderr b/tests/ui/did_you_mean/issue-37139.stderr index dc1bdfaaed568..a07d83b31db1d 100644 --- a/tests/ui/did_you_mean/issue-37139.stderr +++ b/tests/ui/did_you_mean/issue-37139.stderr @@ -7,6 +7,6 @@ LL | test(&mut x); | cannot borrow as mutable | help: try removing `&mut` here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-38147-1.stderr b/tests/ui/did_you_mean/issue-38147-1.stderr index 790ad54a54789..a0392113ab155 100644 --- a/tests/ui/did_you_mean/issue-38147-1.stderr +++ b/tests/ui/did_you_mean/issue-38147-1.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | fn f(&mut self) { | ~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-38147-3.stderr b/tests/ui/did_you_mean/issue-38147-3.stderr index 5b32b5a782c07..1d92f7742c178 100644 --- a/tests/ui/did_you_mean/issue-38147-3.stderr +++ b/tests/ui/did_you_mean/issue-38147-3.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | s: &'a mut String | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-38147-4.stderr b/tests/ui/did_you_mean/issue-38147-4.stderr index 38ab3c54d01ba..57309172194f4 100644 --- a/tests/ui/did_you_mean/issue-38147-4.stderr +++ b/tests/ui/did_you_mean/issue-38147-4.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | fn f(x: usize, f: &mut Foo) { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-40823.stderr b/tests/ui/did_you_mean/issue-40823.stderr index 6f1ed35543820..d9f69eb47d241 100644 --- a/tests/ui/did_you_mean/issue-40823.stderr +++ b/tests/ui/did_you_mean/issue-40823.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | let mut buf = &mut [1, 2, 3, 4]; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr b/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr index c20bbce3f24a9..d60db01a4653d 100644 --- a/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr +++ b/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr @@ -2,7 +2,12 @@ error[E0560]: struct `Demo` has no field named `inocently_mispellable` --> $DIR/issue-42599_available_fields_note.rs:16:39 | LL | Self { secret_integer: 2, inocently_mispellable: () } - | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` + | ^^^^^^^^^^^^^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | Self { secret_integer: 2, innocently_misspellable: () } + | ~~~~~~~~~~~~~~~~~~~~~~~ error[E0560]: struct `Demo` has no field named `egregiously_nonexistent_field` --> $DIR/issue-42599_available_fields_note.rs:21:39 @@ -16,7 +21,12 @@ error[E0609]: no field `inocently_mispellable` on type `Demo` --> $DIR/issue-42599_available_fields_note.rs:32:41 | LL | let innocent_field_misaccess = demo.inocently_mispellable; - | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` + | ^^^^^^^^^^^^^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let innocent_field_misaccess = demo.innocently_misspellable; + | ~~~~~~~~~~~~~~~~~~~~~~~ error[E0609]: no field `egregiously_nonexistent_field` on type `Demo` --> $DIR/issue-42599_available_fields_note.rs:35:42 diff --git a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr index 589b2c3784926..92cbc03e0dd78 100644 --- a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr +++ b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr @@ -9,5 +9,5 @@ help: to omit remaining fields, use `..` LL | PersonalityInventory { expressivity: exp, .. } => exp | ~~ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/did_you_mean/println-typo.stderr b/tests/ui/did_you_mean/println-typo.stderr index 43b7b1894e2ae..a1e0b1f1ba4f1 100644 --- a/tests/ui/did_you_mean/println-typo.stderr +++ b/tests/ui/did_you_mean/println-typo.stderr @@ -7,5 +7,5 @@ LL | prinltn!(); | = note: similarly named macro `println` defined here -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/did_you_mean/pub-macro-rules.stderr b/tests/ui/did_you_mean/pub-macro-rules.stderr index 0bde5783b8cc6..ba9020460cea3 100644 --- a/tests/ui/did_you_mean/pub-macro-rules.stderr +++ b/tests/ui/did_you_mean/pub-macro-rules.stderr @@ -4,5 +4,5 @@ error: can't qualify macro_rules invocation with `pub` LL | pub macro_rules! foo { | ^^^ help: try exporting the macro: `#[macro_export]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/did_you_mean/recursion_limit.stderr b/tests/ui/did_you_mean/recursion_limit.stderr index 70e49566ac0d9..bff57a63deb16 100644 --- a/tests/ui/did_you_mean/recursion_limit.stderr +++ b/tests/ui/did_you_mean/recursion_limit.stderr @@ -56,6 +56,6 @@ note: required by a bound in `is_send` LL | fn is_send() { } | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/did_you_mean/recursion_limit_macro.stderr b/tests/ui/did_you_mean/recursion_limit_macro.stderr index 71855cf1e20f3..dc4189ed9ab68 100644 --- a/tests/ui/did_you_mean/recursion_limit_macro.stderr +++ b/tests/ui/did_you_mean/recursion_limit_macro.stderr @@ -10,5 +10,5 @@ LL | recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9); = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_macro`) = note: this error originates in the macro `recurse` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr b/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr index 730836a40c26a..2ca6436bb9997 100644 --- a/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr +++ b/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr @@ -13,6 +13,6 @@ help: try replacing `_` with the types in the corresponding trait method signatu LL | fn bar(i: i32, t: usize, s: &()) -> (usize, i32) { | ~~~ ~~~~~ ~~~ ~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/directory_ownership/macro-expanded-mod.stderr b/tests/ui/directory_ownership/macro-expanded-mod.stderr index 8976341b1ad97..2cacd52b94ef6 100644 --- a/tests/ui/directory_ownership/macro-expanded-mod.stderr +++ b/tests/ui/directory_ownership/macro-expanded-mod.stderr @@ -9,5 +9,5 @@ LL | mod_decl!(foo); | = note: this error originates in the macro `mod_decl` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/directory_ownership/non-inline-mod-restriction.stderr b/tests/ui/directory_ownership/non-inline-mod-restriction.stderr index 64189bee43f6e..882c8652520b0 100644 --- a/tests/ui/directory_ownership/non-inline-mod-restriction.stderr +++ b/tests/ui/directory_ownership/non-inline-mod-restriction.stderr @@ -4,5 +4,5 @@ error: cannot declare a non-inline module inside a block unless it has a path at LL | mod foo; | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr index 596ad4bf784bb..45c7a8bb475a6 100644 --- a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr @@ -12,6 +12,6 @@ help: consider borrowing the pattern binding LL | let X { x: ref y } = x; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr index e32a4dd441149..837904cbae072 100644 --- a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr @@ -15,6 +15,6 @@ help: consider borrowing the pattern binding LL | X { x: ref y } => println!("contents: {}", y) | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/diverging-fn-tail-35849.stderr b/tests/ui/diverging-fn-tail-35849.stderr index f5b5a4cccad2c..614f9b9cb5d20 100644 --- a/tests/ui/diverging-fn-tail-35849.stderr +++ b/tests/ui/diverging-fn-tail-35849.stderr @@ -10,6 +10,6 @@ LL | ::std::mem::transmute::(panic!()) = note: expected type `!` found array `[u8; 8]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/does-nothing.stderr b/tests/ui/does-nothing.stderr index dca7923151767..d5ea3626e81c8 100644 --- a/tests/ui/does-nothing.stderr +++ b/tests/ui/does-nothing.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `this_does_nothing_what_the` in this scope LL | fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/dont-suggest-private-trait-method.stderr b/tests/ui/dont-suggest-private-trait-method.stderr index 1492670dc6335..f251ad59a587b 100644 --- a/tests/ui/dont-suggest-private-trait-method.stderr +++ b/tests/ui/dont-suggest-private-trait-method.stderr @@ -7,6 +7,6 @@ LL | struct T; LL | T::new(); | ^^^ function or associated item not found in `T` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/double-type-import.stderr b/tests/ui/double-type-import.stderr index a2f30d82ec38b..8a8fe05ec1928 100644 --- a/tests/ui/double-type-import.stderr +++ b/tests/ui/double-type-import.stderr @@ -8,6 +8,6 @@ LL | use self::bar::X; | = note: `X` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/drop/drop-foreign-fundamental.stderr b/tests/ui/drop/drop-foreign-fundamental.stderr index fbd1ba0859134..a4b322106dfc8 100644 --- a/tests/ui/drop/drop-foreign-fundamental.stderr +++ b/tests/ui/drop/drop-foreign-fundamental.stderr @@ -4,6 +4,6 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums, LL | impl Drop for Pin> { | ^^^^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0120`. diff --git a/tests/ui/dropck/drop-with-active-borrows-1.stderr b/tests/ui/dropck/drop-with-active-borrows-1.stderr index 0409ffa02b1ac..229514c6feef0 100644 --- a/tests/ui/dropck/drop-with-active-borrows-1.stderr +++ b/tests/ui/dropck/drop-with-active-borrows-1.stderr @@ -10,6 +10,6 @@ LL | drop(a); LL | for s in &b { | -- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/dropck/drop-with-active-borrows-2.stderr b/tests/ui/dropck/drop-with-active-borrows-2.stderr index ffec9306b7771..9d5c500f8cc56 100644 --- a/tests/ui/dropck/drop-with-active-borrows-2.stderr +++ b/tests/ui/dropck/drop-with-active-borrows-2.stderr @@ -7,6 +7,6 @@ LL | raw_lines.iter().map(|l| l.trim()).collect() | returns a value referencing data owned by the current function | `raw_lines` is borrowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/dropck/dropck-union.stderr b/tests/ui/dropck/dropck-union.stderr index 7d48e9fdcee31..7828aaf23fb6d 100644 --- a/tests/ui/dropck/dropck-union.stderr +++ b/tests/ui/dropck/dropck-union.stderr @@ -11,6 +11,6 @@ LL | } | `v` dropped here while still borrowed | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Wrap` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr index 3e39d15f9b0cd..8f4d301b5cacc 100644 --- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr @@ -6,6 +6,6 @@ LL | let ft = | = note: overflowed on FingerTree>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0320`. diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr index dbb7435447138..4ef7aa61db7a8 100644 --- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr @@ -6,6 +6,6 @@ LL | let ft = | = note: overflowed on FingerTree>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0320`. diff --git a/tests/ui/dropck/dropck_trait_cycle_checked.stderr b/tests/ui/dropck/dropck_trait_cycle_checked.stderr index 4d4f7b9df1179..63fd07a91633d 100644 --- a/tests/ui/dropck/dropck_trait_cycle_checked.stderr +++ b/tests/ui/dropck/dropck_trait_cycle_checked.stderr @@ -8,6 +8,8 @@ LL | o1.set0(&o2); ... LL | } | - `o2` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:112:13 @@ -20,6 +22,8 @@ LL | o1.set1(&o3); ... LL | } | - `o3` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:113:13 @@ -32,6 +36,8 @@ LL | o2.set0(&o2); ... LL | } | - `o2` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:114:13 @@ -44,6 +50,8 @@ LL | o2.set1(&o3); ... LL | } | - `o3` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o1` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:115:13 @@ -56,6 +64,8 @@ LL | o3.set0(&o1); LL | o3.set1(&o2); LL | } | - `o1` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:116:13 @@ -67,6 +77,8 @@ LL | o3.set1(&o2); | ^^^ borrowed value does not live long enough LL | } | - `o2` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error: aborting due to 6 previous errors diff --git a/tests/ui/dropck/explicit-implied-outlives.bad1.stderr b/tests/ui/dropck/explicit-implied-outlives.bad1.stderr index bf6d70e7d3758..82bc7bc082203 100644 --- a/tests/ui/dropck/explicit-implied-outlives.bad1.stderr +++ b/tests/ui/dropck/explicit-implied-outlives.bad1.stderr @@ -10,6 +10,6 @@ note: the implementor must specify the same requirement LL | struct DropMe<'a, T>(&'a T); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/dropck/explicit-implied-outlives.bad2.stderr b/tests/ui/dropck/explicit-implied-outlives.bad2.stderr index 27a15170bddb5..9d2436f058cd0 100644 --- a/tests/ui/dropck/explicit-implied-outlives.bad2.stderr +++ b/tests/ui/dropck/explicit-implied-outlives.bad2.stderr @@ -10,6 +10,6 @@ note: the implementor must specify the same requirement LL | struct DropMe<'a, T>(&'a T); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/dropck/issue-38868.stderr b/tests/ui/dropck/issue-38868.stderr index ec81c2ea646f8..61fef42fdd26e 100644 --- a/tests/ui/dropck/issue-38868.stderr +++ b/tests/ui/dropck/issue-38868.stderr @@ -11,6 +11,6 @@ note: use the same sequence of generic lifetime, type and const parameters as th LL | pub struct List { | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0366`. diff --git a/tests/ui/dropck/negative.stderr b/tests/ui/dropck/negative.stderr index d613e30b5ea59..886b05e347c9a 100644 --- a/tests/ui/dropck/negative.stderr +++ b/tests/ui/dropck/negative.stderr @@ -4,5 +4,5 @@ error: negative `Drop` impls are not supported LL | impl !Drop for NonDrop {} | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/dropck/relate_lt_in_type_outlives_bound.stderr b/tests/ui/dropck/relate_lt_in_type_outlives_bound.stderr index 3d9685db683f6..9c13b6dc258d3 100644 --- a/tests/ui/dropck/relate_lt_in_type_outlives_bound.stderr +++ b/tests/ui/dropck/relate_lt_in_type_outlives_bound.stderr @@ -10,6 +10,6 @@ note: the implementor must specify the same requirement LL | struct Wrapper<'a, T>(&'a T) | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/dropck/reservation.stderr b/tests/ui/dropck/reservation.stderr index 19325d6ed4401..a6ebf158a075d 100644 --- a/tests/ui/dropck/reservation.stderr +++ b/tests/ui/dropck/reservation.stderr @@ -4,5 +4,5 @@ error: reservation `Drop` impls are not supported LL | impl Drop for ReservedDrop { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/dropck/transitive-outlives.bad.stderr b/tests/ui/dropck/transitive-outlives.bad.stderr index da5088b27b414..9ecc4841dce53 100644 --- a/tests/ui/dropck/transitive-outlives.bad.stderr +++ b/tests/ui/dropck/transitive-outlives.bad.stderr @@ -10,6 +10,6 @@ note: the implementor must specify the same requirement LL | struct DropMe<'a, 'b: 'a, 'c: 'b>(PhantomData<&'a ()>, PhantomData<&'b ()>, PhantomData<&'c ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/dst/dst-bad-assign-2.stderr b/tests/ui/dst/dst-bad-assign-2.stderr index 6c9e2971c6d6f..bca22036fb815 100644 --- a/tests/ui/dst/dst-bad-assign-2.stderr +++ b/tests/ui/dst/dst-bad-assign-2.stderr @@ -7,6 +7,6 @@ LL | f5.ptr = *z; = help: the trait `Sized` is not implemented for `dyn ToBar` = note: the left-hand-side of an assignment must have a statically known size -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-bad-deep-2.stderr b/tests/ui/dst/dst-bad-deep-2.stderr index b22850814109a..c7e9854340f09 100644 --- a/tests/ui/dst/dst-bad-deep-2.stderr +++ b/tests/ui/dst/dst-bad-deep-2.stderr @@ -9,6 +9,6 @@ LL | let h: &(([isize],),) = &(*g,); = note: required because it appears within the type `(([isize],),)` = note: tuples must have a statically known size to be initialized -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-bad-deep.stderr b/tests/ui/dst/dst-bad-deep.stderr index 98db79591152f..1b0f9738ab09a 100644 --- a/tests/ui/dst/dst-bad-deep.stderr +++ b/tests/ui/dst/dst-bad-deep.stderr @@ -12,6 +12,6 @@ LL | struct Fat { | ^^^ = note: structs must have a statically known size to be initialized -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/issue-113447.stderr b/tests/ui/dst/issue-113447.stderr index 240553a675bfe..266eb228046a2 100644 --- a/tests/ui/dst/issue-113447.stderr +++ b/tests/ui/dst/issue-113447.stderr @@ -20,6 +20,6 @@ help: convert the array to a `&[u8]` slice instead LL | let _ = &[0u8] == &[0xAA][..]; | + ++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/duplicate/dupe-symbols-1.stderr b/tests/ui/duplicate/dupe-symbols-1.stderr index 933ed5e89e58b..03ebc9d6e7a92 100644 --- a/tests/ui/duplicate/dupe-symbols-1.stderr +++ b/tests/ui/duplicate/dupe-symbols-1.stderr @@ -4,5 +4,5 @@ error: symbol `fail` is already defined LL | pub fn b() { | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/dupe-symbols-2.stderr b/tests/ui/duplicate/dupe-symbols-2.stderr index b132eae4b88d7..091c3051e7c0a 100644 --- a/tests/ui/duplicate/dupe-symbols-2.stderr +++ b/tests/ui/duplicate/dupe-symbols-2.stderr @@ -4,5 +4,5 @@ error: symbol `fail` is already defined LL | pub extern "C" fn fail() { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/dupe-symbols-3.stderr b/tests/ui/duplicate/dupe-symbols-3.stderr index 6300b4908d196..9417f8817a87f 100644 --- a/tests/ui/duplicate/dupe-symbols-3.stderr +++ b/tests/ui/duplicate/dupe-symbols-3.stderr @@ -4,5 +4,5 @@ error: symbol `fail` is already defined LL | pub fn fail() { | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/dupe-symbols-4.stderr b/tests/ui/duplicate/dupe-symbols-4.stderr index 1407a4883e16e..4c5f1e7867f50 100644 --- a/tests/ui/duplicate/dupe-symbols-4.stderr +++ b/tests/ui/duplicate/dupe-symbols-4.stderr @@ -4,5 +4,5 @@ error: symbol `fail` is already defined LL | fn fail(self) {} | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/dupe-symbols-5.stderr b/tests/ui/duplicate/dupe-symbols-5.stderr index 558f868a0c621..74c296e33a6f2 100644 --- a/tests/ui/duplicate/dupe-symbols-5.stderr +++ b/tests/ui/duplicate/dupe-symbols-5.stderr @@ -4,5 +4,5 @@ error: symbol `fail` is already defined LL | pub fn b() { | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/dupe-symbols-6.stderr b/tests/ui/duplicate/dupe-symbols-6.stderr index 6692a63dce8f9..2be68132787c0 100644 --- a/tests/ui/duplicate/dupe-symbols-6.stderr +++ b/tests/ui/duplicate/dupe-symbols-6.stderr @@ -4,5 +4,5 @@ error: symbol `fail` is already defined LL | static HELLO_TWICE: u16 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/dupe-symbols-7.stderr b/tests/ui/duplicate/dupe-symbols-7.stderr index cd5147c0e1530..23f74ef750925 100644 --- a/tests/ui/duplicate/dupe-symbols-7.stderr +++ b/tests/ui/duplicate/dupe-symbols-7.stderr @@ -6,5 +6,5 @@ LL | fn main(){} | = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/dupe-symbols-8.stderr b/tests/ui/duplicate/dupe-symbols-8.stderr index 8d6a79e12d9e8..67eb0bc71a92f 100644 --- a/tests/ui/duplicate/dupe-symbols-8.stderr +++ b/tests/ui/duplicate/dupe-symbols-8.stderr @@ -6,5 +6,5 @@ LL | fn main() { | = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/duplicate-check-macro-exports.stderr b/tests/ui/duplicate/duplicate-check-macro-exports.stderr index ba723b38bfada..eff19c09062f0 100644 --- a/tests/ui/duplicate/duplicate-check-macro-exports.stderr +++ b/tests/ui/duplicate/duplicate-check-macro-exports.stderr @@ -13,6 +13,6 @@ help: you can use `as` to change the binding name of the import LL | pub use std::panic as other_panic; | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/duplicate/duplicate-parameter.stderr b/tests/ui/duplicate/duplicate-parameter.stderr index f3ef0bcf3a056..413d8b6f8a4db 100644 --- a/tests/ui/duplicate/duplicate-parameter.stderr +++ b/tests/ui/duplicate/duplicate-parameter.stderr @@ -4,6 +4,6 @@ error[E0415]: identifier `a` is bound more than once in this parameter list LL | fn f(a: isize, a: isize) {} | ^ used as parameter more than once -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0415`. diff --git a/tests/ui/duplicate_entry_error.stderr b/tests/ui/duplicate_entry_error.stderr index 6d078dfbd2053..592640a884c9a 100644 --- a/tests/ui/duplicate_entry_error.stderr +++ b/tests/ui/duplicate_entry_error.stderr @@ -8,6 +8,6 @@ LL | fn panic_impl(info: &PanicInfo) -> ! { = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib = note: second definition in the local crate (`duplicate_entry_error`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/dyn-keyword/dyn-angle-brackets.stderr b/tests/ui/dyn-keyword/dyn-angle-brackets.stderr index 0bb764d712e23..0b194cb8364c6 100644 --- a/tests/ui/dyn-keyword/dyn-angle-brackets.stderr +++ b/tests/ui/dyn-keyword/dyn-angle-brackets.stderr @@ -16,5 +16,5 @@ help: use `dyn` LL | ::fmt(self, f) | +++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/dyn-star/align.normal.stderr b/tests/ui/dyn-star/align.normal.stderr index 42fa4fd6f00ce..d3ee0d3e550ec 100644 --- a/tests/ui/dyn-star/align.normal.stderr +++ b/tests/ui/dyn-star/align.normal.stderr @@ -15,6 +15,6 @@ LL | let x = AlignedUsize(12) as dyn* Debug; | = help: the trait `PointerLike` is not implemented for `AlignedUsize` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/align.over_aligned.stderr b/tests/ui/dyn-star/align.over_aligned.stderr index 42fa4fd6f00ce..d3ee0d3e550ec 100644 --- a/tests/ui/dyn-star/align.over_aligned.stderr +++ b/tests/ui/dyn-star/align.over_aligned.stderr @@ -15,6 +15,6 @@ LL | let x = AlignedUsize(12) as dyn* Debug; | = help: the trait `PointerLike` is not implemented for `AlignedUsize` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr index ba42f619a5461..f291b1e2ca3d9 100644 --- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr @@ -10,6 +10,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn polymorphic(t: &T) where &T: PointerLike { | +++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr index ba42f619a5461..f291b1e2ca3d9 100644 --- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr @@ -10,6 +10,6 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | fn polymorphic(t: &T) where &T: PointerLike { | +++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/check-size-at-cast.stderr b/tests/ui/dyn-star/check-size-at-cast.stderr index e60b5c56ff049..b402403ee6fa1 100644 --- a/tests/ui/dyn-star/check-size-at-cast.stderr +++ b/tests/ui/dyn-star/check-size-at-cast.stderr @@ -6,6 +6,6 @@ LL | let i = [1, 2, 3, 4] as dyn* Debug; | = help: the trait `PointerLike` is not implemented for `[i32; 4]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/dyn-to-rigid.stderr b/tests/ui/dyn-star/dyn-to-rigid.stderr index 588e6d97e5ca3..b198c5245dea0 100644 --- a/tests/ui/dyn-star/dyn-to-rigid.stderr +++ b/tests/ui/dyn-star/dyn-to-rigid.stderr @@ -4,6 +4,6 @@ error[E0606]: casting `(dyn* Tr + 'static)` as `usize` is invalid LL | x as usize | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/dyn-star/error.stderr b/tests/ui/dyn-star/error.stderr index e039bb6f1c82b..a9f4a05451927 100644 --- a/tests/ui/dyn-star/error.stderr +++ b/tests/ui/dyn-star/error.stderr @@ -10,6 +10,6 @@ help: this trait has no implementations, consider adding one LL | trait Foo {} | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/feature-gate-dyn_star.stderr b/tests/ui/dyn-star/feature-gate-dyn_star.stderr index 342e71c3a3a92..d8fe25b84bd3e 100644 --- a/tests/ui/dyn-star/feature-gate-dyn_star.stderr +++ b/tests/ui/dyn-star/feature-gate-dyn_star.stderr @@ -7,6 +7,6 @@ LL | pub fn dyn_star_parameter(_: &dyn* Send) { = note: see issue #102425 for more information = help: add `#![feature(dyn_star)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/dyn-star/gated-span.stderr b/tests/ui/dyn-star/gated-span.stderr index 626b6cd1b7f0e..da5afa2d57840 100644 --- a/tests/ui/dyn-star/gated-span.stderr +++ b/tests/ui/dyn-star/gated-span.stderr @@ -7,6 +7,6 @@ LL | t!(dyn* Send); = note: see issue #102425 for more information = help: add `#![feature(dyn_star)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/dyn-star/no-explicit-dyn-star.stderr b/tests/ui/dyn-star/no-explicit-dyn-star.stderr index 49706fae19e23..641404aa09e20 100644 --- a/tests/ui/dyn-star/no-explicit-dyn-star.stderr +++ b/tests/ui/dyn-star/no-explicit-dyn-star.stderr @@ -4,6 +4,6 @@ error[E0606]: casting `usize` as `dyn* std::fmt::Display` is invalid LL | dyn_star_foreign::require_dyn_star_display(1usize as _); | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/dyn-star/no-implicit-dyn-star.stderr b/tests/ui/dyn-star/no-implicit-dyn-star.stderr index 66e1b9a092c36..06c7bcc574825 100644 --- a/tests/ui/dyn-star/no-implicit-dyn-star.stderr +++ b/tests/ui/dyn-star/no-implicit-dyn-star.stderr @@ -14,6 +14,6 @@ note: function defined here LL | pub fn require_dyn_star_display(_: dyn* Display) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs index a4eb669e32104..0201c8897065c 100644 --- a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs +++ b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs @@ -1,4 +1,4 @@ -#![feature(dyn_star, trait_upcasting)] +#![feature(dyn_star)] //~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes trait A: B {} diff --git a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr index c7f1a4b9ae113..7e2cf661369b9 100644 --- a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr +++ b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr @@ -1,7 +1,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/no-unsize-coerce-dyn-trait.rs:1:12 | -LL | #![feature(dyn_star, trait_upcasting)] +LL | #![feature(dyn_star)] | ^^^^^^^^ | = note: see issue #102425 for more information @@ -18,6 +18,6 @@ LL | let y: Box = x; = note: expected struct `Box` found struct `Box` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/dyn-star/param-env-region-infer.current.stderr b/tests/ui/dyn-star/param-env-region-infer.current.stderr index b982be4519671..b50117c1efb40 100644 --- a/tests/ui/dyn-star/param-env-region-infer.current.stderr +++ b/tests/ui/dyn-star/param-env-region-infer.current.stderr @@ -4,6 +4,6 @@ error[E0282]: type annotations needed LL | t as _ | ^ cannot infer type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr b/tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr index f6444a60a4654..b3274580afe0e 100644 --- a/tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr +++ b/tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr @@ -4,6 +4,6 @@ error[E0605]: non-primitive cast: `i32` as `&dyn* Debug` LL | let i = 42 as &dyn* Debug; | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/dyn-star/upcast.rs b/tests/ui/dyn-star/upcast.rs index c667ac143a395..7748cdda943c2 100644 --- a/tests/ui/dyn-star/upcast.rs +++ b/tests/ui/dyn-star/upcast.rs @@ -1,6 +1,6 @@ // known-bug: #104800 -#![feature(dyn_star, trait_upcasting)] +#![feature(dyn_star)] trait Foo: Bar { fn hello(&self); diff --git a/tests/ui/dyn-star/upcast.stderr b/tests/ui/dyn-star/upcast.stderr index 8b34c7f8b710f..bdf77da713a0e 100644 --- a/tests/ui/dyn-star/upcast.stderr +++ b/tests/ui/dyn-star/upcast.stderr @@ -1,7 +1,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/upcast.rs:3:12 | -LL | #![feature(dyn_star, trait_upcasting)] +LL | #![feature(dyn_star)] | ^^^^^^^^ | = note: see issue #102425 for more information @@ -15,6 +15,6 @@ LL | let w: dyn* Bar = w; | = help: the trait `PointerLike` is not implemented for `dyn* Foo` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/editions/dyn-trait-sugg-2021.stderr b/tests/ui/editions/dyn-trait-sugg-2021.stderr index 8c68dec1df7e4..8a65fea11c95c 100644 --- a/tests/ui/editions/dyn-trait-sugg-2021.stderr +++ b/tests/ui/editions/dyn-trait-sugg-2021.stderr @@ -9,6 +9,6 @@ help: add `dyn` keyword before this trait LL | ::hi(123); | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/editions/edition-imports-2015.stderr b/tests/ui/editions/edition-imports-2015.stderr index 3f38e6f8e8036..606843361f875 100644 --- a/tests/ui/editions/edition-imports-2015.stderr +++ b/tests/ui/editions/edition-imports-2015.stderr @@ -6,5 +6,5 @@ LL | gen_glob!(); | = note: this error originates in the macro `gen_glob` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/editions/edition-imports-2018.stderr b/tests/ui/editions/edition-imports-2018.stderr index e7f760e49bcc0..4776478b9766b 100644 --- a/tests/ui/editions/edition-imports-2018.stderr +++ b/tests/ui/editions/edition-imports-2018.stderr @@ -6,5 +6,5 @@ LL | gen_glob!(); | = note: this error originates in the macro `gen_glob` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/editions/edition-imports-virtual-2015-gated.stderr b/tests/ui/editions/edition-imports-virtual-2015-gated.stderr index e4bdd28213ea4..83c648e54aa16 100644 --- a/tests/ui/editions/edition-imports-virtual-2015-gated.stderr +++ b/tests/ui/editions/edition-imports-virtual-2015-gated.stderr @@ -6,6 +6,6 @@ LL | gen_gated!(); | = note: this error originates in the macro `gen_gated` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/editions/edition-keywords-2015-2018-expansion.stderr b/tests/ui/editions/edition-keywords-2015-2018-expansion.stderr index 570bbac2b21f6..c66ccf1ba78a0 100644 --- a/tests/ui/editions/edition-keywords-2015-2018-expansion.stderr +++ b/tests/ui/editions/edition-keywords-2015-2018-expansion.stderr @@ -11,5 +11,5 @@ help: escape `async` to use it as an identifier LL | () => (pub fn r#async() {}) | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/editions/edition-keywords-2018-2018-expansion.stderr b/tests/ui/editions/edition-keywords-2018-2018-expansion.stderr index 69f275746bdc4..6bfc06ad7996b 100644 --- a/tests/ui/editions/edition-keywords-2018-2018-expansion.stderr +++ b/tests/ui/editions/edition-keywords-2018-2018-expansion.stderr @@ -11,5 +11,5 @@ help: escape `async` to use it as an identifier LL | () => (pub fn r#async() {}) | ++ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/editions/edition-raw-pointer-method-2015.stderr b/tests/ui/editions/edition-raw-pointer-method-2015.stderr index 612dd17e71efc..3d8b3f633ce8c 100644 --- a/tests/ui/editions/edition-raw-pointer-method-2015.stderr +++ b/tests/ui/editions/edition-raw-pointer-method-2015.stderr @@ -13,5 +13,5 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(tyvar_behind_raw_pointer)]` implied by `#[deny(warnings)]` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/editions/edition-raw-pointer-method-2018.stderr b/tests/ui/editions/edition-raw-pointer-method-2018.stderr index b9afa0133cac3..663843ad7bc78 100644 --- a/tests/ui/editions/edition-raw-pointer-method-2018.stderr +++ b/tests/ui/editions/edition-raw-pointer-method-2018.stderr @@ -4,6 +4,6 @@ error[E0699]: cannot call a method on a raw pointer with an unknown pointee type LL | let _ = y.is_null(); | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0699`. diff --git a/tests/ui/elide-errors-on-mismatched-tuple.stderr b/tests/ui/elide-errors-on-mismatched-tuple.stderr index e0537ff6faaf8..f852a223b425f 100644 --- a/tests/ui/elide-errors-on-mismatched-tuple.stderr +++ b/tests/ui/elide-errors-on-mismatched-tuple.stderr @@ -9,6 +9,6 @@ LL | let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, shou = note: expected tuple `(A, A)` found tuple `(_, _, _)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/elided-test.stderr b/tests/ui/elided-test.stderr index c74c307c492fe..e323b8ba7eadc 100644 --- a/tests/ui/elided-test.stderr +++ b/tests/ui/elided-test.stderr @@ -4,6 +4,6 @@ error[E0601]: `main` function not found in crate `elided_test` LL | } | ^ consider adding a `main` function to `$DIR/elided-test.rs` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/empty/empty-comment.stderr b/tests/ui/empty/empty-comment.stderr index 7cc8d8fe9229a..07a1d9b45c760 100644 --- a/tests/ui/empty/empty-comment.stderr +++ b/tests/ui/empty/empty-comment.stderr @@ -13,5 +13,5 @@ note: while trying to match meta-variable `$fmt:expr` LL | ($fmt:expr) => (print!(concat!($fmt, "\n"))); | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/empty/empty-linkname.stderr b/tests/ui/empty/empty-linkname.stderr index adcf3670d1d71..9fbcbc3ca9dc8 100644 --- a/tests/ui/empty/empty-linkname.stderr +++ b/tests/ui/empty/empty-linkname.stderr @@ -4,6 +4,6 @@ error[E0454]: link name must not be empty LL | #[link(name = "")] | ^^ empty link name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0454`. diff --git a/tests/ui/empty/empty-macro-use.stderr b/tests/ui/empty/empty-macro-use.stderr index 5d552e4c40846..cdf3ff83cc38c 100644 --- a/tests/ui/empty/empty-macro-use.stderr +++ b/tests/ui/empty/empty-macro-use.stderr @@ -9,5 +9,5 @@ help: consider importing this macro LL + use two_macros::macro_two; | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/empty/empty-never-array.stderr b/tests/ui/empty/empty-never-array.stderr index a488e484b2bf8..0104a43553843 100644 --- a/tests/ui/empty/empty-never-array.stderr +++ b/tests/ui/empty/empty-never-array.stderr @@ -19,6 +19,6 @@ help: you might want to use `let else` to handle the variant that isn't matched LL | let Helper::U(u) = Helper::T(t, []) else { todo!() }; | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/entry-point/imported_main_conflict.stderr b/tests/ui/entry-point/imported_main_conflict.stderr index 8fadd0e19b395..783e9345acf69 100644 --- a/tests/ui/entry-point/imported_main_conflict.stderr +++ b/tests/ui/entry-point/imported_main_conflict.stderr @@ -14,6 +14,6 @@ LL | use m2::*; | ^^^^^ = help: consider adding an explicit import of `main` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr index fabb6ffb02f77..1e7d82a73bc93 100644 --- a/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr +++ b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -6,6 +6,6 @@ LL | use foo::BAR as main; | | | non-function item at `crate::main` is found -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/entry-point/imported_main_const_forbidden.stderr b/tests/ui/entry-point/imported_main_const_forbidden.stderr index 9d8b40dc3c9bc..6f34015a2cd57 100644 --- a/tests/ui/entry-point/imported_main_const_forbidden.stderr +++ b/tests/ui/entry-point/imported_main_const_forbidden.stderr @@ -6,6 +6,6 @@ LL | use foo::BAR as main; | | | non-function item at `crate::main` is found -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr index 3c68933101c87..ce4a94670a784 100644 --- a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr +++ b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr @@ -7,6 +7,6 @@ LL | pub fn boilerplate(x: u8) {} = note: expected signature `fn()` found signature `fn(u8)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr b/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr index 8cee74696295c..3b718c6465bdf 100644 --- a/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr +++ b/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr @@ -4,6 +4,6 @@ error[E0732]: `#[repr(inttype)]` must be specified LL | enum Enum { | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0732`. diff --git a/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr b/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr index 38cfd13b9b88e..054bd25a400ae 100644 --- a/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr +++ b/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr @@ -4,6 +4,6 @@ error[E0322]: explicit impls for the `DiscriminantKind` trait are not permitted LL | impl DiscriminantKind for NewType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `DiscriminantKind` not allowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0322`. diff --git a/tests/ui/enum-discriminant/issue-41394.stderr b/tests/ui/enum-discriminant/issue-41394.stderr index fa95ca9c18a10..e81562df04f54 100644 --- a/tests/ui/enum-discriminant/issue-41394.stderr +++ b/tests/ui/enum-discriminant/issue-41394.stderr @@ -6,6 +6,6 @@ LL | A = "" + 1 | | | &str -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr index 2cb159ee29102..01d83e6ded3d3 100644 --- a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr +++ b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr @@ -6,5 +6,5 @@ LL | Some(T) = std::mem::size_of::(), | = note: type parameters may not be used in enum discriminant values -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr b/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr index 15cd6d30364b9..39f0d086ccbd7 100644 --- a/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr +++ b/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr @@ -6,5 +6,5 @@ LL | Some(T) = core::mem::size_of::<*mut T>(), | = note: type parameters may not be used in enum discriminant values -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/enum-discriminant/issue-72554.stderr b/tests/ui/enum-discriminant/issue-72554.stderr index d12be539f7c17..381f24d351e9c 100644 --- a/tests/ui/enum-discriminant/issue-72554.stderr +++ b/tests/ui/enum-discriminant/issue-72554.stderr @@ -12,6 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | A(Box) | ++++ + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/enum/enum-and-module-in-same-scope.stderr b/tests/ui/enum/enum-and-module-in-same-scope.stderr index 538898c2f2a6f..0293acd6201b2 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.stderr +++ b/tests/ui/enum/enum-and-module-in-same-scope.stderr @@ -9,6 +9,6 @@ LL | mod Foo { | = note: `Foo` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/enum/enum-discrim-autosizing.stderr b/tests/ui/enum/enum-discrim-autosizing.stderr index be3d7c64e28bd..03c722a68b4cd 100644 --- a/tests/ui/enum/enum-discrim-autosizing.stderr +++ b/tests/ui/enum/enum-discrim-autosizing.stderr @@ -10,6 +10,6 @@ LL | LL | Bu64 = 0x8000_0000_0000_0000 | --------------------- `0` (overflowed from `9223372036854775808`) assigned here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0081`. diff --git a/tests/ui/enum/enum-in-scope.stderr b/tests/ui/enum/enum-in-scope.stderr index 49a01abcbd693..9c0dd8f3dd8d7 100644 --- a/tests/ui/enum/enum-in-scope.stderr +++ b/tests/ui/enum/enum-in-scope.stderr @@ -7,6 +7,6 @@ LL | struct hello(isize); LL | let hello = 0; | ^^^^^ cannot be named the same as a tuple struct -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/enum/enum-variant-type-2.stderr b/tests/ui/enum/enum-variant-type-2.stderr index 7e8453c61f62b..216dbda5dd7ad 100644 --- a/tests/ui/enum/enum-variant-type-2.stderr +++ b/tests/ui/enum/enum-variant-type-2.stderr @@ -7,6 +7,6 @@ LL | fn foo(x: Foo::Bar) {} | not a type | help: try using the variant's enum: `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/enum/suggest-default-attribute.stderr b/tests/ui/enum/suggest-default-attribute.stderr index b56d599a78663..fa72db6aaef9d 100644 --- a/tests/ui/enum/suggest-default-attribute.stderr +++ b/tests/ui/enum/suggest-default-attribute.stderr @@ -10,5 +10,5 @@ LL + #[derive(Default)] LL | pub enum Test { | -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0001.stderr b/tests/ui/error-codes/E0001.stderr index 577c49032d799..49bb73e7ba866 100644 --- a/tests/ui/error-codes/E0001.stderr +++ b/tests/ui/error-codes/E0001.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0004-2.stderr b/tests/ui/error-codes/E0004-2.stderr index e829bac196f79..cc4e18f76d01f 100644 --- a/tests/ui/error-codes/E0004-2.stderr +++ b/tests/ui/error-codes/E0004-2.stderr @@ -20,6 +20,6 @@ LL + None | Some(_) => todo!(), LL ~ } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/error-codes/E0004.stderr b/tests/ui/error-codes/E0004.stderr index ced478d65eaec..17e2caa866bb8 100644 --- a/tests/ui/error-codes/E0004.stderr +++ b/tests/ui/error-codes/E0004.stderr @@ -18,6 +18,6 @@ LL ~ Terminator::TalkToMyHand => {}, LL + Terminator::HastaLaVistaBaby => todo!() | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/error-codes/E0005.stderr b/tests/ui/error-codes/E0005.stderr index 4692b66413dff..4be37e2e45497 100644 --- a/tests/ui/error-codes/E0005.stderr +++ b/tests/ui/error-codes/E0005.stderr @@ -12,6 +12,6 @@ help: you might want to use `let else` to handle the variant that isn't matched LL | let Some(y) = x else { todo!() }; | ++++++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/error-codes/E0013.stderr b/tests/ui/error-codes/E0013.stderr index dc22053a63895..b07c8bdb700fe 100644 --- a/tests/ui/error-codes/E0013.stderr +++ b/tests/ui/error-codes/E0013.stderr @@ -6,6 +6,6 @@ LL | const Y: i32 = X; | = help: consider extracting the value of the `static` to a `const`, and referring to that -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/error-codes/E0015.stderr b/tests/ui/error-codes/E0015.stderr index ec1ce47b2ce78..9d892a3e0985d 100644 --- a/tests/ui/error-codes/E0015.stderr +++ b/tests/ui/error-codes/E0015.stderr @@ -6,6 +6,6 @@ LL | const FOO: Option = create_some(); | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/error-codes/E0025.stderr b/tests/ui/error-codes/E0025.stderr index dfec6d0276a59..03347538a7ac3 100644 --- a/tests/ui/error-codes/E0025.stderr +++ b/tests/ui/error-codes/E0025.stderr @@ -6,6 +6,6 @@ LL | let Foo { a: x, a: y, b: 0 } = x; | | | first use of `a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0025`. diff --git a/tests/ui/error-codes/E0026-teach.stderr b/tests/ui/error-codes/E0026-teach.stderr index 3d460490eb3f5..a496a7bdec726 100644 --- a/tests/ui/error-codes/E0026-teach.stderr +++ b/tests/ui/error-codes/E0026-teach.stderr @@ -8,6 +8,6 @@ LL | Thing { x, y, z } => {} If you are using shorthand field patterns but want to refer to the struct field by a different name, you should rename it explicitly. -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0026`. diff --git a/tests/ui/error-codes/E0026.stderr b/tests/ui/error-codes/E0026.stderr index 031481812d0bb..4d0dfbbf1795f 100644 --- a/tests/ui/error-codes/E0026.stderr +++ b/tests/ui/error-codes/E0026.stderr @@ -4,6 +4,6 @@ error[E0026]: struct `Thing` does not have a field named `z` LL | Thing { x, y, z } => {} | ^ struct `Thing` does not have this field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0026`. diff --git a/tests/ui/error-codes/E0029-teach.stderr b/tests/ui/error-codes/E0029-teach.stderr index b89b2e7d11e8b..6b7d19f7b2276 100644 --- a/tests/ui/error-codes/E0029-teach.stderr +++ b/tests/ui/error-codes/E0029-teach.stderr @@ -9,6 +9,6 @@ LL | "hello" ..= "world" => {} | = note: In a match expression, only numbers and characters can be matched against a range. This is because the compiler checks that the range is non-empty at compile-time, and is unable to evaluate arbitrary comparison functions. If you want to capture values of an orderable type between two end-points, you can use a guard. -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0029`. diff --git a/tests/ui/error-codes/E0029.stderr b/tests/ui/error-codes/E0029.stderr index f7250b39d3f91..d596553dc5316 100644 --- a/tests/ui/error-codes/E0029.stderr +++ b/tests/ui/error-codes/E0029.stderr @@ -7,6 +7,6 @@ LL | "hello" ..= "world" => {} | | this is of type `&'static str` but it should be `char` or numeric | this is of type `&'static str` but it should be `char` or numeric -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0029`. diff --git a/tests/ui/error-codes/E0030-teach.stderr b/tests/ui/error-codes/E0030-teach.stderr index 9435cb204bdd6..36200d2b86afa 100644 --- a/tests/ui/error-codes/E0030-teach.stderr +++ b/tests/ui/error-codes/E0030-teach.stderr @@ -6,6 +6,6 @@ LL | 1000 ..= 5 => {} | = note: When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0030`. diff --git a/tests/ui/error-codes/E0030.stderr b/tests/ui/error-codes/E0030.stderr index 1aeca29167875..4e9378dfe1dc4 100644 --- a/tests/ui/error-codes/E0030.stderr +++ b/tests/ui/error-codes/E0030.stderr @@ -4,6 +4,6 @@ error[E0030]: lower range bound must be less than or equal to upper LL | 1000 ..= 5 => {} | ^^^^^^^^^^ lower bound larger than upper bound -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0030`. diff --git a/tests/ui/error-codes/E0033-teach.stderr b/tests/ui/error-codes/E0033-teach.stderr index 31bc6719a562e..303c293442811 100644 --- a/tests/ui/error-codes/E0033-teach.stderr +++ b/tests/ui/error-codes/E0033-teach.stderr @@ -8,6 +8,6 @@ LL | let &invalid = trait_obj; You can read more about trait objects in the Trait Objects section of the Reference: https://doc.rust-lang.org/reference/types.html#trait-objects -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0033`. diff --git a/tests/ui/error-codes/E0033.stderr b/tests/ui/error-codes/E0033.stderr index ab2e780ee624d..b091ad21720f1 100644 --- a/tests/ui/error-codes/E0033.stderr +++ b/tests/ui/error-codes/E0033.stderr @@ -4,6 +4,6 @@ error[E0033]: type `&dyn SomeTrait` cannot be dereferenced LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0033`. diff --git a/tests/ui/error-codes/E0034.stderr b/tests/ui/error-codes/E0034.stderr index da6f221881cec..48b8efcf8a29b 100644 --- a/tests/ui/error-codes/E0034.stderr +++ b/tests/ui/error-codes/E0034.stderr @@ -21,6 +21,6 @@ LL | ::foo() LL | ::foo() | ~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/error-codes/E0038.stderr b/tests/ui/error-codes/E0038.stderr index 3773d6f5234b0..99130396e0282 100644 --- a/tests/ui/error-codes/E0038.stderr +++ b/tests/ui/error-codes/E0038.stderr @@ -13,6 +13,6 @@ LL | fn foo(&self) -> Self; | ^^^^ ...because method `foo` references the `Self` type in its return type = help: consider moving `foo` to another trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/error-codes/E0040.stderr b/tests/ui/error-codes/E0040.stderr index 839be79d28d29..00cccb07c0f55 100644 --- a/tests/ui/error-codes/E0040.stderr +++ b/tests/ui/error-codes/E0040.stderr @@ -9,6 +9,6 @@ help: consider using `drop` function LL | drop(x); | +++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0040`. diff --git a/tests/ui/error-codes/E0044.stderr b/tests/ui/error-codes/E0044.stderr index e889c167b98d2..e38959fda068d 100644 --- a/tests/ui/error-codes/E0044.stderr +++ b/tests/ui/error-codes/E0044.stderr @@ -6,6 +6,6 @@ LL | fn sqrt(f: T) -> T; | = help: replace the type parameters with concrete types like `u32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0044`. diff --git a/tests/ui/error-codes/E0045.stderr b/tests/ui/error-codes/E0045.stderr index fcc613b11b8d1..25b2f2654da15 100644 --- a/tests/ui/error-codes/E0045.stderr +++ b/tests/ui/error-codes/E0045.stderr @@ -4,6 +4,6 @@ error[E0045]: C-variadic function must have a compatible calling convention, lik LL | extern "Rust" { fn foo(x: u8, ...); } | ^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0045`. diff --git a/tests/ui/error-codes/E0054.stderr b/tests/ui/error-codes/E0054.stderr index 0a4adabbaf6dc..be35242ad7253 100644 --- a/tests/ui/error-codes/E0054.stderr +++ b/tests/ui/error-codes/E0054.stderr @@ -9,6 +9,6 @@ help: compare with zero instead LL | let x_is_nonzero = x != 0; | ~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0054`. diff --git a/tests/ui/error-codes/E0055.stderr b/tests/ui/error-codes/E0055.stderr index a52c90962355f..5cdc8b9946991 100644 --- a/tests/ui/error-codes/E0055.stderr +++ b/tests/ui/error-codes/E0055.stderr @@ -6,6 +6,6 @@ LL | ref_foo.foo(); | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`E0055`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0055`. diff --git a/tests/ui/error-codes/E0059.stderr b/tests/ui/error-codes/E0059.stderr index 4f6abb22ab2f0..a7591d2b04bef 100644 --- a/tests/ui/error-codes/E0059.stderr +++ b/tests/ui/error-codes/E0059.stderr @@ -7,6 +7,6 @@ LL | fn foo>(f: F) -> F::Output { f(3) } note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0059`. diff --git a/tests/ui/error-codes/E0060.stderr b/tests/ui/error-codes/E0060.stderr index 934a18d896dc6..88c1f1bbb2a5c 100644 --- a/tests/ui/error-codes/E0060.stderr +++ b/tests/ui/error-codes/E0060.stderr @@ -14,6 +14,6 @@ help: provide the argument LL | unsafe { printf(/* *const u8 */); } | ~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0060`. diff --git a/tests/ui/error-codes/E0062.stderr b/tests/ui/error-codes/E0062.stderr index a3e14099507ce..87c1c595e016d 100644 --- a/tests/ui/error-codes/E0062.stderr +++ b/tests/ui/error-codes/E0062.stderr @@ -6,6 +6,6 @@ LL | x: 0, LL | x: 0, | ^ used more than once -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0062`. diff --git a/tests/ui/error-codes/E0069.stderr b/tests/ui/error-codes/E0069.stderr index ff9bbe01dd529..20ff8c258a004 100644 --- a/tests/ui/error-codes/E0069.stderr +++ b/tests/ui/error-codes/E0069.stderr @@ -6,6 +6,6 @@ LL | fn foo() -> u8 { LL | return; | ^^^^^^ return type is not `()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0069`. diff --git a/tests/ui/error-codes/E0071.stderr b/tests/ui/error-codes/E0071.stderr index 7bd4ddaf26be2..bbd49f43b20d3 100644 --- a/tests/ui/error-codes/E0071.stderr +++ b/tests/ui/error-codes/E0071.stderr @@ -4,6 +4,6 @@ error[E0071]: expected struct, variant or union type, found `Foo` LL | let u = FooAlias { value: 0 }; | ^^^^^^^^ not a struct -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0071`. diff --git a/tests/ui/error-codes/E0075.stderr b/tests/ui/error-codes/E0075.stderr index 3f927726a030f..43e9971e3095d 100644 --- a/tests/ui/error-codes/E0075.stderr +++ b/tests/ui/error-codes/E0075.stderr @@ -4,6 +4,6 @@ error[E0075]: SIMD vector cannot be empty LL | struct Bad; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0075`. diff --git a/tests/ui/error-codes/E0076.stderr b/tests/ui/error-codes/E0076.stderr index 7d4ff87981686..ea3bbf094976f 100644 --- a/tests/ui/error-codes/E0076.stderr +++ b/tests/ui/error-codes/E0076.stderr @@ -4,6 +4,6 @@ error[E0076]: SIMD vector should be homogeneous LL | struct Bad(u16, u32, u32); | ^^^^^^^^^^ SIMD elements must have the same type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0076`. diff --git a/tests/ui/error-codes/E0077.stderr b/tests/ui/error-codes/E0077.stderr index 9a84b2ec4069f..aae4b3f2c2927 100644 --- a/tests/ui/error-codes/E0077.stderr +++ b/tests/ui/error-codes/E0077.stderr @@ -4,6 +4,6 @@ error[E0077]: SIMD vector element type should be a primitive scalar (integer/flo LL | struct Bad(String); | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0077`. diff --git a/tests/ui/error-codes/E0084.stderr b/tests/ui/error-codes/E0084.stderr index e1bda22b8d19a..f1fbe6c2532b1 100644 --- a/tests/ui/error-codes/E0084.stderr +++ b/tests/ui/error-codes/E0084.stderr @@ -6,6 +6,6 @@ LL | #[repr(i32)] LL | enum Foo {} | -------- zero-variant enum -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0084`. diff --git a/tests/ui/error-codes/E0092.stderr b/tests/ui/error-codes/E0092.stderr index 2d590a8e1d706..4ff2e6f077d24 100644 --- a/tests/ui/error-codes/E0092.stderr +++ b/tests/ui/error-codes/E0092.stderr @@ -4,6 +4,6 @@ error[E0092]: unrecognized atomic operation function: `foo` LL | fn atomic_foo(); | ^^^^^^^^^^^^^^^^ unrecognized atomic operation -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0092`. diff --git a/tests/ui/error-codes/E0093.stderr b/tests/ui/error-codes/E0093.stderr index cb0305593a7b4..387e0c55d4d29 100644 --- a/tests/ui/error-codes/E0093.stderr +++ b/tests/ui/error-codes/E0093.stderr @@ -4,6 +4,6 @@ error[E0093]: unrecognized intrinsic function: `foo` LL | fn foo(); | ^^^^^^^^^ unrecognized intrinsic -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0093`. diff --git a/tests/ui/error-codes/E0094.stderr b/tests/ui/error-codes/E0094.stderr index 531cd4c784d33..1bad5bd950ece 100644 --- a/tests/ui/error-codes/E0094.stderr +++ b/tests/ui/error-codes/E0094.stderr @@ -4,6 +4,6 @@ error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 LL | fn size_of() -> usize; | ^^^^^^ expected 1 type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0094`. diff --git a/tests/ui/error-codes/E0109.stderr b/tests/ui/error-codes/E0109.stderr index 8f4cb86de99a0..ab0d4aac74305 100644 --- a/tests/ui/error-codes/E0109.stderr +++ b/tests/ui/error-codes/E0109.stderr @@ -12,6 +12,6 @@ LL - type X = u32; LL + type X = u32; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/error-codes/E0110.stderr b/tests/ui/error-codes/E0110.stderr index 4ce2a0a410ce4..2f51329ba7329 100644 --- a/tests/ui/error-codes/E0110.stderr +++ b/tests/ui/error-codes/E0110.stderr @@ -12,6 +12,6 @@ LL - type X = u32<'static>; LL + type X = u32; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/error-codes/E0116.stderr b/tests/ui/error-codes/E0116.stderr index 8a02768676084..bf215435ba6a0 100644 --- a/tests/ui/error-codes/E0116.stderr +++ b/tests/ui/error-codes/E0116.stderr @@ -6,6 +6,6 @@ LL | impl Vec {} | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0116`. diff --git a/tests/ui/error-codes/E0118.stderr b/tests/ui/error-codes/E0118.stderr index 442f8a4f870f2..0d837aa59ff71 100644 --- a/tests/ui/error-codes/E0118.stderr +++ b/tests/ui/error-codes/E0118.stderr @@ -6,6 +6,6 @@ LL | impl T { | = note: either implement a trait on it or create a newtype to wrap it instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0118`. diff --git a/tests/ui/error-codes/E0119.stderr b/tests/ui/error-codes/E0119.stderr index e08a2c7fcbbd0..838dba081b9ed 100644 --- a/tests/ui/error-codes/E0119.stderr +++ b/tests/ui/error-codes/E0119.stderr @@ -7,6 +7,6 @@ LL | impl MyTrait for T { LL | impl MyTrait for Foo { | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/E0120.stderr b/tests/ui/error-codes/E0120.stderr index 75778f1f94a16..aef777ad06071 100644 --- a/tests/ui/error-codes/E0120.stderr +++ b/tests/ui/error-codes/E0120.stderr @@ -4,6 +4,6 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums, LL | impl Drop for dyn MyTrait { | ^^^^^^^^^^^ must be a struct, enum, or union in the current crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0120`. diff --git a/tests/ui/error-codes/E0124.stderr b/tests/ui/error-codes/E0124.stderr index 73819a89d7533..f33495806e14e 100644 --- a/tests/ui/error-codes/E0124.stderr +++ b/tests/ui/error-codes/E0124.stderr @@ -6,6 +6,6 @@ LL | field1: i32, LL | field1: i32, | ^^^^^^^^^^^ field already declared -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/error-codes/E0128.stderr b/tests/ui/error-codes/E0128.stderr index eb66d46936a85..c1ccb4c9e7440 100644 --- a/tests/ui/error-codes/E0128.stderr +++ b/tests/ui/error-codes/E0128.stderr @@ -4,6 +4,6 @@ error[E0128]: generic parameters with a default cannot use forward declared iden LL | struct Foo { | ^ defaulted generic parameters cannot be forward declared -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/error-codes/E0130.stderr b/tests/ui/error-codes/E0130.stderr index a45571f40a146..a31517218b448 100644 --- a/tests/ui/error-codes/E0130.stderr +++ b/tests/ui/error-codes/E0130.stderr @@ -4,6 +4,6 @@ error[E0130]: patterns aren't allowed in foreign function declarations LL | fn foo((a, b): (u32, u32)); | ^^^^^^ pattern not allowed in foreign function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0130`. diff --git a/tests/ui/error-codes/E0131.stderr b/tests/ui/error-codes/E0131.stderr index 4467e19e95d29..3a485cdf3fdf1 100644 --- a/tests/ui/error-codes/E0131.stderr +++ b/tests/ui/error-codes/E0131.stderr @@ -4,6 +4,6 @@ error[E0131]: `main` function is not allowed to have generic parameters LL | fn main() { | ^^^ `main` cannot have generic parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0131`. diff --git a/tests/ui/error-codes/E0132.stderr b/tests/ui/error-codes/E0132.stderr index d4ddc07b52112..b1990afa3ae18 100644 --- a/tests/ui/error-codes/E0132.stderr +++ b/tests/ui/error-codes/E0132.stderr @@ -4,6 +4,6 @@ error[E0132]: `#[start]` function is not allowed to have type parameters LL | fn f< T >() {} | ^^^^^ `#[start]` function cannot have type parameters -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0132`. diff --git a/tests/ui/error-codes/E0133.mir.stderr b/tests/ui/error-codes/E0133.mir.stderr index b11d5e2c2fc72..f8703ef06335f 100644 --- a/tests/ui/error-codes/E0133.mir.stderr +++ b/tests/ui/error-codes/E0133.mir.stderr @@ -6,6 +6,6 @@ LL | f(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/error-codes/E0133.thir.stderr b/tests/ui/error-codes/E0133.thir.stderr index f1d7aba2aa3b6..fd4d42bcb8b62 100644 --- a/tests/ui/error-codes/E0133.thir.stderr +++ b/tests/ui/error-codes/E0133.thir.stderr @@ -6,6 +6,6 @@ LL | f(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/error-codes/E0138.stderr b/tests/ui/error-codes/E0138.stderr index fa8c39427323c..04877ab4082cb 100644 --- a/tests/ui/error-codes/E0138.stderr +++ b/tests/ui/error-codes/E0138.stderr @@ -7,6 +7,6 @@ LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } LL | fn f(argc: isize, argv: *const *const u8) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `start` functions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0138`. diff --git a/tests/ui/error-codes/E0152.stderr b/tests/ui/error-codes/E0152.stderr index 29f7e4ad683d3..816ba2d569b6b 100644 --- a/tests/ui/error-codes/E0152.stderr +++ b/tests/ui/error-codes/E0152.stderr @@ -8,6 +8,6 @@ LL | struct Foo(T); = note: first definition in `alloc` loaded from SYSROOT/liballoc-*.rlib = note: second definition in the local crate (`E0152`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/error-codes/E0161.base.stderr b/tests/ui/error-codes/E0161.base.stderr index ae82e6702e604..d80de66b24733 100644 --- a/tests/ui/error-codes/E0161.base.stderr +++ b/tests/ui/error-codes/E0161.base.stderr @@ -4,6 +4,6 @@ error[E0161]: cannot move a value of type `dyn Bar` LL | x.f(); | ^ the size of `dyn Bar` cannot be statically determined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0161`. diff --git a/tests/ui/error-codes/E0164.stderr b/tests/ui/error-codes/E0164.stderr index 5a80d6ec31aa9..1ed5b0a8f07f0 100644 --- a/tests/ui/error-codes/E0164.stderr +++ b/tests/ui/error-codes/E0164.stderr @@ -4,6 +4,6 @@ error[E0164]: expected tuple struct or tuple variant, found associated constant LL | Foo::B(i) => i, | ^^^^^^^^^ not a tuple struct or tuple variant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 52f1f30a4087d..625c6685a6144 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -6,6 +6,6 @@ LL | #[derive(Copy)] | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0184`. diff --git a/tests/ui/error-codes/E0185.stderr b/tests/ui/error-codes/E0185.stderr index 8a99c0688e302..40d6ad3f2bdb8 100644 --- a/tests/ui/error-codes/E0185.stderr +++ b/tests/ui/error-codes/E0185.stderr @@ -7,6 +7,6 @@ LL | fn foo(); LL | fn foo(&self) {} | ^^^^^^^^^^^^^ `&self` used in impl -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0185`. diff --git a/tests/ui/error-codes/E0186.stderr b/tests/ui/error-codes/E0186.stderr index 8971d61fc758e..59b210927deb3 100644 --- a/tests/ui/error-codes/E0186.stderr +++ b/tests/ui/error-codes/E0186.stderr @@ -7,6 +7,6 @@ LL | fn foo(&self); LL | fn foo() {} | ^^^^^^^^ expected `&self` in impl -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0186`. diff --git a/tests/ui/error-codes/E0191.stderr b/tests/ui/error-codes/E0191.stderr index 57eda4785a9fc..63974fd6cbbbd 100644 --- a/tests/ui/error-codes/E0191.stderr +++ b/tests/ui/error-codes/E0191.stderr @@ -7,6 +7,6 @@ LL | type Bar; LL | type Foo = dyn Trait; | ^^^^^ help: specify the associated type: `Trait` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/error-codes/E0194.stderr b/tests/ui/error-codes/E0194.stderr index f2c908eea0bb0..25fc1a3b79f4d 100644 --- a/tests/ui/error-codes/E0194.stderr +++ b/tests/ui/error-codes/E0194.stderr @@ -7,6 +7,6 @@ LL | fn do_something(&self) -> T; LL | fn do_something_else(&self, bar: T); | ^ already used -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/error-codes/E0195.stderr b/tests/ui/error-codes/E0195.stderr index 6eaa1750ee355..b88064b7f90b2 100644 --- a/tests/ui/error-codes/E0195.stderr +++ b/tests/ui/error-codes/E0195.stderr @@ -7,6 +7,6 @@ LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str); LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { | ^^^^^^^ lifetimes do not match method in trait -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/error-codes/E0197.stderr b/tests/ui/error-codes/E0197.stderr index 35e1042649ef9..c06777396e87e 100644 --- a/tests/ui/error-codes/E0197.stderr +++ b/tests/ui/error-codes/E0197.stderr @@ -6,6 +6,6 @@ LL | unsafe impl Foo { } | | | unsafe because of this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0197`. diff --git a/tests/ui/error-codes/E0198.stderr b/tests/ui/error-codes/E0198.stderr index bb2efefb427ba..65b4f5364c292 100644 --- a/tests/ui/error-codes/E0198.stderr +++ b/tests/ui/error-codes/E0198.stderr @@ -7,6 +7,6 @@ LL | unsafe impl !Send for Foo { } | | negative because of this | unsafe because of this -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0198`. diff --git a/tests/ui/error-codes/E0199.stderr b/tests/ui/error-codes/E0199.stderr index 68c308b15cc08..a61a18d170bfd 100644 --- a/tests/ui/error-codes/E0199.stderr +++ b/tests/ui/error-codes/E0199.stderr @@ -10,6 +10,6 @@ LL - unsafe impl Bar for Foo { } LL + impl Bar for Foo { } | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0199`. diff --git a/tests/ui/error-codes/E0200.stderr b/tests/ui/error-codes/E0200.stderr index c70a2d4f3d1f1..fe8353deed111 100644 --- a/tests/ui/error-codes/E0200.stderr +++ b/tests/ui/error-codes/E0200.stderr @@ -10,6 +10,6 @@ help: add `unsafe` to this trait implementation LL | unsafe impl Bar for Foo { } | ++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0200`. diff --git a/tests/ui/error-codes/E0206.stderr b/tests/ui/error-codes/E0206.stderr index 60d8d7bfe983d..d19f2e33ac9b2 100644 --- a/tests/ui/error-codes/E0206.stderr +++ b/tests/ui/error-codes/E0206.stderr @@ -4,6 +4,6 @@ error[E0206]: the trait `Copy` cannot be implemented for this type LL | impl Copy for &'static mut Bar { } | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0206`. diff --git a/tests/ui/error-codes/E0207.stderr b/tests/ui/error-codes/E0207.stderr index 5ef51ed86926a..01d7c41854412 100644 --- a/tests/ui/error-codes/E0207.stderr +++ b/tests/ui/error-codes/E0207.stderr @@ -4,6 +4,6 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self LL | impl Foo { | ^ unconstrained type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/error-codes/E0208.stderr b/tests/ui/error-codes/E0208.stderr index 2c7072a7e7626..77b6ceae4dcee 100644 --- a/tests/ui/error-codes/E0208.stderr +++ b/tests/ui/error-codes/E0208.stderr @@ -4,5 +4,5 @@ error: [+, o] LL | struct Foo<'a, T> { | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0214.stderr b/tests/ui/error-codes/E0214.stderr index e0179aac27fb3..76b11f30996ea 100644 --- a/tests/ui/error-codes/E0214.stderr +++ b/tests/ui/error-codes/E0214.stderr @@ -9,6 +9,6 @@ help: use angle brackets instead LL | let v: Vec<&str> = vec!["foo"]; | ~ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/error-codes/E0221.stderr b/tests/ui/error-codes/E0221.stderr index e600acf783446..07e7485b67e03 100644 --- a/tests/ui/error-codes/E0221.stderr +++ b/tests/ui/error-codes/E0221.stderr @@ -28,7 +28,7 @@ LL | fn test() { LL | let _: Self::Err; | ^^^^^^^^^ ambiguous associated type `Err` | - = note: associated type `Self` could derive from `FromStr` + = note: associated type `Err` could derive from `FromStr` help: use fully-qualified syntax to disambiguate | LL | let _: ::Err; diff --git a/tests/ui/error-codes/E0223.stderr b/tests/ui/error-codes/E0223.stderr index 1299ba5f50c15..e985a4c9bf0d9 100644 --- a/tests/ui/error-codes/E0223.stderr +++ b/tests/ui/error-codes/E0223.stderr @@ -4,6 +4,6 @@ error[E0223]: ambiguous associated type LL | let foo: MyTrait::X; | ^^^^^^^^^^ help: use fully-qualified syntax: `::X` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/error-codes/E0227.stderr b/tests/ui/error-codes/E0227.stderr index 26de5b4c40015..c77a2e98af70e 100644 --- a/tests/ui/error-codes/E0227.stderr +++ b/tests/ui/error-codes/E0227.stderr @@ -4,6 +4,6 @@ error[E0227]: ambiguous lifetime bound, explicit lifetime bound required LL | baz: dyn FooBar<'foo, 'bar>, | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0227`. diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr index 46793314bf9f9..e981fb91ce89f 100644 --- a/tests/ui/error-codes/E0229.stderr +++ b/tests/ui/error-codes/E0229.stderr @@ -4,6 +4,6 @@ error[E0229]: associated type bindings are not allowed here LL | fn baz(x: &>::A) {} | ^^^^^ associated type not allowed here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/error-codes/E0252.stderr b/tests/ui/error-codes/E0252.stderr index 2722dfe5e0543..efbb9ec96dee6 100644 --- a/tests/ui/error-codes/E0252.stderr +++ b/tests/ui/error-codes/E0252.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | use bar::baz as other_baz; | ~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/error-codes/E0253.stderr b/tests/ui/error-codes/E0253.stderr index 8f21a0aaba565..4ee36b70fe510 100644 --- a/tests/ui/error-codes/E0253.stderr +++ b/tests/ui/error-codes/E0253.stderr @@ -4,6 +4,6 @@ error[E0253]: `do_something` is not directly importable LL | use foo::MyTrait::do_something; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0253`. diff --git a/tests/ui/error-codes/E0254.stderr b/tests/ui/error-codes/E0254.stderr index b098f8e1a7f49..d89497b2804bf 100644 --- a/tests/ui/error-codes/E0254.stderr +++ b/tests/ui/error-codes/E0254.stderr @@ -13,6 +13,6 @@ help: you can use `as` to change the binding name of the import LL | use foo::alloc as other_alloc; | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/error-codes/E0255.stderr b/tests/ui/error-codes/E0255.stderr index 352c5ba5be095..e5f908217e138 100644 --- a/tests/ui/error-codes/E0255.stderr +++ b/tests/ui/error-codes/E0255.stderr @@ -13,6 +13,6 @@ help: you can use `as` to change the binding name of the import LL | use bar::foo as other_foo; | ~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/error-codes/E0259.stderr b/tests/ui/error-codes/E0259.stderr index 06cbc5b4fb5f2..6e086268fc6d1 100644 --- a/tests/ui/error-codes/E0259.stderr +++ b/tests/ui/error-codes/E0259.stderr @@ -13,6 +13,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate libc as other_alloc; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/error-codes/E0260.stderr b/tests/ui/error-codes/E0260.stderr index 2d3305bd15b0c..35698c6535902 100644 --- a/tests/ui/error-codes/E0260.stderr +++ b/tests/ui/error-codes/E0260.stderr @@ -13,6 +13,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate alloc as other_alloc; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0260`. diff --git a/tests/ui/error-codes/E0262.stderr b/tests/ui/error-codes/E0262.stderr index ad90b7171266e..092db22ed5e16 100644 --- a/tests/ui/error-codes/E0262.stderr +++ b/tests/ui/error-codes/E0262.stderr @@ -4,6 +4,6 @@ error[E0262]: invalid lifetime parameter name: `'static` LL | fn foo<'static>(x: &'static str) { } | ^^^^^^^ 'static is a reserved lifetime name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0262`. diff --git a/tests/ui/error-codes/E0263.stderr b/tests/ui/error-codes/E0263.stderr index e3f9aea296a2c..dcf57d8e3bcc9 100644 --- a/tests/ui/error-codes/E0263.stderr +++ b/tests/ui/error-codes/E0263.stderr @@ -6,6 +6,6 @@ LL | fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { | | | first use of `'a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/error-codes/E0264.stderr b/tests/ui/error-codes/E0264.stderr index e8e35a12cbb49..14a4ffbe31666 100644 --- a/tests/ui/error-codes/E0264.stderr +++ b/tests/ui/error-codes/E0264.stderr @@ -4,6 +4,6 @@ error[E0264]: unknown external lang item: `cake` LL | fn cake(); | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0264`. diff --git a/tests/ui/error-codes/E0267.stderr b/tests/ui/error-codes/E0267.stderr index 1f8657373efec..81f9005d6e6d6 100644 --- a/tests/ui/error-codes/E0267.stderr +++ b/tests/ui/error-codes/E0267.stderr @@ -6,6 +6,6 @@ LL | let w = || { break; }; | | | enclosing closure -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0267`. diff --git a/tests/ui/error-codes/E0268.stderr b/tests/ui/error-codes/E0268.stderr index 6422e8a9490e9..8d03103dafc3a 100644 --- a/tests/ui/error-codes/E0268.stderr +++ b/tests/ui/error-codes/E0268.stderr @@ -4,6 +4,6 @@ error[E0268]: `break` outside of a loop or labeled block LL | break; | ^^^^^ cannot `break` outside of a loop or labeled block -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/error-codes/E0271.stderr b/tests/ui/error-codes/E0271.stderr index 1e2f4383459e2..0e456eb0d500a 100644 --- a/tests/ui/error-codes/E0271.stderr +++ b/tests/ui/error-codes/E0271.stderr @@ -17,6 +17,6 @@ note: required by a bound in `foo` LL | fn foo(t: T) where T: Trait { | ^^^^^^^^^^^^^^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/error-codes/E0275.stderr b/tests/ui/error-codes/E0275.stderr index c702c3790a7c7..b507540834060 100644 --- a/tests/ui/error-codes/E0275.stderr +++ b/tests/ui/error-codes/E0275.stderr @@ -13,6 +13,6 @@ LL | impl Foo for T where Bar: Foo {} = note: 126 redundant requirements hidden = note: required for `Bar` to implement `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/error-codes/E0276.stderr b/tests/ui/error-codes/E0276.stderr index 1013f041bbe3c..eb004370a1c6b 100644 --- a/tests/ui/error-codes/E0276.stderr +++ b/tests/ui/error-codes/E0276.stderr @@ -7,6 +7,6 @@ LL | fn foo(x: T); LL | fn foo(x: T) where T: Copy {} | ^^^^ impl has extra requirement `T: Copy` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/error-codes/E0277-2.stderr b/tests/ui/error-codes/E0277-2.stderr index a2abf37931a4f..9a262f7559075 100644 --- a/tests/ui/error-codes/E0277-2.stderr +++ b/tests/ui/error-codes/E0277-2.stderr @@ -26,6 +26,6 @@ note: required by a bound in `is_send` LL | fn is_send() { } | ^^^^ required by this bound in `is_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/error-codes/E0277-3.stderr b/tests/ui/error-codes/E0277-3.stderr index 0d4782935df41..6cdfaa04f4a27 100644 --- a/tests/ui/error-codes/E0277-3.stderr +++ b/tests/ui/error-codes/E0277-3.stderr @@ -18,6 +18,6 @@ LL + #[derive(PartialEq)] LL | struct S; | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/error-codes/E0282.stderr b/tests/ui/error-codes/E0282.stderr index 58332454a3753..295e848034973 100644 --- a/tests/ui/error-codes/E0282.stderr +++ b/tests/ui/error-codes/E0282.stderr @@ -9,6 +9,6 @@ help: consider giving `x` an explicit type LL | let x: /* Type */; | ++++++++++++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/error-codes/E0297.stderr b/tests/ui/error-codes/E0297.stderr index 293028f5f68b1..3bfe8a668332a 100644 --- a/tests/ui/error-codes/E0297.stderr +++ b/tests/ui/error-codes/E0297.stderr @@ -6,6 +6,6 @@ LL | for Some(x) in xs {} | = note: the matched value is of type `Option` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/error-codes/E0308-2.stderr b/tests/ui/error-codes/E0308-2.stderr index 3a8a81a73a6ce..b149779179734 100644 --- a/tests/ui/error-codes/E0308-2.stderr +++ b/tests/ui/error-codes/E0308-2.stderr @@ -13,6 +13,6 @@ LL | impl Eq for &dyn DynEq {} | ^ = note: ...does not necessarily outlive the static lifetime -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0308-4.stderr b/tests/ui/error-codes/E0308-4.stderr index 39c0676373794..9f33220a591a6 100644 --- a/tests/ui/error-codes/E0308-4.stderr +++ b/tests/ui/error-codes/E0308-4.stderr @@ -8,6 +8,6 @@ LL | 0u8..=3i8 => (), | | | this is of type `u8` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0308.stderr b/tests/ui/error-codes/E0308.stderr index 141abed6032eb..bc6c5a632a1a8 100644 --- a/tests/ui/error-codes/E0308.stderr +++ b/tests/ui/error-codes/E0308.stderr @@ -7,6 +7,6 @@ LL | fn size_of(); = note: expected signature `extern "rust-intrinsic" fn() -> usize` found signature `extern "rust-intrinsic" fn()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0311.stderr b/tests/ui/error-codes/E0311.stderr index 96546b83f2f93..bac18596f3e5c 100644 --- a/tests/ui/error-codes/E0311.stderr +++ b/tests/ui/error-codes/E0311.stderr @@ -11,6 +11,6 @@ help: consider adding an explicit lifetime bound LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { | +++ ++++ ++ ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/error-codes/E0328.stderr b/tests/ui/error-codes/E0328.stderr index 70e6baf69d3f5..1143c383414da 100644 --- a/tests/ui/error-codes/E0328.stderr +++ b/tests/ui/error-codes/E0328.stderr @@ -4,6 +4,6 @@ error[E0328]: explicit impls for the `Unsize` trait are not permitted LL | impl Unsize for MyType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Unsize` not allowed -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0328`. diff --git a/tests/ui/error-codes/E0365.stderr b/tests/ui/error-codes/E0365.stderr index 5bfcf1394d9fe..d6eb9d6c38339 100644 --- a/tests/ui/error-codes/E0365.stderr +++ b/tests/ui/error-codes/E0365.stderr @@ -6,6 +6,6 @@ LL | pub use foo as foo2; | = note: consider declaring type or module `foo` with `pub` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0365`. diff --git a/tests/ui/error-codes/E0370.stderr b/tests/ui/error-codes/E0370.stderr index 7fb622ee80bbf..7bcd99b957867 100644 --- a/tests/ui/error-codes/E0370.stderr +++ b/tests/ui/error-codes/E0370.stderr @@ -6,6 +6,6 @@ LL | Y, | = note: explicitly set `Y = -9223372036854775808` if that is desired outcome -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0370`. diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr index 49ec0bce44169..148fa1348ab66 100644 --- a/tests/ui/error-codes/E0374.stderr +++ b/tests/ui/error-codes/E0374.stderr @@ -7,6 +7,6 @@ LL | | where T: CoerceUnsized {} | = note: expected a single field to be coerced, none found -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0374`. diff --git a/tests/ui/error-codes/E0375.stderr b/tests/ui/error-codes/E0375.stderr index a68b3af5aaf76..0a5e4128ae9d7 100644 --- a/tests/ui/error-codes/E0375.stderr +++ b/tests/ui/error-codes/E0375.stderr @@ -7,6 +7,6 @@ LL | impl CoerceUnsized> for Foo {} = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0375`. diff --git a/tests/ui/error-codes/E0376.stderr b/tests/ui/error-codes/E0376.stderr index e91efb045c156..46668e05a42f4 100644 --- a/tests/ui/error-codes/E0376.stderr +++ b/tests/ui/error-codes/E0376.stderr @@ -4,6 +4,6 @@ error[E0376]: the trait `CoerceUnsized` may only be implemented for a coercion b LL | impl CoerceUnsized for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0376`. diff --git a/tests/ui/error-codes/E0377.stderr b/tests/ui/error-codes/E0377.stderr index 9cb11e5a3d3a5..5d710d8e15294 100644 --- a/tests/ui/error-codes/E0377.stderr +++ b/tests/ui/error-codes/E0377.stderr @@ -6,6 +6,6 @@ LL | impl CoerceUnsized> for Foo where T: CoerceUnsized {} | = note: expected coercion between the same definition; expected `Foo`, found `Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0377`. diff --git a/tests/ui/error-codes/E0389.stderr b/tests/ui/error-codes/E0389.stderr index e4001856c388b..156bff7f0223f 100644 --- a/tests/ui/error-codes/E0389.stderr +++ b/tests/ui/error-codes/E0389.stderr @@ -9,6 +9,6 @@ help: consider changing this to be a mutable reference LL | let fancy_ref = &mut (&mut fancy); | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/error-codes/E0392.stderr b/tests/ui/error-codes/E0392.stderr index 622402999c348..ecbfd5584d5a3 100644 --- a/tests/ui/error-codes/E0392.stderr +++ b/tests/ui/error-codes/E0392.stderr @@ -7,6 +7,6 @@ LL | enum Foo { Bar } = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: usize` instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/error-codes/E0393.stderr b/tests/ui/error-codes/E0393.stderr index d9f70b7293016..4083fa23e87aa 100644 --- a/tests/ui/error-codes/E0393.stderr +++ b/tests/ui/error-codes/E0393.stderr @@ -9,6 +9,6 @@ LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {} | = note: because of the default `Self` reference, type parameters must be specified on object types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/error-codes/E0396-fixed.stderr b/tests/ui/error-codes/E0396-fixed.stderr index e77b2ce9a2298..2f8ea7993f723 100644 --- a/tests/ui/error-codes/E0396-fixed.stderr +++ b/tests/ui/error-codes/E0396-fixed.stderr @@ -4,6 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const VALUE: u8 = unsafe { *REG_ADDR }; | ^^^^^^^^^ memory access failed: 0x5f3759df[noalloc] is a dangling pointer (it has no provenance) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index 0a069e8d35063..d27fade487fe2 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -55,7 +55,7 @@ error[E0283]: type annotations needed LL | bfnr(x); | ^^^^ cannot infer type of the type parameter `W` declared on the function `bfnr` | - = note: multiple `impl`s satisfying `_: Fn<()>` found in the following crates: `alloc`, `core`: + = note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`: - impl Fn for &F where A: Tuple, F: Fn, F: ?Sized; - impl Fn for Box diff --git a/tests/ui/error-codes/E0403.stderr b/tests/ui/error-codes/E0403.stderr index d76a58a7c80de..02f255b7e4626 100644 --- a/tests/ui/error-codes/E0403.stderr +++ b/tests/ui/error-codes/E0403.stderr @@ -6,6 +6,6 @@ LL | fn foo(s: T, u: T) {} | | | first use of `T` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/error-codes/E0405.stderr b/tests/ui/error-codes/E0405.stderr index a22afe6f3e8c3..1fb115c9e999b 100644 --- a/tests/ui/error-codes/E0405.stderr +++ b/tests/ui/error-codes/E0405.stderr @@ -4,6 +4,6 @@ error[E0405]: cannot find trait `SomeTrait` in this scope LL | impl SomeTrait for Foo {} | ^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/error-codes/E0407.stderr b/tests/ui/error-codes/E0407.stderr index 6f6d1ff6a8f41..889668f58927c 100644 --- a/tests/ui/error-codes/E0407.stderr +++ b/tests/ui/error-codes/E0407.stderr @@ -7,6 +7,6 @@ LL | fn b() {} | | help: there is an associated function with a similar name: `a` | not a member of trait `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0407`. diff --git a/tests/ui/error-codes/E0408.stderr b/tests/ui/error-codes/E0408.stderr index 132a9432254fc..45ac480061f6b 100644 --- a/tests/ui/error-codes/E0408.stderr +++ b/tests/ui/error-codes/E0408.stderr @@ -6,6 +6,6 @@ LL | Some(y) | None => {} | | | variable not in all patterns -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/error-codes/E0411.stderr b/tests/ui/error-codes/E0411.stderr index 4c99f9fcbf1de..16da10348a28f 100644 --- a/tests/ui/error-codes/E0411.stderr +++ b/tests/ui/error-codes/E0411.stderr @@ -6,6 +6,6 @@ LL | fn main() { LL | ::foo; | ^^^^ `Self` is only available in impls, traits, and type definitions -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0411`. diff --git a/tests/ui/error-codes/E0412.stderr b/tests/ui/error-codes/E0412.stderr index 7bdaa18073075..7c1172642faff 100644 --- a/tests/ui/error-codes/E0412.stderr +++ b/tests/ui/error-codes/E0412.stderr @@ -4,6 +4,6 @@ error[E0412]: cannot find type `Something` in this scope LL | impl Something {} | ^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/error-codes/E0415.stderr b/tests/ui/error-codes/E0415.stderr index c2b8fdc7c558b..77e5752de817b 100644 --- a/tests/ui/error-codes/E0415.stderr +++ b/tests/ui/error-codes/E0415.stderr @@ -4,6 +4,6 @@ error[E0415]: identifier `f` is bound more than once in this parameter list LL | fn foo(f: i32, f: i32) {} | ^ used as parameter more than once -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0415`. diff --git a/tests/ui/error-codes/E0416.stderr b/tests/ui/error-codes/E0416.stderr index 78acac5c6617e..643b99087019b 100644 --- a/tests/ui/error-codes/E0416.stderr +++ b/tests/ui/error-codes/E0416.stderr @@ -4,6 +4,6 @@ error[E0416]: identifier `x` is bound more than once in the same pattern LL | (x, x) => {} | ^ used in a pattern more than once -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0416`. diff --git a/tests/ui/error-codes/E0425.stderr b/tests/ui/error-codes/E0425.stderr index 9ef4608da7dad..db78dc3f7abe3 100644 --- a/tests/ui/error-codes/E0425.stderr +++ b/tests/ui/error-codes/E0425.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `elf` in this scope LL | elf; | ^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/error-codes/E0426.stderr b/tests/ui/error-codes/E0426.stderr index 035f2eb86b90c..3e03030dfc966 100644 --- a/tests/ui/error-codes/E0426.stderr +++ b/tests/ui/error-codes/E0426.stderr @@ -4,6 +4,6 @@ error[E0426]: use of undeclared label `'a` LL | break 'a; | ^^ undeclared label `'a` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/error-codes/E0428.stderr b/tests/ui/error-codes/E0428.stderr index 205bcf342f1ad..b5bb84e2e68fc 100644 --- a/tests/ui/error-codes/E0428.stderr +++ b/tests/ui/error-codes/E0428.stderr @@ -8,6 +8,6 @@ LL | struct Bar; | = note: `Bar` must be defined only once in the type namespace of this module -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/error-codes/E0429.stderr b/tests/ui/error-codes/E0429.stderr index 08b99232ee22b..d2d9ba209f745 100644 --- a/tests/ui/error-codes/E0429.stderr +++ b/tests/ui/error-codes/E0429.stderr @@ -14,6 +14,6 @@ help: alternatively, use the multi-path `use` syntax to import `self` LL | use std::fmt::{self}; | + + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0429`. diff --git a/tests/ui/error-codes/E0431.stderr b/tests/ui/error-codes/E0431.stderr index adfd2d923c78a..f77c62bec6819 100644 --- a/tests/ui/error-codes/E0431.stderr +++ b/tests/ui/error-codes/E0431.stderr @@ -4,6 +4,6 @@ error[E0431]: `self` import can only appear in an import list with a non-empty p LL | use {self}; | ^^^^ can only appear in an import list with a non-empty prefix -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0431`. diff --git a/tests/ui/error-codes/E0432.stderr b/tests/ui/error-codes/E0432.stderr index ed9536f164ef0..473e82f863437 100644 --- a/tests/ui/error-codes/E0432.stderr +++ b/tests/ui/error-codes/E0432.stderr @@ -6,6 +6,6 @@ LL | use something::Foo; | = help: consider adding `extern crate something` to use the `something` crate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/error-codes/E0433.stderr b/tests/ui/error-codes/E0433.stderr index 265d8885c8df0..1ac8c3ebc4d40 100644 --- a/tests/ui/error-codes/E0433.stderr +++ b/tests/ui/error-codes/E0433.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared type `NonExistingMap` LL | let map = NonExistingMap::new(); | ^^^^^^^^^^^^^^ use of undeclared type `NonExistingMap` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/error-codes/E0434.stderr b/tests/ui/error-codes/E0434.stderr index 14508ccbc9a7c..db9b087f5fd8c 100644 --- a/tests/ui/error-codes/E0434.stderr +++ b/tests/ui/error-codes/E0434.stderr @@ -6,6 +6,6 @@ LL | y | = help: use the `|| { ... }` closure form instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/error-codes/E0435.stderr b/tests/ui/error-codes/E0435.stderr index fc08fade91cee..68d6ddba2a107 100644 --- a/tests/ui/error-codes/E0435.stderr +++ b/tests/ui/error-codes/E0435.stderr @@ -6,6 +6,6 @@ LL | let foo: usize = 42; LL | let _: [u8; foo]; | ^^^ non-constant value -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/error-codes/E0437.stderr b/tests/ui/error-codes/E0437.stderr index 217b164036f87..b011fa40e1eb9 100644 --- a/tests/ui/error-codes/E0437.stderr +++ b/tests/ui/error-codes/E0437.stderr @@ -4,6 +4,6 @@ error[E0437]: type `Bar` is not a member of trait `Foo` LL | type Bar = bool; | ^^^^^^^^^^^^^^^^ not a member of trait `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0437`. diff --git a/tests/ui/error-codes/E0438.stderr b/tests/ui/error-codes/E0438.stderr index 853f0c3c2399d..701c007afe3a2 100644 --- a/tests/ui/error-codes/E0438.stderr +++ b/tests/ui/error-codes/E0438.stderr @@ -4,6 +4,6 @@ error[E0438]: const `BAR` is not a member of trait `Bar` LL | const BAR: bool = true; | ^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Bar` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0438`. diff --git a/tests/ui/error-codes/E0454.stderr b/tests/ui/error-codes/E0454.stderr index b9a506fee830a..e16982542cfa2 100644 --- a/tests/ui/error-codes/E0454.stderr +++ b/tests/ui/error-codes/E0454.stderr @@ -4,6 +4,6 @@ error[E0454]: link name must not be empty LL | #[link(name = "")] extern "C" {} | ^^ empty link name -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0454`. diff --git a/tests/ui/error-codes/E0458.stderr b/tests/ui/error-codes/E0458.stderr index e641bba541ee0..c13ae4e78629a 100644 --- a/tests/ui/error-codes/E0458.stderr +++ b/tests/ui/error-codes/E0458.stderr @@ -1,4 +1,4 @@ -error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib +error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib, link-arg --> $DIR/E0458.rs:1:15 | LL | #[link(kind = "wonderful_unicorn")] extern "C" {} diff --git a/tests/ui/error-codes/E0459.stderr b/tests/ui/error-codes/E0459.stderr index 8f0dd25e0309a..21c1a50bf849a 100644 --- a/tests/ui/error-codes/E0459.stderr +++ b/tests/ui/error-codes/E0459.stderr @@ -4,6 +4,6 @@ error[E0459]: `#[link]` attribute requires a `name = "string"` argument LL | #[link(kind = "dylib")] extern "C" {} | ^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0459`. diff --git a/tests/ui/error-codes/E0462.stderr b/tests/ui/error-codes/E0462.stderr index 43e27965ffc50..18f20d79385e3 100644 --- a/tests/ui/error-codes/E0462.stderr +++ b/tests/ui/error-codes/E0462.stderr @@ -8,6 +8,6 @@ LL | extern crate found_staticlib; crate `found_staticlib`: $TEST_BUILD_DIR/error-codes/E0462/auxiliary/libfound_staticlib.somelib = help: please recompile that crate using --crate-type lib -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0462`. diff --git a/tests/ui/error-codes/E0464.stderr b/tests/ui/error-codes/E0464.stderr index 574270f94a672..edb0b1cf41e1a 100644 --- a/tests/ui/error-codes/E0464.stderr +++ b/tests/ui/error-codes/E0464.stderr @@ -8,6 +8,6 @@ LL | extern crate crateresolve1; = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-2.somelib = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-3.somelib -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0464`. diff --git a/tests/ui/error-codes/E0476.stderr b/tests/ui/error-codes/E0476.next.stderr similarity index 92% rename from tests/ui/error-codes/E0476.stderr rename to tests/ui/error-codes/E0476.next.stderr index 0378ac6e8ec91..454dbecc7d01f 100644 --- a/tests/ui/error-codes/E0476.stderr +++ b/tests/ui/error-codes/E0476.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>` - --> $DIR/E0476.rs:9:1 + --> $DIR/E0476.rs:11:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,18 +9,18 @@ LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S where 'b: 'a, T: Unsize, T: ?Sized, U: ?Sized; error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type - --> $DIR/E0476.rs:9:1 + --> $DIR/E0476.rs:11:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: object type is valid for the lifetime `'a` as defined here - --> $DIR/E0476.rs:9:6 + --> $DIR/E0476.rs:11:6 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ note: source pointer is only valid for the lifetime `'b` as defined here - --> $DIR/E0476.rs:9:10 + --> $DIR/E0476.rs:11:10 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ diff --git a/tests/ui/error-codes/E0476.old.stderr b/tests/ui/error-codes/E0476.old.stderr new file mode 100644 index 0000000000000..454dbecc7d01f --- /dev/null +++ b/tests/ui/error-codes/E0476.old.stderr @@ -0,0 +1,31 @@ +error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>` + --> $DIR/E0476.rs:11:1 + | +LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl<'a, 'b, T, U> CoerceUnsized<&'a U> for &'b T + where 'b: 'a, T: Unsize, T: ?Sized, U: ?Sized; + +error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type + --> $DIR/E0476.rs:11:1 + | +LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: object type is valid for the lifetime `'a` as defined here + --> $DIR/E0476.rs:11:6 + | +LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} + | ^^ +note: source pointer is only valid for the lifetime `'b` as defined here + --> $DIR/E0476.rs:11:10 + | +LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} + | ^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0476. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/E0476.rs b/tests/ui/error-codes/E0476.rs index d5e4b8d237274..e9afc7567260f 100644 --- a/tests/ui/error-codes/E0476.rs +++ b/tests/ui/error-codes/E0476.rs @@ -1,3 +1,5 @@ +// revisions: old next +//[next] compile-flags: -Ztrait-solver=next-coherence #![feature(coerce_unsized)] #![feature(unsize)] diff --git a/tests/ui/error-codes/E0478.stderr b/tests/ui/error-codes/E0478.stderr index ec650085a2b9d..6ecde0e14e5e3 100644 --- a/tests/ui/error-codes/E0478.stderr +++ b/tests/ui/error-codes/E0478.stderr @@ -15,6 +15,6 @@ note: but lifetime parameter must outlive the lifetime `'kiss` as defined here LL | struct Prince<'kiss, 'SnowWhite> { | ^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/error-codes/E0496.stderr b/tests/ui/error-codes/E0496.stderr index 80ca2b1fbdb5d..2d60aee77f849 100644 --- a/tests/ui/error-codes/E0496.stderr +++ b/tests/ui/error-codes/E0496.stderr @@ -6,6 +6,6 @@ LL | impl<'a> Foo<'a> { LL | fn f<'a>(x: &'a i32) { | ^^ lifetime `'a` already in scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0496`. diff --git a/tests/ui/error-codes/E0499.stderr b/tests/ui/error-codes/E0499.stderr index d56baf7227201..03f2bad6cb5bd 100644 --- a/tests/ui/error-codes/E0499.stderr +++ b/tests/ui/error-codes/E0499.stderr @@ -9,6 +9,6 @@ LL | a.use_mut(); LL | x.use_mut(); | - first borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/error-codes/E0502.stderr b/tests/ui/error-codes/E0502.stderr index cade6d71852f8..88d914c0e7736 100644 --- a/tests/ui/error-codes/E0502.stderr +++ b/tests/ui/error-codes/E0502.stderr @@ -8,6 +8,6 @@ LL | bar(a); LL | y.use_ref(); | - immutable borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/error-codes/E0503.stderr b/tests/ui/error-codes/E0503.stderr index 275abb23f53af..f1469cdc59bcd 100644 --- a/tests/ui/error-codes/E0503.stderr +++ b/tests/ui/error-codes/E0503.stderr @@ -8,6 +8,6 @@ LL | let _sum = value + 1; LL | _borrow.use_mut(); | ------- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr index 20e16a5381061..c8a48961cb3b1 100644 --- a/tests/ui/error-codes/E0504.stderr +++ b/tests/ui/error-codes/E0504.stderr @@ -14,6 +14,6 @@ LL | println!("child function: {}", fancy_num.num); LL | println!("main function: {}", fancy_ref.num); | ------------- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr index 1a85e03170538..250680d2c1c5d 100644 --- a/tests/ui/error-codes/E0505.stderr +++ b/tests/ui/error-codes/E0505.stderr @@ -11,6 +11,6 @@ LL | eat(x); LL | _ref_to_val.use_ref(); | ----------- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/error-codes/E0506.stderr b/tests/ui/error-codes/E0506.stderr index 17ad7c611f824..2cc2885f7757a 100644 --- a/tests/ui/error-codes/E0506.stderr +++ b/tests/ui/error-codes/E0506.stderr @@ -9,6 +9,6 @@ LL | LL | println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); | ------------- borrow later used here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr index 0899395162285..767fedfccbfb8 100644 --- a/tests/ui/error-codes/E0507.stderr +++ b/tests/ui/error-codes/E0507.stderr @@ -12,6 +12,6 @@ note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, w LL | fn nothing_is_true(self) {} | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr index 208ba30729f8b..1153b1d09c733 100644 --- a/tests/ui/error-codes/E0508-fail.stderr +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -12,6 +12,6 @@ help: consider borrowing here LL | let _value = &array[0]; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr index df2d3b0d311c9..4c864e2414463 100644 --- a/tests/ui/error-codes/E0508.stderr +++ b/tests/ui/error-codes/E0508.stderr @@ -12,6 +12,6 @@ help: consider borrowing here LL | let _value = &array[0]; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr index c00d9142e7505..59843a5491ab2 100644 --- a/tests/ui/error-codes/E0509.stderr +++ b/tests/ui/error-codes/E0509.stderr @@ -12,6 +12,6 @@ help: consider borrowing here LL | let fancy_field = &drop_struct.fancy; | + -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/error-codes/E0511.stderr b/tests/ui/error-codes/E0511.stderr index d797b10d5a654..59eb19d2ee526 100644 --- a/tests/ui/error-codes/E0511.stderr +++ b/tests/ui/error-codes/E0511.stderr @@ -4,6 +4,6 @@ error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD in LL | unsafe { simd_add(0, 1); } | ^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/error-codes/E0512.stderr b/tests/ui/error-codes/E0512.stderr index 3fecce542ce9b..eb8ce8b17a4b7 100644 --- a/tests/ui/error-codes/E0512.stderr +++ b/tests/ui/error-codes/E0512.stderr @@ -7,6 +7,6 @@ LL | unsafe { takes_u8(::std::mem::transmute(0u16)); } = note: source type: `u16` (16 bits) = note: target type: `u8` (8 bits) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/error-codes/E0516.stderr b/tests/ui/error-codes/E0516.stderr index 5243b7caf225b..62e70a4668d12 100644 --- a/tests/ui/error-codes/E0516.stderr +++ b/tests/ui/error-codes/E0516.stderr @@ -9,6 +9,6 @@ help: consider replacing `typeof(...)` with an actual type LL | let x: i32 = 92; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0516`. diff --git a/tests/ui/error-codes/E0519.stderr b/tests/ui/error-codes/E0519.stderr index e24fc4aaa70fb..4fbd268134f20 100644 --- a/tests/ui/error-codes/E0519.stderr +++ b/tests/ui/error-codes/E0519.stderr @@ -4,6 +4,6 @@ error[E0519]: the current crate is indistinguishable from one of its dependencie LL | extern crate crateresolve1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0519`. diff --git a/tests/ui/error-codes/E0520.stderr b/tests/ui/error-codes/E0520.stderr index 06658a49b83aa..83319203023ff 100644 --- a/tests/ui/error-codes/E0520.stderr +++ b/tests/ui/error-codes/E0520.stderr @@ -19,6 +19,6 @@ LL | default fn fly(&self) {} | = note: to specialize, `fly` in the parent `impl` must be marked `default` -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/error-codes/E0522.stderr b/tests/ui/error-codes/E0522.stderr index 0a8a41598da92..66359cbacc846 100644 --- a/tests/ui/error-codes/E0522.stderr +++ b/tests/ui/error-codes/E0522.stderr @@ -4,6 +4,6 @@ error[E0522]: definition of an unknown language item: `cookie` LL | #[lang = "cookie"] | ^^^^^^^^^^^^^^^^^^ definition of unknown language item `cookie` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0522`. diff --git a/tests/ui/error-codes/E0523.stderr b/tests/ui/error-codes/E0523.stderr index 8e3eb2159c298..c6e65b55e2b30 100644 --- a/tests/ui/error-codes/E0523.stderr +++ b/tests/ui/error-codes/E0523.stderr @@ -8,6 +8,6 @@ LL | extern crate crateresolve1; = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-2.somelib = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-3.somelib -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0464`. diff --git a/tests/ui/error-codes/E0527.stderr b/tests/ui/error-codes/E0527.stderr index a2e6288b21be2..80d8412a5206e 100644 --- a/tests/ui/error-codes/E0527.stderr +++ b/tests/ui/error-codes/E0527.stderr @@ -4,6 +4,6 @@ error[E0527]: pattern requires 2 elements but array has 4 LL | &[a, b] => { | ^^^^^^ expected 4 elements -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/error-codes/E0528.stderr b/tests/ui/error-codes/E0528.stderr index 21615f954c363..94c83d36e2210 100644 --- a/tests/ui/error-codes/E0528.stderr +++ b/tests/ui/error-codes/E0528.stderr @@ -4,6 +4,6 @@ error[E0528]: pattern requires at least 3 elements but array has 2 LL | &[a, b, c, rest @ ..] => { | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0528`. diff --git a/tests/ui/error-codes/E0529.stderr b/tests/ui/error-codes/E0529.stderr index 96b22bb226381..b3e25a9652591 100644 --- a/tests/ui/error-codes/E0529.stderr +++ b/tests/ui/error-codes/E0529.stderr @@ -4,6 +4,6 @@ error[E0529]: expected an array or slice, found `f32` LL | [a, b] => { | ^^^^^^ pattern cannot match with input type `f32` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/error-codes/E0530.stderr b/tests/ui/error-codes/E0530.stderr index c312144132d3b..125b60bc91423 100644 --- a/tests/ui/error-codes/E0530.stderr +++ b/tests/ui/error-codes/E0530.stderr @@ -7,6 +7,6 @@ LL | static TEST: i32 = 0; LL | TEST => {} | ^^^^ cannot be named the same as a static -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/error-codes/E0532.stderr b/tests/ui/error-codes/E0532.stderr index eeccadccc636a..0cd276a3cc77a 100644 --- a/tests/ui/error-codes/E0532.stderr +++ b/tests/ui/error-codes/E0532.stderr @@ -4,6 +4,6 @@ error[E0532]: expected tuple struct or tuple variant, found constant `StructCons LL | StructConst1(_) => { }, | ^^^^^^^^^^^^ not a tuple struct or tuple variant -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/error-codes/E0534.stderr b/tests/ui/error-codes/E0534.stderr index 23f9cd7ce2db7..6983de7ab69c6 100644 --- a/tests/ui/error-codes/E0534.stderr +++ b/tests/ui/error-codes/E0534.stderr @@ -4,6 +4,6 @@ error[E0534]: expected one argument LL | #[inline()] | ^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0534`. diff --git a/tests/ui/error-codes/E0559.stderr b/tests/ui/error-codes/E0559.stderr index 63ee1cd78201a..59317780f4174 100644 --- a/tests/ui/error-codes/E0559.stderr +++ b/tests/ui/error-codes/E0559.stderr @@ -6,6 +6,6 @@ LL | let s = Field::Fool { joke: 0 }; | = note: available fields are: `x` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0559`. diff --git a/tests/ui/error-codes/E0560.stderr b/tests/ui/error-codes/E0560.stderr index bb5ce478ae1a7..934bc41cce289 100644 --- a/tests/ui/error-codes/E0560.stderr +++ b/tests/ui/error-codes/E0560.stderr @@ -6,6 +6,6 @@ LL | let s = Simba { mother: 1, father: 0 }; | = note: all struct fields are already assigned -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/error-codes/E0565-1.stderr b/tests/ui/error-codes/E0565-1.stderr index 1283a9c5ef653..806eed2a632f8 100644 --- a/tests/ui/error-codes/E0565-1.stderr +++ b/tests/ui/error-codes/E0565-1.stderr @@ -4,6 +4,6 @@ error[E0565]: item in `deprecated` must be a key/value pair LL | #[deprecated("since")] | ^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/error-codes/E0565-2.stderr b/tests/ui/error-codes/E0565-2.stderr index 097871bd31906..42199351c3da2 100644 --- a/tests/ui/error-codes/E0565-2.stderr +++ b/tests/ui/error-codes/E0565-2.stderr @@ -6,6 +6,6 @@ LL | #[deprecated(since = b"1.29", note = "hi")] | | | help: consider removing the prefix -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/error-codes/E0565.stderr b/tests/ui/error-codes/E0565.stderr index 6ed90c0ae4ffe..68f4a37dcff38 100644 --- a/tests/ui/error-codes/E0565.stderr +++ b/tests/ui/error-codes/E0565.stderr @@ -4,6 +4,6 @@ error[E0565]: meta item in `repr` must be an identifier LL | #[repr("C")] | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/error-codes/E0572.stderr b/tests/ui/error-codes/E0572.stderr index 36619f8dee4cc..e0f59ec84682e 100644 --- a/tests/ui/error-codes/E0572.stderr +++ b/tests/ui/error-codes/E0572.stderr @@ -4,6 +4,6 @@ error[E0572]: return statement outside of function body LL | const FOO: u32 = return 0; | ^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/error-codes/E0583.stderr b/tests/ui/error-codes/E0583.stderr index 6707f2864f23c..cad61dde4756f 100644 --- a/tests/ui/error-codes/E0583.stderr +++ b/tests/ui/error-codes/E0583.stderr @@ -7,6 +7,6 @@ LL | mod module_that_doesnt_exist; = help: to create the module `module_that_doesnt_exist`, create file "$DIR/module_that_doesnt_exist.rs" or "$DIR/module_that_doesnt_exist/mod.rs" = note: if there is a `mod module_that_doesnt_exist` elsewhere in the crate already, import it with `use crate::...` instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/error-codes/E0585.stderr b/tests/ui/error-codes/E0585.stderr index 53c82fb416b81..f0464cc0b0339 100644 --- a/tests/ui/error-codes/E0585.stderr +++ b/tests/ui/error-codes/E0585.stderr @@ -6,6 +6,6 @@ LL | /// Hello! I'm useless... | = help: doc comments must come before what they document, if a comment was intended use `//` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/error-codes/E0586.stderr b/tests/ui/error-codes/E0586.stderr index 0bbf9a6080349..f562e358cba1a 100644 --- a/tests/ui/error-codes/E0586.stderr +++ b/tests/ui/error-codes/E0586.stderr @@ -6,6 +6,6 @@ LL | let x = &tmp[1..=]; | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/error-codes/E0594.stderr b/tests/ui/error-codes/E0594.stderr index f4d96f4e45a56..e010cda83ff90 100644 --- a/tests/ui/error-codes/E0594.stderr +++ b/tests/ui/error-codes/E0594.stderr @@ -4,6 +4,6 @@ error[E0594]: cannot assign to immutable static item `NUM` LL | NUM = 20; | ^^^^^^^^ cannot assign -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/error-codes/E0596.stderr b/tests/ui/error-codes/E0596.stderr index 3f9aebcc8aead..9f1092d88cf36 100644 --- a/tests/ui/error-codes/E0596.stderr +++ b/tests/ui/error-codes/E0596.stderr @@ -9,6 +9,6 @@ help: consider changing this to be mutable LL | let mut x = 1; | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/error-codes/E0597.stderr b/tests/ui/error-codes/E0597.stderr index 82e3481b65a59..d3206112bd06f 100644 --- a/tests/ui/error-codes/E0597.stderr +++ b/tests/ui/error-codes/E0597.stderr @@ -14,6 +14,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are defined -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/error-codes/E0599.stderr b/tests/ui/error-codes/E0599.stderr index a1fb58f483f6d..5c1c71d39f719 100644 --- a/tests/ui/error-codes/E0599.stderr +++ b/tests/ui/error-codes/E0599.stderr @@ -7,6 +7,6 @@ LL | struct Foo; LL | || if let Foo::NotEvenReal() = Foo {}; | ^^^^^^^^^^^ associated item not found in `Foo` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/error-codes/E0600.stderr b/tests/ui/error-codes/E0600.stderr index 95ac4510ca885..a76f2354da651 100644 --- a/tests/ui/error-codes/E0600.stderr +++ b/tests/ui/error-codes/E0600.stderr @@ -4,6 +4,6 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str` LL | !"a"; | ^^^^ cannot apply unary operator `!` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/error-codes/E0601.stderr b/tests/ui/error-codes/E0601.stderr index a687f575615d7..41a4a8f7dbbaa 100644 --- a/tests/ui/error-codes/E0601.stderr +++ b/tests/ui/error-codes/E0601.stderr @@ -4,6 +4,6 @@ error[E0601]: `main` function not found in crate `E0601` LL | | ^ consider adding a `main` function to `$DIR/E0601.rs` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/error-codes/E0603.stderr b/tests/ui/error-codes/E0603.stderr index ee902584f56da..1ac1bbd89a765 100644 --- a/tests/ui/error-codes/E0603.stderr +++ b/tests/ui/error-codes/E0603.stderr @@ -10,6 +10,6 @@ note: the constant `PRIVATE` is defined here LL | const PRIVATE: u32 = 0x_a_bad_1dea_u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/error-codes/E0604.stderr b/tests/ui/error-codes/E0604.stderr index 68da03928b783..e91f74d6b3fd6 100644 --- a/tests/ui/error-codes/E0604.stderr +++ b/tests/ui/error-codes/E0604.stderr @@ -7,6 +7,6 @@ LL | 1u32 as char; | invalid cast | help: try `char::from_u32` instead: `char::from_u32(1u32)` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0604`. diff --git a/tests/ui/error-codes/E0607.stderr b/tests/ui/error-codes/E0607.stderr index a0fe02c1c4d95..835ababf44953 100644 --- a/tests/ui/error-codes/E0607.stderr +++ b/tests/ui/error-codes/E0607.stderr @@ -4,6 +4,6 @@ error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` LL | v as *const [u8]; | ^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0607`. diff --git a/tests/ui/error-codes/E0608.stderr b/tests/ui/error-codes/E0608.stderr index f23f9977ba0ba..da7be147819c8 100644 --- a/tests/ui/error-codes/E0608.stderr +++ b/tests/ui/error-codes/E0608.stderr @@ -4,6 +4,6 @@ error[E0608]: cannot index into a value of type `u8` LL | 0u8[2]; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/error-codes/E0609-private-method.stderr b/tests/ui/error-codes/E0609-private-method.stderr index d2a11e9062740..c889765be54e5 100644 --- a/tests/ui/error-codes/E0609-private-method.stderr +++ b/tests/ui/error-codes/E0609-private-method.stderr @@ -4,6 +4,6 @@ error[E0609]: no field `method` on type `Foo` LL | f.method; | ^^^^^^ unknown field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/error-codes/E0609.stderr b/tests/ui/error-codes/E0609.stderr index 797e95d02dda3..cad857553da30 100644 --- a/tests/ui/error-codes/E0609.stderr +++ b/tests/ui/error-codes/E0609.stderr @@ -4,7 +4,7 @@ error[E0609]: no field `foo` on type `Foo` LL | let _ = x.foo; | ^^^ unknown field | - = note: available fields are: `x` + = note: available field is: `x` error[E0609]: no field `1` on type `Bar` --> $DIR/E0609.rs:11:7 diff --git a/tests/ui/error-codes/E0610.stderr b/tests/ui/error-codes/E0610.stderr index a2966eea44c01..4263368ff4216 100644 --- a/tests/ui/error-codes/E0610.stderr +++ b/tests/ui/error-codes/E0610.stderr @@ -4,6 +4,6 @@ error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields LL | let _ = x.foo; | ^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0610`. diff --git a/tests/ui/error-codes/E0614.stderr b/tests/ui/error-codes/E0614.stderr index 598117c2b6058..ae7c2ce9a132c 100644 --- a/tests/ui/error-codes/E0614.stderr +++ b/tests/ui/error-codes/E0614.stderr @@ -4,6 +4,6 @@ error[E0614]: type `u32` cannot be dereferenced LL | *y; | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/error-codes/E0615.stderr b/tests/ui/error-codes/E0615.stderr index c12e1a3a64361..13446a475a058 100644 --- a/tests/ui/error-codes/E0615.stderr +++ b/tests/ui/error-codes/E0615.stderr @@ -9,6 +9,6 @@ help: use parentheses to call the method LL | f.method(); | ++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/error-codes/E0616.stderr b/tests/ui/error-codes/E0616.stderr index da349ed2fde35..73eb64ab468dd 100644 --- a/tests/ui/error-codes/E0616.stderr +++ b/tests/ui/error-codes/E0616.stderr @@ -4,6 +4,6 @@ error[E0616]: field `x` of struct `Foo` is private LL | f.x; | ^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/error-codes/E0620.stderr b/tests/ui/error-codes/E0620.stderr index 65152b2b74dd4..5bc8903624cef 100644 --- a/tests/ui/error-codes/E0620.stderr +++ b/tests/ui/error-codes/E0620.stderr @@ -10,6 +10,6 @@ help: consider using an implicit coercion to `&[usize]` instead LL | let _foo = &[1_usize, 2] as [usize]; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0620`. diff --git a/tests/ui/error-codes/E0621-does-not-trigger-for-closures.stderr b/tests/ui/error-codes/E0621-does-not-trigger-for-closures.stderr index b9edeb8346bdc..2d96926a230ff 100644 --- a/tests/ui/error-codes/E0621-does-not-trigger-for-closures.stderr +++ b/tests/ui/error-codes/E0621-does-not-trigger-for-closures.stderr @@ -7,5 +7,5 @@ LL | invoke(&x, |a, b| if a > b { a } else { b }); | |return type of closure is &'2 i32 | has type `&'1 i32` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr index 8466dfe3848c2..c59776b211fd6 100644 --- a/tests/ui/error-codes/E0622.stderr +++ b/tests/ui/error-codes/E0622.stderr @@ -4,6 +4,6 @@ error[E0622]: intrinsic must be a function LL | pub static breakpoint : unsafe extern "rust-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0622`. diff --git a/tests/ui/error-codes/E0624.stderr b/tests/ui/error-codes/E0624.stderr index 23a8ea8a8c98e..b2bc2c92d368d 100644 --- a/tests/ui/error-codes/E0624.stderr +++ b/tests/ui/error-codes/E0624.stderr @@ -7,6 +7,6 @@ LL | fn method(&self) {} LL | foo.method(); | ^^^^^^ private method -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/error-codes/E0646.stderr b/tests/ui/error-codes/E0646.stderr index 069401b3f1829..7f8d7ae70222c 100644 --- a/tests/ui/error-codes/E0646.stderr +++ b/tests/ui/error-codes/E0646.stderr @@ -4,6 +4,6 @@ error[E0646]: `main` function is not allowed to have a `where` clause LL | fn main() where (): Copy {} | ^^^^^^^^^^^^^^ `main` cannot have a `where` clause -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0646`. diff --git a/tests/ui/error-codes/E0647.stderr b/tests/ui/error-codes/E0647.stderr index 9d1ab967127ad..4b444e5a39726 100644 --- a/tests/ui/error-codes/E0647.stderr +++ b/tests/ui/error-codes/E0647.stderr @@ -4,6 +4,6 @@ error[E0647]: `#[start]` function is not allowed to have a `where` clause LL | fn start(_: isize, _: *const *const u8) -> isize where (): Copy { | ^^^^^^^^^^^^^^ `#[start]` function cannot have a `where` clause -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0647`. diff --git a/tests/ui/error-codes/E0648.stderr b/tests/ui/error-codes/E0648.stderr index 1a65825c7b6c6..e995e53139511 100644 --- a/tests/ui/error-codes/E0648.stderr +++ b/tests/ui/error-codes/E0648.stderr @@ -4,6 +4,6 @@ error[E0648]: `export_name` may not contain null characters LL | #[export_name="\0foo"] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0648`. diff --git a/tests/ui/error-codes/E0658.stderr b/tests/ui/error-codes/E0658.stderr index 8d423484528a1..686394b6d2259 100644 --- a/tests/ui/error-codes/E0658.stderr +++ b/tests/ui/error-codes/E0658.stderr @@ -7,6 +7,6 @@ LL | enum Foo { = note: see issue #56071 for more information = help: add `#![feature(repr128)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/error-codes/E0659.stderr b/tests/ui/error-codes/E0659.stderr index b0c73c636c62f..dbb72bb675999 100644 --- a/tests/ui/error-codes/E0659.stderr +++ b/tests/ui/error-codes/E0659.stderr @@ -18,6 +18,6 @@ LL | pub use earth::*; | ^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/error-codes/E0718.stderr b/tests/ui/error-codes/E0718.stderr index 30378dd167457..9a3db136d23c0 100644 --- a/tests/ui/error-codes/E0718.stderr +++ b/tests/ui/error-codes/E0718.stderr @@ -4,6 +4,6 @@ error[E0718]: `owned_box` language item must be applied to a struct LL | #[lang = "owned_box"] | ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0718`. diff --git a/tests/ui/error-codes/E0730.stderr b/tests/ui/error-codes/E0730.stderr index 067e8c57cd63b..5e996ac355512 100644 --- a/tests/ui/error-codes/E0730.stderr +++ b/tests/ui/error-codes/E0730.stderr @@ -4,6 +4,6 @@ error[E0730]: cannot pattern-match on an array without a fixed length LL | [1, 2, ..] => true, | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0730`. diff --git a/tests/ui/error-codes/E0771.stderr b/tests/ui/error-codes/E0771.stderr index 9450c61c27be0..e1384effe37ab 100644 --- a/tests/ui/error-codes/E0771.stderr +++ b/tests/ui/error-codes/E0771.stderr @@ -15,6 +15,6 @@ LL | #![feature(adt_const_params)] = note: see issue #95174 for more information = note: `#[warn(incomplete_features)]` on by default -error: aborting due to previous error; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/error-codes/E0778.stderr b/tests/ui/error-codes/E0778.stderr index 42647e5c6a1b9..7eb24c493bf54 100644 --- a/tests/ui/error-codes/E0778.stderr +++ b/tests/ui/error-codes/E0778.stderr @@ -4,6 +4,6 @@ error[E0778]: `#[instruction_set]` requires an argument LL | #[instruction_set()] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0778`. diff --git a/tests/ui/error-codes/E0779.stderr b/tests/ui/error-codes/E0779.stderr index 7c6a119a09615..a01aa98b914c5 100644 --- a/tests/ui/error-codes/E0779.stderr +++ b/tests/ui/error-codes/E0779.stderr @@ -4,6 +4,6 @@ error[E0779]: invalid instruction set specified LL | #[instruction_set(arm::magic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0779`. diff --git a/tests/ui/error-codes/e0119/complex-impl.stderr b/tests/ui/error-codes/e0119/complex-impl.stderr index 654073eec2602..c0519c60e4227 100644 --- a/tests/ui/error-codes/e0119/complex-impl.stderr +++ b/tests/ui/error-codes/e0119/complex-impl.stderr @@ -9,6 +9,6 @@ LL | impl External for (Q, R) {} | = note: define and implement a trait or new type instead -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/error-codes/e0119/issue-23563.stderr b/tests/ui/error-codes/e0119/issue-23563.stderr index 1b2d64282e1e2..86737742f749b 100644 --- a/tests/ui/error-codes/e0119/issue-23563.stderr +++ b/tests/ui/error-codes/e0119/issue-23563.stderr @@ -8,6 +8,6 @@ LL | impl<'a, T> LolFrom<&'a [T]> for LocalType { - impl LolFrom for U where T: LolInto; -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/e0119/issue-27403.stderr b/tests/ui/error-codes/e0119/issue-27403.stderr index 9b3345c23bb23..b0918a3d64973 100644 --- a/tests/ui/error-codes/e0119/issue-27403.stderr +++ b/tests/ui/error-codes/e0119/issue-27403.stderr @@ -8,6 +8,6 @@ LL | impl Into for GenX { - impl Into for T where U: From; -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/e0119/issue-28981.stderr b/tests/ui/error-codes/e0119/issue-28981.stderr index 97b570bc7aca3..be3e4aea51a1a 100644 --- a/tests/ui/error-codes/e0119/issue-28981.stderr +++ b/tests/ui/error-codes/e0119/issue-28981.stderr @@ -7,6 +7,6 @@ LL | impl Deref for Foo { } = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/error-codes/e0119/so-37347311.stderr b/tests/ui/error-codes/e0119/so-37347311.stderr index 99367e808419f..869b11b1909fb 100644 --- a/tests/ui/error-codes/e0119/so-37347311.stderr +++ b/tests/ui/error-codes/e0119/so-37347311.stderr @@ -7,6 +7,6 @@ LL | impl From for MyError { = note: conflicting implementation in crate `core`: - impl From for T; -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/ex-E0611.stderr b/tests/ui/error-codes/ex-E0611.stderr index 1da7b33be9dce..fb61eba15096a 100644 --- a/tests/ui/error-codes/ex-E0611.stderr +++ b/tests/ui/error-codes/ex-E0611.stderr @@ -4,6 +4,6 @@ error[E0616]: field `0` of struct `Foo` is private LL | y.0; | ^ private field -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/error-codes/ex-E0612.stderr b/tests/ui/error-codes/ex-E0612.stderr index b21b6fdfcf1f2..23c1697b9b20f 100644 --- a/tests/ui/error-codes/ex-E0612.stderr +++ b/tests/ui/error-codes/ex-E0612.stderr @@ -2,8 +2,13 @@ error[E0609]: no field `1` on type `Foo` --> $DIR/ex-E0612.rs:5:6 | LL | y.1; - | ^ help: a field with a similar name exists: `0` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | y.0; + | ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/error-should-say-copy-not-pod.stderr b/tests/ui/error-should-say-copy-not-pod.stderr index 637eb27db01e6..658584e2ff4bb 100644 --- a/tests/ui/error-should-say-copy-not-pod.stderr +++ b/tests/ui/error-should-say-copy-not-pod.stderr @@ -12,6 +12,6 @@ note: required by a bound in `check_bound` LL | fn check_bound(_: T) {} | ^^^^ required by this bound in `check_bound` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/issue-104621-extern-not-file.stderr b/tests/ui/errors/issue-104621-extern-not-file.stderr index 5aaf9741360ef..61496e5b57b3c 100644 --- a/tests/ui/errors/issue-104621-extern-not-file.stderr +++ b/tests/ui/errors/issue-104621-extern-not-file.stderr @@ -4,5 +4,5 @@ error: extern location for foo is not a file: . LL | extern crate foo; | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr index 51e3b776cb2c0..7aa66be0d0977 100644 --- a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr +++ b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr @@ -9,6 +9,6 @@ LL | let _ = remapped_dep::SomeStruct; // ~ERROR E0423 LL | pub struct SomeStruct {} // This line should be show as part of the error. | --------------------- `remapped_dep::SomeStruct` defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr index 51e3b776cb2c0..7aa66be0d0977 100644 --- a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr +++ b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr @@ -9,6 +9,6 @@ LL | let _ = remapped_dep::SomeStruct; // ~ERROR E0423 LL | pub struct SomeStruct {} // This line should be show as part of the error. | --------------------- `remapped_dep::SomeStruct` defined here -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/errors/remap-path-prefix.normal.stderr b/tests/ui/errors/remap-path-prefix.normal.stderr index 004f10b4e4314..46d33d26052cb 100644 --- a/tests/ui/errors/remap-path-prefix.normal.stderr +++ b/tests/ui/errors/remap-path-prefix.normal.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `ferris` in this scope LL | ferris | ^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr b/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr index 004f10b4e4314..46d33d26052cb 100644 --- a/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr +++ b/tests/ui/errors/remap-path-prefix.with-diagnostic-scope.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `ferris` in this scope LL | ferris | ^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr b/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr index 98fe328193ced..0badea6e27bf3 100644 --- a/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr +++ b/tests/ui/errors/remap-path-prefix.without-diagnostic-scope.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `ferris` in this scope LL | ferris | ^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/explicit-tail-calls/become-outside.array.stderr b/tests/ui/explicit-tail-calls/become-outside.array.stderr index 839c20509fe73..81ed683737c75 100644 --- a/tests/ui/explicit-tail-calls/become-outside.array.stderr +++ b/tests/ui/explicit-tail-calls/become-outside.array.stderr @@ -4,6 +4,6 @@ error[E0572]: become statement outside of function body LL | struct Bad([(); become f()]); | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/explicit-tail-calls/become-outside.constant.stderr b/tests/ui/explicit-tail-calls/become-outside.constant.stderr index 9b67f08af3aea..07747e2cc9cd5 100644 --- a/tests/ui/explicit-tail-calls/become-outside.constant.stderr +++ b/tests/ui/explicit-tail-calls/become-outside.constant.stderr @@ -4,6 +4,6 @@ error[E0572]: become statement outside of function body LL | become f(); | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/explicit/explicit-call-to-dtor.stderr b/tests/ui/explicit/explicit-call-to-dtor.stderr index f2e0b73b6c5e6..6f40f3998a98c 100644 --- a/tests/ui/explicit/explicit-call-to-dtor.stderr +++ b/tests/ui/explicit/explicit-call-to-dtor.stderr @@ -9,6 +9,6 @@ help: consider using `drop` function LL | drop(x); | +++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0040`. diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr index 5fa42fcf19118..d2d69ce6daf72 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr @@ -9,6 +9,6 @@ help: consider using `drop` function LL | drop(self); | +++++ ~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0040`. diff --git a/tests/ui/expr/if/attrs/bad-cfg.stderr b/tests/ui/expr/if/attrs/bad-cfg.stderr index 8a2890886a15c..ca0eced267d65 100644 --- a/tests/ui/expr/if/attrs/bad-cfg.stderr +++ b/tests/ui/expr/if/attrs/bad-cfg.stderr @@ -4,5 +4,5 @@ error: removing an expression is not supported in this position LL | let _ = #[cfg(FALSE)] if true {}; | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/expr/if/attrs/stmt-expr-gated.stderr b/tests/ui/expr/if/attrs/stmt-expr-gated.stderr index 47dac39a9ae88..afc26757c4615 100644 --- a/tests/ui/expr/if/attrs/stmt-expr-gated.stderr +++ b/tests/ui/expr/if/attrs/stmt-expr-gated.stderr @@ -7,6 +7,6 @@ LL | let _ = #[deny(warnings)] if true { = note: see issue #15701 for more information = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/expr/if/bad-if-let-suggestion.rs b/tests/ui/expr/if/bad-if-let-suggestion.rs index 99d584ac7a5d5..b0d0676e1ea75 100644 --- a/tests/ui/expr/if/bad-if-let-suggestion.rs +++ b/tests/ui/expr/if/bad-if-let-suggestion.rs @@ -1,6 +1,3 @@ -// FIXME(compiler-errors): This really should suggest `let` on the RHS of the -// `&&` operator, but that's kinda hard to do because of precedence. -// Instead, for now we just make sure not to suggest `if let let`. fn a() { if let x = 1 && i = 2 {} //~^ ERROR cannot find value `i` in this scope diff --git a/tests/ui/expr/if/bad-if-let-suggestion.stderr b/tests/ui/expr/if/bad-if-let-suggestion.stderr index 20ac9ca76ba9b..0d1f895bd82bf 100644 --- a/tests/ui/expr/if/bad-if-let-suggestion.stderr +++ b/tests/ui/expr/if/bad-if-let-suggestion.stderr @@ -1,19 +1,27 @@ error: expected expression, found `let` statement - --> $DIR/bad-if-let-suggestion.rs:5:8 + --> $DIR/bad-if-let-suggestion.rs:2:8 | LL | if let x = 1 && i = 2 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions +help: you might have meant to continue the let-chain + | +LL | if let x = 1 && let i = 2 {} + | +++ +help: you might have meant to compare for equality + | +LL | if let x = 1 && i == 2 {} + | + error[E0425]: cannot find value `i` in this scope - --> $DIR/bad-if-let-suggestion.rs:5:21 + --> $DIR/bad-if-let-suggestion.rs:2:21 | LL | if let x = 1 && i = 2 {} | ^ not found in this scope error[E0425]: cannot find value `i` in this scope - --> $DIR/bad-if-let-suggestion.rs:12:9 + --> $DIR/bad-if-let-suggestion.rs:9:9 | LL | fn a() { | ------ similarly named function `a` defined here @@ -22,7 +30,7 @@ LL | if (i + j) = i {} | ^ help: a function with a similar name exists: `a` error[E0425]: cannot find value `j` in this scope - --> $DIR/bad-if-let-suggestion.rs:12:13 + --> $DIR/bad-if-let-suggestion.rs:9:13 | LL | fn a() { | ------ similarly named function `a` defined here @@ -31,7 +39,7 @@ LL | if (i + j) = i {} | ^ help: a function with a similar name exists: `a` error[E0425]: cannot find value `i` in this scope - --> $DIR/bad-if-let-suggestion.rs:12:18 + --> $DIR/bad-if-let-suggestion.rs:9:18 | LL | fn a() { | ------ similarly named function `a` defined here @@ -40,7 +48,7 @@ LL | if (i + j) = i {} | ^ help: a function with a similar name exists: `a` error[E0425]: cannot find value `x` in this scope - --> $DIR/bad-if-let-suggestion.rs:19:8 + --> $DIR/bad-if-let-suggestion.rs:16:8 | LL | fn a() { | ------ similarly named function `a` defined here @@ -49,7 +57,7 @@ LL | if x[0] = 1 {} | ^ help: a function with a similar name exists: `a` error[E0308]: mismatched types - --> $DIR/bad-if-let-suggestion.rs:5:8 + --> $DIR/bad-if-let-suggestion.rs:2:8 | LL | if let x = 1 && i = 2 {} | ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` diff --git a/tests/ui/expr/if/if-branch-types.stderr b/tests/ui/expr/if/if-branch-types.stderr index d2bba88211ea8..0e86a24f31b7d 100644 --- a/tests/ui/expr/if/if-branch-types.stderr +++ b/tests/ui/expr/if/if-branch-types.stderr @@ -11,6 +11,6 @@ help: change the type of the numeric literal from `u32` to `i32` LL | let x = if true { 10i32 } else { 10i32 }; | ~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-let-arm-types.stderr b/tests/ui/expr/if/if-let-arm-types.stderr index b40a0f479d318..285f5c4a6f222 100644 --- a/tests/ui/expr/if/if-let-arm-types.stderr +++ b/tests/ui/expr/if/if-let-arm-types.stderr @@ -12,6 +12,6 @@ LL | | 1 LL | | }; | |_____- `if` and `else` have incompatible types -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-typeck.stderr b/tests/ui/expr/if/if-typeck.stderr index 74ed0ed0ae6bd..1be43a20105fa 100644 --- a/tests/ui/expr/if/if-typeck.stderr +++ b/tests/ui/expr/if/if-typeck.stderr @@ -7,6 +7,6 @@ LL | if f { } = note: expected type `bool` found fn item `fn() {f}` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-without-block.stderr b/tests/ui/expr/if/if-without-block.stderr index 2d1ee04ce09a8..98bde827a72ab 100644 --- a/tests/ui/expr/if/if-without-block.stderr +++ b/tests/ui/expr/if/if-without-block.stderr @@ -10,5 +10,5 @@ help: this binary operation is possibly unfinished LL | if 5 == { | ^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/expr/if/if-without-else-result.stderr b/tests/ui/expr/if/if-without-else-result.stderr index 317faf7c619f6..4eaa039349670 100644 --- a/tests/ui/expr/if/if-without-else-result.stderr +++ b/tests/ui/expr/if/if-without-else-result.stderr @@ -10,6 +10,6 @@ LL | let a = if true { true }; = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/expr/if/issue-4201.stderr b/tests/ui/expr/if/issue-4201.stderr index 612fe77642ce5..c761d0b855318 100644 --- a/tests/ui/expr/if/issue-4201.stderr +++ b/tests/ui/expr/if/issue-4201.stderr @@ -13,6 +13,6 @@ LL | | }; = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr index f70b321174333..1264d96934252 100644 --- a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr +++ b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr @@ -22,6 +22,6 @@ help: you might have meant to create the closure instead of a block LL | Some(true).filter(|_| { | +++ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/expr/malformed_closure/missing_block_in_let_binding.stderr b/tests/ui/expr/malformed_closure/missing_block_in_let_binding.stderr index d4640fba96cfe..8af7030172cb8 100644 --- a/tests/ui/expr/malformed_closure/missing_block_in_let_binding.stderr +++ b/tests/ui/expr/malformed_closure/missing_block_in_let_binding.stderr @@ -12,5 +12,5 @@ help: you might have meant to open the body of the closure LL | let x = |x| { | + -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure.stderr b/tests/ui/expr/malformed_closure/ruby_style_closure.stderr index e8b34121b5f8d..b1607bbacc926 100644 --- a/tests/ui/expr/malformed_closure/ruby_style_closure.stderr +++ b/tests/ui/expr/malformed_closure/ruby_style_closure.stderr @@ -4,6 +4,6 @@ error[E0425]: cannot find value `x` in this scope LL | Some(x * 2) | ^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr index e44ec5ca93ce8..a7ed9f5880b6b 100644 --- a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr +++ b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr @@ -20,6 +20,6 @@ LL - let p = Some(45).and_then({|x| LL + let p = Some(45).and_then(|x| { | -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/ext-nonexistent.stderr b/tests/ui/ext-nonexistent.stderr index f3aa83fd50806..8891e823e4af7 100644 --- a/tests/ui/ext-nonexistent.stderr +++ b/tests/ui/ext-nonexistent.stderr @@ -4,5 +4,5 @@ error: cannot find macro `iamnotanextensionthatexists` in this scope LL | fn main() { iamnotanextensionthatexists!(""); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extenv/extenv-arg-2-not-string-literal.stderr b/tests/ui/extenv/extenv-arg-2-not-string-literal.stderr index 258e2b347fba8..9db1c0be74686 100644 --- a/tests/ui/extenv/extenv-arg-2-not-string-literal.stderr +++ b/tests/ui/extenv/extenv-arg-2-not-string-literal.stderr @@ -4,5 +4,5 @@ error: expected string literal LL | fn main() { env!("one", 10); } | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extenv/extenv-escaped-var.stderr b/tests/ui/extenv/extenv-escaped-var.stderr index 25e218c63f336..ef5e654d0543a 100644 --- a/tests/ui/extenv/extenv-escaped-var.stderr +++ b/tests/ui/extenv/extenv-escaped-var.stderr @@ -7,5 +7,5 @@ LL | env!("\t"); = help: use `std::env::var("\t")` to read the variable at run time = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extenv/extenv-no-args.stderr b/tests/ui/extenv/extenv-no-args.stderr index 70b85932c2338..36d485676c21b 100644 --- a/tests/ui/extenv/extenv-no-args.stderr +++ b/tests/ui/extenv/extenv-no-args.stderr @@ -4,5 +4,5 @@ error: `env!()` takes 1 or 2 arguments LL | fn main() { env!(); } | ^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extenv/extenv-not-defined-custom.stderr b/tests/ui/extenv/extenv-not-defined-custom.stderr index e7da4e046ab85..9b6e32bc95f24 100644 --- a/tests/ui/extenv/extenv-not-defined-custom.stderr +++ b/tests/ui/extenv/extenv-not-defined-custom.stderr @@ -6,5 +6,5 @@ LL | fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } | = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extenv/extenv-not-defined-default.stderr b/tests/ui/extenv/extenv-not-defined-default.stderr index e3dce000530ae..5198818f89cc6 100644 --- a/tests/ui/extenv/extenv-not-defined-default.stderr +++ b/tests/ui/extenv/extenv-not-defined-default.stderr @@ -7,5 +7,5 @@ LL | env!("CARGO__HOPEFULLY_NOT_DEFINED__"); = help: Cargo sets build script variables at run time. Use `std::env::var("CARGO__HOPEFULLY_NOT_DEFINED__")` instead = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extenv/extenv-not-string-literal.stderr b/tests/ui/extenv/extenv-not-string-literal.stderr index 342a9f7096e71..85ed442e2fead 100644 --- a/tests/ui/extenv/extenv-not-string-literal.stderr +++ b/tests/ui/extenv/extenv-not-string-literal.stderr @@ -4,5 +4,5 @@ error: expected string literal LL | fn main() { env!(10, "two"); } | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extenv/extenv-too-many-args.stderr b/tests/ui/extenv/extenv-too-many-args.stderr index 47cf810b70d77..c0fd5d57251f1 100644 --- a/tests/ui/extenv/extenv-too-many-args.stderr +++ b/tests/ui/extenv/extenv-too-many-args.stderr @@ -4,5 +4,5 @@ error: `env!()` takes 1 or 2 arguments LL | fn main() { env!("one", "two", "three"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extern-flag/multiple-opts.stderr b/tests/ui/extern-flag/multiple-opts.stderr index 5088fb1c4d2ed..0aaca5ee253e4 100644 --- a/tests/ui/extern-flag/multiple-opts.stderr +++ b/tests/ui/extern-flag/multiple-opts.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `somedep` LL | somedep::somefun(); | ^^^^^^^ use of undeclared crate or module `somedep` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/extern-flag/no-nounused.stderr b/tests/ui/extern-flag/no-nounused.stderr index 6446c53236ca2..171079287f0b3 100644 --- a/tests/ui/extern-flag/no-nounused.stderr +++ b/tests/ui/extern-flag/no-nounused.stderr @@ -6,5 +6,5 @@ LL | fn main() { | = note: requested on the command line with `-D unused-crate-dependencies` -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extern-flag/noprelude.stderr b/tests/ui/extern-flag/noprelude.stderr index 57878721683a1..23b9b2fd94b27 100644 --- a/tests/ui/extern-flag/noprelude.stderr +++ b/tests/ui/extern-flag/noprelude.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `somedep` LL | somedep::somefun(); | ^^^^^^^ use of undeclared crate or module `somedep` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/extern-flag/public-and-private.stderr b/tests/ui/extern-flag/public-and-private.stderr index 9dfc10effcf1f..209f5d4dadc5d 100644 --- a/tests/ui/extern-flag/public-and-private.stderr +++ b/tests/ui/extern-flag/public-and-private.stderr @@ -10,5 +10,5 @@ note: the lint level is defined here LL | #![deny(exported_private_dependencies)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-const.fixed b/tests/ui/extern/extern-const.fixed index 9d96b4f63fb6c..248efc93d008a 100644 --- a/tests/ui/extern/extern-const.fixed +++ b/tests/ui/extern/extern-const.fixed @@ -6,7 +6,6 @@ // run-rustfix // ignore-wasm32-bare no external library to link to. -// ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/extern/extern-const.rs b/tests/ui/extern/extern-const.rs index 7cef5b3497b5a..d3b3bef6dae6f 100644 --- a/tests/ui/extern/extern-const.rs +++ b/tests/ui/extern/extern-const.rs @@ -6,7 +6,6 @@ // run-rustfix // ignore-wasm32-bare no external library to link to. -// ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/extern/extern-const.stderr b/tests/ui/extern/extern-const.stderr index 7f67adbdb19c7..4c2c3d6e0a848 100644 --- a/tests/ui/extern/extern-const.stderr +++ b/tests/ui/extern/extern-const.stderr @@ -1,5 +1,5 @@ error: extern items cannot be `const` - --> $DIR/extern-const.rs:16:11 + --> $DIR/extern-const.rs:15:11 | LL | const rust_dbg_static_mut: libc::c_int; | ------^^^^^^^^^^^^^^^^^^^ @@ -8,5 +8,5 @@ LL | const rust_dbg_static_mut: libc::c_int; | = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-crate-rename.stderr b/tests/ui/extern/extern-crate-rename.stderr index 5f14779552110..43f6e56ab0e70 100644 --- a/tests/ui/extern/extern-crate-rename.stderr +++ b/tests/ui/extern/extern-crate-rename.stderr @@ -12,6 +12,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate m2 as other_m1; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/extern/extern-ffi-fn-with-body.stderr b/tests/ui/extern/extern-ffi-fn-with-body.stderr index 079c9cecd8ed4..dc34490b39a00 100644 --- a/tests/ui/extern/extern-ffi-fn-with-body.stderr +++ b/tests/ui/extern/extern-ffi-fn-with-body.stderr @@ -14,5 +14,5 @@ LL | | } = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-macro.stderr b/tests/ui/extern/extern-macro.stderr index 5b7a720736a1e..e4d767f0e8644 100644 --- a/tests/ui/extern/extern-macro.stderr +++ b/tests/ui/extern/extern-macro.stderr @@ -4,6 +4,6 @@ error[E0433]: failed to resolve: partially resolved path in a macro LL | let _ = Foo::bar!(); | ^^^^^^^^ partially resolved path in a macro -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/extern/extern-main-fn.stderr b/tests/ui/extern/extern-main-fn.stderr index 846102670a83f..fd4e67e893e68 100644 --- a/tests/ui/extern/extern-main-fn.stderr +++ b/tests/ui/extern/extern-main-fn.stderr @@ -7,6 +7,6 @@ LL | extern "C" fn main() {} = note: expected signature `fn()` found signature `extern "C" fn()` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/extern/extern-main-issue-86110.stderr b/tests/ui/extern/extern-main-issue-86110.stderr index 18dfddc46bd36..8a3262fbcc7be 100644 --- a/tests/ui/extern/extern-main-issue-86110.stderr +++ b/tests/ui/extern/extern-main-issue-86110.stderr @@ -4,5 +4,5 @@ error: the `main` function cannot be declared in an `extern` block LL | fn main(); | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-type-diag-not-similar.stderr b/tests/ui/extern/extern-type-diag-not-similar.stderr index 75836f7eca19c..3547f9b3ff613 100644 --- a/tests/ui/extern/extern-type-diag-not-similar.stderr +++ b/tests/ui/extern/extern-type-diag-not-similar.stderr @@ -11,6 +11,6 @@ note: required by a bound in `assert_send` LL | fn assert_send() {} | ^^^^ required by this bound in `assert_send` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern-types-distinct-types.stderr b/tests/ui/extern/extern-types-distinct-types.stderr index 3e6dc5cefadf2..ea4e51862f31f 100644 --- a/tests/ui/extern/extern-types-distinct-types.stderr +++ b/tests/ui/extern/extern-types-distinct-types.stderr @@ -14,6 +14,6 @@ LL | r = note: expected reference `&B` found reference `&A` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/extern/extern-with-type-bounds.stderr b/tests/ui/extern/extern-with-type-bounds.stderr index 88be1e5dd3da0..42448d9e9246d 100644 --- a/tests/ui/extern/extern-with-type-bounds.stderr +++ b/tests/ui/extern/extern-with-type-bounds.stderr @@ -4,6 +4,6 @@ error[E0405]: cannot find trait `NoSuchTrait` in this scope LL | fn align_of() -> usize; | ^^^^^^^^^^^ not found in this scope -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/extern/extern-wrong-value-type.stderr b/tests/ui/extern/extern-wrong-value-type.stderr index 463cee83169d3..1c08aa1717f4b 100644 --- a/tests/ui/extern/extern-wrong-value-type.stderr +++ b/tests/ui/extern/extern-wrong-value-type.stderr @@ -14,6 +14,6 @@ note: required by a bound in `is_fn` LL | fn is_fn(_: F) where F: Fn() {} | ^^^^ required by this bound in `is_fn` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/issue-116203.rs b/tests/ui/extern/issue-116203.rs new file mode 100644 index 0000000000000..f821284164495 --- /dev/null +++ b/tests/ui/extern/issue-116203.rs @@ -0,0 +1,21 @@ +extern "C" { + thread_local! { + static FOO: u32 = 0; + //~^ error: extern items cannot be `const` + //~| error: incorrect `static` inside `extern` block + } +} + +macro_rules! hello { + ($name:ident) => { + const $name: () = (); + }; +} + +extern "C" { + hello! { yes } + //~^ error: extern items cannot be `const` + //~| error: incorrect `static` inside `extern` block +} + +fn main() {} diff --git a/tests/ui/extern/issue-116203.stderr b/tests/ui/extern/issue-116203.stderr new file mode 100644 index 0000000000000..86e4cc763bd6e --- /dev/null +++ b/tests/ui/extern/issue-116203.stderr @@ -0,0 +1,46 @@ +error: extern items cannot be `const` + --> $DIR/issue-116203.rs:3:14 + | +LL | static FOO: u32 = 0; + | ^^^ + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: extern items cannot be `const` + --> $DIR/issue-116203.rs:16:14 + | +LL | hello! { yes } + | ^^^ + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `static` inside `extern` block + --> $DIR/issue-116203.rs:3:14 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body +LL | / thread_local! { +LL | | static FOO: u32 = 0; + | | ^^^ cannot have a body +LL | | +LL | | +LL | | } + | |_____- the invalid body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `static` inside `extern` block + --> $DIR/issue-116203.rs:16:14 + | +LL | const $name: () = (); + | -- the invalid body +... +LL | extern "C" { + | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body +LL | hello! { yes } + | ^^^ cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 4 previous errors + diff --git a/tests/ui/extern/issue-28324.mir.stderr b/tests/ui/extern/issue-28324.mir.stderr index aff8bf7927dd1..9376ac35e2154 100644 --- a/tests/ui/extern/issue-28324.mir.stderr +++ b/tests/ui/extern/issue-28324.mir.stderr @@ -6,6 +6,6 @@ LL | pub static BAZ: u32 = *&error_message_count; | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/extern/issue-28324.thir.stderr b/tests/ui/extern/issue-28324.thir.stderr index c696c35983016..8857f379ad189 100644 --- a/tests/ui/extern/issue-28324.thir.stderr +++ b/tests/ui/extern/issue-28324.thir.stderr @@ -6,6 +6,6 @@ LL | pub static BAZ: u32 = *&error_message_count; | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr index 5f78775f5409b..25348b64002fa 100644 --- a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr +++ b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr @@ -6,6 +6,6 @@ LL | static symbol: [usize]; | = help: the trait `Sized` is not implemented for `[usize]` -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extoption_env-no-args.stderr b/tests/ui/extoption_env-no-args.stderr index 65067942b85c4..d40f905b6659d 100644 --- a/tests/ui/extoption_env-no-args.stderr +++ b/tests/ui/extoption_env-no-args.stderr @@ -4,5 +4,5 @@ error: option_env! takes 1 argument LL | fn main() { option_env!(); } | ^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extoption_env-not-string-literal.stderr b/tests/ui/extoption_env-not-string-literal.stderr index 272751916f5be..d4fec1b45c9d3 100644 --- a/tests/ui/extoption_env-not-string-literal.stderr +++ b/tests/ui/extoption_env-not-string-literal.stderr @@ -4,5 +4,5 @@ error: argument must be a string literal LL | fn main() { option_env!(10); } | ^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/extoption_env-too-many-args.stderr b/tests/ui/extoption_env-too-many-args.stderr index a34e60b6448f9..c7aeaac75dd6d 100644 --- a/tests/ui/extoption_env-too-many-args.stderr +++ b/tests/ui/extoption_env-too-many-args.stderr @@ -4,5 +4,5 @@ error: option_env! takes 1 argument LL | fn main() { option_env!("one", "two"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/fail-simple.stderr b/tests/ui/fail-simple.stderr index af8f54291ff47..39fec3e2517b2 100644 --- a/tests/ui/fail-simple.stderr +++ b/tests/ui/fail-simple.stderr @@ -6,5 +6,5 @@ LL | panic!(@); | = note: while trying to match end of macro -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/allow-features.stderr b/tests/ui/feature-gates/allow-features.stderr index 9caf48dd1386b..ebd03e91c2282 100644 --- a/tests/ui/feature-gates/allow-features.stderr +++ b/tests/ui/feature-gates/allow-features.stderr @@ -4,6 +4,6 @@ error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed LL | #![feature(unknown_stdlib_feature)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0725`. diff --git a/tests/ui/feature-gates/doc-rust-logo.stderr b/tests/ui/feature-gates/doc-rust-logo.stderr index ff5855290d405..15398c8505f0f 100644 --- a/tests/ui/feature-gates/doc-rust-logo.stderr +++ b/tests/ui/feature-gates/doc-rust-logo.stderr @@ -7,6 +7,6 @@ LL | #![doc(rust_logo)] = note: see issue #90418 for more information = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr b/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr index 1757befec35c0..3cc7b100db2f9 100644 --- a/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr +++ b/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr @@ -6,6 +6,6 @@ LL | extern "unadjusted" fn foo() { | = help: add `#![feature(abi_unadjusted)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr index 13b9b84f0be4e..e6eeca2e098a9 100644 --- a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr +++ b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr @@ -7,5 +7,5 @@ LL | struct Foo; = note: the only supported types are integers, `bool` and `char` = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr index f414eb463dfbc..1f22c8c585130 100644 --- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr +++ b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr @@ -7,6 +7,6 @@ LL | #[alloc_error_handler] = note: see issue #51540 for more information = help: add `#![feature(alloc_error_handler)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allocator_internals.stderr b/tests/ui/feature-gates/feature-gate-allocator_internals.stderr index 6e276f7bccd69..66a1c1be3f4e8 100644 --- a/tests/ui/feature-gates/feature-gate-allocator_internals.stderr +++ b/tests/ui/feature-gates/feature-gate-allocator_internals.stderr @@ -6,6 +6,6 @@ LL | #![default_lib_allocator] | = help: add `#![feature(allocator_internals)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr index 4621bc0b30e53..c2d29db686695 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr @@ -10,6 +10,6 @@ LL | bar!(); = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr index 1232d13a457a7..c0ab67025b265 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr @@ -10,6 +10,6 @@ LL | bar!(); = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr index 3c1a4bfc7d2ca..cb6cf4699fd81 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr @@ -6,6 +6,6 @@ LL | #[allow_internal_unstable()] | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_arch.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_arch.stderr index 4a859430e044d..9db088475a16c 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_arch.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_arch.stderr @@ -7,6 +7,6 @@ LL | asm!(""); = note: see issue #93335 for more information = help: add `#![feature(asm_experimental_arch)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_unwind.stderr b/tests/ui/feature-gates/feature-gate-asm_unwind.stderr index 05e66acb556ad..eeabf7a5b0c8e 100644 --- a/tests/ui/feature-gates/feature-gate-asm_unwind.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_unwind.stderr @@ -7,6 +7,6 @@ LL | asm!("", options(may_unwind)); = note: see issue #93334 for more information = help: add `#![feature(asm_unwind)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-assoc-type-defaults.stderr b/tests/ui/feature-gates/feature-gate-assoc-type-defaults.stderr index 9edad61532735..2ebaf40dcf6e0 100644 --- a/tests/ui/feature-gates/feature-gate-assoc-type-defaults.stderr +++ b/tests/ui/feature-gates/feature-gate-assoc-type-defaults.stderr @@ -7,6 +7,6 @@ LL | type Bar = u8; = note: see issue #29661 for more information = help: add `#![feature(associated_type_defaults)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr b/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr index 6563fbcba2e4b..a5f92b44c41d1 100644 --- a/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr +++ b/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr @@ -7,6 +7,6 @@ LL | fn foo>() {} = note: see issue #92827 for more information = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-box_patterns.stderr b/tests/ui/feature-gates/feature-gate-box_patterns.stderr index 601ec46a44394..da15f698b75cb 100644 --- a/tests/ui/feature-gates/feature-gate-box_patterns.stderr +++ b/tests/ui/feature-gates/feature-gate-box_patterns.stderr @@ -7,6 +7,6 @@ LL | let box x = Box::new('c'); = note: see issue #29641 for more information = help: add `#![feature(box_patterns)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr b/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr index 3bc7848f66dd3..6601d4cb417a0 100644 --- a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr +++ b/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr @@ -7,6 +7,6 @@ LL | builtin # offset_of(Foo, v); = note: see issue #110680 for more information = help: add `#![feature(builtin_syntax)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.stderr b/tests/ui/feature-gates/feature-gate-c_variadic.stderr index 7b3af8d994f62..a439f297ba334 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic.stderr @@ -7,6 +7,6 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { } = note: see issue #44930 for more information = help: add `#![feature(c_variadic)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr index 592768a420313..bd43e190513fb 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr @@ -7,6 +7,6 @@ LL | #[cfg(relocation_model = "pic")] = note: see issue #114929 for more information = help: add `#![feature(cfg_relocation_model)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr index af59c71414773..3400808bb728e 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr @@ -7,6 +7,6 @@ LL | #[cfg_attr(target_thread_local, thread_local)] = note: see issue #29594 for more information = help: add `#![feature(cfg_target_thread_local)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.stderr b/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.stderr index 79aba7945f6ab..22f9af8390d4b 100644 --- a/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.stderr @@ -7,6 +7,6 @@ LL | #[cfg(overflow_checks)] = note: see issue #111466 for more information = help: add `#![feature(cfg_overflow_checks)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg_sanitize.stderr b/tests/ui/feature-gates/feature-gate-cfg_sanitize.stderr index 8088585da8dd6..b53fc3acdbcc9 100644 --- a/tests/ui/feature-gates/feature-gate-cfg_sanitize.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg_sanitize.stderr @@ -7,6 +7,6 @@ LL | #[cfg(not(sanitize = "thread"))] = note: see issue #39699 for more information = help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfi_encoding.stderr b/tests/ui/feature-gates/feature-gate-cfi_encoding.stderr index b10a15088818f..04b206499405a 100644 --- a/tests/ui/feature-gates/feature-gate-cfi_encoding.stderr +++ b/tests/ui/feature-gates/feature-gate-cfi_encoding.stderr @@ -7,6 +7,6 @@ LL | #[cfi_encoding = "3Bar"] = note: see issue #89653 for more information = help: add `#![feature(cfi_encoding)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-check-cfg.rs b/tests/ui/feature-gates/feature-gate-check-cfg.rs index 4012a3b04b522..953b8e3ffcebc 100644 --- a/tests/ui/feature-gates/feature-gate-check-cfg.rs +++ b/tests/ui/feature-gates/feature-gate-check-cfg.rs @@ -1,3 +1,3 @@ -// compile-flags: --check-cfg "names()" +// compile-flags: --check-cfg "cfg()" fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-collapse_debuginfo.stderr b/tests/ui/feature-gates/feature-gate-collapse_debuginfo.stderr index 2cbde893af9bd..f0b8fd1f373a6 100644 --- a/tests/ui/feature-gates/feature-gate-collapse_debuginfo.stderr +++ b/tests/ui/feature-gates/feature-gate-collapse_debuginfo.stderr @@ -7,6 +7,6 @@ LL | #[collapse_debuginfo] = note: see issue #100758 for more information = help: add `#![feature(collapse_debuginfo)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr b/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr index 9d04aef8621ea..eadc4ddcb286a 100644 --- a/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr +++ b/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr @@ -6,6 +6,6 @@ LL | #![compiler_builtins] | = help: add `#![feature(compiler_builtins)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-concat_bytes.stderr b/tests/ui/feature-gates/feature-gate-concat_bytes.stderr index 4b3ee4c19cecd..69b196335daeb 100644 --- a/tests/ui/feature-gates/feature-gate-concat_bytes.stderr +++ b/tests/ui/feature-gates/feature-gate-concat_bytes.stderr @@ -7,6 +7,6 @@ LL | let a = concat_bytes!(b'A', b"BC"); = note: see issue #87555 for more information = help: add `#![feature(concat_bytes)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.stderr b/tests/ui/feature-gates/feature-gate-custom_mir.stderr index 3c149d30d82bd..f0f67adcca581 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.stderr +++ b/tests/ui/feature-gates/feature-gate-custom_mir.stderr @@ -6,6 +6,6 @@ LL | #[custom_mir(dialect = "built")] | = help: add `#![feature(custom_mir)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-decl_macro.stderr b/tests/ui/feature-gates/feature-gate-decl_macro.stderr index 800caf2523950..94b609f05262d 100644 --- a/tests/ui/feature-gates/feature-gate-decl_macro.stderr +++ b/tests/ui/feature-gates/feature-gate-decl_macro.stderr @@ -7,6 +7,6 @@ LL | macro m() {} = note: see issue #39412 for more information = help: add `#![feature(decl_macro)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr index ce06ce916a758..e727b69ffceb8 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr @@ -7,6 +7,6 @@ LL | fn cell(self: Cell<&Self>); = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin